何をするか?
MixJuice経由でWeb APIを利用し、IchigoJamから現在の日時を取得します。
現在の日時を取得するWeb API
現在の日時を取得するWeb APIを探したところ、以下のものが見つかりました。
日本標準時プロジェクト
日本標準時プロジェクト https/http を介してアクセスされる場合
現在時刻を時分秒形式で返すAPIが定義されています。
https://ntp-a1.nict.go.jp/cgi-bin/time
以下のような形式で現在時刻が取得できる仕様です。
Sat Jun 5 03:53:33 2021 JST
月が数字ではなく英字列なのが気になりますが、余計なデータが無く扱いやすそうな仕様!
さらに、ヘッダはAccess-Control-Allow-Origin:*
を含み、HTTPSにも対応する仕様となっています。
IchigoJam webのバーチャルMixJuice対応もバッチリな仕様!
…しかし、毎月6日~月末はサービス停止、
2022年3月31日をもって完全にサービス終了となっており、使い物になりません。
入出力の仕様が素晴らしいだけに、非常に残念!!
IchigoJam + MixJuice用 日付&時間データ
IchigoJam + MixJuice用 日付&時間データ
以下のURLで日本の現在時刻を取得できます。
http://www.openspc2.org/data/date/full.txt
以下のような形式の結果が返ります。
2021
12
14
2
0
23
秒の情報は取得できないようですが、「MixJuice用」と銘打っているだけあって形式のシンプルさは最高です。
しかし、ヘッダにAccess-Control-Allow-Origin
が含まれておらず、
HTTPSにも対応していない(接続できない)ので、IchigoJam webのバーチャルMixJuiceからのアクセスは難しそうです。
World Time API
以下のURLで日本の現在時刻を取得できます。
https://worldtimeapi.org/api/timezone/Asia/Tokyo
また、アクセス元のIPアドレスに基づくタイムゾーンの自動選択もできます。
https://worldtimeapi.org/api/ip
以下のような形式の結果が返ります。
{"abbreviation":"JST","client_ip":"35.199.178.127","datetime":"2021-12-14T00:12:43.579568+09:00","day_of_week":2,"day_of_year":348,"dst":false,"dst_from":null,"dst_offset":0,"dst_until":null,"raw_offset":32400,"timezone":"Asia/Tokyo","unixtime":1639408363,"utc_datetime":"2021-12-13T15:12:43.579568+00:00","utc_offset":"+09:00","week_number":50}
見やすく整形すると、以下のようになります。
{
"abbreviation": "JST",
"client_ip": "35.199.178.127",
"datetime": "2021-12-14T00:12:43.579568+09:00",
"day_of_week": 2,
"day_of_year": 348,
"dst": false,
"dst_from": null,
"dst_offset": 0,
"dst_until": null,
"raw_offset": 32400,
"timezone": "Asia/Tokyo",
"unixtime": 1639408363,
"utc_datetime": "2021-12-13T15:12:43.579568+00:00",
"utc_offset": "+09:00",
"week_number": 50
}
HTTPSでのアクセスに対応しており、ヘッダにaccess-control-allow-origin: *
が含まれるため、
IchigoJam webのバーチャルMixJuiceからのアクセスもしやすいです。
ただし、単純に時刻を取得するためだけに使うには結果が長いです。
結果をJSONではなくプレーンテキストで返すモードもありますが、結果の長さはあまり変わりませんでした。
TimeAPI
Simple and Free Time API | TimeAPI
以下のURLで日本の現在時刻を取得できます。
https://www.timeapi.io/api/Time/current/zone?timeZone=Asia/Tokyo
以下のような形式の結果が返ります。
{"year":2021,"month":12,"day":13,"hour":23,"minute":51,"seconds":12,"milliSeconds":388,"dateTime":"2021-12-13T23:51:12.3888497","date":"12/13/2021","time":"23:51","timeZone":"Asia/Tokyo","dayOfWeek":"Monday","dstActive":false}
見やすく整形すると、以下のようになります。
{
"year": 2021,
"month": 12,
"day": 13,
"hour": 23,
"minute": 51,
"seconds": 12,
"milliSeconds": 388,
"dateTime": "2021-12-13T23:51:12.3888497",
"date": "12/13/2021",
"time": "23:51",
"timeZone": "Asia/Tokyo",
"dayOfWeek": "Monday",
"dstActive": false
}
HTTPSには対応していますが、Access-Control-Allow-Origin
ヘッダは入っておらず、
IchigoJam webのバーチャルMixJuiceでの利用は若干面倒かもしれません。
(CORS Everywhereなどの拡張機能を用いればアクセスは可能です)
World Clock API
以下のURLでUTCの現在時刻(日本時間の9時間前)が取得できます。
http://worldclockapi.com/api/json/utc/now
以下のような形式の結果が返ります。
{"$id":"1","currentDateTime":"2021-12-13T15:30Z","utcOffset":"00:00:00","isDayLightSavingsTime":false,"dayOfTheWeek":"Monday","timeZoneName":"UTC","currentFileTime":132838830284824919,"ordinalDate":"2021-347","serviceResponse":null}
見やすく整形すると、以下のようになります。
{
"$id": "1",
"currentDateTime": "2021-12-13T15:30Z",
"utcOffset": "00:00:00",
"isDayLightSavingsTime": false,
"dayOfTheWeek": "Monday",
"timeZoneName": "UTC",
"currentFileTime": 132838830284824910,
"ordinalDate": "2021-347",
"serviceResponse": null
}
ただし、日本時間の直接取得には対応していないようです。
(utc
の代わりにjst
やすべてのタイムゾーンでの現在の時間に載っている他のUTC+9のタイムゾーンの名前を入れると、無効なタイムゾーン(not a valid Time Zone)としてエラーになりました)
また、秒単位の時刻の取得も簡単にはできないようです。
(CyberChefを用いるとcurrentFileTime
から秒単位の時刻を取り出せるので、不可能ではないと思われます)
さらに、HTTPSへの対応が不完全(接続は出来るが証明書の名前が無効)であり、
ヘッダにAccess-Control-Allow-Origin
が含まれないため、
IchigoJam webのバーチャルMixJuiceからのアクセスは難しそうです。
まとめ
API | HTTPS対応 | CORS対応 | 結果のシンプルさ | 日本時間対応 | 秒単位対応 | 時間の制約無くアクセス可能 |
---|---|---|---|---|---|---|
日本標準時プロジェクト | ○ | ○ | ○ | ○ | ○ | × |
IchigoJam + MixJuice用 日付&時間データ | × | × | ○ | ○ | × | ○ |
World Time API | ○ | ○ | × | ○ | ○ | ○ |
TimeAPI | ○ | × | × | ○ | ○ | ○ |
World Clock API | × | × | × | × | △ | ○ |
(ヘッダがAccess-Control-Allow-Origin:*
を含むことを「CORS対応」としています)
現在の日時を取得する
方針
今回は、IchigoJam webのバーチャルMixJuiceからのアクセスがしやすく、
利用時間の制限も無い World Time API を用いて現在の日時を取得することにしました。
取得する形式は、データの終わりが}
で明示されるためわかりやすいJSONを用いることにしました。
返されるデータのうち、"datetime":"2021-12-14T00:12:43.579568+09:00",
の部分に日時の情報が、
"day_of_week":2,
の部分に曜日の情報が入っているので、これらから情報を抜き出します。
今回扱うJSONのデータでは、オブジェクトのネストが無く、
データの文字列にカンマやエスケープ、閉じカッコは含まれていないようです。
そこで、この性質を利用し、以下のようなロジックで情報を抜き出します。
-
,
があったら、名前モードにする。 -
:
があったら、データモードにする。 -
"
があったら、文字列モードかどうかを切り替える。(名前/データモードとは別に管理するモード) -
}
があったら、読み取りを終了する。 - 名前モードの文字列モードでは、名前の識別のため、名前の文字の文字コードの和を計算する。
- データモードでは、十進数値を読み取り、数字の後数字以外が来たら読み取った数値を記録する。
-
"datetime"
の後では、日時を表す数値をそれぞれ配列に格納する。 -
"day_of_week"
の後では、曜日を表す数値を変数に格納する。 - それ以外では、無視する。
-
実装
コード全体
10 ' ジコク シュトク
20 ?"MJ GETS worldtimeapi.org/api/timezone/Asia/Tokyo"
30 W=0:LET[0],0,0,0,0,0,0:N=1:H=0:S=0:P=0:V=0:E=0
40 C=INKEY():IF C=0 GOTO 40 ELSE GOTO 70
50 CLT
60 C=INKEY():IF TICK()>=30 GOTO 160 ELSE IF C=0 GOTO 60
70 IF C=#22 S=!S:IF S AND N H=-#22
80 IF S AND N H=H+C
90 IF C=#3A:N=0
100 IF C=#2C:N=1
110 IF #30 <= C AND C <= #39 V=V*10+C-#30:E=1 ELSE IF E GOTO 130
120 IF C=#7D GOTO 160 ELSE GOTO 50
130 IF H=845 AND P<6 [P]=V:P=P+1
140 IF H=1149 W=V
150 V=0:E=0:GOTO 120
160 ?[0];"/";[1];"/";[2];" (";
170 IF W=0 ?"Sun";
180 IF W=1 ?"Mon";
190 IF W=2 ?"Tue";
200 IF W=3 ?"Wed";
210 IF W=4 ?"Thu";
220 IF W=5 ?"Fri";
230 IF W=6 ?"Sat";
240 ?") ";[3];":";[4];":";[5]
解説
タイトルを置きます。
10 ' ジコク シュトク
クエリを送ります。
20 ?"MJ GETS worldtimeapi.org/api/timezone/Asia/Tokyo"
以下の変数を初期化します。
-
W
:曜日 - 配列:日時
-
N
:名前モードか -
H
:名前の文字の文字コードの和 -
S
:文字列モードか -
P
:次に読み取った数値を格納する配列の要素 -
V
:読み取り中の数値 -
E
:数値を読み取り中か
30 W=0:LET[0],0,0,0,0,0,0:N=1:H=0:S=0:P=0:V=0:E=0
結果の最初の文字を時間無制限で待ち、読み取ります。
40 C=INKEY():IF C=0 GOTO 40 ELSE GOTO 70
結果の2文字目以降を読み取ります。0.5秒文字が来なかったら、読み取りを打ち切ります。
50 CLT
60 C=INKEY():IF TICK()>=30 GOTO 160 ELSE IF C=0 GOTO 60
読み取った文字が"
なら、文字列モードかどうかを切り替えます。
名前モードで文字列モードに入るなら、名前の文字の文字コードの和H
を初期化します。
(この"
の文字コードも足されるため、その分マイナスにしておきます)
70 IF C=#22 S=!S:IF S AND N H=-#22
名前モードの文字列モードなら、今の文字の文字コードを足します。
80 IF S AND N H=H+C
読み取った文字が:
であれば、データモードに切り替えます。
90 IF C=#3A:N=0
読み取った文字が,
であれば、名前モードに切り替えます。
100 IF C=#2C:N=1
読み取った文字が数字であれば、数値の読み取り状態を更新します。
数値を読み取った状態で数字以外の文字を読み取った時は、読み取った数値を記録する処理に行きます。
110 IF #30 <= C AND C <= #39 V=V*10+C-#30:E=1 ELSE IF E GOTO 130
読み取った文字が}
であれば、読み取りを終了します。
そうでなければ、次の文字の読み取りに行きます。
120 IF C=#7D GOTO 160 ELSE GOTO 50
読み取った名前が"datetime"
であれば、読み取った日時を表す数値を配列に格納します。
130 IF H=845 AND P<6 [P]=V:P=P+1
読み取った名前が"day_of_week"
であれば、読み取った数値を曜日を表す変数に格納します。
140 IF H=1149 W=V
数値の読み取り状態を初期化し、次の文字の読み取りに行きます。
150 V=0:E=0:GOTO 120
読み取った日時と曜日を出力します。
160 ?[0];"/";[1];"/";[2];" (";
170 IF W=0 ?"Sun";
180 IF W=1 ?"Mon";
190 IF W=2 ?"Tue";
200 IF W=3 ?"Wed";
210 IF W=4 ?"Thu";
220 IF W=5 ?"Fri";
230 IF W=6 ?"Sat";
240 ?") ";[3];":";[4];":";[5]
実験結果
MixJuiceを接続した状態でプログラムを実行し、しばらく待つと、
2021/12/14 (Tue) 3:41:5
のような形式で現在の日時が出力されました。
(取得を開始したタイミングの日時なので、出力されるタイミングからは遅れています)
MixJuice実機では、MJ SPW (送信間隔[ms])
コマンドでデータをIchigoJamに転送する速度を調整できるようです。
また、今回のプログラムでは、
75 ?CHR$(C);
という行を追加することで、受信したデータを出力して確認できるようになります。
IchigoJam webでは日時の取得に成功し、実行を開始してから約50秒後に日時が出力されました。
(現在の)バーチャルMixJuiceではMJ SPW
コマンドは効かないようで、データは欠けていました。
IchigoJam実機 (1.0.0) では、送信間隔を40msに設定すると、データが欠けて曜日の取得に失敗しました。
送信間隔を45msに設定すると、データが欠けずに日時の取得に成功し、
実行を開始してから約16秒で日時が出力されました。
IchigoJam実機 (1.3.1) では、送信間隔を15msに設定してもデータは欠けず、
実行を開始してから約7秒で日時が出力されました。
また、送信間隔を0msに設定しても最初の128バイト程度は受信できるようで、
データは欠けたものの日時の取得には成功し、実行を開始してから約3秒で日時が出力されました。
おわりに
Web APIを利用してIchigoJamからMixJuice経由で現在の日時を取得し、出力することができました。
ちなみに、執筆時においてMixJuiceのページもHTTPSには対応していないようです。
(接続はできるが証明書の名前が無効で、無視して続行すると404 Not Foundになりました)
IchigoJamはjig.jpの登録商標です。