はじめに
PicoMiteのユーザマニュアル77ページにTCPクライアントの実装例としてopenweathermap.orgから現在のパリの気温を取得するプログラムが示されている。このプログラムは動作するが、OpenWeatherMapの現在のAPIは[One Call API 3.0](https://openweathermap.org/api)
になっています。
ここではWebMite(MMBasic)のユーザマニュアルのプログラムをもとにOne Call API 3,.0
を利用してopenweathermap.orgからの気象情報の取得するプログラムについて説明しています。
実行環境
実行環境は次の通りです。
- ハードウェア:Raspberry Pi Pico 2 Wを搭載したPicoCalc
- ファームウェア:WebMiteバージョン6.0002RC26(https://github.com/madcock/PicoMiteAllVersions からダウンロードしたソースからRP2350用に自分でビルドしました)
MMBasicのプログラムはMac上で入力し、TFTPで転送しています。
準備〜OpenWeatherへユーザ登録
openweathermap.orgのAPIのOne Call API 3.0を利用するには次の作業が必要です。
- OpenWeathermapへのユーザ登録
- ユーザ名、メールアドレス、パスワードを登録します
- 確認メール内のリンクをクリックして確認
- プラン選択はないので登録完了で無料プラン(Free Plan)になります
- APIキーの生成
- ユーザ登録完了後にサインインし、メニューの
My API Keys
から生成します
- ユーザ登録完了後にサインインし、メニューの
- One Call API 3.0のサブスクライブ
- Weather APIのページからSubscribeをクリックして支払い情報などを登録します。
- 登録完了後、その情報がすぐには反映されないようで小一時間待ってOne Call API 3.0が利用できるようになりました
https://openweathermap.org/api の記載ではOne Call API 3.0
を利用すると下記のデータにアクセスできると記されています。
-
現在の天気と予報:
- 1時間ごとの分予報
- 48時間ごとの時間予報
- 8日間の日次予報
および政府の気象警報
- 46年以上の過去の気象データアーカイブと4日後の予報を含む、任意のタイムスタンプの気象データ
- 46年以上のアーカイブと1.5年先の予報を含む、気象データの日次集計
- 今日と明日の予報を人間が読める形式で表示する天気概要
一日のAPI呼び出しのうち、最初の1000コールまでは無料で、それを越えると1コール0.0012GBPの費用が発生します。https://openweathermap.org/price#weatherに価格の記載があります。APIのコール数の集計はJSTではなくUTCのタイムゾーンで行われています。
MMBasicでTCPクライアント
処理手順
MMBasicでTCPクライアントを実現するにはサーバからの応答を保存する配列(長い文字列変数)を用意し、次の手順で処理します。
-
WEB OPEN TCP CLIENT domain$, port
コマンドで接続先ドメイン(domain$)にポート番号(port)で接続 -
WEB TCP CLIENT REQUEST query$, inbuf
コマンドでリクエスト(query$)を送信して応答を変数(inbuf)に保存 -
WEB CLOSE TCP CLIENT
コマンドでTCPのセッションを閉じる - 受信したデータの処理
作成したプログラム
ユーザマニュアル77ページの例題プログラムとOpenWeathMapのAPIを参考に、の現在の天気を取得するプログラムを作成しました。プログラムは次の通りです。
1 Const Key = "0123456789ABCDEFGHIJLKMNOPQRSTUV" ' API key
2 Const CRLF$ = Chr$(13) + Chr$(10) ' CR+LF
3 Const Domain$ = "api.openweathermap.org" ' Traget domain
4 Const lat = "35.70" ' Latitude
5 COnst lon = "139.77" ' Longitude
6 Dim Query$ = "GET /data/3.0/onecall?" ' Query string
7 Query$ = Query$ + "lat=" + lat + "&lon=" + lon
8 Query$ = Query$ + "&exclude=minutely,hourly,daily"
9 Query$ = Query$ + "&units=metric"
10 Query$ = Query$ + "&APPID="+Key+CRLF$
11 Dim buff%(4096/8) ' LongString variable
12
13 WEB Open tcp client Domain$, 80 ' Connect to Server
14 WEB tcp client request Query$, buff%() ' Send sequest
15 WEB close tcp client ' Close connection
16 ' Get value
17 off = Val(Json$(buff%(), "timezone_offset"))
18 dt$ = DateTime$(Val(Json$(buff%(),"current.dt")) + off)
19 sr$ = DateTime$(Val(Json$(buff%(),"current.sunrise")) + off)
20 ss$ = DateTime$(Val(Json$(buff%(),"current.sunset")) + off)
21 main$= Json$(buff%(),"current.weather[0].main")
22 desc$= Json$(buff%(),"current.weather[0].description")
23 temp = Val(Json$(buff%(), "current.temp"))
24 pres = Val(Json$(buff%(),"current.pressure"))
25 humi = Val(Json$(buff%(),"current.humidity"))
26
27 Print
28 Print "=== Akihabara weather ==="
29 print "Date :";dt$
30 Print "Sunrise:";sr$
31 Print "Sunset :";ss$
32 Print "main :";main$
33 Print "Temp :";temp;"C"
34 Print "Press :";pres;"hPa"
35 Print "Humid :";humi;"%"
36 Print "Desc :";desc$
定数と変数定義
プログラムの1〜11行目でサーバへ接続し、問合せするために必要な値を定数および変数に設定しています。
定数・変数 | 値など |
---|---|
Key | 取得したAPIキー |
CRLF$ | 改行コード |
lat | 情報を取得する場所の緯度 |
lon | 情報を取得する場所の軽度 |
Query$ | APIでの問合せの文字列 |
buff%() | 問合せ結果を保存 |
buff%()は配列の定義と同じですが長い文字列変数とするために添字を8で割る設定にし定ます。これにより配列の各要素が8バイトを占めるようしています。この定義で4096文字を保存できます。
API
One Call API 3.0で現在の天気データと予報データを取得するAPIの形式は次のとおりです。
https://api.openweathermap.org/data/3.0/onecall?lat={lat}&lon={lon}&exclude={part}&appid={API key}
このAPIの/data/3.0/onecall?lat={lat}&lon={lon}&exclude={part}&appid={API key}
の部分をGETメソッドで取得するリソースとして変数Query$
に格納します。
APIのパラメータを表に示します。
パラメータ | 必須か | 内容 |
---|---|---|
lat | 必須 | 緯度(-90〜90) |
lon | 必須 | 軽度(-180〜180) |
appid | 必須 | 取得したAPIキー |
exclude | オプション | 気象データからの除外項目指定。current(現在),minutely(分単位),hourly(時間単位),daily(日単位),alerts(警告) |
units | オプション | 測定単位。stanard(温度:ケルビン、風速:m/s),metric(温度:摂氏、風速:m/s),imperial(温度:華氏、風速:マイル/時)。デフォルトはstandard |
lang | オプション | 出力(descriptionフィールド)の言語指定(日本語はja) |
13〜15行目でOpenWeatherMapに接続し、GETメソッドを使ってAPIを呼び出し、その応答をbuff%()に格納し、接続を閉じます。OpenWeatherMapからの応答はJSON形式の文字列データで、下記に取得したデータを読みやすい形式に整形したリストを表示します。
{
"lat": 35.7,
"lon": 139.77,
"timezone": "Asia/Tokyo",
"timezone_offset": 32400,
"current": {
"dt": 1749366544,
"sunrise": 1749324297,
"sunset": 1749376508,
"temp": 299.28,
"feels_like": 299.28,
"pressure": 1009,
"humidity": 61,
"dew_point": 291.17,
"uvi": 1.31,
"clouds": 0,
"visibility": 10000,
"wind_speed": 4.63,
"wind_deg": 190,
"weather": [
{
"id": 500,
"main": "Rain",
"description": "light rain",
"icon": "10d"
}
],
"rain": {
"1h": 0.53
}
}
}
JSON形式データから値の取り出し
17〜25行目でJSON$関数を使って上記のJSON形式のデータから下記のデータを取り出しています。
JSON$関数のパラメータは長い文字列変数(buff%()と取り出すデータのキーの文字列です。
JSON$(buff%(), key$)
キー | 内容 | 変数 |
---|---|---|
timezone_offset | タイムゾーンのオフセットの秒数 | off |
dt | 現在の日時(UTC) | dt$ |
current.sunrise | 日出時間(UTC) | sr$ |
current.sunset | 日没時間(UTC) | ss$ |
current.weather[0].main | 現在の天気 | main$ |
current.weather[0].description | 天気の説明 | desc$ |
current.temp | 温度(℃) | temp |
current.pressure | 気圧(hPa) | pres |
current.humidity | 湿度(%) | humi |
27〜36行目で取得したデータを表示しています。
実行結果
プログラムは秋葉原付近の現在の天気情報を取得し、現在日時、日出、日没、天気、気温、気圧、湿度、説明を表示しています。
> RUN
tcp address 15.235.226.167
Connected
=== Akihabara weather ===
Date :08-06-2025 21:45:05
Sunrise:08-06-2025 04:24:57
Sunset :08-06-2025 18:55:08
main :Clear
Temp : 23.5C
Press : 1011hPa
Humid : 75%
Desc :clear sky
>
最後に
最初は気象庁の防災データを取得しようとしましたがHTTPで気象庁のデータを取得しようとすると301エラーとなり、HTTPでのデータ取得ができません。これはMMBasicのTCPクライアントはHTTP(80番ポート)接続のみでHTTPS(443番ポート)接続をサポートしていないのが原因でした。TLS接続をサポートしたファームウェアの登場を期待したいところです。