jmri_openlcb.events
EventId — the 64-bit OpenLCB event identifier.
OpenLCB events are 64-bit values uniquely identifying something happened on the network. A sensor turning on produces one event ID; the same sensor turning off produces a different event ID. Beans that should react bind specific event IDs to specific state transitions.
The canonical text form is dotted hex, big-endian, e.g.
"05.01.01.01.4C.43.00.01" — eight bytes joined by dots. We parse
both that form and a plain hex string "05010101 4C430001" (with or
without spaces) since both appear in JMRI configs.
1"""``EventId`` — the 64-bit OpenLCB event identifier. 2 3OpenLCB events are 64-bit values uniquely identifying *something happened* 4on the network. A sensor turning on produces one event ID; the same 5sensor turning off produces a different event ID. Beans that should 6react bind specific event IDs to specific state transitions. 7 8The canonical text form is dotted hex, big-endian, e.g. 9``"05.01.01.01.4C.43.00.01"`` — eight bytes joined by dots. We parse 10both that form and a plain hex string ``"05010101 4C430001"`` (with or 11without spaces) since both appear in JMRI configs. 12""" 13from __future__ import annotations 14 15from dataclasses import dataclass 16 17 18@dataclass(frozen=True, slots=True) 19class EventId: 20 """64-bit OpenLCB event identifier.""" 21 22 value: int # 0..2**64-1 23 24 def __post_init__(self) -> None: 25 if not 0 <= self.value < (1 << 64): 26 raise ValueError(f"EventId must be 0..2**64-1, got {self.value}") 27 28 @classmethod 29 def parse(cls, text: str) -> EventId: 30 """Parse the dotted-hex or plain-hex text form into an :class:`EventId`.""" 31 cleaned = text.replace(".", "").replace(" ", "").strip() 32 if not cleaned: 33 raise ValueError(f"empty EventId text {text!r}") 34 try: 35 return cls(int(cleaned, 16)) 36 except ValueError as e: 37 raise ValueError(f"invalid EventId text {text!r}: {e}") from None 38 39 @property 40 def bytes(self) -> bytes: 41 return self.value.to_bytes(8, "big") 42 43 def __str__(self) -> str: 44 b = self.bytes 45 return ".".join(f"{x:02X}" for x in b) 46 47 48@dataclass(frozen=True, slots=True) 49class EventReport: 50 """Produced/Consumer Event Report — the workhorse message. 51 52 Sent by producers to announce "this event happened"; observed by 53 consumers to drive their state. The 64-bit ``event`` is enough; the 54 16-bit source ``alias`` identifies *which* node produced it (useful 55 for diagnostics; we don't validate aliases here). 56 """ 57 58 event: EventId 59 source_alias: int # 12-bit node alias, observed in the CAN header
19@dataclass(frozen=True, slots=True) 20class EventId: 21 """64-bit OpenLCB event identifier.""" 22 23 value: int # 0..2**64-1 24 25 def __post_init__(self) -> None: 26 if not 0 <= self.value < (1 << 64): 27 raise ValueError(f"EventId must be 0..2**64-1, got {self.value}") 28 29 @classmethod 30 def parse(cls, text: str) -> EventId: 31 """Parse the dotted-hex or plain-hex text form into an :class:`EventId`.""" 32 cleaned = text.replace(".", "").replace(" ", "").strip() 33 if not cleaned: 34 raise ValueError(f"empty EventId text {text!r}") 35 try: 36 return cls(int(cleaned, 16)) 37 except ValueError as e: 38 raise ValueError(f"invalid EventId text {text!r}: {e}") from None 39 40 @property 41 def bytes(self) -> bytes: 42 return self.value.to_bytes(8, "big") 43 44 def __str__(self) -> str: 45 b = self.bytes 46 return ".".join(f"{x:02X}" for x in b)
64-bit OpenLCB event identifier.
29 @classmethod 30 def parse(cls, text: str) -> EventId: 31 """Parse the dotted-hex or plain-hex text form into an :class:`EventId`.""" 32 cleaned = text.replace(".", "").replace(" ", "").strip() 33 if not cleaned: 34 raise ValueError(f"empty EventId text {text!r}") 35 try: 36 return cls(int(cleaned, 16)) 37 except ValueError as e: 38 raise ValueError(f"invalid EventId text {text!r}: {e}") from None
Parse the dotted-hex or plain-hex text form into an EventId.
49@dataclass(frozen=True, slots=True) 50class EventReport: 51 """Produced/Consumer Event Report — the workhorse message. 52 53 Sent by producers to announce "this event happened"; observed by 54 consumers to drive their state. The 64-bit ``event`` is enough; the 55 16-bit source ``alias`` identifies *which* node produced it (useful 56 for diagnostics; we don't validate aliases here). 57 """ 58 59 event: EventId 60 source_alias: int # 12-bit node alias, observed in the CAN header
Produced/Consumer Event Report — the workhorse message.
Sent by producers to announce "this event happened"; observed by
consumers to drive their state. The 64-bit event is enough; the
16-bit source alias identifies which node produced it (useful
for diagnostics; we don't validate aliases here).