暫無描述
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.

lib.rs 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. //! Library which implements serialization and deserialization for the packet format used by the
  2. //! base station and all sensor/display nodes.
  3. #![no_std]
  4. use core::convert::TryInto;
  5. use crc16::{State, KERMIT};
  6. use xxtea_nostd::decrypt;
  7. #[derive(Debug, Clone)]
  8. pub enum Packet {
  9. GetSalt,
  10. Salt(u64),
  11. Report(Report),
  12. GetValues(GetValues),
  13. Values(Values),
  14. }
  15. impl Packet {
  16. pub fn decrypt_and_parse(key: &[u8], data: &mut [u8]) -> Option<Packet> {
  17. decrypt_cbc(key, data);
  18. let checksummed = &data[8..];
  19. let remainder = State::<KERMIT>::calculate(&checksummed);
  20. if remainder != 0 {
  21. return None;
  22. }
  23. Self::decode(&checksummed[..22])
  24. }
  25. fn decode(data: &[u8]) -> Option<Packet> {
  26. let type_ = data[0] & 0x1f;
  27. // count can be at most 7, so we do not need any checks when indexing 8-element arrays
  28. // below.
  29. let count = data[0] >> 5;
  30. match type_ {
  31. 0 => Some(Self::GetSalt),
  32. 1 => Some(Self::Salt({
  33. // The lowest 8 bit of the salt are the device ID and are filled in by the caller.
  34. u64::from_le_bytes(data[1..9].try_into().unwrap()) << 8
  35. })),
  36. 2 => Some(Self::Report(Report::decode(count, &data[1..])?)),
  37. 3 => Some(Self::GetValues(GetValues::decode(count, &data[1..])?)),
  38. 4 => Some(Self::Values(Values::decode(count, &data[1..])?)),
  39. _ => None,
  40. }
  41. }
  42. }
  43. #[derive(Debug, Clone)]
  44. pub struct Report {
  45. pub count: u8,
  46. pub values: [Value; 8],
  47. }
  48. impl Report {
  49. fn decode(count: u8, mut data: &[u8]) -> Option<Report> {
  50. let mut report = Self {
  51. count,
  52. values: [Value::Invalid; 8],
  53. };
  54. for i in 0..count {
  55. report.values[i as usize] = Value::decode(&mut data)?;
  56. }
  57. Some(report)
  58. }
  59. }
  60. #[derive(Debug, Clone)]
  61. pub struct GetValues {
  62. pub count: u8,
  63. pub location: Location,
  64. pub types_: [ValueType; 8],
  65. }
  66. impl GetValues {
  67. fn decode(_count: u8, _data: &[u8]) -> Option<GetValues> {
  68. // TODO
  69. None
  70. }
  71. }
  72. #[derive(Debug, Clone)]
  73. pub struct Values {
  74. pub count: u8,
  75. pub location: Location,
  76. pub values: [Value; 8],
  77. }
  78. impl Values {
  79. fn decode(_count: u8, _data: &[u8]) -> Option<Values> {
  80. // TODO
  81. None
  82. }
  83. }
  84. #[derive(Debug, Clone, Copy)]
  85. pub enum Location {
  86. Livingroom,
  87. Bathroom,
  88. Bedroom,
  89. Kitchen,
  90. Balcony,
  91. }
  92. #[derive(Debug, Clone, Copy)]
  93. pub enum Value {
  94. Invalid,
  95. Time(u64),
  96. Temperature(i16),
  97. Pressure(u32),
  98. Humidity(u16),
  99. }
  100. impl Value {
  101. fn decode(data: &mut &[u8]) -> Option<Value> {
  102. let type_ = data[0];
  103. let length = match type_ {
  104. 0 => 9,
  105. 1 => 3,
  106. 2 => 5,
  107. 3 => 3,
  108. _ => return None,
  109. };
  110. if data.len() < length {
  111. return None;
  112. }
  113. let result = match type_ {
  114. 0 => Self::Time(u64::from_le_bytes(data[1..9].try_into().unwrap())),
  115. 1 => Self::Temperature(i16::from_le_bytes(data[1..3].try_into().unwrap())),
  116. 2 => Self::Pressure(u32::from_le_bytes(data[1..5].try_into().unwrap())),
  117. 3 => Self::Humidity(u16::from_le_bytes(data[1..3].try_into().unwrap())),
  118. _ => return None,
  119. };
  120. *data = &data[length..];
  121. Some(result)
  122. }
  123. }
  124. #[derive(Debug, Clone, Copy)]
  125. pub enum ValueType {
  126. Time,
  127. Temperature,
  128. Pressure,
  129. Humidity,
  130. }
  131. fn decrypt_cbc(key: &[u8], data: &mut [u8]) {
  132. let mut blocks = data.rchunks_mut(8).peekable();
  133. loop {
  134. let block = blocks.next().unwrap();
  135. let prev_block = match blocks.peek() {
  136. Some(b) => b,
  137. None => break,
  138. };
  139. decrypt(&key, block);
  140. for i in 0..8 {
  141. block[i] ^= prev_block[i];
  142. }
  143. }
  144. }