jmri_core.beans.consist
Consist — an ordered group of locomotives operating together.
Not a NamedBean: a consist is a configuration object that owns a set of addresses + per-loco direction flags. The hardware-level consisting (whether the loconet/NCE/etc. command station tracks the group, or whether the software simply broadcasts identical commands to each address) is the driver's concern; here we only carry the data.
1"""``Consist`` — an ordered group of locomotives operating together. 2 3Not a NamedBean: a consist is a configuration object that owns a set of 4addresses + per-loco direction flags. The hardware-level consisting (whether 5the loconet/NCE/etc. command station tracks the group, or whether the 6software simply broadcasts identical commands to each address) is the 7driver's concern; here we only carry the data. 8""" 9from __future__ import annotations 10 11from typing import Literal 12 13from pydantic import BaseModel, Field 14 15ConsistKind = Literal["advanced", "command_station", "software"] 16 17# Consist addresses are constrained to NMRA CV19's 7-bit range across 18# every kind — advanced consists literally encode the group into CV19 19# on each decoder, and we hold command-station / software consists to 20# the same rule so the address space is uniform and the UI doesn't 21# have to fork on kind. Bit 7 of CV19 carries direction, so only 22# 1..127 is available for the group identifier itself. 23CONSIST_ADDRESS_MAX = 127 24 25 26class ConsistLoco(BaseModel): 27 """One member of a consist. Individual member locomotives may still 28 have long addresses — only the *consist*'s own address is 29 restricted to short 1..127.""" 30 31 address: int = Field(ge=1, le=10239) 32 long_address: bool = False 33 direction_normal: bool = True 34 # Position is the index within the consist; first added = 0. 35 position: int = Field(ge=0) 36 37 38class Consist(BaseModel): 39 """An ordered group of locomotives. 40 41 The "consist address" identifies the group on the bus. For advanced 42 (CV19) consists this is the active short address shared across locos; 43 for command-station consists it's a slot/handle the command station 44 assigns; for software consists it's the bookkeeping key. All three 45 variants are held to the 1..127 short-address range for consistency 46 with the CV19 wire limit. 47 """ 48 49 address: int = Field(ge=1, le=CONSIST_ADDRESS_MAX) 50 kind: ConsistKind = "advanced" 51 locos: list[ConsistLoco] = Field(default_factory=list) 52 comment: str = "" 53 54 def add(self, loco: ConsistLoco) -> None: 55 self.locos.append(loco) 56 57 def remove(self, address: int) -> bool: 58 """Drop the loco at *address*. Returns True if found.""" 59 for i, loco in enumerate(self.locos): 60 if loco.address == address: 61 del self.locos[i] 62 return True 63 return False
27class ConsistLoco(BaseModel): 28 """One member of a consist. Individual member locomotives may still 29 have long addresses — only the *consist*'s own address is 30 restricted to short 1..127.""" 31 32 address: int = Field(ge=1, le=10239) 33 long_address: bool = False 34 direction_normal: bool = True 35 # Position is the index within the consist; first added = 0. 36 position: int = Field(ge=0)
One member of a consist. Individual member locomotives may still have long addresses — only the consist's own address is restricted to short 1..127.
39class Consist(BaseModel): 40 """An ordered group of locomotives. 41 42 The "consist address" identifies the group on the bus. For advanced 43 (CV19) consists this is the active short address shared across locos; 44 for command-station consists it's a slot/handle the command station 45 assigns; for software consists it's the bookkeeping key. All three 46 variants are held to the 1..127 short-address range for consistency 47 with the CV19 wire limit. 48 """ 49 50 address: int = Field(ge=1, le=CONSIST_ADDRESS_MAX) 51 kind: ConsistKind = "advanced" 52 locos: list[ConsistLoco] = Field(default_factory=list) 53 comment: str = "" 54 55 def add(self, loco: ConsistLoco) -> None: 56 self.locos.append(loco) 57 58 def remove(self, address: int) -> bool: 59 """Drop the loco at *address*. Returns True if found.""" 60 for i, loco in enumerate(self.locos): 61 if loco.address == address: 62 del self.locos[i] 63 return True 64 return False
An ordered group of locomotives.
The "consist address" identifies the group on the bus. For advanced (CV19) consists this is the active short address shared across locos; for command-station consists it's a slot/handle the command station assigns; for software consists it's the bookkeeping key. All three variants are held to the 1..127 short-address range for consistency with the CV19 wire limit.
58 def remove(self, address: int) -> bool: 59 """Drop the loco at *address*. Returns True if found.""" 60 for i, loco in enumerate(self.locos): 61 if loco.address == address: 62 del self.locos[i] 63 return True 64 return False
Drop the loco at address. Returns True if found.