| 429 | } |
| 430 | |
| 431 | async fn get_next_device_queue_item(&mut self, is_response: bool) -> Result<()> { |
| 432 | trace!("Getting next device queue-item"); |
| 433 | |
| 434 | // If this is a response, the device is operating as a Class-B enabled device and has the |
| 435 | // class_b_downlink_only flag set, we do not retrieve a downlink from the queue. |
| 436 | if is_response |
| 437 | && self |
| 438 | .device_profile |
| 439 | .class_b_params |
| 440 | .as_ref() |
| 441 | .map(|v| v.class_b_downlink_only) |
| 442 | .unwrap_or_default() |
| 443 | && self.device.enabled_class == DeviceClass::B |
| 444 | { |
| 445 | return Ok(()); |
| 446 | } |
| 447 | |
| 448 | let ds = self.device.get_device_session()?; |
| 449 | |
| 450 | // sanity check |
| 451 | if self.downlink_frame_items.is_empty() { |
| 452 | return Err(anyhow!("downlink_frame_items is empty")); |
| 453 | } |
| 454 | |
| 455 | // We use the first downlink opportunity to determine the max-payload size |
| 456 | // for the downlink. |
| 457 | let max_payload_size = self.downlink_frame_items[0].remaining_payload_size; |
| 458 | |
| 459 | // It might require a couple of iterations to get the device-queue item. |
| 460 | loop { |
| 461 | let (qi, more_in_queue) = |
| 462 | match device_queue::get_next_for_dev_eui(&self.device.dev_eui).await { |
| 463 | Ok(v) => v, |
| 464 | Err(e) => match e { |
| 465 | // If no queue items could be found, do not return an error. |
| 466 | storage::error::Error::NotFound(_) => { |
| 467 | return Ok(()); |
| 468 | } |
| 469 | _ => { |
| 470 | return Err(e).context("Get next queue-item"); |
| 471 | } |
| 472 | }, |
| 473 | }; |
| 474 | |
| 475 | // The queue item: |
| 476 | // * should fit within the max payload size |
| 477 | // * should not be pending |
| 478 | // * should not be expired |
| 479 | // * in case encrypted, should have a valid FCntDown |
| 480 | if !(qi.data.len() > max_payload_size |
| 481 | || qi.is_pending |
| 482 | || qi.expires_at.is_some() && qi.expires_at.unwrap() < Utc::now() |
| 483 | || qi.is_encrypted |
| 484 | && (qi.f_cnt_down.unwrap_or_default() as u32) < ds.get_a_f_cnt_down()) |
| 485 | { |
| 486 | trace!(id = %qi.id, more_in_queue = more_in_queue, "Found device queue-item for downlink"); |
| 487 | self.device_queue_item = Some(qi); |
| 488 | self.more_device_queue_items = more_in_queue; |