LoginSignup
0
1

More than 1 year has passed since last update.

MicroPythonにおけるBLEモジュールのTips

Last updated at Posted at 2021-11-23

はじめに

今回は前のBLEの実装作業の続きとして、BLEモジュールを使っていくつかのTipsを紹介します。本文にはubluetoothを使って送信時に必要なパケットの圧縮形式と受信で識別する時の識別子の話となります。
前回:
ESP32でBLEの実装作業【スキャン】
ESP32でBLEの実装作業【ブロードキャスト】
ESP32でBLEの実装作業【ペリフェラルとセントラル】

BLEのパケット

BLEは送信、および受信の際に圧縮されたC言語で定義したパケットで行われています。ustruct.unpack("<h", data)[0]によって圧縮されたデータを読み取ることができます。ここに注意してほしいのは最初の"<h"部分です。これはリトルエンディアンのshortと定義されているという意味であり、データを圧縮と解凍する時に参照する形式の一種です。基本的に送信側が圧縮するパケットの形式と受信側の解凍する形式は一致しなければなりません(自分は異なる形式をやった結果buffer too smallというエラー文が出ってきました)。

コード

ここにESP32でBLEの実装作業【ペリフェラルとセントラル】のスキャンプログラムを例として、注目してほしいのはdef_update_valueの三行目です。前述の通りでここに使っている解凍する形式は"<h"であるリトルエンディアンのshortとなります。

ble_scanner.py
#パケットの解凍形式
class BLETemperatureCentral:
    def __init__(self, ble):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(self._irq)

        self._reset()
   def _update_value(self, data):
        # Data is sint16 in degrees Celsius with a resolution of 0.01 degrees Celsius.
        self._value = struct.unpack("<h", data)[0] / 100
        return self._value

BLEの識別

BLEデバイスお互いに一般的にUUIDというサービス番号で識別していますが、しかし同じようなサービス番号を使うことも時々起きます。その解決の一種となるのは、UUIDだけではなく、サービスの名前も合併して一緒に識別子とします。

コード

ここにESP32でBLEの実装作業【ペリフェラルとセントラル】のスキャンプログラムを例として、注目してほしいのはdef _irqの5行目です。今はUUIDのみ識別子を使っています。この行の後ろにand decode_name(adv_data) == "好きな名前"と追加していればサービスの名前も一緒にif分に入れ、自分のデバイスしか識別できないようにすることができます。すると5行目下記の通りになります。
if adv_type in (_ADV_IND, _ADV_DIRECT_IND) and _ENV_SENSE_UUID in decode_services(adv_data) and decode_name(adv_data) == "好きな名前":
(もちろんペリフェラルの方からもnameの設定を"好きな名前"にしないとなりませんね)

ble_scanner.py
_IRQ_SCAN_RESULT                     = const(5)
#EVENT中で識別子を書き換える
class BLETemperatureCentral:
    def __init__(self, ble):
        self._ble = ble
        self._ble.active(True)
        self._ble.irq(self._irq)

        self._reset()
    def _irq(self, event, data):
        if event == _IRQ_SCAN_RESULT:
            addr_type, addr, adv_type, rssi, adv_data = data
            print('type:{} addr:{} rssi:{} data:{}'.format(addr_type, ubinascii.hexlify(addr), rssi, ubinascii.hexlify(adv_data)))
            if adv_type in (_ADV_IND, _ADV_DIRECT_IND) and _ENV_SENSE_UUID in decode_services(adv_data) and decode_name(adv_data) == "好きな名前":
                # Found a potential device, remember it and stop scanning.
                self._addr_type = addr_type
                self._addr = bytes(
                    addr
                )  # Note: addr buffer is owned by caller so need to copy it.
                self._name = decode_name(adv_data) or "?"
                self._ble.gap_scan(None)



0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1