jmri_core.beans.power
Track power control.
Each ~jmri_core.hal.connection.SystemConnection exposes a single
PowerManager instance — there is no per-bean Power object because
the layout track has exactly one power state per connection.
1"""Track power control. 2 3Each :class:`~jmri_core.hal.connection.SystemConnection` exposes a single 4:class:`PowerManager` instance — there is no per-bean Power object because 5the layout track has exactly one power state per connection. 6""" 7from __future__ import annotations 8 9from dataclasses import dataclass 10 11from jmri_core.events import Signal 12from jmri_core.state import PowerState 13 14 15@dataclass(frozen=True, slots=True) 16class PowerChange: 17 previous: PowerState 18 current: PowerState 19 20 21class PowerManager: 22 """Track power state for one system connection. 23 24 Not a NamedBean — it has no system name and there is exactly one per 25 connection. Drivers override :meth:`set_power` to send the hardware 26 command and call :meth:`_set_state` when the layout reports a change. 27 """ 28 29 def __init__(self) -> None: 30 self._state: PowerState = PowerState.UNKNOWN 31 self.state_changed: Signal[PowerChange] = Signal() 32 33 @property 34 def state(self) -> PowerState: 35 return self._state 36 37 async def set_power(self, state: PowerState) -> None: 38 """Command the layout to *state*. Base impl just updates in-memory.""" 39 await self._set_state(state) 40 41 async def _set_state(self, state: PowerState) -> None: 42 prev = self._state 43 if prev == state: 44 return 45 self._state = state 46 await self.state_changed.emit(PowerChange(prev, state))
@dataclass(frozen=True, slots=True)
class
PowerChange:
16@dataclass(frozen=True, slots=True) 17class PowerChange: 18 previous: PowerState 19 current: PowerState
PowerChange( previous: jmri_core.state.PowerState, current: jmri_core.state.PowerState)
previous: jmri_core.state.PowerState
current: jmri_core.state.PowerState
class
PowerManager:
22class PowerManager: 23 """Track power state for one system connection. 24 25 Not a NamedBean — it has no system name and there is exactly one per 26 connection. Drivers override :meth:`set_power` to send the hardware 27 command and call :meth:`_set_state` when the layout reports a change. 28 """ 29 30 def __init__(self) -> None: 31 self._state: PowerState = PowerState.UNKNOWN 32 self.state_changed: Signal[PowerChange] = Signal() 33 34 @property 35 def state(self) -> PowerState: 36 return self._state 37 38 async def set_power(self, state: PowerState) -> None: 39 """Command the layout to *state*. Base impl just updates in-memory.""" 40 await self._set_state(state) 41 42 async def _set_state(self, state: PowerState) -> None: 43 prev = self._state 44 if prev == state: 45 return 46 self._state = state 47 await self.state_changed.emit(PowerChange(prev, state))
Track power state for one system connection.
Not a NamedBean — it has no system name and there is exactly one per
connection. Drivers override set_power() to send the hardware
command and call _set_state() when the layout reports a change.
state_changed: jmri_core.Signal[PowerChange]
state: jmri_core.state.PowerState