Add support for HHCCJCY10 to xiaomi_ble (#82069)
This commit is contained in:
parent
1ded3ac51e
commit
af73afa2e2
7 changed files with 121 additions and 36 deletions
|
@ -4,12 +4,16 @@
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/xiaomi_ble",
|
"documentation": "https://www.home-assistant.io/integrations/xiaomi_ble",
|
||||||
"bluetooth": [
|
"bluetooth": [
|
||||||
|
{
|
||||||
|
"connectable": false,
|
||||||
|
"service_data_uuid": "0000fd50-0000-1000-8000-00805f9b34fb"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"connectable": false,
|
"connectable": false,
|
||||||
"service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
"service_data_uuid": "0000fe95-0000-1000-8000-00805f9b34fb"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"requirements": ["xiaomi-ble==0.10.0"],
|
"requirements": ["xiaomi-ble==0.12.1"],
|
||||||
"dependencies": ["bluetooth"],
|
"dependencies": ["bluetooth"],
|
||||||
"codeowners": ["@Jc2k", "@Ernst79"],
|
"codeowners": ["@Jc2k", "@Ernst79"],
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push"
|
||||||
|
|
|
@ -36,10 +36,25 @@ from .const import DOMAIN
|
||||||
from .device import device_key_to_bluetooth_entity_key, sensor_device_info_to_hass
|
from .device import device_key_to_bluetooth_entity_key, sensor_device_info_to_hass
|
||||||
|
|
||||||
SENSOR_DESCRIPTIONS = {
|
SENSOR_DESCRIPTIONS = {
|
||||||
(DeviceClass.TEMPERATURE, Units.TEMP_CELSIUS): SensorEntityDescription(
|
(DeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
|
||||||
key=f"{DeviceClass.TEMPERATURE}_{Units.TEMP_CELSIUS}",
|
key=f"{DeviceClass.BATTERY}_{Units.PERCENTAGE}",
|
||||||
device_class=SensorDeviceClass.TEMPERATURE,
|
device_class=SensorDeviceClass.BATTERY,
|
||||||
native_unit_of_measurement=TEMP_CELSIUS,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
(DeviceClass.CONDUCTIVITY, Units.CONDUCTIVITY): SensorEntityDescription(
|
||||||
|
key=str(Units.CONDUCTIVITY),
|
||||||
|
device_class=None,
|
||||||
|
native_unit_of_measurement=CONDUCTIVITY,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
),
|
||||||
|
(
|
||||||
|
DeviceClass.FORMALDEHYDE,
|
||||||
|
Units.CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||||
|
): SensorEntityDescription(
|
||||||
|
key=f"{DeviceClass.FORMALDEHYDE}_{Units.CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER}",
|
||||||
|
native_unit_of_measurement=CONCENTRATION_MILLIGRAMS_PER_CUBIC_METER,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
(DeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
|
(DeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
|
||||||
|
@ -54,26 +69,18 @@ SENSOR_DESCRIPTIONS = {
|
||||||
native_unit_of_measurement=LIGHT_LUX,
|
native_unit_of_measurement=LIGHT_LUX,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
|
(DeviceClass.MOISTURE, Units.PERCENTAGE): SensorEntityDescription(
|
||||||
|
key=f"{DeviceClass.MOISTURE}_{Units.PERCENTAGE}",
|
||||||
|
device_class=SensorDeviceClass.MOISTURE,
|
||||||
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
),
|
||||||
(DeviceClass.PRESSURE, Units.PRESSURE_MBAR): SensorEntityDescription(
|
(DeviceClass.PRESSURE, Units.PRESSURE_MBAR): SensorEntityDescription(
|
||||||
key=f"{DeviceClass.PRESSURE}_{Units.PRESSURE_MBAR}",
|
key=f"{DeviceClass.PRESSURE}_{Units.PRESSURE_MBAR}",
|
||||||
device_class=SensorDeviceClass.PRESSURE,
|
device_class=SensorDeviceClass.PRESSURE,
|
||||||
native_unit_of_measurement=PRESSURE_MBAR,
|
native_unit_of_measurement=PRESSURE_MBAR,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
(DeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
|
|
||||||
key=f"{DeviceClass.BATTERY}_{Units.PERCENTAGE}",
|
|
||||||
device_class=SensorDeviceClass.BATTERY,
|
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
|
||||||
),
|
|
||||||
(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,
|
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
|
||||||
),
|
|
||||||
(
|
(
|
||||||
DeviceClass.SIGNAL_STRENGTH,
|
DeviceClass.SIGNAL_STRENGTH,
|
||||||
Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
Units.SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||||
|
@ -85,26 +92,26 @@ SENSOR_DESCRIPTIONS = {
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
entity_category=EntityCategory.DIAGNOSTIC,
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
),
|
),
|
||||||
# Used for e.g. moisture sensor on HHCCJCY01
|
(DeviceClass.TEMPERATURE, Units.TEMP_CELSIUS): SensorEntityDescription(
|
||||||
|
key=f"{DeviceClass.TEMPERATURE}_{Units.TEMP_CELSIUS}",
|
||||||
|
device_class=SensorDeviceClass.TEMPERATURE,
|
||||||
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
),
|
||||||
|
(DeviceClass.VOLTAGE, Units.ELECTRIC_POTENTIAL_VOLT): SensorEntityDescription(
|
||||||
|
key=f"{DeviceClass.VOLTAGE}_{Units.ELECTRIC_POTENTIAL_VOLT}",
|
||||||
|
device_class=SensorDeviceClass.VOLTAGE,
|
||||||
|
native_unit_of_measurement=ELECTRIC_POTENTIAL_VOLT,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
entity_category=EntityCategory.DIAGNOSTIC,
|
||||||
|
),
|
||||||
|
# Used for e.g. consumable sensor on WX08ZM
|
||||||
(None, Units.PERCENTAGE): SensorEntityDescription(
|
(None, Units.PERCENTAGE): SensorEntityDescription(
|
||||||
key=str(Units.PERCENTAGE),
|
key=str(Units.PERCENTAGE),
|
||||||
device_class=None,
|
device_class=None,
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
state_class=SensorStateClass.MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
# Used for e.g. conductivity sensor on HHCCJCY01
|
|
||||||
(None, Units.CONDUCTIVITY): SensorEntityDescription(
|
|
||||||
key=str(Units.CONDUCTIVITY),
|
|
||||||
device_class=None,
|
|
||||||
native_unit_of_measurement=CONDUCTIVITY,
|
|
||||||
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,
|
|
||||||
),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -384,6 +384,11 @@ BLUETOOTH: list[dict[str, bool | str | int | list[int]]] = [
|
||||||
],
|
],
|
||||||
"manufacturer_id": 76,
|
"manufacturer_id": 76,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"connectable": False,
|
||||||
|
"domain": "xiaomi_ble",
|
||||||
|
"service_data_uuid": "0000fd50-0000-1000-8000-00805f9b34fb",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"connectable": False,
|
"connectable": False,
|
||||||
"domain": "xiaomi_ble",
|
"domain": "xiaomi_ble",
|
||||||
|
|
|
@ -2576,7 +2576,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.10.0
|
xiaomi-ble==0.12.1
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==1.2.0
|
xknx==1.2.0
|
||||||
|
|
|
@ -1789,7 +1789,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.10.0
|
xiaomi-ble==0.12.1
|
||||||
|
|
||||||
# homeassistant.components.knx
|
# homeassistant.components.knx
|
||||||
xknx==1.2.0
|
xknx==1.2.0
|
||||||
|
|
|
@ -84,6 +84,20 @@ YLKG07YL_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||||
connectable=False,
|
connectable=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
HHCCJCY10_SERVICE_INFO = BluetoothServiceInfoBleak(
|
||||||
|
name="HHCCJCY10",
|
||||||
|
address="DC:23:4D:E5:5B:FC",
|
||||||
|
device=BLEDevice("00:00:00:00:00:00", None),
|
||||||
|
rssi=-56,
|
||||||
|
manufacturer_data={},
|
||||||
|
service_data={"0000fd50-0000-1000-8000-00805f9b34fb": b"\x0e\x00n\x014\xa4(\x00["},
|
||||||
|
service_uuids=["0000fd50-0000-1000-8000-00805f9b34fb"],
|
||||||
|
source="local",
|
||||||
|
advertisement=generate_advertisement_data(local_name="Not it"),
|
||||||
|
time=0,
|
||||||
|
connectable=False,
|
||||||
|
)
|
||||||
|
|
||||||
MISSING_PAYLOAD_ENCRYPTED = BluetoothServiceInfoBleak(
|
MISSING_PAYLOAD_ENCRYPTED = BluetoothServiceInfoBleak(
|
||||||
name="LYWSD02MMC",
|
name="LYWSD02MMC",
|
||||||
address="A4:C1:38:56:53:84",
|
address="A4:C1:38:56:53:84",
|
||||||
|
|
|
@ -5,7 +5,7 @@ from homeassistant.components.sensor import ATTR_STATE_CLASS
|
||||||
from homeassistant.components.xiaomi_ble.const import DOMAIN
|
from homeassistant.components.xiaomi_ble.const import DOMAIN
|
||||||
from homeassistant.const import ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT
|
from homeassistant.const import ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT
|
||||||
|
|
||||||
from . import MMC_T201_1_SERVICE_INFO, make_advertisement
|
from . import HHCCJCY10_SERVICE_INFO, MMC_T201_1_SERVICE_INFO, make_advertisement
|
||||||
|
|
||||||
from tests.common import MockConfigEntry
|
from tests.common import MockConfigEntry
|
||||||
from tests.components.bluetooth import inject_bluetooth_service_info_bleak
|
from tests.components.bluetooth import inject_bluetooth_service_info_bleak
|
||||||
|
@ -433,3 +433,58 @@ async def test_xiaomi_CGDK2(hass):
|
||||||
|
|
||||||
assert await hass.config_entries.async_unload(entry.entry_id)
|
assert await hass.config_entries.async_unload(entry.entry_id)
|
||||||
await hass.async_block_till_done()
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
|
||||||
|
async def test_hhcc_HHCCJCY10(hass):
|
||||||
|
"""This device used a different UUID compared to the other Xiaomi sensors."""
|
||||||
|
entry = MockConfigEntry(
|
||||||
|
domain=DOMAIN,
|
||||||
|
unique_id="DC:23:4D:E5:5B:FC",
|
||||||
|
)
|
||||||
|
entry.add_to_hass(hass)
|
||||||
|
|
||||||
|
assert await hass.config_entries.async_setup(entry.entry_id)
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
|
||||||
|
inject_bluetooth_service_info_bleak(hass, HHCCJCY10_SERVICE_INFO)
|
||||||
|
|
||||||
|
await hass.async_block_till_done()
|
||||||
|
assert len(hass.states.async_all()) == 5
|
||||||
|
|
||||||
|
temp_sensor = hass.states.get("sensor.plant_sensor_5bfc_temperature")
|
||||||
|
temp_sensor_attr = temp_sensor.attributes
|
||||||
|
assert temp_sensor.state == "11.0"
|
||||||
|
assert temp_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 5BFC Temperature"
|
||||||
|
assert temp_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "°C"
|
||||||
|
assert temp_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||||
|
|
||||||
|
illu_sensor = hass.states.get("sensor.plant_sensor_5bfc_illuminance")
|
||||||
|
illu_sensor_attr = illu_sensor.attributes
|
||||||
|
assert illu_sensor.state == "79012"
|
||||||
|
assert illu_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 5BFC Illuminance"
|
||||||
|
assert illu_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "lx"
|
||||||
|
assert illu_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||||
|
|
||||||
|
cond_sensor = hass.states.get("sensor.plant_sensor_5bfc_conductivity")
|
||||||
|
cond_sensor_attr = cond_sensor.attributes
|
||||||
|
assert cond_sensor.state == "91"
|
||||||
|
assert cond_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 5BFC Conductivity"
|
||||||
|
assert cond_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "µS/cm"
|
||||||
|
assert cond_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||||
|
|
||||||
|
moist_sensor = hass.states.get("sensor.plant_sensor_5bfc_moisture")
|
||||||
|
moist_sensor_attr = moist_sensor.attributes
|
||||||
|
assert moist_sensor.state == "14"
|
||||||
|
assert moist_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 5BFC Moisture"
|
||||||
|
assert moist_sensor_attr[ATTR_UNIT_OF_MEASUREMENT] == "%"
|
||||||
|
assert moist_sensor_attr[ATTR_STATE_CLASS] == "measurement"
|
||||||
|
|
||||||
|
bat_sensor = hass.states.get("sensor.plant_sensor_5bfc_battery")
|
||||||
|
bat_sensor_attr = bat_sensor.attributes
|
||||||
|
assert bat_sensor.state == "40"
|
||||||
|
assert bat_sensor_attr[ATTR_FRIENDLY_NAME] == "Plant Sensor 5BFC 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()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue