jmri_core.beans.id_tag
IdTag — one RFID / tag identity a reader has seen (or hasn't).
The JMRI mobile-throttle apps read ID-tag reads to attribute a locomotive to a physical block via an RFID reader; the tag bean stores the last reporter that saw it and the timestamp.
Wire shape (per jmri/server/json/idtag/idTag-server.json):
name— system name (typicallyIDxxx).userName— friendly label.comment— free-form.state— 0 UNKNOWN, 2 SEEN, 3 UNSEEN.reporter— system name of the last reporter to have read this tag, ornullif never seen.time— ISO-8601 timestamp of the last sighting, ornull.
1"""``IdTag`` — one RFID / tag identity a reader has seen (or hasn't). 2 3The JMRI mobile-throttle apps read ID-tag reads to attribute a 4locomotive to a physical block via an RFID reader; the tag bean stores 5the last reporter that saw it and the timestamp. 6 7Wire shape (per ``jmri/server/json/idtag/idTag-server.json``): 8 9* ``name`` — system name (typically ``IDxxx``). 10* ``userName`` — friendly label. 11* ``comment`` — free-form. 12* ``state`` — 0 UNKNOWN, 2 SEEN, 3 UNSEEN. 13* ``reporter`` — system name of the last reporter to have read this 14 tag, or ``null`` if never seen. 15* ``time`` — ISO-8601 timestamp of the last sighting, or ``null``. 16""" 17from __future__ import annotations 18 19from jmri_core.bean import AbstractNamedBean 20from jmri_core.manager import Manager 21 22# JMRI Java's IdTag.getState() values. UNKNOWN=0 matches every other 23# NamedBean's unknown; SEEN=2 mirrors sensor ACTIVE=2; UNSEEN=3 is 24# specific to IdTag (a tag that WAS seen but has since been reported 25# gone by the reader). 26ID_TAG_STATE_UNKNOWN = 0 27ID_TAG_STATE_SEEN = 2 28ID_TAG_STATE_UNSEEN = 3 29 30 31class IdTag(AbstractNamedBean): 32 """One RFID / detector tag. Read-only from the layout's perspective — 33 the app doesn't command tags, it observes reader reports.""" 34 35 __slots__ = ("_reporter_name", "_state", "_time") 36 37 type_letter = "D" 38 39 def __init__( 40 self, system_name: str, user_name: str | None = None, 41 ) -> None: 42 super().__init__(system_name, user_name) 43 self._state: int = ID_TAG_STATE_UNKNOWN 44 # Set by a reporter when the tag comes into range; kept as a 45 # string so the JSON layer can hand it back without needing a 46 # live reference to the reporter bean. 47 self._reporter_name: str | None = None 48 self._time: str | None = None 49 50 @property 51 def state(self) -> int: 52 return self._state 53 54 @property 55 def reporter_name(self) -> str | None: 56 return self._reporter_name 57 58 @property 59 def time(self) -> str | None: 60 return self._time 61 62 async def report_seen( 63 self, reporter_name: str, when: str, 64 ) -> None: 65 """A reader saw this tag at time ``when``. ``when`` is an ISO 66 timestamp string — no timezone parsing at the bean level, 67 callers supply what they already have.""" 68 self._state = ID_TAG_STATE_SEEN 69 self._reporter_name = reporter_name 70 self._time = when 71 await self.state_changed.emit(self._state) 72 73 async def report_unseen(self, when: str) -> None: 74 """The reader no longer sees this tag. Reporter attribution is 75 retained so clients can render "last seen at X, gone since Y".""" 76 self._state = ID_TAG_STATE_UNSEEN 77 self._time = when 78 await self.state_changed.emit(self._state) 79 80 81class IdTagManager(Manager[IdTag]): 82 type_letter = "D" 83 84 def _create(self, system_name: str) -> IdTag: 85 return IdTag(system_name)
32class IdTag(AbstractNamedBean): 33 """One RFID / detector tag. Read-only from the layout's perspective — 34 the app doesn't command tags, it observes reader reports.""" 35 36 __slots__ = ("_reporter_name", "_state", "_time") 37 38 type_letter = "D" 39 40 def __init__( 41 self, system_name: str, user_name: str | None = None, 42 ) -> None: 43 super().__init__(system_name, user_name) 44 self._state: int = ID_TAG_STATE_UNKNOWN 45 # Set by a reporter when the tag comes into range; kept as a 46 # string so the JSON layer can hand it back without needing a 47 # live reference to the reporter bean. 48 self._reporter_name: str | None = None 49 self._time: str | None = None 50 51 @property 52 def state(self) -> int: 53 return self._state 54 55 @property 56 def reporter_name(self) -> str | None: 57 return self._reporter_name 58 59 @property 60 def time(self) -> str | None: 61 return self._time 62 63 async def report_seen( 64 self, reporter_name: str, when: str, 65 ) -> None: 66 """A reader saw this tag at time ``when``. ``when`` is an ISO 67 timestamp string — no timezone parsing at the bean level, 68 callers supply what they already have.""" 69 self._state = ID_TAG_STATE_SEEN 70 self._reporter_name = reporter_name 71 self._time = when 72 await self.state_changed.emit(self._state) 73 74 async def report_unseen(self, when: str) -> None: 75 """The reader no longer sees this tag. Reporter attribution is 76 retained so clients can render "last seen at X, gone since Y".""" 77 self._state = ID_TAG_STATE_UNSEEN 78 self._time = when 79 await self.state_changed.emit(self._state)
One RFID / detector tag. Read-only from the layout's perspective — the app doesn't command tags, it observes reader reports.
40 def __init__( 41 self, system_name: str, user_name: str | None = None, 42 ) -> None: 43 super().__init__(system_name, user_name) 44 self._state: int = ID_TAG_STATE_UNKNOWN 45 # Set by a reporter when the tag comes into range; kept as a 46 # string so the JSON layer can hand it back without needing a 47 # live reference to the reporter bean. 48 self._reporter_name: str | None = None 49 self._time: str | None = None
63 async def report_seen( 64 self, reporter_name: str, when: str, 65 ) -> None: 66 """A reader saw this tag at time ``when``. ``when`` is an ISO 67 timestamp string — no timezone parsing at the bean level, 68 callers supply what they already have.""" 69 self._state = ID_TAG_STATE_SEEN 70 self._reporter_name = reporter_name 71 self._time = when 72 await self.state_changed.emit(self._state)
A reader saw this tag at time when. when is an ISO
timestamp string — no timezone parsing at the bean level,
callers supply what they already have.
74 async def report_unseen(self, when: str) -> None: 75 """The reader no longer sees this tag. Reporter attribution is 76 retained so clients can render "last seen at X, gone since Y".""" 77 self._state = ID_TAG_STATE_UNSEEN 78 self._time = when 79 await self.state_changed.emit(self._state)
The reader no longer sees this tag. Reporter attribution is retained so clients can render "last seen at X, gone since Y".
Inherited Members
82class IdTagManager(Manager[IdTag]): 83 type_letter = "D" 84 85 def _create(self, system_name: str) -> IdTag: 86 return IdTag(system_name)
Per-type bean registry. Subclass and override _create().
Attributes set on the class describe the bean type:
type_letter— single uppercase letter the bean class owns (e.g."T"for Turnout). Must be set by subclass.system_prefix— connection prefix (e.g."L"). Set per-instance because one bean class can have many connection-specific managers.