|
1 | | -"""Custom integration to integrate BatteryNotes with Home Assistant. |
| 1 | +"""Battery Notes integration for Home Assistant. |
2 | 2 |
|
3 | 3 | For more details about this integration, please refer to |
4 | 4 | https://github.com/andrew-codechimp/ha-battery-notes |
|
9 | 9 | import logging |
10 | 10 | import re |
11 | 11 | from dataclasses import dataclass, field |
12 | | -from datetime import datetime |
13 | 12 |
|
14 | 13 | import voluptuous as vol |
15 | 14 | from awesomeversion.awesomeversion import AwesomeVersion |
16 | 15 | from homeassistant.config_entries import ConfigEntry |
17 | 16 | from homeassistant.const import __version__ as HA_VERSION # noqa: N812 |
18 | 17 | from homeassistant.core import HomeAssistant, callback |
19 | 18 | from homeassistant.helpers import config_validation as cv |
20 | | -from homeassistant.helpers import device_registry as dr |
21 | 19 | from homeassistant.helpers import entity_registry as er |
22 | 20 | from homeassistant.helpers.typing import ConfigType |
23 | 21 | from homeassistant.util import dt as dt_util |
24 | 22 |
|
25 | 23 | from .config_flow import CONFIG_VERSION |
26 | 24 | from .const import ( |
27 | | - ATTR_BATTERY_LAST_REPORTED, |
28 | | - ATTR_BATTERY_LAST_REPORTED_DAYS, |
29 | | - ATTR_BATTERY_LAST_REPORTED_LEVEL, |
30 | | - ATTR_BATTERY_LEVEL, |
31 | | - ATTR_BATTERY_LOW, |
32 | | - ATTR_BATTERY_QUANTITY, |
33 | | - ATTR_BATTERY_THRESHOLD_REMINDER, |
34 | | - ATTR_BATTERY_TYPE, |
35 | | - ATTR_BATTERY_TYPE_AND_QUANTITY, |
36 | | - ATTR_DEVICE_ID, |
37 | | - ATTR_DEVICE_NAME, |
38 | | - ATTR_PREVIOUS_BATTERY_LEVEL, |
39 | 25 | ATTR_REMOVE, |
40 | | - ATTR_SOURCE_ENTITY_ID, |
41 | 26 | CONF_BATTERY_INCREASE_THRESHOLD, |
42 | 27 | CONF_BATTERY_QUANTITY, |
43 | 28 | CONF_BATTERY_TYPE, |
|
55 | 40 | DEFAULT_BATTERY_LOW_THRESHOLD, |
56 | 41 | DOMAIN, |
57 | 42 | DOMAIN_CONFIG, |
58 | | - EVENT_BATTERY_NOT_REPORTED, |
59 | | - EVENT_BATTERY_REPLACED, |
60 | | - EVENT_BATTERY_THRESHOLD, |
61 | 43 | MIN_HA_VERSION, |
62 | 44 | PLATFORMS, |
63 | | - SERVICE_BATTERY_REPLACED, |
64 | | - SERVICE_BATTERY_REPLACED_SCHEMA, |
65 | | - SERVICE_CHECK_BATTERY_LAST_REPORTED, |
66 | | - SERVICE_CHECK_BATTERY_LAST_REPORTED_SCHEMA, |
67 | | - SERVICE_CHECK_BATTERY_LOW, |
68 | | - SERVICE_DATA_DATE_TIME_REPLACED, |
69 | | - SERVICE_DATA_DAYS_LAST_REPORTED, |
70 | 45 | ) |
71 | 46 | from .device import BatteryNotesDevice |
72 | 47 | from .discovery import DiscoveryManager |
73 | 48 | from .library_updater import ( |
74 | 49 | LibraryUpdater, |
75 | 50 | ) |
| 51 | +from .services import setup_services |
76 | 52 | from .store import ( |
77 | 53 | async_get_registry, |
78 | 54 | ) |
@@ -158,7 +134,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool: |
158 | 134 | _LOGGER.debug("Auto discovery disabled") |
159 | 135 |
|
160 | 136 | # Register custom services |
161 | | - register_services(hass) |
| 137 | + setup_services(hass) |
162 | 138 |
|
163 | 139 | return True |
164 | 140 |
|
@@ -267,210 +243,3 @@ async def async_migrate_entry(hass: HomeAssistant, config_entry: ConfigEntry): |
267 | 243 | async def async_update_options(hass: HomeAssistant, entry: ConfigEntry) -> None: |
268 | 244 | """Update options.""" |
269 | 245 | await hass.config_entries.async_reload(entry.entry_id) |
270 | | - |
271 | | - |
272 | | -@callback |
273 | | -def register_services(hass: HomeAssistant): |
274 | | - """Register services used by battery notes component.""" |
275 | | - |
276 | | - async def handle_battery_replaced(call): |
277 | | - """Handle the service call.""" |
278 | | - device_id = call.data.get(ATTR_DEVICE_ID, "") |
279 | | - source_entity_id = call.data.get(ATTR_SOURCE_ENTITY_ID, "") |
280 | | - datetime_replaced_entry = call.data.get(SERVICE_DATA_DATE_TIME_REPLACED) |
281 | | - |
282 | | - if datetime_replaced_entry: |
283 | | - datetime_replaced = dt_util.as_utc(datetime_replaced_entry).replace( |
284 | | - tzinfo=None |
285 | | - ) |
286 | | - else: |
287 | | - datetime_replaced = datetime.utcnow() |
288 | | - |
289 | | - entity_registry = er.async_get(hass) |
290 | | - device_registry = dr.async_get(hass) |
291 | | - |
292 | | - if source_entity_id: |
293 | | - source_entity_entry = entity_registry.async_get(source_entity_id) |
294 | | - if not source_entity_entry: |
295 | | - _LOGGER.error( |
296 | | - "Entity %s not found", |
297 | | - source_entity_id, |
298 | | - ) |
299 | | - return |
300 | | - |
301 | | - # entity_id is the associated entity, now need to find the config entry for battery notes |
302 | | - for config_entry in hass.config_entries.async_entries(DOMAIN): |
303 | | - if config_entry.data.get("source_entity_id") == source_entity_id: |
304 | | - config_entry_id = config_entry.entry_id |
305 | | - |
306 | | - coordinator = ( |
307 | | - hass.data[DOMAIN][DATA].devices[config_entry_id].coordinator |
308 | | - ) |
309 | | - |
310 | | - coordinator.last_replaced =datetime_replaced |
311 | | - await coordinator.async_request_refresh() |
312 | | - |
313 | | - _LOGGER.debug( |
314 | | - "Entity %s battery replaced on %s", |
315 | | - source_entity_id, |
316 | | - str(datetime_replaced), |
317 | | - ) |
318 | | - |
319 | | - hass.bus.async_fire( |
320 | | - EVENT_BATTERY_REPLACED, |
321 | | - { |
322 | | - ATTR_DEVICE_ID: coordinator.device_id or "", |
323 | | - ATTR_SOURCE_ENTITY_ID: coordinator.source_entity_id |
324 | | - or "", |
325 | | - ATTR_DEVICE_NAME: coordinator.device_name, |
326 | | - ATTR_BATTERY_TYPE_AND_QUANTITY: coordinator.battery_type_and_quantity, |
327 | | - ATTR_BATTERY_TYPE: coordinator.battery_type, |
328 | | - ATTR_BATTERY_QUANTITY: coordinator.battery_quantity, |
329 | | - }, |
330 | | - ) |
331 | | - |
332 | | - _LOGGER.debug( |
333 | | - "Raised event battery replaced %s", |
334 | | - coordinator.device_id, |
335 | | - ) |
336 | | - |
337 | | - return |
338 | | - |
339 | | - _LOGGER.error("Entity %s not configured in Battery Notes", source_entity_id) |
340 | | - |
341 | | - else: |
342 | | - device_entry = device_registry.async_get(device_id) |
343 | | - if not device_entry: |
344 | | - _LOGGER.error( |
345 | | - "Device %s not found", |
346 | | - device_id, |
347 | | - ) |
348 | | - return |
349 | | - |
350 | | - for entry_id in device_entry.config_entries: |
351 | | - if ( |
352 | | - entry := hass.config_entries.async_get_entry(entry_id) |
353 | | - ) and entry.domain == DOMAIN: |
354 | | - coordinator = ( |
355 | | - hass.data[DOMAIN][DATA].devices[entry.entry_id].coordinator |
356 | | - ) |
357 | | - |
358 | | - coordinator.last_replaced =datetime_replaced |
359 | | - |
360 | | - await coordinator.async_request_refresh() |
361 | | - |
362 | | - _LOGGER.debug( |
363 | | - "Device %s battery replaced on %s", |
364 | | - device_id, |
365 | | - str(datetime_replaced), |
366 | | - ) |
367 | | - |
368 | | - hass.bus.async_fire( |
369 | | - EVENT_BATTERY_REPLACED, |
370 | | - { |
371 | | - ATTR_DEVICE_ID: coordinator.device_id or "", |
372 | | - ATTR_SOURCE_ENTITY_ID: coordinator.source_entity_id |
373 | | - or "", |
374 | | - ATTR_DEVICE_NAME: coordinator.device_name, |
375 | | - ATTR_BATTERY_TYPE_AND_QUANTITY: coordinator.battery_type_and_quantity, |
376 | | - ATTR_BATTERY_TYPE: coordinator.battery_type, |
377 | | - ATTR_BATTERY_QUANTITY: coordinator.battery_quantity, |
378 | | - }, |
379 | | - ) |
380 | | - |
381 | | - _LOGGER.debug( |
382 | | - "Raised event battery replaced %s", |
383 | | - coordinator.device_id, |
384 | | - ) |
385 | | - |
386 | | - # Found and dealt with, exit |
387 | | - return |
388 | | - |
389 | | - _LOGGER.error( |
390 | | - "Device %s not configured in Battery Notes", |
391 | | - device_id, |
392 | | - ) |
393 | | - |
394 | | - |
395 | | - async def handle_battery_last_reported(call): |
396 | | - """Handle the service call.""" |
397 | | - days_last_reported = call.data.get(SERVICE_DATA_DAYS_LAST_REPORTED) |
398 | | - |
399 | | - device: BatteryNotesDevice |
400 | | - for device in hass.data[DOMAIN][DATA].devices.values(): |
401 | | - if device.coordinator.wrapped_battery and device.coordinator.last_reported: |
402 | | - time_since_lastreported = ( |
403 | | - datetime.fromisoformat(str(datetime.utcnow()) + "+00:00") |
404 | | - - device.coordinator.last_reported |
405 | | - ) |
406 | | - |
407 | | - if time_since_lastreported.days > days_last_reported: |
408 | | - hass.bus.async_fire( |
409 | | - EVENT_BATTERY_NOT_REPORTED, |
410 | | - { |
411 | | - ATTR_DEVICE_ID: device.coordinator.device_id or "", |
412 | | - ATTR_SOURCE_ENTITY_ID: device.coordinator.source_entity_id |
413 | | - or "", |
414 | | - ATTR_DEVICE_NAME: device.coordinator.device_name, |
415 | | - ATTR_BATTERY_TYPE_AND_QUANTITY: device.coordinator.battery_type_and_quantity, |
416 | | - ATTR_BATTERY_TYPE: device.coordinator.battery_type, |
417 | | - ATTR_BATTERY_QUANTITY: device.coordinator.battery_quantity, |
418 | | - ATTR_BATTERY_LAST_REPORTED: device.coordinator.last_reported, |
419 | | - ATTR_BATTERY_LAST_REPORTED_DAYS: time_since_lastreported.days, |
420 | | - ATTR_BATTERY_LAST_REPORTED_LEVEL: device.coordinator.last_reported_level, |
421 | | - }, |
422 | | - ) |
423 | | - |
424 | | - _LOGGER.debug( |
425 | | - "Raised event device %s not reported since %s", |
426 | | - device.coordinator.device_id, |
427 | | - str(device.coordinator.last_reported), |
428 | | - ) |
429 | | - |
430 | | - async def handle_battery_low(call): |
431 | | - """Handle the service call.""" |
432 | | - |
433 | | - device: BatteryNotesDevice |
434 | | - for device in hass.data[DOMAIN][DATA].devices.values(): |
435 | | - if device.coordinator.battery_low is True: |
436 | | - hass.bus.async_fire( |
437 | | - EVENT_BATTERY_THRESHOLD, |
438 | | - { |
439 | | - ATTR_DEVICE_ID: device.coordinator.device_id or "", |
440 | | - ATTR_DEVICE_NAME: device.coordinator.device_name, |
441 | | - ATTR_SOURCE_ENTITY_ID: device.coordinator.source_entity_id |
442 | | - or "", |
443 | | - ATTR_BATTERY_LOW: device.coordinator.battery_low, |
444 | | - ATTR_BATTERY_TYPE_AND_QUANTITY: device.coordinator.battery_type_and_quantity, |
445 | | - ATTR_BATTERY_TYPE: device.coordinator.battery_type, |
446 | | - ATTR_BATTERY_QUANTITY: device.coordinator.battery_quantity, |
447 | | - ATTR_BATTERY_LEVEL: device.coordinator.rounded_battery_level, |
448 | | - ATTR_PREVIOUS_BATTERY_LEVEL: device.coordinator.rounded_previous_battery_level, |
449 | | - ATTR_BATTERY_THRESHOLD_REMINDER: True, |
450 | | - }, |
451 | | - ) |
452 | | - |
453 | | - _LOGGER.debug( |
454 | | - "Raised event device %s battery low", |
455 | | - device.coordinator.device_id, |
456 | | - ) |
457 | | - |
458 | | - hass.services.async_register( |
459 | | - DOMAIN, |
460 | | - SERVICE_BATTERY_REPLACED, |
461 | | - handle_battery_replaced, |
462 | | - schema=SERVICE_BATTERY_REPLACED_SCHEMA, |
463 | | - ) |
464 | | - |
465 | | - hass.services.async_register( |
466 | | - DOMAIN, |
467 | | - SERVICE_CHECK_BATTERY_LAST_REPORTED, |
468 | | - handle_battery_last_reported, |
469 | | - schema=SERVICE_CHECK_BATTERY_LAST_REPORTED_SCHEMA, |
470 | | - ) |
471 | | - |
472 | | - hass.services.async_register( |
473 | | - DOMAIN, |
474 | | - SERVICE_CHECK_BATTERY_LOW, |
475 | | - handle_battery_low, |
476 | | - ) |
0 commit comments