irox_nmea0183/input/
ratectrl.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3
4use irox_bits::{Error, ErrorKind};
5use irox_tools::packetio::Packet;
6
7use crate::MessageType;
8
9#[derive(Debug, Copy, Clone, PartialEq)]
10pub enum ControlCommand {
11    SetRate,
12    QueryOnce,
13    ABPOn,
14    ABPOff,
15    ReverseEEOn,
16    ReverseEEOff,
17    NavOn5hz,
18    NavOff5hz,
19    SBASRangingOn,
20    SBASRangingOff,
21    FTSOn,
22    FTSOff,
23}
24
25#[derive(Debug, Clone, PartialEq)]
26pub struct RateControlRF103 {
27    pub msg: MessageType,
28    pub command: ControlCommand,
29    pub rate_seconds: u8,
30    pub cksum_enable: bool,
31}
32
33impl RateControlRF103 {
34    pub fn set_rate(msg: MessageType, rate_seconds: u8) -> RateControlRF103 {
35        RateControlRF103 {
36            msg,
37            rate_seconds,
38            command: ControlCommand::SetRate,
39            cksum_enable: true,
40        }
41    }
42    pub fn enable_abp(enabled: bool) -> RateControlRF103 {
43        let command = match enabled {
44            true => ControlCommand::ABPOn,
45            false => ControlCommand::ABPOff,
46        };
47        RateControlRF103 {
48            msg: MessageType::GGA,
49            rate_seconds: 0,
50            cksum_enable: true,
51            command,
52        }
53    }
54    pub fn enable_reverseee(enabled: bool) -> RateControlRF103 {
55        let command = match enabled {
56            true => ControlCommand::ReverseEEOn,
57            false => ControlCommand::ReverseEEOff,
58        };
59        RateControlRF103 {
60            msg: MessageType::GGA,
61            rate_seconds: 0,
62            cksum_enable: true,
63            command,
64        }
65    }
66    pub fn enable_5hz_nav(enabled: bool) -> RateControlRF103 {
67        let command = match enabled {
68            true => ControlCommand::NavOn5hz,
69            false => ControlCommand::NavOff5hz,
70        };
71        RateControlRF103 {
72            msg: MessageType::GGA,
73            rate_seconds: 0,
74            cksum_enable: true,
75            command,
76        }
77    }
78    pub fn enable_sbas_ranging(enabled: bool) -> RateControlRF103 {
79        let command = match enabled {
80            true => ControlCommand::SBASRangingOn,
81            false => ControlCommand::SBASRangingOff,
82        };
83        RateControlRF103 {
84            msg: MessageType::GGA,
85            rate_seconds: 0,
86            cksum_enable: true,
87            command,
88        }
89    }
90    pub fn enable_fts(enabled: bool) -> RateControlRF103 {
91        let command = match enabled {
92            true => ControlCommand::FTSOn,
93            false => ControlCommand::FTSOff,
94        };
95        RateControlRF103 {
96            msg: MessageType::GGA,
97            rate_seconds: 0,
98            cksum_enable: true,
99            command,
100        }
101    }
102}
103
104impl Packet for RateControlRF103 {
105    type PacketType = MessageType;
106
107    fn get_bytes(&self) -> Result<Vec<u8>, Error> {
108        let msg = match self.msg {
109            MessageType::GGA => 0,
110            MessageType::GLL => 1,
111            MessageType::GSA => 2,
112            MessageType::GSV => 3,
113            MessageType::RMC => 4,
114            MessageType::VTG => 5,
115            MessageType::MSS => 6,
116            MessageType::ZDA => 8,
117            _ => return Err(ErrorKind::InvalidInput.into()),
118        };
119        let cmd = match self.command {
120            ControlCommand::SetRate => 0,
121            ControlCommand::QueryOnce => 1,
122            ControlCommand::ABPOn => 2,
123            ControlCommand::ABPOff => 3,
124            ControlCommand::ReverseEEOn => 4,
125            ControlCommand::ReverseEEOff => 5,
126            ControlCommand::NavOn5hz => 6,
127            ControlCommand::NavOff5hz => 7,
128            ControlCommand::SBASRangingOn => 8,
129            ControlCommand::SBASRangingOff => 9,
130            ControlCommand::FTSOn => 10,
131            ControlCommand::FTSOff => 11,
132        };
133        let cksum = match self.cksum_enable {
134            true => 1,
135            false => 0,
136        };
137        let out = format!(
138            "$PSRF103,{:02},{:02},{:02},{:02}*",
139            msg, cmd, self.rate_seconds, cksum
140        );
141        let cksum = crate::calculate_checksum(&out);
142        Ok(Vec::from(format!("{out}{cksum:02X}\r\n")))
143    }
144
145    fn get_type(&self) -> Self::PacketType {
146        MessageType::SRF103
147    }
148}
149
150#[cfg(test)]
151mod test {
152    use irox_tools::packetio::Packet;
153
154    use crate::input::ratectrl::{ControlCommand, RateControlRF103};
155    use crate::MessageType;
156
157    #[test]
158    fn test() {
159        let exp = "$PSRF103,00,01,00,01*25\r\n";
160        let pkt = RateControlRF103 {
161            msg: MessageType::GGA,
162            command: ControlCommand::QueryOnce,
163            rate_seconds: 0,
164            cksum_enable: true,
165        };
166
167        let buf = pkt.get_bytes().unwrap();
168        assert_eq!(buf, exp.as_bytes());
169    }
170}