Quantcast
Channel: C#タグが付けられた新着記事 - Qiita
Viewing all articles
Browse latest Browse all 9691

緊急地震速報の生電文を受信しよう

$
0
0

日本は地震が多いですね。その割には情報を入手する手段が少ない気がします。
テレビでは震度5弱以上予想時のみ提供されますが、震度4以下の場合には事後の提供のみです。
提供してもらえないなら自分で入手しましょう。
(毎回 Qiita 記事の頭の文章が適当になってしまう)

なお、記事の最後に わざわざ自分で電文を受信して解析する必要がない方法も紹介します。

免責事項

筆者は現在この記事で紹介する方法は 使用していません。今後使えなくなっても責任は負いかねます。
参考にする場合は自己責任でお願いします。

環境

  • 安定したネットワーク環境 (1Mbps 以下でも接続を維持できればOK)
  • C# 開発環境
  • Windows 10
  • WeatherNews.jp 有料会員

流れをざっくりと説明

気象庁 -> WeatherNews.jp -> 利用者

WeatherNews.jp -> 利用者 の間は TCPSocket を使用します。

プログラム

簡単にサンプルで作成したプログラムを載せます。自由に改変や修正を加えてください。
途中の正規表現は即席なのでもっと良いパターンがあればコメントでお願いします。
また、 WNI が緊急地震速報を送信するサーバーの IP アドレスは http://lst10s-sp.wni.co.jp/server_list.txtに記述されていますが、どれでもOKです。
選択するサーバーによっては遅延がかなり酷く、平気で1分以上遅れたりする場合があります。
なのでサーバーガチャで勝利してください。
「ここ速かったよ!」とかありましたらコメントでお願いします。(使っていないけど)

あ、死活管理は適宜実装してください。

WniClient.cs
publicclassWniClient:IDisposable{privateSocket_socket;privateconstintBufferSize=1024;privatereadonlybyte[]_buffer=newbyte[BufferSize];publicasyncTaskConnectAsync(stringmailAddress,stringpassWord){// パスワードを MD5 に変換varpassWordByte=MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(passWord));// MD5 に変換すると byte[] になるため string に変換varpassWordStr=BitConverter.ToString(passWordByte).ToLower().Replace("-","");_socket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);_socket.Connect(newIPEndPoint(IPAddress.Parse(awaitGetServerIpAsync()),80));// 認証情報を送信_socket.Send(newUTF8Encoding().GetBytes($"GET /login HTTP/1.1\r\nX-WNI-Account: {mailAddress}\r\nX-WNI-Password: {passWordStr}\r\n\r\n"));// データ受信時にイベント発火_socket.BeginReceive(_buffer,0,BufferSize,SocketFlags.None,ReceiveCallback,_socket);}privatestaticasyncTask<string>GetServerIpAsync(){usingvarc=newHttpClient();varservers=(awaitc.GetStringAsync("http://lst10s-sp.wni.co.jp/server_list.txt").ConfigureAwait(false)).Split('\n');varrdm=newRandom();varserver=servers[rdm.Next(0,servers.Length-1)];returnserver.Split(':')[0];}publicvoidDisconnect()=>_socket.Disconnect(false);publicvoidDispose()=>_socket.Close();privatevoidReceiveCallback(IAsyncResultasyncResult){varsocket=(Socket)asyncResult.AsyncState;if(socket==null)return;intbyteSize;try{byteSize=socket.EndReceive(asyncResult);}catch(Exceptionex){OnException?.Invoke(ex);return;}if(byteSize<1)return;varres=Encoding.UTF8.GetString(_buffer,0,byteSize);if(res.Contains("X-WNI-ID: Data")){res=newstring(res.Replace("\n"," ").Replace("\r"," ").Replace("  "," ").Where(x=>!char.IsControl(x)).ToArray());varmc=newRegex("3([0-9/]{1}) ([0-9/]{2}) ([0-9/]{2}) ([0-9/]{12}) C([0-9/]{2}) ([0-9/]{12}) ND([0-9/]{14}) NCN([0-9A-Z/]{3}) JD([0-9/]{14}) JN([0-9/]{3}) ([0-9/]{3}) ([N0-9/]{4}) ([E0-9/]{5}) ([0-9/]{3}) ([0-9/]{2}) ([0-9/+-]{2}) RK([0-9/]{5}) RT([0-9/]{5}) RC([0-9/]{5}) (.*?)9999=",RegexOptions.None).Matches(res);foreach(Matchminmc)OnReceiveData?.Invoke(m.Value.Trim());}socket.BeginReceive(_buffer,0,_buffer.Length,SocketFlags.None,ReceiveCallback,socket);}publicdelegatevoidReceiveEventHandler(stringreceiveData);publiceventReceiveEventHandlerOnReceiveData;publicdelegatevoidOnExceptionEventHandler(Exceptionexception);publiceventOnExceptionEventHandlerOnException;}
Main.cs
privatestaticasyncTaskMain(){usingvarclient=newWniClient();// 受信したら OnReceiveData が発火し、電文が渡されるclient.OnReceiveData+=Console.WriteLine;awaitclient.ConnectAsync("[メールアドレス]","[パスワード]");Console.ReadLine();client.Disconnect();}

まとめ

The Last 10-Secondで使用されている緊急地震速報配信サーバーを利用する方法を紹介しました。
とにかく遅延が酷いです。調子がいい時は3秒遅れ程度や遅延無しで配信されます。
速いサーバーを見つけた方は共有しましょう。

楽な方法

手前味噌ですが https://api.iedred7584.com/eew/を使ってください。(宣伝)


Viewing all articles
Browse latest Browse all 9691

Trending Articles