✖
8K いらないみたいな話を見ると腹が立ってくる
8K とか、あるいはその周辺で VR ってのは福祉なわけ。映像はまだまだ発展途上なの。歳をとって寝たきりになっても旅行を体験したいでしょう。ただ生きているだけでは辛い。
✖
しごとはじめ
今の会社は2012年1月1日入社ってことになってるので、今年で6年目になる模様。結構続いてる。
✖
年末年始
年末の、ちょうどかかりつけの小児科が休みになった翌日から子どもが高熱(一時的に39℃超、その後38℃超)を出し、おさまらないので休日夜間急患診療所に(妻が)連れていったところインフルエンザと診断されてタミフルが処方された。
子どもは2日ぐらいには解熱してやたら元気になったが外出するわけもいかず、急患診療所は3日分しか薬を処方できないのにタミフルは5日間飲み続ける必要があるという制約があったり (年末年始のような長期休暇時には急患診療所に再度行かないといけない)、それが終わっても保育園登園のためにはかかりつけ医に登園許可証を書いてもらう必要がありかなり面倒くさい。
ということで実家に帰ったりする予定をキャンセルし、年末年始は完全にひきこもっておりコンビニぐらいでしか外にでなかった。プラレールの技術力が上がってきた。
とりあえずは大人が発症しなかったのと痙攣が起きなかったのは不幸中の幸い。
タミフルといえば異常行動が有名だけど、うちの子供も若干様子がおかしかった。プラレール組みたてながら悪寒?っぽい動きをしたかと思えば「オバケがいた」と言い出したり、一時的にハイテンションになったりしていた。実際にこれが副作用かどうかは微妙だけど「これがタミフルのチカラか〜」と思った。あとたぶん副作用で下痢をしていた。
VPSのSSD化の効果
さくらのVPSの1GB HDDプランから、2GB SSD プランに移行してしばらく経過した。Google のサーチコンソールで見た感じだと全体的にスピードが上がって、なおかつ安定している。
Kindle Paperwhite のブラウザ(体験版)のWebSocketがおかしい(未解決)
接続しようとしても即座に onclose が呼ばれてしまう。しかもこのブラウザの onclose イベントには code プロパティも reason プロパティも存在してなくて原因がわからない。
- サーバサイドでは 400 を返している
- wss (TLS 経由) もダメ
備考
Kindle Paperwhite のブラウザはうっかり alert() を無限ループさせると端末再起動しかない。しかし再起動ダイアログが alert() のダイアログの下に出てしまう。
2017年の抱負
今年やったことを自分で承認する
日記を読みかえしてみたら今年もいろいろやっていた。年末にせめて自分で自分を承認してあげたい。おおまかには
- 高周波関係
- アンテナアナライザ製作
- キーボード製作
- 3D モデリング
の順に興味がうつりかわり、同時にウェブ技術とかNC切削とか、普段通りという感じのこともやっていた。振り替えってみると思ったより密度高く生きてるが、主観的にはそうでもないというかやる気がなさすぎて困っているという実感がある。なぜだろう……
ウェブとか HTTP/2 関係
h2 対応とか、このウェブサイトの最適化を結構やっていた。ハードウェア触る気力がなくなると、ノートPCだけでぼーっと最適化するみたいな流れ…… ウェブ技術はなんというか、仕事じゃなければあんまり気を張らなくても実装できるので、とりあえずやっておくというか、良い言いかたをすれば癒し的側面がある。
サーバサイドで Mathjax するあたりとかは結構がんばったし効果が高かった。
h2 対応のために h2o を導入したので、それ関係のエントリがかなり多い。
類似エントリみたいな、ちょっとアルゴリズムよりのこともやってみた。ただ実装するというより SQLite にこだわって工夫してやってみたところは良かった。仕事で SQLite 使うことはないので役には立たない。アルゴリズムの実装がものすごく苦手なんだけど (こういうこと言うとバカにされまくる……)、ちょっと頑張った例。TF-IDF なんてクソみたいに簡単なアルゴリズムではあるが……
仕事だと分業のおかげで、こういう上から下まで一貫してチューニングするみたいなのはやる機会がない。
- lowreal.net のHTTP2/HTTPS 化を実施 | tech - 氾濫原
- nginx の rewrite ルールっぽく h2o の mruby でリクエストの rewrite を行う | tech - 氾濫原
- h2o のログ設定 (logrotate.d) | tech - 氾濫原
- 現在の h2o.conf.yaml | tech - 氾濫原 (今はもっとだいぶ肥大化してます)
- サイトの最適化 | tech - 氾濫原
- サーバーサイド MathJax で数式表示を高速化する | tech - 氾濫原
- HTTP2 で何をサーバープッシュすべきか | tech - 氾濫原
- デザインの調整 | tech - 氾濫原
- JavaScript の必要ないソーシャルボタン | tech - 氾濫原
- h2o での server-push タイミングの最適化 | tech - 氾濫原
- ブログシステムの HTML 生成を効率化 | tech - 氾濫原
- ブログのキャッシュバックエンドの変更 | tech - 氾濫原
- トラックバックを実装しました | tech - 氾濫原
- 複数の psgi を1つのサーバでサービスするときにメモリをケチる | tech - 氾濫原
- SQLite で「PRIMARY KEY」を《真のプライマリキー》とするには | tech - 氾濫原
- TF-IDFとコサイン類似度による類似エントリー機能の実装 | tech - 氾濫原
- Gist に置いた JavaScript のベンチマークをとる | tech - 氾濫原
- SQLite の WITHOUT ROWID の効果測定 | tech - 氾濫原
- さくらのVPS、大阪・東京・石狩でどれを選ぶべきか | tech - 氾濫原
- AMP に対するモヤモヤ | tech - 氾濫原
- サーバー移行 | tech - 氾濫原
- このサイトのキャッシュ | tech - 氾濫原
- さくらのVPSのウェブサーバでIPv6の接続をうける | tech - 氾濫原
- サイトの負荷のシミュレーション | tech - 氾濫原
- h2o の proxy.reverse.url で localhost を指定していたら確率的に connection failure | tech - 氾濫原
- h2o で listen するポートを増やしたときは master プロセスの再起動が必要 | tech - 氾濫原
- nginx をアンインストール | tech - 氾濫原
- IPv6 対応にした | tech - 氾濫原
- h2o の duration stats | tech - 氾濫原
- h2o の status/json を mackerel に送る | tech - 氾濫原
おうちハック的なのもやっている。
アンテナアナライザなど高周波関係
デジタルSWR計。アンテナアナライザへの布石。
- 自作 デジタル SWR 計(再) | ログアンプを使いQRP〜1KWまで | tech - 氾濫原
- 自作 デジタル SWR 計(再) 2 | 方向性結合器の改善編 | tech - 氾濫原
- 自作SWR 計を一旦仕上げ | tech - 氾濫原
- AD8307 を 3.3V で動かすときの罠 | tech - 氾濫原
アンテナアナライザ関係。いろいろ勉強になっておもしろかった。 今年前半では一番大きなプロジェクトだったように思う。数学苦手なのだけれど面白いなと思えたところが地味な収穫かもしれない。
- AD9851 DDS モジュールを LPC1114/mbed と | tech - 氾濫原
- アンテナアナライザの回路 シリーズ抵抗1本型 | tech - 氾濫原
- アンテナアナライザの回路 ブリッジ型 | tech - 氾濫原
- アンテナアナライザの回路 - ブリッジの三つの電位差を測るタイプ | tech - 氾濫原
- アンテナアナライザの回路 ー 位相検出器を使ったタイプ | tech - 氾濫原
- アンテナアナライザの回路 ー ヘテロダインを使ったタイプ | tech - 氾濫原
- 複素電圧・複素電流とはなんなのか | tech - 氾濫原
- 「コイルとコンデンサは電圧と電流の位相差を90度進めさせる/遅れさせる」とはどういう意味なのか | tech - 氾濫原
- 簡単かつ安く高精度なアンテナアナライザーを自作したい | tech - 氾濫原
- 簡単かつ安く高精度なアンテナアナライザーを自作したい (2) | tech - 氾濫原
- 自作アンテナアナライザーのBluetooth化とアプリケーション | tech - 氾濫原
- アンテナアナライザーをケースに収めた | tech - 氾濫原
スペアナ最高に楽しい。でも最近高周波回路やってなくてあんまり起動してない……
- スペクトラムアナライザ DSA815-TG を買いました / LAN経由でスクリーンショットとれるようにしました | tech - 氾濫原
- DSA815-TG の 10MHz 付近の奇妙なバグとファームウェアアップグレード | tech - 氾濫原
- アマチュア無線用コモンモードフィルタの特性評価 | tech - 氾濫原
- スペアナとリターンロスブリッジを使ってSWRを測ってみる | tech - 氾濫原
- 高周波用アッテネータを作ってみる | tech - 氾濫原
- 10MHz バンドパスフィルタ | tech - 氾濫原
- 10MHz バンドパスフィルタ2 | tech - 氾濫原
- LTSpice で伝送線路トランス | tech - 氾濫原
キーボード関係
ヤパチーからの流れで自作して、builderscon で発表させてもらった。今年後半の主なプロジェクトとなった。結果的には、カンファレンスできっかけをもらってカンファレンスのトークに還元した感じになって主観的には良かった。
- ErgoDox について調べた(買わないけど) | tech - 氾濫原
- Inkscape で作図したファイルを KiCAD の pcbnew で読みこむ | tech - 氾濫原
- BLE Nano の開発 - ブレッドボード配線 | tech - 氾濫原
- OSX + BLE で HID over GATT でペアリング(bonding)ができなくてハマった | tech - 氾濫原
- BLE Nano + mbed の ADC の基準電圧 | tech - 氾濫原
- HHKB を左右分割エルゴノミクスキーボードにする (OSX) | tech - 氾濫原
- BLE Nano + mbed の Serial の実装がつらい感じだった | tech - 氾濫原
- KiCAD で複数ボードプロジェクトを運用する | tech - 氾濫原
- OS X で KiCAD を使う際の注意点 | tech - 氾濫原
- BLE Nano (nRF51822) でどうしても 1mA 以上電流食うぞというとき | tech - 氾濫原
- BLE Nano (nRF51822) のドライブ能力を外付け部品なしで拡張する | tech - 氾濫原
- mbed + BLE Nano で FOTA (DFUService) を使うには? | tech - 氾濫原
- なぜ BLE Nano にご執心なのか | tech - 氾濫原
- BLE Nano (nRF51) + mbed でセキュリティ付きペアリングをして 0x3d エラーがでる | tech - 氾濫原
- ErgoDox ではないナニか。オープンソースかつ Bluetooth 接続のキーボード | tech - 氾濫原 まとめエントリ
- 自作キーボードの製作 — コンセンプトとキーレイアウトおよび技術仕様編 | tech - 氾濫原 (1)
- 自作キーボードの製作 — 回路設計とアートワーク・ハードの製作編 | tech - 氾濫原 (2)
- 自作キーボードの製作 — ファームウェアの実装編 | tech - 氾濫原 (3)
- BLE Nano のオンラインプロジェクトをエクスポートして GCC でコンパイルして RAM 32kB 使えるようにする | tech - 氾濫原
- BLE Nano (nRF51822)、waitForEvent ( sd_app_evt_wait() ) 中に予期せず WDT が発動する場合 | tech - 氾濫原
- Karabiner で自作キーボードが認識しなかった件 | tech - 氾濫原
- BLE Nano (nRF51) HOGP で接続中のアイドル電流 | tech - 氾濫原
- BIOS 画面でもBluetooth LE な無線キーボードを使いたい | tech - 氾濫原
- Microsoft Universal Foldable Keyboard (US版) を買ってみたら辛い事実がわかった | tech - 氾濫原
- builderscon tokyo 2016 で「 Bluetooth キーボードの作りかた」を喋りました | tech - 氾濫原
その他組み込みや電子工作
ESP8266 結構触ってたなという感じ。安くなると夢が広がる。
- ESP8266 から GrowthForecast へセンサーデータをPOST | tech - 氾濫原
- ESP8266 (ESP-WROOM-02) の Deep Sleep でデータを引き継ぐ | tech - 氾濫原
- ESP8266 起動時にシリアルにでるゴミっぽいもの | tech - 氾濫原
- メモ: ESP8266 での実測電流 | tech - 氾濫原
- ESP8266 の低消費電力の限界をさぐる (ESP-NOWを使ってみる) | tech - 氾濫原
- ESP-NOW はどのように IEEE802.11 フレームを使っているか? | tech - 氾濫原
ebay とかで買ったやつをとにかく動かすシリ〜ズみたいなのをやってた。意外と得るものが多い。そのときそのときで触ってる環境で動かしてるのでプラットフォームに一貫性がない。
- Use IIC/I2C/TWI 1602 Serial Blue Backlight LCD Display | tech - 氾濫原
- 超小型 DC/DC ステップアップコンバータ SX1308 2A $0.99 | tech - 氾濫原
- I2C 8*8 LED dot Matrix module HT16K33 | tech - 氾濫原
- BMP180 I2C 気圧・温度計センサー | tech - 氾濫原
- MQ-135 Sensor Air Quality Sensor Hazardous Gas Detection LM393 MQ135 gas sensor | tech - 氾濫原
- AD9850 DDS モジュール | tech - 氾濫原
- AD9851 DDS モジュール | tech - 氾濫原
- 100円ぐらいで売られている中華ラジケータ(アナログパネルメータ)を試す | tech - 氾濫原
- 中華AD8307を使ってみる | tech - 氾濫原
- 中華AD8307をデジタル電力計にしてみる | tech - 氾濫原
- MAX7219 8桁 7セグメント LED モジュール / Arduino | tech - 氾濫原
- ST7735 128x128 TFT カラー液晶モジュール | tech - 氾濫原
- STM32F103 C8 T6 の安いボードでLチカ (platformio + mbed) | tech - 氾濫原
- 中華製の J-Link OB を使い OpenOCD で nRF51 に書きこむ | tech - 氾濫原
- 中華製 HDMI -> USB 3.0 UVC キャプチャデバイス | tech - 氾濫原
- MH-Z19 という格安 CO2 センサを読んでみた | tech - 氾濫原
- CO2 センサの可視化 | tech - 氾濫原
- 歪みゲージと HX711 を使って重量計測する (Arduino) | tech - 氾濫原
ioctl を Ruby から呼ぶのを割とやってて、書いてないけどこれ以外にも SPI を Ruby でやるとかもやってたりした。Ruby は IO 処理書くのがかなり楽なのと全体的に可読性が良く、ビルトインメソッドが充実しているので「パフォーマンスはともかく理解しやすいコードを書く」みたいなときに Ruby で書くことが多い。
gem とか使わないとダメになってくると他の言語に逃げがち。gem、クオリティ低いものが大量にあって、どれを使うべきか?自分で実装すべきか?とか悩んでるうちに1日終わる。テキトーに動かしたいときはほんと時間の無駄。
- ruby-serialport で任意のボーレートを設定するには (ただし Linux に限る) | tech - 氾濫原
- Ruby で IO#ioctl の引数に構造体 (struct) へのポインタを渡したいとき | tech - 氾濫原
- Ruby の pack テンプレート文字列からそのデータサイズを求める | tech | ruby - 氾濫原
- Ruby でネストした構造体文字列をネストした配列として unpack する | tech | ruby - 氾濫原
消費電力可視化もいろいろやってみたが、今のところ実用に至ってない。
- 市販の節電モニターから値を読みだしてグラフ化 | tech - 氾濫原
- コンセントごとの消費電力を知りたい人生 | tech - 氾濫原
- スマートメータのBルートサービスで Wi-SUN モジュールを使って瞬間消費電力を読み出す | tech - 氾濫原
- スマートメータから瞬間消費電力を読むRubyのコード | tech - 氾濫原
急に C++ と親密になって好きになった。組込みなら絶対 C++ で書きたい。
mbed 関係。結構さわったしコードも読んだ。
- LPC1114 LPC1114FN28 / mbed 開発を platformio を使ってやる | tech - 氾濫原
- mbed のフレームワークの温度感 | tech - 氾濫原
- mbed InterruptIn はネストするか | tech - 氾濫原
GPS DO を途中までつくった感じ。完成してない (必要性の無さに気付いて、やる気をうしなってしまった)
CNC / PCB Milling 関係
いろんなことで、かなり役に立っている。元はとったな〜というぐらいの気分でいる。grbl からmachinekit (beaglebone black) への移行が主なトピック。machinekit を収める筐体作りがまだ途中。
- PCB Milling で TSSOP | tech - 氾濫原
- 間違えて RN-42 の 2mmピッチ基板のやつを買ってしまった | tech - 氾濫原
- YAP(achimon)C::Asia Hachioji 2016 mid in Shinagawa | tech - 氾濫原
- メモ書き:KiCAD + pcb2gcode で pcbmilling | tech - 氾濫原
- pcb2gcode へのプルリク | tech - 氾濫原
- Machinekit (Linux CNC) のアーキテクチャと、BeagleBone Black での動作 | tech - 氾濫原
- CNC フライスで加工台の面出しをするG-Codeを生成するRubyスクリプト | tech - 氾濫原
- Beagle Bone Black + Machinekit での CNC 制御 (Sable-2015) | tech - 氾濫原
- Machinekit (LinuxCNC) を XBox コントローラを使って機械を動かす。 | tech - 氾濫原
- Beagle Bone Black + Machinekit での PCB Milling | tech - 氾濫原
- pcb2gcode のオートレベリングを使ってみる | tech - 氾濫原
- 最適な Probe 速度を計算する | tech - 氾濫原
- Fusion 360 + Machinekit (LinuxCNC) でちゃんとパスがトレースされない | tech - 氾濫原
- 非導体系材料用に Touch Probe を作った | tech - 氾濫原
- BeagleBone Black の LED をはんだゴテなしで延長する | tech - 氾濫原
- Autoleveller を使ってリカバリ可能なオートレベリングをする | tech - 氾濫原
知見はかなり溜ってきた。
3D モデリング
Fusion 360 導入で可能性がとてもひろがった。全く新しい分野の技術習得という意味では今年一番価値があったかもしれない。拘束によって作図するのはとても気持ちいい。
3D プリンタがない (置く場所がない) のが悩み。欲しんだけどなあ。
- SketchUp Make を捨てて Autodesk Fusion 360 に移行した | tech - 氾濫原
- Fusion 360 の練習 RCA ジャック | tech - 氾濫原
- Fusion 360 の練習 非常停止ボタン | tech - 氾濫原
- Fusion 360 練習 パネルマウント USB コネクタ (USB 内部延長) | tech - 氾濫原
- Fusion 360 の練習 DB25 のプラグ (オス) コネクタ | tech - 氾濫原
- Fusion 360 で SVG をインポートしてスケッチに利用する | tech - 氾濫原
- Fusion 360 のいいところ - 氾濫原
- モデリングしたものを削り出す | tech - 氾濫原
- Fusion 360 の練習 DC プラグ2連発 | tech - 氾濫原
- Fusion 360 の練習 - トグルスイッチ・DCジャック・LED | tech - 氾濫原
- Fusion 360 同軸切換器 CX210A | tech - 氾濫原
- Fusion 360 - RCサーボモータ S03T 2BBMG | tech - 氾濫原
- Fusion 360 - HDMI パネルマウントメス | tech - 氾濫原
- Fusion 360 の練習 - 神明鳥居 | tech - 氾濫原
- Fusion360 — 電源ボタン - 氾濫原
- Fusion360 - リレーモジュール - 氾濫原
その他
全く分類できないもの
cmake はプログラミング言語ってことはわかったけど結局役に立ってない。相変わらず他人の書いた CMakefile.txt は読む気がしない。
RabbitMQ に TLSv1.1 で接続しようとしても tlsv1 alert insufficient security と言われる
表題の通りでハマってしまった。
各ソフトウェアのバージョン
$ sudo rabbitmqctl status
...
{rabbit,"RabbitMQ","3.6.6"}
... $ cat /usr/lib/erlang/releases/18/OTP_VERSION 18.3
rabbitmq.config
{versions, ['tlsv1.2', 'tlsv1.1', tlsv1]} 接続確認
openssl s_client で接続確認してみる。
tls1.2
$ openssl s_client -connect 127.0.0.1:5671 -tls1_2 < /dev/null
これ問題なかった。
tls1 tls1.1
どっちもなぜか同じように以下のようなエラーになる。
$ openssl s_client -connect 127.0.0.1:5671 -tls1_1 < /dev/null
CONNECTED(00000003)
139728874526360:error:1409442F:SSL routines:ssl3_read_bytes:tlsv1 alert insufficient security:s3_pkt.c:1472:SSL alert number 71
139728874526360:error:1409E0E5:SSL routines:ssl3_write_bytes:ssl handshake failure:s3_pkt.c:656:
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 7 bytes and written 0 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.1
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
PSK identity: None
PSK identity hint: None
SRP username: None
Start Time: 1483074781
Timeout : 7200 (sec)
Verify return code: 0 (ok)
--- 解決方法
結局これは Erlang の ssl ライブラリの問題らしく、基本的には Erlang のバージョンをあげる必要があるっぽい。しかしRabbitMQ 3.6.1 / Erlang 18.3 TLS insufficient security failures からリンクがある通り以下のようにするとうまくいった。
{versions, ['tlsv1.2', 'tlsv1.1', tlsv1]},
{ciphers, ["ECDHE-ECDSA-AES256-GCM-SHA384","ECDHE-RSA-AES256-GCM-SHA384",
"ECDHE-ECDSA-AES256-SHA384","ECDHE-RSA-AES256-SHA384", "ECDHE-ECDSA-DES-CBC3-SHA",
"ECDH-ECDSA-AES256-GCM-SHA384","ECDH-RSA-AES256-GCM-SHA384","ECDH-ECDSA-AES256-SHA384",
"ECDH-RSA-AES256-SHA384","DHE-DSS-AES256-GCM-SHA384","DHE-DSS-AES256-SHA256",
"AES256-GCM-SHA384","AES256-SHA256","ECDHE-ECDSA-AES128-GCM-SHA256",
"ECDHE-RSA-AES128-GCM-SHA256","ECDHE-ECDSA-AES128-SHA256","ECDHE-RSA-AES128-SHA256",
"ECDH-ECDSA-AES128-GCM-SHA256","ECDH-RSA-AES128-GCM-SHA256","ECDH-ECDSA-AES128-SHA256",
"ECDH-RSA-AES128-SHA256","DHE-DSS-AES128-GCM-SHA256","DHE-DSS-AES128-SHA256",
"AES128-GCM-SHA256","AES128-SHA256","ECDHE-ECDSA-AES256-SHA",
"ECDHE-RSA-AES256-SHA","DHE-DSS-AES256-SHA","ECDH-ECDSA-AES256-SHA",
"ECDH-RSA-AES256-SHA","AES256-SHA","ECDHE-ECDSA-AES128-SHA",
"ECDHE-RSA-AES128-SHA","DHE-DSS-AES128-SHA","ECDH-ECDSA-AES128-SHA",
"ECDH-RSA-AES128-SHA","AES128-SHA"]},
{honor_cipher_order, true}, ref
RabbitMQ で MQTT over WebSocket
ウェブページから JavaScript で MQTT ブローカーに送られてくるデータを取得したかったので、MQTT over WebSocket を試してみました。
RabbitMQ 3.6.6 をいれる
Ubuntu のレポジトリのは 3.5.7 と古いので、Installing on Debian / Ubuntu にしたがって 3.6.6 にします。
既に古いのが入っていても、説明通りに RabbitMQの apt レポジトリを設定して、 apt-get update して install したら自動でアップグレードされます。
プラグインをいれる
rabbitmq_web_mqtt をいれます。これは Community Plugins にありますが、 RabbitMQ のチームが作っているので安心感があります。プラグイン自体が比較的新しくて、RabbitMQ 3.6.1 以降でないと使えません。
$ wget --content-disposition https://bintray.com/rabbitmq/community-plugins/download_file\?file_path\=rabbitmq_web_mqtt-3.6.x-14dae543.ez $ sudo mv rabbitmq_web_mqtt-3.6.x-14dae543.ez /usr/lib/rabbitmq/lib/rabbitmq_server-3.6.6/plugins/ $ sudo rabbitmq-plugins list | grep web_mqtt [ ] rabbitmq_web_mqtt $ sudo rabbitmq-plugins enable rabbitmq_web_mqtt The following plugins have been enabled: cowlib cowboy rabbitmq_web_mqtt Applying plugin configuration to rabbit@stfuawsc... started 3 plugins. $ sudo rabbitmq-plugins list | grep web_mqtt [E*] rabbitmq_web_mqtt
設定する
デフォルトで 15675 が listen されています。このままでいいのですが、念のため設定を書いておくことにしました。
設定例がないのでソースを読むしかないようです。rabbitmq_web_mqtt.schema が設定ファイルのスキーマのようなので、これを参考に以下のようにしました。
{rabbitmq_web_mqtt,
[
{tcp_config,[{port, 15675}]}
]
} WebSocket 経路の TLS 化はリバースプロキシ (h2o) で行うので、このサーバ自体には TLS の設定を書いていません。
リバースプロキシ
HTTP フロントエンドの h2o からポート 15675 にリバースプロキシするように設定しました。これで外部から接続可能になります。
なおh2oは定期的にWebSocket接続を切るようになっているので、クライアント側で再接続するコードが必須です。
WebSocket から繋ぐ
認証はどうなるのか? という疑問があるところですが、MQTT レイヤーでのユーザ認証があります。Upgrade 時に Origin による制限などはかけられないようです。
rabbitmq-web-mqtt-examples というレポジトリがあり、これを参考にすれば簡単に接続できます。
ライブラリとして Eclipse Paho の JavaScript 版を使っています。WebSocket のエンドポイントを指定する以外は普通にMQTTするのと変わりません。
var TOPIC = "/foo/bar/baz";
var USER = "foo";
var PASS = "bar";
function mqttConnect() {
var client = new Paho.MQTT.Client(
location.hostname,
location.port || 80,
"/mqtt", "myclientid_" + Math.random().toString(32)
);
client.onConnectionLost = function (responseObject) {
console.log(responseObject);
// reconnect
setTimeout(mqttConnect, 1000);
};
client.onMessageArrived = function (message) {
var data = Number(message.payloadString);
console.log(data);
};
client.connect({
userName: USER,
password: PASS,
timeout: 3,
onSuccess: function () {
console.log('onSuccess');
client.subscribe(TOPIC, {qos: 1});
},
onFailure: function (message) {
console.log('onFailure', message.errorMessage, message);
}
});
} ブラウザ上の WebSocket の場合、TLS はブラウザ側でやってくれるので、普通の MQTT with TLS の接続で考えることよりも少なくて楽です。
ref
センサーデータ用に RabbitMQ + MQTT をセットアップする
RabbitMQ + MQTT で Pub/Sub サーバを立てることにしました。
いろいろなセンサーのグラフ化にあたって GrowthForecast へ直接 POST を行っていましたが、やはり一旦メッセージブローカー的なものをいれたほうがよさそうだという感じになってきました。
なぜメッセージブローカーが必要か
センサーデータを複数のプログラムから使いたい場合、特にほぼリアルタイムで情報を得たいようなケースだと、直接各アプリケーションに投げるのではなくて、センサーはある一箇所に値を投げることだけを考え、アプリケーションはある一箇所からデータを受けとることだけを考えるように分離したくなります。
例えば今まではセンサーデータをアプリケーションであるグラフサービスに直接投げていましたが、これだとセンサーデータをさらに別のデバイスから読みだして表示するといった場合に、本来の用途ではないグラフサービス側のAPIに問合せたりする必要があって不便です。
MQTT を選択
MQTT はキューがない (最後の値だけ保存する/Retain) Pub/Sub のメッセージ配信プロトコルで、組込み系だとそこそこメジャーなようです。ググってみるとクライアント実装はそこそこ充実しています。
サーバ実装がいまいちコレというのがない気がするのですが、RabbitMQ のプラグインに MQTT プロトコルサポートがあるので、これを利用するのが比較的よさそうでした。
これ系のプロトコルは MQTT 以外にもいろいろあって、RabbitMQ の本来の用途である AMQP も競合プロトコルになります。AMQP より MQTT が好まれるのはプロトコルのシンプルさのためですが、機能的には AMQP が勝ります。
RabbitMQ のインストール
ひとまず Ubuntu のパッケージをそのままつかうことにしました。
sudo apt-get install rabbitmq-server
Rabbit MQ は Erlang で書かれているので、Erlang 関係のパッケージが大量にはいります。
インストール直後から起動していて、rabbitmqctl status でステータスが見れます (root 権限が必要です)。デフォルトではクラスタリング用のポート25672と、AMQP 用のポート 5672 が listen されていました。
sudo rabbitmqctl status
続いて mqtt プラグインを有効にしておきます。
sudo rabbitmq-plugins enable rabbitmq_mqtt
このコマンドは自動的に設定が反映され、status を見ると mqtt を 1883 で listen していることがわかります。
RabbitMQ の設定
適当に見てみると /etc/rabbitmq/rabbitmq-env.conf というのが最初からありますが、これは環境変数設定ファイルなのでとりあえずそのままにしておきます。
ログとして /var/log/rabbitmq/$node@$host.log というファイルがあり、これの冒頭に
node : rabbit@stfuawsc home dir : /var/lib/rabbitmq config file(s) : /etc/rabbitmq/rabbitmq.config (not found) cookie hash : log : /var/log/rabbitmq/rabbit@stfuawsc.log sasl log : /var/log/rabbitmq/rabbit@stfuawsc-sasl.log database dir : /var/lib/rabbitmq/mnesia/rabbit@stfuawsc
というログが出ています。この通り設定ファイルは /etc/rabbitmq/rabbitmq.config になりますが、まだないので作る必要があります。
サンプル設定ファイルがあるのでとりあえずこれをコピペしてつくるのがよさそうです。
# とりあえず眺める zless /usr/share/doc/rabbitmq-server/rabbitmq.config.example.gz # コピペからはじめる sudo sh -c 'zcat /usr/share/doc/rabbitmq-server/rabbitmq.config.example.gz > /etc/rabbitmq/rabbitmq.config'
Erlang の設定ファイル形式なのでちょっと読みにくいです。
- % から行末まではコメント
- シングルクオートはアトム (Ruby でいうところのシンボルと同様)
- ダブルクオートはその文字列の数値のリスト
- 括弧付きダブルクオートはバイナリ (Bit Syntax)
- 余計なカンマがあると怒られる (ケツカンマ問題がある)
設定方針
ここでは方針として以下のようにします。
- MQTT を使う
- TLS を使う
TLS の設定では取得済みの Let's Encrypt の証明書をそのまま流用します。ただ、Let's Encrypt がつくる /etc/letsencrypt/live 以下が root 以外読めないようになっている一方、RabbitMQ は証明書ファイルを rabbitmq ユーザで読もうとするようで eacces がでます。
しかたないので以下のようにしてアクセスを許可するように変えてしまいました。なにかもっとスマートに解決したほうがいいと思うのですが、思いつきませんでした。
sudo chmod 0755 /etc/letsencrypt/{live,archive} 設定
以下のようにしてみました。
%% -*- mode: erlang -*-
%% ----------------------------------------------------------------------------
%% RabbitMQ Sample Configuration File.
%%
%% See http://www.rabbitmq.com/configure.html for details.
%% ----------------------------------------------------------------------------
[
{rabbit,
[
{ssl_listeners, [5671]},
{handshake_timeout, 10000},
{log_levels, [{connection, info}, {channel, info}]},
{ssl_options, [{cacertfile, "/etc/letsencrypt/live/cho45.stfuawsc.com/fullchain.pem"},
{certfile, "/etc/letsencrypt/live/cho45.stfuawsc.com/cert.pem"},
{keyfile, "/etc/letsencrypt/live/cho45.stfuawsc.com/privkey.pem"},
{verify, verify_peer},
{fail_if_no_peer_cert, false}]},
{auth_mechanisms, ['PLAIN', 'AMQPLAIN']},
{auth_backends, [rabbit_auth_backend_internal]},
{ssl_handshake_timeout, 5000}
]},
{rabbitmq_mqtt,
[
{allow_anonymous, false},
{vhost, <<"/">>},
{exchange, <<"amq.topic">>},
{subscription_ttl, 1800000},
{prefetch, 10},
{tcp_listeners, [1883]},
{ssl_listeners, [8883]}
]}
]. ユーザの追加
もともとある guest/guest は localhost からだけ接続が許されているのでそのままにして、外部から使う用のユーザを追加します。
# guest しかない $ sudo rabbitmqctl list_users Listing users ... guest [administrator] # ユーザ追加 $ sudo rabbitmqctl add_user tsun pass Creating user "tsun" ... # 確認 $ sudo rabbitmqctl list_users Listing users ... guest [administrator] tsun [] # パーミッションを追加 conf write read の順で指定する。これは正規表現。ここでは全権 $ sudo rabbitmqctl set_permissions tsun ".*" ".*" ".*" Setting permissions for user "tsun" in vhost "/" ...
繋いでみる
クライアントに rubygems の mqtt を使ってみます
gem install mqtt
#!/usr/bin/env ruby
require 'mqtt'
require 'thread'
# MQTT::Client seems not thread safe
mutex = Mutex.new
pub_thread = Thread.start do
mutex.lock
MQTT::Client.connect(
host: '127.0.0.1',
port: 8883,
ssl: true,
username: 'guest',
password: 'guest',
) do |client|
mutex.unlock
p [:pub, client]
10.times do
sleep 1
p :publish
client.publish("test", "this is test", false)
end
end
end
sub_thread = Thread.start do
mutex.lock
MQTT::Client.connect(
host: '127.0.0.1',
port: 8883,
ssl: true,
username: 'tsun',
password: 'dere',
) do |client|
mutex.unlock
p [:sub, client]
client.subscribe("test")
client.get do |topic,message|
p [ topic, message ]
end
end
end
pub_thread.join こんな感じのコードで動いていることを確認できるはずです。ただし guest を指定しているので、同一ホストで動かす必要があります。
ポートを開ける
基本の動作確認ができたので、パブリックにアクセス可能にするためポートをあけます。ufw で 8883 (MQTT with TLS) だけをあけました。他はいまのところ使用予定がないので閉じたままです。listen 自体しないほうがより安全ですが、サーバ内でごにょごにょすることはありそうなのでそのままにしています。
sudo ufw allow 8883
外部から、さきほど作ったユーザで接続確認を行ってとりあえずセットアップ完了です。



