lotus_extra/messages/
pis.rs

1use std::{fmt, time::Duration};
2
3use lotus_script::{content::ContentId, prelude::message_type};
4use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
7pub struct TerminusText([String; 2]);
8
9impl From<[String; 2]> for TerminusText {
10    fn from(val: [String; 2]) -> Self {
11        TerminusText(val)
12    }
13}
14
15impl TerminusText {
16    pub fn new(line_1: impl Into<String>, line_2: impl Into<String>) -> Self {
17        TerminusText([line_1.into(), line_2.into()])
18    }
19    pub fn new_empty() -> Self {
20        TerminusText(["".to_string(), "".to_string()])
21    }
22    pub fn is_multiline(&self) -> bool {
23        !self.0[1].is_empty()
24    }
25    pub fn line_1(&self) -> String {
26        self.0[0].clone()
27    }
28    pub fn line_2(&self) -> String {
29        self.0[1].clone()
30    }
31    pub fn is_empty(&self) -> bool {
32        self.0[0].is_empty() && self.0[1].is_empty()
33    }
34}
35
36//-----------------------------
37// Lotus Messages
38//-----------------------------
39
40//===========================================================
41
42/// Current line number & specialchar (entered by hand, or by line/route default)
43/// Mandatory
44///
45/// The special character 0 corresponds to ‘no special character’.
46/// Due to the data type u32, negative values are not possible.
47#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
48pub struct LineSpecialchar {
49    pub line: u32,
50    pub specialchar: u32,
51}
52
53message_type!(LineSpecialchar, "Std_Pis", "LineSpecialchar", "TrainBus");
54
55//-----------------------------
56
57///A new parameter in the standard is the course number. This comes from Julian's `Wagenbus`
58/// and the VDV-300 script. It can be used to control digital course display modules,
59/// for example. If no course is used, this message does not need to be sent.
60/// Otherwise, however, it is a mandatory message. Here, the value 0 corresponds to ‘no course’, too.
61#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
62pub struct Course {
63    pub value: u32,
64}
65
66message_type!(Course, "Std_Pis", "Course", "TrainBus");
67
68//-----------------------------
69
70///Here we have the first change in content compared to the previous solution.
71/// In the old system, `ROUTE_LISTINDEX` is transferred here. In the future, however,
72/// we want to transfer the route number entered (NOT the ListIndex). A breakdown
73/// into the ListIndex would then take place in the module. This message is also a mandatory message.
74/// Route 0 corresponds to ‘no route’.
75#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
76pub struct Route {
77    pub value: u32,
78}
79
80message_type!(Route, "Std_Pis", "Route", "TrainBus");
81
82//-----------------------------
83
84///Here we have another major change. The message `TERMINUS_LISTINDEX` from the old system
85/// is hereby replaced and expanded. As it is possible in modern IBIS devices and vehicles,
86/// we want to offer the option of overwriting the display text with free text
87/// (or with text from special FIS files). This is made possible by the `Option<TerminusText>`,
88/// both for overwriting front displays and for side displays.
89/// In addition, the destination code (NOT the ListIndex) is transferred.
90/// This always applies when no overwriting destination text is transferred and is generally
91/// considered a valid destination for AI passengers (more on this below).
92///
93/// In principle, the transmission of the destination code is a mandatory message,
94/// but the use of override texts is optional.
95/// However, since the transmission of destination texts originates from the VDV 300 font,
96/// displays should support it.
97#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
98pub struct Terminus {
99    pub code: u32,
100    pub override_front: Option<TerminusText>,
101    pub override_side: Option<TerminusText>,
102}
103
104message_type!(Terminus, "Std_Pis", "Terminus", "TrainBus");
105
106//-----------------------------
107
108///In the old Lotus, `LINE` and `ROUTE` were used for the information that the vehicle sent to the route balises.
109/// The vehicle then sent these values to the ITCS server.
110/// In the future, we want to reduce this to a kind of train control number.
111/// Nothing will change for conventional IBIS devices for the time being.
112/// Together with a planned additional text field in the FIS file, these train control numbers
113/// should be adjustable per line and route.
114/// This will also allow alternative train control devices to be supported and
115/// direction-based traffic light requests to be achieved in the future.
116/// (However, this is still a long way off and is more of a preliminary step at this stage.)
117/// This is a mandatory message. Ultimately, however, the vehicle must also decide
118/// whether it supports this type of request at all.
119#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
120pub struct RoutingCode {
121    pub value: u32,
122}
123
124message_type!(RoutingCode, "Std_Pis", "RoutingCode", "TrainBus");
125
126//-----------------------------
127
128///We would like to offer an alternative to labelling simple internal displays.
129/// In the VDV-300 font, these simple internal displays are supplied directly with text from IBIS.
130/// For this reason, we wanted to use this option as well.
131/// The ‘script logic’ for simple internal displays is thus transferred to the IBIS device,
132/// and the displays themselves only show the text transmitted to them.
133/// The IBIS device must determine this display text.
134///
135///More complex interior displays (such as monitors) are explicitly not controlled by this.
136/// These continue to form their content from the other available information.
137#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
138pub struct StopText {
139    pub value: TerminusText,
140}
141
142message_type!(StopText, "Std_Pis", "StopText", "TrainBus");
143
144//-----------------------------
145
146///Here we replace the previous message `STOP_SEQ`.
147/// The index of the current stop on a route is passed as an option on a 0-based scale.
148/// If no route is set, the value is `NONE`. Once a route is set, `SOME(u32)` corresponds to the index.
149/// This message is again a mandatory message.
150#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
151pub struct StopIndex {
152    pub value: Option<u32>,
153}
154
155message_type!(StopIndex, "Std_Pis", "StopIndex", "TrainBus");
156
157//-----------------------------
158
159///As an optional message, we would like to add parameters for validator modules
160/// (it is now called ‘validator’ here, but the values can also be used by all other modules).
161///
162/// * The value `zone` corresponds to the fare zone (or honeycomb, depending on the local requirements
163///   of the transport company). If the validators are not available
164///   (e.g. if no fare zone is set or if the validators are locked in raid mode),
165///   `NONE` is transmitted; otherwise, a fare zone is specified as `SOME(u32)`.
166///
167/// * The value `stop_index` works like the `StopIndex` from the previous section.
168///   Since certain IBIS devices only increment the StopIndex for the validators when the doors were open,
169///   there may be deviations from the `stop_index` in the previous section.
170#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
171pub struct Validator {
172    pub zone: Option<u32>,
173    pub stop_index: Option<u32>,
174}
175
176message_type!(Validator, "Std_Pis", "Validator", "TrainBus");
177
178//-----------------------------
179
180///It is possible to transfer a timestamp both in Julian 's ‘Wagenbus’ and in the VDV-300 document.
181/// For the sake of simplicity, let us assume that the modules use the simulation time directly.
182/// To enable the ‘system time’ to be adjusted on the IBIS device, we want to make this possible
183/// through this message. A duration is sent. This represents the offset to the simulation time.
184/// This offers the advantage that the information in question only needs to be transferred once
185/// when it changes and can be directly offset against the time stamp of the situation.
186/// (Simulation time + duration = changed IBIS system time).
187/// This message is, of course, completely optional for sending,
188/// just as such a feature is not available in every IBIS.
189#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
190pub struct TimeDelta {
191    pub value: Duration,
192}
193
194message_type!(TimeDelta, "Std_Pis", "TimeDelta", "TrainBus");
195
196//-----------------------------
197
198///This section should still be treated with caution, because, as mentioned in the introduction,
199/// there is no interface to the FIS file yet. Playing ID-based sounds is also not yet available.
200/// So there may still be some changes here.
201///
202///In general, we want to use this message to replace several old messages:
203/// `ANNOUNCE_USERID`, `ANNOUNCE_SUBID` and `ANNOUNCE_GLUED`. A ContentId corresponds to a
204/// Lotus structure and directly bundles the user ID and sub-ID.
205/// A list of content IDs is transferred. I cannot explain any more about this at this stage because,
206/// as I said, the corresponding interfaces do not yet exist.
207///
208/// The transmission of announcements is, of course, also optional.
209/// Announcements only need to be transmitted if they are available and the
210/// IBIS device supports this function. Similarly, a vehicle only needs to be able to
211/// evaluate and play them if it has the appropriate functions.
212#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
213pub struct Announcement {
214    pub value: Vec<ContentId>,
215}
216
217message_type!(Announcement, "Std_Pis", "Announcement", "TrainBus");
218
219//-----------------------------
220
221///Until now, switch requests have been transmitted from IBIS to the vehicle using `SWITCH`.
222/// We want to make two changes here. Firstly, all components (including the vehicle itself)
223/// should send information about whether a switch command is currently pending
224/// (there are IBIS devices, for example, that can also display switch commands from the
225/// vehicle with switch buttons). The second change is that each module/vehicle itself
226/// checks the conditions for transmitting the command.
227/// If a setting command is to be sent from the IBIS for 100 meters when a button is pressed,
228/// the IBIS first sends the direction of the setting command,
229/// checks the distance travelled itself, and resets the setting command after 100 meters by
230/// transmitting RoutingDirection::Off. The decision as to which signal overwrites which
231/// (e.g. vehicle overwrites IBIS) is still made in the vehicle when the command is transmitted.
232/// This message is optional and only needs to be sent.
233#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize, PartialEq)]
234pub enum RoutingDirection {
235    Left,
236    Right,
237    Straight,
238    #[default]
239    Off,
240}
241
242impl fmt::Display for RoutingDirection {
243    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244        match *self {
245            RoutingDirection::Left => write!(f, "Left"),
246            RoutingDirection::Right => write!(f, "Right"),
247            RoutingDirection::Straight => write!(f, "Straight"),
248            RoutingDirection::Off => write!(f, "Off"),
249        }
250    }
251}
252
253message_type!(RoutingDirection, "Std_Pis", "RoutingDirection", "TrainBus");
254
255//-----------------------------
256
257///This message is currently more of a glimpse into the future.
258/// LOTUS does not yet support manual requests. It currently serves only as a preliminary service.
259#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
260pub struct RoutingRequest {}
261
262message_type!(RoutingRequest, "Std_Pis", "RoutingRequest", "TrainBus");
263
264//===========================================================
265
266/// This is intended to inform the vehicle which destination code they are currently
267/// displaying (or None, if no destination is displayed). In a sense, this is a
268/// preliminary service for the AI passengers. As is known from the old system,
269/// the AI passengers respond to the destination code set in RC_PIS_Terminus.
270/// Until now, this value has only been provided by IBIS.
271///
272///This preliminary work also makes things possible, such as distinguishing between AI people getting on
273/// and AI people getting off. For example, in the case of school transport,
274/// passengers should only get on the way to school and only get off when they reach
275/// the school. In addition, this system also provides better support for plug-in signs
276/// (whether in the vehicle or as a module). It also allows displays to individually specify
277/// ‘when’ they are finished with signs.
278///
279///Using the transmitter's module slot, a vehicle can then clearly recognise
280/// which module slot and thus which type of module the information came from.
281///
282///As a precise link to the AI is still pending (due to the lack of AI), I would like to
283/// leave this point half open for now.
284#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
285pub struct NowDisplaying {
286    pub code: Option<u32>,
287}
288
289message_type!(NowDisplaying, "Std_Pis", "Displaying");