随分昔に、Weathernewsの緊急地震速報プロトコルを解析されたコードを公開されてる方を見つけて、それ改造してIRCに流すbotを作ったのですが、プロトコルが変態すぎてなかなか安定しませんでした*1。今動くのかなこのコード*2。
今はOCN IPv6を契約するとIPv6マルチキャストで契約してなくてもOCN緊急地震速報っぽいパケットがだだ漏れしてくる時代に。Twitter bot走らせてる人もいたり。
参考:
要するにIPv6マルチキャストを受信すればいいのね。というわけで、調べてみました。
例によって、書いてある内容は未保証です。
OCN IPv6でつなぐ
取り敢えずOCN IPv6繋がないと始まりません。このへん参照した気がする。
pppデバイスが出来ればMulticast受信はできるので、IPv6取ってきたりする設定まではしてません。いいのかそれで。
取り敢えず受信する
PerlだとIO::Socket::Multicast6使えば受信出来ます。こんな感じかしら。先述のURIにもありますが、30秒ごとにpingパケットが飛んでくるので、40秒でタイムアウトするようにしました。
#!/usr/bin/env perl use strict; use warnings; use IO::Socket::Multicast6; use IO::Select; my $port = 8001; my $group = 'FF3E::8000:1000'; my $eew_sock = IO::Socket::Multicast6->new( Domain => AF_INET6 , LocalPort => $port , Proto => 'udp' , LocalAddr => $group ); $eew_sock->mcast_add($group); my $s = IO::Select->new(); $s->add($eew_sock); while (1) { my @socks = $s->can_read(40); if(scalar @socks == 0){ print "recv timeout"; exit; } foreach my $sock(@socks) { if($sock == $eew_sock){ my $data; $sock->recv($data,512); process_packet($data); } } } sub process_packet { my $data = shift; #受信しましたわ。 }
パケットを解析する
こうすると、「30秒ごとのpingパケット」「毎正時のテスト電文」「緊急地震速報電文」の三種類の電文が飛んできます。飛んでくるデータのhex dumpは文末にまとめました。三種類とか言いましたが、テスト電文も気象庁が送ってるので、実際は二種類ですね。しばらく上のコードを走らせる*3と色んなデータパケットがたまるので、それを眺めてどんな構造になっているのか猫よりバカな脳みそで考えてみたのが以下。
パケットの構造は先頭から「OCN緊急地震速報ヘッダ*4」「JMAソケットヘッダ+電文制御ヘッダ」「電文」の三種類になっています。
UDPなので、気象庁からNTTに飛んでくる電文のサイズが一定サイズを超えるとNTT側で複数のパケットに分割して送ってきます。この時、2つ目以降のパケットにはJMAソケットヘッダは付きません*5。
OCN緊急地震速報ヘッダ
気象庁から電文を受信したNTTがつけるヘッダです。このヘッダには以下の情報が入ってるようです。
- パケットのサイズ
- パケットの種類
- テストか、電文か
- 何回目の送信か
- 同じデータを三回送るよ、三回中何回目か、の二つ
- 何分割していくつめのブロックか
- 通し番号
- 日付+通し番号でユニークですね。NTTが受信した際に振ってると思われ。
飛んでくるデータはUDPで、気象庁からNTTに飛んでくる電文のサイズが一定サイズを超えると複数のパケットに分割して送ってきますが、その情報もヘッダに入ってます。
先頭30バイトをunpackすると、こんなところですか。
# $length パケットのサイズ(short) # $type パケットの種類(0x00 =>電文, 0xff => ping) # $ptotal 何回同じパケット送るのか # $pcount 何回目の送信か # $dtotal 全部でいくつに分割されてるのか # $dcount 幾つ目の分割パケットか # $name 通し番号(16文字固定で、pingのときはnull) my($length,$type,$ptotal,$pcount,$dtotal,$dcount,$name) = unpack('vx3CCCx2CxCxa16',$data);
サイズ実はshortやcharじゃなくてlongだったとかありそうだけど、そんなでかい電文来ないと信じて、食らったらその時考えることに。
で、このヘッダのサイズなんですが、基本的には0x30=48バイトです。が、分割された際の2つ目からは0x1e=30バイトに縮むようです。なんでやねん。ちなみに。30秒に一回のpingはこのヘッダだけ飛んできます。つまり48バイトのデータが来ます。
#実際にはprocess_packetを呼ぶ部分より前(whileの前あたりとか)に書かないとダメです my $last_dcount = ''; my $last_name = ''; my @message = (); sub process_packet { my $data = shift; my($length,$type,$ptotal,$pcount,$dtotal,$dcount,$name) = unpack('vx3CCCx2CxCxa16',$data); #pingなので何もしない。 return if $type == 255; #既に受信したことがあるパケットなら無視 return if($last_dcount eq $dcount && $last_name eq $name); @message = () if $last_name ne $name; $last_dcount = $dcount; $last_name = $name; #OCNEEWヘッダを取る $message[$dcount-1] = substr($data,30); #全部受信しきったので繋いで処理する。 if(count(@message) == $dtotal){ #何故か最初のパケットだけ18バイトおまけがつく process_eew(substr(join('',@message),18),$name); @message = (); } } sub count { my $c = 0; foreach my $i (@_){ $c++ if defined $i; } $c; } sub process_eew { my ($msg,$ocn_id) = @_; # $msgに電文、$ocn_idには電文のNTT的通し番号がはいる。 }
JMAソケットヘッダ+電文制御ヘッダ
気象業務支援センターが電文をNTT等へ送る際にJMAソケット付きTCP/IPなるものを使って送ってくるんですが、単にTCP/IPでヘッダを付けてデータを送るだけ*6。
まず、JMAソケットヘッダ。10バイトで先頭8バイトがデータサイズが8桁の数字文字で入ってて、空きはゼロフィルされてます。のこり2バイトはデータの種類。
my($size,$type) = unpack('A8A2',$msg); $size += 0;
こんな感じで。種類は「aN」で文字データだそうな。
次に、電文制御ヘッダ。あんまり意味は無さそう。ここに電文本体の文字コードが書いてあるんだけど、1バイト系という謎のcharsetとあとJISとシフトJISとバイナリという謎の種類しか定義されてない。
20バイトから最大60バイト変わり得るらしいけど、ヘッダ情報では20バイトだっていうのに実際には制御ヘッダ先頭から電文まで36バイトあるってどういうことよ。電文制御ヘッダ最初のバイトで上4bitが制御ヘッダバージョン、下4bitが制御ヘッダサイズの1/4が入ってます。
電文そのものは0x0aから始まるっぽいので、indexあたりで0x0aまで読み飛ばせばいいんじゃないかなーと。
sub split_header { my $msg = shift; $msg = substr($msg,10); my $size = (unpack('C',$msg) & 0xf) *4; $msg = substr($msg,$size); my $stx = index($msg,"\x0a"); return "" if($stx < 0); substr($msg,$stx); } sub process_eew { my ($msg,$ocn_id) = @_; $msg = split_header($msg); #$msgには生の電文が入ってるはずだ。 }
あそぶ
電文の処理は Earthquake::EEW::Decoder使って解析できます。
本番の電文は1秒もあかずに随時新情報が降ってくるし、あんまりゆっくりしてると間に合いません。IRCに流すとかいいんじゃないでしょうかね。
ちなみに、ここで書かれているサンプルコードは複数のEEWが同時に飛んでくることを想定していないので、実際にはconcatするバッファをOCNのつけてくれるIDあたりで区分しないと正常にパケットを生成出来ないことがありますこれ、この前の大誤報の時に気付いたんですがまだサンプルコードでは修正できてません(22 Aug 2013追記)。
パケットの例
文字コードはShift_JISで飛んできます(文中で解説)。
30秒ごとのping
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 30 00 00 00 00 FF 03 03-00 00 01 00 01 00 00 00 0............... 000010 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
毎正時のテスト電文
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 E1 00 00 00 00 00 03 03-00 00 01 00 01 00 32 30 ..............20 000010 31 33 30 31 30 36 30 30-30 30 30 30 32 33 00 00 13010600000023.. 000020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000030 30 30 30 30 30 31 36 37-61 4E 35 04 14 71 00 20 00000167aN5..q. 000040 00 00 00 00 AE 6A 08 00-00 00 00 00 00 00 00 00 ....ョj.......... 000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 0A C5 ...............ナ 000060 B3 B7 D4 BD C4 C3 BD C4-39 31 20 B7 BC D6 B3 0A ウキヤストテスト91 キシヨウ. 000070 02 0A 33 38 20 30 33 20-32 30 20 31 33 30 31 30 ..38 03 20 13010 000080 36 31 30 30 30 30 30 20-43 31 31 20 39 39 39 39 6100000 C11 9999 000090 0A 0A 8B D9 8B 7D 92 6E-90 6B 91 AC 95 F1 82 CC ..緊急地震速報の 0000A0 83 65 83 58 83 67 93 64-95 B6 82 C5 82 B7 0A 82 テスト電文です.2 0000B0 51 82 4F 82 50 82 52 94-4E 82 4F 82 50 8C 8E 82 013年01月0 0000C0 4F 82 55 93 FA 82 50 82-4F 8E 9E 82 4F 82 4F 95 6日10時00分 0000D0 AA 82 4F 82 4F 95 62 0A-8B 43 8F DB 92 A1 3D 0A 00秒.気象庁=. 0000E0 03 .
緊急地震速報本文
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 FC 00 00 00 00 00 03 01-00 00 01 00 01 00 32 30 ..............20 000010 31 33 30 31 31 31 30 30-30 30 30 30 30 39 00 00 13011100000009.. 000020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000030 30 30 30 30 30 31 39 34-61 4E 35 04 16 66 00 10 00000194aN5..f.. 000040 10 00 00 00 9C 85 08 00-00 00 00 00 00 00 00 00 ....怛.......... 000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 0A C5 ...............ナ 000060 B3 B7 D4 BD C4 33 20 B7-BC D6 B3 0A 02 0A 33 37 ウキヤスト3 キシヨウ...37 000070 20 30 33 20 30 30 20 31-33 30 31 31 31 30 36 32 03 00 130111062 000080 32 32 36 20 43 31 31 0A-31 33 30 31 31 31 30 36 226 C11.13011106 000090 32 32 30 38 0A 4E 44 32-30 31 33 30 31 31 31 30 2208.ND201301110 0000A0 36 32 32 31 37 20 4E 43-4E 30 30 31 20 4A 44 2F 62217 NCN001 JD/ 0000B0 2F 2F 2F 2F 2F 2F 2F 2F-2F 2F 2F 2F 2F 20 4A 4E ///////////// JN 0000C0 2F 2F 2F 0A 37 39 33 20-4E 32 38 35 20 45 31 32 ///.793 N285 E12 0000D0 39 33 20 30 35 30 20 34-35 20 30 33 20 52 4B 34 93 050 45 03 RK4 0000E0 34 35 31 34 20 52 54 31-30 2F 2F 2F 20 52 43 2F 4514 RT10/// RC/ 0000F0 2F 2F 2F 2F 0A 39 39 39-39 3D 0A 03 ////.9999=..
分割された電文の例
1/2
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 F4 01 00 00 00 00 03 01-00 00 02 00 01 00 32 30 ..............20 000010 31 33 30 32 30 32 30 30-30 30 30 30 36 35 00 00 13020200000065.. 000020 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ 000030 30 30 30 30 30 36 39 38-61 4E 35 04 26 15 00 10 00000698aN5.&... 000040 10 00 00 00 8C D6 08 00-00 00 00 00 00 00 00 00 ....誇.......... 000050 00 00 00 00 00 00 00 00-00 00 00 00 00 00 0A C5 ...............ナ 000060 B3 B7 D4 BD C4 33 20 B7-BC D6 B3 0A 02 0A 33 37 ウキヤスト3 キシヨウ...37 000070 20 30 33 20 30 30 20 31-33 30 32 30 32 32 33 31 03 00 130202231 000080 38 32 30 20 43 31 31 0A-31 33 30 32 30 32 32 33 820 C11.13020223 000090 31 37 33 34 0A 4E 44 32-30 31 33 30 32 30 32 32 1734.ND201302022 0000A0 33 31 37 35 30 20 4E 43-4E 30 30 38 20 4A 44 2F 31750 NCN008 JD/ 0000B0 2F 2F 2F 2F 2F 2F 2F 2F-2F 2F 2F 2F 2F 20 4A 4E ///////////// JN 0000C0 2F 2F 2F 0A 31 35 37 20-4E 34 32 36 20 45 31 34 ///.157 N426 E14 0000D0 33 32 20 31 31 30 20 36-34 20 35 2D 20 52 4B 36 32 110 64 5- RK6 0000E0 36 35 35 34 20 52 54 30-31 2F 2F 2F 20 52 43 30 6554 RT01/// RC0 0000F0 2F 2F 2F 2F 0A 45 42 49-20 31 35 36 20 53 35 2D ////.EBI 156 S5- 000100 35 2D 20 2F 2F 2F 2F 2F-2F 20 31 31 20 31 35 37 5- ////// 11 157 000110 20 53 30 34 30 34 20 2F-2F 2F 2F 2F 2F 20 31 31 S0404 ////// 11 000120 20 31 35 32 20 53 30 34-30 34 20 2F 2F 2F 2F 2F 152 S0404 ///// 000130 2F 20 31 31 0A 31 35 35-20 53 30 34 30 34 20 2F / 11.155 S0404 / 000140 2F 2F 2F 2F 2F 20 31 31-20 31 35 31 20 53 30 34 ///// 11 151 S04 000150 30 34 20 2F 2F 2F 2F 2F-2F 20 31 31 20 31 35 30 04 ////// 11 150 000160 20 53 30 34 30 34 20 2F-2F 2F 2F 2F 2F 20 31 31 S0404 ////// 11 000170 0A 31 32 37 20 53 30 34-30 34 20 2F 2F 2F 2F 2F .127 S0404 ///// 000180 2F 20 31 31 20 31 34 36-20 53 30 34 30 34 20 2F / 11 146 S0404 / 000190 2F 2F 2F 2F 2F 20 31 31-20 31 36 31 20 53 30 34 ///// 11 161 S04 0001A0 30 34 20 2F 2F 2F 2F 2F-2F 20 31 31 0A 31 34 31 04 ////// 11.141 0001B0 20 53 30 34 30 34 20 2F-2F 2F 2F 2F 2F 20 30 31 S0404 ////// 01 0001C0 20 31 32 32 20 53 30 34-30 34 20 2F 2F 2F 2F 2F 122 S0404 ///// 0001D0 2F 20 31 31 20 31 32 31-20 53 30 34 30 34 20 2F / 11 121 S0404 / 0001E0 2F 2F 2F 2F 2F 20 30 31-0A 31 36 30 20 53 30 34 ///// 01.160 S04 0001F0 30 34 20 2F 04 /
2/2
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 1E 01 00 00 00 00 03 01-00 00 02 00 02 00 32 30 ..............20 000010 31 33 30 32 30 32 30 30-30 30 30 30 36 35 2F 2F 13020200000065// 000020 2F 2F 2F 20 30 31 20 31-30 31 20 53 30 34 30 34 /// 01 101 S0404 000030 20 2F 2F 2F 2F 2F 2F 20-31 31 20 31 30 32 20 53 ////// 11 102 S 000040 30 34 30 34 20 2F 2F 2F-2F 2F 2F 20 31 31 0A 31 0404 ////// 11.1 000050 30 30 20 53 30 34 30 34-20 2F 2F 2F 2F 2F 2F 20 00 S0404 ////// 000060 31 31 20 31 36 36 20 53-30 34 30 34 20 2F 2F 2F 11 166 S0404 /// 000070 2F 2F 2F 20 30 31 20 31-34 30 20 53 30 34 30 34 /// 01 140 S0404 000080 20 32 33 31 38 32 31 20-30 30 0A 31 34 35 20 53 231821 00.145 S 000090 30 34 30 34 20 32 33 31-38 32 32 20 31 30 20 31 0404 231822 10 1 0000A0 36 37 20 53 30 34 30 34-20 32 33 31 38 32 34 20 67 S0404 231824 0000B0 30 30 20 31 30 36 20 53-30 34 30 34 20 32 33 31 00 106 S0404 231 0000C0 38 32 36 20 31 30 0A 31-36 35 20 53 30 34 30 34 826 10.165 S0404 0000D0 20 32 33 31 38 32 37 20-30 30 20 32 30 33 20 53 231827 00 203 S 0000E0 30 34 30 34 20 32 33 31-38 33 30 20 31 30 20 31 0404 231830 10 1 0000F0 32 36 20 53 30 34 30 33-20 2F 2F 2F 2F 2F 2F 20 26 S0403 ////// 000100 30 31 0A 31 32 30 20 53-30 34 30 33 20 2F 2F 2F 01.120 S0403 /// 000110 2F 2F 2F 20 30 31 0A 39-39 39 39 3D 0A 03 /// 01.9999=..
(おまけ)WeathernewのEEW
+0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +A +B +C +D +E +F 0123456789ABCDEF 000000 01 0A 54 4B 43 43 20 32-36 33 34 36 20 20 41 44 ..TKCC 26346 AD 000010 54 4B 20 31 32 32 31 35-39 31 34 0A 0A C5 B3 B7 TK 12215914..ナウキ 000020 D4 BD C4 33 20 B7 BC D6-B3 0A 02 0A 02 0A 33 37 ヤスト3 キシヨウ.....37 000030 20 30 33 20 30 30 20 31-31 30 33 31 33 30 36 35 03 00 110313065 000040 39 31 34 20 43 31 31 0A-31 31 30 33 31 33 30 36 914 C11.11031306 000050 35 38 31 35 0A 4E 44 32-30 31 31 30 33 31 33 30 5815.ND201103130 000060 36 35 38 33 31 20 4E 43-4E 30 30 33 20 4A 44 2F 65831 NCN003 JD/ 000070 2F 2F 2F 2F 2F 2F 2F 2F-2F 2F 2F 2F 2F 20 4A 4E ///////////// JN 000080 2F 2F 2F 0A 32 38 36 20-4E 33 39 30 20 45 31 34 ///.286 N390 E14 000090 32 34 20 30 31 30 20 34-37 20 30 33 20 52 4B 36 24 010 47 03 RK6 0000A0 36 32 30 34 20 52 54 31-30 2F 2F 2F 20 52 43 30 6204 RT10/// RC0 0000B0 2F 2F 2F 2F 0A 39 39 39-39 3D 0A 03 ////.9999=..