【Python】bluepyライブラリを使ったBLEプログラムの基本

Python

今回作業でRasberryPi4Bluetoothを利用することになったためその時に利用したものの確認です。
可能であれば、C言語でBluetooth通信を行えるようにしたかったが、サンプルがあまり見つからなかったためpythonでとりあえず実装、、、
いつかC言語でもBLEプログラム出来たら良いなと思います。

BLEについて簡単に

ここ数年、ワイヤレス機器の普及によりBluetoothを利用することが機会が多いです。
Bluetoothは色々なところで利用されていてよく利用されるものだと以下がよく使われますよね、、、

・イヤホン
・スマホ
・キーボード、マウスなどPC周辺機器

このように生活圏でBluetoothを使用する機会が非常に増えてます。
そのBluetoothはどんどん開発が進み、バージョンアップしています。
販売されている機器にも「対応バージョンなどが記載されているはずです。

現在だと、おそらくバージョン5.0と5.1が主流のはず。。。。
バージョン5.0があるということは、もちろん以前に4.0…3.0…2.0,とありました。
このバージョンついては大きく2種類に別れます。

BLE(Bluetooth LE)・・・バージョン4.0から追加された低消費電量の通信規格
クラシックBluetooth・・・バージョン4.0より以前の旧バージョンを示す。

今回はBLE規格(バージョン4.0以上)に対応したものを想定します。
※注意:クラシックBluetoothについて対応していません。

事前準備(bluepyをインストール)

PythonでBluetoothに関する操作をおこなうbluepyをインストールするには、以下のコマンドを実行します。

$sudo apt-get update
$sudo apt-get -y upgrade
$sudo apt-get -y install python3-pip libglib2.0-dev
$sudo pip3 install bluepy

インストール完了後hcitoolコマンドが使用できます。
それによって周辺のBluetooth機器をスキャンすることが可能です。

$sudo hcitool lescan

以下からさっそくインストールしたbluepyを利用してプログラムを確認します。

プログラム

BLE通信はマスター側スレーブ側に分類できます。

Point

マスター:発生している電波を受信、制御するデバイス

Point

スレーブ:一定間隔で電波を送るデバイス

以下で説明するのはするのはマスター側のプログラムです。

スキャニング

はじめに周辺にどんなデバイスが存在するかスキャンします。
スキャニングには以下の2種類あります。
パッシブスキャン・・・アドバタイジングパケットを受信するのみ
アクティブスキャン・・・アドバタイジングパケット+追加情報を取得

以下は、パッシブスキャンです。

from bluepy import btle

scannner = btle.Scanner(0)
#3秒スキャン
devices = scanner.scan(3.0)

for dev in devices:
    print("[MAC-Adress  ]:", dev.addr)
    print("[Address-Type]:", dev.addrType)
    print("[RSSI        ]:", dev.rssi)
注意

上のサンプルプログラム(scan.py)を実行するときには、root権限が必要です。

スキャン調べたMACアドレスとアドレスタイプを確認して接続

アドレスタイプには2種類あります。

public・・・MACアドレスは固定。
・random・・・MACアドレスは固定ではない。

そのため事前にスキャニングを行い、該当するMACアドレスを確認したら接続という手順になります。

from bluepy import btle
##任意のMACアドレスに変更して下さい
MAC_ADDRESS        "xx:xx:xx:xx:xx:xx" 

# create instance
peripheral = btle.Peripheral()
# connect
peripheral.connect(MAC_ADDRESS)

# disconnected
peripheral.disconnect()

通知が来たらデータを読み込むようにコールバック関数をセット

デリゲートオブジェクトを作成し、それに登録することによって通知が処理できます。
以下に示すように、接続した機器から通知を受信する度にデリゲートメソッドが呼び出されます。

from bluepy import btle
import struct

# 以下の「任意」部分は、スレーブ側の情報に合わせてください。
MAC_ADDRESS             = "XX:XX:XX:XX:XX:XX" #任意のMACアドレスを入力
SERVER_UUID             = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

CAHRACTERISTIC_UUID_TX  = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #任意
CAHRACTERISTIC_UUID_RX  = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" #任意

TX_HANDLE               = 42  # 任意
RX_HANDLE               = 45  # 任意
TIMEOUT                 = 1.0 # 任意


class NotifyDelegate(btle.DefaultDelegate):
    #通知受信用デリゲートクラス
    def __init__(self):
        # 初期化
        btle.DefaultDelegate.__init__(self)

    def handleNotification(self, cHandle, data):
        # 受信時に呼び出されるメソッド.
        print(cHandle, ":", data)
        # 上記はデータ表示のみなので、このあたりで受信処理を行う

# create instance
peripheral = btle.Peripheral(MAC_ADDRESS)
peripheral.withDelegate(NotifyDelegate())

# メインループ
while True:
    if peripheral.waitForNotifications(TIMEOUT) :
        # handleNotification() が呼び出されました
        continue
    print("timeout")
    # ここで受信以外の別処理を実行?
peripheral.disconnect()

接続処理でタイムアウトの時間設定したい

bluepyを利用して接続処理を行う時は「peripheral.connect(MAC_ADDRESS)」と記載します。
その時に接続処理に失敗した場合のタイムアウト処理についてです。
以下のページで方法などをまとめていますので気になる方はご確認ください。

参考

Working with notifications — bluepy 0.9.11 documentation

コメント

タイトルとURLをコピーしました