Hi,
Normally ChirpStack LNS only publish LoRa messages from registered devices to the MQTT topic application/APPLICATION_ID/device/DEV_EUI/event/EVENT
. I made a small customization to the Chirpstack server code and now it can also publish up-events of the unregistered devices under Unknown device (dev EUI 00000000000000000). Please, see the image below.
This is just experimental code, but it seems possible to implement this kind of functionality quite easily.
I added following changes in chirpstack\src\uplink\data.rs file.
About at the line 265 added a new function call: self.handle_unknown_device(dev_addr).await?
async fn get_device_for_phy_payload(&mut self) -> Result<(), Error> {
trace!("Getting device for PhyPayload");
let dev_addr = if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
pl.fhdr.devaddr
} else {
return Err(Error::Anyhow(anyhow!("No MacPayload in PhyPayload")));
};
match device::get_for_phypayload_and_incr_f_cnt_up(
...
Err(e) => match e {
StorageError::NotFound(s) => {
info!(dev_addr = %s, "No device-session exists for dev_addr");
// Start a new process flow to tracking location of the unknown devices.
self.handle_unknown_device(dev_addr).await?;
return Err(Error::Abort);
}
...
Ok(())
}
And a new function handle_unknown_device() at the end of the file.
// GLSensor-tracker - Unkown devices app - unknown device
async fn handle_unknown_device(&mut self, dev_addr: lrwn::DevAddr) -> Result<(), Error> {
use crate::uplink::data::fields::DeviceSession;
const UNKNOWN_DEVICE_EUI: &str = "0000000000000000";
const UNKNOWN_APPLICATION_NAME: &str = "Unknown devices";
const UNKNOWN_DEVICE_NAME: &str = "Unknown device";
let unknown_device_eui: EUI64 = EUI64::from_str(UNKNOWN_DEVICE_EUI).unwrap_or_default();
let (dev, app, t, dp) = get_all_device_data(unknown_device_eui).await?;
if app.name == UNKNOWN_APPLICATION_NAME && dev.name == UNKNOWN_DEVICE_NAME {
// OK, continue process
} else {
return Ok(());
}
info!("Create uplink event for the unknown device (addr: {}) of the unknown devices application", dev_addr );
if let lrwn::Payload::MACPayload(pl) = &self.phy_payload.payload {
self.f_cnt_up_full = pl.fhdr.f_cnt;
} else {
return Err(anyhow!("Expected MacPayload"));
};
// Create a dummy session for the unknown device
let dev_session = internal::DeviceSession {
region_config_id: dp.region_config_id.as_ref().map_or("",|v| v).to_string(),
dev_addr: dev_addr.to_vec(),
s_nwk_s_int_key: vec![
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
f_nwk_s_int_key: vec![
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
nwk_s_enc_key: vec![
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
],
f_cnt_up: 1,
skip_f_cnt_check: true,
..Default::default()
};
let mut device = dev;
device.name = format!("{} - {}", "Unknown", dev_addr);
device.dev_addr = Some(dev_addr);
device.device_session = Some(DeviceSession::new(dev_session));
self.device = Some(device);
self.tenant = Some(t);
self.application = Some(app);
self.device_profile = Some(dp);
self.set_device_info()?;
self.set_device_gateway_rx_info()?;
self.log_uplink_frame_set().await?;
self.set_uplink_data_rate().await?;
self.log_uplink_meta().await?;
if !self._is_roaming() {
self.save_device_gateway_rx_info().await?;
}
self.append_meta_data_to_uplink_history()?;
self.send_uplink_event().await?;
self.update_device().await?;
self.save_metrics().await?;
Ok(())
}