Skip to content

Commit f3be42e

Browse files
authored
Merge pull request #15 from poolski/configurable-reporting-interval
Add configurable reporting interval
2 parents f09ce8e + 95281cb commit f3be42e

2 files changed

Lines changed: 41 additions & 54 deletions

File tree

‎custom_components/pytap/coordinator.py‎

Lines changed: 36 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -110,12 +110,12 @@ def __init__(self, hass: HomeAssistant, entry: ConfigEntry) -> None:
110110
self._host: str = entry.data[CONF_HOST]
111111
self._port: int = entry.data.get(CONF_PORT, DEFAULT_PORT)
112112
self._modules: list[dict[str, Any]] = entry.data.get(CONF_MODULES, [])
113-
raw_write_interval = entry.data.get(CONF_WRITE_INTERVAL, DEFAULT_WRITE_INTERVAL)
114-
try:
115-
write_interval = float(raw_write_interval)
116-
except (TypeError, ValueError):
117-
write_interval = float(DEFAULT_WRITE_INTERVAL)
118-
self._write_interval: float = max(0.0, write_interval)
113+
raw_write_interval = entry.data.get(CONF_WRITE_INTERVAL, DEFAULT_WRITE_INTERVAL)
114+
try:
115+
self._write_interval: float = float(raw_write_interval)
116+
except (TypeError, ValueError):
117+
self._write_interval = float(DEFAULT_WRITE_INTERVAL)
118+
self._write_interval = max(0.0, self._write_interval)
119119

120120
# Build barcode allowlist from configured modules
121121
self._configured_barcodes: set[str] = {
@@ -350,36 +350,36 @@ def _listen(self) -> None:
350350
if self._process_event(event):
351351
self._ha_update_pending = True
352352

353-
# Push to HA at most once per write interval, sending
354-
# per-barcode averages over the buffered readings rather
355-
# than the most-recent raw snapshot.
356-
now = time.monotonic()
357-
if self._ha_update_pending and (
358-
now - self._last_ha_update >= self._write_interval
359-
):
360-
self.data["counters"] = parser.counters
361-
snapshot = self._build_averaged_snapshot()
362-
per_node_counts = {
363-
barcode: len(readings)
364-
for barcode, readings in self._reading_buffers.items()
365-
if readings and barcode in snapshot["nodes"]
366-
}
367-
_LOGGER.debug(
368-
"HA update: %d node(s) — %s",
369-
len(per_node_counts),
370-
", ".join(
371-
f"{snapshot['nodes'][b].get('name', b)}: "
372-
f"{n} reading(s)"
373-
for b, n in per_node_counts.items()
374-
),
375-
)
376-
self._reading_buffers.clear()
377-
self.hass.loop.call_soon_threadsafe(
378-
self.async_set_updated_data,
379-
snapshot,
380-
)
381-
self._last_ha_update = now
382-
self._ha_update_pending = False
353+
# Push to HA at most once per write interval, sending
354+
# per-barcode averages over the buffered readings rather
355+
# than the most-recent raw snapshot.
356+
now = time.monotonic()
357+
if self._ha_update_pending and (
358+
now - self._last_ha_update >= self._write_interval
359+
):
360+
self.data["counters"] = parser.counters
361+
snapshot = self._build_averaged_snapshot()
362+
per_node_counts = {
363+
barcode: len(readings)
364+
for barcode, readings in self._reading_buffers.items()
365+
if readings and barcode in snapshot["nodes"]
366+
}
367+
_LOGGER.debug(
368+
"HA update: %d node(s) — %s",
369+
len(per_node_counts),
370+
", ".join(
371+
f"{snapshot['nodes'][b].get('name', b)}: "
372+
f"{n} reading(s)"
373+
for b, n in per_node_counts.items()
374+
),
375+
)
376+
self._reading_buffers.clear()
377+
self.hass.loop.call_soon_threadsafe(
378+
self.async_set_updated_data,
379+
snapshot,
380+
)
381+
self._last_ha_update = now
382+
self._ha_update_pending = False
383383
elif (
384384
RECONNECT_TIMEOUT > 0
385385
and (time.monotonic() - last_data_time) > RECONNECT_TIMEOUT

‎tests/test_write_interval.py‎

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import time
55
from unittest.mock import MagicMock
66

7+
import pytest
8+
79
from homeassistant.const import CONF_HOST, CONF_PORT
810
from homeassistant.core import HomeAssistant
9-
import pytest
1011

1112
from custom_components.pytap.const import (
1213
CONF_MODULE_BARCODE,
@@ -18,9 +19,10 @@
1819
DEFAULT_PORT,
1920
DEFAULT_WRITE_INTERVAL,
2021
)
21-
from custom_components.pytap.coordinator import _AVERAGED_FIELDS, PyTapDataUpdateCoordinator
22+
from custom_components.pytap.coordinator import PyTapDataUpdateCoordinator, _AVERAGED_FIELDS
2223
from custom_components.pytap.pytap.core.events import InfrastructureEvent, PowerReportEvent
2324

25+
2426
MOCK_MODULES = [
2527
{
2628
CONF_MODULE_STRING: "A",
@@ -106,10 +108,6 @@ def _run_batch(self, coordinator, event):
106108
coordinator._ha_update_pending = True
107109

108110
now = time.monotonic()
109-
return self._run_flush_check(coordinator, now)
110-
111-
def _run_flush_check(self, coordinator, now: float) -> bool:
112-
"""Simulate the write-interval flush check in the listener loop."""
113111
pushed = False
114112
if coordinator._ha_update_pending and (
115113
now - coordinator._last_ha_update >= coordinator._write_interval
@@ -157,18 +155,6 @@ def test_pending_flag_cleared_after_push(self, hass: HomeAssistant) -> None:
157155

158156
assert coordinator._ha_update_pending is False
159157

160-
def test_pending_flushes_even_when_no_new_data(self, hass: HomeAssistant) -> None:
161-
"""Pending data flushes once interval elapses, even on an empty read tick."""
162-
entry = _make_entry(hass, write_interval=60)
163-
coordinator = PyTapDataUpdateCoordinator(hass, entry)
164-
coordinator._ha_update_pending = True
165-
coordinator._last_ha_update = time.monotonic() - 61
166-
167-
pushed = self._run_flush_check(coordinator, time.monotonic())
168-
169-
assert pushed is True
170-
assert coordinator._ha_update_pending is False
171-
172158

173159
MOCK_MODULES_TWO = [
174160
{
@@ -380,3 +366,4 @@ def test_data_nodes_retains_latest_raw_value(self, hass: HomeAssistant) -> None:
380366
assert coordinator.data["nodes"]["A-1234567B"]["power"] == pytest.approx(
381367
200.0, rel=0.01
382368
)
369+

0 commit comments

Comments
 (0)