雨雲レーダーの表示に取り掛かる
ここまでの手順でM5Stackからセルラー通信が利用できることが確認できました。いよいよ雨雲レーダーを表示できるようにします。
Yahoo!デベロッパーネットワーク:YOLP(地図)
雨雲レーダーはYahoo! JAPAN様の技術者向けプラットフォーム「Yahoo!デベロッパーネットワーク」の中で提供されている「Yahoo! Open Local Platform(YOLP)」を活用します。
YOLPの利用にはYahoo! JAPAN ID(無償)が必要となります。
アプリケーションIDの登録
雨雲レーダーを利用するためにはYahoo! JAPAN IDとは別にアプリケーションIDの登録が必要です。
-
アプリケーション管理>[新しいアプリケーションを開発]に進みます。
- ログインが必要な場合はYahoo! JAPAN IDでログインしてください。
-
アプリケーション情報の入力では以下を入力してから[確認]に進みます。
- アプリケーションの種類:サーバーサイド(Yahoo! ID連携 v2)
-
アプリケーション名:
M5Stack RainRadar app(任意で構いません) - サイトURL:(ご自分のブログや会社のURLを記入ください)
- ガイドラインの同意へのチェック
- 入力内容の確認では、内容を確認して[登録]に進みます。
以上でClient IDとシークレットが発行されます。
Webブラウザでテストをする
先ほど入手したClient IDを使って、まずはWebブラウザで雨雲レーダーを表示してみます。以下のURLをWebブラウザのアドレスバーに入力してください。
その際、<YOUR_CLIENT_ID>を先ほどのClient IDに置き換えてください。
https://map.yahooapis.jp/map/V1/static?appid=<YOUR_CLIENT_ID>&output=jpg&quality=50&width=320&height=208&overlay=type:rainfall%7Cdatelabel:off&mode=map&style=base:simple&z=8&lat=35.6313456&lon=139.7312189
以下のように画像が表示されることを確認してください。
表示されない場合は<YOUR_CLIENT_ID>の書き換え忘れや転記ミスがないか確認してください。
雨雲レーダー表示のスケッチを書く
M5StackとPCをUSB Type-Cで接続した後、以下の手順を行います。基本的な手順は今までと同じです。
-
Arduino IDEのメニューから[ツール]>[ボード: ...]で、
M5Stack-Core-ESP32を選択します。 - Arduino IDEのメニューから[ツール]>[シリアルポート: ...]で、M5Stackが接続されているポートを選択します。
- Arduino IDEのメニューから[ファイル]>[新規ファイル]を選択し、新たなスケッチを書けるようにします。
-
新たなスケッチの内容をGist / m5stack_rainradar.inoの内容にします。以下の書き換えを行ってください。
-
103行目:
<YOUR_CLIENT_ID>をClient IDに置き換え
-
103行目:
- Arduino IDEで「書き込み」を行います。
書き込みが正常に完了すれば自動的に再起動して書き込まれたスケッチが実行され、液晶ディスプレイが以下のように表示されます。
この状態で一番左のボタンを押すと雨雲レーダーの画像を取得する処理が実行され、しばらくすると画像が表示されます。
右上の(prog...はデータの取得状態を表しています。(prog...が消えても画像が表示されない場合は<YOUR_CLIENT_ID>の書き換え忘れや転記ミスがないか確認するようにしてください。
左ボタンを押すごとに、その時点の最新の雨雲レーダー画像を取得・表示します。
Gistで配布しているソースコード
Gistで配布しているソースコードを、こちらにも掲載します。
/*
* Copyright (c) 2019 Kohei "Max" MATSUSHITA
* Released under the MIT license
* https://opensource.org/licenses/mit-license.php
*/
#include <M5Stack.h>
#define CONSOLE Serial
#define MODEM Serial2 /* Serial2 is Modem of 3G Module */
#include <string.h>
#define TINY_GSM_MODEM_UBLOX
#include <TinyGsmClient.h>
TinyGsm modem(MODEM);
TinyGsmClientSecure ctx(modem);
void modem_enabler();
void render_rain_radar();
void print_top();
void print_bottom();
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue);
void setup() {
M5.begin();
CONSOLE.begin(115200);
M5.Lcd.clear(BLACK);
M5.Lcd.setTextSize(2);
print_top();
print_bottom();
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setCursor(0, 16);
M5.Lcd.println("## Congrats,");
M5.Lcd.println("## Boot successfully!");
}
void loop() {
if (M5.BtnA.wasReleased()) {
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setCursor(218, 0);
M5.Lcd.print(F("(prog..."));
modem_enabler();
get_and_render_rain_radar();
print_top();
print_bottom();
modem.gprsDisconnect();
}
M5.update();
}
/* ------------------------------------------------------------*/
void modem_enabler() {
M5.Lcd.setTextColor(WHITE);
MODEM.begin(115200, SERIAL_8N1, 16, 17);
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setCursor(0, 224);
M5.Lcd.println(F("modem.restart()"));
CONSOLE.println(F("modem.restart()"));
modem.restart();
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setCursor(0, 224);
M5.Lcd.println(F("waitForNetwork()"));
CONSOLE.println(F("waitForNetwork()"));
while (!modem.waitForNetwork()) M5.Lcd.print(".");
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setCursor(0, 224);
M5.Lcd.println(F("gprsConnect(soracom.io)"));
CONSOLE.println(F("gprsConnect(soracom.io)"));
modem.gprsConnect("soracom.io", "sora", "sora");
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setCursor(0, 224);
M5.Lcd.println(F("isNetworkConnected()"));
CONSOLE.println(F("isNetworkConnected()"));
while (!modem.isNetworkConnected()) M5.Lcd.print(".");
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setCursor(0, 224);
M5.Lcd.print(F("MyIP:"));
CONSOLE.print(F("MyIP: "));
IPAddress ipaddr = modem.localIP();
M5.Lcd.println(ipaddr);
CONSOLE.println(ipaddr);
}
char _buf[32*1024] = {0}; /* store for JPG image data */
void get_and_render_rain_radar() {
/* connect to host */
const char *host = "map.yahooapis.jp";
const int port = 443;
int timeout_s = 60;
CONSOLE.print("Connecting:");
CONSOLE.println(host);
if (!ctx.connect(host, port, timeout_s)) {
CONSOLE.println("fail");
return;
}
/* send request */
const char *path = "GET /map/V1/static?appid=<YOUR_CLIENT_ID>&output=jpg&quality=50&width=320&height=208&overlay=type:rainfall%7Cdatelabel:off&mode=map&style=base:simple&z=8&lat=35.6313456&lon=139.7312189 HTTP/1.0";
CONSOLE.println(path);
ctx.println(path);
ctx.print("Host: ");
ctx.println(host);
ctx.println();
Serial.println("sent.");
/* receive response */
while (ctx.connected()) {
String line = ctx.readStringUntil('\n');
CONSOLE.println(line);
if (line == "\n") {
CONSOLE.println("headers received.");
break;
}
}
ctx.readBytes(_buf, sizeof(_buf)); /* body */
ctx.stop();
/* rendering */
size_t _buf_s = strlen(_buf);
CONSOLE.println(_buf_s);
CONSOLE.println(_buf);
M5.Lcd.drawJpg((const unsigned char *)_buf, _buf_s, 0, 16);
_buf[0] = '\0'; /* cleanup */
CONSOLE.println("done.");
}
void print_top() {
M5.Lcd.fillRect(0, 0, 320, 16, getColor(51, 244, 204));
M5.Lcd.setTextColor(BLACK);
M5.Lcd.setCursor(0, 0);
M5.Lcd.print(F("RainRadar by YOLP"));
}
void print_bottom() {
M5.Lcd.fillRect(0, 224, 320, 16, BLACK); /* clean up */
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setCursor(0, 224);
M5.Lcd.print(F("Btn => Retreve RainRadar"));
}
uint16_t getColor(uint8_t red, uint8_t green, uint8_t blue) {
return ((red>>3)<<11) | ((green>>2)<<5) | (blue>>3);
}
