GPSシールドを使ってみちびき(QZSS)の災害・危機管理通報サービス(DC Report・DCX)を受信してみた。
Stratum 1 NTPサーバーに使用したESPr® Developer用GPSシールド SAM-M8Q搭載が、みちびき(準天頂衛星システム)の災害・危機管理通報サービス(DC Report)とその拡張版(DCX)を受信できることに気づきました。今年4月からはJアラート(ミサイル発射情報等)やLアラート(避難情報)の配信が開始されているとのことで、早速受信してみることにしました。
この記事では災害・危機管理通報サービス(DC Report)とその拡張版(DCX)を受信する受信機の実装の詳細について解説します。
みちびきの信号を受信している様子。。
みちびきと災害・危機管理通報サービス
みちびきは日本が運用する準天頂衛星システム(QZSS)で、日本周辺地域での高精度な位置情報サービスを提供します。日本の上空に長時間とどまる衛星で、GPSを補強する信号を出して安定した測位サービスを提供します。
災害・危機管理通報サービスはみちびきが提供するサービスの一つで、地震、津波、火山噴火、気象警報などの防災情報を配信します。この中には、以下の2種類があります。
- DC Report(基本サービス):防災気象情報に基づいた情報を配信。
- DCX(拡張サービス):Jアラート(ミサイル発射情報等)やLアラート(避難情報)、アジア太平洋地域向けの災害情報を配信。
次の図は災害・危機管理通報サービスの概要を表しています。防災関連機関から発信された情報は地上管制局からみちびきに送られ、みちびきから日本全国・アジア地域に配信されます。
みちびきウェブサイトより引用
使用機材とその役割
使用する機材はStratum 1 NTPサーバーをそのまま利用します。
-
ESPr® Developer用GPSシールド SAM-M8Q搭載
- みちびきのL1S信号を受信
- UBX-RXM-SFRBXメッセージを出力
-
ESPr® Developer C6
- GPSシールドのL1S信号の受信設定
- DC ReportとDCXをデコードする
- デコード結果を出力する
ソースコード
GPSシールドの制御にはSparkFun_u-blox_GNSS_Arduino_Libraryを使用しています。DC ReportのデコードにはSPRESENSE向けのQZQSMライブラリを1箇所修正して使用しています。
@@ -4481,7 +4481,7 @@ int QZQSM::get_val(int startbit, int bitwidth)
void QZQSM::utc2jst(int& month, int& day, int& hour, int& minute)
{
- uint32_t sec;
+ time_t sec;
struct tm tm;
DCXのデコード用のライブラリは見つからなかったので、DCXの仕様書(IS-QZSS-DCX-002)を参考に自作しました。少々手抜き実装ですがこちらで公開しています。
SparkFun_u-blox_GNSS_Arduino_LibraryとQZQSMはライブラリマネージャからインストールしてください。DCXのライブラリはgithubからZIPをダウンロードしてArduinoのライブラリフォルダにコピーしてください。
DCXのライブラリもArduinoライブラリマネージャからインストールできるようになりました!QZSSDCXで検索するとでてきます。
ESPr® Developer C6のビルド手順は商品ページに記載しています。そちらも参照してください。ESPr® Developer 32やESPr® Developer S3でも動作すると思います、が、やっぱり動作確認はしていません(ごめんなさい!)。
みちびきのL1S信号を受信する
GPSシールドのL1S信号の受信設定
DC ReportとDCXはL1S信号で送信されます。GPSシールドに搭載されているSAM-M8QはみちびきのL1S信号を受信できるように作られていますが、その機能は電源オン直後はオフになっています。まずはSAM-M8QがL1S信号を受信するように、UBX-CFG-GNSSメッセージを送ってQZSSのL1S信号を有効にします。UBX-CFG-GNSSメッセージの詳細はu-bloxのドキュメントを参照してください。
// QZSSのL1S信号を受信するよう設定する
bool enableQZSSL1S(void) {
uint8_t customPayload[MAX_PAYLOAD_SIZE];
ubxPacket customCfg = { 0, 0, 0, 0, 0, customPayload, 0, 0, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED, SFE_UBLOX_PACKET_VALIDITY_NOT_DEFINED };
customCfg.cls = UBX_CLASS_CFG;
customCfg.id = UBX_CFG_GNSS;
customCfg.len = 0;
customCfg.startingSpot = 0;
if (myGNSS.sendCommand(&customCfg) != SFE_UBLOX_STATUS_DATA_RECEIVED)
return (false);
int numConfigBlocks = customPayload[3];
for (int block = 0; block < numConfigBlocks; block++) {
if (customPayload[(block * 8) + 4] == (uint8_t)SFE_UBLOX_GNSS_ID_QZSS) {
customPayload[(block * 8) + 8] |= 0x01; // set enable bit
customPayload[(block * 8) + 8 + 2] |= 0x05; // set 0x01 QZSS L1C/A 0x04 = QZSS L1S
}
}
return (myGNSS.sendCommand(&customCfg) == SFE_UBLOX_STATUS_DATA_SENT);
}
UBX-RXM-SFRBXメッセージを出力
DC ReportとDCXはSAM-M8QからUBX-RXM-SFRBXメッセージとして出力されます。GNSSライブラリのsetAutoRXMSFRBXcallbackPtr
関数を使ってコールバック関数を登録するとUBX-RXM-SFRBXメッセージの出力が有効になり、UBX-RXM-SFRBXメッセージが届くたびにコールバック関数が呼ばれるようになります。コールバック関数の引数dataにUBX-RXM-SFRBXメッセージの内容が格納されています。
void newSFRBX(UBX_RXM_SFRBX_data_t *data) {
#if DBG_PRINT_SFRBX
Serial.print("SFRBX gnssId: ");
Serial.print(data->gnssId);
Serial.print(" svId: ");
Serial.print(data->svId);
Serial.print(" freqId: ");
Serial.print(data->freqId);
Serial.print(" numWords: ");
Serial.print(data->numWords);
Serial.print(" version: ");
Serial.print(data->version);
Serial.print(" ");
for (int i = 0; i < data->numWords; i++) {
Serial.print(dwrd_to_str(data->dwrd[i]));
}
Serial.println();
#endif
}
UBX_RXM_SFRBX_data_t構造体のメンバ変数gnssId
はGNSSの種類を表しています。0はGPS、5はQZSS(みちびき)、6はGLONASSなどです。衛星から受信したデータはdwrd
に格納されていて、その個数はnumWords
で表されます。以下は実際に受信したデータdwrd
を出力した内容です。
SFRBX gnssId: 0 svId: 26 freqId: 0 numWords: 10 version: 2 22C126301D6C099012640029891F912A993D01AC0BDCC10426410392881669AB003FE2AA805AD170
SFRBX gnssId: 0 svId: 10 freqId: 0 numWords: 10 version: 2 22C126301D6C099012640029891F912A993D01AC0BDCC10426410172AF566988003FDF76B906A2E7
SFRBX gnssId: 6 svId: 2 freqId: 3 numWords: 4 version: 2 4F05292CAF34C08A87C0C80009B30001
SFRBX gnssId: 6 svId: 21 freqId: 11 numWords: 4 version: 2 4F05292CAF34C08A87C0C80009B30001
SFRBX gnssId: 5 svId: 4 freqId: 0 numWords: 10 version: 2 22C0AA819D6C01F3126841D32000002A800000298000002980003EBB2C56316A803FFFDC00B4AB68
SFRBX gnssId: 5 svId: 2 freqId: 0 numWords: 10 version: 2 22C0AA819D6C01F3126841D32000002A800000298000002980000122AC563143003FFFF58002164F
SFRBX gnssId: 5 svId: 4 freqId: 0 numWords: 8 version: 2 C6CA8001FD8002DF5A043FE5FCD04105000EFE4000000000000000002808DB94
SFRBX gnssId: 5 svId: 2 freqId: 0 numWords: 8 version: 2 C6CA8001FD8002DF5A043FE5FCD04105000EFE4000000000000000002808DB94
DC ReportとDCXをデコードする
UBX_RXM_SFRBXメッセージのコールバック関数は、みちびき以外の衛星の信号でも呼び出されます。今回注目するのはみちびきの信号なのでgnssId
が5(QZSS)である場合にのみデコードを行います。
またdwrd
は32ビットのリトルエンディアン形式になっているため、バイト順を変換しつつl1s_msg_buf
にコピーします。
みちびきから受信したデータl1s_msg_buf
は250ビットのフォーマットで構成されています(下図)。先頭に8ビットのプリアンブル(PAB)、6ビットのメッセージタイプ(MT)が格納されています。プリアンブル(PAB)は0x53・0x9A・0xC6いずれかです。PABとMTの値を確認してデコードを処理を振り分けます。MT43がDC Report、MT44がDCXです。
IS-QZSS-L1S-007 - 4.1.1.1. Overviewより抜粋
void newSFRBX(UBX_RXM_SFRBX_data_t *data) {
// QZSS L1Sメッセージ解析
if (data->gnssId == 5) {
// SFRBXのdwrdはリトルエンディアンなので入れ替える
for (int i = 0; i < min(int(data->numWords), 8); i++) {
l1s_msg_buf[(i << 2) + 0] = (data->dwrd[i] >> 24) & 0xff;
l1s_msg_buf[(i << 2) + 1] = (data->dwrd[i] >> 16) & 0xff;
l1s_msg_buf[(i << 2) + 2] = (data->dwrd[i] >> 8) & 0xff;
l1s_msg_buf[(i << 2) + 3] = (data->dwrd[i]) & 0xff;
}
byte pab = l1s_msg_buf[0];
byte mt = l1s_msg_buf[1] >> 2;
if (pab == 0x53 || pab == 0x9A || pab == 0xC6) {
// 災害・危機管理通報サービス(DC Report)のメッセージ内容を表示
if (mt == 43) {
dc_report.Decode(l1s_msg_buf);
Serial.println(dc_report.GetReport());
}
// 災害・危機管理通報サービス(拡張)(DCX)のメッセージ内容を表示
else if (mt == 44) {
dcx_decoder.decode(l1s_msg_buf);
dcx_decoder.printSummary(Serial, dcx_decoder.r);
}
}
}
}
MT43の時、QZQSMライブラリを使ってデコードし、結果をSerial
に出力します。
MT44の時、QZSSDCXライブラリを使ってデコードし、結果をSerial
に出力します。
DCXフォーマット
折角なのでちょっとだけDCXのメッセージフォーマットについて触れておきます。先頭のPAB・MTは先に説明したとおりでそのあとSatellite Designation (SD)が10ビット、Common Alert Message Format (CAMF)が122ビット、Extended Messageが74ビットと続きます。
詳細は省きますがCommon Alert Message Format (CAMF)やExtended Messageには次のようにパラメータがビット単位でギチギチに詰め込まれています。
パラメータAによってパラメータBの意味が変わるといった仕様があり理解するのに苦労しました。またパラメータに対応する文字列の種類が多く、ライブラリの実装にかなり苦労しました…
動作確認
製作した受信機を空の見える場所に設置してシリアルモニターを開くとつぎのように衛星の数とその種類が表示されます。QZSSが表示されていない状態だとDC ReportもDCXも表示されません。QZSSが1以上になるまで待つ必要があります。
Satellites: 26 GPS: 10 QZSS: 3 GLONASS: 10
Satellites: 26 GPS: 10 QZSS: 3 GLONASS: 10
Satellites: 26 GPS: 10 QZSS: 3 GLONASS: 10
QZSSが見つかるとDC Reportが4秒周期で表示されると思います。通常、Jアラート(ミサイル発射情報等)やLアラート(避難情報)などのDCXメッセージは配信されておらず、空メッセージが表示されます。
43 DC Report
災危通報(海上)(発表)
発表時刻:12月5日11時35分
海上着氷警報:サハリン東方海上
海上着氷警報:サハリン西方海上
海上着氷警報:網走沖
海上着氷警報:宗谷海峡
海上着氷警報:北海道西方海上
海上着氷警報:沿海州南部沖
海上風警報:宗谷海峡
海上風警報:北海道西方海上
Satellites: 23 GPS: 10 QZSS: 1 GLONASS: 9
Satellites: 23 GPS: 10 QZSS: 1 GLONASS: 9
44 DCX message
### 空メッセージ ###
試験用データ配信
DCXが配信されることはまれなので、月に2回実施されるDCX試験用データの定期配信を利用して、実際のDCXデータを用いたテストを行いました(2024年12月3日)。デコードした内容を一部紹介します。試験データの詳細は、上記URLから確認してください。
### Lアラート(テスト) ###
国/地域名: 日本
情報提供: 一般財団法人マルチメディア振興センター(FMMC)
災害カテゴリ種別: 安全性 - 有害物質の事故
重大度: 中程度 - 生命または財産への可能性のある脅威
災害発生週: 今週
災害発生日時: 火曜日 13:45 UTC
災害の継続時間: 12時間 <= 継続時間 < 24時間
避難行動: (指示なし)
楕円情報
中心緯度: 35.688
中心経度: 139.757
長軸半径: 3.269 km
短軸半径: 2.418 km
方位角: 50.625
対象地域: 東京都千代田区
## Jアラート(テスト) ###
国/地域名: 日本
情報提供: 消防庁(FDMA)
災害カテゴリ種別: 安全性 - 安全性警告
重大度: 極端 - 生命または財産への非常に重大な脅威
災害発生週: 今週
災害発生日時: 火曜日 14:00 UTC
災害の継続時間: 不明
避難行動: (指示なし)
対象地域: 沖縄県 鹿児島県 宮崎県 大分県 熊本県 長崎県 佐賀県 福岡県 高知県 愛媛県 香川県 徳島県 山口県 広島県 岡山県 島根県 鳥取県 和歌山県 奈良県 兵庫県 大阪府 京都府 滋賀県 三重県 愛知県 静岡県 岐阜県 長野県 山梨県 福井県 石川県 富山県 新潟県 神奈川県 東京都 千葉県 埼玉県 群馬県 栃木県 茨城県 福島県 山形県 秋田県 宮城県 岩手県 青森県 北海道
以上です。