1use std::{convert::TryFrom, fmt};
2
3use crate::error::*;
4use crate::frame::*;
5
6#[derive(Copy, Clone, Debug, PartialEq)]
10pub enum Command {
11 On,
14
15 OnFast,
19
20 Off,
23
24 OffFast,
28
29 Ping,
31
32 VersionQuery,
34
35 CancelLinking,
37
38 StartLinking,
40
41 StatusRequest,
43
44 Beep,
46
47 Other(u8),
49
50 None,
51}
52
53impl Default for Command {
54 fn default() -> Self {
55 Command::None
56 }
57}
58
59impl fmt::Display for Command {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 write!(f, "{:?}", self)
62 }
63}
64
65impl From<u8> for Command {
66 fn from(b: u8) -> Self {
67 use Command::*;
68 match b {
69 0x08u8 => CancelLinking,
70 0x09u8 => StartLinking,
71 0x0du8 => VersionQuery,
72 0x0fu8 => Ping,
73 0x19u8 => StatusRequest,
74 0x11u8 => On,
75 0x12u8 => OnFast,
76 0x13u8 => Off,
77 0x14u8 => OffFast,
78 0x30u8 => Beep,
79 0 => None,
80 _ => Other(b),
81 }
82 }
83}
84
85impl From<Command> for u8 {
86 fn from(c: Command) -> Self {
87 use Command::*;
88 match c {
89 On => 0x11u8,
90 OnFast => 0x12u8,
91 Off => 0x13u8,
92 OffFast => 0x14u8,
93 Ping => 0x0fu8,
94 VersionQuery => 0x0du8,
95 CancelLinking => 0x08u8,
96 StartLinking => 0x09u8,
97 StatusRequest => 0x19u8,
98 Beep => 0x30u8,
99 Other(cmd) => cmd,
100 None => 0u8,
101 }
102 }
103}
104
105#[derive(Copy, Clone, Debug, PartialEq)]
107pub struct Message {
108 pub from: Address,
110
111 pub to: Address,
113
114 pub flags: MessageFlags,
116
117 pub hops_remaining: u8,
119
120 pub max_hops: u8,
122
123 pub cmd1: Command,
125
126 pub cmd2: Command,
129
130 pub data: [u8; 14],
132}
133
134impl Message {
135 pub fn is_ack(&self, other: &Message) -> bool {
137 match *other {
138 Message { from, flags, .. } if self.to == from && flags.contains(MessageFlags::ACK) => {
139 true
140 }
141 _ => false,
142 }
143 }
144}
145
146impl Default for Message {
147 fn default() -> Self {
148 Message {
149 from: Address::default(),
150 to: Address::default(),
151 flags: MessageFlags::default(),
152 hops_remaining: 3,
153 max_hops: 3,
154 cmd1: Command::default(),
155 cmd2: Command::default(),
156 data: [0u8; 14],
157 }
158 }
159}
160
161impl From<(Address, Command)> for Message {
162 fn from(c: (Address, Command)) -> Self {
163 let mut msg = Message::default();
164 let (to, cmd1) = c;
165 msg.to = to;
166 msg.cmd1 = cmd1;
167 msg
168 }
169}
170
171impl From<(Address, Command, Command)> for Message {
172 fn from(c: (Address, Command, Command)) -> Self {
173 let mut msg = Message::default();
174 let (to, cmd1, cmd2) = c;
175 msg.to = to;
176 msg.cmd1 = cmd1;
177 msg.cmd2 = cmd2;
178 msg
179 }
180}
181
182impl From<(Address, Command, MessageFlags)> for Message {
183 fn from(c: (Address, Command, MessageFlags)) -> Self {
184 let mut msg = Message::default();
185 let (to, cmd1, flags) = c;
186 msg.to = to;
187 msg.cmd1 = cmd1;
188 msg.flags = flags;
189 msg
190 }
191}
192
193impl From<(Address, Command, Command, MessageFlags)> for Message {
194 fn from(c: (Address, Command, Command, MessageFlags)) -> Self {
195 let mut msg = Message::default();
196 let (to, cmd1, cmd2, flags) = c;
197 msg.to = to;
198 msg.cmd1 = cmd1;
199 msg.cmd2 = cmd2;
200 msg.flags = flags;
201 msg
202 }
203}
204
205impl TryFrom<Frame> for Message {
206 type Error = Error;
207
208 fn try_from(frame: Frame) -> Result<Self, Self::Error> {
209 match frame {
210 Frame::StandardInsteonReceive {
211 from,
212 to,
213 flags,
214 hops_remaining,
215 max_hops,
216 cmd1,
217 cmd2,
218 } => Ok(Message {
219 from,
220 to,
221 flags,
222 hops_remaining,
223 max_hops,
224 cmd1: cmd1.into(),
225 cmd2: cmd2.into(),
226 data: [0u8; 14],
227 }),
228 Frame::ExtendedInsteonReceive {
229 from,
230 to,
231 flags,
232 hops_remaining,
233 max_hops,
234 cmd1,
235 cmd2,
236 data,
237 } => Ok(Message {
238 from,
239 to,
240 flags,
241 hops_remaining,
242 max_hops,
243 cmd1: cmd1.into(),
244 cmd2: cmd2.into(),
245 data,
246 }),
247 _ => Err(Error::UnexpectedResponse),
248 }
249 }
250}