1use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
2use snafu::{ensure_whatever, whatever, Whatever};
3use std::io::{Cursor, Read};
4
5#[derive(Debug)]
9pub struct TunnelingRequest {
10 pub communication_channel_id: u8,
11 pub sequence_nr: u8,
12 pub cemi: Vec<u8>,
13}
14
15impl TunnelingRequest {
16 pub fn new(communication_channel_id: u8, sequence_nr: u8, cemi: Vec<u8>) -> Self {
17 Self {
18 communication_channel_id,
19 sequence_nr,
20 cemi,
21 }
22 }
23
24 pub fn get_cemi(&self) -> &Vec<u8> {
25 &self.cemi
26 }
27
28 pub fn packet(&self) -> Vec<u8> {
29 let mut packet = vec![0x06, 0x10, 0x04, 0x20];
30 packet.write_u16::<BigEndian>(10 + self.cemi.len() as u16).unwrap();
31 packet.write_u8(4).unwrap();
32 packet.write_u8(self.communication_channel_id).unwrap();
33 packet.write_u8(self.sequence_nr).unwrap();
34 packet.write_u8(0).unwrap();
35 packet.extend(&self.cemi);
36 packet
37 }
38
39 pub fn from_packet(packet_reader: &mut Cursor<&[u8]>) -> Result<Self, Whatever> {
40 verify_header(packet_reader)?;
41
42 match packet_reader.read_u16::<BigEndian>() {
43 Ok(code) => {
44 ensure_whatever!(code == 0x0420, "Code should be 0x0420 instead of {:0x?}", code);
45 }
46 Err(e) => whatever!("Unable to read code {:?}", e),
47 };
48
49 let size = match packet_reader.read_u16::<BigEndian>() {
50 Ok(size) => size,
51 Err(e) => whatever!("Unable to read packet size {:?}", e),
52 };
53
54 match packet_reader.read_u8() {
55 Ok(size) => {
56 ensure_whatever!(size == 0x04, "Size should be 0x04 instead of {}", size);
57 }
58 Err(e) => whatever!("Unable to read message code {:?}", e),
59 };
60
61 let communication_channel_id = match packet_reader.read_u8() {
62 Ok(id) => id,
63 Err(e) => whatever!("Unable to read communication channel id {:?}", e),
64 };
65
66 let sequence_nr = match packet_reader.read_u8() {
67 Ok(sequence_nr) => sequence_nr,
68 Err(e) => whatever!("Unable to read sequence number {:?}", e),
69 };
70
71 match packet_reader.read_u8() {
72 Ok(_) => (),
73 Err(e) => whatever!("Unable to read padding {:?}", e),
74 };
75
76 let mut cemi = vec![0; size as usize - 10];
77 if let Err(e) = packet_reader.read(&mut cemi) {
78 whatever!("Unable to read cemi part {:?}", e);
79 }
80
81 Ok(Self {
82 communication_channel_id,
83 sequence_nr,
84 cemi,
85 })
86 }
87}
88
89#[derive(Debug)]
93pub struct TunnelingAck {
94 pub communication_channel_id: u8,
95 pub sequence_nr: u8,
96 pub status: u8,
97}
98
99impl TunnelingAck {
100 pub fn new(communication_channel_id: u8, sequence_nr: u8, status: u8) -> Self {
101 Self {
102 communication_channel_id,
103 sequence_nr,
104 status,
105 }
106 }
107
108 pub fn packet(&self) -> Vec<u8> {
109 let mut packet = vec![0x06, 0x10, 0x04, 0x21, 0, 0x0a];
110 packet.write_u8(4).unwrap();
111 packet.write_u8(self.communication_channel_id).unwrap();
112 packet.write_u8(self.sequence_nr).unwrap();
113 packet.write_u8(self.status).unwrap();
114 packet
115 }
116
117 pub fn from_packet(packet_reader: &mut Cursor<&[u8]>) -> Result<Self, Whatever> {
118 verify_header(packet_reader)?;
119
120 match packet_reader.read_u16::<BigEndian>() {
121 Ok(code) => ensure_whatever!(code == 0x0421, "Response code should be 0x0421 instead of {:0x?}", code),
122 Err(e) => whatever!("Unable to read response code {:?}", e),
123 }
124
125 match packet_reader.read_u16::<BigEndian>() {
126 Ok(size) => ensure_whatever!(size == 0x0a, "Packet size should be 0x0a instead of {:0x?}", size),
127 Err(e) => whatever!("Unable to read packet size {:?}", e),
128 }
129
130 match packet_reader.read_u8() {
131 Ok(struct_size) => ensure_whatever!(struct_size == 0x04, "Structure size should be 0x04 instead of {:0x?}", struct_size),
132 Err(e) => whatever!("Unable to read struct size {:?}", e),
133 }
134
135 let communication_channel_id = match packet_reader.read_u8() {
136 Ok(id) => id,
137 Err(e) => whatever!("Unable to read communication channel id {:?}", e),
138 };
139
140 let sequence_nr = match packet_reader.read_u8() {
141 Ok(nr) => nr,
142 Err(e) => whatever!("Unable to read communication channel id {:?}", e),
143 };
144
145 let status = match packet_reader.read_u8() {
146 Ok(status) => status,
147 Err(e) => whatever!("Unable to read status {:?}", e),
148 };
149
150 Ok(Self {
151 communication_channel_id,
152 sequence_nr,
153 status,
154 })
155 }
156}
157
158#[derive(Copy, Clone, Debug)]
159#[repr(u8)]
160pub enum KnxIpFeature {
161 MaskVersion = 0x02,
162 IndividualAddress = 0x06,
163 MaxApduLength = 0x07,
164 InfoServiceEnable = 0x08,
165}
166
167#[derive(Debug)]
168pub struct FeatureSet {
169 feature: KnxIpFeature,
170 value: u8,
171 pub communication_channel_id: u8,
172 pub sequence_nr: u8,
173}
174
175impl FeatureSet {
176 pub fn new(communication_channel_id: u8, sequence_nr: u8, feature: KnxIpFeature, value: u8) -> Self {
177 Self {
178 communication_channel_id,
179 sequence_nr,
180 feature,
181 value,
182 }
183 }
184
185 pub fn packet(&self) -> Vec<u8> {
186 let mut packet = vec![0x06, 0x10, 0x04, 0x24, 0, 0x0d];
187 packet.write_u8(4).unwrap();
188 packet.write_u8(self.communication_channel_id).unwrap();
189 packet.write_u8(self.sequence_nr).unwrap();
190 packet.write_u8(0).unwrap();
191 packet.write_u8(self.feature as u8).unwrap();
192 packet.write_u8(0).unwrap();
193 packet.write_u8(self.value).unwrap();
194 packet
195 }
196}
197
198#[derive(Debug)]
199pub struct FeatureResp {
200 pub feature: KnxIpFeature,
201 pub value: u8,
202 pub status: u8,
203 pub communication_channel_id: u8,
204 pub sequence_nr: u8,
205}
206
207impl FeatureResp {
208 pub fn packet(&self) -> Vec<u8> {
209 let mut packet = vec![0x06, 0x10, 0x04, 0x24, 0, 0x0d];
210 packet.write_u8(4).unwrap();
211 packet.write_u8(self.communication_channel_id).unwrap();
212 packet.write_u8(self.sequence_nr).unwrap();
213 packet.write_u8(0).unwrap();
214 packet.write_u8(self.feature as u8).unwrap();
215 packet.write_u8(0).unwrap();
216 packet.write_u8(self.value).unwrap();
217 packet
218 }
219
220 pub fn from_packet(packet_reader: &mut Cursor<&[u8]>) -> Result<Self, Whatever> {
221 verify_header(packet_reader)?;
222
223 match packet_reader.read_u16::<BigEndian>() {
224 Ok(code) => ensure_whatever!(code == 0x0423, "Response code should be 0x0423 instead of {:0x?}", code),
225 Err(e) => whatever!("Unable to read response code {:?}", e),
226 }
227
228 match packet_reader.read_u16::<BigEndian>() {
229 Ok(size) => ensure_whatever!(size == 0x0d, "Packet size should be 0x0d instead of {:0x?}", size),
230 Err(e) => whatever!("Unable to read packet size {:?}", e),
231 }
232
233 match packet_reader.read_u8() {
234 Ok(struct_size) => ensure_whatever!(struct_size == 0x04, "Structure size should be 0x04 instead of {:0x?}", struct_size),
235 Err(e) => whatever!("Unable to read struct size {:?}", e),
236 }
237
238 let communication_channel_id = match packet_reader.read_u8() {
239 Ok(id) => id,
240 Err(e) => whatever!("Unable to read communication channel id {:?}", e),
241 };
242
243 let sequence_nr = match packet_reader.read_u8() {
244 Ok(nr) => nr,
245 Err(e) => whatever!("Unable to read communication channel id {:?}", e),
246 };
247
248 match packet_reader.read_u8() {
249 Ok(_) => (),
250 Err(e) => whatever!("Unable to read reserved field {:?}", e),
251 };
252
253 let feature: KnxIpFeature = match packet_reader.read_u8() {
254 Ok(feature) => feature.try_into()?,
255 Err(e) => whatever!("Unable to read status {:?}", e),
256 };
257
258 let status = match packet_reader.read_u8() {
259 Ok(status) => status,
260 Err(e) => whatever!("Unable to read status {:?}", e),
261 };
262
263 let value = match packet_reader.read_u8() {
264 Ok(value) => value,
265 Err(e) => whatever!("Unable to read value {:?}", e),
266 };
267
268 Ok(Self {
269 communication_channel_id,
270 sequence_nr,
271 status,
272 feature,
273 value,
274 })
275 }
276}
277
278fn verify_header(packet_reader: &mut Cursor<&[u8]>) -> Result<(), Whatever> {
279 match packet_reader.read_u8() {
280 Ok(size) => ensure_whatever!(size == 6, "Header size should be 6 instead of {}", size),
281 Err(_e) => whatever!("Unable to read header size"),
282 };
283
284 match packet_reader.read_u8() {
285 Ok(version) => ensure_whatever!(version == 0x10, "Version should be 0x10 instead of {:0x?}", version),
286 Err(_e) => whatever!("Unable to read header version"),
287 };
288
289 Ok(())
290}
291
292impl TryFrom<u8> for KnxIpFeature {
293 type Error = Whatever;
294
295 fn try_from(v: u8) -> Result<Self, Self::Error> {
296 match v {
297 x if x == KnxIpFeature::MaskVersion as u8 => Ok(KnxIpFeature::MaskVersion),
298 x if x == KnxIpFeature::IndividualAddress as u8 => Ok(KnxIpFeature::IndividualAddress),
299 x if x == KnxIpFeature::MaxApduLength as u8 => Ok(KnxIpFeature::MaxApduLength),
300 x if x == KnxIpFeature::InfoServiceEnable as u8 => Ok(KnxIpFeature::InfoServiceEnable),
301 _ => whatever!("Unknown KNXIP feature {:?}", v),
302 }
303 }
304}