pybragerone.gateway¶
Gateway package: BragerOneGateway facade and internal helpers.
Public import path stays from pybragerone.gateway import BragerOneGateway.
Internal layout: connectivity / recovery / session mixins behind the facade.
- class pybragerone.gateway.ApiClient(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for the HTTP client used by the gateway.
This makes the gateway easy to test by allowing a lightweight fake.
- class pybragerone.gateway.BragerOneGateway(*, api: ApiClient, object_id: int, modules: Iterable[str], ws: RealtimeManagerClient | None = None, owns_api: bool = False, connectivity_poll_interval: float = 60.0, stale_prime_after_s: float = 180.0, zombie_hard_restart_after: int = 2, zombie_full_recycle_after: int = 3, zombie_rebuild_after: int = 2, zombie_recovery_cooldown_s: float = 300.0, zombie_quarantine_after: int = 3, zombie_quarantine_s: float = 21600.0, connectivity_episode_limit: int = 20, get_modules_fail_offline_after: int = 3, cloud_session_down_hysteresis_s: float | None = None)[source]¶
Bases:
ConnectivityMixin,SessionMixin,RecoveryMixinHigh-level orchestrator for BragerOne realtime data.
- Flow:
ensure_auth (proactive/reactive refresh in HTTP client)
Socket.IO connect → modules.connect (binding WS with DEV)
subscribe to streams (parameters, activity)
“prime” (REST snapshot of parameters + activity quantities)
EventBus emits ParamUpdate for consumers (ParamStore/HA/CLI)
Background REST poll of
get_modulesdiffsconnectedAtand notifieson_module_connectivity(module↔cloud; separate from EventBus)Socket.IO up/down notifies
on_cloud_session(library↔cloud; self-healing)
- Parameters:
api (ApiClient)
object_id (int)
ws (RealtimeManagerClient | None)
owns_api (bool)
connectivity_poll_interval (float)
stale_prime_after_s (float)
zombie_hard_restart_after (int)
zombie_full_recycle_after (int)
zombie_rebuild_after (int)
zombie_recovery_cooldown_s (float)
zombie_quarantine_after (int)
zombie_quarantine_s (float)
connectivity_episode_limit (int)
get_modules_fail_offline_after (int)
cloud_session_down_hysteresis_s (float | None)
- flatten_parameters(payload: dict[str, Any], *, source: str = 'unknown')[source]¶
Convert WS/REST parameter payload into ParamUpdate events.
- async classmethod from_credentials(*, email: str, password: str, object_id: int, modules: Iterable[str], server: ServerConfig | None = None, ws: RealtimeManagerClient | None = None, api: TypeAliasForwardRef('pybragerone.api.BragerOneApiClient') | None = None, connectivity_poll_interval: float = 60.0, get_modules_fail_offline_after: int = 3)[source]¶
Create a gateway from credentials.
This is a convenience helper for CLI/examples.
- Parameters:
email (
str) – BragerOne account email.password (
str) – BragerOne account password.object_id (
int) – BragerOne object/group ID.server (
ServerConfig|None) – Optional server/platform configuration (e.g. TiSConnect).ws (
RealtimeManagerClient|None) – Optional WS client instance (testing).api (
Optional[pybragerone.api.BragerOneApiClient]) – Optional API client instance (testing/customization).connectivity_poll_interval (
float) – See__init__().get_modules_fail_offline_after (
int) – Deprecated no-op; see__init__().
- Returns:
BragerOneGateway– An initialized gateway (not started).- Return type:
- async ingest_activity_quantity(data: dict[str, Any] | None)[source]¶
Ingest /modules/activity/quantity prime (optional).
- async ingest_alarm_quantity(data: dict[str, Any] | None, *, source: Literal['rest', 'ws'] = 'rest', ws_floor: dict[str, int] | None = None, rest_seq: int | None = None)[source]¶
Ingest alarm quantity payload and notify
on_alarm_quantitylisteners.
- async ingest_prime_parameters(data: dict[str, Any])[source]¶
Treat /modules/parameters prime as “cold snapshot” and publish all pairs.
- last_live_param_update_age_s()[source]¶
Return seconds since the last live (WS)
ParamUpdate, orNoneif never.
- last_param_update_age_s()[source]¶
Return seconds since the last published
ParamUpdate, orNoneif never.
- module_gateway(devid: str)[source]¶
Return the last gateway blob for devid (address/interface/version).
- on_alarm_quantity(cb: Callable[[AlarmQuantityChanged], Awaitable[None] | None])[source]¶
Register callback for per-module alarm count changes.
Callbacks receive
AlarmQuantityChangedwhen REST prime or Socket.IOapp:modules:alarms:quantity:changereports a new count for a subscribed module.- Return type:
- Parameters:
cb (Callable[[AlarmQuantityChanged], Awaitable[None] | None])
- on_any(cb: Callable[[str, Any], Awaitable[None] | None])[source]¶
Register callback for any WS event for diagnostics.
- on_cloud_session(cb: Callable[[CloudSessionConnectivity], Awaitable[None] | None])[source]¶
Register callback for library↔cloud Socket.IO session up/down.
Callbacks receive
CloudSessionConnectivity. Distinct fromon_module_connectivity(): a dropped client session must self-heal and stay detectable without looking like a module went offline.- Return type:
- Parameters:
cb (Callable[[CloudSessionConnectivity], Awaitable[None] | None])
- on_live_push(cb: Callable[[LivePushHealth], Awaitable[None] | None])[source]¶
Register callback for live
ParamUpdatepush-health flips.Callbacks receive
LivePushHealth. Distinct fromon_cloud_session(): Socket.IO can stay up while push goes stale (zombie). Preferlive_push_health()for polling.- Return type:
- Parameters:
cb (Callable[[LivePushHealth], Awaitable[None] | None])
- on_module_connectivity(cb: Callable[[ModuleConnectivity], Awaitable[None] | None])[source]¶
Register callback for module↔cloud online/offline (SPA
connectedAt).Callbacks receive
ModuleConnectivity. This path is intentionally separate frombussoParamUpdatesubscribers stay unchanged. Offline modules are observed only — the client cannot repair plant↔cloud links.- Return type:
- Parameters:
cb (Callable[[ModuleConnectivity], Awaitable[None] | None])
- on_parameters_change(cb: Callable[[str, dict[str, Any]], Awaitable[None] | None])[source]¶
Register callback for app:modules:parameters:change.
- on_snapshot(cb: Callable[[dict[str, Any]], Awaitable[None] | None])[source]¶
Register callback for snapshot event (full state-like payload).
- class pybragerone.gateway.RealtimeManager(token: str, *, origin: str = 'https://one.brager.pl', referer: str = 'https://one.brager.pl/', io_base: str = 'https://io.brager.pl', socket_path: str = '/socket.io', namespace: str = '/ws', token_provider: Callable[[], Awaitable[str]] | None = None, connect_timeout_s: float = 20.0)[source]¶
Bases:
objectThin Socket.IO wrapper for BragerOne realtime channel.
The manager keeps a single AsyncClient connection, exposes the Engine.IO SID and the namespace SID, and forwards selected events to a user-provided callback (
EventHandler). It does not interpret payloads; that is the gateway’s responsibility.Notes
Authentication is provided only via HTTP headers (Bearer token).
We always connect to the :data:`~.constants.WS_NAMESPACE` namespace.
We listen to:
snapshotand the various*:parameters:changeevents.Subscriptions are emitted in a few payload variants (
modules/devids) and optionally includegroup_id.
- Parameters:
- add_on_connected(cb: Callable[[], Awaitable[None] | None])[source]¶
Register a callback to be called when the connection is established.
- add_on_disconnected(cb: Callable[[], Awaitable[None] | None])[source]¶
Register a callback to be called when the Socket.IO session drops.
- async connect()[source]¶
Open a Socket.IO connection with appropriate headers and wait for join.
- Return type:
- async force_reconnect()[source]¶
Tear down a still-“connected” Socket.IO session and reconnect.
Used when ParamUpdates go silent while the client still reports up (zombie Engine.IO that skipped disconnect callbacks). The SPA recovers via built-in Socket.IO reconnect then
connect→ModulesService.connect+ REST/modules/parameters; our supervisor only acts whenconnectedlooks down, so this forces that same path (on_connected→ gateway resubscribe + prime).Waits for the namespace join (same as
connect()) so callers can safelysid()/modules.connectimmediately afterwards.- Return type:
- async hard_reset()[source]¶
Abandon the Socket.IO client and open a brand-new transport session.
Stronger than
force_reconnect(): stops the supervisor, replaces theAsyncClient(handlers re-bound), then runs a fullconnect(). Used when disconnect/reconnect on the same client fails to restore liveParamUpdatetraffic.- Return type:
- on_event(handler: EventDispatcher)[source]¶
Register a single event dispatcher (gateway attaches here).
- Return type:
- Parameters:
handler (EventDispatcher)
- class pybragerone.gateway.RealtimeManagerClient(*args, **kwargs)[source]¶
Bases:
ProtocolProtocol for the WS client used by the gateway.