rust_powered_lego/lego/
message_parameters.rs

1// Long list of structs representing each command / message + valid values of its parameters
2// Simple command is transfered as is. Complicated command needs encoding.
3// See message_types for list of these commands / messages.
4
5use crate::lego::consts::{
6    EndState, 
7    Profile
8};
9
10use super::message_types::SubcommandType;
11
12
13// The communicator is expected to send command as [u8]
14// Since each command has different way of definition and payload,
15// this trait aims to standardized the serialization process.
16pub trait Serialized {
17    fn serialize(&self) -> Vec<u8>;
18}
19
20/***************************************/
21/************ HubProperties ************/
22/***************************************/
23
24pub struct HubPropertiesParams { 
25    pub property:           HubPropertiesProperties,
26    pub operation:          HubPropertiesOperations,
27}
28
29#[derive(Clone, Copy)]
30#[repr(u8)]
31pub enum HubPropertiesProperties {
32    AdvertisingName                 = 0x01, // Advertising Name
33    Button                          = 0x02,	// Button
34    FWVersion                       = 0x03,	// FW Version
35    HWVersion                       = 0x04,	// HW Version
36    RSSI                            = 0x05,	// RSSI
37    BatteryVoltage                  = 0x06,	// Battery Voltage
38    BatteryType                     = 0x07,	// Battery Type
39    ManufacturerName                = 0x08,	// Manufacturer Name
40    RadioFirmwareVersion            = 0x09,	// Radio Firmware Version
41    LEGOWirelessProtocolVersion     = 0x0A,	// LEGO Wireless Protocol Version
42    SystemTypeID                    = 0x0B,	// System Type ID
43    HWNetworkID                     = 0x0C,	// H/W Network ID
44    PrimaryMACAddress               = 0x0D,	// Primary MAC Address
45    SecondaryMACAddress             = 0x0E,	// Secondary MAC Address
46    HardwareNetworkFamily           = 0x0F,	// Hardware Network Family
47}
48
49#[derive(Clone, Copy)]
50#[repr(u8)]
51pub enum HubPropertiesOperations {
52    Set             = 0x01, // Set              (Downstream)
53    EnableUpdates   = 0x02, // Enable Updates   (Downstream)
54    DisableUpdates  = 0x03, // Disable Updates  (Downstream)
55    Reset           = 0x04, // Reset            (Downstream)
56    RequestUpdate   = 0x05, // Request Update   (Downstream)
57    Update          = 0x06, // Update           (Upstream)
58}
59
60impl Serialized for HubPropertiesParams {
61    fn serialize(&self) -> Vec<u8> {
62        vec![self.property as u8, self.operation as u8]
63    }
64}
65
66
67/***************************************/
68/************* HubActions **************/
69/***************************************/
70
71pub struct HubActionsParams {
72    pub action_type:        HubActionsTypes,
73}
74
75#[derive(Clone, Copy)]
76pub enum HubActionsTypes {
77    SwitchOffHub            = 0x01, // Switch Off Hub
78    Disconnect              = 0x02,	// Disconnect
79    VCCPortControlOn        = 0x03,	// VCC Port Control On
80    VCCPortControlOff       = 0x04,	// VCC Port Control Off
81    ActivateBUSYIndication  = 0x05,	// Activate BUSY Indication (Shown byRGB. Actual RGB settings preserved).
82    ResetBUSYIndication     = 0x06,	// Reset BUSY Indication (RGB shows the previously preserve RGB settings).
83    Shutdown                = 0x2f,	// Shutdown the Hub without any up-stream information send. Used for fast power down in production. Suggested for PRODUCTION USE ONLY!
84
85    /* Only Upstream */
86    HubWillSwitchOff        = 0x30, // Hub Will Switch Off
87    HubWillDisconnect       = 0x31,	// Hub Will Disconnect
88    HubWillGoIntoBootMode   = 0x32,	// Hub Will Go Into Boot Mode
89}
90
91impl Serialized for HubActionsParams {
92    fn serialize(&self) -> Vec<u8> {
93        vec![self.action_type as u8]
94    }
95}
96
97
98
99/***************************************/
100/******* PortInformationRequest ********/
101/***************************************/
102
103pub struct PortInformationRequestParams {
104    pub port_id:            u8,
105    pub information_type:   PortInformationType,
106}
107
108#[derive(Clone, Copy)]
109pub enum PortInformationType {
110    PortValue                   = 0x00, // Port Value
111    ModeInfo                    = 0x01, // Mode Info
112    PossibleModeCombinations    = 0x02, //Possible Mode Combinations. Should only be used if the “Logical Combinable”-bit is set in the (MODE INFO Capabilities byte). I.e. in the Port Information 0x43
113}
114
115impl Serialized for PortInformationRequestParams {
116    fn serialize(&self) -> Vec<u8> {
117        vec![self.port_id, self.information_type as u8]
118    }
119}
120
121
122/***************************************/
123/***** PortModeInformationRequest ******/
124/***************************************/
125
126pub struct PortModeInformationRequestParams {
127    pub port_id:            u8,
128    pub mode_id:            u8,
129    pub information_type:   PortModeInformationType,
130}
131
132#[derive(Clone, Copy)]
133pub enum PortModeInformationType {
134    Name            = 0x00,    // NAME	                                Name of the mode
135    Raw             = 0x01,    // RAW	                                The raw range
136    Pct             = 0x02,    // PCT	                                The percent range
137    Si              = 0x03,    // SI	                                The SI value range
138    Symbol          = 0x04,    // SYMBOL	                            The standard name of value
139    Mapping         = 0x05,    // MAPPING	 
140    Internal        = 0x06,    // Used internally
141    MotorBias       = 0x07,    // Motor Bias (0-100%)
142    CapabilityBits  = 0x08,    // Capability bits (6 bytes total)
143    ValueFormat     = 0x80,    // VALUE FORMAT	Value encoding
144}
145
146impl Serialized for PortModeInformationRequestParams {
147    fn serialize(&self) -> Vec<u8> {
148        vec![self.port_id, self.mode_id, self.information_type as u8]
149    }
150}
151
152
153/***************************************/
154/***** PortInputFormatSetupSingle ******/
155/***************************************/
156
157pub struct PortInputFormatSetupSingleParams {
158    pub port_id:                u8,
159    pub mode_id:                u8,
160    pub delta:                  u32,
161    pub enable_notifications:   bool,
162}
163
164impl Serialized for PortInputFormatSetupSingleParams {
165    fn serialize(&self) -> Vec<u8> {
166        let mut data = vec![self.port_id, self.mode_id];
167        data.append(&mut Vec::from(self.delta.to_le_bytes()));
168        data.push(if self.enable_notifications {1} else {0});
169        data
170    }
171}
172
173
174/***************************************/
175/********** PortOutputCommand **********/
176/***************************************/
177
178pub struct PortOutputCommandParams {
179    pub port_id:        u8,
180    pub start_up_info:  StartupAndCompletionInfo,
181    pub subcommand_id:  SubcommandType,
182    pub payload:        SubcommandPayload,
183}
184
185impl Serialized for PortOutputCommandParams {
186    fn serialize(&self) -> Vec<u8> {
187        let mut res = vec![self.port_id, self.start_up_info as u8, self.subcommand_id as u8];
188        res.append(self.payload.serialize().as_mut());
189        res
190    }
191}
192
193#[derive(Clone, Copy)]
194pub enum StartupAndCompletionInfo {
195    BufferAndNoAction               = 0b00000000,
196    BufferAndFeedback               = 0b00000001,
197    ExecuteImmediatelyAndNoAction   = 0b00010000,
198    ExecuteImmediatelyAndFeedback   = 0b00010001,
199}
200
201
202
203
204
205////////////////////////////////////////////////////////////////////////////////
206/******************************************************************************/
207/*************************** Subcommands Parameters ***************************/
208/*************************** Subcommands Parameters ***************************/
209/*************************** Subcommands Parameters ***************************/
210/******************************************************************************/
211////////////////////////////////////////////////////////////////////////////////
212
213
214
215pub enum SubcommandPayload {
216    SetAccTime(SetAccTimePayload),
217    SetDecTime(SetDecTimePayload),
218    StartSpeed(StartSpeedPayload),
219    StartSpeedForDegrees(StartSpeedForDegreesPayload),
220    GotoAbsolutePosition(GotoAbsolutePositionPayload),
221    WriteDirectModeData(WriteDirectModeDataPayload),
222}
223
224impl Serialized for SubcommandPayload {
225    fn serialize(&self) -> Vec<u8> {
226        match self {
227            SubcommandPayload::SetAccTime(payload) => {
228                payload.serialize()
229            },
230            SubcommandPayload::SetDecTime(payload) => {
231                payload.serialize()
232            },
233            SubcommandPayload::StartSpeed(payload) => {
234                payload.serialize()
235            },
236            SubcommandPayload::StartSpeedForDegrees(payload) => {
237                payload.serialize()
238            },
239            SubcommandPayload::GotoAbsolutePosition(payload) => {
240                payload.serialize()
241            },
242            SubcommandPayload::WriteDirectModeData(payload) => {
243                payload.serialize()
244            },
245        }
246    }
247}
248
249
250/***************************************/
251/************* SetAccTime **************/
252/***************************************/
253
254pub struct SetAccTimePayload {
255    pub time:   i16,
256}
257
258impl Serialized for SetAccTimePayload {
259    fn serialize(&self) -> Vec<u8> {
260        let mut data = Vec::from(self.time.to_le_bytes());
261        data.append(vec![
262            Profile::Acc as u8,
263        ].as_mut());
264        data
265    }
266}
267
268
269/***************************************/
270/************* SetAccTime **************/
271/***************************************/
272
273pub struct SetDecTimePayload {
274    pub time:   i16,
275}
276
277impl Serialized for SetDecTimePayload {
278    fn serialize(&self) -> Vec<u8> {
279        let mut data = Vec::from(self.time.to_le_bytes());
280        data.append(vec![
281            Profile::Dec as u8,
282        ].as_mut());
283        data
284    }
285}
286
287
288/***************************************/
289/************* StartSpeed **************/
290/***************************************/
291
292pub struct StartSpeedPayload {
293    pub speed:          i8,
294    pub max_power:      i8,
295    pub use_profile:    Profile,
296}
297
298impl Serialized for StartSpeedPayload {
299    fn serialize(&self) -> Vec<u8> {
300        vec![
301            self.speed.to_le_bytes()[0], 
302            self.max_power.to_le_bytes()[0], 
303            self.use_profile as u8
304            ]
305    }
306}
307
308
309/***************************************/
310/******** StartSpeedForDegrees *********/
311/***************************************/
312
313pub struct StartSpeedForDegreesPayload {
314    pub degrees:        i32,
315    pub speed:          i8,
316    pub max_power:      i8,
317    pub end_state:      EndState,
318    pub use_profile:    Profile,
319}
320
321impl Serialized for StartSpeedForDegreesPayload {
322    fn serialize(&self) -> Vec<u8> {
323        let mut data = Vec::from(self.degrees.to_le_bytes());
324        data.append(vec![
325            self.speed.to_le_bytes()[0],
326            self.max_power.to_le_bytes()[0],
327            (self.end_state as u8).to_le_bytes()[0],
328            self.use_profile as u8,
329        ].as_mut());
330        data
331    }
332}
333
334
335/***************************************/
336/******** GotoAbsolutePosition *********/
337/***************************************/
338
339pub struct GotoAbsolutePositionPayload {
340    pub abs_pos:        i32,        // Degrees
341    pub speed:          i8,
342    pub max_power:      i8,
343    pub end_state:      EndState,
344    pub use_profile:    Profile,
345}
346
347impl Serialized for GotoAbsolutePositionPayload {
348    fn serialize(&self) -> Vec<u8> {
349        let mut data = Vec::from(self.abs_pos.to_le_bytes());
350        data.append(vec![
351            self.speed.to_le_bytes()[0],
352            self.max_power.to_le_bytes()[0],
353            (self.end_state as u8).to_le_bytes()[0],
354            self.use_profile as u8,
355        ].as_mut());
356        data
357    }
358}
359
360
361/***************************************/
362/********* WriteDirectModeData *********/
363/***************************************/
364
365pub struct WriteDirectModeDataPayload {
366    pub mode:       u8,
367    pub payload:    WriteDirectModeDataCommands,
368}
369
370impl Serialized for WriteDirectModeDataPayload {
371    fn serialize(&self) -> Vec<u8> {
372        let mut data = vec![self.mode];
373        data.append(self.payload.serialize().as_mut());
374        data
375    }
376}
377
378pub enum WriteDirectModeDataCommands {
379    StartPower(StartPowerPayload),
380    SetAbsolutePosition(SetAbsolutePositionPayload),
381}
382
383impl Serialized for WriteDirectModeDataCommands {
384    fn serialize(&self) -> Vec<u8> {
385        match self {
386            WriteDirectModeDataCommands::StartPower(payload) => {
387                payload.serialize()
388            },
389            WriteDirectModeDataCommands::SetAbsolutePosition(payload) => {
390                payload.serialize()
391            },
392        }
393    }
394}
395
396
397/************* WriteDirectModeDataCommands *************/
398
399
400/***************************************/
401/************* StartPower **************/
402/***************************************/
403
404pub struct StartPowerPayload {
405    pub power: i8,
406}
407
408impl Serialized for StartPowerPayload {
409    fn serialize(&self) -> Vec<u8> {
410        Vec::from(self.power.to_le_bytes())
411    }
412}
413
414
415/***************************************/
416/********* SetAbsolutePosition *********/
417/***************************************/
418
419pub struct SetAbsolutePositionPayload {
420    pub position: i32,
421}
422
423impl Serialized for SetAbsolutePositionPayload {
424    fn serialize(&self) -> Vec<u8> {
425        Vec::from(self.position.to_le_bytes())
426    }
427}