1 """Support for ISY number entities."""
3 from __future__
import annotations
5 from dataclasses
import replace
8 from pyisy.constants
import (
19 from pyisy.helpers
import EventListener, NodeProperty
20 from pyisy.nodes
import Node, NodeChangedEvent
21 from pyisy.variables
import Variable
25 NumberEntityDescription,
43 percentage_to_ranged_value,
44 ranged_value_to_percentage,
48 CONF_VAR_SENSOR_STRING,
49 DEFAULT_VAR_SENSOR_STRING,
53 from .entity
import ISYAuxControlEntity
54 from .helpers
import convert_isy_value_to_hass
55 from .models
import IsyData
57 ISY_MAX_SIZE = (2**32) / 2
62 native_unit_of_measurement=PERCENTAGE,
63 entity_category=EntityCategory.CONFIG,
65 native_max_value=100.0,
70 native_unit_of_measurement=PERCENTAGE,
71 entity_category=EntityCategory.CONFIG,
73 native_max_value=100.0,
77 BACKLIGHT_MEMORY_FILTER = {
"memory": DEV_BL_ADDR,
"cmd1": DEV_CMD_MEMORY_WRITE}
82 config_entry: ConfigEntry,
83 async_add_entities: AddEntitiesCallback,
85 """Set up ISY/IoX number entities from config entry."""
86 isy_data: IsyData = hass.data[DOMAIN][config_entry.entry_id]
87 device_info = isy_data.devices
89 ISYVariableNumberEntity | ISYAuxControlNumberEntity | ISYBacklightNumberEntity
91 var_id = config_entry.options.get(CONF_VAR_SENSOR_STRING, DEFAULT_VAR_SENSOR_STRING)
93 for node
in isy_data.variables[Platform.NUMBER]:
94 step = 10 ** (-1 *
int(node.prec))
95 min_max = ISY_MAX_SIZE / (10 **
int(node.prec))
99 entity_registry_enabled_default=var_id
in node.name,
100 native_unit_of_measurement=
None,
102 native_min_value=-min_max,
103 native_max_value=min_max,
105 description_init = replace(
107 key=f
"{node.address}_init",
108 name=f
"{node.name} Initial Value",
109 entity_category=EntityCategory.CONFIG,
115 unique_id=isy_data.uid_base(node),
116 description=description,
117 device_info=device_info[CONF_VARIABLES],
123 unique_id=f
"{isy_data.uid_base(node)}_init",
124 description=description_init,
125 device_info=device_info[CONF_VARIABLES],
130 for node, control
in isy_data.aux_properties[Platform.NUMBER]:
134 "unique_id": f
"{isy_data.uid_base(node)}_{control}",
135 "description": CONTROL_DESC[control],
136 "device_info": device_info.get(node.primary_node),
138 if control == CMD_BACKLIGHT:
146 """Representation of a ISY/IoX Aux Control Number entity."""
148 _attr_mode = NumberMode.SLIDER
152 """Return the state of the variable."""
154 if node_prop.value == ISY_VALUE_UNKNOWN:
159 and node_prop.uom == UOM_8_BIT_RANGE
162 return int(node_prop.value)
165 """Update the current value."""
168 if self.
entity_descriptionentity_description.native_unit_of_measurement == PERCENTAGE:
171 if node_prop.uom == UOM_8_BIT_RANGE
175 await self.
_node_node.set_on_level(value)
180 f
"Could not set {self.name} to {value} for {self._node.address}"
185 """Representation of an ISY variable as a number entity device."""
187 _attr_has_entity_name =
False
188 _attr_should_poll =
False
191 entity_description: NumberEntityDescription
197 description: NumberEntityDescription,
198 device_info: DeviceInfo,
199 init_entity: bool =
False,
201 """Initialize the ISY variable number."""
213 """Subscribe to the node change events."""
218 """Handle the update event from the ISY Node."""
223 """Return the state of the variable."""
227 self.
_node_node.prec,
232 """Get the state attributes for the device."""
234 "last_edited": self.
_node_node.last_edited,
241 f
"Could not set {self.name} to {value} for {self._node.address}"
246 """Representation of a ISY/IoX Backlight Number entity."""
248 _assumed_state =
True
255 description: NumberEntityDescription,
256 device_info: DeviceInfo |
None,
258 """Initialize the ISY Backlight number entity."""
259 super().
__init__(node, control, unique_id, description, device_info)
264 """Load the last known state when added to hass."""
269 if last_state.state
not in (STATE_UNKNOWN, STATE_UNAVAILABLE):
276 TAG_ADDRESS: self.
_node_node.address,
277 ATTR_ACTION: DEV_MEMORY,
284 """Handle a memory write event from the ISY Node."""
285 if not (BACKLIGHT_MEMORY_FILTER.items() <= event.event_info.items()):
294 """Update the current value."""
296 if not await self.
_node_node.send_cmd(
297 CMD_BACKLIGHT, val=
int(value), uom=UOM_PERCENTAGE
300 f
"Could not set backlight to {value}% for {self._node.address}"
float|int|None native_value(self)
None async_set_native_value(self, float value)
None async_added_to_hass(self)
None __init__(self, Node node, str control, str unique_id, NumberEntityDescription description, DeviceInfo|None device_info)
None async_on_memory_write(self, NodeChangedEvent event, str key)
None async_set_native_value(self, float value)
None async_on_update(self, NodeProperty event)
None async_set_native_value(self, float value)
None __init__(self, Variable node, str unique_id, NumberEntityDescription description, DeviceInfo device_info, bool init_entity=False)
dict[str, Any] extra_state_attributes(self)
float|int|None native_value(self)
None async_added_to_hass(self)
None set_value(self, float value)
NumberExtraStoredData|None async_get_last_number_data(self)
None async_write_ha_state(self)
State|None async_get_last_state(self)
float|int|None convert_isy_value_to_hass(float|None value, str|None uom, int|str precision, int|None fallback_precision=None)
None async_setup_entry(HomeAssistant hass, ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
float percentage_to_ranged_value(tuple[float, float] low_high_range, float percentage)
int ranged_value_to_percentage(tuple[float, float] low_high_range, float value)