CircuitPython 10行プログラミング Step8 (10) BLE float characteristics
第8回、マイコン・ボードSeeed XIAO BLE SenseのI2Cバスに、温湿度センサAHT20を接続しペリフェラルにしました。ここでは、センサの乗っていないSeeed XIAO BLEをセントラルにしました。
しかし、第9回のようにstreamで実数をうまくハンドリングできませんでした。ここでは、FloatCharacteristicを利用します。
●ペリフェラルSensorServiceクラス
温度と湿度を読み取るfloatのcharacteristics UUIDを用意します。
次のプログラムをSwitchBot.pyで保存します。streamのimportが残っていますが、使ってはいません
# SPDX-FileCopyrightText: 2020 Mark Raleson
# SPDX-License-Identifier: MIT
from adafruit_ble.uuid import VendorUUID
from adafruit_ble.services import Service
from adafruit_ble.characteristics import Characteristic
from adafruit_ble.characteristics.stream import StreamIn
from adafruit_ble.characteristics.stream import StreamOut
from adafruit_ble.characteristics.float import FloatCharacteristic
class SensorService(Service):
uuid = VendorUUID("51ad213f-e568-4e35-84e4-67af89c79ef0")
sensorsT = FloatCharacteristic(
uuid=VendorUUID("e077bdec-f18b-4944-9e9e-8b3a815162b4"),
properties=Characteristic.READ | Characteristic.NOTIFY,
)
sensorsH = FloatCharacteristic(
uuid=VendorUUID("528ff74b-fdb8-444c-9c64-3dd5da4135ae"),
properties=Characteristic.READ | Characteristic.NOTIFY,
)
def __init__(self, service=None):
super().__init__(service=service)
self.connectable = True
●ペリフェラルのプログラム
センサの読み取った値をそれぞれのcharacteristic UUIDに代入することで送信しています。streamのようにread/writeはありません。
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT
import time
import struct
import board
import adafruit_ahtx0
from SwitchBot import SensorService
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
# Create BLE radio, custom service, and advertisement.
ble = BLERadio()
sService = SensorService()
advertisement = ProvideServicesAdvertisement(sService)
ble.name = "AHT20 Humidity&Temperature"
# Create sensor object, communicating over the board's default I2C bus
i2c = board.I2C() # uses board.SCL and board.SDA
sensor = adafruit_ahtx0.AHTx0(i2c)
while True:
print("Advertise services")
ble.stop_advertising() # you need to do this to stop any persistent old advertisement
ble.start_advertising(advertisement)
print("Waiting for connection...")
while not ble.connected:
pass
ble.stop_advertising()
print("Connected")
while ble.connected:
print("\nTemperature: %0.1f C" % sensor.temperature)
print("Humidity: %0.1f %%" % sensor.relative_humidity)
sService.sensorsT = sensor.temperature
sService.sensorsH = sensor.relative_humidity
time.sleep(3)
print("Disconnected")
●セントラルのSensorServiceクラス
温度と湿度を読み取るfloatのcharacteristics UUIDを用意します。
次のプログラムをSwitchBot.pyで保存します。ペリフェラルと同じ記述です。
# SPDX-FileCopyrightText: 2020 Mark Raleson
# SPDX-License-Identifier: MIT
from adafruit_ble.uuid import VendorUUID
from adafruit_ble.services import Service
from adafruit_ble.characteristics import Characteristic
from adafruit_ble.characteristics.stream import StreamIn
from adafruit_ble.characteristics.stream import StreamOut
from adafruit_ble.characteristics.float import FloatCharacteristic
class SensorService(Service):
uuid = VendorUUID("51ad213f-e568-4e35-84e4-67af89c79ef0")
sensorsT = FloatCharacteristic (
uuid=VendorUUID("e077bdec-f18b-4944-9e9e-8b3a815162b4"),
properties=Characteristic.READ | Characteristic.NOTIFY,
)
sensorsH = FloatCharacteristic(
uuid=VendorUUID("528ff74b-fdb8-444c-9c64-3dd5da4135ae"),
properties=Characteristic.READ | Characteristic.NOTIFY,
)
def __init__(self, service=None):
super().__init__(service=service)
self.connectable = True
●セントラルのプログラム
少し離れたところで動作しているペリフェラルは、実数で温度と湿度を送っています。フォーマットは不明です。
start_scanで、アドバタイジングしているペリフェラルを見つけ、その中のservice UUIDがSensorService(Service)なのを見つけたらconnectします。
そのserviceのなかの温度characteristics UUIDなるsensorsT、同様に湿度sensorsHのオブジェクトを変数RTとRH代入します。送った実数がそのまま入っています。
# SPDX-FileCopyrightText: 2020 Mark Raleson
# SPDX-License-Identifier: MIT
from SwitchBot import SensorService
from adafruit_ble import BLERadio
from adafruit_ble.advertising.standard import ProvideServicesAdvertisement
import time
import struct
ble = BLERadio()
connection = None
while True:
if not connection:
print("Scanning")
for adv in ble.start_scan(ProvideServicesAdvertisement):
addr = adv.address
s = ProvideServicesAdvertisement.matches
#address = str(addr)[9:26]
#print(address, adv)
if SensorService in adv.services:
connection = ble.connect(adv)
print("Connected")
break
print(".")
ble.stop_scan()
print("stopped scan")
if connection and connection.connected:
service = connection[SensorService]
while connection.connected:
RT = service.sensorsT
RH = service.sensorsH
print("Temp: ", RT)
print("Humi: ", RH)
print("")
time.sleep(3)
実行中の様子です。