気象庁の雨量データをスクレイピングしM5Stackで表示する

## 概要
* 集合住宅では雨の様子が窓からは分からず、エントランスに出てから雨に気づき傘を取りに戻ることが良くあった
* 一部のオフィスビル(30階建て以上)では、エレベーターホールに傘のサインで降水を知らせてくれていた
* ベランダに降水センサーを設置しアラームを通知する方法もあるが、電源確保、センサーの耐久性の面から難しい
* 気象庁の観測データページを、常時起動しているサーバー(Raspberry Pi)でスクレイピングした結果をM5Stackで表示する  
https://www.data.jma.go.jp/obd/stats/data/mdrr/pre_rct/alltable/pre1h00.html

![IMG_9811.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/8fc7752e-d1da-cd53-60bf-ccce4ffe6e33.jpeg)


## 用意するもの
* Raspberry Pi3 Model B (4でもおそらく大丈夫)
* Raspberry Pi用のケース
* Raspberry Pi用のヒートシンク
* Raspberry Pi3 Model B B+ 対応 電源セット(5V 3.0A)
* M5Stack
* M5Stack用の電源
* Arduino IDEが動くPC (Mac/Windows)

※サーバーは前回作成した来客通知システム(常時起動)を兼用する
https://qiita.com/cami_oshimo/items/b4e4002f7c47dd00ba84

## 環境構築

(1)Arduino IDEをインストール
https://www.arduino.cc/en/main/software
(2)M5Stack関連のライブラリをインストール
https://mag.switch-science.com/2018/02/28/getting-started-with-m5stack/
(3)Raspberri PiにApache(httpサーバー)をインストールしておく
※Raspberry Pi側のセットアップは割愛
## 準備

* 気象庁の降水量のページをChromeのDeveloperToolで開き、該当地区の降水量が出力されている場所を確認する

例）広島市中区　※私は広島市よりリモート勤務中です
![スクリーンショット 2020-09-23 9.57.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/cd1a601d-98ca-00df-6ea7-ee6c8e2db614.png)


## プログラミング
* 常時起動したRaspberry PiでPythonを使ったコードでスクレイピングを行い `index.html` に出力する
* M5Stackで `index.html` を表示する

メインプログラム
`広島（ヒロシマ）` を他地域に変更すればその土地の降水量が取得できます。

```PHP:/var/www/html/rain.php
<?php

mb_language("Japanese");//処理言語の設定
mb_internal_encoding("UTF-8");//文字コードの指定
date_default_timezone_set('Asia/Tokyo');//timezoneをセット

$url = "http://www.data.jma.go.jp/obd/stats/data/mdrr/pre_rct/alltable/pre1h00.h
tml";
 
//webページの読み込み
$contents= file_get_contents($url);
 
//文字コードの変換
$contents_utf = mb_convert_encoding($contents,"UTF-8","auto");
 
//指定した文字列で囲まれた部分を取り出す。
$startString = '<td style="white-space:nowrap">広島（ヒロシマ）*</td><td style="
text-align:right;white-space:nowrap;">';
$endString = '</td>';
 
$startPoint = mb_strpos($contents_utf,$startString) ;//$startStringが現れる位置を調べる
$startPoint = $startPoint + mb_strlen($startString);//開始位置
//echo $startPoint;
//echo"";
 
$endPoint = mb_strpos($contents_utf,$endString,$startPoint );//$endStringが次に
現れる位置を調べる
//echo $endPoint;
//echo"";
 
$length = $endPoint - $startPoint;//文字列の長さを求める。
$rainfallString = mb_substr($contents_utf,$startPoint,$length)." mm"."\n\n"."GET
 Time"."\n".date("H:i:s")."\n";
echo $rainfallString;
file_put_contents("/var/www/html/index.html", $rainfallString);
?>
```

PHP実行用のシェルスクリプト

```sh:/var/www/html/cron.php
#!/bin/sh
/usr/bin/php /var/www/html/rain.php
```

PHP実行結果

```html:/var/www/html/index.html
0.0 mm

GET Time
09:30:02
```

ブラウザからも見えることを確認する。
![スクリーンショット 2020-09-23 9.37.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/701445/6f572be4-7cbc-a139-b68c-936ef193cb3f.png)

自動起動の設定(この例では1時間毎に降水量を取得)
`*/60 * * * * root sudo sh /var/www/html/cron.sh`

M5Stack側のプログラミング

```C:rain.ino
#include <M5Stack.h>
#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid       = "XXXXXXXXXXXXX";  // Wifi SSID
const char* password   = "XXXXXXXXXXXXX";  // Wifi Password

const long  gmtOffset_sec = 3600;
const int   daylightOffset_sec = 3600;


void setup()
{
  M5.begin();
  M5.Lcd.setBrightness(10);
  M5.Lcd.printf("Connecting to %s ", ssid);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
      M5.Lcd.printf(".");
  }

  M5.Lcd.println(" CONNECTED");
  M5.Lcd.fillScreen(BLACK);
}

void getrain()
{
  M5.Lcd.fillScreen(BLACK);
  HTTPClient http;

  http.begin("http://xxx.xxx.xxx.xxx/index.html");  // Raspberry PiのIPアドレス
  int httpCode = http.GET();

  String result = http.getString();
  M5.Lcd.setTextSize(5);
  M5.Lcd.setCursor(0,0);
  M5.Lcd.print(result);
  
  http.end();

}

void loop()
{
  getrain();
  delay(xxxxxxx);  // raspberryPiから `index.html` を取得する間隔（ミリ秒）
}
```

## 注意点
* スクレイピングの頻度を上げすぎると相手側のサーバーの負荷となり、問題になるので気をつける

## 使ってみて
* スマホアプリでも降水量が見られるが、玄関先などに置いておくと簡単に確認できるので便利
* 当初さくらのVPS(Linux)で2年ほど稼働させていたが、月額固定費用がかかることもあり廃止し、Raspberry Piに移行した(1ヶ月程度経過したが問題なし)