Skip to content

Commit

Permalink
Merge pull request #3282 from Bravo555/improve/smartrest-types
Browse files Browse the repository at this point in the history
refactor: Create a module with smartrest message id consts
  • Loading branch information
Bravo555 authored Dec 11, 2024
2 parents 76b4c83 + f0ff4f7 commit 82cde40
Show file tree
Hide file tree
Showing 14 changed files with 215 additions and 65 deletions.
19 changes: 11 additions & 8 deletions crates/core/c8y_api/src/smartrest/alarm.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::json_c8y::AlarmSeverity;
use crate::json_c8y::C8yAlarm;
use crate::smartrest::message_ids::*;
use time::format_description::well_known::Rfc3339;

use super::payload::SmartrestPayload;
Expand All @@ -9,21 +10,23 @@ pub fn serialize_alarm(c8y_alarm: &C8yAlarm) -> Result<SmartrestPayload, time::e
let smartrest = match c8y_alarm {
C8yAlarm::Create(alarm) => {
let smartrest_code = match alarm.severity {
AlarmSeverity::Critical => "301",
AlarmSeverity::Major => "302",
AlarmSeverity::Minor => "303",
AlarmSeverity::Warning => "304",
AlarmSeverity::Critical => CREATE_CRITICAL_ALARM,
AlarmSeverity::Major => CREATE_MAJOR_ALARM,
AlarmSeverity::Minor => CREATE_MINOR_ALARM,
AlarmSeverity::Warning => CREATE_WARNING_ALARM,
};
SmartrestPayload::serialize([
SmartrestPayload::serialize((
smartrest_code,
&alarm.alarm_type,
&alarm.text,
&alarm.time.format(&Rfc3339)?,
])
))
.expect("TODO: should alarm text be trimmed?")
}
C8yAlarm::Clear(alarm) => SmartrestPayload::serialize((306, &alarm.alarm_type))
.expect("alarm type should be shorter than payload size limit"),
C8yAlarm::Clear(alarm) => {
SmartrestPayload::serialize((CLEAR_EXISTING_ALARM, &alarm.alarm_type))
.expect("alarm type should be shorter than payload size limit")
}
};
Ok(smartrest)
}
Expand Down
32 changes: 21 additions & 11 deletions crates/core/c8y_api/src/smartrest/inventory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,16 @@
// smartrest messages are sent. There should be one comprehensive API for
// generating them.

use crate::smartrest::csv::fields_to_csv_string;
use crate::smartrest::topic::publish_topic_from_ancestors;
use crate::smartrest::topic::C8yTopic;
use mqtt_channel::MqttMessage;
use std::time::Duration;
use tedge_config::TopicPrefix;

use super::message_ids::CHILD_DEVICE_CREATION;
use super::message_ids::SERVICE_CREATION;
use super::message_ids::SET_DEVICE_PROFILE_THAT_IS_BEING_APPLIED;
use super::message_ids::SET_REQUIRED_AVAILABILITY;
use super::payload::SmartrestPayload;

/// Create a SmartREST message for creating a child device under the given ancestors.
Expand Down Expand Up @@ -49,7 +52,7 @@ pub fn child_device_creation_message(
}

let payload = SmartrestPayload::serialize((
101,
CHILD_DEVICE_CREATION,
child_id,
device_name.unwrap_or(child_id),
device_type.unwrap_or("thin-edge.io-child"),
Expand Down Expand Up @@ -115,11 +118,16 @@ pub fn service_creation_message_payload(
});
}

let payload =
SmartrestPayload::serialize((102, service_id, service_type, service_name, service_status))
.expect(
"TODO: message can get over the limit but none of the fields can be reasonably trimmed",
);
let payload = SmartrestPayload::serialize((
SERVICE_CREATION,
service_id,
service_type,
service_name,
service_status,
))
.expect(
"TODO: message can get over the limit but none of the fields can be reasonably trimmed",
);

