Logo address

XBee (3)

2023/07/30

はじめに

以下では Plan9 用に開発した、XBee 用のソフトウェア att.luaapi.lua を紹介する。

Location

att.luaapi.lua
http://p9.nyx.link/netlib/xbee/ に置かれている。

Ref

[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
これが一番基本的。

att.lua and api.lua

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.luaquit あるいはキーボード割り込みで終了するように設計されている。
あるいはどちらも、他の Window から att.luaapi.lua に対して、 kill コマンドを発行してもよい。

非同期通信では、1つの process が何かの理由で終了したときに、他の process も終了させる必要がある。もちろん kill コマンドがあるが、人手の介入は好ましくはない。しかし自動化するのはかなり難しい。幸い Plan9 はこの点は良くできている。問題は(C ではなく) Lua で書かれていることにある。Lua は割り込み制御に関してはかなり窮屈なのである。実験によると、この場合にも api.lua は何とかなっているようだが、また完璧ではないかも知れない。

なお Plan9 には kill に関するコマンドは

がある。この順に強くなる。なぜ弱い kill が存在するのか? 仕事中の process に終了命令を下したときに、後片付けをして終了してくれるのが望ましい。弱い kill は後片付けを促しているのである。

実行

api.lua を展開したディレクトリで 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 の部分は環境に依存する。
目的に応じでメニューを選ぶ。

dump.lua

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 を調べるコマンド ATVRdump.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 のネットワークを構成している全てのノード
にも同様の処理をしておく。これで次の ATND の表示が見やすくなる。

なお 16bit アドレス addr16 の方は XBee がリセットされると保持されない。この現象は次の実験においても現れている。

現在のところ dump.lua はすべての応答には対応していない。対応しているのは、筆者が経験した応答だけである。

ATND

ATND は無線で接続している XBee たちがどのような親子関係にあるか示してくれる。
MYMP の意味は次の通りである。

これらは各々 ATMY, ATMP コマンドで得られる値であるが、マニュアルによれば ATMP コマンドの対象は EndDevice のみである! Coordinator に対して発行すると Error が帰る。Router に対して発行すると FFFE が返ってくる。Router の親を考えることは意味がないと考えているのだろう。なお addr16 = 0000 は Coordinator を意味する。

XBee の親子関係は MYMPNI に注目していれば辿っていける。次は 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

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" オプションを添える。

ATIR to xbeeC

interval を 60秒として xbeeC にサンプリング送信を要請する。
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

Zigbee Transmit Request/Status

XBee に対するリクエストは必ずしも AT コマンドを通じて行われる訳ではない。API モードでは frame type によってリクエストが行われることもある。文献[4]の "Zigbee Transmit Request" がそれである。このリクエストは remote XBee に対して何かメッセージを送るのに使われる。api.lua では二重引用符に続けて送りたいメッセージを書けばよいように設計されている。例えば xbeeC にメッセージ "abc" を送るのであれば

dest 0013A200:40A74509
"abc
とする。

このリクエストの応答にはデバッグに役に立つ情報が含まれている。すなわち応答には

が含まれている。

しかし、送信されたメッセージは何の役に立ち得るのか? 解り難いものがあるので、実験してみた。

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
and select:
api.lua -p /mnt/consoles/usb9 | dump.lua
and wait messages to xbeeG, where "usb9" depends on the system.

on Hebe execute:

setup
and select:
api.lua -p /mnt/consoles/usb6 | dump.lua
where "usb9" depends on the system.
And release command:
dest 0013A200:4072167C
"abc
the reponse is:
* 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	5F
Note that "616263" is the internal code of "abc" which is sent to Eee.

さて問題は、メッセージが送られるとして、そのことが何の役に立つのか? 良く解らないいことにある。
メッセージを受け取る XBee がプロセッサを持っていれば、大いに役に立つだろう。しかしその場合には消費電力が大きくなる。大きな消費電力を許容できるのなら、メッセージを送るもっと良い他の手段、例えば WiFi などが存在するだろう。そういうわけで、"Zigbee Transmit Request/Status" は我が家ではデバッグ以上の使い方は有りそうない。