Remember inkbird device type in the config entry (#138967)

This commit is contained in:
J. Nick Koston 2025-02-21 06:22:34 -06:00 committed by GitHub
parent 113e703d5c
commit 4f43c971cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 79 additions and 18 deletions

View File

@ -4,17 +4,20 @@ from __future__ import annotations
import logging
from inkbird_ble import INKBIRDBluetoothDeviceData
from inkbird_ble import INKBIRDBluetoothDeviceData, SensorUpdate
from homeassistant.components.bluetooth import BluetoothScanningMode
from homeassistant.components.bluetooth import (
BluetoothScanningMode,
BluetoothServiceInfo,
)
from homeassistant.components.bluetooth.passive_update_processor import (
PassiveBluetoothProcessorCoordinator,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import Platform
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, callback
from .const import DOMAIN
from .const import CONF_DEVICE_TYPE, DOMAIN
PLATFORMS: list[Platform] = [Platform.SENSOR]
@ -25,20 +28,33 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Set up INKBIRD BLE device from a config entry."""
address = entry.unique_id
assert address is not None
data = INKBIRDBluetoothDeviceData()
coordinator = hass.data.setdefault(DOMAIN, {})[entry.entry_id] = (
PassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.ACTIVE,
update_method=data.update,
)
device_type: str | None = entry.data.get(CONF_DEVICE_TYPE)
data = INKBIRDBluetoothDeviceData(device_type)
@callback
def _async_on_update(service_info: BluetoothServiceInfo) -> SensorUpdate:
"""Handle update callback from the passive BLE processor."""
nonlocal device_type
update = data.update(service_info)
if device_type is None and data.device_type is not None:
device_type_str = str(data.device_type)
hass.config_entries.async_update_entry(
entry, data={**entry.data, CONF_DEVICE_TYPE: device_type_str}
)
device_type = device_type_str
return update
coordinator = PassiveBluetoothProcessorCoordinator(
hass,
_LOGGER,
address=address,
mode=BluetoothScanningMode.ACTIVE,
update_method=_async_on_update,
)
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(
coordinator.async_start()
) # only start after all platforms have had a chance to subscribe
# only start after all platforms have had a chance to subscribe
entry.async_on_unload(coordinator.async_start())
return True

View File

@ -1,3 +1,5 @@
"""Constants for the INKBIRD Bluetooth integration."""
DOMAIN = "inkbird"
CONF_DEVICE_TYPE = "device_type"

View File

@ -22,6 +22,17 @@ SPS_SERVICE_INFO = BluetoothServiceInfo(
source="local",
)
SPS_WITH_CORRUPT_NAME_SERVICE_INFO = BluetoothServiceInfo(
name="XXXXcorruptXXXX",
address="AA:BB:CC:DD:EE:FF",
rssi=-63,
service_data={},
manufacturer_data={2096: b"\x0f\x12\x00Z\xc7W\x06"},
service_uuids=["0000fff0-0000-1000-8000-00805f9b34fb"],
source="local",
)
IBBQ_SERVICE_INFO = BluetoothServiceInfo(
name="iBBQ",
address="4125DDBA-2774-4851-9889-6AADDD4CAC3D",

View File

@ -1,11 +1,11 @@
"""Test the INKBIRD config flow."""
from homeassistant.components.inkbird.const import DOMAIN
from homeassistant.components.inkbird.const import CONF_DEVICE_TYPE, DOMAIN
from homeassistant.components.sensor import ATTR_STATE_CLASS
from homeassistant.const import ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT
from homeassistant.core import HomeAssistant
from . import SPS_SERVICE_INFO
from . import SPS_SERVICE_INFO, SPS_WITH_CORRUPT_NAME_SERVICE_INFO
from tests.common import MockConfigEntry
from tests.components.bluetooth import inject_bluetooth_service_info
@ -34,5 +34,37 @@ async def test_sensors(hass: HomeAssistant) -> None:
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
# Make sure we remember the device type
# in case the name is corrupted later
assert entry.data[CONF_DEVICE_TYPE] == "IBS-TH"
assert await hass.config_entries.async_unload(entry.entry_id)
await hass.async_block_till_done()
async def test_device_with_corrupt_name(hass: HomeAssistant) -> None:
"""Test setting up a known device type with a corrupt name."""
entry = MockConfigEntry(
domain=DOMAIN,
unique_id="AA:BB:CC:DD:EE:FF",
data={CONF_DEVICE_TYPE: "IBS-TH"},
)
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(hass, SPS_WITH_CORRUPT_NAME_SERVICE_INFO)
await hass.async_block_till_done()
assert len(hass.states.async_all()) == 3
temp_sensor = hass.states.get("sensor.ibs_th_eeff_battery")
temp_sensor_attribtes = temp_sensor.attributes
assert temp_sensor.state == "87"
assert temp_sensor_attribtes[ATTR_FRIENDLY_NAME] == "IBS-TH EEFF Battery"
assert temp_sensor_attribtes[ATTR_UNIT_OF_MEASUREMENT] == "%"
assert temp_sensor_attribtes[ATTR_STATE_CLASS] == "measurement"
assert entry.data[CONF_DEVICE_TYPE] == "IBS-TH"
assert await hass.config_entries.async_unload(entry.entry_id)
await hass.async_block_till_done()