Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Added codec plugin implementation #671

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 16 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions api/proto/api/device_profile.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ enum CodecRuntime {

// JavaScript.
JS = 2;

// JavaScript plugin.
JS_PLUGIN = 3;
}

enum MeasurementKind {
Expand Down Expand Up @@ -178,6 +181,14 @@ service DeviceProfileService {
get : "/api/device-profiles/adr-algorithms"
};
}

// List available codec plugins.
rpc ListCodecPlugins(google.protobuf.Empty)
returns (ListDeviceProfileCodecPluginsResponse) {
option (google.api.http) = {
get : "/api/device-profiles/codec-plugins"
};
}
}

message DeviceProfile {
Expand Down Expand Up @@ -457,6 +468,9 @@ message DeviceProfile {

// Application Layer parameters.
AppLayerParams app_layer_params = 54;

// Payload codec plugin ID.
string codec_plugin_id = 55;
}

message Measurement {
Expand Down Expand Up @@ -593,3 +607,19 @@ message AdrAlgorithmListItem {
// Algorithm name.
string name = 2;
}

message ListDeviceProfileCodecPluginsResponse {
// Total number of plugins.
uint32 total_count = 1;

// Result-set.
repeated CodecPluginListItem result = 2;
}

message CodecPluginListItem {
// Pluigin ID.
string id = 1;

// Plugin name.
string name = 2;
}
3 changes: 3 additions & 0 deletions api/proto/api/device_profile_template.proto
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ message DeviceProfileTemplate {
// keys of the decoded payload. In cases where the decoded payload contains
// random keys in the data, you want to set this to false.
bool auto_detect_measurements = 29;

// Payload codec plugin ID.
string codec_plugin_id = 30;
}

message DeviceProfileTemplateListItem {
Expand Down
30 changes: 30 additions & 0 deletions api/rust/proto/chirpstack/api/device_profile.proto
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ enum CodecRuntime {

// JavaScript.
JS = 2;

// JavaScript plugin.
JS_PLUGIN = 3;
}

enum MeasurementKind {
Expand Down Expand Up @@ -178,6 +181,14 @@ service DeviceProfileService {
get : "/api/device-profiles/adr-algorithms"
};
}

// List available codec plugins.
rpc ListCodecPlugins(google.protobuf.Empty)
returns (ListDeviceProfileCodecPluginsResponse) {
option (google.api.http) = {
get : "/api/device-profiles/codec-plugins"
};
}
}

message DeviceProfile {
Expand Down Expand Up @@ -457,6 +468,9 @@ message DeviceProfile {

// Application Layer parameters.
AppLayerParams app_layer_params = 54;

// Payload codec plugin ID.
string codec_plugin_id = 55;
}

message Measurement {
Expand Down Expand Up @@ -593,3 +607,19 @@ message AdrAlgorithmListItem {
// Algorithm name.
string name = 2;
}

message ListDeviceProfileCodecPluginsResponse {
// Total number of plugins.
uint32 total_count = 1;

// Result-set.
repeated CodecPluginListItem result = 2;
}

message CodecPluginListItem {
// Pluigin ID.
string id = 1;

// Plugin name.
string name = 2;
}
3 changes: 3 additions & 0 deletions api/rust/proto/chirpstack/api/device_profile_template.proto
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,9 @@ message DeviceProfileTemplate {
// keys of the decoded payload. In cases where the decoded payload contains
// random keys in the data, you want to set this to false.
bool auto_detect_measurements = 29;

// Payload codec plugin ID.
string codec_plugin_id = 30;
}

message DeviceProfileTemplateListItem {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alter table device_profile
drop column codec_plugin_id;

alter table device_profile_template
drop column codec_plugin_id;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alter table device_profile
add column codec_plugin_id varchar(100) not null default '';

alter table device_profile_template
add column codec_plugin_id varchar(100) not null default '';
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alter table device_profile
drop column codec_plugin_id;

alter table device_profile_template
drop column codec_plugin_id;
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
alter table device_profile
add column codec_plugin_id varchar(100) not null default '';

alter table device_profile_template
add column codec_plugin_id varchar(100) not null default '';
1 change: 1 addition & 0 deletions chirpstack/src/api/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1087,6 +1087,7 @@ impl DeviceService for Device {
req_qi.f_port as u8,
&dev.variables,
&dp.payload_codec_script,
&dp.codec_plugin_id,
obj,
)
.await
Expand Down
46 changes: 46 additions & 0 deletions chirpstack/src/api/device_profile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use super::error::ToStatus;
use super::helpers;
use super::helpers::{FromProto, ToProto};
use crate::adr;
use crate::codec;
use crate::storage::{device_profile, fields};

pub struct DeviceProfile {
Expand Down Expand Up @@ -52,6 +53,7 @@ impl DeviceProfileService for DeviceProfile {
mac_version: req_dp.mac_version().from_proto(),
reg_params_revision: req_dp.reg_params_revision().from_proto(),
adr_algorithm_id: req_dp.adr_algorithm_id.clone(),
codec_plugin_id: req_dp.codec_plugin_id.clone(),
payload_codec_runtime: req_dp.payload_codec_runtime().from_proto(),
payload_codec_script: req_dp.payload_codec_script.clone(),
flush_queue_on_activate: req_dp.flush_queue_on_activate,
Expand Down Expand Up @@ -196,6 +198,7 @@ impl DeviceProfileService for DeviceProfile {
mac_version: dp.mac_version.to_proto().into(),
reg_params_revision: dp.reg_params_revision.to_proto().into(),
adr_algorithm_id: dp.adr_algorithm_id,
codec_plugin_id: dp.codec_plugin_id,
payload_codec_runtime: dp.payload_codec_runtime.to_proto().into(),
payload_codec_script: dp.payload_codec_script,
flush_queue_on_activate: dp.flush_queue_on_activate,
Expand Down Expand Up @@ -308,6 +311,7 @@ impl DeviceProfileService for DeviceProfile {
mac_version: req_dp.mac_version().from_proto(),
reg_params_revision: req_dp.reg_params_revision().from_proto(),
adr_algorithm_id: req_dp.adr_algorithm_id.clone(),
codec_plugin_id: req_dp.codec_plugin_id.clone(),
payload_codec_runtime: req_dp.payload_codec_runtime().from_proto(),
payload_codec_script: req_dp.payload_codec_script.clone(),
flush_queue_on_activate: req_dp.flush_queue_on_activate,
Expand Down Expand Up @@ -525,6 +529,33 @@ impl DeviceProfileService for DeviceProfile {
result,
}))
}

async fn list_codec_plugins(
&self,
request: Request<()>,
) -> Result<Response<api::ListDeviceProfileCodecPluginsResponse>, Status> {
self.validator
.validate(
request.extensions(),
validator::ValidateActiveUserOrKey::new(),
)
.await?;

let items = codec::js_plugin::get_plugins().await;
let mut result: Vec<api::CodecPluginListItem> = items
.iter()
.map(|(k, v)| api::CodecPluginListItem {
id: k.clone(),
name: v.clone(),
})
.collect();
result.sort_by(|a, b| a.name.cmp(&b.name));

Ok(Response::new(api::ListDeviceProfileCodecPluginsResponse {
total_count: items.len() as u32,
result,
}))
}
}

#[cfg(test)]
Expand Down Expand Up @@ -574,6 +605,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
},
Expand Down Expand Up @@ -606,6 +638,7 @@ pub mod test {
ts005_version: api::Ts005Version::Ts005NotImplemented.into(),
ts005_f_port: 200,
}),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
get_resp.get_ref().device_profile
Expand All @@ -623,6 +656,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
},
Expand All @@ -647,6 +681,7 @@ pub mod test {
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
app_layer_params: Some(api::AppLayerParams::default()),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
get_resp.get_ref().device_profile
Expand Down Expand Up @@ -697,6 +732,17 @@ pub mod test {
assert_eq!("default", list_adr_algs_resp.result[0].id);
assert_eq!("lr_fhss", list_adr_algs_resp.result[1].id);
assert_eq!("lora_lr_fhss", list_adr_algs_resp.result[2].id);

// list codec plugins
let list_codec_plugins_req = get_request(&u.id, ());
let list_codec_plugins_resp = service
.list_codec_plugins(list_codec_plugins_req)
.await
.unwrap();
let list_codec_plugins_resp = list_codec_plugins_resp.get_ref();
assert_eq!(1, list_codec_plugins_resp.total_count);
assert_eq!(1, list_codec_plugins_resp.result.len());
assert_eq!("passthrough", list_codec_plugins_resp.result[0].id);
}

fn get_request<T>(user_id: &Uuid, req: T) -> Request<T> {
Expand Down
7 changes: 7 additions & 0 deletions chirpstack/src/api/device_profile_template.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ impl DeviceProfileTemplateService for DeviceProfileTemplate {
mac_version: req_dp.mac_version().from_proto(),
reg_params_revision: req_dp.reg_params_revision().from_proto(),
adr_algorithm_id: req_dp.adr_algorithm_id.clone(),
codec_plugin_id: req_dp.codec_plugin_id.clone(),
payload_codec_runtime: req_dp.payload_codec_runtime().from_proto(),
payload_codec_script: req_dp.payload_codec_script.clone(),
flush_queue_on_activate: req_dp.flush_queue_on_activate,
Expand Down Expand Up @@ -123,6 +124,7 @@ impl DeviceProfileTemplateService for DeviceProfileTemplate {
mac_version: dp.mac_version.to_proto().into(),
reg_params_revision: dp.reg_params_revision.to_proto().into(),
adr_algorithm_id: dp.adr_algorithm_id,
codec_plugin_id: dp.codec_plugin_id,
payload_codec_runtime: dp.payload_codec_runtime.to_proto().into(),
payload_codec_script: dp.payload_codec_script,
flush_queue_on_activate: dp.flush_queue_on_activate,
Expand Down Expand Up @@ -192,6 +194,7 @@ impl DeviceProfileTemplateService for DeviceProfileTemplate {
mac_version: req_dp.mac_version().from_proto(),
reg_params_revision: req_dp.reg_params_revision().from_proto(),
adr_algorithm_id: req_dp.adr_algorithm_id.clone(),
codec_plugin_id: req_dp.codec_plugin_id.clone(),
payload_codec_runtime: req_dp.payload_codec_runtime().from_proto(),
payload_codec_script: req_dp.payload_codec_script.clone(),
flush_queue_on_activate: req_dp.flush_queue_on_activate,
Expand Down Expand Up @@ -338,6 +341,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
},
Expand All @@ -362,6 +366,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
get_resp.get_ref().device_profile_template
Expand All @@ -380,6 +385,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
},
Expand All @@ -404,6 +410,7 @@ pub mod test {
mac_version: common::MacVersion::Lorawan103.into(),
reg_params_revision: common::RegParamsRevision::A.into(),
adr_algorithm_id: "default".into(),
codec_plugin_id: "passthrough".into(),
..Default::default()
}),
get_resp.get_ref().device_profile_template
Expand Down
2 changes: 2 additions & 0 deletions chirpstack/src/api/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ impl ToProto<api::CodecRuntime> for Codec {
Codec::NONE => api::CodecRuntime::None,
Codec::CAYENNE_LPP => api::CodecRuntime::CayenneLpp,
Codec::JS => api::CodecRuntime::Js,
Codec::JS_PLUGIN => api::CodecRuntime::JsPlugin,
}
}
}
Expand All @@ -143,6 +144,7 @@ impl FromProto<Codec> for api::CodecRuntime {
api::CodecRuntime::None => Codec::NONE,
api::CodecRuntime::CayenneLpp => Codec::CAYENNE_LPP,
api::CodecRuntime::Js => Codec::JS,
api::CodecRuntime::JsPlugin => Codec::JS_PLUGIN,
}
}
}
Expand Down
10 changes: 10 additions & 0 deletions chirpstack/src/cmd/configfile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -573,6 +573,16 @@ pub fn run() {
# Maximum execution time.
max_execution_time="{{ codec.js.max_execution_time }}"

# Custom codec plugins.
#
# The custom codec plugin must be implemented in JavaScript. For an example
# skeleton, please see file examples/custom_plugins/plugin_skeleton.js
plugins=[
{{#each codec.js.plugins}}
"{{this}}",
{{/each}}
]


# User authentication configuration.
[user_authentication]
Expand Down
3 changes: 2 additions & 1 deletion chirpstack/src/cmd/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use signal_hook_tokio::Signals;
use tracing::{info, warn};

use crate::gateway;
use crate::{adr, api, applayer::fuota, backend, downlink, integration, region, storage};
use crate::{adr, api, applayer::fuota, backend, codec, downlink, integration, region, storage};

pub async fn run() -> Result<()> {
info!(
Expand All @@ -18,6 +18,7 @@ pub async fn run() -> Result<()> {
region::setup()?;
backend::setup().await?;
adr::setup().await?;
codec::js_plugin::setup().await?;
integration::setup().await?;
gateway::backend::setup().await?;
downlink::setup().await;
Expand Down
6 changes: 3 additions & 3 deletions chirpstack/src/codec/js/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use rquickjs::{CatchResultExt, IntoJs};
use super::convert;
use crate::config;

mod vendor_base64_js;
mod vendor_buffer;
mod vendor_ieee754;
pub mod vendor_base64_js;
pub mod vendor_buffer;
pub mod vendor_ieee754;

pub async fn decode(
recv_time: DateTime<Utc>,
Expand Down
Loading