Skip to content

Commit 9d00dc0

Browse files
andrew-codechimpCopilot
andauthored
Update throttle (#4655)
Co-authored-by: Copilot <copilot@github.com>
1 parent 8f286e7 commit 9d00dc0

3 files changed

Lines changed: 44 additions & 11 deletions

File tree

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
[![License][license-shield]](LICENSE)
88
[![hacs][hacsbadge]][hacs]
99

10-
Integration to add battery notes to a device or entity, with automatic discovery via a growing [battery library](library.md) for devices.
10+
Integration to add battery notes to a device or entity, with automatic discovery via a growing [battery library](library.md) for devices.
11+
1112
Track the battery type, when the battery was replaced, when a battery is low based on device or global thresholds and also when a battery hasn't been reported for a while.
1213

14+
The library makes adding battery notes easy, identifying the type of battery when known, but you can also add your own manually.
15+
1316
**Dashboard cards usage**
1417

1518
A battery+ sensor provides useful attributes for easy use in dashboards, the standard battery can optionally be hidden.

custom_components/battery_notes/const.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
DEFAULT_BATTERY_LOW_THRESHOLD = 10
2323
DEFAULT_BATTERY_INCREASE_THRESHOLD = 25
24+
STATE_WRITE_INTERVAL_SECONDS = 60 * 60 # 1 hour
2425
DEFAULT_LIBRARY_URL = "https://battery-notes-data.codechimp.org/library.json"
2526
DEFAULT_SCHEMA_URL = "https://battery-notes-data.codechimp.org/schema.json"
2627
FALLBACK_LIBRARY_URL = "https://raw.githubusercontent.com/andrew-codechimp/HA-Battery-Notes/main/library/library.json" # pylint: disable=line-too-long

custom_components/battery_notes/sensor.py

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@
7676
CONF_ROUND_BATTERY,
7777
CONF_SOURCE_ENTITY_ID,
7878
DOMAIN,
79+
STATE_WRITE_INTERVAL_SECONDS,
7980
SUBENTRY_BATTERY_NOTE,
8081
)
8182
from .coordinator import (
@@ -419,6 +420,33 @@ def __init__( # noqa: PLR0913
419420
self._attr_state_class = SensorStateClass.MEASUREMENT
420421
self._attr_native_unit_of_measurement = PERCENTAGE
421422

423+
self._last_ha_state_write: datetime | None = None
424+
self._last_written_battery_level: float | None = None
425+
426+
@callback
427+
def _write_tracked_ha_state(self) -> None:
428+
"""Write state at startup, on value changes, or when interval elapsed."""
429+
native_value = self._attr_native_value
430+
if isinstance(native_value, int | float | str):
431+
try:
432+
current_battery_level = float(native_value)
433+
except ValueError:
434+
current_battery_level = None
435+
else:
436+
current_battery_level = None
437+
438+
if self._last_ha_state_write is not None:
439+
if (
440+
current_battery_level == self._last_written_battery_level
441+
and (dt_util.utcnow() - self._last_ha_state_write).total_seconds()
442+
< STATE_WRITE_INTERVAL_SECONDS
443+
):
444+
return
445+
446+
self._last_ha_state_write = dt_util.utcnow()
447+
self._last_written_battery_level = current_battery_level
448+
self.async_write_ha_state()
449+
422450
@property
423451
def extra_state_attributes(self) -> dict[str, Any] | None:
424452
"""Return the state attributes of the battery type."""
@@ -518,7 +546,7 @@ async def async_state_changed_listener(
518546

519547
self._attr_native_value = None
520548
self._attr_available = False
521-
self.async_write_ha_state()
549+
self._write_tracked_ha_state()
522550
return
523551

524552
self.coordinator.current_battery_level = wrapped_battery_state.state
@@ -529,7 +557,7 @@ async def async_state_changed_listener(
529557
self._attr_native_value = self.coordinator.rounded_battery_level
530558
self._wrapped_attributes = wrapped_battery_state.attributes
531559

532-
self.async_write_ha_state()
560+
self._write_tracked_ha_state()
533561

534562
@callback
535563
async def async_state_reported_listener(
@@ -557,23 +585,21 @@ async def async_state_reported_listener(
557585
):
558586
self._attr_native_value = None
559587
self._attr_available = False
560-
self.async_write_ha_state()
588+
self._write_tracked_ha_state()
561589
return
562590

563591
# Don't update if battery level same and it's been < 1 hour
564592
delta = dt_util.utcnow() - self.coordinator.last_wrapped_battery_state_write
565593
if (
566594
self.coordinator.last_reported_level == wrapped_battery_state.state
567-
and delta.total_seconds() < 3600 # 1 hour
595+
and delta.total_seconds() < STATE_WRITE_INTERVAL_SECONDS
568596
):
569597
self._attr_available = True
570598
return
571599

572600
self.coordinator.last_wrapped_battery_state_write = dt_util.utcnow()
573601
self.coordinator.current_battery_level = wrapped_battery_state.state
574602

575-
await self.coordinator.async_request_refresh()
576-
577603
self.coordinator.last_reported = dt_util.utcnow()
578604

579605
_LOGGER.debug(
@@ -587,7 +613,7 @@ async def async_state_reported_listener(
587613
self._attr_native_value = self.coordinator.rounded_battery_level
588614
self._wrapped_attributes = wrapped_battery_state.attributes
589615

590-
self.async_write_ha_state()
616+
self._write_tracked_ha_state()
591617

592618
async def _register_entity_id_change_listener(
593619
self,
@@ -743,8 +769,12 @@ def _handle_coordinator_update(self) -> None:
743769
"""Handle updated data from the coordinator."""
744770

745771
_LOGGER.debug("Update from coordinator")
772+
battery_level = self.coordinator.rounded_battery_level
746773

747-
self.async_write_ha_state()
774+
if battery_level is not None:
775+
self._attr_native_value = battery_level
776+
777+
self._write_tracked_ha_state()
748778

749779
@property
750780
def extra_state_attributes(self) -> dict[str, Any] | None:
@@ -922,8 +952,7 @@ def _handle_results(
922952
event, update.template, update.last_result, update.result
923953
)
924954

925-
self.async_write_ha_state()
926-
return
955+
self._write_tracked_ha_state()
927956

928957
@callback
929958
def _update_state(self, result):

0 commit comments

Comments
 (0)