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
121
122
123
use super::*;
use crate::tx_ack::TxPkNack;
use std::convert::TryFrom;
const PROTOCOL_VERSION_INDEX: usize = 0;
const IDENTIFIER_INDEX: usize = 3;
const PACKET_PAYLOAD_START: usize = 8;
fn random_token(buffer: &[u8]) -> u16 {
(buffer[1] as u16) << 8 | buffer[2] as u16
}
pub fn gateway_mac(buffer: &[u8]) -> MacAddress {
MacAddress::new(
buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7],
)
}
pub trait Parser {
fn parse(buffer: &[u8]) -> std::result::Result<Packet, ParseError>;
}
impl Packet {
pub fn parse_uplink(buffer: &[u8]) -> std::result::Result<Up, ParseError> {
match Self::parse(buffer)? {
Packet::Up(up) => Ok(up),
Packet::Down(down) => Err(ParseError::UnexpectedDownlink(down)),
}
}
pub fn parse_downlink(buffer: &[u8]) -> std::result::Result<Down, ParseError> {
match Self::parse(buffer)? {
Packet::Down(down) => Ok(down),
Packet::Up(up) => Err(ParseError::UnexpectedUplink(up)),
}
}
}
impl Parser for Packet {
fn parse(buffer: &[u8]) -> std::result::Result<Packet, ParseError> {
if buffer[PROTOCOL_VERSION_INDEX] != PROTOCOL_VERSION {
return Err(ParseError::InvalidProtocolVersion);
};
match Identifier::try_from(buffer[IDENTIFIER_INDEX]) {
Err(_) => Err(ParseError::InvalidIdentifier),
Ok(id) => {
let random_token = random_token(buffer);
let buffer = &buffer[4..];
Ok(match id {
Identifier::PullData => {
let gateway_mac = gateway_mac(&buffer[..PACKET_PAYLOAD_START]);
pull_data::Packet {
random_token,
gateway_mac,
}
.into()
}
Identifier::PushData => {
let gateway_mac = gateway_mac(&buffer[..PACKET_PAYLOAD_START]);
let json_str = std::str::from_utf8(&buffer[PACKET_PAYLOAD_START..])?;
let data = serde_json::from_str(json_str).map_err(|json_error| {
ParseError::InvalidJson {
identifier: id,
json_str: json_str.into(),
json_error,
}
})?;
push_data::Packet {
random_token,
gateway_mac,
data,
}
.into()
}
Identifier::TxAck => {
let gateway_mac = gateway_mac(&buffer[..PACKET_PAYLOAD_START]);
let data = if buffer.len() > PACKET_PAYLOAD_START {
if buffer.len() == PACKET_PAYLOAD_START + 1
&& buffer[PACKET_PAYLOAD_START] == 0
{
TxPkNack::default()
} else {
let json_str =
std::str::from_utf8(&buffer[PACKET_PAYLOAD_START..])?;
serde_json::from_str(json_str).map_err(|json_error| {
ParseError::InvalidJson {
identifier: id,
json_str: json_str.into(),
json_error,
}
})?
}
} else {
TxPkNack::default()
};
tx_ack::Packet {
random_token,
gateway_mac,
data,
}
.into()
}
Identifier::PushAck => push_ack::Packet { random_token }.into(),
Identifier::PullAck => pull_ack::Packet { random_token }.into(),
Identifier::PullResp => {
let json_str = std::str::from_utf8(buffer)?;
let data = serde_json::from_str(json_str).map_err(|json_error| {
ParseError::InvalidJson {
identifier: id,
json_str: json_str.into(),
json_error,
}
})?;
pull_resp::Packet { random_token, data }.into()
}
})
}
}
}
}