にゃみかんてっくろぐ

猫か百合を見守る壁になりたい

Raspberry PiでNHKラジオ第一の緊急地震速報を検出する

P2P地震情報では,NHKラジオ第一の放送から緊急地震速報の発表を検出しています. 今回,その検出をPCではなくRaspberry Piで行うように変更しました.そのときの記録です.

前提: 自動音声による放送

NHKラジオ第一では,緊急地震速報(警報)が発表されると,通常の放送を中断して緊急地震速報の放送が入ります.

放送の内容は下記の通り.事前に収録した音声で自動的に放送されているようです.

(チャイム音)
緊急地震速報です.(震源名)で地震.次の地域は,強い揺れに警戒してください.(地域名)

緊急地震速報です(以下繰り返しの後,該当地域の方々への注意喚起など)

「発表されたこと」だけを検出する場合,冒頭の音声をパターンマッチするだけで実現が出来ます.これをやります.

材料

Raspberry Piによる録音

アダプタを接続するだけです.

$ lsusb
Bus 001 Device 002: ID 0d8c:013c C-Media Electronics, Inc. CM108 Audio Controller
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

$ arecord -l
**** ハードウェアデバイス CAPTURE のリスト ****
カード 1: Device [USB PnP Sound Device], デバイス 0: USB Audio [USB Audio]
  サブデバイス: 1/1
  サブデバイス #0: subdevice #0

$ arecord -L
(省略)
plughw:CARD=Device,DEV=0
    USB PnP Sound Device, USB Audio
    Hardware device with all software conversions

$ arecord -D plughw:1,0 test.wav
録音中 WAVE 'test.wav' : Unsigned 8 bit, レート 8000 Hz, モノラル

Python3による音声のパターンマッチ

GitHubにソース公開しています.見せるように作っていないのでかなり汚いです.

github.com

技術的なポイントはこのへん.

  • 音声波形そのままではなく,FFT変換した周波数スペクトルでパターンマッチング
  • FFT変換はNumPyライブラリで実施(お手軽)
  • 精度(しきい値)は人力で調整.といっても大した手間ではない

緊急地震速報の検出のためのポイントはこのへん.

  • 検出負荷を下げるために正解データは短く
    • チャイム音は2回繰り返すうち1回分
    • 自動音声は冒頭の「緊急地」のみ
  • 必ずチャイム音と音声をセットで検出(過去,チャイム音を用いた啓蒙放送等があったため)

※正解データは著作権の関係で公開できません.

実行

arecordの標準出力をPythonスクリプトの標準入力に食わせます.

$ arecord -D plughw:1,0 -t raw | python3 fft_analyze.py

f:id:no_clock:20190203233109p:plain

過去の放送音声を流してみたところ,正しく認識されました.CPU使用率は約20%,良い感じです.

(失敗)pyaudioで録音&パターンマッチ

そもそもpyaudioライブラリを使えば,Pythonで完結させることが出来ます.しかし,失敗しました.

f:id:no_clock:20190203235500p:plain

Input overflowedの表示の通り,録音データをリアルタイムに処理出来ていません.

arecordでは8000Hz, 1ch, 8bitという低いデータレートで録音していましたが,これはarecord内部でリサンプリングされたものでした.一方,pyaudioにはそうした機能はありません.デバイスが対応する44100Hz, 1ch, 16bitという高いデータレートで録音するしかなく,リアルタイムに扱うには厳しい量でした.

その結果,arecordの標準出力から食わせる,という方法に落ち着きました.

参考

P2P地震情報14周年: 個人サービスを長く続けるための技術

個人開発 #2 Advent Calendar 2018 8日目の記事です.

せっかく作った個人サービスを長く続けていくための技術についてお話ししようと思います.

3行でまとめると

  • Dogfooding … 使い続ける
  • Maintenance-free … とにかく省力化する
  • Write Code Every Day … 小さい変更を積み重ねる

P2P地震情報

P2P地震情報というサービスを開発・運用しています.

気象庁地震情報やユーザ同士の「揺れた!」という地震感知情報を,P2Pネットワークによって共有するサービスです.

現在のサービス構成は下記の通りです.本体はP2Pですが,サーバの役割は多岐にわたります.なお,耐災害性の観点から,一部機能は有志の方々のご協力により全国数ヶ所に分散しています.

