結論
- 英語版READMEのコードを実施すれば、何も考えずにToioコアキューブのスキャンと接続が可能。
-
日本語版READMEで実施した際に、コードが古かったことでエラーが出て、色々と詰まっていたというのが今回の記事の内容。
- とは言いつつ、
CubeInfo or a CubeInterfaceの下りがあるので想定されたエラーではなさそう?
- とは言いつつ、
環境
- RaspberryPi 5 8GB
- Python 3.11.2
pip freezeは下記
bleak==2.0.0
dbus-fast==3.1.2
toio.py==1.1.0
typing_extensions==4.15.0
公式ページのScannerを試そうとしたところ..
こちらのリンクをそのまま実行したら、エラーが出てきた
コードはこちら。コピペです
import asyncio
from toio import *
async def scan_and_connect():
dev_list = await BLEScanner.scan(num=1)
assert len(dev_list)
cube = ToioCoreCube(dev_list[0])
await cube.connect()
await asyncio.sleep(3)
await cube.disconnect()
return 0
if __name__ == "__main__":
asyncio.run(scan_and_connect())
Scan後に作ったcubeにconnectメソッドは無い、という趣旨みたい。
Traceback (most recent call last):
File "/home/****/toio_check/toio_official_scan.py", line 17, in <module>
asyncio.run(scan_and_connect())
File "/usr/lib/python3.11/asyncio/runners.py", line 190, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/home/****/toio_check/toio_official_scan.py", line 9, in scan_and_connect
await cube.connect()
File "/home/****/toio_check/toio/lib/python3.11/site-packages/toio/cube/__init__.py", line 229, in connect
connect_result = await self.interface.connect()
^^^^^^^^^^^^^^^^^^^^^^
AttributeError: 'CubeInfo' object has no attribute 'connect'
まずはスキャンだけ
import asyncio
from toio import BLEScanner
async def scan_and_print():
# 例:最大 100 台まで探す
devices = await BLEScanner.scan(num=100)
print("Found devices:")
for info in devices:
name = info.name
device_id = info.device.address
print(f"name: {name}, device_id: {device_id}")
asyncio.run(scan_and_print())
とりあえずはtoioコアキューブのスキャンはできているみたい。
Found devices:
name: toio Core Cube-***, device_id: ...
name: toio Core Cube-***, device_id: ...
IDを指定してみよう
import asyncio
from toio import *
async def scan_and_connect():
dev_list = await BLEScanner.scan_with_id(cube_id={"ここにnameの三文字IDを入れる"})
print(dev_list)
cube = ToioCoreCube(dev_list[0])
return 0
if __name__ == "__main__":
asyncio.run(scan_and_connect())
ちゃんと探せているみたい
また、ToioCoreCubeでエラーは発生していない。
[CubeInfo(name='toio Core Cube-***', device=BLEDevice(..., toio Core Cube-***), interface=<toio.device_interface.ble.BleCube object at 0x7ffeec176710>, advertisement=AdvertisementData(local_name='toio Core Cube-***', service_uuids=['10b20100-5b3b-4571-9508-cf3efcd7bbae'], rssi=-31))]
取得してきたデータがnullだった、ということは無さそうだ。
解決
ToioCoreCubeに渡すデータをCubeInfoではなくCubeInterfaceにしてみたらうごいた!
cube = ToioCoreCube(dev_list[0].interface)
こちらのコメントには「CubeInfo or a CubeInterface」と書いてあったので、お試しでCubeInterfaceを入れてみたら、動いた。
でも、該当コードのコメントアウトには下記が書かれていたのでCubeInfoで動かなかった理由はまだ謎のまま。。!
If you initialize ToioCoreCube with a CubeInfo or a CubeInterface,
you can connect to specified cube by calling the connect() function.
In this case, the scan() function does not work.
そして、結局のオチ
英語版READMEの方はちゃんとinterfaceが入っていた。日本語版のREADMEが古かった、というだけだった。。
cube = ToioCoreCube(dev_list[0].interface)
以下はコピペです。
import asyncio
from toio import *
async def scan_and_connect():
dev_list = await BLEScanner.scan(num=1)
assert len(dev_list)
cube = ToioCoreCube(dev_list[0].interface)
await cube.connect()
await asyncio.sleep(3)
await cube.disconnect()
return 0
if __name__ == "__main__":
asyncio.run(scan_and_connect())
一応Issueに書いてみた
プルリクも考えて見つつ、結局CubeInfoによる初期化を正義とするのかどうかが分かっていなかったので、判断を仰ぐ意味でもIssueを残してみました。
貢献になればいいな~。