以下では Plan9 用に開発した、XBee 用のソフトウェア att.lua
と api.lua
を紹介する。
att.lua
と api.lua
は
http://p9.nyx.link/netlib/xbee/
に置かれている。
[1] 濱原、佐藤「超お手軽無線モジュールXBee」(CQ出版社)
注釈: これが一番詳しいが、特殊なハード環境を想定している。また重要な説明を欠いていることがある。
[2] Robert Faludi (小林、水原訳)「XBee で作るワイヤレスセンサーネットワーク」(O’REILLY)
注釈: ZigBee ネットワークを概念的に知るのに良い。
[3] 鄭立「ZigBee 開発ハンドブック」(リックテレコム, 2012)
注釈: XBee コマンドリファレンスが載っていない!
[4] Digi International: "Zigbee RF Modules User Guide"
https://www.digi.com/resources/documentation/digidocs/pdfs/90000976.pdf
これが一番基本的。
I have rewritten att.c
and api.c
in Lua (9lua).
NB: needs 9lua released on 2023/07/28 or later.
att.c ==> att.lua
api.c ==> api.lua -p
api.lua ==> api.lua
att.lua
は、透過モード用の通信プログラムである。シリーズ1の XBee を対象にしている。普通の通信プログラムと同様に、2つの process が平行に(つまり非同期に)動作する。これには 9lua の能力が要求される。
api.lua
は APIモード用の通信プログラムである。主にシリーズ2以降の XBee を対象にしている。これまでは非同期通信は xbee/app
で、同期通信は api.lua
で行っていたのであるが、これを1つに纏めた。すなわち "-p
" flag の下で, api.lua
は非同期で動作する。この場合、2つの process が並行して動作する。キーボードを読み取る process と XBee からの応答を読み取る process である。"-p
" は parallel の p であるが、"no prompt" の p でもある。
"-p
" flag を添えない場合には、api.lua
はこれまで通りの動作をする。すなわち同期通信であり、prompt ">
" を表示する。
att.lua
はキーボード割り込みで、api.lua
は quit
あるいはキーボード割り込みで終了するように設計されている。att.lua
や api.lua
に対して、 kill
コマンドを発行してもよい。
非同期通信では、1つの process が何かの理由で終了したときに、他の process も終了させる必要がある。もちろん kill
コマンドがあるが、人手の介入は好ましくはない。しかし自動化するのはかなり難しい。幸い Plan9 はこの点は良くできている。問題は(C ではなく) Lua で書かれていることにある。Lua は割り込み制御に関してはかなり窮屈なのである。実験によると、この場合にも api.lua
は何とかなっているようだが、また完璧ではないかも知れない。
なお Plan9 には kill に関するコマンドは
kill
- slay
- Kill
setup
を実行すると今度は# select: # getdataB # getdataB.rc # getdataC # getdataC.rc # att.lua /mnt/consoles/usb6 # api.lua /mnt/consoles/usb6 # api.lua -p /mnt/consoles/usb6 | dump.luaのメニューが表示される。
usb6
の部分は環境に依存する。
api.lua
では、XBee からの応答はすべて 16 進数の列である。しかし、16進数の列は余程慣れていないと理解できない。その都度、本やマニュアルを読みながら解読していくことになる。この問題を緩和するために dump.lua
を開発した。
dump.lua
は普通の Lua で書かれているので、Lua が動く環境があれば使える。しかし、Digi が提供するツール XCTU
は、見栄え良く作られてはいるが機能的ではない。XCTU
の出力から XBee の応答部分を取り出すのに苦労するだろう。従って勉強にはならない。
使い方の例を示す:
atvr 7E 00 04 08 01 56 52 4E * 7E 00 07 88 01 56 52 00 21 A7 06 hebe# s='* 7E 00 07 88 01 56 52 00 21 A7 06' hebe# echo $s | dump.lua * 7E 00 07 88 01 56 52 00 21 A7 06 delim 7E length 0007 7 ftype 88 fid 01 addr64 nil addr16 nil cname 5652 VR status 00 OK cdata 21A7 chksum 06 hebe#
この例では XBee の firmware version を調べるコマンド ATVR
を dump.lua
を使って解析している。この例は AT コマンドをローカルな XBee に発行した場合の典型的な応答フレーム(frame type 88
)である。XBee に関する殆どのテキストには、このフレームの意味が解説されているはずである。
dump.lua
は XBee からの応答、すなわち "*
" で始まる行のみに作用する。従って api.lua
の出力を dump.lua
に pipe で渡す事によって16進数の意味が解り易くなる。例えば
hebe# api.lua -p /mnt/consoles/usb6 | dump.lua ATVR 7E 00 04 08 01 56 52 4E * 7E 00 07 88 01 56 52 00 21 A7 06 delim 7E length 0007 7 ftype 88 fid 01 addr64 nil addr16 nil cname 5652 VR status 00 OK cdata 21A7 chksum 06 DEST 0013A200:40A74509 ATNI xbeeC 7E 00 14 17 03 00 13 A2 00 40 A7 45 09 FF FE 02 4E 49 78 62 65 65 43 7E * 7E 00 0F 97 03 00 13 A2 00 40 A7 45 09 88 00 4E 49 00 5C delim 7E length 000F 15 ftype 97 fid 03 addr64 0013A20040A74509 addr16 8800 cname 4E49 NI status 00 OK cdata chksum 5C僕は拡張 MAC
0013A200:40A74509
の XBee には紙ラベル "xbeeC
" を貼り付けている。それと類似のことをソフト的に行ったのである。XBee のネットワークを構成している全てのノードxbeeC
(0013A200:40A74509
) -- EndDevicexbeeD
(0013A200:40ADD45D
) -- EndDevicexbeeG
(0013A200:4072167C
) -- RouterxbeeE
(0013A200:40A74607
) -- CoordinatorATND
の表示が見やすくなる。
なお 16bit アドレス addr16
の方は XBee がリセットされると保持されない。この現象は次の実験においても現れている。
現在のところ dump.lua
はすべての応答には対応していない。対応しているのは、筆者が経験した応答だけである。
ATND
は無線で接続している XBee たちがどのような親子関係にあるか示してくれる。
MY
と MP
の意味は次の通りである。
MY
: my addr16
MP
: my parent addr16
ATMY
, ATMP
コマンドで得られる値であるが、マニュアルによれば ATMP
コマンドの対象は EndDevice のみである! Coordinator に対して発行すると Error が帰る。Router に対して発行すると FFFE
が返ってくる。Router の親を考えることは意味がないと考えているのだろう。なお addr16 = 0000
は Coordinator を意味する。
XBee の親子関係は MY
と MP
と NI
に注目していれば辿っていける。次は http:index2.html
の図3 のネットワークに対して ATND
を発行した結果である。なお ATND
は同期プログラムでは動かないことに注意。("-p
" flag を添えた理由)
DEST local ATND 7E 00 04 08 12 4E 44 53 * 7E 00 1D 88 12 4E 44 00 72 74 00 13 A2 00 40 AD D4 5D 78 62 65 65 44 00 00 00 02 00 C1 05 10 1E 3C delim 7E length 001D 29 fdata 88 12 4E 44 00 72 74 00 13 A2 00 40 AD D4 5D 78 62 65 65 44 00 00 00 02 00 C1 05 10 1E 3C ftype 88 fid 12 addr64 nil addr16 nil cname 4E44 ND status 00 OK cdata 72740013A20040ADD45D78626565440000000200C105101E MY 7274 SH 0013A200 SL 40ADD45D NI 786265654400 xbeeD MP 0000 dev 02 (01:router 02:enddev) status 00 pid C105 mid 101E chksum 3C * 7E 00 1D 88 12 4E 44 00 D8 77 00 13 A2 00 40 72 16 7C 78 62 65 65 47 00 FF FE 01 00 C1 05 10 1E AE delim 7E length 001D 29 fdata 88 12 4E 44 00 D8 77 00 13 A2 00 40 72 16 7C 78 62 65 65 47 00 FF FE 01 00 C1 05 10 1E AE ftype 88 fid 12 addr64 nil addr16 nil cname 4E44 ND status 00 OK cdata D8770013A2004072167C786265654700FFFE0100C105101E MY D877 SH 0013A200 SL 4072167C NI 786265654700 xbeeG MP FFFE dev 01 (01:router 02:enddev) status 00 pid C105 mid 101E chksum AE * 7E 00 1D 88 12 4E 44 00 68 64 00 13 A2 00 40 A7 45 09 78 62 65 65 43 00 D8 77 02 00 C1 05 10 1E F1 delim 7E length 001D 29 fdata 88 12 4E 44 00 68 64 00 13 A2 00 40 A7 45 09 78 62 65 65 43 00 D8 77 02 00 C1 05 10 1E F1 ftype 88 fid 12 addr64 nil addr16 nil cname 4E44 ND status 00 OK cdata 68640013A20040A74509786265654300D8770200C105101E MY 6864 SH 0013A200 SL 40A74509 NI 786265654300 xbeeC MP D877 dev 02 (01:router 02:enddev) status 00 pid C105 mid 101E chksum F1これから親子関係を調べるために必要な情報を取り出すと
MY 7274 NI 786265654400 xbeeD MP 0000 MY D877 NI 786265654700 xbeeG MP FFFE MY 6864 NI 786265654300 xbeeC MP D877となろう。Coordinator は
xbeeE
であった。従ってこの結果から得られたネットワークの親子関係はxbeeE → xbeeD
xbeeE → xbeeG → xbeeC
ATIR
コマンドも非同期を要する。
(a) ATIR
-- interval
の内容を見る
(b) ATIR interval
-- interval
でサンプリングの送信周期を設定する。
interval
の範囲: 0x32 - 0xFFFF
単位は mili sec
ATIR 4FF -- set IR to 1 sec ATIR F0FF -- set IR to 60 sec ATIR FFFF -- set IR to 255 sec
api.lua
の起動に "-p
" オプションを添える。
hebe# api.lua -p /mnt/consoles/usb6 | dump.lua dest 0013A200:40A74509 atir F0FF 7E 00 11 17 17 00 13 A2 00 40 A7 45 09 FF FE 02 49 52 F0 FF 5E * 7E 00 0F 97 17 00 13 A2 00 40 A7 45 09 68 64 49 52 00 00 delim 7E length 000F 15 fdata 97 17 00 13 A2 00 40 A7 45 09 68 64 49 52 00 00 ftype 97 fid 17 addr64 0013A20040A74509 addr16 6864 cname 4952 IR status 00 OK cdata chksum 00 * 7E 00 14 92 00 13 A2 00 40 A7 45 09 68 64 01 01 00 10 01 00 00 02 DA C8 delim 7E length 0014 20 fdata 92 00 13 A2 00 40 A7 45 09 68 64 01 01 00 10 01 00 00 02 DA C8 ftype 92 addr64 0013A20040A74509 addr16 6864 option 01 header 01 dmask 0010 amask 01 ddata 0000 adata 02DA
XBee に対するリクエストは必ずしも AT コマンドを通じて行われる訳ではない。API モードでは frame type によってリクエストが行われることもある。文献[4]の "Zigbee Transmit Request" がそれである。このリクエストは remote XBee に対して何かメッセージを送るのに使われる。api.lua
では二重引用符に続けて送りたいメッセージを書けばよいように設計されている。例えば xbeeC にメッセージ "abc" を送るのであれば
dest 0013A200:40A74509 "abc
このリクエストの応答にはデバッグに役に立つ情報が含まれている。すなわち応答には
0x00 = Success
0x01 = MAC ACK Failure
0x02 = CCA Failure
0x15 = Invalid destination endpoint
0x21 = Network ACK Failure
0x22 = Not Joined to Network
0x23 = Self-addressed
0x24 = Address Not Found
0x25 = Route Not Found
0x26 = Broadcast source failed to hear a neighbor relay the message
0x2B = Invalid binding table index
0x2C = Resource error lack of free buffers, timers, and so forth.
0x2D = Attempted broadcast with APS transmission
0x2E = Attempted unicast with APS transmission, but EE=0
0x32 = Resource error lack of free buffers, timers, and so forth.
0x74 = Data payload too large
0x00 = No Discovery Overhead
0x01 = Address Discovery
0x02 = Route Discovery
0x03 = Address and Route
0x40 = Extended Timeout Discovery
しかし、送信されたメッセージは何の役に立ち得るのか? 解り難いものがあるので、実験してみた。
Experient below needs two PCs, Hebe and Eee, which are running on Plan9.
We assume that xbee tools are already installed to them.
XBee coordinator xbeeE is connected to Hebe
and also XBee router xbeeG is connected to Eee
on Eee execute:
setup
api.lua -p /mnt/consoles/usb9 | dump.lua
on Hebe execute:
setup
api.lua -p /mnt/consoles/usb6 | dump.lua
dest 0013A200:4072167C "abc
* 7E 00 07 8B 03 D8 77 90 00 00 92 delim 7E length 0007 7 fdata 8B 03 D8 77 90 00 00 92 ftype 8B fid 03 addr16 D877 nretry 90 delistat 00 Success discstat 00 No Discovery Overhead chksum 92
and you will see a message "abc" on Eee:
* 7E 00 0F 90 00 13 A2 00 40 A7 46 07 00 00 01 61 62 63 5F delim 7E length 000F 15 fdata 90 00 13 A2 00 40 A7 46 07 00 00 01 61 62 63 5F ftype 90 addr64 0013A20040A74607 addr16 0000 option 01 data 616263 chksum 5FNote that "
616263
" is the internal code of "abc" which is sent to Eee.
さて問題は、メッセージが送られるとして、そのことが何の役に立つのか? 良く解らないいことにある。
メッセージを受け取る XBee がプロセッサを持っていれば、大いに役に立つだろう。しかしその場合には消費電力が大きくなる。大きな消費電力を許容できるのなら、メッセージを送るもっと良い他の手段、例えば WiFi などが存在するだろう。そういうわけで、"Zigbee Transmit Request/Status" は我が家ではデバッグ以上の使い方は有りそうない。