祝14周年🎉 (なお理想と現実は異なる)

2004年12月に公開し,今年で丸14年です.思った以上に長く続いています.

残念ながら,やりたいことは十分に実現出来ていません.GUIアプリケーションは未だにVB6製で,なかなかのレガシーです.*1

それでも,14年間続けることができました.なんだかんだで良かったと思っています.どうして続けられたのかというと,これから話す3つの技術が大事なのではと感じています.

サービスを続けていくための技術

Dogfooding: 使い続ける

サービスを続けるには,モチベーションを維持し続けることが重要です.

その最も簡単な方法が,自分自身がモチベーションの源泉となるように,サービスを自ら使い続けることだと感じています.

昔,LaTeXのオンラインコンパイラやPDFファイルの画像化といったサービスを公開していましたが,自分が使わなくなった途端にメンテナンスしなくなり,外部からアクセスは続いていたものの公開を終了したことがあります.

Maintenance-free: とにかく省力化する

モチベーション(と時間)を無駄にしないために,維持するためにかかるコストを最小限に抑えます.

色々ありますが,一番やってよかったのはひとりSlackでした.

サービスに関わるあらゆるメール,通知,実行ログをSlackに集約し,「とりあえずSlackの新着を見ればよい」という状態に辿り着きました.メールの未読消化と比べて圧倒的な省力化です.

f:id:no_clock:20181206231200p:plain

f:id:no_clock:20181206231214p:plain

Write Code Every Day: 小さい変更を積み重ねる

学生から社会人になり,「まとまった時間が取れない」「しかし週末に一気にやる気持ちにもなれない」という矛盾する悩みを抱えていました.数年間悩み続けた末,John Resigの記事に出会いました.

