浏览代码

base-station: Use rust-protocol library for packet handling.

父节点
当前提交
eccba895bf
共有 3 个文件被更改,包括 97 次插入134 次删除
  1. 9
    2
      base-station/software/Cargo.lock
  2. 1
    2
      base-station/software/Cargo.toml
  3. 87
    130
      base-station/software/src/radio.rs

+ 9
- 2
base-station/software/Cargo.lock 查看文件

24
 name = "base-station"
24
 name = "base-station"
25
 version = "0.1.0"
25
 version = "0.1.0"
26
 dependencies = [
26
 dependencies = [
27
- "crc16",
28
  "embedded-hal",
27
  "embedded-hal",
29
  "embedded-nrf24l01",
28
  "embedded-nrf24l01",
30
  "env_logger",
29
  "env_logger",
31
  "linux-embedded-hal",
30
  "linux-embedded-hal",
32
  "log",
31
  "log",
33
  "mqtt-protocol",
32
  "mqtt-protocol",
33
+ "protocol",
34
  "thiserror",
34
  "thiserror",
35
- "xxtea-nostd",
36
 ]
35
 ]
37
 
36
 
38
 [[package]]
37
 [[package]]
234
  "unicode-xid",
233
  "unicode-xid",
235
 ]
234
 ]
236
 
235
 
236
+[[package]]
237
+name = "protocol"
238
+version = "0.1.0"
239
+dependencies = [
240
+ "crc16",
241
+ "xxtea-nostd",
242
+]
243
+
237
 [[package]]
244
 [[package]]
238
 name = "quick-error"
245
 name = "quick-error"
239
 version = "1.2.3"
246
 version = "1.2.3"

+ 1
- 2
base-station/software/Cargo.toml 查看文件

14
 env_logger = "0.7"
14
 env_logger = "0.7"
15
 log = "0.4"
15
 log = "0.4"
16
 thiserror = "1.0"
16
 thiserror = "1.0"
17
-crc16 = "0.4.0"
18
-xxtea-nostd = "0.1.0"
17
+protocol = { path = "../../common/rust-protocol" }

+ 87
- 130
base-station/software/src/radio.rs 查看文件

4
 use std::thread::sleep;
4
 use std::thread::sleep;
5
 use std::time::{Duration, Instant};
5
 use std::time::{Duration, Instant};
6
 
6
 
7
-use crc16::{State, KERMIT};
8
 use embedded_nrf24l01::{Configuration, CrcMode, DataRate, NRF24L01};
7
 use embedded_nrf24l01::{Configuration, CrcMode, DataRate, NRF24L01};
9
 use linux_embedded_hal::spidev::{SpiModeFlags, Spidev, SpidevOptions};
8
 use linux_embedded_hal::spidev::{SpiModeFlags, Spidev, SpidevOptions};
10
 use linux_embedded_hal::sysfs_gpio::Direction;
9
 use linux_embedded_hal::sysfs_gpio::Direction;
11
 use linux_embedded_hal::Pin;
10
 use linux_embedded_hal::Pin;
12
 use log::{error, info};
11
 use log::{error, info};
13
-use xxtea_nostd::{decrypt, encrypt};
12
+use protocol::{Location, Packet, Value};
14
 
13
 
15
 use crate::spi::EmbeddedHalSpidev;
14
 use crate::spi::EmbeddedHalSpidev;
16
 use crate::Error;
15
 use crate::Error;
17
 use crate::{SensorData, SensorUpdate};
16
 use crate::{SensorData, SensorUpdate};
18
 
17
 
