diff --git a/README.md b/README.md index 24aed6c..56baf5e 100644 --- a/README.md +++ b/README.md @@ -249,7 +249,7 @@ Add listener for data updates. ### `listen(self)` Listen to the telemetry stream. -### `listen_Credits(callback: Callable[[dict[str, str | int]], None]) -> Callable[[], None]` +### `listen_Credits(callback: Callable[[CreditsEvent], None]) -> Callable[[], None]` Add listener for credit events. ### `listen_Balance(callback: Callable[[int], None]) -> Callable[[], None]` diff --git a/teslemetry_stream/const.py b/teslemetry_stream/const.py index 2a01dd2..ea3f1f8 100644 --- a/teslemetry_stream/const.py +++ b/teslemetry_stream/const.py @@ -423,6 +423,33 @@ def from_dict(cls, data: dict[str, float | None]) -> EnergyHistoryTotals: return cls(**{field: data.get(field) for field in cls.__dataclass_fields__}) +@dataclass +class CreditsEvent: + """A credits accounting event. + + `quota` is carried through as the server sends it rather than typed + field-by-field - every observed payload has shipped it empty, so there + is no evidence yet of what it contains when populated. + """ + + type: str + cost: int + name: str + balance: int + quota: dict[str, Any] + + @classmethod + def from_dict(cls, data: dict[str, Any]) -> CreditsEvent: + """Build from the event's `credits` dict.""" + return cls( + type=data["type"], + cost=data["cost"], + name=data["name"], + balance=data["balance"], + quota=data.get("quota", {}), + ) + + @dataclass class TeslaLocation: """Location data""" diff --git a/teslemetry_stream/stream.py b/teslemetry_stream/stream.py index 021f34f..a067dca 100644 --- a/teslemetry_stream/stream.py +++ b/teslemetry_stream/stream.py @@ -9,6 +9,7 @@ import aiohttp +from .const import CreditsEvent from .energysite import TeslemetryStreamEnergySite from .exception import TeslemetryStreamEnded from .vehicle import TeslemetryStreamVehicle @@ -462,7 +463,7 @@ async def listen(self) -> None: LOGGER.debug("Listen has finished") def listen_Credits( - self, callback: Callable[[dict[str, str | int]], None] + self, callback: Callable[[CreditsEvent], None] ) -> Callable[[], None]: """ Listen for credits update. @@ -471,7 +472,7 @@ def listen_Credits( :return: Function to remove the listener. """ return self.async_add_listener( - lambda x: callback(x["credits"]), {"credits": None} + lambda x: callback(CreditsEvent.from_dict(x["credits"])), {"credits": None} ) def listen_Balance(self, callback: Callable[[int], None]) -> Callable[[], None]: