From 89946e0981050bb4e5fd4fd1476f634203c996aa Mon Sep 17 00:00:00 2001 From: zerzhang <916250497@qq.com> Date: Wed, 22 Oct 2025 20:18:13 +0800 Subject: [PATCH] add support for climate panel --- .../components/switchbot/__init__.py | 1 + .../components/switchbot/binary_sensor.py | 1 - homeassistant/components/switchbot/const.py | 3 + tests/components/switchbot/__init__.py | 29 +++++++++ tests/components/switchbot/test_sensor.py | 64 +++++++++++++++++++ 5 files changed, 97 insertions(+), 1 deletion(-) diff --git a/homeassistant/components/switchbot/__init__.py b/homeassistant/components/switchbot/__init__.py index 415ba4d48dafab..cd8a8b08f1d336 100644 --- a/homeassistant/components/switchbot/__init__.py +++ b/homeassistant/components/switchbot/__init__.py @@ -101,6 +101,7 @@ SupportedModels.PLUG_MINI_EU.value: [Platform.SWITCH, Platform.SENSOR], SupportedModels.RELAY_SWITCH_2PM.value: [Platform.SWITCH, Platform.SENSOR], SupportedModels.GARAGE_DOOR_OPENER.value: [Platform.COVER, Platform.SENSOR], + SupportedModels.CLIMATE_PANEL.value: [Platform.SENSOR, Platform.BINARY_SENSOR], } CLASS_BY_DEVICE = { SupportedModels.CEILING_LIGHT.value: switchbot.SwitchbotCeilingLight, diff --git a/homeassistant/components/switchbot/binary_sensor.py b/homeassistant/components/switchbot/binary_sensor.py index 6d1490c895b3ad..fc87ad2e497528 100644 --- a/homeassistant/components/switchbot/binary_sensor.py +++ b/homeassistant/components/switchbot/binary_sensor.py @@ -24,7 +24,6 @@ ), "motion_detected": BinarySensorEntityDescription( key="pir_state", - name=None, device_class=BinarySensorDeviceClass.MOTION, ), "contact_open": BinarySensorEntityDescription( diff --git a/homeassistant/components/switchbot/const.py b/homeassistant/components/switchbot/const.py index 80f7978f4dc315..4c29ed7d67298f 100644 --- a/homeassistant/components/switchbot/const.py +++ b/homeassistant/components/switchbot/const.py @@ -57,6 +57,7 @@ class SupportedModels(StrEnum): RELAY_SWITCH_2PM = "relay_switch_2pm" K11_PLUS_VACUUM = "k11+_vacuum" GARAGE_DOOR_OPENER = "garage_door_opener" + CLIMATE_PANEL = "climate_panel" CONNECTABLE_SUPPORTED_MODEL_TYPES = { @@ -93,6 +94,7 @@ class SupportedModels(StrEnum): SwitchbotModel.RELAY_SWITCH_2PM: SupportedModels.RELAY_SWITCH_2PM, SwitchbotModel.K11_VACUUM: SupportedModels.K11_PLUS_VACUUM, SwitchbotModel.GARAGE_DOOR_OPENER: SupportedModels.GARAGE_DOOR_OPENER, + SwitchbotModel.CLIMATE_PANEL: SupportedModels.CLIMATE_PANEL, } NON_CONNECTABLE_SUPPORTED_MODEL_TYPES = { @@ -106,6 +108,7 @@ class SupportedModels(StrEnum): SwitchbotModel.REMOTE: SupportedModels.REMOTE, SwitchbotModel.HUBMINI_MATTER: SupportedModels.HUBMINI_MATTER, SwitchbotModel.HUB3: SupportedModels.HUB3, + SwitchbotModel.CLIMATE_PANEL: SupportedModels.CLIMATE_PANEL, } SUPPORTED_MODEL_TYPES = ( diff --git a/tests/components/switchbot/__init__.py b/tests/components/switchbot/__init__.py index 9fc401270fbaeb..4a9fcd772b20c7 100644 --- a/tests/components/switchbot/__init__.py +++ b/tests/components/switchbot/__init__.py @@ -1171,3 +1171,32 @@ def make_advertisement( connectable=True, tx_power=-127, ) + + +CLIMATE_PANEL_SERVICE_INFO = BluetoothServiceInfoBleak( + name="Climate Panel", + manufacturer_data={ + 2409: b"\xb0\xe9\xfe\x8e\x98Oi_\x06\x9a,\x00\x00\x00\x00\xe4\x00\x08\x04\x00\x01\x00\x00" + }, + service_data={ + "0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00 _\x00\x10\xf3\xd8@", + }, + service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"], + address="AA:BB:CC:DD:EE:FF", + rssi=-60, + source="local", + advertisement=generate_advertisement_data( + local_name="Climate Panel", + manufacturer_data={ + 2409: b"\xb0\xe9\xfe\x8e\x98Oi_\x06\x9a,\x00\x00\x00\x00\xe4\x00\x08\x04\x00\x01\x00\x00" + }, + service_data={ + "0000fd3d-0000-1000-8000-00805f9b34fb": b"\x00 _\x00\x10\xf3\xd8@" + }, + service_uuids=["cba20d00-224d-11e6-9fb8-0002a5d5c51b"], + ), + device=generate_ble_device("AA:BB:CC:DD:EE:FF", "Climate Panel"), + time=0, + connectable=True, + tx_power=-127, +) diff --git a/tests/components/switchbot/test_sensor.py b/tests/components/switchbot/test_sensor.py index 0e46324076696d..b38a4e43fbfd63 100644 --- a/tests/components/switchbot/test_sensor.py +++ b/tests/components/switchbot/test_sensor.py @@ -24,6 +24,7 @@ from . import ( CIRCULATOR_FAN_SERVICE_INFO, + CLIMATE_PANEL_SERVICE_INFO, EVAPORATIVE_HUMIDIFIER_SERVICE_INFO, HUB3_SERVICE_INFO, HUBMINI_MATTER_SERVICE_INFO, @@ -728,3 +729,66 @@ async def test_relay_switch_2pm_sensor(hass: HomeAssistant) -> None: assert await hass.config_entries.async_unload(entry.entry_id) await hass.async_block_till_done() + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_climate_panel_sensor(hass: HomeAssistant) -> None: + """Test setting up creates the sensor for Climate Panel.""" + await async_setup_component(hass, DOMAIN, {}) + inject_bluetooth_service_info(hass, CLIMATE_PANEL_SERVICE_INFO) + + entry = MockConfigEntry( + domain=DOMAIN, + data={ + CONF_ADDRESS: "AA:BB:CC:DD:EE:FF", + CONF_NAME: "test-name", + CONF_SENSOR_TYPE: "climate_panel", + }, + unique_id="aabbccddeeff", + ) + 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("sensor")) == 4 + assert len(hass.states.async_all("binary_sensor")) == 2 + + temperature_sensor = hass.states.get("sensor.test_name_temperature") + temperature_sensor_attrs = temperature_sensor.attributes + assert temperature_sensor.state == "26.6" + assert temperature_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Temperature" + assert temperature_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "°C" + assert temperature_sensor_attrs[ATTR_STATE_CLASS] == "measurement" + + humidity_sensor = hass.states.get("sensor.test_name_humidity") + humidity_sensor_attrs = humidity_sensor.attributes + assert humidity_sensor.state == "44" + assert humidity_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Humidity" + assert humidity_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "%" + assert humidity_sensor_attrs[ATTR_STATE_CLASS] == "measurement" + + rssi_sensor = hass.states.get("sensor.test_name_bluetooth_signal") + rssi_sensor_attrs = rssi_sensor.attributes + assert rssi_sensor.state == "-60" + assert rssi_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Bluetooth signal" + assert rssi_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "dBm" + + battery_sensor = hass.states.get("sensor.test_name_battery") + battery_sensor_attrs = battery_sensor.attributes + assert battery_sensor.state == "95" + assert battery_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Battery" + assert battery_sensor_attrs[ATTR_STATE_CLASS] == "measurement" + + light_sensor = hass.states.get("binary_sensor.test_name_light") + light_sensor_attrs = light_sensor.attributes + assert light_sensor.state == "off" + assert light_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Light" + + motion_sensor = hass.states.get("binary_sensor.test_name_motion") + motion_sensor_attrs = motion_sensor.attributes + assert motion_sensor.state == "on" + assert motion_sensor_attrs[ATTR_FRIENDLY_NAME] == "test-name Motion" + + assert await hass.config_entries.async_unload(entry.entry_id) + await hass.async_block_till_done()