forked from elupus/hass_nibe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
entity.py
188 lines (159 loc) · 6.03 KB
/
entity.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
"""Base entities for nibe."""
from __future__ import annotations
import logging
from typing import Optional
from homeassistant.core import callback
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from nibeuplink.typing import ParameterId, ParameterType
from . import NibeSystem
from .const import DOMAIN as DOMAIN_NIBE
ParameterSet = dict[ParameterId, Optional[ParameterType]]
_LOGGER = logging.getLogger(__name__)
UNIT_ICON = {"A": "mdi:power-plug", "Hz": "mdi:update", "h": "mdi:clock"}
class NibeEntity(CoordinatorEntity[NibeSystem]):
"""Base class for all nibe system entities."""
def __init__(
self,
system: NibeSystem,
parameters: set[ParameterId | None],
):
"""Initialize base class."""
super().__init__(system)
self._system = system
self._uplink = system.uplink
self._system_id = system.system_id
self._attr_device_info = {"identifiers": {(DOMAIN_NIBE, self._system_id)}}
self._parameters = parameters
def get_parameter(self, parameter_id: ParameterId | None) -> ParameterType | None:
"""Get the full parameter dict."""
if not parameter_id:
return None
return self._system.get_parameter(parameter_id)
def get_bool(self, parameter_id: ParameterId | None) -> bool | None:
"""Get bool parameter."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or data["value"] is None:
return False
else:
return bool(data["value"])
def get_float(
self, parameter_id: ParameterId | None, default: float | None = None
) -> float | None:
"""Get float parameter."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or data["value"] is None:
return default
else:
return float(data["value"])
def get_value(self, parameter_id: ParameterId | None, default=None):
"""Get value in display format."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or data["value"] is None:
return default
else:
return data["value"]
def get_unit(
self, parameter_id: ParameterId | None, default: str | None = None
) -> str | None:
"""Get value in display format."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or not data["unit"]:
return default
else:
# Work around strange degree unit
if data["unit"] == "ºC":
return "°C"
return data["unit"]
def get_raw(self, parameter_id: ParameterId | None, default=None):
"""Get value in display format."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or data["rawValue"] is None:
return default
else:
return data["rawValue"]
def get_scale(self, parameter_id: ParameterId | None) -> float | None:
"""Calculate scale of parameter."""
if not parameter_id:
return None
data = self._system.get_parameter(parameter_id)
if data is None or data["value"] is None:
return 1.0
else:
return float(data["rawValue"]) / float(data["value"])
def parse_data(self):
"""Parse data to update internal variables."""
pass
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self.parse_data()
self.async_write_ha_state()
async def async_added_to_hass(self) -> None:
"""When entity is added to hass."""
await super().async_added_to_hass()
self.async_on_remove(self._system.add_parameter_subscriber(self._parameters))
async def async_update(self):
"""Handle request to update this entity."""
if not self.enabled:
return
_LOGGER.debug("Update %s", self.entity_id)
await self._system.update_parameters(self._parameters)
self.parse_data()
class NibeParameterEntity(NibeEntity):
"""Base class with common attributes for parameter entities."""
def __init__(
self,
system: NibeSystem,
parameter_id: ParameterId,
entity_id_format: str | None = None,
):
"""Initialize base class for parameters."""
super().__init__(system, parameters={parameter_id})
self._parameter_id = parameter_id
self._value = None
self._attr_unique_id = f"{system.system_id}_{parameter_id}"
self._attr_name = None
self._attr_icon = None
self.parse_data()
if entity_id_format:
self.entity_id = entity_id_format.format(
f"{DOMAIN_NIBE}_{system.system_id}_{str(parameter_id)}"
)
@property
def extra_state_attributes(self):
"""Return the state attributes."""
data = self.get_parameter(self._parameter_id)
if data:
return {
"designation": data["designation"],
"parameter_id": data["parameterId"],
"display_value": data["displayValue"],
"raw_value": data["rawValue"],
"display_unit": data["unit"],
}
else:
return {}
@property
def available(self):
"""Return True if entity is available."""
return super().available and self._value is not None
def parse_data(self):
"""Parse data to update internal variables."""
data = self.get_parameter(self._parameter_id)
if data:
if self._attr_name is None:
self._attr_name = data["title"]
self._attr_icon = UNIT_ICON.get(data["unit"], None)
self._value = data["value"]
else:
self._value = None