diff --git a/homeassistant/components/xiaomi_ble/binary_sensor.py b/homeassistant/components/xiaomi_ble/binary_sensor.py index 5ff418fe831..5490676ad1a 100644 --- a/homeassistant/components/xiaomi_ble/binary_sensor.py +++ b/homeassistant/components/xiaomi_ble/binary_sensor.py @@ -72,6 +72,9 @@ BINARY_SENSOR_DESCRIPTIONS = { key=ExtendedBinarySensorDeviceClass.PRY_THE_DOOR, device_class=BinarySensorDeviceClass.TAMPER, ), + ExtendedBinarySensorDeviceClass.TOOTHBRUSH: BinarySensorEntityDescription( + key=ExtendedBinarySensorDeviceClass.TOOTHBRUSH, + ), } diff --git a/homeassistant/components/xiaomi_ble/manifest.json b/homeassistant/components/xiaomi_ble/manifest.json index e2b327c6823..a03e3f388ed 100644 --- a/homeassistant/components/xiaomi_ble/manifest.json +++ b/homeassistant/components/xiaomi_ble/manifest.json @@ -24,5 +24,5 @@ "dependencies": ["bluetooth_adapters"], "documentation": "https://www.home-assistant.io/integrations/xiaomi_ble", "iot_class": "local_push", - "requirements": ["xiaomi-ble==0.20.0"] + "requirements": ["xiaomi-ble==0.21.1"] } diff --git a/homeassistant/components/xiaomi_ble/sensor.py b/homeassistant/components/xiaomi_ble/sensor.py index 86ffdedafd1..56bfbb1b020 100644 --- a/homeassistant/components/xiaomi_ble/sensor.py +++ b/homeassistant/components/xiaomi_ble/sensor.py @@ -2,6 +2,7 @@ from __future__ import annotations from xiaomi_ble import DeviceClass, SensorUpdate, Units +from xiaomi_ble.parser import ExtendedSensorDeviceClass from homeassistant import config_entries from homeassistant.components.bluetooth.passive_update_processor import ( @@ -25,6 +26,7 @@ from homeassistant.const import ( UnitOfMass, UnitOfPressure, UnitOfTemperature, + UnitOfTime, ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -129,13 +131,23 @@ SENSOR_DESCRIPTIONS = { state_class=SensorStateClass.MEASUREMENT, entity_category=EntityCategory.DIAGNOSTIC, ), - # Used for e.g. consumable sensor on WX08ZM - (None, Units.PERCENTAGE): SensorEntityDescription( - key=str(Units.PERCENTAGE), - device_class=None, + # Used for e.g. consumable sensor on WX08ZM and M1S-T500 + (ExtendedSensorDeviceClass.CONSUMABLE, Units.PERCENTAGE): SensorEntityDescription( + key=str(ExtendedSensorDeviceClass.CONSUMABLE), native_unit_of_measurement=PERCENTAGE, state_class=SensorStateClass.MEASUREMENT, ), + # Used for score after brushing with a toothbrush + (ExtendedSensorDeviceClass.SCORE, None): SensorEntityDescription( + key=str(ExtendedSensorDeviceClass.SCORE), + state_class=SensorStateClass.MEASUREMENT, + ), + # Used for counting during brushing + (ExtendedSensorDeviceClass.COUNTER, Units.TIME_SECONDS): SensorEntityDescription( + key=str(ExtendedSensorDeviceClass.COUNTER), + native_unit_of_measurement=UnitOfTime.SECONDS, + state_class=SensorStateClass.MEASUREMENT, + ), } @@ -153,7 +165,7 @@ def sensor_update_to_bluetooth_data_update( (description.device_class, description.native_unit_of_measurement) ] for device_key, description in sensor_update.entity_descriptions.items() - if description.native_unit_of_measurement + if description.device_class }, entity_data={ device_key_to_bluetooth_entity_key(device_key): sensor_values.native_value diff --git a/requirements_all.txt b/requirements_all.txt index 645dcf3fde0..bcfa77e219d 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -2698,7 +2698,7 @@ wyoming==1.1.0 xbox-webapi==2.0.11 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.20.0 +xiaomi-ble==0.21.1 # homeassistant.components.knx xknx==2.11.2 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index c8e3c0e76e8..f8e922977e9 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -1983,7 +1983,7 @@ wyoming==1.1.0 xbox-webapi==2.0.11 # homeassistant.components.xiaomi_ble -xiaomi-ble==0.20.0 +xiaomi-ble==0.21.1 # homeassistant.components.knx xknx==2.11.2 diff --git a/tests/components/xiaomi_ble/test_sensor.py b/tests/components/xiaomi_ble/test_sensor.py index 7f39228a012..a2b0e62821a 100644 --- a/tests/components/xiaomi_ble/test_sensor.py +++ b/tests/components/xiaomi_ble/test_sensor.py @@ -132,6 +132,40 @@ async def test_xiaomi_consumable(hass: HomeAssistant) -> None: await hass.async_block_till_done() +async def test_xiaomi_score(hass: HomeAssistant) -> None: + """Make sure that score sensors are correctly mapped.""" + entry = MockConfigEntry( + domain=DOMAIN, + unique_id="ED:DE:34:3F:48:0C", + data={"bindkey": "1330b99cded13258acc391627e9771f7"}, + ) + entry.add_to_hass(hass) + + assert await hass.config_entries.async_setup(entry.entry_id) + await hass.async_block_till_done() + + assert len(hass.states.async_all()) == 0 + inject_bluetooth_service_info_bleak( + hass, + make_advertisement( + "ED:DE:34:3F:48:0C", + b"\x48\x58\x06\x08\xc9H\x0e\xf1\x12\x81\x07\x973\xfc\x14\x00\x00VD\xdbA", + ), + ) + await hass.async_block_till_done() + assert len(hass.states.async_all()) == 2 + + sensor = hass.states.get("sensor.smart_toothbrush_480c_score") + + sensor_attr = sensor.attributes + assert sensor.state == "83" + assert sensor_attr[ATTR_FRIENDLY_NAME] == "Smart Toothbrush 480C Score" + assert sensor_attr[ATTR_STATE_CLASS] == "measurement" + + assert await hass.config_entries.async_unload(entry.entry_id) + await hass.async_block_till_done() + + async def test_xiaomi_battery_voltage(hass: HomeAssistant) -> None: """Make sure that battery voltage sensors are correctly mapped.""" entry = MockConfigEntry(