2015年5月31日
[ble]Advertisingまで
Advertisingするまでだ。
Nordic nRF51822でBLEしてみました 2
こんな感じですよ、程度なので、詳細はBLEにせよnRF51822にせよ調べ直してもらうことになるだろうが、まあとっかかりになるくらいの資料にはなったんじゃなかろうか。
自分が数ヶ月後に見て「ああ、そういえばそうだった」みたいな資料になればよいのだが。
2015年5月30日
[ble]サンプルを動かすまで
が、入門資料はあふれているし、nRF51822はバージョンアップが激しくて数ヶ月も経つと風化どころか役に立たなくなるので、さらっとしたものを作ることにした。
Nordic nRF51822でBLEしてみました
まあ、しっかり書く気力がなかった言い訳なんだけどね。
Windows Live Writeで投稿できなくなった
このブログはBloggerなのだが、いつも使っているWindows Live Writerでの投稿が出来なくなった。
Blogger側の問題かと思っていたのだが、こちらを読むとそうではないようだ。
bloggerでWindows Live Writerが使えなくなりました。[blogger] | ブログ改善のネタ帳
Bloggerの認証が変わったが、Live Writerはそれに対応していないから使えない、ということらしい。
うーむ。
今のままではダメですよ、というのは事前にアナウンスされていたようだ。
まあ、そりゃそうだよな。私が知らんかっただけだ。
OAuth 2 または OpenID Connect への移行期限まであと 1 ヶ月 - Google Developer Japan Blog
画像の埋め込みと、ソースの埋め込みさえ簡単にできれば特にこだわらないのだが、なかなかねぇ。
またZoundry Ravenに戻すか。
Zoundry Ravenでもダメみたいだ。
がーん。
A Tinkerer's Blog: Unable To Access Blogger/Blogspot From Raven/RavenPlus
どうしよう・・・。
あまりここに時間を掛けたくないので、Live Writerが使えるようになるか、他のブログエディタが見つかるまでは更新をお休みしよう。
2015年5月27日
[ble]ATTテーブルの参考にSensorTagがよさそうだ
Peripheralは、なんとなくわかった気がする。
Centralも、とりあえずなんとかなりそうな気がする。
じゃあ、作ってみよう!
・・・なんだけど・・・どう作ればいいんだろう?
BLEのインターフェース仕様書にあたるものは、ATTテーブルだろうと思っている。
このアトリビュートは、こんな動作しますよ、というやつだ。
それさえ決めれば、アクセス方法がだいたい決まるだろう。
・・・だが・・・どういうテーブルにするのがよいのだろう?
いや、よいとか悪いとかじゃなくて、どんな感じにするものなのかという基礎がわかってない。
例えるなら、「シュークリームというのは、焼いた薄い皮の中に甘いクリームが入ってますよ」という情報だけを知って、そこから甘い餃子を作ってしまうような感じを避けたいというところだ。
「だいたいシュークリームというのはこんなもの」というのがわかれば、まったく意図しないものになってしまうことだけは避けられるだろう(使い勝手とかは、また別のことだ)。
ネットで入手でき、手元に装置もあるATTテーブルとなると、SensorTagのものしか思いつかない。
なので、まずはこれをお手本にしようとしている。
見ただけだと身につかないタイプなので、わざわざExcelに書き写しながら考えたりなど。
2015年5月25日
[ble]TxAdd=1はrandom address
SensorTagはBlueZのgatttoolでつながることがわかったので、手持ちのBVMCNDT52(Braveridge社、nRF51822)に載せたアプリで試してみた。
が、connectできず・・・。
しばらく悩んだが、パケットモニタで確認するとわかった。
SensorTagはpublic addressなのだが、私はrandom addressでやってたのだ。
hiro99ma blog: [ble]Device Addressのpublicとrandom
上が自作、下がSensorTagだ。
gatttoolはデフォルトでpublicとしてconnectするようになっているので、指定が必要。
[F1:78:92:42:17:BF][LE]> connect F1:78:92:42:17:BF random
これで接続できた。
primaryコマンドでも、自作サービスのUUID(128bit)が載っている。
載っているのだが、ハンドル値の意味がよくわからない。
まあ、ハンドル値はSoftDeviceが返してくるから管理対象ではないのだけど、有効範囲は知っておきたい。
Core_V4.2.pdfのVol.3 Part GにGATTのことが書いてあり、その2.5章 ATTRIBUTE PROTOCOLの2.5.1節に「0x0001~0xFFFF」と書かれていた。
最初が0x0001で、追加するごとにインクリメントしているようだ。
2015年5月17日
汝の名はBlueZ - (11) : githubに置いた
BlueZ特集の最後だ。
初回が4月21日だから、1ヶ月近くやってたんだ・・・。
SensorTagに少し対応したgatttoolをgithubに置いた。
確認環境は、Raspberry Pi(2011.12) + BT-Micro4だ。
https://github.com/hirokuma/bluez-gatttool-sensortag
ソースはBlueZのattribフォルダがほぼそのまま。
違うのは、gatttool.cとinteractive.cくらい。
gatttool.cは、引数を打ち込むのが面倒なのでデフォルト値を付けただけ。
主にinteractive.cを変更している。
対応と言っても大したことはしておらず、以下を自動的にやるだけだ。
- connect
- primary
- ボタンとIR TemperatureへのNotify許可
- ボタンのNotificationを受けたら、ボタンがS2なのかS3なのかをコンソール出力
makeは、BlueZ 5.30で行っている。
BlueZのソースファイルからビルドしておかないと、makeできない。
というのも、BlueZのビルド時に生成される内部用ライブラリを2つほど使っているからだ。
makefile自体は、nRF51822で使われているものを流用した。
私はMakefile書くのが上手じゃないし、nRF51822のはクロスコンパイルもセルフコンパイルもどっちでもいけそうなので、テンプレートに仕立てたのだ。
makeすると、"gatttool"ではなく"gatool"ができる。
一応名前を分けておかないと、紛らわしいだろうと思ってね。
実行は、普通のgatttoolと同じようにできる。
引数を省略すると、gatttool.cのmain()に書いたデフォルト値が使われるので、書き換えると良いだろう。
インタラクティブモードで"st"というコマンドを追加していて、これを実行すると上記の自動でやることをやってくれる。
少々だったら、こんな感じで作っていけばCentral側として相手になってくれそうだ。
画面を出したいとか思ったら、やはりAndroidみたいなスマートフォンが手軽になりそうだけど、コンソールにいろいろ出せるとデバッグがしやすいので、これはこれでよいと思うのだよ。
汝の名はBlueZ - (10) : gatttoolをいじる
GLibのイベントループのことを調べたけど、gatttoolで状態を持ってるのは接続のことだけで、primaryとかの非同期コマンドの実行状態などは管理していない。
なので、これが終わったらこれしたい、というようなことをやりたいのであれば、実行状態を持つように書き換えがいる。
追加するのは、コマンドの開始時と、完了コールバックのところになるだろう。
それを全部に対してやるくらいだったら、コールバック関数のところに自分の関数を呼ぶように作り替えてしまえば、わざわざ何も無いときにポーリングするような作りにしなくても済みそうだ。
だが、処理は1箇所にまとめたいので、ポーリングするようにしようかとも思っている。
まずはサンプルとして、TIのSensorTag向けに作ってみよう。
SensorTagはいろいろとセンサーが付いているので、題材として使いやすい。
Characteristicを読んだり書いたりするだけだったら、別にコードを作り込まずともコマンドを入力すれば良い。
今回の目指すところは、こんなところにしよう。
- ボタンを押したらNotifyを受け取り、押されたのがS2かS3かをコンソールに出力する
- インタラクティブモードで起動し、開始コマンド(自作)を打ち込んだら、後は勝手にやってくれる
たったこれだけ?と思われそうだが、準備運動せずに海に飛び込んではだめなのだ。
connectやCharacteristicへの操作はコマンドを打ち込むが、Notificationはどうなってるのか知らなかった。
調べたところ、受けとったらコンソールに出力されるようだ。
SensorTagで試してみた。0x6CはボタンのNotificationを許可設定するCCCDで、01:00で許可になる。
[34:B1:F7:D4:FA:33][LE]> char-write-req 6c 0100
Characteristic value was written successfully
Notification handle = 0x006b value: 01
Notification handle = 0x006b value: 00
この辺を受け付けられるところがGLibを使った強みか。
受けとっているのは、interactive.cのevents_handler()。
コンソール出力からソースをgrepできるのがありがたい。
events_handler()は、connectが完了したコールバックで登録されている。
なので、connectの動作をgatttoolのルートでやってしまうなら、そのまま流用できる。
ただ、Characteristic操作と違って開始-終了がCentral側ではわからず通知だけになるので、ここはコールバック時に処理をした方がよいだろう。
2015年5月16日
GLibのイベントループ
BlueZのgatttoolを変更して、Central側の動作確認ツールを作ろうとしている。
まずはconnectさせて、connectしたらprimaryを見るだけのところを作っているのだが、これがなかなかうまくいかない。
connect実行後に接続状態を監視するスレッドを作って、本体はjoinで待たせている。
しかし、接続状態が変化しないのだ。
Peripheralは接続が完了しているので、connect自体は動いている。
volatileつけてなかったから最適化されてしまったのかと思ったが、そもそもconnect完了のコールバックが呼ばれていない。
おそらく、joinで待たせているためGLibのイベントループが動かず、コールバックが呼ばれないのだと思っている。
なので、状態監視しているスレッドの中でイベントループを回す関数でも呼び出してやればよいと思うのだが、それに該当するAPIが見つけられていない。
軽く調べておこう。
GLibの本家資料は、たぶんここだろう。
GNUかGNOME。
今回やりたイベントループのことは、ここになるか。
https://developer.gnome.org/glib/stable/glib-The-Main-Event-Loop.html#glib-The-Main-Event-Loop.description
イベントはファイルディスクリプタとタイムアウトとなっている。
Wikipediaの説明でもそう書いてあるので、そうなんだろう。
なので、今回やりたいような「この変数がこの値になったら」みたいなのはイベントにできなさそうだ。
そういうことをしたければ、自分でfdつくって値の変更タイミングで書込むイベントにするか、タイマで監視するようなしくみにするか・・・。
APIを見てると、g_idle_add()というのがあった。
優先度の高いイベントが無いときに呼ばれるそうだ。
試しにやってみると、確かにそういう動きをする。
何かイベントが発生し終わったときに呼ばれるのではなく、アイドル状態だったら呼び出され続けるようだ。
"add"なので、BlueZでアイドル状態を監視するようになっていたとしても追加できる。
このAPIは呼び出していないのだが、g_idle_add()は使えた。
BlueZをgrepしても出てこないので、たぶん誰も呼び出していないのだが、それでよいのだろうか?
こちらを見て気付いたのだが、g_main_context_iteration()を呼ぶことでイベントループを1回だけ回せるようだ。
PyGTKで重い処理をしているときにGUIを固まらせないための手法をまとめる - 試験運用中なLinux備忘録
そういう視点でGLib Referenceを読むと、Descriptionにアイドルのこともシングルなイベントループ呼び出しのことも書いてあった。
英語を読む力が弱いのは課題だな・・・。
callとinvoke
英語の話になるが、callとinvokeの違いがよくわからない。
なんとなく、callだと直接呼び出し、invokeだと別コンテキストから呼び出すような感じを受ける。
invokeの意味 - 英和辞書 - 英語辞書 - goo辞書
たぶんラテン語が語源になってるのだろうが、「上に呼びかける」ということで、お祈りする意味があったようだ。
なので、OSとかフレームワークとかにお願いしておく、みたいなとらえ方で良いのかな。
2015年5月11日
[bluez]gatttoolを切り離してビルド
直接BlueZとは関係が無いので、タイトルはいつものとは別にした。
pythonで書こうかと思っていたのだが、gatttoolのコンソール出力を使って判断する、というのがどうもしっくりこない。
ツールが出力するログが変わったら、ソースの修正が必要になるので、そうそう変わるものではないとわかってはいるのだが、やる気が出なくなってしまった。
お仕事だったらあきらめてやるのだけど、せっかく趣味でやってるだけなんだから、やりたくないことはやらないようにしよう。
gatttoolはinteractiveじゃないモードもあるから、それでやるならpythonでもよいかと思ったのだが、1回実行するごとにconnect→操作→disconnect、となるようなので、ちょっと期待と異なる。
connectしたら、しばらくはdisconnectしたくないのだ。
だからinteractiveモードを使うんだろうけど、今回はそれを使いたくない。
だったら、自分で作るしかない。
BlueZのtestディレクトリにpythonで書かれたものがあったが、あれはD-Busを使っているようだ。
D-Busがよくわかっていないから何とも言えないが、軽く調べた範囲ではC言語から使うのはめんどくさそうだ。
じゃあpythonでやろうかとも思ったのだが、Characteristicを操作するようなサンプルがない・・・。
ドキュメントにはgatt-api.txtというのがあり、API仕様っぽいものが書かれているのだけど、D-Busがわかっていないためか見てもさっぱりわからない。
ネットで検索しても、これを使っていそうなサンプルを見つけることが出来なかった。
「なら私が!」と思えれば良いのだけど、ちょっと厳しい。
じゃあ、やっぱりC言語でやるか。
どうせ個人用のツールなので、gatttoolを変更するだけで済ませようと思う。
まずは準備として、gatttoolをBlueZのmakeではなく自分のmakeで行えるようにする。
attribディレクトリを別の場所にコピーし、Makefileを自作して、makeするだけ。
Makefileを作るのに時間がかかったのと、gatt.cがbluetooth.hをうまくincludeしないようだったので明示的に書いた(書く場所を上の方にしておかないと、なぜか読み込んでいなかったようだ)。
ソースとbluetooth、readline、GLibのリンクだけで済むかと思ったら、BlueZビルド時にできるbluetool-internalとshared-glibもリンクしないといかんようだった。
できればBlueZをインストールするときにコピーされるライブラリだけで構成したいのだが、知識が足りないので今回はこのままにしておこう。