diff --git a/homeassistant/components/rainmachine/__init__.py b/homeassistant/components/rainmachine/__init__.py index 09af357617d..6a239bc84a1 100644 --- a/homeassistant/components/rainmachine/__init__.py +++ b/homeassistant/components/rainmachine/__init__.py @@ -19,7 +19,6 @@ from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.helpers import aiohttp_client, config_validation as cv import homeassistant.helpers.device_registry as dr -from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import ( CoordinatorEntity, DataUpdateCoordinator, @@ -174,48 +173,32 @@ class RainMachineEntity(CoordinatorEntity): """Define a generic RainMachine entity.""" def __init__( - self, coordinator: DataUpdateCoordinator, controller: Controller + self, + coordinator: DataUpdateCoordinator, + controller: Controller, + entity_type: str, ) -> None: """Initialize.""" super().__init__(coordinator) - self._attrs = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION} - self._controller = controller - self._device_class = None + + self._attr_device_info = { + "identifiers": {(DOMAIN, controller.mac)}, + "connections": {(dr.CONNECTION_NETWORK_MAC, controller.mac)}, + "name": controller.name, + "manufacturer": "RainMachine", + "model": ( + f"Version {controller.hardware_version} " + f"(API: {controller.api_version})" + ), + "sw_version": controller.software_version, + } + self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION} # The colons are removed from the device MAC simply because that value # (unnecessarily) makes up the existing unique ID formula and we want to avoid # a breaking change: - self._unique_id = controller.mac.replace(":", "") - self._name = None - - @property - def device_class(self) -> str: - """Return the device class.""" - return self._device_class - - @property - def device_info(self) -> DeviceInfo: - """Return device registry information for this entity.""" - return { - "identifiers": {(DOMAIN, self._controller.mac)}, - "connections": {(dr.CONNECTION_NETWORK_MAC, self._controller.mac)}, - "name": self._controller.name, - "manufacturer": "RainMachine", - "model": ( - f"Version {self._controller.hardware_version} " - f"(API: {self._controller.api_version})" - ), - "sw_version": self._controller.software_version, - } - - @property - def extra_state_attributes(self) -> dict: - """Return the state attributes.""" - return self._attrs - - @property - def name(self) -> str: - """Return the name of the entity.""" - return self._name + self._attr_unique_id = f"{controller.mac.replace(':', '')}_{entity_type}" + self._controller = controller + self._entity_type = entity_type @callback def _handle_coordinator_update(self): diff --git a/homeassistant/components/rainmachine/binary_sensor.py b/homeassistant/components/rainmachine/binary_sensor.py index 171fd26b910..b666d9ed150 100644 --- a/homeassistant/components/rainmachine/binary_sensor.py +++ b/homeassistant/components/rainmachine/binary_sensor.py @@ -125,32 +125,11 @@ class RainMachineBinarySensor(RainMachineEntity, BinarySensorEntity): enabled_by_default: bool, ) -> None: """Initialize the sensor.""" - super().__init__(coordinator, controller) - self._enabled_by_default = enabled_by_default - self._icon = icon - self._name = name - self._sensor_type = sensor_type - self._state = None + super().__init__(coordinator, controller, sensor_type) - @property - def entity_registry_enabled_default(self) -> bool: - """Determine whether an entity is enabled by default.""" - return self._enabled_by_default - - @property - def icon(self) -> str: - """Return the icon.""" - return self._icon - - @property - def is_on(self) -> bool: - """Return the status of the sensor.""" - return self._state - - @property - def unique_id(self) -> str: - """Return a unique, Home Assistant friendly identifier for this entity.""" - return f"{self._unique_id}_{self._sensor_type}" + self._attr_entity_registry_enabled_default = enabled_by_default + self._attr_icon = icon + self._attr_name = name class CurrentRestrictionsBinarySensor(RainMachineBinarySensor): @@ -159,18 +138,18 @@ class CurrentRestrictionsBinarySensor(RainMachineBinarySensor): @callback def update_from_latest_data(self) -> None: """Update the state.""" - if self._sensor_type == TYPE_FREEZE: - self._state = self.coordinator.data["freeze"] - elif self._sensor_type == TYPE_HOURLY: - self._state = self.coordinator.data["hourly"] - elif self._sensor_type == TYPE_MONTH: - self._state = self.coordinator.data["month"] - elif self._sensor_type == TYPE_RAINDELAY: - self._state = self.coordinator.data["rainDelay"] - elif self._sensor_type == TYPE_RAINSENSOR: - self._state = self.coordinator.data["rainSensor"] - elif self._sensor_type == TYPE_WEEKDAY: - self._state = self.coordinator.data["weekDay"] + if self._entity_type == TYPE_FREEZE: + self._attr_is_on = self.coordinator.data["freeze"] + elif self._entity_type == TYPE_HOURLY: + self._attr_is_on = self.coordinator.data["hourly"] + elif self._entity_type == TYPE_MONTH: + self._attr_is_on = self.coordinator.data["month"] + elif self._entity_type == TYPE_RAINDELAY: + self._attr_is_on = self.coordinator.data["rainDelay"] + elif self._entity_type == TYPE_RAINSENSOR: + self._attr_is_on = self.coordinator.data["rainSensor"] + elif self._entity_type == TYPE_WEEKDAY: + self._attr_is_on = self.coordinator.data["weekDay"] class ProvisionSettingsBinarySensor(RainMachineBinarySensor): @@ -179,8 +158,8 @@ class ProvisionSettingsBinarySensor(RainMachineBinarySensor): @callback def update_from_latest_data(self) -> None: """Update the state.""" - if self._sensor_type == TYPE_FLOW_SENSOR: - self._state = self.coordinator.data["system"].get("useFlowSensor") + if self._entity_type == TYPE_FLOW_SENSOR: + self._attr_is_on = self.coordinator.data["system"].get("useFlowSensor") class UniversalRestrictionsBinarySensor(RainMachineBinarySensor): @@ -189,7 +168,7 @@ class UniversalRestrictionsBinarySensor(RainMachineBinarySensor): @callback def update_from_latest_data(self) -> None: """Update the state.""" - if self._sensor_type == TYPE_FREEZE_PROTECTION: - self._state = self.coordinator.data["freezeProtectEnabled"] - elif self._sensor_type == TYPE_HOT_DAYS: - self._state = self.coordinator.data["hotDaysExtraWatering"] + if self._entity_type == TYPE_FREEZE_PROTECTION: + self._attr_is_on = self.coordinator.data["freezeProtectEnabled"] + elif self._entity_type == TYPE_HOT_DAYS: + self._attr_is_on = self.coordinator.data["hotDaysExtraWatering"] diff --git a/homeassistant/components/rainmachine/sensor.py b/homeassistant/components/rainmachine/sensor.py index 2ebd9d0fdb4..87feb85046d 100644 --- a/homeassistant/components/rainmachine/sensor.py +++ b/homeassistant/components/rainmachine/sensor.py @@ -124,39 +124,13 @@ class RainMachineSensor(RainMachineEntity, SensorEntity): enabled_by_default: bool, ) -> None: """Initialize.""" - super().__init__(coordinator, controller) - self._device_class = device_class - self._enabled_by_default = enabled_by_default - self._icon = icon - self._name = name - self._sensor_type = sensor_type - self._state = None - self._unit = unit + super().__init__(coordinator, controller, sensor_type) - @property - def entity_registry_enabled_default(self) -> bool: - """Determine whether an entity is enabled by default.""" - return self._enabled_by_default - - @property - def icon(self) -> str: - """Return the icon.""" - return self._icon - - @property - def state(self) -> str: - """Return the name of the entity.""" - return self._state - - @property - def unique_id(self) -> str: - """Return a unique, Home Assistant friendly identifier for this entity.""" - return f"{self._unique_id}_{self._sensor_type}" - - @property - def unit_of_measurement(self) -> str: - """Return the unit the value is expressed in.""" - return self._unit + self._attr_device_class = device_class + self._attr_entity_registry_enabled_default = enabled_by_default + self._attr_icon = icon + self._attr_name = name + self._attr_unit_of_measurement = unit class ProvisionSettingsSensor(RainMachineSensor): @@ -165,24 +139,26 @@ class ProvisionSettingsSensor(RainMachineSensor): @callback def update_from_latest_data(self) -> None: """Update the state.""" - if self._sensor_type == TYPE_FLOW_SENSOR_CLICK_M3: - self._state = self.coordinator.data["system"].get( + if self._entity_type == TYPE_FLOW_SENSOR_CLICK_M3: + self._attr_state = self.coordinator.data["system"].get( "flowSensorClicksPerCubicMeter" ) - elif self._sensor_type == TYPE_FLOW_SENSOR_CONSUMED_LITERS: + elif self._entity_type == TYPE_FLOW_SENSOR_CONSUMED_LITERS: clicks = self.coordinator.data["system"].get("flowSensorWateringClicks") clicks_per_m3 = self.coordinator.data["system"].get( "flowSensorClicksPerCubicMeter" ) if clicks and clicks_per_m3: - self._state = (clicks * 1000) / clicks_per_m3 + self._attr_state = (clicks * 1000) / clicks_per_m3 else: - self._state = None - elif self._sensor_type == TYPE_FLOW_SENSOR_START_INDEX: - self._state = self.coordinator.data["system"].get("flowSensorStartIndex") - elif self._sensor_type == TYPE_FLOW_SENSOR_WATERING_CLICKS: - self._state = self.coordinator.data["system"].get( + self._attr_state = None + elif self._entity_type == TYPE_FLOW_SENSOR_START_INDEX: + self._attr_state = self.coordinator.data["system"].get( + "flowSensorStartIndex" + ) + elif self._entity_type == TYPE_FLOW_SENSOR_WATERING_CLICKS: + self._attr_state = self.coordinator.data["system"].get( "flowSensorWateringClicks" ) @@ -193,5 +169,5 @@ class UniversalRestrictionsSensor(RainMachineSensor): @callback def update_from_latest_data(self) -> None: """Update the state.""" - if self._sensor_type == TYPE_FREEZE_TEMP: - self._state = self.coordinator.data["freezeProtectTemp"] + if self._entity_type == TYPE_FREEZE_TEMP: + self._attr_state = self.coordinator.data["freezeProtectTemp"] diff --git a/homeassistant/components/rainmachine/switch.py b/homeassistant/components/rainmachine/switch.py index b0544b1adbe..68ecd8c8d64 100644 --- a/homeassistant/components/rainmachine/switch.py +++ b/homeassistant/components/rainmachine/switch.py @@ -53,6 +53,8 @@ CONF_PROGRAM_ID = "program_id" CONF_SECONDS = "seconds" CONF_ZONE_ID = "zone_id" +DEFAULT_ICON = "mdi:water" + DAYS = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"] RUN_STATUS_MAP = {0: "Not Running", 1: "Running", 2: "Queued"} @@ -181,6 +183,8 @@ async def async_setup_entry( class RainMachineSwitch(RainMachineEntity, SwitchEntity): """A class to represent a generic RainMachine switch.""" + _attr_icon = DEFAULT_ICON + def __init__( self, coordinator: DataUpdateCoordinator, @@ -190,34 +194,24 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity): entry: ConfigEntry, ) -> None: """Initialize a generic RainMachine switch.""" - super().__init__(coordinator, controller) + super().__init__(coordinator, controller, type(self).__name__) + + self._attr_is_on = False + self._attr_name = name self._data = coordinator.data[uid] self._entry = entry self._is_active = True - self._is_on = False - self._name = name - self._switch_type = type(self).__name__ self._uid = uid @property def available(self) -> bool: """Return True if entity is available.""" - return self._is_active and self.coordinator.last_update_success - - @property - def icon(self) -> str: - """Return the icon.""" - return "mdi:water" - - @property - def is_on(self) -> bool: - """Return whether the program is running.""" - return self._is_on + return super().available and self._is_active @property def unique_id(self) -> str: """Return a unique, Home Assistant friendly identifier for this entity.""" - return f"{self._unique_id}_{self._switch_type}_{self._uid}" + return f"{super().unique_id}_{self._uid}" async def _async_run_switch_coroutine(self, api_coro: Coroutine) -> None: """Run a coroutine to toggle the switch.""" @@ -226,7 +220,7 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity): except RequestError as err: LOGGER.error( 'Error while toggling %s "%s": %s', - self._switch_type, + self._entity_type, self.unique_id, err, ) @@ -235,7 +229,7 @@ class RainMachineSwitch(RainMachineEntity, SwitchEntity): if resp["statusCode"] != 0: LOGGER.error( 'Error while toggling %s "%s": %s', - self._switch_type, + self._entity_type, self.unique_id, resp["message"], ) @@ -334,7 +328,7 @@ class RainMachineProgram(RainMachineSwitch): """Update the state.""" super().update_from_latest_data() - self._is_on = bool(self._data["status"]) + self._attr_is_on = bool(self._data["status"]) if self._data.get("nextRun") is not None: next_run = datetime.strptime( @@ -344,7 +338,7 @@ class RainMachineProgram(RainMachineSwitch): else: next_run = None - self._attrs.update( + self._attr_extra_state_attributes.update( { ATTR_ID: self._uid, ATTR_NEXT_RUN: next_run, @@ -376,9 +370,9 @@ class RainMachineZone(RainMachineSwitch): """Update the state.""" super().update_from_latest_data() - self._is_on = bool(self._data["state"]) + self._attr_is_on = bool(self._data["state"]) - self._attrs.update( + self._attr_extra_state_attributes.update( { ATTR_STATUS: RUN_STATUS_MAP[self._data["state"]], ATTR_AREA: self._data.get("waterSense").get("area"),