| 6 | use crate::uplink::UplinkFrameSet; |
| 7 | |
| 8 | pub fn handle( |
| 9 | uplink_frame_set: &UplinkFrameSet, |
| 10 | dev: &mut device::Device, |
| 11 | block: &lrwn::MACCommandSet, |
| 12 | pending: Option<&lrwn::MACCommandSet>, |
| 13 | ) -> Result<Option<lrwn::MACCommandSet>> { |
| 14 | let dev_eui = dev.dev_eui; |
| 15 | let ds = dev.get_device_session_mut()?; |
| 16 | |
| 17 | if pending.is_none() { |
| 18 | return Err(anyhow!("Expected pending LinkADRReq mac-command")); |
| 19 | } |
| 20 | |
| 21 | let region_conf = region::get(&uplink_frame_set.region_config_id)?; |
| 22 | |
| 23 | let mut ch_mask_ack = true; |
| 24 | let mut dr_ack = true; |
| 25 | let mut tx_power_ack = true; |
| 26 | |
| 27 | for mac in &**block { |
| 28 | if let lrwn::MACCommand::LinkADRAns(pl) = mac { |
| 29 | if !pl.ch_mask_ack { |
| 30 | ch_mask_ack = false; |
| 31 | } |
| 32 | if !pl.dr_ack { |
| 33 | dr_ack = false; |
| 34 | } |
| 35 | if !pl.tx_power_ack { |
| 36 | tx_power_ack = false; |
| 37 | } |
| 38 | } |
| 39 | } |
| 40 | |
| 41 | let mut link_adr_reqs: Vec<lrwn::LinkADRReqPayload> = Vec::new(); |
| 42 | |
| 43 | // we already validated that this is not None |
| 44 | for mac in &**pending.unwrap() { |
| 45 | if let lrwn::MACCommand::LinkADRReq(pl) = mac { |
| 46 | link_adr_reqs.push(pl.clone()); |
| 47 | } |
| 48 | } |
| 49 | |
| 50 | // as we're sending the same txpower and nbrep for each channel we |
| 51 | // take the last one |
| 52 | let link_adr_req = link_adr_reqs.last().unwrap(); |
| 53 | |
| 54 | if ch_mask_ack && dr_ack && tx_power_ack { |
| 55 | // The device acked all request (channel-mask, data-rate and power), |
| 56 | // in this case we update the device-session with all the requested |
| 57 | // modifications. |
| 58 | |
| 59 | // reset the error counter |
| 60 | ds.mac_command_error_count |
| 61 | .remove(&(lrwn::CID::LinkADRReq.to_u8() as u32)); |
| 62 | |
| 63 | let chans = region_conf |
| 64 | .get_enabled_uplink_channel_indices_for_link_adr_payloads( |
| 65 | &ds.enabled_uplink_channel_indices |