From 216795460da1a5058295e4fdcac5db817fac249a Mon Sep 17 00:00:00 2001 From: conway220 Date: Sat, 18 Mar 2023 14:29:55 -0400 Subject: [PATCH 1/4] fix: add extra logging/move polling functionality --- src/oralb_ble/parser.py | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/src/oralb_ble/parser.py b/src/oralb_ble/parser.py index de39242..439af51 100644 --- a/src/oralb_ble/parser.py +++ b/src/oralb_ble/parser.py @@ -12,7 +12,7 @@ from dataclasses import dataclass from enum import Enum, auto -from bleak import BLEDevice +from bleak import BleakError, BLEDevice from bleak_retry_connector import BleakClientWithServiceCache, establish_connection from bluetooth_data_tools import short_address from bluetooth_sensor_state_data import BluetoothData @@ -333,6 +333,7 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: """ Poll the device to retrieve any values we can't get from passive listening. """ + _LOGGER.debug("Polling Oral-B device: %s", ble_device.address) client = await establish_connection( BleakClientWithServiceCache, ble_device, ble_device.address ) @@ -341,19 +342,23 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: battery_payload = await client.read_gatt_char(battery_char) pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE) pressure_payload = await client.read_gatt_char(pressure_char) + tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( + pressure_payload[0], f"unknown pressure {pressure_payload[0]}" + ) + self.update_sensor( + str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure" + ) + self.update_sensor( + str(OralBSensor.BATTERY_PERCENT), + Units.PERCENTAGE, + battery_payload[0], + SensorDeviceClass.BATTERY, + "Battery", + ) + _LOGGER.debug("Successfully read active gatt characters") + except BleakError as err: + _LOGGER.debug(f"Reading gatt characters failed with err: {err}") finally: await client.disconnect() - tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( - pressure_payload[0], f"unknown pressure {pressure_payload[0]}" - ) - self.update_sensor( - str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure" - ) - self.update_sensor( - str(OralBSensor.BATTERY_PERCENT), - Units.PERCENTAGE, - battery_payload[0], - SensorDeviceClass.BATTERY, - "Battery", - ) + _LOGGER.debug("Disconnected from active bluetooth client") return self._finish_update() From 5f84adc784dbb82b59553ea47344532d1cf8248a Mon Sep 17 00:00:00 2001 From: conway220 Date: Mon, 20 Mar 2023 08:37:44 -0400 Subject: [PATCH 2/4] fix: moved code within else block --- src/oralb_ble/parser.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/oralb_ble/parser.py b/src/oralb_ble/parser.py index 439af51..2bc8a84 100644 --- a/src/oralb_ble/parser.py +++ b/src/oralb_ble/parser.py @@ -342,6 +342,9 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: battery_payload = await client.read_gatt_char(battery_char) pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE) pressure_payload = await client.read_gatt_char(pressure_char) + except BleakError as err: + _LOGGER.debug(f"Reading gatt characters failed with err: {err}") + else: tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( pressure_payload[0], f"unknown pressure {pressure_payload[0]}" ) @@ -356,8 +359,6 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: "Battery", ) _LOGGER.debug("Successfully read active gatt characters") - except BleakError as err: - _LOGGER.debug(f"Reading gatt characters failed with err: {err}") finally: await client.disconnect() _LOGGER.debug("Disconnected from active bluetooth client") From 67a558bf8da86f250482788a332583ea9e6ae745 Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 21 Mar 2023 07:51:04 -0400 Subject: [PATCH 3/4] Change to warning --- src/oralb_ble/parser.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/oralb_ble/parser.py b/src/oralb_ble/parser.py index 2bc8a84..4e70276 100644 --- a/src/oralb_ble/parser.py +++ b/src/oralb_ble/parser.py @@ -343,7 +343,7 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE) pressure_payload = await client.read_gatt_char(pressure_char) except BleakError as err: - _LOGGER.debug(f"Reading gatt characters failed with err: {err}") + _LOGGER.warning(f"Reading gatt characters failed with err: {err}") else: tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( pressure_payload[0], f"unknown pressure {pressure_payload[0]}" From 573d41d0409b8ab247824799e422824fe141baff Mon Sep 17 00:00:00 2001 From: Luke Date: Tue, 21 Mar 2023 12:26:02 -0400 Subject: [PATCH 4/4] feat: add retry_connector to get_payload --- src/oralb_ble/parser.py | 48 ++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 20 deletions(-) diff --git a/src/oralb_ble/parser.py b/src/oralb_ble/parser.py index 4e70276..080bd05 100644 --- a/src/oralb_ble/parser.py +++ b/src/oralb_ble/parser.py @@ -13,7 +13,11 @@ from enum import Enum, auto from bleak import BleakError, BLEDevice -from bleak_retry_connector import BleakClientWithServiceCache, establish_connection +from bleak_retry_connector import ( + BleakClientWithServiceCache, + establish_connection, + retry_bluetooth_connection_error, +) from bluetooth_data_tools import short_address from bluetooth_sensor_state_data import BluetoothData from home_assistant_bluetooth import BluetoothServiceInfo @@ -329,6 +333,28 @@ def poll_needed( update_interval = BRUSHING_UPDATE_INTERVAL_SECONDS return last_poll > update_interval + @retry_bluetooth_connection_error() + async def _get_payload(self, client: BleakClientWithServiceCache) -> None: + """Get the payload from the brush using its gatt_characteristics.""" + battery_char = client.services.get_characteristic(CHARACTERISTIC_BATTERY) + battery_payload = await client.read_gatt_char(battery_char) + pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE) + pressure_payload = await client.read_gatt_char(pressure_char) + tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( + pressure_payload[0], f"unknown pressure {pressure_payload[0]}" + ) + self.update_sensor( + str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure" + ) + self.update_sensor( + str(OralBSensor.BATTERY_PERCENT), + Units.PERCENTAGE, + battery_payload[0], + SensorDeviceClass.BATTERY, + "Battery", + ) + _LOGGER.debug("Successfully read active gatt characters") + async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: """ Poll the device to retrieve any values we can't get from passive listening. @@ -338,27 +364,9 @@ async def async_poll(self, ble_device: BLEDevice) -> SensorUpdate: BleakClientWithServiceCache, ble_device, ble_device.address ) try: - battery_char = client.services.get_characteristic(CHARACTERISTIC_BATTERY) - battery_payload = await client.read_gatt_char(battery_char) - pressure_char = client.services.get_characteristic(CHARACTERISTIC_PRESSURE) - pressure_payload = await client.read_gatt_char(pressure_char) + await self._get_payload(client) except BleakError as err: _LOGGER.warning(f"Reading gatt characters failed with err: {err}") - else: - tb_pressure = ACTIVE_CONNECTION_PRESSURE.get( - pressure_payload[0], f"unknown pressure {pressure_payload[0]}" - ) - self.update_sensor( - str(OralBSensor.PRESSURE), None, tb_pressure, None, "Pressure" - ) - self.update_sensor( - str(OralBSensor.BATTERY_PERCENT), - Units.PERCENTAGE, - battery_payload[0], - SensorDeviceClass.BATTERY, - "Battery", - ) - _LOGGER.debug("Successfully read active gatt characters") finally: await client.disconnect() _LOGGER.debug("Disconnected from active bluetooth client")