- <NWK_SIMPLE> - 非常にシンプルな簡易中継ネットワークです。
- <NWK_LAYERED> - レイヤー補助を用いた簡略化された木構造ネットワーク。(注:MWXは受信のみのパラントノードしかサポートしていません。)
セクションの複数ページをまとめています。 印刷またはPDF形式で保存...
ネットワークビヘイビア (NWK)
1 - シンプル中継ネット <NWK_SIMPLE>
auto&& nwksmpl = the_twelite.network.use<NWK_SIMPLE>();
nwksmpl << NWK_SIMPLE::logical_id(0xFE)
<< NWK_SIMPLE::repeat_max(3);
上記はネットワークの利用宣言と設定例です。詳細は後述しますが、ネットワークのアドレスについての考え方など基本的な内容をまず解説します。
このネットワークでの各無線局は8bitの論理IDで識別されます。この値は起動時に各無線局が独自に設定します。論理IDは重複しても構いませんが、重複したことを前提とした通信を行う必要があります。
各無線局のIDを設定します。通常はネットワークには親機の役割の無線局と子機の役割の無線局を配置します。子機のみのネットワークも運用できます。
また子機は中継機の役割にもなります。
無線局の識別ID | 役割 |
---|---|
0x00 | 親局 |
0x01 ..0xEF | 子局 |
0xFE | IDを割り振らない子局 |
論理IDを宛先として指定できますが、0xFE
,0xFF
は特別な意味を持ちます。下表に宛先指定についてまとめます。
宛先ID | 意味 |
---|---|
0x00 | 子局から親局を指定する。親局からの指定は無効。 |
0x01 ..0xEF | 特定の子局を指定する。 |
0xFE | すべての子局を指定する同報通信(ブロードキャスト)。 |
0xFF | すべての無線局を指定する同報通信(ブロードキャスト)。 |
また、無線局を特定するのに32bitで指定するシリアル番号も利用できます。
パケットの配送は、IEEE802.15.4のブロードキャストを用います。ACKを用いないため、配送の成功が送信元では判別できませんが、替わりに要求に合った成功率が得られる適当な再送回数を設定したうえ、到達確認が必要な場合は通常パケットの通信を用います。
大規模で頻繁な通信を行う場合は非効率に見えるかもしれませんが、もっぱらデータ収集のみを行い、比較的中継段数が少ないネットワークの場合などより効率的になる場合もあります。
またネットワークを構築するための通信を必要としないため、障害等例外的な状況においても全く通信が止まってしまうといったことが原理的に少なくなります。親機が受信状態かつ子機からの無線到達範囲にあって、子機がパケットを送信しさえすれば、多くの場合親機は受信できます。ネットワークの構築のために通信が必要なネットワークでは、一旦、設定情報などが失われた後は、再度親機と子機間の通信確立のための通信が完了しなければデータが送れません。ネットワークビヘイビア<NWK_SIMPLE>
がその命名にシンプルとしているのは、こういった理由があります。
このシンプルネットワークを動作させるためには、多くの場合複数回届く再送パケット(同一パケット)を無視する必要があります。<NWK_SIMPLE>
での同一パケットの識別は送信元のシリアル番号と送信時のパケットの続き番号によって行います(重複チェッカと呼びます)。続き番号は0..63として、順番に割り当てられ、近い時間に届くパケットの続き番号は近い番号であるという仮定を置いています。一定時間以上経過した番号的に遠い(今10番を受信したとしたら40番台のパケットはしばらく前に送信されたと考えられる)続き番号はタイムアウトとして重複対象から除外します。
重複チェッカでの考慮すべきことは以下になります。
- チェック可能な要素数(数を増やせばメモリ消費とチェックのための処理時間が増える)
- タイムアウト時間の設定
デフォルトではタイムアウトは1秒で、チェックする無線局の数は16です。つまり中継パケットがまわりまわって1秒以上経過した場合、重複パケットとみなされななくなります。また短期的に16を超える無線局からのパケットが到達した場合、超過した無線局については重複チェックが出来なくなります。
中継段数や段数が少なくとも中継局の数が多い場合、再送を非常に長い間隔で行う場合は、設定を考慮すべき場合もあります。
宣言・登録
ネットワークビヘイビア<NWK_SIMPLE>
を利用例を挙げます。
##include <TWELITE>
##include <NWK_SIMPLE>
void setup() {
...
auto&& nwk = the_twelite.network.use<NWK_SIMPLE>();
}
2行目で<NWK_SIMPLE>
の定義情報をインクルードします。7行目でthe_twelite
に<NWK_SIMPLE>
を登録します。
設定
<NWK_SIMPLE>
登録後に設定を行います。
void setup() {
auto&& nwksmpl = the_twelite.network.use<NWK_SIMPLE>();
nwksmpl << NWK_SIMPLE::logical_id(0xFE);
}
設定は<<
演算子で行います。
<<
演算子 (設定)
オブジェクトthe_twelite
の初期設定を行うために<<
演算子を用います。
以下に挙げる設定用のクラスオブジェクトを入力とし、設定をしなければデフォルト値が適用されます。
NWK_SIMPLE::logical_id(uint8_t id)
パラメータid
に指定した論理デバイスIDを設定します。デフォルトは0xFE
(ID未設定子機)です。
NWK_SIMPLE::retry_default(uint8_t val)
パラメータval
に指定した回数を送信時の再送回数のデフォルト値とします。
NWK_SIMPLE::repeat_max(uint8_t val)
パラメータval
に指定した回数を最大中継回数とします。デフォルトは2
です。
中継をさせたくない場合は0
を指定します。
NWK_SIMPLE::dup_check(uint8_t maxnodes, uint16_t timeout_ms, uint8_t tickscale)
重複パケットの検出アルゴリズムのパラメータです。
maxnodes
は履歴を保持するため無線局(ノード)の数です。ノード数を少なく設定した場合、短期間に設定以上のノードからのパケットが来た場合、重複除外できないノードが出てきます。重複除外できない場合、受信時に複数回データが表示される、必要以上に再中継してしまうといった問題が出ます。デフォルトは16
です。1ノード当たり21バイトメモリを消費します。timeout_ms
は履歴を抹消するまでのタイムアウト時間[ms]です。タイムアウトは続き番号のブロック単位で管理されていて、ブロック単位でタイムアウト処理が行われます。デフォルトは1000
[ms]です。tickscale
はタイムアウトを管理するための時間単位で2^tickscale
[ms]となります。時間は7bitで管理されるため、127*(2^tickscale) > timeout_ms
になるように設定します。デフォルトは5
(32ms)です。
NWK_SIMPLE::secure_pkt(const uint8_t *pukey, bool b_recv_plain_pkt = false)
暗号化パケットの有効化します。
pukey
は暗号化の鍵を 16バイト (128bit) で指定します。b_recv_plain_pkt
はtrue
を指定すると、同じアプリケーションID、チャネルの平文パケットを受信します。
packet_rx::is_secure_pkt()
が true
(暗号化) か false
(平文) で判定できます。STG_STD
インタラクティブモードの設定値を反映します。以下の値を反映します。
auto&& set = the_twelite.settings.use<STG_STD>();
auto&& nwk = the_twelite.network.use<NWK_SIMPLE>();
...
set.reload(); // 設定値をロード
nwk << set; // インタラクティブモードの設定値を反映
- logical_id
- retry_default
メソッド
prepare_tx_packet()
// 型名はpacket_tx_nwk_simple<NWK_SIMPLE>ですがauto&&と記載します。
auto&& preare_tx_packet()
//例
if (auto&& pkt =
the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {
...
pkt.transmit();
}
送信オブジェクトを取得します。オブジェクトはpacket_tx
の派生クラスになります。このオブジェクトに送信アドレスやペイロードを格納し.transmit()
メソッドで送信を行います。
このオブジェクトにはbool
演算子が定義されています。オブジェクト生成時にTWENETが送信要求を受け付けられない場合はfalse
を返します。
送信オブジェクト
.prepare_tx_packet()
メソッドにて取得した送信オブジェクトのメソッドです。
bool
演算子
operator bool()
// 例
if (auto&& pkt =
the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {
オブジェクト生成時にTWENETが送信要求を受け付けられない場合はfalse
を返します。
transmit()
MWX_APIRET transmit()
// 例
uint8_t txid;
if (auto&& pkt =
the_twelite.network.use<NWK_SIMPLE>().prepare_tx_packet()) {
...
MWX_APIRET ret = pkt.transmit();
if (ret) {
txid = pkt.get_value();
}
}
パケットの送信処理を行います。MWX_APIRET
がtrue
の場合に送信要求が成功ですが、この要求時点では送信処理が始まりません。
パケットの送信IDはMWX_APIRET
の.get_value()
で得られる値部に格納されます。the_twelite.tx_status.is_complete()
またはtransmit_complete()
より送信完了を確認できます。
パケット最大長と構造
パケットの最大長を以下に示します。宛先をLID(論理デバイスID)とした場合は、暗号化無しで91バイトまで含めることが可能です。
ネットワーク層 | 暗号化 | ペイロードの最大 |
---|---|---|
<NWK_SIMPLE> | なし | 91 |
<NWK_SIMPLE> | あり | 89 |
※ 将来のための予備として2バイト分は予備としています。ユーザの判断でこの予備バイトを利用することも可能です。
パケットの構造は以下のようになっています。
|MacH:XX[........................................]MacF:2|
TWENET:3[.....................]TwenetF:1
NWK_SIMPLE:11|PAYLOAD
(:nはバイト数)
1: MacH は IEEE802.15.4 MAC のヘッダ情報
2: TwenetH は TWENET 識別のための情報
3: NWK_SIMPLE は NWK_SIMPLEネットワークの制御情報
|Type:1|Src LID:1|Src Addr:4|Dest LID:1|Dst Addr:4|Repeat:1|
4: PAYLOAD はペイドード
5: TwenetF は CRC8 のチェックサム(TWENETパケットの弁別を目的とする)
6: MacF は CRC16 のMAC 層のチェックサム
2 - <NWK_LAYERED>
以下のように setup()
中で初期化します。NWK_LAYERED::ROLE_PARENT
として親機としてのロールを割り当てます。
##include <NWK_LAYERED>
void setup() {
...
auto&& nwk_ly = the_twelite.network.use<NWK_LAYERED>();
nwk_ly << NWK_LAYERED::network_role(NWK_LAYERED::ROLE_PARENT);
// set a role as parent.
}
パケットの受信が行われたときは、NWK_SIMPLE
と同様に on_rx_packet()
が呼び出されます。
void on_rx_packet(packet_rx& rx, bool_t &handled) {
auto type = rx.get_network_type();
if (type == mwx::NETWORK::LAYERED) {
; // レイヤーツリーネットのパケット
handled = true; // 処理済みにする
}
}
rx
はパケット情報をラップしたクラスです。内部的には _get_network_type()
の処理用の内部フラグを設定する以外はパケット情報等の加工は行っていません。
つまりtsRxDataApp*
を返すrx.get_psRxDataApp()
を参照すれば、TWENET C ライブラリと同様のパケット情報が得られます。packet_rx
はこの情報にアクセスするためのいくつかの手続きが定義されていますが、得られる情報に変わりはありません。
NWK_SIMPLE
との併用
NWK_SIMPLE
と併用する場合は、the_twelite.network
にNWK_LAYERED
を、the_twelite.newwork2
にNWK_SIMPLE
を割り当てます。
##include <NWK_LAYERED>
##include <NWK_SIMPLE>
void setup() {
...
auto&& nwk_ly = the_twelite.network.use<NWK_LAYERED>();
auto&& nwk_sm = the_twelite.network2.use<NWK_SIMPLE>();
}
void on_rx_packet(packet_rx& rx, bool_t &handled) {
auto type = rx.get_network_type();
if (type == mwx::NETWORK::LAYERED) {
; // レイヤーツリーネットのパケット
}
else if (type == mwx::NETWORK::SIMPLE) {
; // NWK_SIMPLE のパケット
}
else if (type == mwx::NETWORK::NONE) {
; // 通常のアプリ (App_Twelite など)
}
else {
; // 解釈できなかったもの
}
// パケットを処理済みにし、これ以上 MWX ライブラリの介入はしない。
handled = true;
}
各パケット種別は上記のように .get_network_type()
により判別します。
mwx::NETWORK::LAYERED
: そのままパケット情報を参照します。mwx::NETWORK::SIMPLE
:NWK_SIMPLE
の処理に倣います。mwx::NETWORK::NONE
: ネットワーク処理や重複パケットの処理など一切が行われません。例えば App_Twelite 標準アプリケーションの場合、例えば1送信ごとに再送を含め3パケットずつ送出されます。この際、すべてのパケットの受信が成功した場合on_rx_packt()
が3回呼び出されることになります。通常は、3回受信できたからと言って2回目、3回目のデータは必要ありません。こういった重複パケットの処理を追加する必要があります。
実例はAct_SamplesのRcv_Univsl
を参照してください。TWELITE PAL, Act_samples, App_Twelite といった無線チャネルとアプリケーションIDが同一だが、種別の違うパケットの受信処理しています。さらに App_Twelite のために重複チェッカーの処理も用意しています。