18
+const DISPLAY_ID: u8 = 0x20;
19
+const DISPLAY_KEY: [u8; 16] = include!("../../../common/display_key.txt");
20
+const WEATHER_STATION_0_ID: u8 = 0x30;
21
+const WEATHER_STATION_0_KEY: [u8; 16] = include!("../../../common/weather_station_0_key.txt");
22
+
19
 pub fn start(updates: mpsc::Sender<SensorUpdate>) {
23
 pub fn start(updates: mpsc::Sender<SensorUpdate>) {
20
     // TODO: Channels for sensor readings.
24
     // TODO: Channels for sensor readings.
21
     thread::spawn(move || {
25
     thread::spawn(move || {
73
     nrf24.set_rf(DataRate::R2Mbps, 3)?;
77
     nrf24.set_rf(DataRate::R2Mbps, 3)?;
74
     nrf24.set_crc(Some(CrcMode::OneByte))?;
78
     nrf24.set_crc(Some(CrcMode::OneByte))?;
75
     nrf24.set_auto_retransmit(250, 3)?;
79
     nrf24.set_auto_retransmit(250, 3)?;
76
-    nrf24.set_pipes_rx_enable(&[false, true, false, false, false, false])?; // TODO enable pipe 0 once the base station receives messages
80
+    nrf24.set_pipes_rx_enable(&[true, false, false, false, false, false])?; // TODO enable pipe 0 once the base station receives messages
77
     nrf24
81
     nrf24
78
-        .set_rx_addr(1, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
82
+        .set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
79
         .unwrap();
83
         .unwrap();
80
     nrf24.flush_rx().unwrap();
84
     nrf24.flush_rx().unwrap();
81
     nrf24.flush_tx().unwrap();
85
     nrf24.flush_tx().unwrap();
104
                 continue;
108
                 continue;
105
             }
109
             }
106
 
110
 
107
-            let mut payload = payload.as_ref().to_vec();
108
-
109
-            let sensor_id = payload[0];
110
-
111
-            // Decrypt the package
112
-            let key = [
113
-                0x9e, 0x37, 0x79, 0xb9, 0x9b, 0x97, 0x73, 0xe9, 0xb9, 0x79, 0x37, 0x9e, 0x6b, 0x69,
114
-                0x51, 0x56,
115
-            ]; //TODO: define somewhere else
116
-            decrypt_cbc(&key, &mut payload);
117
-            info!("decrypted: {:x?}", payload);
118
-
119
-            // Calculate the CRC
120
-            let crc_calculation_buffer = payload[8..30].to_vec();
121
-            let calculated_crc = State::<KERMIT>::calculate(&crc_calculation_buffer);
122
-            info!("calculated crc: 0x{:x}", calculated_crc);
123
-            let crc = u16::from_le_bytes(payload[30..32].try_into().unwrap());
124
-
125
-            if crc != calculated_crc {
126
-                info!("malformed packet received: crc mismatch!");
127
-                info!(
128
-                    "Calculated crc: 0x{:x}, received crc: 0x{:x}",
129
-                    calculated_crc, crc
130
-                );
131
-                continue;
132
-            }
133
-
134
-            let packet_identifier = payload[8];
135
-            let packet_payload = &payload[9..30];
136
-            info!("sensor id: 0x{:x}", sensor_id);
137
-            info!("crc: 0x{:x}", crc);
138
-
139
-            let packet_type = packet_identifier & 0x1F;
140
-            let element_count = (packet_identifier & 0xE0) >> 5;
141
-
142
-            let mut temperature = 0;
143
-            let mut pressure = 0;
144
-            let mut humidity = 0;
145
-
146
-            if packet_type == 1 {
147
-                let mut i = 0;
148
-                let mut buffer_position = 0;
149
-                info!("report packet received");
150
-                while i < element_count {
151
-                    let value_type = packet_payload[buffer_position];
152
-
153
-                    buffer_position += 1; // Set the position to the value
154
-
155
-                    if value_type == 0 {
156
-                        info!("time value not yet supported");
157
-                        buffer_position += 8;
158
-                    } else if value_type == 1 {
159
-                        temperature = i16::from_le_bytes(
160
-                            packet_payload[buffer_position..buffer_position + 2]
161
-                                .try_into()
162
-                                .unwrap(),
163
-                        );
164
-                        buffer_position += 2;
165
-                    } else if value_type == 2 {
166
-                        pressure = u32::from_le_bytes(
167
-                            packet_payload[buffer_position..buffer_position + 4]
168
-                                .try_into()
169
-                                .unwrap(),
170
-                        );
171
-                        buffer_position += 4;
172
-                    } else if value_type == 3 {
173
-                        humidity = u16::from_le_bytes(
174
-                            packet_payload[buffer_position..buffer_position + 2]
175
-                                .try_into()
176
-                                .unwrap(),
177
-                        );
178
-                        buffer_position += 2;
179
-                    } else {
180
-                        info!("unknown value type");
181
-                    }
182
-
183
-                    i += 1;
111
+            // Get the key of the device.
112
+            let device_id = payload[0];
113
+            let key = match device_id {
114
+                DISPLAY_ID => &DISPLAY_KEY,
115
+                WEATHER_STATION_0_ID => &WEATHER_STATION_0_KEY,
116
+                _ => {
117
+                    info!("packet from unknown device {:02x}", device_id);
118
+                    continue;
184
                 }
119
                 }
185
-            } else {
186
-                info!("unknown packet type");
187
-                continue;
188
-            }
120
+            };
121
+
122
+            // Decode the packet.
123
+            let mut payload: [u8; 32] = payload.as_ref().try_into().unwrap();
124
+            let packet = match Packet::decrypt_and_parse(key, &mut payload) {
125
+                None => {
126
+                    info!("invalid packet from device {:02x}", device_id);
127
+                    continue;
128
+                }
129
+                Some(p) => p,
130
+            };
131
+            // TODO: For all packets except for salt requests, check whether the
132
+            // salt was incremented to prevent replay attacks.
133
+            // TODO: Also check whether the device bit in the salt is 0.
189
 
134
 
190
-            /* Check the values for validity */
191
-            if pressure < 50000 || pressure > 150000 {
192
-                info!("pressure outside of range: {}", pressure);
193
-                continue;
194
-            }
135
+            info!("packet from {}: {:?}", device_id, packet);
195
 
136
 
196
-            if temperature < -50 * 10 || temperature > 100 * 10 {
197
-                info!("temperature outside of range: {}", temperature);
198
-                continue;
199
-            }
200
-
201
-            if humidity > 10000 {
202
-                info!("humidity outside of range: {}", humidity);
203
-                continue;
137
+            match packet {
138
+                Packet::GetSalt => {
139
+                    // TODO
140
+                }
141
+                Packet::Salt(_) => {
142
+                    error!("received Salt packet from device.");
143
+                }
144
+                Packet::Report(payload) => {
145
+                    let location = get_location(device_id);
146
+                    let count = payload.count;
147
+                    for i in 0..count {
148
+                        match payload.values[i as usize] {
149
+                            Value::Invalid => {}
150
+                            Value::Time(_) => {
151
+                                error!("device tried to report a time");
152
+                            }
153
+                            Value::Temperature(temperature) => {
154
+                                let temperature = temperature as f32 / 10.0;
155
+                                info!("{:?} temperature: {} °C", location, temperature);
156
+                            }
157
+                            Value::Pressure(pressure) => {
158
+                                let pressure = pressure as f32 / 100.0;
159
+                                info!("{:?} pressure: {} HPa", location, pressure);
160
+                            }
161
+                            Value::Humidity(humidity) => {
162
+                                let humidity = humidity as f32 / 100.0;
163
+                                info!("{:?} humidity: {}%", location, humidity);
164
+                            }
165
+                        }
166
+                    }
167
+                    // TODO: Send values via MQTT
168
+                    /*
169
+                    updates
170
+                        .send(SensorUpdate {
171
+                            location: 0,
172
+                            data: vec![
173
+                                SensorData::Temperature(temperature),
174
+                                SensorData::Pressure(pressure),
175
+                                SensorData::Humidity(humidity),
176
+                            ],
177
+                        })
178
+                        .unwrap();
179
+                    */
180
+                }
181
+                Packet::GetValues(_payload) => {
182
+                    error!("GetValues not yet implemented.");
183
+                    // TODO
184
+                }
185
+                Packet::Values(_payload) => {
186
+                    error!("received Values packet from device.");
187
+                }
204
             }
188
             }
205
 
189
 
206
-            let pressure = pressure as f32 / 100.0;
207
-            let temperature = temperature as f32 / 10.0;
208
-            let humidity = humidity as f32 / 100.0;
209
-            info!("pressure: {} HPa", pressure);
210
-            info!("temperature: {} °C", temperature);
211
-            info!("humidity: {}%", humidity);
212
-
213
-            /*
214
-            updates
215
-                .send(SensorUpdate {
216
-                    location: 0,
217
-                    data: vec![
218
-                        SensorData::Temperature(temperature),
219
-                        SensorData::Pressure(pressure),
220
-                        SensorData::Humidity(humidity),
221
-                    ],
222
-                })
223
-                .unwrap();
224
-            */
225
             let end = Instant::now();
190
             let end = Instant::now();
226
             let elapsed = end.duration_since(start);
191
             let elapsed = end.duration_since(start);
227
             info!("Debug: {:?}", elapsed);
192
             info!("Debug: {:?}", elapsed);
230
     }
195
     }
231
 }
196
 }
232
 
197
 
233
-fn decrypt_cbc(key: &[u8], data: &mut [u8]) {
234
-    let mut blocks = data.rchunks_mut(8).peekable();
235
-    loop {
236
-        let block = blocks.next().unwrap();
237
-        let prev_block = match blocks.peek() {
238
-            Some(b) => b,
239
-            None => break,
240
-        };
241
-        decrypt(&key, block);
242
-
243
-        for i in 0..8 {
244
-            block[i] ^= prev_block[i];
245
-        }
198
+fn get_location(device_id: u8) -> Location {
199
+    match device_id {
200
+        DISPLAY_ID => Location::Bedroom,
201
+        WEATHER_STATION_0_ID => Location::Livingroom,
202
+        _ => Location::Livingroom,
246
     }
203
     }
247
 }
204
 }
248
 
205
 

正在加载...
取消
保存