Ok(payload)
}
Expand All @@ -140,8 +148,9 @@ impl From<C8ySmartRestSetInterval117> for MqttMessage {
fn from(value: C8ySmartRestSetInterval117) -> Self {
let topic = value.c8y_topic.to_topic(&value.prefix).unwrap();
let interval_in_minutes = value.interval.as_secs() / 60;
let payload = SmartrestPayload::serialize((117, &interval_in_minutes))
.expect("interval should not increase size over the limit");
let payload =
SmartrestPayload::serialize((SET_REQUIRED_AVAILABILITY, &interval_in_minutes))
.expect("interval should not increase size over the limit");
MqttMessage::new(&topic, payload.into_inner())
}
}
Expand All @@ -152,8 +161,9 @@ impl From<C8ySmartRestSetInterval117> for MqttMessage {
/// When all individual operations are finished (i.e. firmware update, software
/// update and configuration update), the `profile_executed` field should be set
/// to `true`, otherwise it should be `false`.
pub fn set_c8y_profile_target_payload(profile_executed: bool) -> String {
fields_to_csv_string(["121", &profile_executed.to_string()])
pub fn set_c8y_profile_target_payload(profile_executed: bool) -> SmartrestPayload {
SmartrestPayload::serialize((SET_DEVICE_PROFILE_THAT_IS_BEING_APPLIED, profile_executed))
.expect("shouldn't put payload over size limit")
}

#[derive(thiserror::Error, Debug)]
Expand Down
107 changes: 107 additions & 0 deletions crates/core/c8y_api/src/smartrest/message_ids.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
//! Definitions of Smartrest MQTT message ids.
//!
//! - https://cumulocity.com/docs/smartrest/smartrest-one/#built-in-messages
//! - https://cumulocity.com/docs/smartrest/mqtt-static-templates/
// Message IDs

pub const ERROR: usize = 41;
pub const JWT_TOKEN: usize = 71;

// Static templates

// Publish templates

// Inventory templates (1xx)

pub const DEVICE_CREATION: usize = 100;
pub const CHILD_DEVICE_CREATION: usize = 101;
pub const SERVICE_CREATION: usize = 102;
pub const SERVICE_STATUS_UPDATE: usize = 104;
pub const GET_CHILD_DEVICES: usize = 105;
pub const CLEAR_DEVICE_FRAGMENT: usize = 107;
pub const CONFIGURE_HARDWARE: usize = 110;
pub const CONFIGURE_MOBILE: usize = 111;
pub const CONFIGURE_POSITION: usize = 112;
pub const SET_CONFIGURATION: usize = 113;
pub const SET_SUPPORTED_OPERATIONS: usize = 114;
pub const SET_FIRMWARE: usize = 115;
pub const SET_SOFTWARE_LIST: usize = 116;
pub const SET_REQUIRED_AVAILABILITY: usize = 117;
pub const SET_SUPPORTED_LOGS: usize = 118;
pub const SET_SUPPORTED_CONFIGURATIONS: usize = 119;
pub const SET_CURRENTLY_INSTALLED_CONFIGURATION: usize = 120;
pub const SET_DEVICE_PROFILE_THAT_IS_BEING_APPLIED: usize = 121;
pub const SET_DEVICE_AGENT_INFORMATION: usize = 122;
pub const GET_DEVICE_MANAGED_OBJECT_ID: usize = 123;
pub const SEND_HEARTBEAT: usize = 125;
pub const SET_ADVANCED_SOFTWARE_LIST: usize = 140;
pub const APPEND_ADVANCED_SOFTWARE_ITEMS: usize = 141;
pub const REMOVE_ADVANCED_SOFTWARE_ITEMS: usize = 142;
pub const SET_SUPPORTED_SOFTWARE_TYPES: usize = 143;
pub const SET_CLOUD_REMOTE_ACCESS: usize = 150;

// Measurement templates (2xx)

pub const CREATE_CUSTOM_MEASUREMENT: usize = 200;
pub const CREATE_A_CUSTOM_MEASUREMENT_WITH_MULTIPLE_FRAGMENTS_AND_SERIES: usize = 201;
pub const CREATE_SIGNAL_STRENGTH_MEASUREMENT: usize = 210;
pub const CREATE_TEMPERATURE_MEASUREMENT: usize = 211;
pub const CREATE_BATTERY_MEASUREMENT: usize = 212;

// Alarm templates (3xx)

pub const CREATE_CRITICAL_ALARM: usize = 301;
pub const CREATE_MAJOR_ALARM: usize = 302;
pub const CREATE_MINOR_ALARM: usize = 303;
pub const CREATE_WARNING_ALARM: usize = 304;
pub const UPDATE_SEVERITY_OF_EXISTING_ALARM: usize = 305;
pub const CLEAR_EXISTING_ALARM: usize = 306;
pub const CLEAR_ALARM_FRAGMENT: usize = 307;

// Event templates (4xx)

pub const CREATE_BASIC_EVENT: usize = 400;
pub const CREATE_LOCATION_UPDATE_EVENT: usize = 401;
pub const CREATE_LOCATION_UPDATE_EVENT_WITH_DEVICE_UPDATE: usize = 402;
pub const CLEAR_EVENT_FRAGMENT: usize = 407;

// Operation templates (5xx)

pub const GET_PENDING_OPERATIONS: usize = 500;
pub const SET_OPERATION_TO_EXECUTING: usize = 501;
pub const SET_OPERATION_TO_FAILED: usize = 502;
pub const SET_OPERATION_TO_SUCCESSFUL: usize = 503;
pub const SET_OPERATION_TO_EXECUTING_ID: usize = 504;
pub const SET_OPERATION_TO_FAILED_ID: usize = 505;
pub const SET_OPERATION_TO_SUCCESSFUL_ID: usize = 506;
pub const SET_EXECUTING_OPERATIONS_TO_FAILED: usize = 507;

// Subscribe templates

// Inventory templates (1xx)

pub const GET_CHILDREN_OF_DEVICE: usize = 106;
pub const GET_DEVICE_MANAGED_OBJECT_ID_RESPONSE: usize = 124;

// Operation templates (5xx)

pub const RESTART: usize = 510;
pub const COMMAND: usize = 511;
pub const CONFIGURATION: usize = 513;
pub const FIRMWARE: usize = 515;
pub const SOFTWARE_LIST: usize = 516;
pub const MEASUREMENT_REQUEST_OPERATION: usize = 517;
pub const RELAY: usize = 518;
pub const RELAY_ARRAY: usize = 519;
pub const UPLOAD_CONFIGURATION_FILE: usize = 520;
pub const DOWNLOAD_CONFIGURATION_FILE: usize = 521;
pub const LOGFILE_REQUEST: usize = 522;
pub const COMMUNICATION_MODE: usize = 523;
pub const DOWNLOAD_CONFIGURATION_FILE_WITH_TYPE: usize = 524;
pub const FIRMWARE_FROM_PATCH: usize = 525;
pub const UPLOAD_CONFIGURATION_FILE_WITH_TYPE: usize = 526;
pub const SET_DEVICE_PROFILES: usize = 527;
pub const UPDATE_SOFTWARE: usize = 528;
pub const UPDATE_ADVANCED_SOFTWARE: usize = 529;
pub const CLOUD_REMOTE_ACCESS_CONNECT: usize = 530;
1 change: 1 addition & 0 deletions crates/core/c8y_api/src/smartrest/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod csv;
pub mod error;
pub mod inventory;
pub mod message;
pub mod message_ids;
pub mod payload;
pub mod smartrest_deserializer;
pub mod smartrest_serializer;
Expand Down
5 changes: 4 additions & 1 deletion crates/core/c8y_api/src/smartrest/payload.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,12 @@ impl Display for SmartrestPayload {
mod tests {
use super::*;

use crate::smartrest::message_ids::SET_DEVICE_PROFILE_THAT_IS_BEING_APPLIED;

#[test]
fn serializes_payload() {
let payload = SmartrestPayload::serialize((121, true)).unwrap();
let payload =
SmartrestPayload::serialize((SET_DEVICE_PROFILE_THAT_IS_BEING_APPLIED, true)).unwrap();
assert_eq!(payload.as_str(), "121,true");
}

Expand Down
8 changes: 5 additions & 3 deletions crates/core/c8y_api/src/smartrest/smartrest_deserializer.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use super::message_ids::GET_CHILDREN_OF_DEVICE;
use super::message_ids::JWT_TOKEN;
use crate::smartrest::error::SmartRestDeserializerError;
use csv::ReaderBuilder;
use serde::de::Error;
Expand Down Expand Up @@ -136,7 +138,7 @@ pub struct SmartRestJwtResponse {
impl Default for SmartRestJwtResponse {
fn default() -> Self {
Self {
id: 71,
id: JWT_TOKEN as u16,
token: "".into(),
}
}
Expand All @@ -153,7 +155,7 @@ impl SmartRestJwtResponse {
jwt = result.unwrap();
}

if jwt.id != 71 {
if jwt.id != JWT_TOKEN as u16 {
return Err(SmartRestDeserializerError::InvalidMessageId(jwt.id));
}

Expand All @@ -177,7 +179,7 @@ impl SmartRestRequestGeneric for AvailableChildDevices {}
impl Default for AvailableChildDevices {
fn default() -> Self {
Self {
message_id: "106".into(),
message_id: GET_CHILDREN_OF_DEVICE.to_string(),
devices: Default::default(),
}
}
Expand Down
Loading

0 comments on commit 82cde40

Please sign in to comment.