mirror of
https://github.com/home-assistant/core.git
synced 2025-07-23 13:17:32 +00:00
Add xiaomi_ble voltage, consumable and formaldehyde sensors (#75807)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
This commit is contained in:
parent
aaf5837759
commit
f8b115dd9d
@ -8,7 +8,7 @@
|
|||||||
"service_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
"service_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requirements": ["xiaomi-ble==0.5.1"],
|
"requirements": ["xiaomi-ble==0.6.1"],
|
||||||
"dependencies": ["bluetooth"],
|
"dependencies": ["bluetooth"],
|
||||||
"codeowners": ["@Jc2k", "@Ernst79"],
|
"codeowners": ["@Jc2k", "@Ernst79"],
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push"
|
||||||
|
@ -30,7 +30,9 @@ from homeassistant.const import (
|
|||||||
ATTR_MANUFACTURER,
|
ATTR_MANUFACTURER,
|
||||||
ATTR_MODEL,
|
ATTR_MODEL,
|
||||||
ATTR_NAME,
|
ATTR_NAME,
|
||||||
|
CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||||
CONDUCTIVITY,
|
CONDUCTIVITY,
|
||||||
|
ELECTRIC_POTENTIAL_VOLT,
|
||||||
LIGHT_LUX,
|
LIGHT_LUX,
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
PRESSURE_MBAR,
|
PRESSURE_MBAR,
|
||||||
@ -74,6 +76,12 @@ SENSOR_DESCRIPTIONS = {
|
|||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
(DeviceClass.VOLTAGE, Units.ELECTRIC_POTENTIAL_VOLT): SensorEntityDescription(
|
||||||
|
key=str(Units.ELECTRIC_POTENTIAL_VOLT),
|
||||||
|
device_class=SensorDeviceClass.VOLTAGE,
|
||||||
|
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
),
|
||||||
(
|
(
|
||||||
DeviceClass.SIGNAL_STRENGTH,
|
DeviceClass.SIGNAL_STRENGTH,
|
||||||
Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||||
@ -98,6 +106,12 @@ SENSOR_DESCRIPTIONS = {
|
|||||||
native_unit_of_measurement=CONDUCTIVITY,
|
native_unit_of_measurement=CONDUCTIVITY,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
# Used for e.g. formaldehyde
|
||||||
|
(None, Units.CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER): SensorEntityDescription(
|
||||||
|
key=str(Units.CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER),
|
||||||
|
native_unit_of_measurement=CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2470,7 +2470,7 @@ xbox-webapi==2.0.11
|
|||||||
xboxapi==2.0.1
|
xboxapi==2.0.1
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_ble
|
# homeassistant.components.xiaomi_ble
|
||||||
xiaomi-ble==0.5.1
|
xiaomi-ble==0.6.1
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==0.22.0
|
xknx==0.22.0
|
||||||
|
@ -1662,7 +1662,7 @@ wolf_smartset==0.1.11
|
|||||||
xbox-webapi==2.0.11
|
xbox-webapi==2.0.11
|
||||||
|
|
||||||
# homeassistant.components.xiaomi_ble
|
# homeassistant.components.xiaomi_ble
|
||||||
xiaomi-ble==0.5.1
|
xiaomi-ble==0.6.1
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==0.22.0
|
xknx==0.22.0
|
||||||
|
@ -50,6 +50,154 @@ async def test_sensors(hass):
|
|||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_xiaomi_formaldeyhde(hass):
|
||||||
|
"""Make sure that formldehyde sensors are correctly mapped."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="C4:7C:8D:6A:3E:7A",
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
saved_callback = None
|
||||||
|
|
||||||
|
def _async_register_callback(_hass, _callback, _matcher):
|
||||||
|
nonlocal saved_callback
|
||||||
|
saved_callback = _callback
|
||||||
|
return lambda: None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bluetooth.update_coordinator.async_register_callback",
|
||||||
|
_async_register_callback,
|
||||||
|
):
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass.states.async_all()) == 0
|
||||||
|
|
||||||
|
# WARNING: This test data is synthetic, rather than captured from a real device
|
||||||
|
# obj type is 0x1010, payload len is 0x2 and payload is 0xf400
|
||||||
|
saved_callback(
|
||||||
|
make_advertisement(
|
||||||
|
"C4:7C:8D:6A:3E:7A", b"q \x98\x00iz>j\x8d|\xc4\r\x10\x10\x02\xf4\x00"
|
||||||
|
),
|
||||||
|
BluetoothChange.ADVERTISEMENT,
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass.states.async_all()) == 1
|
||||||
|
|
||||||
|
sensor = hass.states.get("sensor.test_device_formaldehyde")
|
||||||
|
sensor_attr = sensor.attributes
|
||||||
|
assert sensor.state == "2.44"
|
||||||
|
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Test Device Formaldehyde"
|
||||||
|
assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "mg/m³"
|
||||||
|
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_consumable(hass):
|
||||||
|
"""Make sure that consumable sensors are correctly mapped."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="C4:7C:8D:6A:3E:7A",
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
saved_callback = None
|
||||||
|
|
||||||
|
def _async_register_callback(_hass, _callback, _matcher):
|
||||||
|
nonlocal saved_callback
|
||||||
|
saved_callback = _callback
|
||||||
|
return lambda: None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bluetooth.update_coordinator.async_register_callback",
|
||||||
|
_async_register_callback,
|
||||||
|
):
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass.states.async_all()) == 0
|
||||||
|
|
||||||
|
# WARNING: This test data is synthetic, rather than captured from a real device
|
||||||
|
# obj type is 0x1310, payload len is 0x2 and payload is 0x6000
|
||||||
|
saved_callback(
|
||||||
|
make_advertisement(
|
||||||
|
"C4:7C:8D:6A:3E:7A", b"q \x98\x00iz>j\x8d|\xc4\r\x13\x10\x02\x60\x00"
|
||||||
|
),
|
||||||
|
BluetoothChange.ADVERTISEMENT,
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass.states.async_all()) == 1
|
||||||
|
|
||||||
|
sensor = hass.states.get("sensor.test_device_consumable")
|
||||||
|
sensor_attr = sensor.attributes
|
||||||
|
assert sensor.state == "96"
|
||||||
|
assert sensor_attr[ATTR_FRIENDLY_NAME] == "Test Device Consumable"
|
||||||
|
assert sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||||
|
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):
|
||||||
|
"""Make sure that battery voltage sensors are correctly mapped."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="C4:7C:8D:6A:3E:7A",
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
saved_callback = None
|
||||||
|
|
||||||
|
def _async_register_callback(_hass, _callback, _matcher):
|
||||||
|
nonlocal saved_callback
|
||||||
|
saved_callback = _callback
|
||||||
|
return lambda: None
|
||||||
|
|
||||||
|
with patch(
|
||||||
|
"homeassistant.components.bluetooth.update_coordinator.async_register_callback",
|
||||||
|
_async_register_callback,
|
||||||
|
):
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
assert len(hass.states.async_all()) == 0
|
||||||
|
|
||||||
|
# WARNING: This test data is synthetic, rather than captured from a real device
|
||||||
|
# obj type is 0x0a10, payload len is 0x2 and payload is 0x6400
|
||||||
|
saved_callback(
|
||||||
|
make_advertisement(
|
||||||
|
"C4:7C:8D:6A:3E:7A", b"q \x98\x00iz>j\x8d|\xc4\r\x0a\x10\x02\x64\x00"
|
||||||
|
),
|
||||||
|
BluetoothChange.ADVERTISEMENT,
|
||||||
|
)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass.states.async_all()) == 2
|
||||||
|
|
||||||
|
volt_sensor = hass.states.get("sensor.test_device_voltage")
|
||||||
|
volt_sensor_attr = volt_sensor.attributes
|
||||||
|
assert volt_sensor.state == "3.1"
|
||||||
|
assert volt_sensor_attr[ATTR_FRIENDLY_NAME] == "Test Device Voltage"
|
||||||
|
assert volt_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "V"
|
||||||
|
assert volt_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||||
|
|
||||||
|
bat_sensor = hass.states.get("sensor.test_device_battery")
|
||||||
|
bat_sensor_attr = bat_sensor.attributes
|
||||||
|
assert bat_sensor.state == "100"
|
||||||
|
assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Test Device Battery"
|
||||||
|
assert bat_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||||
|
assert bat_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_HHCCJCY01(hass):
|
async def test_xiaomi_HHCCJCY01(hass):
|
||||||
"""This device has multiple advertisements before all sensors are visible. Test that this works."""
|
"""This device has multiple advertisements before all sensors are visible. Test that this works."""
|
||||||
entry = MockConfigEntry(
|
entry = MockConfigEntry(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user