diff --git a/homeassistant/components/bosch_shc/__init__.py b/homeassistant/components/bosch_shc/__init__.py index c5d56782fde3..621942675f71 100644 --- a/homeassistant/components/bosch_shc/__init__.py +++ b/homeassistant/components/bosch_shc/__init__.py @@ -1,6 +1,7 @@ """The Bosch Smart Home Controller integration.""" import logging +from typing import TYPE_CHECKING from boschshcpy import SHCSession from boschshcpy.exceptions import SHCAuthenticationError, SHCConnectionError @@ -47,6 +48,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: BoschConfigEntry) -> boo raise ConfigEntryNotReady from err shc_info = session.information + if TYPE_CHECKING: + assert shc_info is not None and shc_info.unique_id is not None if shc_info.updateState.name == "UPDATE_AVAILABLE": _LOGGER.warning("Please check for software updates in the Bosch Smart Home App") diff --git a/homeassistant/components/bosch_shc/binary_sensor.py b/homeassistant/components/bosch_shc/binary_sensor.py index 097d7ca6a120..c9632152ed8a 100644 --- a/homeassistant/components/bosch_shc/binary_sensor.py +++ b/homeassistant/components/bosch_shc/binary_sensor.py @@ -1,8 +1,13 @@ """Platform for binarysensor integration.""" -from typing import override +from typing import TYPE_CHECKING, override -from boschshcpy import SHCBatteryDevice, SHCShutterContact +from boschshcpy import ( + BatteryLevelService, + SHCBatteryDevice, + SHCShutterContact, + ShutterContactService, +) from boschshcpy.device import SHCDevice from homeassistant.components.binary_sensor import ( @@ -24,34 +29,38 @@ async def async_setup_entry( """Set up the SHC binary sensor platform.""" session = config_entry.runtime_data + shc_info = session.information + if TYPE_CHECKING: + assert shc_info is not None and shc_info.unique_id is not None + entities: list[BinarySensorEntity] = [ ShutterContactSensor( device=binary_sensor, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, ) for binary_sensor in ( - session.device_helper.shutter_contacts - + session.device_helper.shutter_contacts2 + *session.device_helper.shutter_contacts, + *session.device_helper.shutter_contacts2, ) ] entities.extend( BatterySensor( device=binary_sensor, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, ) for binary_sensor in ( - session.device_helper.motion_detectors - + session.device_helper.shutter_contacts - + session.device_helper.shutter_contacts2 - + session.device_helper.smoke_detectors - + session.device_helper.thermostats - + session.device_helper.twinguards - + session.device_helper.universal_switches - + session.device_helper.wallthermostats - + session.device_helper.water_leakage_detectors + *session.device_helper.motion_detectors, + *session.device_helper.shutter_contacts, + *session.device_helper.shutter_contacts2, + *session.device_helper.smoke_detectors, + *session.device_helper.thermostats, + *session.device_helper.twinguards, + *session.device_helper.universal_switches, + *session.device_helper.wallthermostats, + *session.device_helper.water_leakage_detectors, ) ) @@ -62,11 +71,12 @@ class ShutterContactSensor(SHCEntity, BinarySensorEntity): """Representation of an SHC shutter contact sensor.""" _attr_name = None + _device: SHCShutterContact def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: - """Initialize an SHC shutter contact sensor..""" + """Initialize an SHC shutter contact sensor.""" super().__init__(device, parent_id, entry_id) - switcher = { + switcher: dict[str | None, BinarySensorDeviceClass] = { "ENTRANCE_DOOR": BinarySensorDeviceClass.DOOR, "REGULAR_WINDOW": BinarySensorDeviceClass.WINDOW, "FRENCH_WINDOW": BinarySensorDeviceClass.DOOR, @@ -80,13 +90,14 @@ class ShutterContactSensor(SHCEntity, BinarySensorEntity): @override def is_on(self) -> bool: """Return the state of the sensor.""" - return self._device.state == SHCShutterContact.ShutterContactService.State.OPEN + return self._device.state is ShutterContactService.State.OPEN class BatterySensor(SHCEntity, BinarySensorEntity): """Representation of an SHC battery reporting sensor.""" _attr_device_class = BinarySensorDeviceClass.BATTERY + _device: SHCBatteryDevice def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: """Initialize an SHC battery reporting sensor.""" @@ -97,6 +108,4 @@ class BatterySensor(SHCEntity, BinarySensorEntity): @override def is_on(self) -> bool: """Return the state of the sensor.""" - return ( - self._device.batterylevel != SHCBatteryDevice.BatteryLevelService.State.OK - ) + return self._device.batterylevel is not BatteryLevelService.State.OK diff --git a/homeassistant/components/bosch_shc/cover.py b/homeassistant/components/bosch_shc/cover.py index ddc21945e0a2..931d335da3ed 100644 --- a/homeassistant/components/bosch_shc/cover.py +++ b/homeassistant/components/bosch_shc/cover.py @@ -1,8 +1,8 @@ """Platform for cover integration.""" -from typing import Any, override +from typing import TYPE_CHECKING, Any, override -from boschshcpy import SHCShutterControl +from boschshcpy import SHCShutterControl, ShutterControlService from homeassistant.components.cover import ( ATTR_POSITION, @@ -25,10 +25,14 @@ async def async_setup_entry( """Set up the SHC cover platform.""" session = config_entry.runtime_data + shc_info = session.information + if TYPE_CHECKING: + assert shc_info is not None and shc_info.unique_id is not None + async_add_entities( ShutterControlCover( device=cover, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, ) for cover in session.device_helper.shutter_controls @@ -40,6 +44,7 @@ class ShutterControlCover(SHCEntity, CoverEntity): _attr_name = None _attr_device_class = CoverDeviceClass.SHUTTER + _device: SHCShutterControl _attr_supported_features = ( CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE @@ -68,19 +73,13 @@ class ShutterControlCover(SHCEntity, CoverEntity): @override def is_opening(self) -> bool: """Return if the cover is opening or not.""" - return ( - self._device.operation_state - == SHCShutterControl.ShutterControlService.State.OPENING - ) + return self._device.operation_state is ShutterControlService.State.OPENING @property @override def is_closing(self) -> bool: """Return if the cover is closing or not.""" - return ( - self._device.operation_state - == SHCShutterControl.ShutterControlService.State.CLOSING - ) + return self._device.operation_state is ShutterControlService.State.CLOSING @override def open_cover(self, **kwargs: Any) -> None: diff --git a/homeassistant/components/bosch_shc/entity.py b/homeassistant/components/bosch_shc/entity.py index 4b70eee92789..b43a07741057 100644 --- a/homeassistant/components/bosch_shc/entity.py +++ b/homeassistant/components/bosch_shc/entity.py @@ -65,6 +65,8 @@ class SHCBaseEntity(Entity): class SHCEntity(SHCBaseEntity): """Representation of a SHC device entity.""" + _device: SHCDevice + def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: """Initialize generic SHC device.""" self._attr_unique_id = device.serial @@ -105,6 +107,8 @@ class SHCEntity(SHCBaseEntity): class SHCDomainEntity(SHCBaseEntity): """Representation of a SHC domain service entity.""" + _device: SHCIntrusionSystem + def __init__( self, domain: SHCIntrusionSystem, parent_id: str, entry_id: str ) -> None: diff --git a/homeassistant/components/bosch_shc/manifest.json b/homeassistant/components/bosch_shc/manifest.json index 83bbc1f62163..502f9f6cb530 100644 --- a/homeassistant/components/bosch_shc/manifest.json +++ b/homeassistant/components/bosch_shc/manifest.json @@ -8,7 +8,7 @@ "integration_type": "hub", "iot_class": "local_push", "loggers": ["boschshcpy"], - "requirements": ["boschshcpy==0.3.5"], + "requirements": ["boschshcpy==0.6.4"], "zeroconf": [ { "name": "bosch shc*", diff --git a/homeassistant/components/bosch_shc/sensor.py b/homeassistant/components/bosch_shc/sensor.py index 0c68c0bdd550..8c1d31da48a8 100644 --- a/homeassistant/components/bosch_shc/sensor.py +++ b/homeassistant/components/bosch_shc/sensor.py @@ -2,8 +2,16 @@ from collections.abc import Callable from dataclasses import dataclass -from typing import Any, override +from typing import TYPE_CHECKING, Any, override +from boschshcpy import ( + SHCLightSwitchBSM, + SHCSmartPlug, + SHCSmartPlugCompact, + SHCThermostat, + SHCTwinguard, + SHCWallThermostat, +) from boschshcpy.device import SHCDevice from homeassistant.components.sensor import ( @@ -27,12 +35,17 @@ from .entity import SHCEntity @dataclass(frozen=True, kw_only=True) -class SHCSensorEntityDescription(SensorEntityDescription): - """Describes a SHC sensor.""" +class SHCSensorEntityDescription[_DeviceT: SHCDevice](SensorEntityDescription): + """Describes a SHC sensor. - value_fn: Callable[[SHCDevice], StateType] - attributes_fn: Callable[[SHCDevice], dict[str, Any]] | None = None + Never share one instance across descriptions for different device types. + """ + value_fn: Callable[[_DeviceT], StateType] + attributes_fn: Callable[[_DeviceT], dict[str, Any]] | None = None + + +_PowerMeterDevice = SHCSmartPlug | SHCLightSwitchBSM TEMPERATURE_SENSOR = "temperature" HUMIDITY_SENSOR = "humidity" @@ -46,68 +59,17 @@ POWER_SENSOR = "power" ENERGY_SENSOR = "energy" COMMUNICATION_QUALITY_SENSOR = "communication_quality" -SENSOR_DESCRIPTIONS: dict[str, SHCSensorEntityDescription] = { - TEMPERATURE_SENSOR: SHCSensorEntityDescription( +_THERMOSTAT_TEMPERATURE_DESCRIPTION: SHCSensorEntityDescription[SHCThermostat] = ( + SHCSensorEntityDescription( key=TEMPERATURE_SENSOR, device_class=SensorDeviceClass.TEMPERATURE, state_class=SensorStateClass.MEASUREMENT, native_unit_of_measurement=UnitOfTemperature.CELSIUS, value_fn=lambda device: device.temperature, - ), - HUMIDITY_SENSOR: SHCSensorEntityDescription( - key=HUMIDITY_SENSOR, - device_class=SensorDeviceClass.HUMIDITY, - native_unit_of_measurement=UnitOfRatio.PERCENTAGE, - value_fn=lambda device: device.humidity, - ), - PURITY_SENSOR: SHCSensorEntityDescription( - key=PURITY_SENSOR, - translation_key=PURITY_SENSOR, - native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION, - value_fn=lambda device: device.purity, - ), - AIR_QUALITY_SENSOR: SHCSensorEntityDescription( - key=AIR_QUALITY_SENSOR, - translation_key="air_quality", - value_fn=lambda device: device.combined_rating.name, - attributes_fn=lambda device: { - "rating_description": device.description, - }, - ), - TEMPERATURE_RATING_SENSOR: SHCSensorEntityDescription( - key=TEMPERATURE_RATING_SENSOR, - translation_key=TEMPERATURE_RATING_SENSOR, - value_fn=lambda device: device.temperature_rating.name, - ), - COMMUNICATION_QUALITY_SENSOR: SHCSensorEntityDescription( - key=COMMUNICATION_QUALITY_SENSOR, - translation_key=COMMUNICATION_QUALITY_SENSOR, - value_fn=lambda device: device.communicationquality.name, - ), - HUMIDITY_RATING_SENSOR: SHCSensorEntityDescription( - key=HUMIDITY_RATING_SENSOR, - translation_key=HUMIDITY_RATING_SENSOR, - value_fn=lambda device: device.humidity_rating.name, - ), - PURITY_RATING_SENSOR: SHCSensorEntityDescription( - key=PURITY_RATING_SENSOR, - translation_key=PURITY_RATING_SENSOR, - value_fn=lambda device: device.purity_rating.name, - ), - POWER_SENSOR: SHCSensorEntityDescription( - key=POWER_SENSOR, - device_class=SensorDeviceClass.POWER, - native_unit_of_measurement=UnitOfPower.WATT, - value_fn=lambda device: device.powerconsumption, - ), - ENERGY_SENSOR: SHCSensorEntityDescription( - key=ENERGY_SENSOR, - device_class=SensorDeviceClass.ENERGY, - state_class=SensorStateClass.TOTAL_INCREASING, - native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, - value_fn=lambda device: device.energyconsumption / 1000.0, - ), - VALVE_TAPPET_SENSOR: SHCSensorEntityDescription( + ) +) +_VALVE_TAPPET_DESCRIPTION: SHCSensorEntityDescription[SHCThermostat] = ( + SHCSensorEntityDescription( key=VALVE_TAPPET_SENSOR, translation_key=VALVE_TAPPET_SENSOR, state_class=SensorStateClass.MEASUREMENT, @@ -116,8 +78,122 @@ SENSOR_DESCRIPTIONS: dict[str, SHCSensorEntityDescription] = { attributes_fn=lambda device: { "valve_tappet_state": device.valvestate.name, }, - ), -} + ) +) +_WALLTHERMOSTAT_TEMPERATURE_DESCRIPTION: SHCSensorEntityDescription[ + SHCWallThermostat +] = SHCSensorEntityDescription( + key=TEMPERATURE_SENSOR, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + value_fn=lambda device: device.temperature, +) +_WALLTHERMOSTAT_HUMIDITY_DESCRIPTION: SHCSensorEntityDescription[SHCWallThermostat] = ( + SHCSensorEntityDescription( + key=HUMIDITY_SENSOR, + device_class=SensorDeviceClass.HUMIDITY, + native_unit_of_measurement=UnitOfRatio.PERCENTAGE, + value_fn=lambda device: device.humidity, + ) +) +_TWINGUARD_TEMPERATURE_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=TEMPERATURE_SENSOR, + device_class=SensorDeviceClass.TEMPERATURE, + state_class=SensorStateClass.MEASUREMENT, + native_unit_of_measurement=UnitOfTemperature.CELSIUS, + value_fn=lambda device: device.temperature, + ) +) +_TWINGUARD_HUMIDITY_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=HUMIDITY_SENSOR, + device_class=SensorDeviceClass.HUMIDITY, + native_unit_of_measurement=UnitOfRatio.PERCENTAGE, + value_fn=lambda device: device.humidity, + ) +) +_PURITY_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=PURITY_SENSOR, + translation_key=PURITY_SENSOR, + native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION, + value_fn=lambda device: device.purity, + ) +) +_AIR_QUALITY_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=AIR_QUALITY_SENSOR, + translation_key="air_quality", + value_fn=lambda device: device.combined_rating.name, + attributes_fn=lambda device: { + "rating_description": device.description, + }, + ) +) +_TEMPERATURE_RATING_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=TEMPERATURE_RATING_SENSOR, + translation_key=TEMPERATURE_RATING_SENSOR, + value_fn=lambda device: device.temperature_rating.name, + ) +) +_HUMIDITY_RATING_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=HUMIDITY_RATING_SENSOR, + translation_key=HUMIDITY_RATING_SENSOR, + value_fn=lambda device: device.humidity_rating.name, + ) +) +_PURITY_RATING_DESCRIPTION: SHCSensorEntityDescription[SHCTwinguard] = ( + SHCSensorEntityDescription( + key=PURITY_RATING_SENSOR, + translation_key=PURITY_RATING_SENSOR, + value_fn=lambda device: device.purity_rating.name, + ) +) +_POWER_DESCRIPTION: SHCSensorEntityDescription[_PowerMeterDevice] = ( + SHCSensorEntityDescription( + key=POWER_SENSOR, + device_class=SensorDeviceClass.POWER, + native_unit_of_measurement=UnitOfPower.WATT, + value_fn=lambda device: device.powerconsumption, + ) +) +_ENERGY_DESCRIPTION: SHCSensorEntityDescription[_PowerMeterDevice] = ( + SHCSensorEntityDescription( + key=ENERGY_SENSOR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_fn=lambda device: device.energyconsumption / 1000.0, + ) +) +_COMPACT_POWER_DESCRIPTION: SHCSensorEntityDescription[SHCSmartPlugCompact] = ( + SHCSensorEntityDescription( + key=POWER_SENSOR, + device_class=SensorDeviceClass.POWER, + native_unit_of_measurement=UnitOfPower.WATT, + value_fn=lambda device: device.powerconsumption, + ) +) +_COMPACT_ENERGY_DESCRIPTION: SHCSensorEntityDescription[SHCSmartPlugCompact] = ( + SHCSensorEntityDescription( + key=ENERGY_SENSOR, + device_class=SensorDeviceClass.ENERGY, + state_class=SensorStateClass.TOTAL_INCREASING, + native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR, + value_fn=lambda device: device.energyconsumption / 1000.0, + ) +) +_COMMUNICATION_QUALITY_DESCRIPTION: SHCSensorEntityDescription[SHCSmartPlugCompact] = ( + SHCSensorEntityDescription( + key=COMMUNICATION_QUALITY_SENSOR, + translation_key=COMMUNICATION_QUALITY_SENSOR, + value_fn=lambda device: device.communicationquality.name, + ) +) async def async_setup_entry( @@ -128,88 +204,105 @@ async def async_setup_entry( """Set up the SHC sensor platform.""" session = config_entry.runtime_data + shc_info = session.information + if TYPE_CHECKING: + assert shc_info is not None and shc_info.unique_id is not None + entities: list[SensorEntity] = [ SHCSensor( device, - SENSOR_DESCRIPTIONS[sensor_type], - session.information.unique_id, + description, + shc_info.unique_id, config_entry.entry_id, ) for device in session.device_helper.thermostats - for sensor_type in (TEMPERATURE_SENSOR, VALVE_TAPPET_SENSOR) + for description in ( + _THERMOSTAT_TEMPERATURE_DESCRIPTION, + _VALVE_TAPPET_DESCRIPTION, + ) ] entities.extend( SHCSensor( device, - SENSOR_DESCRIPTIONS[sensor_type], - session.information.unique_id, + description, + shc_info.unique_id, config_entry.entry_id, ) for device in session.device_helper.wallthermostats - for sensor_type in (TEMPERATURE_SENSOR, HUMIDITY_SENSOR) + for description in ( + _WALLTHERMOSTAT_TEMPERATURE_DESCRIPTION, + _WALLTHERMOSTAT_HUMIDITY_DESCRIPTION, + ) ) entities.extend( SHCSensor( device, - SENSOR_DESCRIPTIONS[sensor_type], - session.information.unique_id, + description, + shc_info.unique_id, config_entry.entry_id, ) for device in session.device_helper.twinguards - for sensor_type in ( - TEMPERATURE_SENSOR, - HUMIDITY_SENSOR, - PURITY_SENSOR, - AIR_QUALITY_SENSOR, - TEMPERATURE_RATING_SENSOR, - HUMIDITY_RATING_SENSOR, - PURITY_RATING_SENSOR, + for description in ( + _TWINGUARD_TEMPERATURE_DESCRIPTION, + _TWINGUARD_HUMIDITY_DESCRIPTION, + _PURITY_DESCRIPTION, + _AIR_QUALITY_DESCRIPTION, + _TEMPERATURE_RATING_DESCRIPTION, + _HUMIDITY_RATING_DESCRIPTION, + _PURITY_RATING_DESCRIPTION, ) ) + power_meter_devices: list[_PowerMeterDevice] = [ + *session.device_helper.smart_plugs, + *session.device_helper.light_switches_bsm, + ] entities.extend( SHCSensor( device, - SENSOR_DESCRIPTIONS[sensor_type], - session.information.unique_id, + description, + shc_info.unique_id, config_entry.entry_id, ) - for device in ( - session.device_helper.smart_plugs + session.device_helper.light_switches_bsm - ) - for sensor_type in (POWER_SENSOR, ENERGY_SENSOR) + for device in power_meter_devices + for description in (_POWER_DESCRIPTION, _ENERGY_DESCRIPTION) ) entities.extend( SHCSensor( device, - SENSOR_DESCRIPTIONS[sensor_type], - session.information.unique_id, + description, + shc_info.unique_id, config_entry.entry_id, ) for device in session.device_helper.smart_plugs_compact - for sensor_type in (POWER_SENSOR, ENERGY_SENSOR, COMMUNICATION_QUALITY_SENSOR) + for description in ( + _COMPACT_POWER_DESCRIPTION, + _COMPACT_ENERGY_DESCRIPTION, + _COMMUNICATION_QUALITY_DESCRIPTION, + ) ) async_add_entities(entities) -class SHCSensor(SHCEntity, SensorEntity): +class SHCSensor[_DeviceT: SHCDevice](SHCEntity, SensorEntity): """Representation of a SHC sensor.""" - entity_description: SHCSensorEntityDescription + entity_description: SHCSensorEntityDescription[_DeviceT] def __init__( self, - device: SHCDevice, - entity_description: SHCSensorEntityDescription, + device: _DeviceT, + entity_description: SHCSensorEntityDescription[_DeviceT], parent_id: str, entry_id: str, ) -> None: """Initialize sensor.""" super().__init__(device, parent_id, entry_id) + self._device: _DeviceT = device self.entity_description = entity_description self._attr_unique_id = f"{device.serial}_{entity_description.key}" diff --git a/homeassistant/components/bosch_shc/switch.py b/homeassistant/components/bosch_shc/switch.py index 6974bd0af31d..9537c544632e 100644 --- a/homeassistant/components/bosch_shc/switch.py +++ b/homeassistant/components/bosch_shc/switch.py @@ -1,14 +1,14 @@ """Platform for switch integration.""" from dataclasses import dataclass -from typing import Any, override +from enum import Enum +from typing import TYPE_CHECKING, Any, override from boschshcpy import ( - SHCCamera360, - SHCCameraEyes, - SHCLightSwitch, + CameraLightService, + PowerSwitchService, + PrivacyModeService, SHCSmartPlug, - SHCSmartPlugCompact, ) from boschshcpy.device import SHCDevice @@ -20,7 +20,6 @@ from homeassistant.components.switch import ( from homeassistant.const import EntityCategory from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback -from homeassistant.helpers.typing import StateType from . import BoschConfigEntry from .entity import SHCEntity @@ -31,7 +30,7 @@ class SHCSwitchEntityDescription(SwitchEntityDescription): """Class describing SHC switch entities.""" on_key: str - on_value: StateType + on_value: Enum should_poll: bool @@ -40,35 +39,35 @@ SWITCH_TYPES: dict[str, SHCSwitchEntityDescription] = { key="smartplug", device_class=SwitchDeviceClass.OUTLET, on_key="switchstate", - on_value=SHCSmartPlug.PowerSwitchService.State.ON, + on_value=PowerSwitchService.State.ON, should_poll=False, ), "smartplugcompact": SHCSwitchEntityDescription( key="smartplugcompact", device_class=SwitchDeviceClass.OUTLET, on_key="switchstate", - on_value=SHCSmartPlugCompact.PowerSwitchService.State.ON, + on_value=PowerSwitchService.State.ON, should_poll=False, ), "lightswitch": SHCSwitchEntityDescription( key="lightswitch", device_class=SwitchDeviceClass.SWITCH, on_key="switchstate", - on_value=SHCLightSwitch.PowerSwitchService.State.ON, + on_value=PowerSwitchService.State.ON, should_poll=False, ), "cameraeyes": SHCSwitchEntityDescription( key="cameraeyes", device_class=SwitchDeviceClass.SWITCH, on_key="cameralight", - on_value=SHCCameraEyes.CameraLightService.State.ON, + on_value=CameraLightService.State.ON, should_poll=True, ), "camera360": SHCSwitchEntityDescription( key="camera360", device_class=SwitchDeviceClass.SWITCH, on_key="privacymode", - on_value=SHCCamera360.PrivacyModeService.State.DISABLED, + on_value=PrivacyModeService.State.DISABLED, should_poll=True, ), } @@ -82,10 +81,14 @@ async def async_setup_entry( """Set up the SHC switch platform.""" session = config_entry.runtime_data + shc_info = session.information + if TYPE_CHECKING: + assert shc_info is not None and shc_info.unique_id is not None + entities: list[SwitchEntity] = [ SHCSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, description=SWITCH_TYPES["smartplug"], ) @@ -95,7 +98,7 @@ async def async_setup_entry( entities.extend( SHCRoutingSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, ) for switch in session.device_helper.smart_plugs @@ -104,7 +107,7 @@ async def async_setup_entry( entities.extend( SHCSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, description=SWITCH_TYPES["lightswitch"], ) @@ -114,7 +117,7 @@ async def async_setup_entry( entities.extend( SHCSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, description=SWITCH_TYPES["smartplugcompact"], ) @@ -124,7 +127,7 @@ async def async_setup_entry( entities.extend( SHCSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, description=SWITCH_TYPES["cameraeyes"], ) @@ -134,7 +137,7 @@ async def async_setup_entry( entities.extend( SHCSwitch( device=switch, - parent_id=session.information.unique_id, + parent_id=shc_info.unique_id, entry_id=config_entry.entry_id, description=SWITCH_TYPES["camera360"], ) @@ -166,7 +169,7 @@ class SHCSwitch(SHCEntity, SwitchEntity): """Return the state of the switch.""" return ( getattr(self._device, self.entity_description.on_key) - == self.entity_description.on_value + is self.entity_description.on_value ) @override @@ -195,9 +198,10 @@ class SHCRoutingSwitch(SHCEntity, SwitchEntity): _attr_translation_key = "routing" _attr_entity_category = EntityCategory.CONFIG + _device: SHCSmartPlug def __init__(self, device: SHCDevice, parent_id: str, entry_id: str) -> None: - """Initialize an SHC communication quality reporting sensor.""" + """Initialize an SHC routing switch.""" super().__init__(device, parent_id, entry_id) self._attr_unique_id = f"{device.serial}_routing" diff --git a/requirements_all.txt b/requirements_all.txt index be9f33bc6998..32b322523e2b 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -699,7 +699,7 @@ bond-async==0.2.1 bosch-alarm-mode2==0.4.10 # homeassistant.components.bosch_shc -boschshcpy==0.3.5 +boschshcpy==0.6.4 # homeassistant.components.amazon_polly # homeassistant.components.route53