diff --git a/homeassistant/components/group/light.py b/homeassistant/components/group/light.py index 228645df974..5f4d0a0a0c1 100644 --- a/homeassistant/components/group/light.py +++ b/homeassistant/components/group/light.py @@ -31,6 +31,7 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, filter_supported_color_modes, ) from homeassistant.config_entries import ConfigEntry @@ -42,7 +43,6 @@ from homeassistant.const import ( CONF_UNIQUE_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON, - STATE_ON, STATE_UNAVAILABLE, STATE_UNKNOWN, ) @@ -207,7 +207,7 @@ class LightGroup(GroupEntity, LightEntity): for entity_id in self._entity_ids if (state := self.hass.states.get(entity_id)) is not None ] - on_states = [state for state in states if state.state == STATE_ON] + on_states = [state for state in states if state.state == LightState.ON] valid_state = self.mode( state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE) for state in states @@ -218,7 +218,9 @@ class LightGroup(GroupEntity, LightEntity): self._attr_is_on = None else: # Set as ON if any / all member is ON - self._attr_is_on = self.mode(state.state == STATE_ON for state in states) + self._attr_is_on = self.mode( + state.state == LightState.ON for state in states + ) self._attr_available = any(state.state != STATE_UNAVAILABLE for state in states) self._attr_brightness = reduce_attribute(on_states, ATTR_BRIGHTNESS) diff --git a/homeassistant/components/homekit/type_lights.py b/homeassistant/components/homekit/type_lights.py index 6b57a03153c..69041ee3d4e 100644 --- a/homeassistant/components/homekit/type_lights.py +++ b/homeassistant/components/homekit/type_lights.py @@ -22,16 +22,12 @@ from homeassistant.components.light import ( ATTR_WHITE, DOMAIN as LIGHT_DOMAIN, ColorMode, + LightState, brightness_supported, color_supported, color_temp_supported, ) -from homeassistant.const import ( - ATTR_ENTITY_ID, - SERVICE_TURN_OFF, - SERVICE_TURN_ON, - STATE_ON, -) +from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON from homeassistant.core import CALLBACK_TYPE, State, callback from homeassistant.helpers.event import async_call_later from homeassistant.util.color import ( @@ -244,7 +240,7 @@ class Light(HomeAccessory): state = new_state.state attributes = new_state.attributes color_mode = attributes.get(ATTR_COLOR_MODE) - self.char_on.set_value(int(state == STATE_ON)) + self.char_on.set_value(int(state == LightState.ON)) color_mode_changed = self._previous_color_mode != color_mode self._previous_color_mode = color_mode @@ -265,7 +261,7 @@ class Light(HomeAccessory): # Therefore, if the brightness is 0 and the device is still on, # the brightness is mapped to 1 otherwise the update is ignored in # order to avoid this incorrect behavior. - if brightness == 0 and state == STATE_ON: + if brightness == 0 and state == LightState.ON: brightness = 1 self.char_brightness.set_value(brightness) if color_mode_changed: diff --git a/homeassistant/components/light/__init__.py b/homeassistant/components/light/__init__.py index a496404401a..cfed7d70f64 100644 --- a/homeassistant/components/light/__init__.py +++ b/homeassistant/components/light/__init__.py @@ -15,7 +15,7 @@ from typing import Any, Self, cast, final import voluptuous as vol from homeassistant.config_entries import ConfigEntry -from homeassistant.const import ( +from homeassistant.const import ( # noqa: F401 SERVICE_TOGGLE, SERVICE_TURN_OFF, SERVICE_TURN_ON, @@ -41,6 +41,13 @@ SCAN_INTERVAL = timedelta(seconds=30) DATA_PROFILES: HassKey[Profiles] = HassKey(f"{DOMAIN}_profiles") +class LightState(StrEnum): + """Light entity states.""" + + ON = "on" + OFF = "off" + + class LightEntityFeature(IntFlag): """Supported features of the light entity.""" @@ -297,7 +304,7 @@ _LOGGER = logging.getLogger(__name__) @bind_hass def is_on(hass: HomeAssistant, entity_id: str) -> bool: """Return if the lights are on based on the statemachine.""" - return hass.states.is_state(entity_id, STATE_ON) + return hass.states.is_state(entity_id, LightState.ON) def preprocess_turn_on_alternatives( diff --git a/homeassistant/components/light/reproduce_state.py b/homeassistant/components/light/reproduce_state.py index 4024f2f84ba..7a2de4f5c80 100644 --- a/homeassistant/components/light/reproduce_state.py +++ b/homeassistant/components/light/reproduce_state.py @@ -7,13 +7,7 @@ from collections.abc import Iterable, Mapping import logging from typing import Any, NamedTuple, cast -from homeassistant.const import ( - ATTR_ENTITY_ID, - SERVICE_TURN_OFF, - SERVICE_TURN_ON, - STATE_OFF, - STATE_ON, -) +from homeassistant.const import ATTR_ENTITY_ID, SERVICE_TURN_OFF, SERVICE_TURN_ON from homeassistant.core import Context, HomeAssistant, State from . import ( @@ -30,11 +24,12 @@ from . import ( ATTR_XY_COLOR, DOMAIN, ColorMode, + LightState, ) _LOGGER = logging.getLogger(__name__) -VALID_STATES = {STATE_ON, STATE_OFF} +VALID_STATES = {LightState.ON, LightState.OFF} ATTR_GROUP = [ATTR_BRIGHTNESS, ATTR_EFFECT] @@ -111,7 +106,7 @@ async def _async_reproduce_state( if reproduce_options is not None and ATTR_TRANSITION in reproduce_options: service_data[ATTR_TRANSITION] = reproduce_options[ATTR_TRANSITION] - if state.state == STATE_ON: + if state.state == LightState.ON: service = SERVICE_TURN_ON for attr in ATTR_GROUP: # All attributes that are not colors @@ -140,7 +135,7 @@ async def _async_reproduce_state( service_data[color_attr] = color_attr_state break - elif state.state == STATE_OFF: + elif state.state == LightState.OFF: service = SERVICE_TURN_OFF await hass.services.async_call( diff --git a/homeassistant/components/limitlessled/light.py b/homeassistant/components/limitlessled/light.py index c6b3301081d..9d38e2cbc37 100644 --- a/homeassistant/components/limitlessled/light.py +++ b/homeassistant/components/limitlessled/light.py @@ -31,8 +31,9 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, ) -from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_TYPE, STATE_ON +from homeassistant.const import CONF_HOST, CONF_NAME, CONF_PORT, CONF_TYPE from homeassistant.core import HomeAssistant import homeassistant.helpers.config_validation as cv from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -259,7 +260,7 @@ class LimitlessLEDGroup(LightEntity, RestoreEntity): """Handle entity about to be added to hass event.""" await super().async_added_to_hass() if last_state := await self.async_get_last_state(): - self._attr_is_on = last_state.state == STATE_ON + self._attr_is_on = last_state.state == LightState.ON self._attr_brightness = last_state.attributes.get("brightness") self._attr_color_temp = last_state.attributes.get("color_temp") self._attr_hs_color = last_state.attributes.get("hs_color") diff --git a/homeassistant/components/mqtt/light/schema_basic.py b/homeassistant/components/mqtt/light/schema_basic.py index de6a9d4c126..4826bac1ce4 100644 --- a/homeassistant/components/mqtt/light/schema_basic.py +++ b/homeassistant/components/mqtt/light/schema_basic.py @@ -27,6 +27,7 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, valid_supported_color_modes, ) from homeassistant.const import ( @@ -34,7 +35,6 @@ from homeassistant.const import ( CONF_OPTIMISTIC, CONF_PAYLOAD_OFF, CONF_PAYLOAD_ON, - STATE_ON, ) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv @@ -618,7 +618,7 @@ class MqttLight(MqttEntity, LightEntity, RestoreEntity): setattr(self, f"_attr_{attribute}", last_state.attributes[attribute]) if self._topic[CONF_STATE_TOPIC] is None and self._optimistic and last_state: - self._attr_is_on = last_state.state == STATE_ON + self._attr_is_on = last_state.state == LightState.ON restore_state(ATTR_BRIGHTNESS) restore_state(ATTR_RGB_COLOR) restore_state(ATTR_HS_COLOR, ATTR_RGB_COLOR) diff --git a/homeassistant/components/mqtt/light/schema_json.py b/homeassistant/components/mqtt/light/schema_json.py index 89f338f6bab..5fddaa562c7 100644 --- a/homeassistant/components/mqtt/light/schema_json.py +++ b/homeassistant/components/mqtt/light/schema_json.py @@ -30,6 +30,7 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, brightness_supported, color_supported, filter_supported_color_modes, @@ -44,7 +45,6 @@ from homeassistant.const import ( CONF_OPTIMISTIC, CONF_RGB, CONF_XY, - STATE_ON, ) from homeassistant.core import async_get_hass, callback import homeassistant.helpers.config_validation as cv @@ -514,7 +514,7 @@ class MqttLightJson(MqttEntity, LightEntity, RestoreEntity): last_state = await self.async_get_last_state() if self._optimistic and last_state: - self._attr_is_on = last_state.state == STATE_ON + self._attr_is_on = last_state.state == LightState.ON last_attributes = last_state.attributes self._attr_brightness = last_attributes.get( ATTR_BRIGHTNESS, self.brightness diff --git a/homeassistant/components/mqtt/light/schema_template.py b/homeassistant/components/mqtt/light/schema_template.py index c4f9cad44c5..2873c6aff6d 100644 --- a/homeassistant/components/mqtt/light/schema_template.py +++ b/homeassistant/components/mqtt/light/schema_template.py @@ -19,15 +19,10 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, filter_supported_color_modes, ) -from homeassistant.const import ( - CONF_NAME, - CONF_OPTIMISTIC, - CONF_STATE_TEMPLATE, - STATE_OFF, - STATE_ON, -) +from homeassistant.const import CONF_NAME, CONF_OPTIMISTIC, CONF_STATE_TEMPLATE from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.restore_state import RestoreEntity @@ -184,9 +179,9 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity): def _state_received(self, msg: ReceiveMessage) -> None: """Handle new MQTT messages.""" state = self._value_templates[CONF_STATE_TEMPLATE](msg.payload) - if state == STATE_ON: + if state == LightState.ON: self._attr_is_on = True - elif state == STATE_OFF: + elif state == LightState.OFF: self._attr_is_on = False elif state == PAYLOAD_NONE: self._attr_is_on = None @@ -269,7 +264,7 @@ class MqttLightTemplate(MqttEntity, LightEntity, RestoreEntity): last_state = await self.async_get_last_state() if self._optimistic and last_state: - self._attr_is_on = last_state.state == STATE_ON + self._attr_is_on = last_state.state == LightState.ON if last_state.attributes.get(ATTR_BRIGHTNESS): self._attr_brightness = last_state.attributes.get(ATTR_BRIGHTNESS) if last_state.attributes.get(ATTR_HS_COLOR): diff --git a/homeassistant/components/mysensors/light.py b/homeassistant/components/mysensors/light.py index 87f60174cab..adfbbbbd326 100644 --- a/homeassistant/components/mysensors/light.py +++ b/homeassistant/components/mysensors/light.py @@ -10,9 +10,10 @@ from homeassistant.components.light import ( ATTR_RGBW_COLOR, ColorMode, LightEntity, + LightState, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import STATE_OFF, STATE_ON, Platform +from homeassistant.const import Platform from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -83,7 +84,7 @@ class MySensorsLight(MySensorsChildEntity, LightEntity): if self.assumed_state: # optimistically assume that light has changed state self._state = True - self._values[set_req.V_LIGHT] = STATE_ON + self._values[set_req.V_LIGHT] = LightState.ON def _turn_on_dimmer(self, **kwargs: Any) -> None: """Turn on dimmer child device.""" @@ -113,14 +114,14 @@ class MySensorsLight(MySensorsChildEntity, LightEntity): if self.assumed_state: # optimistically assume that light has changed state self._state = False - self._values[value_type] = STATE_OFF + self._values[value_type] = LightState.OFF self.async_write_ha_state() @callback def _async_update_light(self) -> None: """Update the controller with values from light child.""" value_type = self.gateway.const.SetReq.V_LIGHT - self._state = self._values[value_type] == STATE_ON + self._state = self._values[value_type] == LightState.ON @callback def _async_update_dimmer(self) -> None: diff --git a/homeassistant/components/pilight/entity.py b/homeassistant/components/pilight/entity.py index d2d83813516..6d969ca2566 100644 --- a/homeassistant/components/pilight/entity.py +++ b/homeassistant/components/pilight/entity.py @@ -2,14 +2,8 @@ import voluptuous as vol -from homeassistant.const import ( - CONF_ID, - CONF_NAME, - CONF_PROTOCOL, - CONF_STATE, - STATE_OFF, - STATE_ON, -) +from homeassistant.components.light import LightState +from homeassistant.const import CONF_ID, CONF_NAME, CONF_PROTOCOL, CONF_STATE import homeassistant.helpers.config_validation as cv from homeassistant.helpers.restore_state import RestoreEntity @@ -35,7 +29,7 @@ COMMAND_SCHEMA = vol.Schema( vol.Optional(CONF_UNIT): cv.positive_int, vol.Optional(CONF_UNITCODE): cv.positive_int, vol.Optional(CONF_ID): vol.Any(cv.positive_int, cv.string), - vol.Optional(CONF_STATE): vol.Any(STATE_ON, STATE_OFF), + vol.Optional(CONF_STATE): vol.Coerce(LightState), vol.Optional(CONF_SYSTEMCODE): cv.positive_int, }, extra=vol.ALLOW_EXTRA, @@ -90,7 +84,7 @@ class PilightBaseDevice(RestoreEntity): """Call when entity about to be added to hass.""" await super().async_added_to_hass() if state := await self.async_get_last_state(): - self._is_on = state.state == STATE_ON + self._is_on = state.state == LightState.ON self._brightness = state.attributes.get("brightness") @property diff --git a/homeassistant/components/rfxtrx/light.py b/homeassistant/components/rfxtrx/light.py index 0e2f7bef65a..f430ccc766d 100644 --- a/homeassistant/components/rfxtrx/light.py +++ b/homeassistant/components/rfxtrx/light.py @@ -7,9 +7,13 @@ from typing import Any import RFXtrx as rfxtrxmod -from homeassistant.components.light import ATTR_BRIGHTNESS, ColorMode, LightEntity +from homeassistant.components.light import ( + ATTR_BRIGHTNESS, + ColorMode, + LightEntity, + LightState, +) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import STATE_ON from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity import Entity from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -70,7 +74,7 @@ class RfxtrxLight(RfxtrxCommandEntity, LightEntity): if self._event is None: old_state = await self.async_get_last_state() if old_state is not None: - self._attr_is_on = old_state.state == STATE_ON + self._attr_is_on = old_state.state == LightState.ON if brightness := old_state.attributes.get(ATTR_BRIGHTNESS): self._attr_brightness = int(brightness) diff --git a/homeassistant/components/switch/light.py b/homeassistant/components/switch/light.py index 48d555e6616..bc8763076d6 100644 --- a/homeassistant/components/switch/light.py +++ b/homeassistant/components/switch/light.py @@ -10,6 +10,7 @@ from homeassistant.components.light import ( PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA, ColorMode, LightEntity, + LightState, ) from homeassistant.const import ( ATTR_ENTITY_ID, @@ -17,7 +18,6 @@ from homeassistant.const import ( CONF_NAME, SERVICE_TURN_OFF, SERVICE_TURN_ON, - STATE_ON, STATE_UNAVAILABLE, ) from homeassistant.core import Event, EventStateChangedData, HomeAssistant, callback @@ -108,7 +108,7 @@ class LightSwitch(LightEntity): self._attr_available = False return self._attr_available = True - self._attr_is_on = state.state == STATE_ON + self._attr_is_on = state.state == LightState.ON self.async_write_ha_state() self.async_on_remove( diff --git a/homeassistant/components/template/light.py b/homeassistant/components/template/light.py index cae6c0cebc1..dca1bf2f206 100644 --- a/homeassistant/components/template/light.py +++ b/homeassistant/components/template/light.py @@ -21,6 +21,7 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, filter_supported_color_modes, ) from homeassistant.const import ( @@ -29,8 +30,6 @@ from homeassistant.const import ( CONF_LIGHTS, CONF_UNIQUE_ID, CONF_VALUE_TEMPLATE, - STATE_OFF, - STATE_ON, ) from homeassistant.core import HomeAssistant, callback from homeassistant.exceptions import TemplateError @@ -48,7 +47,7 @@ from .template_entity import ( ) _LOGGER = logging.getLogger(__name__) -_VALID_STATES = [STATE_ON, STATE_OFF, "true", "false"] +_VALID_STATES = [LightState.ON, LightState.OFF, "true", "false"] # Legacy CONF_COLOR_ACTION = "set_color" @@ -737,7 +736,7 @@ class LightTemplate(TemplateEntity, LightEntity): state = str(result).lower() if state in _VALID_STATES: - self._state = state in ("true", STATE_ON) + self._state = state in ("true", LightState.ON) return _LOGGER.error( diff --git a/homeassistant/components/zha/light.py b/homeassistant/components/zha/light.py index fa83ad1cab6..a4576bc0a7d 100644 --- a/homeassistant/components/zha/light.py +++ b/homeassistant/components/zha/light.py @@ -23,9 +23,10 @@ from homeassistant.components.light import ( ColorMode, LightEntity, LightEntityFeature, + LightState, ) from homeassistant.config_entries import ConfigEntry -from homeassistant.const import STATE_ON, Platform +from homeassistant.const import Platform from homeassistant.core import HomeAssistant, State, callback from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.entity_platform import AddEntitiesCallback @@ -194,7 +195,7 @@ class Light(LightEntity, ZHAEntity): def restore_external_state_attributes(self, state: State) -> None: """Restore entity state.""" self.entity_data.entity.restore_external_state_attributes( - state=(state.state == STATE_ON), + state=(state.state == LightState.ON), off_with_transition=state.attributes.get(OFF_WITH_TRANSITION), off_brightness=state.attributes.get(OFF_BRIGHTNESS), brightness=state.attributes.get(ATTR_BRIGHTNESS),