42 lines
1.2 KiB
Python
42 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
import time
|
|
from dataclasses import dataclass, field
|
|
|
|
|
|
@dataclass
|
|
class PeriodicRefresh:
|
|
"""Small scheduler for optional CCU state-refresh frames."""
|
|
|
|
frames: list[bytes] = field(default_factory=list)
|
|
interval: float = 0.0
|
|
_next_due: float | None = None
|
|
_index: int = 0
|
|
|
|
@property
|
|
def enabled(self) -> bool:
|
|
return bool(self.frames) and self.interval > 0
|
|
|
|
def start(self, now: float | None = None) -> None:
|
|
if not self.enabled:
|
|
self._next_due = None
|
|
return
|
|
self._next_due = (time.monotonic() if now is None else now) + self.interval
|
|
|
|
def due_frames(self, now: float | None = None) -> list[bytes]:
|
|
if not self.enabled:
|
|
return []
|
|
current = time.monotonic() if now is None else now
|
|
if self._next_due is None:
|
|
self._next_due = current + self.interval
|
|
return []
|
|
if current < self._next_due:
|
|
return []
|
|
|
|
frame = self.frames[self._index % len(self.frames)]
|
|
self._index += 1
|
|
|
|
while self._next_due <= current:
|
|
self._next_due += self.interval
|
|
return [frame]
|