1 """Support for KNX/IP sensors."""
3 from __future__
import annotations
5 from collections.abc
import Callable
6 from dataclasses
import dataclass
7 from datetime
import datetime, timedelta
8 from functools
import partial
12 from xknx.core.connection_state
import XknxConnectionState, XknxConnectionType
13 from xknx.devices
import Sensor
as XknxSensor
15 from homeassistant
import config_entries
20 SensorEntityDescription,
36 from .
import KNXModule
37 from .const
import ATTR_SOURCE, KNX_MODULE_KEY
38 from .entity
import KnxYamlEntity
39 from .schema
import SensorSchema
44 @dataclass(frozen=True)
46 """Class describing KNX system sensor entities."""
48 always_available: bool =
True
49 entity_category: EntityCategory = EntityCategory.DIAGNOSTIC
50 has_entity_name: bool =
True
51 should_poll: bool =
True
52 value_fn: Callable[[KNXModule], StateType | datetime] =
lambda knx:
None
55 SYSTEM_ENTITY_DESCRIPTIONS = (
57 key=
"individual_address",
58 always_available=
False,
60 value_fn=
lambda knx:
str(knx.xknx.current_address),
63 key=
"connected_since",
64 always_available=
False,
65 device_class=SensorDeviceClass.TIMESTAMP,
67 value_fn=
lambda knx: knx.xknx.connection_manager.connected_since,
70 key=
"connection_type",
71 always_available=
False,
72 device_class=SensorDeviceClass.ENUM,
73 options=[opt.value
for opt
in XknxConnectionType],
75 value_fn=
lambda knx: knx.xknx.connection_manager.connection_type.value,
78 key=
"telegrams_incoming",
79 entity_registry_enabled_default=
False,
81 state_class=SensorStateClass.TOTAL_INCREASING,
82 value_fn=
lambda knx: knx.xknx.connection_manager.cemi_count_incoming,
85 key=
"telegrams_incoming_error",
86 state_class=SensorStateClass.TOTAL_INCREASING,
87 value_fn=
lambda knx: knx.xknx.connection_manager.cemi_count_incoming_error,
90 key=
"telegrams_outgoing",
91 entity_registry_enabled_default=
False,
93 state_class=SensorStateClass.TOTAL_INCREASING,
94 value_fn=
lambda knx: knx.xknx.connection_manager.cemi_count_outgoing,
97 key=
"telegrams_outgoing_error",
98 state_class=SensorStateClass.TOTAL_INCREASING,
99 value_fn=
lambda knx: knx.xknx.connection_manager.cemi_count_outgoing_error,
102 key=
"telegram_count",
104 state_class=SensorStateClass.TOTAL_INCREASING,
105 value_fn=
lambda knx: knx.xknx.connection_manager.cemi_count_outgoing
106 + knx.xknx.connection_manager.cemi_count_incoming
107 + knx.xknx.connection_manager.cemi_count_incoming_error,
115 async_add_entities: AddEntitiesCallback,
117 """Set up sensor(s) for KNX platform."""
118 knx_module = hass.data[KNX_MODULE_KEY]
119 entities: list[SensorEntity] = []
122 for description
in SYSTEM_ENTITY_DESCRIPTIONS
124 config: list[ConfigType] |
None = knx_module.config_yaml.get(Platform.SENSOR)
127 KNXSensor(knx_module, entity_config)
for entity_config
in config
133 """Return a KNX sensor to be used within XKNX."""
136 name=config[CONF_NAME],
137 group_address_state=config[SensorSchema.CONF_STATE_ADDRESS],
138 sync_state=config[SensorSchema.CONF_SYNC_STATE],
139 always_callback=config[SensorSchema.CONF_ALWAYS_CALLBACK],
140 value_type=config[CONF_TYPE],
145 """Representation of a KNX sensor."""
149 def __init__(self, knx_module: KNXModule, config: ConfigType) ->
None:
150 """Initialize of a KNX sensor."""
152 knx_module=knx_module,
155 if device_class := config.get(CONF_DEVICE_CLASS):
159 SensorDeviceClass, self.
_device_device.ha_device_class()
170 """Return the state of the sensor."""
171 return self.
_device_device.resolve_state()
175 """Return device specific state attributes."""
176 attr: dict[str, Any] = {}
178 if self.
_device_device.last_telegram
is not None:
179 attr[ATTR_SOURCE] =
str(self.
_device_device.last_telegram.source_address)
184 """Representation of a KNX system sensor."""
186 _attr_has_entity_name =
True
191 description: KNXSystemEntityDescription,
193 """Initialize of a KNX system sensor."""
194 self.entity_description: KNXSystemEntityDescription = description
204 """Return the state of the sensor."""
205 return self.entity_description.
value_fn(self.
knxknx)
209 """Return True if entity is available."""
210 if self.entity_description.always_available:
212 return self.
knxknx.xknx.connection_manager.state
is XknxConnectionState.CONNECTED
215 """Call after device was updated."""
219 """Store register state change callback."""
220 self.
knxknx.xknx.connection_manager.register_connection_state_changed_cb(
225 self.
knxknx.xknx.connection_manager.unregister_connection_state_changed_cb,
None __init__(self, KNXModule knx_module, ConfigType config)
dict[str, Any]|None extra_state_attributes(self)
_attr_native_unit_of_measurement
StateType native_value(self)
StateType|datetime native_value(self)
None __init__(self, KNXModule knx, KNXSystemEntityDescription description)
None async_added_to_hass(self)
None after_update_callback(self, XknxConnectionState _)
None async_write_ha_state(self)
None async_on_remove(self, CALLBACK_TYPE func)
None async_setup_entry(HomeAssistant hass, config_entries.ConfigEntry config_entry, AddEntitiesCallback async_add_entities)
XknxSensor _create_sensor(XKNX xknx, ConfigType config)