John Resig - Write Code Every Day (日本語訳参考: 毎日コードを書くこと - snowlongの日記

学生時代の開発スタイルではいけないと気付かされました.

それから,100日以上毎日コードを書き続けました.1~2行しか書かない日もありましたが,それでも効果は絶大でした.

f:id:no_clock:20181206231231p:plain

C#版のGUIアプリケーションも徐々に実装が進んでいて,一部機能は既に動作します.レガシーをそろそろ捨てられる日が来そうです.

f:id:no_clock:20181206231243p:plain

楽しい個人開発ライフを!

世の中の便利な個人サービスが,少しでも長く続きますように…!

明日は @ktrkmk さんです.お楽しみに!

*1:余談ですが,Windows 10でもVisual Basic 6.0は動作しますし,IDEコンパイルもできます

Raspberry Piでダッシュボードを作る(7) -時刻表-

f:id:no_clock:20171016214958j:plain

Raspberry Piとミニディスプレイ,各種センサを使ってダッシュボードを作ります.


今回のゴール

  • 通勤に使っている最寄り駅の時刻表を表示させる.

いちいち最寄り駅の時刻表を調べるのは面倒です.ダッシュボードに常に表示させておきましょう.

時刻表の抽出

今回は Yahoo!路線情報 を利用します(※個人利用に留めましょう).例として 日比谷駅(東京メトロ日比谷線)の時刻表 を使ってみます.

情報の抽出には, Nokogiri ライブラリを用います(スクレイピングとも言います).使い方は他所に譲るとして,下記スクリプトparse.rb といった名前で用意します.

#!/usr/bin/env ruby
require 'net/http'
require 'nokogiri'

data = Nokogiri::HTML.parse(Net::HTTP.get(URI.parse(ARGV[0])))

data.css('table.tblDiaDetail > tr').each do |node|
  hour = node.css('td:first-child').text.rjust(2,"0")
  node.css('td:last-child > ul > li').each do |train|
    next if train.text !~ /(\d+)/
    minute = $1.rjust(2,"0")
    puts "#{hour}:#{minute}"
  end
end

実行してみましょう.

$ gem install nokogiri # Nokogiriライブラリをインストール
$ chmod +x ./parse.rb # 実行権限を付与
$ ./parse.rb "https://transit.yahoo.co.jp/station/time/22951/?gid=3301&kind=1&done=time"
05:07
05:26
05:38
05:46
05:54
06:02
(省略)

無事に取得できました.ダッシュボードで表示するために,ファイルに出力しておきます.

$ ./parse.rb "https://transit.yahoo.co.jp/station/time/22951/?gid=3301&kind=1&done=time" > hibiya.txt

ダッシュボードへの表示

今回はかなりゴリ押しです.「むこう60分間の時刻表をいい感じに表示する」ようにします.

          <div class="card">
            <h4 class="card-header">時刻表</h4>
            <div class="card-body">
              <%
                data = File.read("hibiya.txt")
                train_data = data.split(/\n/).map{|e| e.chomp}.select{|e| e>Time.now.strftime("%H:%M") && e<(Time.now+60*60).strftime("%H:%M")}
                             .group_by{|e| e[0,2]}.map{|k,v| "<strong>#{k}</strong>#{"&nbsp;"*3}#{v.map{|e| e[3,2]}.join(" ")}"}.join("<br>")
              %>
              <p><%= train_data %></p>
            </div>
          </div>

これで,「次の電車何分だっけ?」というときにスマートフォンを操作せずに確認出来るようになりました.

f:id:no_clock:20180916224413p:plain

補足

今回,土休日や種別(急行など)は考慮していません.


今日はここまで.

Xamarin.iOS: Storyboard上のアイテムとC#のクラスとをリンクさせる

Xamarin.iOSの日本語文献が少ないので,記録も兼ねてアウトプットしていこうと思います.

Storyboard上のアイテムをC#のクラスとリンクさせる

結論: Storyboardのプロパティ Class にクラス名を書けば,対応する.csファイルが自動的に作成される.

Storyboard上に配置したViewControllerや他アイテムに対してコードを書きたいとき,C#のクラスとリンクさせる必要があります.
このとき,Storyboard上でクラス名を指定すると,対応する .cs ファイルが自動的に作成されます.

例えば,右側の Page View Controller をリンクさせたいときは,Page View Controller を選択した状態でクラス名を入力します.

f:id:no_clock:20180909234001p:plain

クラス名に対応する.csファイルが自動的に作成されます.

f:id:no_clock:20180909234009p:plain

環境

参考

RF-killされたBluetoothデバイスをオンにする

Raspberry Pi Zero WでBluetoothを使って遊ぼうとしたものの,RF-kill,つまり電波を出さないようになっているご様子.

$ sudo hciconfig
hci0:   Type: Primary  Bus: UART
        BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
        DOWN
        RX bytes:654 acl:0 sco:0 events:33 errors:0
        TX bytes:419 acl:0 sco:0 commands:33 errors:0
$ sudo hciconfig hci0 up
Can't init device hci0: Operation not possible due to RF-kill (132)

うーん,CUIでなんとかしたいな? と思ったら,rfkillというそのまんまのコマンドがありました.

bluetooth hci0 soft blocked if not turned on before arch boot / Laptop Issues / Arch Linux Forums

$ rfkill list
0: phy0: Wireless LAN
        Soft blocked: no
        Hard blocked: no
1: hci0: Bluetooth
        Soft blocked: yes
        Hard blocked: no

$ sudo rfkill unblock bluetooth
$ rfkill list
0: phy0: Wireless LAN
        Soft blocked: no
        Hard blocked: no
1: hci0: Bluetooth
        Soft blocked: no
        Hard blocked: no

$ sudo hciconfig hci0 reset
$ sudo hciconfig hci0
hci0:   Type: Primary  Bus: UART
        BD Address: B8:27:EB:xx:xx:xx  ACL MTU: 1021:8  SCO MTU: 64:1
        UP RUNNING PSCAN
        RX bytes:5025 acl:0 sco:0 events:293 errors:0
        TX bytes:5265 acl:0 sco:0 commands:291 errors:0

機内モードのオンオフ的なイメージですね.

manコマンドで調べると分かるのですが,unblock hci0とデバイス名で指定するのではなく,wifi bluetooth wimax などと種類を指定する必要があります.ちょっと分かりにくい.

「Visual Studio IntelliCode」早速使ってみた.

Visual Studio IntelliCodeが発表されました.

詳細は上記記事に譲るとして,既にVisual Studio 2017でC#向けにプレビュー版が使えるようになっています.早速使ってみます.

インストール

  1. Visual Studio IntelliCodeのサイトを開きます.
  2. ページ下部の「Try it out today for C#」のリンクを選択し,Visual Studio Marketplaceに飛びます.
  3. 「Download」からダウンロード. f:id:no_clock:20180508214648p:plain
  4. ダウンロードしたファイルを開くと,Visual Studioにインストールされます.

使用方法

特に設定などせず,普通にコーディングをするだけです. サジェストで「★」が出てきます.

使用例(アニメーション) f:id:no_clock:20180508215455g:plain

参考:IntelliCode不使用時は単にアルファベット順だった f:id:no_clock:20180508220236p:plain

アニメーションだと分かりづらいのですが,オーバーロードのあるメソッド(ここだとConsole.WriteLine)でも,最適と思われる定義が選ばれるようです.

プレビュー版はここまで.

プレビュー版の機能はこれだけ.正直なところ「使う頻度の少ないクラスに触れるときは嬉しいかも?」という程度です.

ただ,IntelliCodeのサイトには,潜在的なバグの検出・修正だったり,コーディングスタイルをソースコードから学習したり,といったことも記載されています.

潜在的なバグの検出に関しては,従来の静的コード解析よりも良いものが出せるのかどうか気になります.大いに期待したいところです.

Spring Fest 2017に参加しました&資料リンク

(11/29追記: 「これから始めるSpringのWebアプリケーション」「Yahoo! JAPANのコンテンツプラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ」の資料リンクを追加)

2017/11/24に開催されたSpring Fest 2017に参加しました.

冷めないうちに,発表資料のリンクと感想をアウトプットしておきます.

(発表者敬称略)

発表資料リンク

Twitter #jsugで見つけたものを可能な限りリンクしました.

時刻 KFC Hall KFC Hall Annex Room 113 Room 115
10:00-10:45 What's New in Spring - Dave Syer (Pivotal) - - -
11:00-11:45 エンタープライズ開発で利用するSpring Boot - 廣末 丈士(株式会社ビッグツリーテクノロジー&コンサルティング Introduction to Spring WebFlux - 槙 俊明 (Pivotal) これから始めるSpringのWebアプリケーション - 土岐 孝平(日本Springユーザ会) SpringFrameworkを用いた社内ライブラリ開発について - 朏島 一樹(リクルートライフスタイル)
12:00-12:45 - Wagby R8 と Spring の関係 - 贄 良則(株式会社ジャスミンソフト - -
13:15-14:00 Spring Security 5 解剖速報 - 岩塚 卓弥、堅田 淳也(NTTソフトウェアイノベーションセンタ) Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり - 高橋 勲(楽天株式会社) これから始めるSpringのWebアプリケーション 〜ハンズオン編〜 - 大野 渉 (Starlight & Storm) Yahoo! JAPANのコンテンツプラットフォームを支えるSpring Cloud Streamによるマイクロサービスアーキテクチャ - 鴨志田 智弥(ヤフー株式会社)
14:15-15:00 ドメイン駆動設計のためのSpringの上手な使い方 - 増田 亨(有限会社システム設計 / ギルドワークス株式会社) 事例で知る!Spring/Angularによる大規模エンタープライズ開発 - 岩佐 歩(株式会社野村総合研究所 Struts -> Spring 移植のテクニックとノウハウを公開 - 鈴木 健夫(株式会社スタイルズ) 脆弱性の探し方 ~発見と対応のノウハウ in NTTDATA~ - 浅原舜平(株式会社NTTデータ
15:30-16:15 Quick start Spring Boot on OpenShift (demo sources) - Kamesh Sampath (Red Hat's) 日本一やさしく説明する予定のマイクロサービス入門 - 長谷川 裕一(Starlight&Storm / 日本Springユーザ会) Pivotal認定講師が教える!Spring Data JPAによるデータアクセス徹底入門 - 多田 真敏(株式会社カサレアル) 2017年のLINEのマイクロサービスを支えるSpring - 井出真広(LINE株式会社)
16:30-17:15 The Road to Serverless - Dave Syer (Pivotal) Spring と TDD - 小川岳史、古家優(株式会社タグバンガーズ) ついに来たリアルタイムSpark~ビッグデータ処理の新常識・SnappyDataの実力~ - 山河 征紀(ウルシステムズ株式会社) Spring エンジニアが理解すべきフロントエンド入門 - Angular編 - 佐川 夫美雄(アシラス株式会社)
17:30-18:15 Spring BootとSpring Cloudで始めるマイクロサービス - 谷本 心(Acroquest Technology株式会社 / 日本Javaユーザーグループ) - 実践JHipster - こざけ(株式会社第一コンピュータリソース) SpringでOAuth 2.0・OpenID Connect 1.0を使う - うらがみ

以下,感想

10:00~ What's New in Spring? (Dave Syer (Pivotal))

  • Thinkpad + Linux + Jekyll + Google Chrome でプレゼンテーション.完成されている
  • 英語+同時通訳だったが,通訳前にリアクションする参加者が多かった.英語力が試される
  • 「これJavaなの?」と思うくらいの隠蔽具合
    • Spring Initializr (またはSpring Tool Suite)で簡単に新規プロジェクトが作成できるうえ,わずかなコーディングで動作する
    • 正直,Ruby on Rails最強だと思っていたので怯えている
  • 「サーバレスに向かっていくのかな?」と感じた
    • WebFlux, Router Functionsなどを用いた "Reactive", "Non-blocking" の説明が強かった

11:00~ Spring Frameworkを用いた社内ライブラリ開発について (朏島 一樹(リクルートライフスタイル))

  • 標準化はどこも苦労しているな~ と思った.地味だけど難しい活動
  • 方針がはっきりしていて良いと感じた
    • フレームワークではなく,あくまでライブラリ』(小分け)
    • 『「汎用性」「実装難易度」の2軸を指標としてライブラリ化』
  • プロダクト(開発プロジェクト)から「これライブラリ化しない?」という話が上がってくる,という話は正直うらやましい
  • 「ボイラープレートコード」(Boilerplate code - Wikipedia (英語版) 初めて聞いた

13:15~ Spring Data RESTを利用したAPIの設計と、作り直しまでの道のり (高橋 勲(楽天株式会社))

  • 貴重な失敗談.「Spring Data RESTは使わない」というオチに笑ってしまった
  • 「簡単なモノを簡単に作るのには向いているが,実際に適用するのは大変」
    • ちょっと触って「これ便利じゃん!」というのは結構危ないなと反省

15:30~ 2017年のLINEのマイクロサービスを支えるSpring (井出真広(LINE株式会社))

  • "Recent apps are Java/Spring applications",意外.勝手な偏見でRubyやらPHPやらゆるふわWeb系なのだと思っていた
  • 技術要素としてHTTP/2が(違和感なく)入っているあたりが眩しい
  • 良いものは使っていく,使ってみる,という空気感がありそうな気がした
    • 『みなさんもぜひ地雷を踏んでいってください』 (ツールのバグに対して)
  • 非同期サービス化するのは大変そう.でも既にだいぶ洗練されている様子だった

16:30~ ついに来たリアルタイムSpark~ビッグデータ処理の新常識・SnappyDataの実力~ (山河 征紀(ウルシステムズ株式会社))

  • Springと全く関係なさそうだ,という理由だけでセッション参加
  • ビッグデータ処理,「要素が多くてとっつきにくそう」という懸念を見事に破ってくれそうな感触
    • 『テーブルとSQLなら出来ると思うんです』 確かに出来そうな気がしてしまう
  • とりわけSynopsis Data Engineが興味深かった
    • 精度を抑える代わりに高速なクエリ処理を実現.信頼度も指定ができる
  • まっったく無関係だが Apache Spark のロゴがスパークかわいい

17:30~ Spring BootとSpring Cloudで始めるマイクロサービス (谷本 心(Acroquest Technology株式会社 / 日本Javaユーザーグループ))

  • やはり使い所は相当限られる,という感覚は間違っていない様子
  • 「学ぶと視野は広がるので,学んでおくことは重要」.どうせ使わないと思っていたけど触ってみてもいいかなと思えた
  • "Start simple, not small"
    • 小さすぎると苦しみは味わえない.確かに,サンプルページ表示しただけでは「ふーん」で終わる…
  • Spring Cloud Netflix Eureka (ユリーカと発音されていた)
    • わずかな設定で勝手にマイクロサービスを管理・探索・ロードバランシングされる.とても気持ち悪い(いい意味で)
  • トランザクションをマイクロサービスにまたがって行うのは難しい(実質不可能)」
  • 非同期処理で流す,サービスのインスタンス増減に自然に対応できる,のがポイントのよう