mirror of
https://github.com/chirpstack/chirpstack.git
synced 2024-12-19 13:17:55 +00:00
Implement support for JSON for GW<>NS.
This auto-detects the encoding used by the gateway and stores this setting such that the commands will be encoded using the same setting. Closes #2.
This commit is contained in:
parent
3348ccf67d
commit
672511c696
@ -1,7 +1,9 @@
|
|||||||
use std::collections::hash_map::DefaultHasher;
|
use std::collections::hash_map::DefaultHasher;
|
||||||
|
use std::collections::HashMap;
|
||||||
use std::env::temp_dir;
|
use std::env::temp_dir;
|
||||||
use std::hash::Hasher;
|
use std::hash::Hasher;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
use std::sync::RwLock;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
@ -55,6 +57,7 @@ lazy_static! {
|
|||||||
);
|
);
|
||||||
counter
|
counter
|
||||||
};
|
};
|
||||||
|
static ref GATEWAY_JSON: RwLock<HashMap<String, bool>> = RwLock::new(HashMap::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
struct MqttContext {
|
struct MqttContext {
|
||||||
@ -247,9 +250,14 @@ impl GatewayBackend for MqttBackend<'_> {
|
|||||||
let topic = self.get_command_topic(&df.gateway_id, "down")?;
|
let topic = self.get_command_topic(&df.gateway_id, "down")?;
|
||||||
let mut df = df.clone();
|
let mut df = df.clone();
|
||||||
df.v4_migrate();
|
df.v4_migrate();
|
||||||
let b = df.encode_to_vec();
|
|
||||||
|
|
||||||
info!(gateway_id = %df.gateway_id, topic = %topic, "Sending downlink frame");
|
let json = gateway_is_json(&df.gateway_id);
|
||||||
|
let b = match json {
|
||||||
|
true => serde_json::to_vec(&df)?,
|
||||||
|
false => df.encode_to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
|
info!(gateway_id = %df.gateway_id, topic = %topic, json = json, "Sending downlink frame");
|
||||||
let msg = mqtt::Message::new(topic, b, self.qos as i32);
|
let msg = mqtt::Message::new(topic, b, self.qos as i32);
|
||||||
self.client.publish(msg).await?;
|
self.client.publish(msg).await?;
|
||||||
trace!("Message sent");
|
trace!("Message sent");
|
||||||
@ -267,9 +275,13 @@ impl GatewayBackend for MqttBackend<'_> {
|
|||||||
})
|
})
|
||||||
.inc();
|
.inc();
|
||||||
let topic = self.get_command_topic(&gw_conf.gateway_id, "config")?;
|
let topic = self.get_command_topic(&gw_conf.gateway_id, "config")?;
|
||||||
let b = gw_conf.encode_to_vec();
|
let json = gateway_is_json(&gw_conf.gateway_id);
|
||||||
|
let b = match json {
|
||||||
|
true => serde_json::to_vec(&gw_conf)?,
|
||||||
|
false => gw_conf.encode_to_vec(),
|
||||||
|
};
|
||||||
|
|
||||||
info!(gateway_id = %gw_conf.gateway_id, topic = %topic, "Sending gateway configuration");
|
info!(gateway_id = %gw_conf.gateway_id, topic = %topic, json = json, "Sending gateway configuration");
|
||||||
let msg = mqtt::Message::new(topic, b, self.qos as i32);
|
let msg = mqtt::Message::new(topic, b, self.qos as i32);
|
||||||
self.client.publish(msg).await?;
|
self.client.publish(msg).await?;
|
||||||
trace!("Message sent");
|
trace!("Message sent");
|
||||||
@ -299,10 +311,13 @@ async fn message_callback(region_name: &str, region_common_name: CommonName, msg
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let json = payload_is_json(&b);
|
||||||
|
|
||||||
info!(
|
info!(
|
||||||
region_name = region_name,
|
region_name = region_name,
|
||||||
topic = topic,
|
topic = topic,
|
||||||
qos = qos,
|
qos = qos,
|
||||||
|
json = json,
|
||||||
"Message received from gateway"
|
"Message received from gateway"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -312,10 +327,14 @@ async fn message_callback(region_name: &str, region_common_name: CommonName, msg
|
|||||||
event: "up".to_string(),
|
event: "up".to_string(),
|
||||||
})
|
})
|
||||||
.inc();
|
.inc();
|
||||||
let mut event = chirpstack_api::gw::UplinkFrame::decode(&mut Cursor::new(b))?;
|
let mut event = match json {
|
||||||
|
true => serde_json::from_slice(&b)?,
|
||||||
|
false => chirpstack_api::gw::UplinkFrame::decode(&mut Cursor::new(b))?,
|
||||||
|
};
|
||||||
event.v4_migrate();
|
event.v4_migrate();
|
||||||
|
|
||||||
if let Some(rx_info) = &mut event.rx_info {
|
if let Some(rx_info) = &mut event.rx_info {
|
||||||
|
set_gateway_json(&rx_info.gateway_id, json);
|
||||||
rx_info.set_metadata_string("region_name", region_name);
|
rx_info.set_metadata_string("region_name", region_name);
|
||||||
rx_info.set_metadata_string("region_common_name", ®ion_common_name.to_string());
|
rx_info.set_metadata_string("region_common_name", ®ion_common_name.to_string());
|
||||||
}
|
}
|
||||||
@ -327,7 +346,10 @@ async fn message_callback(region_name: &str, region_common_name: CommonName, msg
|
|||||||
event: "stats".to_string(),
|
event: "stats".to_string(),
|
||||||
})
|
})
|
||||||
.inc();
|
.inc();
|
||||||
let mut event = chirpstack_api::gw::GatewayStats::decode(&mut Cursor::new(b))?;
|
let mut event = match json {
|
||||||
|
true => serde_json::from_slice(&b)?,
|
||||||
|
false => chirpstack_api::gw::GatewayStats::decode(&mut Cursor::new(b))?,
|
||||||
|
};
|
||||||
event.v4_migrate();
|
event.v4_migrate();
|
||||||
event
|
event
|
||||||
.meta_data
|
.meta_data
|
||||||
@ -336,6 +358,7 @@ async fn message_callback(region_name: &str, region_common_name: CommonName, msg
|
|||||||
"region_common_name".to_string(),
|
"region_common_name".to_string(),
|
||||||
region_common_name.to_string(),
|
region_common_name.to_string(),
|
||||||
);
|
);
|
||||||
|
set_gateway_json(&event.gateway_id, json);
|
||||||
tokio::spawn(uplink::stats::Stats::handle(event));
|
tokio::spawn(uplink::stats::Stats::handle(event));
|
||||||
} else if topic.ends_with("/ack") {
|
} else if topic.ends_with("/ack") {
|
||||||
EVENT_COUNTER
|
EVENT_COUNTER
|
||||||
@ -343,8 +366,12 @@ async fn message_callback(region_name: &str, region_common_name: CommonName, msg
|
|||||||
event: "ack".to_string(),
|
event: "ack".to_string(),
|
||||||
})
|
})
|
||||||
.inc();
|
.inc();
|
||||||
let mut event = chirpstack_api::gw::DownlinkTxAck::decode(&mut Cursor::new(b))?;
|
let mut event = match json {
|
||||||
|
true => serde_json::from_slice(&b)?,
|
||||||
|
false => chirpstack_api::gw::DownlinkTxAck::decode(&mut Cursor::new(b))?,
|
||||||
|
};
|
||||||
event.v4_migrate();
|
event.v4_migrate();
|
||||||
|
set_gateway_json(&event.gateway_id, json);
|
||||||
tokio::spawn(downlink::tx_ack::TxAck::handle(event));
|
tokio::spawn(downlink::tx_ack::TxAck::handle(event));
|
||||||
} else {
|
} else {
|
||||||
return Err(anyhow!("Unknown event type"));
|
return Err(anyhow!("Unknown event type"));
|
||||||
@ -382,3 +409,17 @@ async fn is_locked(key: String) -> Result<bool> {
|
|||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn gateway_is_json(gateway_id: &str) -> bool {
|
||||||
|
let gw_json_r = GATEWAY_JSON.read().unwrap();
|
||||||
|
gw_json_r.get(gateway_id).cloned().unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_gateway_json(gateway_id: &str, is_json: bool) {
|
||||||
|
let mut gw_json_w = GATEWAY_JSON.write().unwrap();
|
||||||
|
gw_json_w.insert(gateway_id.to_string(), is_json);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn payload_is_json(b: &[u8]) -> bool {
|
||||||
|
String::from_utf8_lossy(b).contains("gatewayId")
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user