04.Unifiedで気象庁3日予報表示
04.Unifiedで気象庁3日予報表示
気象庁の天気予報で3日予報を表示します。3日予報と7日予報が有りますが、webで表示されている項目すべてを表示し、明後日で3日予報の不足分は7日予報から追加します。
M5Unifiedを使用しましたが画面サイズは320x240が必要です。確認はM5Stack Basicのみです。
また、ArduinoJsonがVer7になっていました。使い方がVer6と少し違うみたいです。Arduino-IDEはVer2.3.3です。
5時発表
・3日予報・7日予報
・今日
・明日
・明後日
11時発表
・3日予報・7日予報
・今日
・明日
・明後日
17時発表
・3日予報・7日予報
・今日
・明日
・明後日
気象庁の天気予報のweb表示
横浜市の場合https://www.jma.go.jp/bosai/forecast/#area_type=class20s&area_code=1410000
です。
予報項目
発表時・発表気象台・天気マーク・天気文・風・波・降水確率・気温発表時刻
05・11・17時* これ以外の時刻で追加発表することもあります。
発表時刻による表示日数の違い
3日予報
・05時発表は明日までの2日表示・11,17時は2日後までの3日表示
7日予報
・05時発表は6日後までの7日表示・11,17時は 7日後までの8日表示
jsonの内容
https://www.jma.go.jp/bosai/forecast/data/forecast/140000.json* json表記はweb表示内容と異なるところがあります。
3日予報の発表時刻
05:05時11:11時
17:17時
3日予報の天気コード・天気文・風・波
05:2時刻 今日05時,明日00時,明後日無し *明後日のweb表示無し11:3時刻 今日11時,明日00時,明後日00時 *明後日のweb表示有り
17:3時刻 今日17時,明日00時,明後日00時
3日予報の降水確率
05:7時刻 今日--,06,12,18,明日00,06,12,18 *明後日のweb表示無し11:6時刻 今日--,--,12,18,明日00,06,12,18 *明後日のweb表示有り
17:5時刻 今日--,--,--,18,明日00,06,12,18
* 00~06,06~12,12~18,18~24時の4区分ですが、どれも00-06時の予報はありません。
3日予報の温度
05:4時刻 今日09,00,明日00,09 *明後日のweb表示無し11:4時刻 今日09,00,明日00,09 *明後日のweb表示有り
17:2時刻 今日--,--,明日00,09
* 朝の最低気温,日中の最高気温です。05と11時の今日の順番が逆です。しかし、両方とも最高気温値で、webでは最低気温は"-"の表示です。
7日予報の発表時刻
05:前日の17時。web表示では05時です。11:11時
17:17時
7日予報の天気マーク
05:7時刻 0-6日後11:7時刻 1-7日後 webでは0日後(今日)も追加表示しています。
17:上と同じ
7日予報の降水確率
05:7時刻 0-6日後 0日後は"" (スケッチでは1日後はこの値を使用せず3日予報を使用)11:7時刻 1-7日後 1日後は""ですがwebでは3日予報値を表示しています。
17:上と同じ
7日予報の信頼度
05:7時刻 0-6日後 *0と1日後は""となっています。11:7時刻 1-7日後 *1と2日後は""となっています。
17:上と同じ
7日予報の温度
05:7時刻 0-6日後 0日後は"" (スケッチでは1日後はこの値を使用せず3日予報を使用)11:7時刻 1-7日後 1日後は""となっています。
17:上と同じ
* 最高気温と下限と上限,最低気温と下限と上限範囲の6温度
7日予報で平年の最低気温,最高気温
05:各1点11:同じ
17:同じ
7日予報の平年の7日間降水量の最低と最高mm
05:各1点11:同じ
17:同じ
* 表示は小数点以下を四捨五入しています。
3日表示するには
・天気コード・天気文・風・波05時の明後日は7日予報から取得するが、風と波は無し。
それ以外はあります。
・降水確率 (00-06,06-12,12-18,18-24)
今日+明日で05時発表は7点、11時は6点、17時は5点なので今日の範囲時刻とずれないようにします。
明後日は、7日予報から取得するが1日1点表記です。
・気温 (朝の最低,日中の最高)
今日の05時と11時は朝の最低気温はありません。
今日の17時は今日の温度はありません。
明日の表示はあります。
明後日は7日予報から取得します。
天気コードから天気文
7日予報は天気文が無く、天気コードだけなので、Chromeで気象庁の天気予報 > F12(デベロッパーツール) > コンソールの ">" の後に Forecast.Const.TELOPS と手入力 > Enter
表示された文字を、""で文字列化、引用符を二重に、予報の英文を削除 等に修正してjsonを作成し、スケッチ内で天気コードから天気文を表示します。
スケッチ説明
・標準ではメモリ不足なので、"Large APP"に変更しました。・天気予報のwifiは3入力から信号の一番強いものを自動選択(WiFiMulti)します。
・曜日は、年月日から計算します。(ツェラーの公式)
・発表時刻・天気文・風・波は文字変換して短く表示します。
・画面一番下に日付バーを表示します。(左:今日、中央:明日、右:明後日)
・Aキーで前日、Bキーで翌日を表示。端の日まで行くと表示はループします。
・天気と風は2行とし、その他はは1行とします。
・jsonで[があったら0からの数字が入ります。
・文字サイズは、標準で24を使用しました。
・画面サイズは、320x240のみです。
1行目 :24x0.8x1行=Δ19.2
2-10行目:24x1.0x9行=Δ216
日付表示: Δ3
y軸計Δ238
スケッチ
*****は自分のwifiのssidとパスワードを記入します。
// 気象庁の天気予報 3日表示
// M5Stack Basic(320x240), ツール > "Large APP"に変更
#include <M5Unified.h> // M5Unifiedライブラリを使用
#include <ArduinoJson.h> // jsonを使用 Ver7.2.0
#include <WiFi.h> // wifiを使用
#include <WiFiMulti.h> // 複数のwifiのssid入力から選択
WiFiMulti wifiMulti; // 定義
#include <HTTPClient.h> // Webにリクエストを送り応答を受取る
HTTPClient https; // 定義
const char *weatherJson =
"https://www.jma.go.jp/bosai/forecast/data/forecast/140000.json"; // 神奈川県の天気予報
// 神奈川県web表示 https://www.jma.go.jp/bosai/forecast/#area_type=offices&area_code=140000
// 横浜市のweb表示 https://www.jma.go.jp/bosai/forecast/#area_type=class20s&area_code=1410000
// 発表時刻 AM5, AM11, PM5の3回
// 神奈川県 東部 横浜市の天気 webを見て決めます
// 行末まで表示できないので英文削除
const char *weatherCodeJson = "{\"101\":[\"101.svg\",\"501.svg\",\"100\",\"晴時々曇\"],\"102\":[\"102.svg\",\"502.svg\",\"300\",\"晴一時雨\"],\"103\":[\"102.svg\",\"502.svg\",\"300\",\"晴時々雨\"],\"104\":[\"104.svg\",\"504.svg\",\"400\",\"晴一時雪\"],\"105\":[\"104.svg\",\"504.svg\",\"400\",\"晴時々雪\"],\"106\":[\"102.svg\",\"502.svg\",\"300\",\"晴一時雨か雪\"],\"107\":[\"102.svg\",\"502.svg\",\"300\",\"晴時々雨か雪\"],\"108\":[\"102.svg\",\"502.svg\",\"300\",\"晴一時雨か雷雨\"],\"110\":[\"110.svg\",\"510.svg\",\"100\",\"晴後時々曇\"],\"111\":[\"110.svg\",\"510.svg\",\"100\",\"晴後曇\"],\"112\":[\"112.svg\",\"512.svg\",\"300\",\"晴後一時雨\"],\"113\":[\"112.svg\",\"512.svg\",\"300\",\"晴後時々雨\"],\"114\":[\"112.svg\",\"512.svg\",\"300\",\"晴後雨\"],\"115\":[\"115.svg\",\"515.svg\",\"400\",\"晴後一時雪\"],\"116\":[\"115.svg\",\"515.svg\",\"400\",\"晴後時々雪\"],\"117\":[\"115.svg\",\"515.svg\",\"400\",\"晴後雪\"],\"118\":[\"112.svg\",\"512.svg\",\"300\",\"晴後雨か雪\"],\"119\":[\"112.svg\",\"512.svg\",\"300\",\"晴後雨か雷雨\"],\"120\":[\"102.svg\",\"502.svg\",\"300\",\"晴朝夕一時雨\"],\"121\":[\"102.svg\",\"502.svg\",\"300\",\"晴朝の内一時雨\"],\"122\":[\"112.svg\",\"512.svg\",\"300\",\"晴夕方一時雨\"],\"123\":[\"100.svg\",\"500.svg\",\"100\",\"晴山沿い雷雨\"],\"124\":[\"100.svg\",\"500.svg\",\"100\",\"晴山沿い雪\"],\"125\":[\"112.svg\",\"512.svg\",\"300\",\"晴午後は雷雨\"],\"126\":[\"112.svg\",\"512.svg\",\"300\",\"晴昼頃から雨\"],\"127\":[\"112.svg\",\"512.svg\",\"300\",\"晴夕方から雨\"],\"128\":[\"112.svg\",\"512.svg\",\"300\",\"晴夜は雨\"],\"130\":[\"100.svg\",\"500.svg\",\"100\",\"朝の内霧後晴\"],\"131\":[\"100.svg\",\"500.svg\",\"100\",\"晴明け方霧\"],\"132\":[\"101.svg\",\"501.svg\",\"100\",\"晴朝夕曇\"],\"140\":[\"102.svg\",\"502.svg\",\"300\",\"晴時々雨で雷を伴う\"],\"160\":[\"104.svg\",\"504.svg\",\"400\",\"晴一時雪か雨\"],\"170\":[\"104.svg\",\"504.svg\",\"400\",\"晴時々雪か雨\"],\"181\":[\"115.svg\",\"515.svg\",\"400\",\"晴後雪か雨\"],\"200\":[\"200.svg\",\"200.svg\",\"200\",\"曇\"],\"201\":[\"201.svg\",\"601.svg\",\"200\",\"曇時々晴\"],\"202\":[\"202.svg\",\"202.svg\",\"300\",\"曇一時雨\"],\"203\":[\"202.svg\",\"202.svg\",\"300\",\"曇時々雨\"],\"204\":[\"204.svg\",\"204.svg\",\"400\",\"曇一時雪\"],\"205\":[\"204.svg\",\"204.svg\",\"400\",\"曇時々雪\"],\"206\":[\"202.svg\",\"202.svg\",\"300\",\"曇一時雨か雪\"],\"207\":[\"202.svg\",\"202.svg\",\"300\",\"曇時々雨か雪\"],\"208\":[\"202.svg\",\"202.svg\",\"300\",\"曇一時雨か雷雨\"],\"209\":[\"200.svg\",\"200.svg\",\"200\",\"霧\"],\"210\":[\"210.svg\",\"610.svg\",\"200\",\"曇後時々晴\"],\"211\":[\"210.svg\",\"610.svg\",\"200\",\"曇後晴\"],\"212\":[\"212.svg\",\"212.svg\",\"300\",\"曇後一時雨\"],\"213\":[\"212.svg\",\"212.svg\",\"300\",\"曇後時々雨\"],\"214\":[\"212.svg\",\"212.svg\",\"300\",\"曇後雨\"],\"215\":[\"215.svg\",\"215.svg\",\"400\",\"曇後一時雪\"],\"216\":[\"215.svg\",\"215.svg\",\"400\",\"曇後時々雪\"],\"217\":[\"215.svg\",\"215.svg\",\"400\",\"曇後雪\"],\"218\":[\"212.svg\",\"212.svg\",\"300\",\"曇後雨か雪\"],\"219\":[\"212.svg\",\"212.svg\",\"300\",\"曇後雨か雷雨\"],\"220\":[\"202.svg\",\"202.svg\",\"300\",\"曇朝夕一時雨\"],\"221\":[\"202.svg\",\"202.svg\",\"300\",\"曇朝の内一時雨\"],\"222\":[\"212.svg\",\"212.svg\",\"300\",\"曇夕方一時雨\"],\"223\":[\"201.svg\",\"601.svg\",\"200\",\"曇日中時々晴\"],\"224\":[\"212.svg\",\"212.svg\",\"300\",\"曇昼頃から雨\"],\"225\":[\"212.svg\",\"212.svg\",\"300\",\"曇夕方から雨\"],\"226\":[\"212.svg\",\"212.svg\",\"300\",\"曇夜は雨\"],\"228\":[\"215.svg\",\"215.svg\",\"400\",\"曇昼頃から雪\"],\"229\":[\"215.svg\",\"215.svg\",\"400\",\"曇夕方から雪\"],\"230\":[\"215.svg\",\"215.svg\",\"400\",\"曇夜は雪\"],\"231\":[\"200.svg\",\"200.svg\",\"200\",\"曇海上海岸は霧か霧雨\"],\"240\":[\"202.svg\",\"202.svg\",\"300\",\"曇時々雨で雷を伴う\"],\"250\":[\"204.svg\",\"204.svg\",\"400\",\"曇時々雪で雷を伴う\"],\"260\":[\"204.svg\",\"204.svg\",\"400\",\"曇一時雪か雨\"],\"270\":[\"204.svg\",\"204.svg\",\"400\",\"曇時々雪か雨\"],\"281\":[\"215.svg\",\"215.svg\",\"400\",\"曇後雪か雨\"],\"300\":[\"300.svg\",\"300.svg\",\"300\",\"雨\"],\"301\":[\"301.svg\",\"701.svg\",\"300\",\"雨時々晴\"],\"302\":[\"302.svg\",\"302.svg\",\"300\",\"雨時々止む\"],\"303\":[\"303.svg\",\"303.svg\",\"400\",\"雨時々雪\"],\"304\":[\"300.svg\",\"300.svg\",\"300\",\"雨か雪\"],\"306\":[\"300.svg\",\"300.svg\",\"300\",\"大雨\"],\"308\":[\"308.svg\",\"308.svg\",\"300\",\"雨で暴風を伴う\"],\"309\":[\"303.svg\",\"303.svg\",\"400\",\"雨一時雪\"],\"311\":[\"311.svg\",\"711.svg\",\"300\",\"雨後晴\"],\"313\":[\"313.svg\",\"313.svg\",\"300\",\"雨後曇\"],\"314\":[\"314.svg\",\"314.svg\",\"400\",\"雨後時々雪\"],\"315\":[\"314.svg\",\"314.svg\",\"400\",\"雨後雪\"],\"316\":[\"311.svg\",\"711.svg\",\"300\",\"雨か雪後晴\"],\"317\":[\"313.svg\",\"313.svg\",\"300\",\"雨か雪後曇\"],\"320\":[\"311.svg\",\"711.svg\",\"300\",\"朝の内雨後晴\"],\"321\":[\"313.svg\",\"313.svg\",\"300\",\"朝の内雨後曇\"],\"322\":[\"303.svg\",\"303.svg\",\"400\",\"雨朝晩一時雪\"],\"323\":[\"311.svg\",\"711.svg\",\"300\",\"雨昼頃から晴\"],\"324\":[\"311.svg\",\"711.svg\",\"300\",\"雨夕方から晴\"],\"325\":[\"311.svg\",\"711.svg\",\"300\",\"雨夜は晴\"],\"326\":[\"314.svg\",\"314.svg\",\"400\",\"雨夕方から雪\"],\"327\":[\"314.svg\",\"314.svg\",\"400\",\"雨夜は雪\"],\"328\":[\"300.svg\",\"300.svg\",\"300\",\"雨一時強く降る\"],\"329\":[\"300.svg\",\"300.svg\",\"300\",\"雨一時みぞれ\"],\"340\":[\"400.svg\",\"400.svg\",\"400\",\"雪か雨\"],\"350\":[\"300.svg\",\"300.svg\",\"300\",\"雨で雷を伴う\"],\"361\":[\"411.svg\",\"811.svg\",\"400\",\"雪か雨後晴\"],\"371\":[\"413.svg\",\"413.svg\",\"400\",\"雪か雨後曇\"],\"400\":[\"400.svg\",\"400.svg\",\"400\",\"雪\"],\"401\":[\"401.svg\",\"801.svg\",\"400\",\"雪時々晴\"],\"402\":[\"402.svg\",\"402.svg\",\"400\",\"雪時々止む\"],\"403\":[\"403.svg\",\"403.svg\",\"400\",\"雪時々雨\"],\"405\":[\"400.svg\",\"400.svg\",\"400\",\"大雪\"],\"406\":[\"406.svg\",\"406.svg\",\"400\",\"風雪強い\"],\"407\":[\"406.svg\",\"406.svg\",\"400\",\"暴風雪\"],\"409\":[\"403.svg\",\"403.svg\",\"400\",\"雪一時雨\"],\"411\":[\"411.svg\",\"811.svg\",\"400\",\"雪後晴\"],\"413\":[\"413.svg\",\"413.svg\",\"400\",\"雪後曇\"],\"414\":[\"414.svg\",\"414.svg\",\"400\",\"雪後雨\"],\"420\":[\"411.svg\",\"811.svg\",\"400\",\"朝の内雪後晴\"],\"421\":[\"413.svg\",\"413.svg\",\"400\",\"朝の内雪後曇\"],\"422\":[\"414.svg\",\"414.svg\",\"400\",\"雪昼頃から雨\"],\"423\":[\"414.svg\",\"414.svg\",\"400\",\"雪夕方から雨\"],\"425\":[\"400.svg\",\"400.svg\",\"400\",\"雪一時強く降る\"],\"426\":[\"400.svg\",\"400.svg\",\"400\",\"雪後みぞれ\"],\"427\":[\"400.svg\",\"400.svg\",\"400\",\"雪一時みぞれ\"],\"450\":[\"400.svg\",\"400.svg\",\"400\",\"雪で雷を伴う\"]}";
const char *day3area = "東部"; // 3日予報の地方(webより)
const char *day3city = "横浜"; // 3日予報の都市(webより)
const char *day7area = "神奈川県"; // 7日予報の地方(webより)
const char *day7city = "横浜"; // 7日予報の都市(webより)
const uint8_t days3 = 0; // 3日予報のjsonインデックス[0]
const uint8_t days7 = 1; // 7日予報のjsonインデックス[1]
const char *ssid1 = "*****"; // 自分のwifiのssid1
const char *pass1 = "*****"; // そのPW
const char *ssid2 = "*****"; // 自分のwifiのssid2
const char *pass2 = "*****"; // そのPW
const char *ssid3 = "*****"; // 自分のwifiのssid2
const char *pass3 = "*****"; // そのPW
int8_t dMenu; // 0:今日,1:明日,2:明後日
char dayWeek[7][4] = { "土", "日", "月",
"火", "水", "木", "金" }; // 曜日
static JsonDocument doc; // jsonのメモリ領域を確保
static JsonDocument doc2; // 天気コード一覧
String todayStr; // 表示の年月日 検索に使用
uint8_t setWeek(uint16_t yyear, uint8_t mmonth, uint8_t dday) {
if (mmonth < 3) { // ツェラーの公式 年月日から曜日weekを計算
mmonth += 12;
yyear--;
}
uint16_t year1 = yyear / 100;
uint16_t year2 = yyear % 100;
uint8_t week = (dday + (int)(26 * (mmonth + 1) / 10) + year2 + (int)(year2 / 4)
+ (5 * year1) + (int)(year1 / 4))
% 7;
return week;
}
void SetDisplay() { // 初期画面設定関数
int32_t WW = M5.Display.width(); // 画面幅を取得
int32_t HH = M5.Display.height(); // 画面高さを取得
if (WW == HH) { // 画面を横長にする
M5.Display.setRotation(0); // 0度回転
} else {
M5.Display.setRotation(1); // 90度回転
}
if (HH > WW) { // 縦長なので横:WW,縦:HHにする
int32_t HHWW = HH;
HH = WW;
WW = HHWW;
}
M5.Display.fillScreen(TFT_BLACK); // 全画面黒
M5.Display.setFont(&fonts::lgfxJapanGothic_24); // ゴシック(8,12,16,20,24,28,32,36,40)
M5.Display.setTextSize(1); // テキストサイズ(倍)
M5.Display.setBrightness(100); // バックライト輝度(0-255)実際は数段階
M5.Display.setTextColor(TFT_GREEN, TFT_BLACK); // 色設定(文字色[,背景色])
M5.Display.setTextWrap(true, false); // 文字列の折返し(x軸,y軸)
}
String mojiHenkan(String moji) { // 文字変換関数
moji.replace(" ", ""); // 全角空白を削除
moji.replace("晴れ", "晴"); // 天気で使用
moji.replace("くもり", "曇"); // 天気で使用
moji.replace("曇り", "曇"); // 天気で使用
//moji.replace("のち", "/"); // 天気で使用
//moji.replace("時々", "I"); // 天気で使用
//moji.replace("一時", "II"); // 天気で使用
moji.replace("メートル", "m"); // 波で使用
moji.replace("0", "0"); // 半角変換 波で使用
moji.replace("1", "1"); //
moji.replace("2", "2"); //
moji.replace("3", "3"); //
moji.replace("4", "4"); //
moji.replace("5", "5"); //
moji.replace("6", "6"); //
moji.replace("7", "7"); //
moji.replace("8", "8"); //
moji.replace("9", "9"); //
moji.replace(".", "."); //
moji.replace("-", "/"); // "-" → "/" 時刻で使用
moji.replace("T", " "); // "T" → " " 時刻で使用
moji.replace("\n", ""); // 予報文で使用 (今回は未使用)
return moji; // 文字列mojiに変換後入れ戻る
}
// Areaの文字列が検索文字列と一致するIndexを求める
uint8_t FindSpot(JsonDocument doc, uint32_t days, uint32_t timeIndex, String spot) {
for (uint8_t i = 0; i < doc[days]["timeSeries"][timeIndex]["areas"].size(); i++) {
// 全体のjson[0:3日予報/1:7日予報]["timeSeries"][00:天気・風・波/01:降水確率/02:気温/
// 10:天気コード・降水確率・信頼度/11:気温]["areas"] *数字の十の位は〇日予報の値
// 場所の数だけ繰返し
if (doc[days]["timeSeries"][timeIndex]["areas"][i]["area"]["name"].as() == spot) {
// 表示項目の検索場所名と一致したら
return i; // 一致したIndex
}
}
return 0; // 一致しなかったらとりあえず0
}
JsonDocument getJson(const char *url) { // wifi接続+json読込関数
if (WiFi.status() == WL_CONNECTED) { // wifiが接続されていたら
https.begin(url); // アクセスするURLを登録
if (https.GET() > 0) { // アクセス先があれば
DeserializationError error = deserializeJson(doc, https.getString()); // 解析(JsonDocument,JSON入力)
if (error) { // jsonがエラーなら
M5.Display.print("json解析エラー"); // 表示
}
} else { // アクセス先が無ければ
M5.Display.println("エラー HTTP"); // 表示
}
https.end(); // https通信終了
} else { // wifiが接続できないなら
M5.Display.println("エラー wifi"); // 表示
}
return doc; // 取得したjsonを返す
}
void printWeather(JsonDocument doc, int8_t dMenu) { // 天気表示関数
//if (doc == NULL) return;
M5.Display.fillScreen(TFT_BLACK); // 全画面黒
M5.Display.setCursor(0, 0); // カーソル位置
// 1行目 発表時刻・気象台
String s = doc[days3]["reportDatetime"]; // 発表日時を取得
uint8_t reportTime = s.substring(11, 13).toInt(); // 発表時判定用
String reportDateTime = s.substring(5, 7) + "月" + s.substring(8, 10) + "日"
+ s.substring(11, 13) + "時 "; // 発表月日時 年は略
M5.Display.setTextSize(0.8); // 文字サイズ縮小
M5.Display.print(mojiHenkan(reportDateTime)); // 文字変換後表示 発表日時
String publishingOffice = doc[days3]["publishingOffice"]; // 気象台名を取得
M5.Display.println(publishingOffice + "発表"); // 表示 気象台名
M5.Display.setTextSize(1); // 文字サイズ戻す
// 2行目 表示の日付
switch (dMenu) { // 表示日が今日~明後日を表示
case 0:
s = doc[days3]["timeSeries"][0]["timeDefines"][0]
.as(); // 3日予報天気項目の1番目
todayStr = s.substring(0, 10); // 今日の日付
M5.Display.print("今日"); // 表示
break;
case 1:
s = doc[days3]["timeSeries"][0]["timeDefines"][1]
.as(); // 3日予報天気項目の2番目
todayStr = s.substring(0, 10); // 明日の日付
M5.Display.print("明日"); // 表示
break;
case 2:
if (reportTime == 5) { // 5時発表なら
s = doc[days7]["timeSeries"][0]["timeDefines"][2]
.as(); // 7日予報降水確率の3番目
todayStr = s.substring(0, 10); // 明後日の日付
} else { // 11・17時発表なら
s = doc[days3]["timeSeries"][0]["timeDefines"][2]
.as(); // 3日予報天気項目の3番目
todayStr = s.substring(0, 10); // 明後日の日付
}
M5.Display.print("明後日"); // 表示
break;
}
JsonObject dayData = doc[days3]["timeSeries"][0]; // 条件取出し 3日予報 天気・風・波を取得
if ((dayData["timeDefines"].size() == 2) && dMenu == 2) { // 日付が2個and明後日なら (AM5発表時) 7日予報より
JsonObject dayData = doc[days7]["timeSeries"][0]; // 条件取出し 7日予報 天気・風・波を取得
String dateDay = dayData["timeDefines"][dMenu]; // 天気の項目の日付を取得
uint16_t yyear = dateDay.substring(0, 4).toInt(); // 表示する年 曜日計算にのみ使用
uint8_t mmonth = dateDay.substring(5, 7).toInt(); // 表示する月 曜日計算のみに使用
uint8_t dday = dateDay.substring(8, 10).toInt(); // 表示する日
int wweek = setWeek(yyear, mmonth, dday); // 曜日計算
M5.Display.printf(" %2d日(", dday); // 表示する日
M5.Display.print(dayWeek[wweek]); // 表示する曜日
M5.Display.println(") [気象庁]"); // 表示
// 3-4行目 天気コード 7日予報より (AM5発表時)
JsonObject timeData = doc[days7]["timeSeries"][0]; // 7日予報の天気コード・降水確率・信頼度
for (int8_t i = 0; i < timeData["timeDefines"].size(); i++) { // 時刻の数繰返す
if (timeData["timeDefines"][i].as().indexOf(todayStr) != -1) {
// もし、年月日の中から、検索文字(表示日の年月日)が見つかれば
String weatherCode = timeData["areas"][FindSpot(doc, days7, 0, day7area)]
["weatherCodes"][i]
.as(); // 7日予報の天気コード
M5.Display.print("天気: (" + weatherCode + ") "); // 表示 天気コード
DeserializationError error = deserializeJson(doc2, weatherCodeJson); // 解析(JsonDocument,JSON入力)
if (error) {
Serial.print("エラー 天気コード"); // 解析エラー
}
s = doc2[weatherCode][3].as(); // 天気コードから変換した天気文
M5.Display.println(s); // 表示 天気文
}
}
// 5-6行目 風
M5.Display.setCursor(0, 19 + 24 * 3); // カーソル位置
M5.Display.println("風: --"); // 表示
// 7行目 波
M5.Display.setCursor(0, 19 + 24 * 5); // カーソル位置
M5.Display.println("波: --"); // 表示
} else {
String dateDay = dayData["timeDefines"][dMenu]; // 天気の項目の日付を取得
uint16_t yyear = dateDay.substring(0, 4).toInt(); // 表示する年 曜日計算にのみ使用
uint8_t mmonth = dateDay.substring(5, 7).toInt(); // 表示する月 曜日計算のみに使用
uint8_t dday = dateDay.substring(8, 10).toInt(); // 表示する日
int wweek = setWeek(yyear, mmonth, dday); // 曜日計算
M5.Display.printf(" %2d日(", dday); // 表示する日
M5.Display.print(dayWeek[wweek]); // 表示する曜日
M5.Display.println(") [気象庁]"); // 表示
// 3-4行目 天気文 3日予報より
String weather = dayData["areas"][FindSpot(doc, days3, 0, day3area)]["weathers"][dMenu]
.as(); // 天気予報文を取得 (json全体,0=3日予報,0=天気風波,検索文字列)
M5.Display.println("天気: " + mojiHenkan(weather)); // 文字変換後表示 天気予報
// 5-6行目 風 3日予報より
M5.Display.setCursor(0, 19 + 24 * 3); // カーソル位置
String winds = dayData["areas"][FindSpot(doc, days3, 0, day3area)]["winds"][dMenu]
.as(); // 風を文字列で取得
M5.Display.println("風: " + mojiHenkan(winds)); // 文字変換後表示 風
// 7行目 波 3日予報より
M5.Display.setCursor(0, 19 + 24 * 5); // カーソル位置
String waves = dayData["areas"][FindSpot(doc, days3, 0, day3area)]["waves"][dMenu]
.as(); // 波を文字列で取得
M5.Display.println("波: " + mojiHenkan(waves)); // 文字変換後表示 波
}
// 8-9行目 降水確率 3日予報+7日予報
M5.Display.setCursor(0, 19 + 24 * 6); // カーソル位置
M5.Display.println("降水確率 00- 06- 12- 18-"); // 表示
if (dMenu < 2) { // 今日・明日は3日予報より
char popArray[4][5] = { " -- ", " -- ", " -- ", " -- " }; // 降水確率初期表示内容
JsonObject rainData = doc[days3]["timeSeries"][1]; // 条件取出し 3日予報 降水確率を取得
for (int8_t i = 0; i < rainData["timeDefines"].size(); i++) { // 時刻の数繰返す
if (rainData["timeDefines"][i].as().indexOf(todayStr) != -1) {
// もし、天気・風・波の年月日の中から、検索文字(表示日の年月日)が見つかれば (max 4)
String pops = rainData["areas"][FindSpot(doc, days3, 0, day3area)]["pops"][i]
.as(); // 降水確率を抽出
s = rainData["timeDefines"][i].as(); //その降水確率の時間
String rainTime = s.substring(11, 13); // 時を抽出
String ss = " " + pops + " "; // 降水確率
if (rainTime == "00") strcpy(popArray[0], ss.c_str()); // 00-06の範囲の降水確率と交換
if (rainTime == "06") strcpy(popArray[1], ss.c_str()); // 06-12の範囲の降水確率と交換
if (rainTime == "12") strcpy(popArray[2], ss.c_str()); // 12-18の範囲の降水確率と交換
if (rainTime == "18") strcpy(popArray[3], ss.c_str()); // 18-24の範囲の降水確率と交換
}
}
M5.Display.print(" "); // 表示
for (int8_t i = 0; i < 4; i++) { // 4個表示
M5.Display.print(popArray[i]); // 各時間範囲の降水確率
}
M5.Display.println("%"); // 表示
} else { // 明後日は7日予報より
JsonObject rainData = doc[days7]["timeSeries"][0]; // 7日予報の天気コード・降水確率・信頼度
for (int8_t i = 0; i < rainData["timeDefines"].size(); i++) { // 3日予報と同様
if (rainData["timeDefines"][i].as().indexOf(todayStr) != -1) { // 3日予報と同様
String pops = rainData["areas"][FindSpot(doc, days7, 0, day7area)]["pops"][i]
.as(); // 同様に3日予報の値を7日予報に変更
M5.Display.printf(" %2s%% --- --- --- ---\n", pops); // 表示 1日の降水確率
}
}
}
// 10行目 最高最低気温 3日予報+7日予報より
int8_t tmpMin = 99, tmpMax = -99; // 仮の最低・最高温度
if (dMenu < 2) { // 今日・明日は3日予報より
JsonObject tmpData = doc[days3]["timeSeries"][2]; // 条件取り出し 3日予報 気温
for (int i = 0; i < tmpData["timeDefines"].size(); i++) { // 時刻の数だけ繰返す
if (tmpData["timeDefines"][i].as().indexOf(todayStr) != -1) { // 検索日が有ったら
int8_t val = tmpData["areas"][FindSpot(doc, days3, 2, day3city)]["temps"][i]; // 検索日の温度を抽出
if (val < tmpMin) tmpMin = val; // 同日に2値あるので小さい方を最低とする
if (val > tmpMax) tmpMax = val; // 同日に2値あるので大きい方を最高とする
}
}
} else { // 明後日は7日予報より
JsonObject tmpData = doc[days7]["timeSeries"][1]; // 条件取り出し 7日予報 気温
for (int i = 0; i < tmpData["timeDefines"].size(); i++) { // 3日予報と同じ
if (tmpData["timeDefines"][i].as().indexOf(todayStr) != -1) { // 3日予報と同じ
tmpMin = tmpData["areas"][FindSpot(doc, days7, 1, day7city)]["tempsMin"][i]; // 最低気温
tmpMax = tmpData["areas"][FindSpot(doc, days7, 1, day7city)]["tempsMax"][i]; // 最高気温
}
}
}
M5.Display.print("朝 "); // 表示
M5.Display.setTextColor(TFT_CYAN); // 文字色
if ((tmpMin == tmpMax) || (tmpMin == 99)) { // 最低が最高と同じ or 最低が無ければ
M5.Display.print("--"); // 表示
} else { // 最低があれば
M5.Display.print(tmpMin); // 表示 最低気温
}
M5.Display.setTextColor(TFT_GREEN); // 文字色
M5.Display.print("℃min 日中 "); // 表示
M5.Display.setTextColor(TFT_RED); // 文字色
if (tmpMax == -99) { // 最高が無ければ
M5.Display.print("--"); // 表示
} else { // 最高があれば
M5.Display.print(tmpMax); // 表示 最高気温
}
M5.Display.setTextColor(TFT_GREEN); // 文字色
M5.Display.println("℃max"); // 表示
M5.Display.fillRect(106 * dMenu, 237, 106, 3, TFT_LIGHTGREY); // 表示中の日を表すバー (x,y,w,h,色)
delay(500); // 0.5秒待つ
}
void setup() {
auto cfg = M5.config(); // M5設定用の構造体を代入
M5.begin(cfg); // M5本体の初期化
SetDisplay(); // 初期画面設定関数へ
M5.Display.println("wifi接続開始"); // 表示
wifiMulti.addAP(ssid1, pass1); // ssid1を登録
wifiMulti.addAP(ssid2, pass2); // ssid2を登録
wifiMulti.addAP(ssid3, pass3); // ssid3を登録
M5.Display.println("wifi接続中"); // 表示
for (int i = 20; i && WiFi.status() != WL_CONNECTED; --i) { // 20回以内にwifi接続されなかったら
wifiMulti.run(); // 一番強いアクセスポイントに接続
M5.Display.print("."); // 表示
delay(1000); // 1秒待つ
}
if (wifiMulti.run() == WL_CONNECTED) { // wifiが接続されたら
M5.Display.print("\nwifi接続済\nssid:"); // 表示
M5.Display.println(WiFi.SSID()); // 接続したssidを表示
} else { // 接続されなかったら
M5.Display.println("\nwifi未接続"); // 表示
}
doc = getJson(weatherJson); // 関数へ
dMenu = 0; // 表示は今日の予報
printWeather(doc, dMenu); // 表示関数へ
}
void loop() {
M5.update(); // ボタンに合わせて表示日を変更
if (M5.BtnA.wasPressed()) { // Aボタンが押されたら
dMenu--; // 前日
if (dMenu < 0) dMenu = 2; // 今日の前は明後日
printWeather(doc, dMenu); // 表示関数へ
}
if (M5.BtnB.wasPressed()) { // Bボタンが押されたら
dMenu++; // 翌日
if (dMenu > 2) dMenu = 0; // 明後日の次は今日
printWeather(doc, dMenu); // 表示関数へ
}
delay(100); // 0.1秒待つ
}
* flash memory(2.1Mbyte)のうち、スケッチが63%使用。RAM(328kbyte)のうち、global変数が15%使用、local変数で278kbyte使用可能。(1000byte=1kbyteで計算)