|
|
@@ -1,32 +1,29 @@
|
|
1
|
1
|
//! Wrapper around the NRF24 driver which provides tokio-compatible asynchronous interfaces.
|
|
2
|
2
|
|
|
3
|
|
-/*use std::convert::TryInto;
|
|
4
|
|
-use std::sync::mpsc;
|
|
5
|
|
-use std::thread;
|
|
6
|
|
-use std::thread::sleep;
|
|
7
|
|
-use std::time::{Duration, Instant};*/
|
|
|
3
|
+use std::convert::TryInto;
|
|
|
4
|
+use std::io;
|
|
|
5
|
+use std::time::Duration;
|
|
8
|
6
|
|
|
9
|
|
-/*use embedded_hal::blocking::spi::Transfer;
|
|
|
7
|
+use embedded_hal::blocking::spi::Transfer;
|
|
10
|
8
|
use embedded_hal::digital::v2::OutputPin;
|
|
11
|
9
|
use embedded_nrf24l01::{Configuration, CrcMode, DataRate, RxMode, NRF24L01};
|
|
|
10
|
+use futures_util::stream::StreamExt;
|
|
12
|
11
|
use linux_embedded_hal::spidev::{SpiModeFlags, Spidev, SpidevOptions};
|
|
13
|
|
-use linux_embedded_hal::sysfs_gpio::Direction;
|
|
14
|
|
-use linux_embedded_hal::sysfs_gpio::Error as GpioError;
|
|
|
12
|
+use linux_embedded_hal::sysfs_gpio::{Direction, Edge, Error as GpioError};
|
|
15
|
13
|
use linux_embedded_hal::Pin;
|
|
16
|
14
|
use log::{error, info};
|
|
17
|
|
-use rand::rngs::ThreadRng;
|
|
18
|
|
-use rand::Rng;*/
|
|
19
|
15
|
use protocol::{Location, Packet};
|
|
20
|
|
-use tokio::sync::mpsc::UnboundedReceiver;
|
|
|
16
|
+use rand::Rng;
|
|
|
17
|
+use tokio::select;
|
|
|
18
|
+use tokio::sync::mpsc::{self, UnboundedReceiver, UnboundedSender};
|
|
|
19
|
+use tokio::time::delay_for;
|
|
21
|
20
|
|
|
22
|
|
-/*use super::spi::EmbeddedHalSpidev;
|
|
23
|
|
-use super::Error;
|
|
24
|
|
-use super::{SensorData, SensorUpdate};*/
|
|
|
21
|
+use super::spi::EmbeddedHalSpidev;
|
|
25
|
22
|
|
|
26
|
23
|
const DISPLAY_ID: u8 = 0x20;
|
|
27
|
|
-//const DISPLAY_KEY: [u8; 16] = include!("../../../common/display_key.txt");
|
|
|
24
|
+const DISPLAY_KEY: [u8; 16] = include!("../../../common/display_key.txt");
|
|
28
|
25
|
const WEATHER_STATION_0_ID: u8 = 0x30;
|
|
29
|
|
-//const WEATHER_STATION_0_KEY: [u8; 16] = include!("../../../common/weather_station_0_key.txt");
|
|
|
26
|
+const WEATHER_STATION_0_KEY: [u8; 16] = include!("../../../common/weather_station_0_key.txt");
|
|
30
|
27
|
|
|
31
|
28
|
/// Hardware configuration.
|
|
32
|
29
|
pub struct RadioConfig {
|
|
|
@@ -35,16 +32,33 @@ pub struct RadioConfig {
|
|
35
|
32
|
|
|
36
|
33
|
/// Wrapper around the NRF24 radio driver.
|
|
37
|
34
|
pub struct Radio {
|
|
38
|
|
- // TODO
|
|
|
35
|
+ tx: UnboundedSender<(u8, Packet)>,
|
|
39
|
36
|
}
|
|
40
|
37
|
|
|
41
|
38
|
impl Radio {
|
|
42
|
39
|
/// Initializes the radio and returns both radio and the stream of incoming packets.
|
|
43
|
40
|
pub async fn init(
|
|
44
|
|
- _config: RadioConfig,
|
|
|
41
|
+ config: RadioConfig,
|
|
45
|
42
|
) -> Result<(Radio, UnboundedReceiver<(u8, Packet)>), RadioError> {
|
|
46
|
|
- // TODO
|
|
47
|
|
- panic!("Not yet implemented.");
|
|
|
43
|
+ info!("Initializing radio...");
|
|
|
44
|
+ let (tx_send, tx_recv) = mpsc::unbounded_channel();
|
|
|
45
|
+ let (rx_send, rx_recv) = mpsc::unbounded_channel();
|
|
|
46
|
+ let mut task = RadioTask {
|
|
|
47
|
+ config,
|
|
|
48
|
+ nrf24: None,
|
|
|
49
|
+ irq: None,
|
|
|
50
|
+ tx: tx_recv,
|
|
|
51
|
+ rx: rx_send,
|
|
|
52
|
+ };
|
|
|
53
|
+ task.init().await?;
|
|
|
54
|
+ info!("radio initialized.");
|
|
|
55
|
+
|
|
|
56
|
+ // Start a task for packet handling.
|
|
|
57
|
+ tokio::spawn(async move {
|
|
|
58
|
+ task.run().await;
|
|
|
59
|
+ });
|
|
|
60
|
+
|
|
|
61
|
+ Ok((Radio { tx: tx_send }, rx_recv))
|
|
48
|
62
|
}
|
|
49
|
63
|
|
|
50
|
64
|
/// Sends a packet to the specified device.
|
|
|
@@ -55,49 +69,21 @@ impl Radio {
|
|
55
|
69
|
///
|
|
56
|
70
|
/// * `device_id` - the ID of the targeted device
|
|
57
|
71
|
/// * `packet` - the packet to send
|
|
58
|
|
- pub fn send_packet_async(&mut self, _device_id: u8, _packet: Packet) {
|
|
59
|
|
- // TODO
|
|
60
|
|
- panic!("Not yet implemented.");
|
|
|
72
|
+ pub fn send_packet_async(&mut self, device_id: u8, packet: Packet) {
|
|
|
73
|
+ self.tx.send((device_id, packet)).unwrap();
|
|
61
|
74
|
}
|
|
62
|
75
|
}
|
|
63
|
76
|
|
|
64
|
|
-#[derive(Clone, Copy, Debug)]
|
|
65
|
|
-pub enum RadioError {
|
|
66
|
|
- // TODO
|
|
67
|
|
-}
|
|
68
|
|
-
|
|
69
|
|
-/*pub(crate) fn start(updates: mpsc::Sender<SensorUpdate>) {
|
|
70
|
|
- // TODO: Channels for sensor readings.
|
|
71
|
|
- thread::spawn(move || {
|
|
72
|
|
- // Whenever a error occurs, reinitialize the radio module shortly later.
|
|
73
|
|
- loop {
|
|
74
|
|
- match radio_thread(&updates) {
|
|
75
|
|
- Ok(()) => {}
|
|
76
|
|
- Err(e) => {
|
|
77
|
|
- error!("Radio error: {:?}", e);
|
|
78
|
|
- }
|
|
79
|
|
- }
|
|
80
|
|
- thread::sleep(Duration::from_secs(3));
|
|
81
|
|
- }
|
|
82
|
|
- });
|
|
83
|
|
-}
|
|
84
|
|
-
|
|
85
|
|
-fn radio_thread(updates: &mpsc::Sender<SensorUpdate>) -> Result<(), Error> {
|
|
86
|
|
- let mut radio = RadioImpl::init(updates)?;
|
|
87
|
|
- radio.run_loop()?;
|
|
88
|
|
- Ok(())
|
|
89
|
|
-}
|
|
90
|
|
-
|
|
91
|
|
-struct RadioImpl<'a> {
|
|
92
|
|
- rx: Option<RxMode<NRF24L01<GpioError, Pin, Pin, EmbeddedHalSpidev>>>,
|
|
93
|
|
- updates: &'a mpsc::Sender<SensorUpdate>,
|
|
94
|
|
- rng: ThreadRng,
|
|
|
77
|
+struct RadioTask {
|
|
|
78
|
+ config: RadioConfig,
|
|
|
79
|
+ nrf24: Option<RxMode<NRF24L01<GpioError, Pin, Pin, EmbeddedHalSpidev>>>,
|
|
|
80
|
+ irq: Option<Pin>,
|
|
|
81
|
+ tx: UnboundedReceiver<(u8, Packet)>,
|
|
|
82
|
+ rx: UnboundedSender<(u8, Packet)>,
|
|
95
|
83
|
}
|
|
96
|
84
|
|
|
97
|
|
-impl<'a> RadioImpl<'a> {
|
|
98
|
|
- fn init(updates: &'a mpsc::Sender<SensorUpdate>) -> Result<RadioImpl<'a>, Error> {
|
|
99
|
|
- info!("Initializing radio...");
|
|
100
|
|
-
|
|
|
85
|
+impl RadioTask {
|
|
|
86
|
+ async fn init(&mut self) -> Result<(), RadioError> {
|
|
101
|
87
|
// The NRF module is connected as follows:
|
|
102
|
88
|
// - CE: PA1
|
|
103
|
89
|
// - CS: PG8
|
|
|
@@ -127,6 +113,7 @@ impl<'a> RadioImpl<'a> {
|
|
127
|
113
|
let irq = Pin::new(irq_nr);
|
|
128
|
114
|
irq.export().unwrap();
|
|
129
|
115
|
irq.set_direction(Direction::In).unwrap();
|
|
|
116
|
+ irq.set_edge(Edge::FallingEdge)?;
|
|
130
|
117
|
|
|
131
|
118
|
// Configure SPI.
|
|
132
|
119
|
let mut spi = Spidev::open("/dev/spidev0.0").unwrap();
|
|
|
@@ -140,11 +127,11 @@ impl<'a> RadioImpl<'a> {
|
|
140
|
127
|
|
|
141
|
128
|
// HACK: Cycle power until transfers to the module seem to work.
|
|
142
|
129
|
loop {
|
|
143
|
|
- pwr.set_high().unwrap();
|
|
144
|
|
- sleep(Duration::from_millis(10));
|
|
145
|
|
- pwr.set_low().unwrap();
|
|
146
|
|
- sleep(Duration::from_millis(10));
|
|
147
|
|
- cs.set_low().unwrap();
|
|
|
130
|
+ pwr.set_high()?;
|
|
|
131
|
+ delay_for(Duration::from_millis(10)).await;
|
|
|
132
|
+ pwr.set_low()?;
|
|
|
133
|
+ delay_for(Duration::from_millis(10)).await;
|
|
|
134
|
+ cs.set_low()?;
|
|
148
|
135
|
let mut read_aw = [0x03, 0x00];
|
|
149
|
136
|
if spi.transfer(&mut read_aw).is_ok() {
|
|
150
|
137
|
// Correct address field width?
|
|
|
@@ -152,6 +139,8 @@ impl<'a> RadioImpl<'a> {
|
|
152
|
139
|
break;
|
|
153
|
140
|
}
|
|
154
|
141
|
}
|
|
|
142
|
+ println!("radio not yet responding correctly ({:x})...", read_aw[1]);
|
|
|
143
|
+ delay_for(Duration::from_millis(1000)).await;
|
|
155
|
144
|
}
|
|
156
|
145
|
|
|
157
|
146
|
// Initialize the radio module.
|
|
|
@@ -160,80 +149,99 @@ impl<'a> RadioImpl<'a> {
|
|
160
|
149
|
nrf24.set_rf(DataRate::R2Mbps, 3)?;
|
|
161
|
150
|
nrf24.set_crc(Some(CrcMode::OneByte))?;
|
|
162
|
151
|
nrf24.set_auto_retransmit(250, 3)?;
|
|
163
|
|
- nrf24.set_pipes_rx_enable(&[true, true, false, false, false, false])?; // TODO enable pipe 0 once the base station receives messages
|
|
164
|
|
- nrf24
|
|
165
|
|
- .set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
|
|
166
|
|
- .unwrap();
|
|
167
|
|
- nrf24
|
|
168
|
|
- .set_rx_addr(1, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
|
|
169
|
|
- .unwrap();
|
|
170
|
|
- nrf24.flush_rx().unwrap();
|
|
171
|
|
- nrf24.flush_tx().unwrap();
|
|
172
|
|
- nrf24.set_auto_ack(&[true; 6]).unwrap();
|
|
173
|
|
- info!("auto ack: {:?}", nrf24.get_auto_ack().unwrap());
|
|
174
|
|
- nrf24.set_pipes_rx_lengths(&[Some(32); 6]).unwrap();
|
|
175
|
|
-
|
|
176
|
|
- info!("width: {}", nrf24.get_address_width().unwrap());
|
|
177
|
|
-
|
|
178
|
|
- let rx = nrf24.rx().unwrap();
|
|
179
|
|
-
|
|
180
|
|
- Ok(RadioImpl {
|
|
181
|
|
- rx: Some(rx),
|
|
182
|
|
- updates,
|
|
183
|
|
- rng: rand::thread_rng(),
|
|
184
|
|
- })
|
|
185
|
|
- }
|
|
|
152
|
+ nrf24.set_pipes_rx_enable(&[true, true, false, false, false, false])?;
|
|
|
153
|
+ nrf24.set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])?;
|
|
|
154
|
+ nrf24.set_rx_addr(1, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])?;
|
|
|
155
|
+ nrf24.flush_rx()?;
|
|
|
156
|
+ nrf24.flush_tx()?;
|
|
|
157
|
+ nrf24.set_auto_ack(&[true; 6])?;
|
|
|
158
|
+ info!("auto ack: {:?}", nrf24.get_auto_ack()?);
|
|
|
159
|
+ nrf24.set_pipes_rx_lengths(&[Some(32); 6])?;
|
|
|
160
|
+
|
|
|
161
|
+ self.nrf24 = Some(nrf24.rx().unwrap());
|
|
|
162
|
+ self.irq = Some(irq);
|
|
186
|
163
|
|
|
187
|
|
- fn run_loop(&mut self) -> Result<(), Error> {
|
|
188
|
|
- let mut start = Instant::now();
|
|
|
164
|
+ Ok(())
|
|
|
165
|
+ }
|
|
189
|
166
|
|
|
190
|
|
- // Receive data.
|
|
191
|
|
- info!("Starting to receive:");
|
|
|
167
|
+ async fn run(&mut self) {
|
|
192
|
168
|
loop {
|
|
193
|
|
- sleep(Duration::from_millis(1));
|
|
194
|
|
- let rx = self.rx.as_mut().unwrap();
|
|
195
|
|
- if let Some(pipe) = rx.can_read().unwrap() {
|
|
196
|
|
- let payload = rx.read().unwrap();
|
|
197
|
|
- info!(
|
|
198
|
|
- "packet received on pipe {}: {:x?}, {}",
|
|
199
|
|
- pipe,
|
|
200
|
|
- payload.as_ref(),
|
|
201
|
|
- payload.len()
|
|
202
|
|
- );
|
|
203
|
|
- if payload.len() != 32 {
|
|
204
|
|
- continue;
|
|
|
169
|
+ let e = self.run_with_initialized_radio().await;
|
|
|
170
|
+ error!("Error in radio task: {:?}", e);
|
|
|
171
|
+ self.nrf24 = None;
|
|
|
172
|
+ // Try to reinitialize the radio.
|
|
|
173
|
+ loop {
|
|
|
174
|
+ info!("Trying to reinitialize radio: {:?}", e);
|
|
|
175
|
+ match self.init().await {
|
|
|
176
|
+ Ok(_) => break,
|
|
|
177
|
+ Err(e) => error!("Radio reinitialization failed: {:?}", e),
|
|
205
|
178
|
}
|
|
|
179
|
+ delay_for(Duration::from_secs(3)).await;
|
|
|
180
|
+ }
|
|
|
181
|
+ }
|
|
|
182
|
+ }
|
|
206
|
183
|
|
|
207
|
|
- let mut payload: [u8; 32] = payload.as_ref().try_into().unwrap();
|
|
208
|
|
- self.handle_packet(&mut payload)?;
|
|
209
|
|
-
|
|
210
|
|
- let end = Instant::now();
|
|
211
|
|
- let elapsed = end.duration_since(start);
|
|
212
|
|
- info!("Debug: {:?}", elapsed);
|
|
213
|
|
- start = end;
|
|
|
184
|
+ async fn run_with_initialized_radio(&mut self) -> Result<(), RadioError> {
|
|
|
185
|
+ // Wait for an RX interrupt of until we have to send a packet.
|
|
|
186
|
+ let mut irq_states = self.irq.as_mut().unwrap().get_value_stream().unwrap();
|
|
|
187
|
+ loop {
|
|
|
188
|
+ select! {
|
|
|
189
|
+ _pin_value = irq_states.next() => {
|
|
|
190
|
+ // Try to receive until there are no packets left in the RX fifo and until the
|
|
|
191
|
+ // interrupt pin is high again.
|
|
|
192
|
+ self.receive_packets().await?;
|
|
|
193
|
+ },
|
|
|
194
|
+ packet = self.tx.next() => {
|
|
|
195
|
+ let (device_id, packet) = packet.unwrap();
|
|
|
196
|
+ // Switch to TX mode and send the packet.
|
|
|
197
|
+ self.send_packet(device_id, packet).await?;
|
|
|
198
|
+ },
|
|
214
|
199
|
}
|
|
215
|
200
|
}
|
|
216
|
201
|
}
|
|
217
|
202
|
|
|
218
|
|
- fn handle_packet(&mut self, payload: &mut [u8]) -> Result<(), Error> {
|
|
|
203
|
+ async fn receive_packets(&mut self) -> Result<(), RadioError> {
|
|
|
204
|
+ let rx = self.nrf24.as_mut().unwrap();
|
|
|
205
|
+ let pipe = match rx.can_read()? {
|
|
|
206
|
+ Some(p) => p,
|
|
|
207
|
+ None => return Ok(()),
|
|
|
208
|
+ };
|
|
|
209
|
+ let payload = rx.read()?;
|
|
|
210
|
+ info!(
|
|
|
211
|
+ "packet received on pipe {}: {:x?}, {}",
|
|
|
212
|
+ pipe,
|
|
|
213
|
+ payload.as_ref(),
|
|
|
214
|
+ payload.len()
|
|
|
215
|
+ );
|
|
|
216
|
+ if payload.len() != 32 {
|
|
|
217
|
+ return Ok(());
|
|
|
218
|
+ }
|
|
|
219
|
+
|
|
|
220
|
+ let mut payload: [u8; 32] = payload.as_ref().try_into().unwrap();
|
|
|
221
|
+ self.handle_packet(&mut payload).await;
|
|
|
222
|
+
|
|
|
223
|
+ Ok(())
|
|
|
224
|
+ }
|
|
|
225
|
+
|
|
|
226
|
+ async fn handle_packet(&mut self, packet: &mut [u8]) {
|
|
219
|
227
|
// Get the key of the device.
|
|
220
|
|
- let device_id = payload[0];
|
|
|
228
|
+ let device_id = packet[0];
|
|
221
|
229
|
let key = match get_key(device_id) {
|
|
222
|
230
|
Some(k) => k,
|
|
223
|
231
|
None => {
|
|
224
|
232
|
info!("packet from unknown device {:02x}", device_id);
|
|
225
|
|
- return Ok(());
|
|
|
233
|
+ return;
|
|
226
|
234
|
}
|
|
227
|
235
|
};
|
|
228
|
236
|
|
|
229
|
237
|
// Decode the packet.
|
|
230
|
|
- let packet = match Packet::decrypt_and_decode(key, payload) {
|
|
|
238
|
+ let packet = match Packet::decrypt_and_decode(key, packet) {
|
|
231
|
239
|
Err(e) => {
|
|
232
|
240
|
info!(
|
|
233
|
241
|
"invalid packet from device {:02x}, error {:?}",
|
|
234
|
242
|
device_id, e
|
|
235
|
243
|
);
|
|
236
|
|
- return Ok(());
|
|
|
244
|
+ return;
|
|
237
|
245
|
}
|
|
238
|
246
|
Ok(p) => p,
|
|
239
|
247
|
};
|
|
|
@@ -243,76 +251,18 @@ impl<'a> RadioImpl<'a> {
|
|
243
|
251
|
|
|
244
|
252
|
info!("packet from {}: {:?}", device_id, packet);
|
|
245
|
253
|
|
|
246
|
|
- match packet {
|
|
247
|
|
- Packet::GetSalt => {
|
|
248
|
|
- self.send_salt(device_id)?;
|
|
249
|
|
- }
|
|
250
|
|
- Packet::Salt(_) => {
|
|
251
|
|
- error!("received Salt packet from device.");
|
|
252
|
|
- }
|
|
253
|
|
- Packet::Report(payload) => {
|
|
254
|
|
- let location = get_location(device_id);
|
|
255
|
|
- let count = payload.count;
|
|
256
|
|
- for i in 0..count {
|
|
257
|
|
- match payload.values[i as usize] {
|
|
258
|
|
- Value::Invalid => {}
|
|
259
|
|
- Value::Time(_) => {
|
|
260
|
|
- error!("device tried to report a time");
|
|
261
|
|
- }
|
|
262
|
|
- Value::Temperature(temperature) => {
|
|
263
|
|
- let temperature = temperature as f32 / 10.0;
|
|
264
|
|
- info!("{:?} temperature: {} °C", location, temperature);
|
|
265
|
|
- }
|
|
266
|
|
- Value::Pressure(pressure) => {
|
|
267
|
|
- let pressure = pressure as f32 / 100.0;
|
|
268
|
|
- info!("{:?} pressure: {} HPa", location, pressure);
|
|
269
|
|
- }
|
|
270
|
|
- Value::Humidity(humidity) => {
|
|
271
|
|
- let humidity = humidity as f32 / 100.0;
|
|
272
|
|
- info!("{:?} humidity: {}%", location, humidity);
|
|
273
|
|
- }
|
|
274
|
|
- }
|
|
275
|
|
- }
|
|
276
|
|
- // TODO: Send values via MQTT
|
|
277
|
|
- /*
|
|
278
|
|
- updates
|
|
279
|
|
- .send(SensorUpdate {
|
|
280
|
|
- location: 0,
|
|
281
|
|
- data: vec![
|
|
282
|
|
- SensorData::Temperature(temperature),
|
|
283
|
|
- SensorData::Pressure(pressure),
|
|
284
|
|
- SensorData::Humidity(humidity),
|
|
285
|
|
- ],
|
|
286
|
|
- })
|
|
287
|
|
- .unwrap();
|
|
288
|
|
- */
|
|
289
|
|
- }
|
|
290
|
|
- Packet::GetValues(_payload) => {
|
|
291
|
|
- error!("GetValues not yet implemented.");
|
|
292
|
|
- // TODO
|
|
293
|
|
- }
|
|
294
|
|
- Packet::Values(_payload) => {
|
|
295
|
|
- error!("received Values packet from device.");
|
|
296
|
|
- }
|
|
297
|
|
- }
|
|
298
|
|
- Ok(())
|
|
|
254
|
+ self.rx.send((device_id, packet)).unwrap();
|
|
299
|
255
|
}
|
|
300
|
256
|
|
|
301
|
|
- fn send_salt(&mut self, device_id: u8) -> Result<(), Error> {
|
|
302
|
|
- let salt = (self.rng.gen::<u64>() & !0xff & !(1 << 63)) | device_id as u64;
|
|
303
|
|
- let packet = Packet::Salt(salt);
|
|
304
|
|
- self.send_packet(device_id, packet)
|
|
305
|
|
- }
|
|
306
|
|
-
|
|
307
|
|
- fn send_packet(&mut self, device_id: u8, packet: Packet) -> Result<(), Error> {
|
|
308
|
|
- let salt = self.rng.gen::<u64>();
|
|
|
257
|
+ async fn send_packet(&mut self, device_id: u8, packet: Packet) -> Result<(), RadioError> {
|
|
|
258
|
+ let salt = rand::thread_rng().gen::<u64>();
|
|
309
|
259
|
let mut tx = self
|
|
310
|
|
- .rx
|
|
|
260
|
+ .nrf24
|
|
311
|
261
|
.take()
|
|
312
|
262
|
.unwrap()
|
|
313
|
263
|
.standby()
|
|
314
|
264
|
.tx()
|
|
315
|
|
- .map_err(|(_, e)| Error::Radio(e))?;
|
|
|
265
|
+ .map_err(|(_, e)| RadioError::Radio(e))?;
|
|
316
|
266
|
let mut encoded = [0u8; 32];
|
|
317
|
267
|
let key = get_key(device_id);
|
|
318
|
268
|
// TODO: Check whether the packet arrived.
|
|
|
@@ -325,16 +275,32 @@ impl<'a> RadioImpl<'a> {
|
|
325
|
275
|
} else {
|
|
326
|
276
|
info!("could not encode packet {:?}", packet);
|
|
327
|
277
|
}
|
|
328
|
|
- self.rx = Some(
|
|
|
278
|
+ self.nrf24 = Some(
|
|
329
|
279
|
tx.standby()
|
|
330
|
|
- .map_err(Error::Radio)?
|
|
|
280
|
+ .map_err(RadioError::Radio)?
|
|
331
|
281
|
.rx()
|
|
332
|
|
- .map_err(|(_, e)| Error::Radio(e))?,
|
|
|
282
|
+ .map_err(|(_, e)| RadioError::Radio(e))?,
|
|
333
|
283
|
);
|
|
334
|
284
|
info!("packet sent: {:?}", packet);
|
|
335
|
285
|
Ok(())
|
|
336
|
286
|
}
|
|
337
|
|
-}*/
|
|
|
287
|
+}
|
|
|
288
|
+
|
|
|
289
|
+#[derive(thiserror::Error, Debug)]
|
|
|
290
|
+pub enum RadioError {
|
|
|
291
|
+ #[error("I/O error")]
|
|
|
292
|
+ Io(#[from] io::Error),
|
|
|
293
|
+ #[error("GPIO error")]
|
|
|
294
|
+ Gpio(#[from] GpioError),
|
|
|
295
|
+ #[error("radio error: {0:?}")]
|
|
|
296
|
+ Radio(embedded_nrf24l01::Error<std::io::Error>),
|
|
|
297
|
+}
|
|
|
298
|
+
|
|
|
299
|
+impl From<embedded_nrf24l01::Error<std::io::Error>> for RadioError {
|
|
|
300
|
+ fn from(e: embedded_nrf24l01::Error<std::io::Error>) -> Self {
|
|
|
301
|
+ RadioError::Radio(e)
|
|
|
302
|
+ }
|
|
|
303
|
+}
|
|
338
|
304
|
|
|
339
|
305
|
pub fn get_device_location(device_id: u8) -> Location {
|
|
340
|
306
|
match device_id {
|
|
|
@@ -344,7 +310,7 @@ pub fn get_device_location(device_id: u8) -> Location {
|
|
344
|
310
|
}
|
|
345
|
311
|
}
|
|
346
|
312
|
|
|
347
|
|
-/*fn get_key(device_id: u8) -> Option<&'static [u8]> {
|
|
|
313
|
+fn get_key(device_id: u8) -> Option<&'static [u8]> {
|
|
348
|
314
|
match device_id {
|
|
349
|
315
|
DISPLAY_ID => Some(&DISPLAY_KEY),
|
|
350
|
316
|
WEATHER_STATION_0_ID => Some(&WEATHER_STATION_0_KEY),
|
|
|
@@ -354,4 +320,4 @@ pub fn get_device_location(device_id: u8) -> Location {
|
|
354
|
320
|
|
|
355
|
321
|
fn get_pin_number(c: char, n: u64) -> u64 {
|
|
356
|
322
|
(c as u64 - 'A' as u64) * 32 + n
|
|
357
|
|
-}*/
|
|
|
323
|
+}
|