BLE接続時の利用するクラスと関数
以前の記事でBLE通信の基本的な内容をまとめました。
参考になれば幸いです。
上記のページでは接続処理をする時に、Peripheralクラスのconnect()を使いました。
仕様は以下です。
上記に記されていますが、これを利用していると問題点がありました。(後述)
connect関数の問題点とは?
まずはBLE接続の基本プログラムです。
from bluepy import btle
##任意のMACアドレスに変更して下さい
MAC_ADDRESS "xx:xx:xx:xx:xx:xx"
# create instance
peripheral = btle.Peripheral()
# connect
peripheral.connect(MAC_ADDRESS)
connect関数を利用して、接続が成功する場合は問題ありません。
タイムアウトにかかる時間が40秒もあれば長すぎます、、、そんなに待てないです。
解決方法がないかと探していたら同じことを相談している記事がgithubにありました。
上記の内容を見ていると、ドキュメントに記載はなかったが、
timeoutパラメーターが新規追加されているみたいなので、それを使えば解決できるようです。
timeoutパラメータを使う!エラー?
タイムアウトパラメータが追加されているようなので、
引数に追加すればOKということで追加したプログラムです。
from bluepy import btle
##任意のMACアドレスに変更して下さい
MAC_ADDRESS "xx:xx:xx:xx:xx:xx"
# create instance
peripheral = btle.Peripheral()
# connect タイムアウトはとりあえず3秒で設定しています。
peripheral.connect(MAC_ADDRESS timeout=3)
実行してみるとエラーで実行できません。
タイムアウトに該当する引数は存在しないとのこと…
importモジュールの中身を確認
人によって異なるかもしれませんが、以下を確認してみてください。
存在しない場合は、pythonバージョンが異なっていることも考えられるので利用している環境に応じてパスは修正してください。
cd /usr/local/lib/python3.8/dist-packages/bluepy
cat btle.py | grep _connect
上のコマンドbtle.pyファイルからconnect関数を検索しました。
以下は、connect関数周辺のプログラムです。
#引数を確認してもtimeout引数はない。
def _connect(self, addr, addrType=ADDR_TYPE_PUBLIC, iface=None):
if len(addr.split(":")) != 6:
raise ValueError("Expected MAC address, got %s" % repr(addr))
if addrType not in (ADDR_TYPE_PUBLIC, ADDR_TYPE_RANDOM):
raise ValueError("Expected address type public or random, got {}".format(addrType))
self._startHelper(iface)
self.addr = addr
self.addrType = addrType
self.iface = iface
if iface is not None:
self._writeCmd("conn %s %s %s\n" % (addr, addrType, "hci"+str(iface)))
else:
self._writeCmd("conn %s %s\n" % (addr, addrType))
rsp = self._getResp('stat')
while rsp['state'][0] == 'tryconn':
rsp = self._getResp('stat')
if rsp['state'][0] != 'conn':
self._stopHelper()
raise BTLEDisconnectError("Failed to connect to peripheral %s, addr type: %s" % (addr, addrType), rsp)
インストールしたモジュールが古かった?ためtimeoutパラメータがありませんでしたので、
timeoutパラメータが追加されたモジュールをインストールしていきます。
timeoutが追加されたbluepyインストール
timeoutパラメータが追加された新しいバージョンのbluepyをインストールします。
$ sudo apt-get install git build-essential libglib2.0-dev
$ git clone https://github.com/IanHarvey/bluepy.git
$ cd bluepy
$ python3 setup.py build
$ sudo python3 setup.py install
タイムアウトパラメータが追加されていることを確認
インストール完了後、以下のフォルダを確認してください。
※ディレクトリのpythonバージョンは利用環境に応じて変更してください。
#python3.9のところはそれぞれにあったバージョンを確認
cat /usr/local/lib/python3.9/dist-packages/bluepy-1.3.0-py3.8.egg/bluepy/btle.py -n| grep _connect
409 self._connect(deviceAddr.addr, deviceAddr.addrType, deviceAddr.iface, timeout)
411 self._connect(deviceAddr, addrType, iface, timeout)
441 def _connect(self, addr, addrType=ADDR_TYPE_PUBLIC, iface=None, timeout=None):
472 self._connect(addr.addr, addr.addrType, addr.iface, timeout)
474 self._connect(addr, addrType, iface, timeout)
441行目connect関数の引数を確認するとtimeoutが追加されています。
あとは今インストールしたモジュールを利用できればOKです。
インポートしたモジュールの位置を変更
pythonコードから利用しやすいようにファイルの置かれているディレクトリーとディレクトリ名変更します。
モジュール名を「bluepy」から「bluepy2」に変更
cd /usr/local/lib/python3.8/dist-packages/bluepy-1.3.0-py3.8.egg
sudo mv bluepy bluepy2
bluepy2ディレクトリの位置を変更
cd /usr/local/lib/python3.9/dist-packages
sudo mv bluepy-1.3.0-py3.8.egg/bluepy2/ bluepy2
実装
from bluepy2 import btle
##任意のMACアドレスに変更して下さい
MAC_ADDRESS "xx:xx:xx:xx:xx:xx"
# create instance
peripheral = btle.Peripheral()
# connect
peripheral.connect(MAC_ADDRESS timeout=3)
コメント