MCPcopy Create free account
hub / github.com/chirpstack/chirpstack / select_downlink_gateway

Function select_downlink_gateway

chirpstack/src/downlink/helpers.rs:22–157  ·  view source on GitHub ↗

Returns the gateway to use for downlink. It will filter out private gateways (gateways from a different tenant ID, that do not allow downlinks). The result will be sorted based on SNR / RSSI. The returned value is: A random item from the elements with an SNR > minSNR The first item of the sorted slice (failing the above) An error in case no gateways are available

(
    tenant_id: Option<Uuid>,
    region_config_id: &str,
    min_snr_margin: f32,
    history: &[internal::GatewayRxInfoHistory],
    use_only_last_uplink: bool,
)

Source from the content-addressed store, hash-verified

20// * The first item of the sorted slice (failing the above)
21// * An error in case no gateways are available
22pub fn select_downlink_gateway(
23 tenant_id: Option<Uuid>,
24 region_config_id: &str,
25 min_snr_margin: f32,
26 history: &[internal::GatewayRxInfoHistory],
27 use_only_last_uplink: bool,
28) -> Result<internal::DownlinkGateway> {
29 let region_conf = region::get(region_config_id)?;
30 let tenant_id_bytes = tenant_id.map(|v| v.as_bytes().to_vec()).unwrap_or_default();
31
32 // In case of Class-A and OTAA, we only use the last item from the list, as this contains the context
33 // blobs related to the Class-A uplink. We need this context blob as it contains the uplink
34 // timestamp info.
35 let mut history = if use_only_last_uplink {
36 if let Some(h) = history.last() {
37 vec![h.clone()]
38 } else {
39 vec![]
40 }
41 } else {
42 history.to_vec()
43 };
44
45 // Filter out private gateways that are not ours.
46 for h in &mut history {
47 h.items.retain(|rx_info| {
48 if tenant_id_bytes.is_empty() {
49 !rx_info.is_private_down
50 } else if tenant_id_bytes == rx_info.tenant_id {
51 true
52 } else {
53 !rx_info.is_private_down
54 }
55 });
56 }
57
58 // Filter out empty history records.
59 history.retain(|h| !h.items.is_empty());
60
61 if history.is_empty() {
62 return Err(anyhow!(
63 "gateway rx history is empty after filtering, no downlink path available"
64 ));
65 }
66
67 #[derive(Debug, Default, Clone)]
68 struct GatewayStats {
69 gateway_id: Vec<u8>,
70 count: usize,
71 total_snr: f32,
72 total_rssi: i32,
73 total_link_margin: f32,
74 board: u32,
75 antenna: u32,
76 context: Vec<u8>,
77 gateway_downlink_priority: usize,
78 }
79

Callers 4

Calls 6

get_required_snr_for_sfFunction · 0.85
unwrapMethod · 0.80
iterMethod · 0.80
getFunction · 0.50
to_vecMethod · 0.45
get_data_rateMethod · 0.45

Tested by 1