nRF52840 DKで遊ぼう③~Bluetooth Mesh Serial example~

はじめに

nRF5 SDK for MeshのSerial exampleを試します。

|> nRF5-SDK-for-Mesh/examples/serial

www.nordicsemi.com

PyACI

本アプリケーションをテストするためには、Pythonインタラクティブアプリケーションが必要です。 下記の手順に沿って、インストールします。

www.nordicsemi.com

# nRF5-SDK-for-Mesh/scripts/interactive_pyaci
$ pip3 install -r requirements.txt

次のようなコマンドで、インタラクティブシェルを起動します。

$ sudo python3 interactive_pyaci.py -d /dev/ttyACM0

    To control your device, use d[x], where x is the device index.
    Devices are indexed based on the order of the COM ports specified by the -d option.
    The first device, d[0], can also be accessed using device.

    Type d[x]. and hit tab to see the available methods.

Python 3.5.2 (default, Nov 12 2018, 13:43:14) 
Type 'copyright', 'credits' or 'license' for more information
IPython 7.3.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]:

Serial exampleのビルドとFlash

nRF5 SDK for Meshを丸ごとビルドしてあるため、ビルド済みのバイナリを使います。

# nRF5-SDK-for-Mesh/build/examples/serial
nrfjprog -f nrf52 --program serial_nrf52840_xxAA_s140_6.1.0.hex
nrfjprog --reset -f nrf52

動作確認

と、ここまでは良かったのですが、イマイチ使い方が良く分かりません。 これで、pythonインタラクティブシェルからBluetooth Meshが使えるはずですが…?

loopback

ということで、単純なループバックから試していきます。

www.nordicsemi.com

今、開発キットは、/dev/ttyACM0として見えています。

$ sudo python3 interactive_pyaci.py -d /dev/ttyACM0 --no-logfile
...
In [1]: d[0].send(cmd.Echo("hello world"))                                      

2019-03-07 13:01:04,976 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'hello world')}}

無事、開発キットからエコーが返ってきました。

Sending mesh packets

ここからは開発キットが2台必要です。Serial exampleを2台ともに書き込み、USBを念のため再接続しておきます。

$ ls /dev/ttyACM*
/dev/ttyACM0  /dev/ttyACM1

インタラクティブシェルでは、d[0], d[1]として、それぞれアクセス可能です。

In [1]: d[0].send(cmd.Echo("hello world"))                                      

2019-03-07 13:08:56,964 - INFO - ttyACM0: {event: DeviceEchoRsp, data: {'data': bytearray(b'hello world')}}
In [2]: d[1].send(cmd.Echo("hello world"))                                      

2019-03-07 13:09:01,203 - INFO - ttyACM1: {event: DeviceEchoRsp, data: {'data': bytearray(b'hello world')}}

www.nordicsemi.com

まずは、開発キットを初期化します。pythonで書けるので、次のようにできます。

In [3]: for dev in d: dev.quick_setup()                                         

2019-03-07 13:12:19,267 - INFO - ttyACM1: SubnetAdd: {'subnet_handle': 0}
2019-03-07 13:12:19,268 - INFO - ttyACM0: SubnetAdd: {'subnet_handle': 0}
2019-03-07 13:12:19,277 - INFO - ttyACM0: AppkeyAdd: {'appkey_handle': 0}
2019-03-07 13:12:19,278 - INFO - ttyACM1: AppkeyAdd: {'appkey_handle': 0}
2019-03-07 13:12:19,287 - INFO - ttyACM1: Success
2019-03-07 13:12:19,288 - INFO - ttyACM0: Success

アドレスのpublicationを開始します。

In [4]: d[0].send(cmd.AddrPublicationAdd(d[1].local_unicast_address_start))     
2019-03-07 13:24:21,392 - INFO - ttyACM0: AddrPublicationAdd: {'address_handle': 0}

In [5]: d[1].send(cmd.AddrPublicationAdd(d[0].local_unicast_address_start))     
2019-03-07 13:24:32,687 - INFO - ttyACM1: AddrPublicationAdd: {'address_handle': 0}

ここで、address_handleは後程使うため、変数に格納しておきます。

In [6]: publish_handle = 0
In [7]: appkey_handle = 0

PacketSend()で使うための変数を定義します。

In [8]: ttl = 1
In [9]: segmented = 0
In [10]: mic_size = 0
In [11]: friendship_credentials_flag = 0

お互いにデータを送り合ってみます。まず、ttyACM0に繋がっているデバイスから、ttyACM1へパケットを送信します。

In [12]: d[0].send(cmd.PacketSend(appkey_handle, d[0].local_unicast_address_start, publish_handle, ttl, segmented, mic_size, friendship_credentials_flag, "Hello World"))

2019-03-07 13:29:22,257 - INFO - ttyACM0: PacketSend: {'token': 1}     
2019-03-07 13:29:22,269 - INFO - ttyACM0: {event: MeshTxComplete, data: {'token': 1}}
2019-03-07 13:29:22,270 - INFO - ttyACM1: {event: MeshMessageReceivedUnicast, data: {'src': 1, 'dst': 2, 'adv_addr': bytearray(b'\xf1\x9b\\\xd9\xc4\xcd'), 'adv_addr_type': 1, 'rssi': -27, 'data': bytearray(b'Hello World'), 'subnet_handle': 0, 'actual_length': 11, 'ttl': 1, 'appkey_handle': 0}}

次は、逆方向にパケットを送信します。

In [13]: d[1].send(cmd.PacketSend(appkey_handle, d[1].local_unicast_address_start, publish_handle, ttl, segmented, mic_size, friendship_credentials_flag, "Hi there"))                                          

2019-03-07 13:31:16,541 - INFO - ttyACM1: PacketSend: {'token': 1}     
2019-03-07 13:31:16,542 - INFO - ttyACM1: {event: MeshTxComplete, data: {'token': 1}}
2019-03-07 13:31:16,543 - INFO - ttyACM0: {event: MeshMessageReceivedUnicast, data: {'src': 2, 'dst': 1, 'adv_addr': bytearray(b')\na\xbbQ\xd4'), 'adv_addr_type': 1, 'rssi': -25, 'data': bytearray(b'Hi there'), 'subnet_handle': 0, 'actual_length': 8, 'ttl': 1, 'appkey_handle': 0}}

他にもインタラクティブにProvisioningしたり、pub/subできるようです。 だいたい勘所はわかったので、ここまでにします。