Няма описание
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283
  1. use std::convert::TryInto;
  2. use std::sync::mpsc;
  3. use std::thread;
  4. use std::thread::sleep;
  5. use std::time::{Duration, Instant};
  6. use embedded_nrf24l01::{Configuration, CrcMode, DataRate, RxMode, NRF24L01};
  7. use linux_embedded_hal::spidev::{SpiModeFlags, Spidev, SpidevOptions};
  8. use linux_embedded_hal::sysfs_gpio::Direction;
  9. use linux_embedded_hal::sysfs_gpio::Error as GpioError;
  10. use linux_embedded_hal::Pin;
  11. use log::{error, info};
  12. use protocol::{Location, Packet, Value};
  13. use rand::rngs::ThreadRng;
  14. use rand::Rng;
  15. use crate::spi::EmbeddedHalSpidev;
  16. use crate::Error;
  17. use crate::{SensorData, SensorUpdate};
  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. pub fn start(updates: mpsc::Sender<SensorUpdate>) {
  23. // TODO: Channels for sensor readings.
  24. thread::spawn(move || {
  25. // Whenever a error occurs, reinitialize the radio module shortly later.
  26. loop {
  27. match radio_thread(&updates) {
  28. Ok(()) => {}
  29. Err(e) => {
  30. error!("Radio error: {:?}", e);
  31. }
  32. }
  33. thread::sleep(Duration::from_secs(3));
  34. }
  35. });
  36. }
  37. fn radio_thread(updates: &mpsc::Sender<SensorUpdate>) -> Result<(), Error> {
  38. let mut radio = Radio::init(updates)?;
  39. radio.run_loop()?;
  40. Ok(())
  41. }
  42. struct Radio<'a> {
  43. rx: Option<RxMode<NRF24L01<GpioError, Pin, Pin, EmbeddedHalSpidev>>>,
  44. updates: &'a mpsc::Sender<SensorUpdate>,
  45. rng: ThreadRng,
  46. }
  47. impl<'a> Radio<'a> {
  48. fn init(updates: &'a mpsc::Sender<SensorUpdate>) -> Result<Radio<'a>, Error> {
  49. info!("Initializing radio...");
  50. // The NRF module is connected as follows:
  51. // - CE: PA1
  52. // - CS: PG8
  53. // - IRQ: PG9
  54. // - MOSI: PC0
  55. // - MISO: PC1
  56. // - SCK: PC2
  57. // Configure SPI.
  58. let mut spi = Spidev::open("/dev/spidev0.0").unwrap();
  59. let options = SpidevOptions::new()
  60. .bits_per_word(8)
  61. .max_speed_hz(500_000)
  62. .mode(SpiModeFlags::SPI_MODE_0)
  63. .build();
  64. spi.configure(&options).unwrap();
  65. let spi = EmbeddedHalSpidev::from(spi);
  66. // Configure the GPIOs.
  67. let ce_nr = get_pin_number('A', 1);
  68. let ce = Pin::new(ce_nr);
  69. ce.export().unwrap();
  70. ce.set_direction(Direction::Out).unwrap();
  71. let cs_nr = get_pin_number('G', 8);
  72. let cs = Pin::new(cs_nr);
  73. cs.export().unwrap();
  74. cs.set_direction(Direction::Out).unwrap();
  75. let irq_nr = get_pin_number('G', 9);
  76. let irq = Pin::new(irq_nr);
  77. irq.export().unwrap();
  78. irq.set_direction(Direction::In).unwrap();
  79. // Initialize the radio module.
  80. let mut nrf24 = NRF24L01::new(ce, cs, spi)?;
  81. nrf24.set_frequency(0x32)?;
  82. nrf24.set_rf(DataRate::R2Mbps, 3)?;
  83. nrf24.set_crc(Some(CrcMode::OneByte))?;
  84. nrf24.set_auto_retransmit(250, 3)?;
  85. nrf24.set_pipes_rx_enable(&[true, false, false, false, false, false])?; // TODO enable pipe 0 once the base station receives messages
  86. nrf24
  87. .set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, 0x00])
  88. .unwrap();
  89. nrf24.flush_rx().unwrap();
  90. nrf24.flush_tx().unwrap();
  91. nrf24.set_auto_ack(&[true; 6]).unwrap();
  92. info!("auto ack: {:?}", nrf24.get_auto_ack().unwrap());
  93. nrf24.set_pipes_rx_lengths(&[Some(32); 6]).unwrap();
  94. info!("width: {}", nrf24.get_address_width().unwrap());
  95. let rx = nrf24.rx().unwrap();
  96. Ok(Radio {
  97. rx: Some(rx),
  98. updates,
  99. rng: rand::thread_rng(),
  100. })
  101. }
  102. fn run_loop(&mut self) -> Result<(), Error> {
  103. let mut start = Instant::now();
  104. // Receive data.
  105. info!("Starting to receive:");
  106. loop {
  107. sleep(Duration::from_millis(1));
  108. let rx = self.rx.as_mut().unwrap();
  109. if let Some(pipe) = rx.can_read().unwrap() {
  110. let payload = rx.read().unwrap();
  111. info!(
  112. "packet received on pipe {}: {:x?}, {}",
  113. pipe,
  114. payload.as_ref(),
  115. payload.len()
  116. );
  117. if payload.len() != 32 {
  118. continue;
  119. }
  120. let mut payload: [u8; 32] = payload.as_ref().try_into().unwrap();
  121. self.handle_packet(&mut payload)?;
  122. let end = Instant::now();
  123. let elapsed = end.duration_since(start);
  124. info!("Debug: {:?}", elapsed);
  125. start = end;
  126. }
  127. }
  128. }
  129. fn handle_packet(&mut self, payload: &mut [u8]) -> Result<(), Error> {
  130. // Get the key of the device.
  131. let device_id = payload[0];
  132. let key = match get_key(device_id) {
  133. Some(k) => k,
  134. None => {
  135. info!("packet from unknown device {:02x}", device_id);
  136. return Ok(());
  137. }
  138. };
  139. // Decode the packet.
  140. let packet = match Packet::decrypt_and_decode(key, payload) {
  141. None => {
  142. info!("invalid packet from device {:02x}", device_id);
  143. return Ok(());
  144. }
  145. Some(p) => p,
  146. };
  147. // TODO: For all packets except for salt requests, check whether the
  148. // salt was incremented to prevent replay attacks.
  149. // TODO: Also check whether the device bit in the salt is 0.
  150. info!("packet from {}: {:?}", device_id, packet);
  151. match packet {
  152. Packet::GetSalt => {
  153. self.send_salt(device_id)?;
  154. }
  155. Packet::Salt(_) => {
  156. error!("received Salt packet from device.");
  157. }
  158. Packet::Report(payload) => {
  159. let location = get_location(device_id);
  160. let count = payload.count;
  161. for i in 0..count {
  162. match payload.values[i as usize] {
  163. Value::Invalid => {}
  164. Value::Time(_) => {
  165. error!("device tried to report a time");
  166. }
  167. Value::Temperature(temperature) => {
  168. let temperature = temperature as f32 / 10.0;
  169. info!("{:?} temperature: {} °C", location, temperature);
  170. }
  171. Value::Pressure(pressure) => {
  172. let pressure = pressure as f32 / 100.0;
  173. info!("{:?} pressure: {} HPa", location, pressure);
  174. }
  175. Value::Humidity(humidity) => {
  176. let humidity = humidity as f32 / 100.0;
  177. info!("{:?} humidity: {}%", location, humidity);
  178. }
  179. }
  180. }
  181. // TODO: Send values via MQTT
  182. /*
  183. updates
  184. .send(SensorUpdate {
  185. location: 0,
  186. data: vec![
  187. SensorData::Temperature(temperature),
  188. SensorData::Pressure(pressure),
  189. SensorData::Humidity(humidity),
  190. ],
  191. })
  192. .unwrap();
  193. */
  194. }
  195. Packet::GetValues(_payload) => {
  196. error!("GetValues not yet implemented.");
  197. // TODO
  198. }
  199. Packet::Values(_payload) => {
  200. error!("received Values packet from device.");
  201. }
  202. }
  203. Ok(())
  204. }
  205. fn send_salt(&mut self, device_id: u8) -> Result<(), Error> {
  206. let salt = (self.rng.gen::<u64>() & !0xff & !(1 << 63)) | device_id as u64;
  207. let packet = Packet::Salt(salt);
  208. self.send_packet(device_id, packet)
  209. }
  210. fn send_packet(&mut self, device_id: u8, packet: Packet) -> Result<(), Error> {
  211. /*let salt = self.rng.gen::<u64>();
  212. let mut tx = self
  213. .rx
  214. .take()
  215. .unwrap()
  216. .standby()
  217. .tx()
  218. .map_err(|(_, e)| Error::Radio(e))?;
  219. let mut encoded = [0u8; 32];
  220. let key = get_key(device_id);
  221. if packet.encode_and_encrypt(key.unwrap(), salt, &mut encoded) {
  222. tx.set_tx_addr(&[0xB3, 0xB3, 0xB3, 0xB3, device_id])
  223. .unwrap();
  224. tx.set_rx_addr(0, &[0xB3, 0xB3, 0xB3, 0xB3, device_id])
  225. .unwrap();
  226. tx.send(&encoded).unwrap();
  227. // TODO: Check whether the packet arrived.
  228. } else {
  229. info!("could not encode packet {:?}", packet);
  230. }
  231. self.rx = Some(
  232. tx.standby()
  233. .map_err(Error::Radio)?
  234. .rx()
  235. .map_err(|(_, e)| Error::Radio(e))?,
  236. );*/
  237. Ok(())
  238. }
  239. }
  240. fn get_location(device_id: u8) -> Location {
  241. match device_id {
  242. DISPLAY_ID => Location::Bedroom,
  243. WEATHER_STATION_0_ID => Location::Livingroom,
  244. _ => Location::Livingroom,
  245. }
  246. }
  247. fn get_key(device_id: u8) -> Option<&'static [u8]> {
  248. match device_id {
  249. DISPLAY_ID => Some(&DISPLAY_KEY),
  250. WEATHER_STATION_0_ID => Some(&WEATHER_STATION_0_KEY),
  251. _ => None,
  252. }
  253. }
  254. fn get_pin_number(c: char, n: u64) -> u64 {
  255. (c as u64 - 'A' as u64) * 32 + n
  256. }