21
21
BinarySensorEntityDescription ,
22
22
BinarySensorDeviceClass ,
23
23
)
24
-
24
+ from homeassistant .helpers .update_coordinator import (
25
+ CoordinatorEntity ,
26
+ )
25
27
from homeassistant .helpers .entity import DeviceInfo , EntityCategory
26
28
from homeassistant .helpers .event import (
27
- EventStateChangedData ,
28
- async_track_state_change_event ,
29
29
async_track_entity_registry_updated_event ,
30
30
)
31
- from homeassistant .helpers .typing import EventType
32
31
from homeassistant .helpers .reload import async_setup_reload_service
33
32
34
33
from homeassistant .const import (
42
41
43
42
from .const import (
44
43
DOMAIN ,
45
- DOMAIN_CONFIG ,
46
44
DATA ,
47
- CONF_ENABLE_REPLACED ,
48
- CONF_ROUND_BATTERY ,
49
- CONF_BATTERY_INCREASE_THRESHOLD ,
50
- EVENT_BATTERY_THRESHOLD ,
51
- EVENT_BATTERY_INCREASED ,
52
- DEFAULT_BATTERY_INCREASE_THRESHOLD ,
53
- ATTR_DEVICE_ID ,
54
- ATTR_BATTERY_QUANTITY ,
55
- ATTR_BATTERY_TYPE ,
56
- ATTR_BATTERY_TYPE_AND_QUANTITY ,
57
- ATTR_BATTERY_LOW ,
58
45
ATTR_BATTERY_LOW_THRESHOLD ,
59
- ATTR_DEVICE_NAME ,
60
- ATTR_BATTERY_LEVEL ,
61
- ATTR_PREVIOUS_BATTERY_LEVEL ,
62
46
)
63
47
64
48
from .common import isfloat
65
- from . device import BatteryNotesDevice
49
+
66
50
from .coordinator import BatteryNotesCoordinator
67
51
68
52
from .entity import (
@@ -147,21 +131,12 @@ async def async_registry_updated(event: Event) -> None:
147
131
148
132
device_id = async_add_to_device (hass , config_entry )
149
133
150
- enable_replaced = True
151
- round_battery = False
152
-
153
- if DOMAIN_CONFIG in hass .data [DOMAIN ]:
154
- domain_config : dict = hass .data [DOMAIN ][DOMAIN_CONFIG ]
155
- enable_replaced = domain_config .get (CONF_ENABLE_REPLACED , True )
156
- round_battery = domain_config .get (CONF_ROUND_BATTERY , False )
157
-
158
134
description = BatteryNotesBinarySensorEntityDescription (
159
135
unique_id_suffix = "_battery_low" ,
160
- key = "battery_low " ,
136
+ key = "_battery_plus_low " ,
161
137
translation_key = "battery_low" ,
162
138
icon = "mdi:battery-alert" ,
163
139
entity_category = EntityCategory .DIAGNOSTIC ,
164
- entity_registry_enabled_default = enable_replaced ,
165
140
device_class = BinarySensorDeviceClass .BATTERY ,
166
141
)
167
142
@@ -175,8 +150,6 @@ async def async_registry_updated(event: Event) -> None:
175
150
coordinator ,
176
151
description ,
177
152
f"{ config_entry .entry_id } { description .unique_id_suffix } " ,
178
- device ,
179
- round_battery ,
180
153
)
181
154
]
182
155
)
@@ -190,35 +163,28 @@ async def async_setup_platform(
190
163
await async_setup_reload_service (hass , DOMAIN , PLATFORMS )
191
164
192
165
193
- class BatteryNotesBatteryLowSensor (BinarySensorEntity ):
166
+ class BatteryNotesBatteryLowSensor (BinarySensorEntity , CoordinatorEntity [ BatteryNotesCoordinator ] ):
194
167
"""Represents a low battery threshold binary sensor."""
195
168
196
169
_attr_should_poll = False
197
- _battery_entity_id = None
198
- device_name = None
199
- _previous_battery_low = None
200
- _previous_battery_level = None
201
- _previous_state_last_changed = None
202
-
203
- entity_description : BatteryNotesBinarySensorEntityDescription
204
170
205
171
def __init__ (
206
172
self ,
207
173
hass : HomeAssistant ,
208
174
coordinator : BatteryNotesCoordinator ,
209
175
description : BatteryNotesBinarySensorEntityDescription ,
210
176
unique_id : str ,
211
- device : BatteryNotesDevice ,
212
- round_battery : bool ,
213
177
) -> None :
214
178
"""Create a low battery binary sensor."""
179
+
215
180
device_registry = dr .async_get (hass )
216
181
217
182
self .coordinator = coordinator
218
183
self .entity_description = description
219
184
self ._attr_unique_id = unique_id
220
185
self ._attr_has_entity_name = True
221
- self .round_battery = round_battery
186
+
187
+ super ().__init__ (coordinator = coordinator )
222
188
223
189
if coordinator .device_id and (
224
190
device_entry := device_registry .async_get (coordinator .device_id )
@@ -228,141 +194,53 @@ def __init__(
228
194
identifiers = device_entry .identifiers ,
229
195
)
230
196
231
- self .entity_id = f"binary_sensor.{ device .name .lower ()} _{ description .key } "
232
- self .device_name = device .name
233
-
234
- self ._battery_entity_id = (
235
- device .wrapped_battery .entity_id if device .wrapped_battery else None
236
- )
237
-
238
- @callback
239
- async def async_state_changed_listener (
240
- self , event : EventType [EventStateChangedData ] | None = None
241
- ) -> None :
242
- # pylint: disable=unused-argument
243
- """Handle child updates."""
244
-
245
- if not self ._battery_entity_id :
246
- return
247
-
248
- if (
249
- wrapped_battery_state := self .hass .states .get (self ._battery_entity_id )
250
- ) is None or wrapped_battery_state .state in [STATE_UNAVAILABLE , STATE_UNKNOWN ]:
251
- self ._attr_is_on = False
252
- self ._attr_available = True
253
- return
254
-
255
- battery_low = bool (
256
- float (wrapped_battery_state .state ) < self .coordinator .battery_low_threshold
257
- )
258
-
259
- self .coordinator .set_battery_low (battery_low )
260
-
261
- self ._attr_is_on = self .coordinator .battery_low
262
-
263
- self ._attr_available = True
264
-
265
- self .async_write_ha_state ()
266
-
267
- _LOGGER .debug (
268
- "%s battery_low changed: %s" , self ._battery_entity_id , battery_low
269
- )
270
-
271
- await self .coordinator .async_request_refresh ()
272
-
273
- if isfloat (wrapped_battery_state .state ):
274
- if self .round_battery :
275
- battery_level = round (float (wrapped_battery_state .state ), 0 )
276
- else :
277
- battery_level = round (float (wrapped_battery_state .state ), 1 )
278
- else :
279
- battery_level = wrapped_battery_state .state
280
-
281
- if self ._previous_state_last_changed :
282
- # Battery low event
283
- if battery_low != self ._previous_battery_low :
284
- self .hass .bus .fire (
285
- EVENT_BATTERY_THRESHOLD ,
286
- {
287
- ATTR_DEVICE_ID : self .coordinator .device_id ,
288
- ATTR_DEVICE_NAME : self .device_name ,
289
- ATTR_BATTERY_LOW : battery_low ,
290
- ATTR_BATTERY_TYPE_AND_QUANTITY : self .coordinator .battery_type_and_quantity ,
291
- ATTR_BATTERY_TYPE : self .coordinator .battery_type ,
292
- ATTR_BATTERY_QUANTITY : self .coordinator .battery_quantity ,
293
- ATTR_BATTERY_LEVEL : battery_level ,
294
- ATTR_PREVIOUS_BATTERY_LEVEL : self ._previous_battery_level ,
295
- },
296
- )
297
-
298
- _LOGGER .debug ("battery_threshold event fired Low: %s" , battery_low )
299
-
300
- # Battery increased event
301
- increase_threshold = DEFAULT_BATTERY_INCREASE_THRESHOLD
302
- if DOMAIN_CONFIG in self .hass .data [DOMAIN ]:
303
- domain_config : dict = self .hass .data [DOMAIN ][DOMAIN_CONFIG ]
304
- increase_threshold = domain_config .get (
305
- CONF_BATTERY_INCREASE_THRESHOLD , DEFAULT_BATTERY_INCREASE_THRESHOLD
306
- )
307
-
308
- if wrapped_battery_state .state not in [STATE_UNAVAILABLE , STATE_UNKNOWN ]:
309
- if (
310
- wrapped_battery_state .state
311
- and self ._previous_battery_level
312
- and float (wrapped_battery_state .state )
313
- >= (self ._previous_battery_level + increase_threshold )
314
- ):
315
- self .hass .bus .fire (
316
- EVENT_BATTERY_INCREASED ,
317
- {
318
- ATTR_DEVICE_ID : self .coordinator .device_id ,
319
- ATTR_DEVICE_NAME : self .device_name ,
320
- ATTR_BATTERY_LOW : battery_low ,
321
- ATTR_BATTERY_TYPE_AND_QUANTITY : self .coordinator .battery_type_and_quantity ,
322
- ATTR_BATTERY_TYPE : self .coordinator .battery_type ,
323
- ATTR_BATTERY_QUANTITY : self .coordinator .battery_quantity ,
324
- ATTR_BATTERY_LEVEL : battery_level ,
325
- ATTR_PREVIOUS_BATTERY_LEVEL : self ._previous_battery_level ,
326
- },
327
- )
328
-
329
- _LOGGER .debug ("battery_increased event fired" )
330
-
331
- self ._previous_battery_level = battery_level
332
- self ._previous_state_last_changed = wrapped_battery_state .last_changed
333
- self ._previous_battery_low = battery_low
197
+ self .entity_id = f"binary_sensor.{ coordinator .device_name .lower ()} _{ description .key } "
334
198
335
199
async def async_added_to_hass (self ) -> None :
336
200
"""Handle added to Hass."""
337
201
338
- @callback
339
- async def _async_state_changed_listener (
340
- event : EventType [EventStateChangedData ] | None = None ,
341
- ) -> None :
342
- """Handle child updates."""
343
- await self .async_state_changed_listener (event )
344
-
345
- if self ._battery_entity_id :
346
- self .async_on_remove (
347
- async_track_state_change_event (
348
- self .hass , [self ._battery_entity_id ], _async_state_changed_listener
349
- )
350
- )
351
-
352
- # Call once on adding
353
- await _async_state_changed_listener ()
202
+ await super ().async_added_to_hass ()
354
203
355
204
# Update entity options
356
205
registry = er .async_get (self .hass )
357
- if registry .async_get (self .entity_id ) is not None and self ._battery_entity_id :
206
+ if registry .async_get (self .entity_id ) is not None and self .coordinator . wrapped_battery . entity_id :
358
207
registry .async_update_entity_options (
359
208
self .entity_id ,
360
209
DOMAIN ,
361
- {"entity_id" : self ._battery_entity_id },
210
+ {"entity_id" : self .coordinator . wrapped_battery . entity_id },
362
211
)
363
212
364
213
await self .coordinator .async_config_entry_first_refresh ()
365
214
215
+ @callback
216
+ def _handle_coordinator_update (self ) -> None :
217
+ """Handle updated data from the coordinator."""
218
+
219
+ if (
220
+ (
221
+ wrapped_battery_state := self .hass .states .get (
222
+ self .coordinator .wrapped_battery .entity_id
223
+ )
224
+ )
225
+ is None
226
+ or wrapped_battery_state .state
227
+ in [
228
+ STATE_UNAVAILABLE ,
229
+ STATE_UNKNOWN ,
230
+ ]
231
+ or not isfloat (wrapped_battery_state .state )
232
+ ):
233
+ self ._attr_is_on = None
234
+ self ._attr_available = False
235
+ self .async_write_ha_state ()
236
+ return
237
+
238
+ self ._attr_is_on = self .coordinator .battery_low
239
+
240
+ self .async_write_ha_state ()
241
+
242
+ _LOGGER .debug ("%s binary sensor battery_low set to: %s" , self .coordinator .wrapped_battery .entity_id , self .coordinator .battery_low )
243
+
366
244
@property
367
245
def extra_state_attributes (self ) -> dict [str , str ] | None :
368
246
"""Return the state attributes of battery low."""
0 commit comments