myThingsの雨雲予測をLINE BotでPushするテスト

[myThings Developers](https://mythings-developers.yahoo.co.jp)でYahoo!天気の「雨が降りそうなら」をトリガーにして、Herokuで受け付けた後にLINE Botでつぶやいてみた。

# つぶやきまでの流れ
myThingsで雨雲検知→ Herokuで対象の地域の緯度、経度 → LINE BotでPush送信 → 雨雲を確認

# myThings Developersの設定
トリガー　 ： Yahoo!天気「雨が降りそうなら」を選択
アクション ： カスタムトリガーを選択
その他設定 ： 任意（テスト時は地域や日時が固定して送信されるので）

### カスタムトリガーの設定
アクション名　： 自由に設定
リクエストURL： Herokuを利用したので、https://[app名].herokuapp.com/
シークレット　： 未使用


# Herokuに実装する処理
利用した言語はPHP。

### 処理の流れ
1. myThingsからのデータを取得
2. Yahoo!デベロッパーネットワークのYOLP(地図)を利用して地域の緯度、経度を取得
3. LINE BotにURL付きのメッセージをPush送信

### 1. myThingsからのデータを取得
myThingsから受信するデータ

---

{"user_id":"[各自のuser_id]","service_id":"[各自のサービスID]","mythings_id":"[各自のmyThings ID]":[{"area":"\uff1c\u30c6\u30b9\u30c8\u5b9f\u884c\uff1e\u6771\u4eac","datetime":"2017-01-01 00:00","time":"00:00","date":"2017-01-01","rainfall":"1"}]}

---

この中からareaとdatetimeを利用します。areaにユーザーが選択した雨雲をチェックする地域、datetimeに日時が入ります。

### 2. Yahoo!デベロッパーネットワークのYOLP(地図)を利用して地域の緯度、経度を取得
Yahoo!デベロッパーネットワークのYOLP(地図)の、[Yahoo!ジオコーダAPI](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/geocoder.html)を利用して、areaの地域名から緯度、経度を取得します。

※このAPIを利用するには、[Yahoo!デベロッパーネットワーク](https://developer.yahoo.co.jp/)でアプリケーションを登録して、アプリケーションIDを取得する必要があります。

### 3. LINE BotにURL付きのメッセージをPush送信
ソースを参照
※ソースでは特定のLINEユーザーのuserid向けにPush送信を実施。useridはBOTがLINEユーザーからメッセージを受けた時のeventから調べることができます。

### ソース
```php:index.php
<?php
require_once __DIR__ . '/vendor/autoload.php';

// LINE BOTの処理
$httpClient = new \LINE\LINEBot\HTTPClient\CurlHTTPClient(getenv('CHANNEL_ACCESS_TOKEN'));
$bot = new \LINE\LINEBot($httpClient, ['channelSecret' => getenv('CHANNEL_SECRET')]);

$signature = $_SERVER["HTTP_" . \LINE\LINEBot\Constant\HTTPHeader::LINE_SIGNATURE];

# 1. myThingsからのデータを取得
$phpInput = file_get_contents('php://input');
$jsonObj = json_decode($phpInput);

// myThingsの地域の取得
$unicode_escape = $jsonObj->values[0]->area;
$area = preg_replace_callback('|\\\\u([0-9a-f]{4})|i', function($matched){
    return mb_convert_encoding(pack('H*', $matched[1]), 'UTF-8', 'UTF-16');
}, $unicode_escape);

// myThingsのテスト実行では、"＜テスト実行＞東京"となるため、"＜テスト実行＞"を除去
$area = str_replace("＜テスト実行＞", "", $area);
$area_urlencode = urlencode($area);

# 2. Yahoo!デベロッパーネットワークのYOLP(地図)を利用して地域の緯度、経度を取得
#myThingsの日時の取得
$datetime = $jsonObj->values[0]->datetime;

// 地域から緯度、経度を求める
$base_url = "https://map.yahooapis.jp/geocode/V1/geoCoder?appid=[取得したアプリケーションID]&output=json&query=";
$curl = curl_init();

$option = [
  CURLOPT_URL => $base_url.$area_urlencode,
  CURLOPT_CUSTOMREQUEST => 'GET',
  CURLOPT_SSL_VERIFYPEER => false,
  CURLOPT_RETURNTRANSFER => true
];
curl_setopt_array($curl, $option);

$response = curl_exec($curl);
$area_detail = json_decode($response);

curl_close($curl);

$line_user_id = "[LINEユーザーのuseridを指定]";
$lonlat = $area_detail->Feature[0]->Geometry->Coordinates;
$lonlatArray = explode(",", $lonlat);
$lon = $lonlatArray[0];
$lat = $lonlatArray[1];

// 雨雲の地図を表示するPHPのURLに緯度と経度を設定
$url = "https://[Herokuのapp名].herokuapp.com/map.php?lat=".$lat."&lon=".$lon."&datetime=";

// myThings実行時の日時取得
// datetimeをトリガーを引いた日時と想定
$now = new DateTime($datetime, new DateTimeZone('Asia/Tokyo'));
$nowMsg = "30分後に雨が振ります。今の雨雲はこちら\n".$url.$now->format('YmdHi');

// 30分後の日時取得
$plus30m = clone $now;
$plus30m->add(new DateInterval('PT30M'));
$plus30mMsg = "30分後の雨雲はこちら\n".$url.$plus30m->format('YmdHi');

// 60分後の日時取得
$plus60m = clone $now;
$plus60m->add(new DateInterval('PT60M'));
$plus60mMsg = "60分後の雨雲はこちら\n".$url.$plus60m->format('YmdHi');

# 3. LINE BotにURL付きのメッセージをPush送信
$bot->pushMessage($line_user_id,
  (new \LINE\LINEBot\MessageBuilder\MultiMessageBuilder())
    ->add(new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($nowMsg))
    ->add(new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($plus30mMsg))
    ->add(new \LINE\LINEBot\MessageBuilder\TextMessageBuilder($plus60mMsg))
);

?>
```

# myThings Developersでテスト実施
![テスト実行1.png](https://qiita-image-store.s3.amazonaws.com/0/179035/52a2faeb-1708-9144-6a5c-ab7786e65675.png "テスト実行1.png")

![テスト実行2.png](https://qiita-image-store.s3.amazonaws.com/0/179035/159e66c3-eb3f-150a-a9b8-d6fe1ed755a2.png "テスト実行2.png")


# LINEに表示されたメッセージ
![line1.jpg](https://qiita-image-store.s3.amazonaws.com/0/179035/7f71ed08-30ed-7cac-b0d5-3c3319eae3c7.jpeg "line1.jpg")


# 雨雲を表示するPHP(map.php)
Yahoo!デベロッパーネットワークのYOLP(地図)の、[Yahoo!スタティックマップAPI](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/static.html)を利用して、雨雲の地図を表示。

```PHP:map.php
<?php
$lat = $_GET["lat"];
$lon = $_GET["lon"];
$latlon = "lat=".$lat."&lon=".$lon;
$datetime = $_GET["datetime"];
?>
<html lang="ja">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height" />
<title>[LINE Bot]Yahoo! JAPAN スタティックマップAPI 雨雲表示</title>
</head>
<img width="300" height="200" src="https://map.yahooapis.jp/map/V1/static?appid=[取得したアプリケーションID]&<?php echo $latlon;?>&z=15&width=300&height=200&mode=map&overlay=type:rainfall|date:<?php echo $datetime;?>|datelabel:on">
<br>
<p>
<!-- Begin Yahoo! JAPAN Web Services Attribution Snippet -->
<a href="https://developer.yahoo.co.jp/about">
<img src="https://s.yimg.jp/images/yjdn/common/yjdn_attbtn1_250_34.gif" width="250" height="34" title="Webサービス by Yahoo! JAPAN" alt="Webサービス by Yahoo! JAPAN" border="0" style="margin:15px 15px 15px 15px"></a>
<!-- End Yahoo! JAPAN Web Services Attribution Snippet -->
</p>
</body>
</html>
```

![line2.jpg](https://qiita-image-store.s3.amazonaws.com/0/179035/6a1a78a5-efb5-64fc-fcfe-61d281d2bcb0.jpeg "line2.jpg")


# おまけ
LINE BotのReplyの実験をこの前やったので、myThingsIDがリクエストヘッダーに含まれていたらPush、含まれていなかったらユーザーからのメッセージ受信なのでReplyという形で実装してます。

```
...
// リクエストヘッダー取得
$phpInput = file_get_contents('php://input');
$jsonObj = json_decode($phpInput);
$myThingsId = $jsonObj->mythings_id;

if ($myThingsId == "[自分のmyThingsID]") { // myThingsからデータ受信したのでPush処理
  ...
}
else { // Reply処理
  ...
}

```