chakokuのブログ(rev4)

日々のごった煮ブログです

MicroPython版 BLEで試作(Ver1.13 2020/9/02ビルド)

MicroPython版BLEライブラリでPeripheralを書いてみた。スマフォから接続すると瞬間に切れる。。なぜだろう。。
(ソース抜粋)

#//Service	     03B80E5A-EDE8-4B33-A751-6CE34EC4C700
#//Characteristic    7772E5DB-3868-4112-A1A9-F2669D106BF3

MIDI_SRV_UUID = bluetooth.UUID('03B80E5A-EDE8-4B33-A751-6CE34EC4C700')
MIDI_CHR_UUID = bluetooth.UUID('7772E5DB-3868-4112-A1A9-F2669D106BF3')

payload = advertising_payload(
    #name="BLE MIDI 0.01",
    #services=[bluetooth.UUID(0x181A)],
    services=[MIDI_SRV_UUID],
)
BLE_MIDI_CHR = (MIDI_CHR_UUID, bluetooth.FLAG_READ | bluetooth.FLAG_NOTIFY)
BLE_MIDI_SERVICE = (MIDI_SRV_UUID, (BLE_MIDI_CHR,))
SERVICES = (BLE_MIDI_SERVICE, )

bt = bluetooth.BLE()
bt.irq(bt_irq)
bt.active(1)
((midi,),) = bt.gatts_register_services(SERVICES)
bt.gap_advertise(100,adv_data=payload)

print(payload)
print(decode_name(payload))
print(decode_services(payload))

実行結果

GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0
bytearray(b'\x02\x01\x06\x11\x07\x00\xc7\xc4N\xe3lQ\xa73K\xe8\xedZ\x0e\xb8\x03')

[UUID128('03b80e5a-ede8-4b33-a751-6ce34ec4c700')]
>>> --- BT IRQ ---
1
_IRQ_CENTRAL_CONNECT
(0, 1, b'K\xea)\x95Fg')
stop advertise
--- BT IRQ ---
2
_IRQ_CENTRAL_DISCONNECT
(0, 1, b'K\xea)\x95Fg')
GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=0 adv_itvl_max=0
--- BT IRQ ---

一度接続できるが、すぐに切れる。多分、Client側で異常と判断して切りに来ている。。先人の動くサンプルをベースに修正しないと、手探りで作っても動かないと思われる。。
サンプルの ble_temperature.pyを動かしてみたけど、やはり、接続>切断となる。だから、、Pythonプログラムの問題ではなく、BLEライブラリ側がおかしいのでは?と無責任に推測*1*2

GAP procedure initiated: stop advertising.
GAP procedure initiated: stop advertising.
GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=800 adv_itvl_max=800
IRQ
Central Connect
IRQ
Central Disconnect
GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=800 adv_itvl_max=800

使ったのは以下の通り、2020/9/02ビルドのVer1.13 ( esp32-idf4-20200902-v1.13.bin)

>>> uos.uname()
(sysname='esp32', nodename='esp32', release='1.13.0', version='v1.13 on 2020-09-02', machine='ESP32 module with ESP32')

問題切り分けのため、ファームバージョンをV1.12にさげてみる。
esp32-idf4-20191220-v1.12.binを使って再度テスト実施
ble_temperature.pyを動かすと、V1.12でもやはり接続後すぐに切れる。なぜか?? 昔動かした時はすんなり動いた記憶があるのだが。

■追記
別のiPhoneだと正常に接続できた。よって異常動作はiPhone依存のようであった。どうもOS側で過去に接続したBLE Peripheralを記憶していて、いろいろ設定を変えるとその設定との不一致が起きるのか、iPhoneが想定する設定と違うせいか、その辺りで、OS側でNGと判断しているようである(推測)。そのように考える根拠として、、Peripheralの名称を変えたのに、BLEスキャナでは、ずっと古い名称が表示されていて、どこかにキャッシュした情報で補完していると推測できる。回避策として、iOSの設定画面から、古いBLE設定を消して再度試すと、BLEの動作が多少安定した。

■追記
iOS上で動くフリーのBLEスキャナは複数使っていて、それぞれ動作が違っていた。一度動き出すと、他のツールも段々と調子が良くなって、最終的にはどのスキャナでも通信が確立してNotifyで送られてくる温度を取れるようになった。推測だけどiPhoneのOS側で過去に通信して得られたPeripheral情報をcacheして補完してそうなのと、直接通信パケットを見れてないので、動作が安定しない根本原因が分からない。

■追記
ふろに入っていて気づいたのだが、、iPhoneのOS側でBLEペリフェラルを覚えていたというのは、BLEのペアリング設定が残ったままで、EPS32側の設定を変えてしまったからでは?と思う。だったら、iOS側は古い情報を期待して接続に来るのに、ESP32側ではサービスUUIDもアトリビュートのUUIDも変わっていたらエラーにするだろうと想像できる。教訓として、、BLEスキャナで古いペリフェラル名が出てきたらiOSでペアリング設定が残っていないかを再確認すべし

■追記
iPhone上で動作するBLEスキャナでは見えるようになったが、iOSの設定>Bluetoothでデバイスが表示されない。なぜだろうか?? アドバタイズのオプションがまずいのか?

GAP procedure initiated: advertise; disc_mode=2 adv_channel_map=7 own_addr_type=0 adv_filter_policy=0 adv_itvl_min=800 adv_itvl_max=800

■ご参考記事
キャッシュしているという記事(ただしデバイス名だけ)
BLE機器のデバイス名を変更してもiOSから見えるデバイス名が変わらない - Qiita


ble-midi/Apple-Bluetooth-Low-Energy-MIDI-Specification.pdf at master · skratchdot/ble-midi · GitHub

*1:追記:ファームウエア側の問題ではなく、テストで使っているiOS側のキャッシュが悪さしてるのでは?と推測

*2:iOSでBLEの古いペアリング情報が残ったまま、次のテスト(俺MIDI->Temperature等への変更)に進んだからではないかと判断