1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use std::fmt;
use byteorder::BigEndian;
use byteorder::ByteOrder;
use num_traits::ToPrimitive;
const HEADER_LENGTH: u8 = 0x06;
const KNXNET_VERSION: u8 = 0x10;
#[derive(PartialEq, Primitive, Debug)]
#[repr(u16)]
pub enum ServiceType {
SearchRequest = 0x0201,
SearchResponse = 0x0202,
DescriptionRequest = 0x0203,
DescriptionResponse = 0x0204,
ConnectionRequest = 0x0205,
ConnectionResponse = 0x0206,
ConnectionstateRequest = 0x0207,
ConnectionstateResponse = 0x0208,
DisconnectRequest = 0x0209,
DisconnectResponse = 0x020A,
TunnelRequest = 0x0420,
TunnelResponse = 0x0421,
DeviceConfigurationRequest = 0x0310,
DeviceConfigurationAck = 0x0311,
RoutingIndication = 0x0530,
}
#[derive(PartialEq)]
pub struct Header {
_header_length: u8,
_knxnet_version: u8,
service_type: ServiceType,
payload_length: u16,
}
impl Header {
pub fn new(service_type: ServiceType, payload_length: u16) -> Header {
Header {
_header_length: HEADER_LENGTH,
_knxnet_version: KNXNET_VERSION,
service_type: service_type,
payload_length: payload_length,
}
}
pub fn length() -> u8 {
HEADER_LENGTH
}
pub fn knxnet_version() -> u8 {
KNXNET_VERSION
}
pub fn encode(&self) -> Vec<u8> {
let mut buf = vec![self._header_length, self._knxnet_version];
let mut tmp = [0, 2];
BigEndian::write_u16(&mut tmp, self.service_type.to_u16().unwrap());
buf.extend(&tmp);
BigEndian::write_u16(&mut tmp, self.payload_length);
buf.extend(&tmp);
buf
}
}
impl fmt::Display for Header {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
f,
"ServiceType: {:?} Length: {}",
self.service_type, self.payload_length
)
}
}
impl fmt::Debug for Header {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{{ {} }}", self)
}
}
#[cfg(test)]
mod tests {
use crate::header::Header;
use crate::header::ServiceType;
use std::mem::size_of;
#[test]
fn t_header_length() {
assert_eq!(size_of::<Header>(), 0x06);
assert_eq!(Header::length(), 0x06);
}
#[test]
fn t_header_version() {
assert_eq!(Header::knxnet_version(), 0x10);
}
#[test]
fn t_header_fmt() {
assert_eq!(
format!("{}", Header::new(ServiceType::DescriptionRequest, 0x17)),
"ServiceType: DescriptionRequest Length: 23"
);
}
#[test]
fn t_header_encode() {
assert_eq!(
Header::new(ServiceType::DescriptionRequest, 0x17).encode(),
&[0x06, 0x10, 0x02, 0x03, 0x00, 0x17]
);
}
}