| 10 | } |
| 11 | |
| 12 | pub fn handle( |
| 13 | dev: &mut device::Device, |
| 14 | block: &lrwn::MACCommandSet, |
| 15 | pending: Option<&lrwn::MACCommandSet>, |
| 16 | ) -> Result<Option<lrwn::MACCommandSet>> { |
| 17 | let ds = dev.get_device_session_mut()?; |
| 18 | |
| 19 | if pending.is_none() { |
| 20 | return Err(anyhow!("Pending PingSlotChannelReq expected")); |
| 21 | } |
| 22 | |
| 23 | let block_macs = &**block; |
| 24 | let pending_macs = &**pending.unwrap(); |
| 25 | |
| 26 | let req_pl = if let lrwn::MACCommand::PingSlotChannelReq(pl) = pending_macs |
| 27 | .first() |
| 28 | .ok_or_else(|| anyhow!("Empty MACCommandSet"))? |
| 29 | { |
| 30 | pl |
| 31 | } else { |
| 32 | return Err(anyhow!("Expected PingSlotChannelReq")); |
| 33 | }; |
| 34 | |
| 35 | let ans_pl = if let lrwn::MACCommand::PingSlotChannelAns(pl) = block_macs |
| 36 | .first() |
| 37 | .ok_or_else(|| anyhow!("Empty MACCommandSet"))? |
| 38 | { |
| 39 | pl |
| 40 | } else { |
| 41 | return Err(anyhow!("Expected PingSlotChannelAns")); |
| 42 | }; |
| 43 | |
| 44 | if ans_pl.channel_freq_ok && ans_pl.dr_ok { |
| 45 | // Reset the error-counter. |
| 46 | ds.mac_command_error_count |
| 47 | .remove(&(lrwn::CID::PingSlotChannelReq.to_u8() as u32)); |
| 48 | |
| 49 | ds.class_b_ping_slot_dr = req_pl.dr as u32; |
| 50 | ds.class_b_ping_slot_freq = req_pl.freq; |
| 51 | |
| 52 | info!(dev_eui = %dev.dev_eui, channel_freq = req_pl.freq, dr = req_pl.dr, "PingSlotChannelReq acknowledged"); |
| 53 | } else { |
| 54 | let count = ds |
| 55 | .mac_command_error_count |
| 56 | .entry(lrwn::CID::PingSlotChannelReq.to_u8() as u32) |
| 57 | .or_insert(0); |
| 58 | *count += 1; |
| 59 | |
| 60 | warn!(dev_eui = %dev.dev_eui, channel_freq_ok = ans_pl.channel_freq_ok, dr_ok = ans_pl.dr_ok, "PingSlotChannelReq not acknowledged"); |
| 61 | } |
| 62 | |
| 63 | Ok(None) |
| 64 | } |
| 65 | |
| 66 | #[cfg(test)] |
| 67 | pub mod test { |