Files
homeassistant/config/custom_components/nodered/number.py
T
2026-08-24 21:55:33 +08:00

168 lines
5.4 KiB
Python

"""Sensor platform for nodered."""
import logging
from typing import Any
from homeassistant.components.number import RestoreNumber
from homeassistant.components.number.const import (
DEFAULT_MAX_VALUE,
DEFAULT_MIN_VALUE,
DEFAULT_STEP,
NumberMode,
)
from homeassistant.components.websocket_api.connection import ActiveConnection
from homeassistant.components.websocket_api.messages import event_message
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_ICON,
CONF_ID,
CONF_TYPE,
CONF_UNIT_OF_MEASUREMENT,
STATE_UNAVAILABLE,
STATE_UNKNOWN,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import (
CONF_CONFIG,
CONF_NUMBER,
EVENT_VALUE_CHANGE,
NODERED_DISCOVERY_NEW,
NUMBER_ICON,
)
from .entity import NodeRedEntity
_LOGGER = logging.getLogger(__name__)
CONF_MIN_VALUE = "min_value"
CONF_MAX_VALUE = "max_value"
CONF_STEP_VALUE = "step_value"
CONF_MODE = "mode"
CONF_STATE = "state"
CONF_VALUE = "value"
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up the number platform."""
async def async_discover(
config: dict[str, Any], connection: ActiveConnection
) -> None:
await _async_setup_entity(hass, config, async_add_entities, connection)
config_entry.async_on_unload(
async_dispatcher_connect(
hass,
NODERED_DISCOVERY_NEW.format(CONF_NUMBER),
async_discover,
)
)
async def _async_setup_entity(
hass: HomeAssistant,
config: dict[str, Any],
async_add_entities: AddEntitiesCallback,
connection: ActiveConnection,
) -> None:
"""Set up the Node-RED number."""
async_add_entities([NodeRedNumber(hass, config, connection)])
class NodeRedNumber(NodeRedEntity, RestoreNumber):
"""Node-RED number class."""
_attr_native_min_value = DEFAULT_MIN_VALUE
_attr_native_max_value = DEFAULT_MAX_VALUE
_attr_native_step = DEFAULT_STEP
_attr_native_value = 0
_attr_mode = NumberMode.AUTO
_bidirectional = True
component = CONF_NUMBER
def __init__(
self,
hass: HomeAssistant,
config: dict[str, Any],
connection: ActiveConnection,
) -> None:
"""Initialize the number."""
super().__init__(hass, config)
self._message_id = config[CONF_ID]
self._connection = connection
self._attr_icon = self._config.get(CONF_ICON, NUMBER_ICON)
self._attr_native_value = config.get(CONF_STATE)
self._attr_native_min_value = self._config.get(
CONF_MIN_VALUE, DEFAULT_MIN_VALUE
)
self._attr_native_max_value = self._config.get(
CONF_MAX_VALUE, DEFAULT_MAX_VALUE
)
self._attr_native_step = self._config.get(CONF_STEP_VALUE, DEFAULT_STEP)
self._attr_mode = self._config.get(CONF_MODE, NumberMode.AUTO)
async def async_set_native_value(self, value: float) -> None:
"""Set new value."""
self._connection.send_message(
event_message(
self._message_id, {CONF_TYPE: EVENT_VALUE_CHANGE, CONF_VALUE: value}
)
)
async def async_added_to_hass(self) -> None:
"""Load the last known state when added to hass."""
await super().async_added_to_hass()
if (
(last_state := await self.async_get_last_state())
and (last_number_data := await self.async_get_last_number_data())
and last_state.state not in (STATE_UNKNOWN, STATE_UNAVAILABLE)
):
self._attr_native_value = last_number_data.native_value
def update_entity_state_attributes(self, msg: dict[str, Any]) -> None:
"""Update the entity state attributes."""
super().update_entity_state_attributes(msg)
self._attr_native_value = msg.get(CONF_STATE)
def update_config(self, msg: dict[str, Any]) -> None:
"""Update entity config."""
super().update_config(msg)
config = msg.get(CONF_CONFIG, {})
if (min_value := config.get(CONF_MIN_VALUE)) is not None:
self._attr_native_min_value = min_value
if (max_value := config.get(CONF_MAX_VALUE)) is not None:
self._attr_native_max_value = max_value
if (step_value := config.get(CONF_STEP_VALUE)) is not None:
self._attr_native_step = step_value
if (mode := config.get(CONF_MODE)) is not None:
self._attr_mode = mode
if (unit := config.get(CONF_UNIT_OF_MEASUREMENT)) is not None:
self._attr_native_unit_of_measurement = unit
def update_discovery_config(self, msg: dict[str, Any]) -> None:
"""Update the entity config."""
super().update_discovery_config(msg)
self._attr_icon = self._config.get(CONF_ICON, NUMBER_ICON)
self._attr_native_min_value = self._config.get(
CONF_MIN_VALUE, DEFAULT_MIN_VALUE
)
self._attr_native_max_value = self._config.get(
CONF_MAX_VALUE, DEFAULT_MAX_VALUE
)
self._attr_native_step = self._config.get(CONF_STEP_VALUE, DEFAULT_STEP)
self._attr_mode = self._config.get(CONF_MODE, NumberMode.AUTO)
self._attr_native_unit_of_measurement = self._config.get(
CONF_UNIT_OF_MEASUREMENT
)