From a76179042ef37dd9fb5fb4e043c8989937af1f31 Mon Sep 17 00:00:00 2001 From: Marcel Guzik Date: Wed, 4 Dec 2024 20:27:25 +0100 Subject: [PATCH 1/2] Create a module with smartrest message ids consts Signed-off-by: Marcel Guzik --- .../core/c8y_api/src/smartrest/message_ids.rs | 107 ++++++++++++++++++ crates/core/c8y_api/src/smartrest/mod.rs | 1 + 2 files changed, 108 insertions(+) create mode 100644 crates/core/c8y_api/src/smartrest/message_ids.rs diff --git a/crates/core/c8y_api/src/smartrest/message_ids.rs b/crates/core/c8y_api/src/smartrest/message_ids.rs new file mode 100644 index 00000000000..a1d6157346f --- /dev/null +++ b/crates/core/c8y_api/src/smartrest/message_ids.rs @@ -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; diff --git a/crates/core/c8y_api/src/smartrest/mod.rs b/crates/core/c8y_api/src/smartrest/mod.rs index 6bf38f3e77c..03525ad3bb5 100644 --- a/crates/core/c8y_api/src/smartrest/mod.rs +++ b/crates/core/c8y_api/src/smartrest/mod.rs @@ -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; From f0ff4f795bc978176d2f9045ce93afbe11a7fce7 Mon Sep 17 00:00:00 2001 From: Marcel Guzik Date: Wed, 4 Dec 2024 20:32:33 +0100 Subject: [PATCH 2/2] Replace smartrest message id magic numbers with consts from c8y_api Usage of the magic numbers was replaced with using the consts where it could be done trivially, i.e. when these magic numbers were not parts of string literals where replacing them would add a lot of code, which mainly happens to be in the unit tests. Signed-off-by: Marcel Guzik --- crates/core/c8y_api/src/smartrest/alarm.rs | 19 ++++--- .../core/c8y_api/src/smartrest/inventory.rs | 32 +++++++---- crates/core/c8y_api/src/smartrest/payload.rs | 5 +- .../src/smartrest/smartrest_deserializer.rs | 8 +-- .../src/smartrest/smartrest_serializer.rs | 53 +++++++++++-------- crates/core/c8y_api/src/utils.rs | 3 +- .../src/cli/connect/c8y_direct_connection.rs | 3 +- crates/core/tedge/src/cli/connect/command.rs | 8 +-- .../c8y_firmware_manager/src/actor.rs | 26 +++++---- .../c8y_firmware_manager/src/tests.rs | 3 +- .../c8y_firmware_manager/src/worker.rs | 6 ++- .../c8y_mapper_ext/src/operations/convert.rs | 6 ++- 12 files changed, 107 insertions(+), 65 deletions(-) diff --git a/crates/core/c8y_api/src/smartrest/alarm.rs b/crates/core/c8y_api/src/smartrest/alarm.rs index fff630283c6..51bfcc011bb 100644 --- a/crates/core/c8y_api/src/smartrest/alarm.rs +++ b/crates/core/c8y_api/src/smartrest/alarm.rs @@ -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; @@ -9,21 +10,23 @@ pub fn serialize_alarm(c8y_alarm: &C8yAlarm) -> Result { 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) } diff --git a/crates/core/c8y_api/src/smartrest/inventory.rs b/crates/core/c8y_api/src/smartrest/inventory.rs index f46198283ac..e48a2c46bd8 100644 --- a/crates/core/c8y_api/src/smartrest/inventory.rs +++ b/crates/core/c8y_api/src/smartrest/inventory.rs @@ -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. @@ -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"), @@ -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) } @@ -140,8 +148,9 @@ impl From 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()) } } @@ -152,8 +161,9 @@ impl From 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)] diff --git a/crates/core/c8y_api/src/smartrest/payload.rs b/crates/core/c8y_api/src/smartrest/payload.rs index 345c0165c38..3f7f46f2aff 100644 --- a/crates/core/c8y_api/src/smartrest/payload.rs +++ b/crates/core/c8y_api/src/smartrest/payload.rs @@ -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"); } diff --git a/crates/core/c8y_api/src/smartrest/smartrest_deserializer.rs b/crates/core/c8y_api/src/smartrest/smartrest_deserializer.rs index ee5b5f545c9..27070d758fd 100644 --- a/crates/core/c8y_api/src/smartrest/smartrest_deserializer.rs +++ b/crates/core/c8y_api/src/smartrest/smartrest_deserializer.rs @@ -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; @@ -136,7 +138,7 @@ pub struct SmartRestJwtResponse { impl Default for SmartRestJwtResponse { fn default() -> Self { Self { - id: 71, + id: JWT_TOKEN as u16, token: "".into(), } } @@ -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)); } @@ -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(), } } diff --git a/crates/core/c8y_api/src/smartrest/smartrest_serializer.rs b/crates/core/c8y_api/src/smartrest/smartrest_serializer.rs index b572922eb6b..dd5a46bd7dd 100644 --- a/crates/core/c8y_api/src/smartrest/smartrest_serializer.rs +++ b/crates/core/c8y_api/src/smartrest/smartrest_serializer.rs @@ -10,35 +10,38 @@ use tedge_api::SoftwareListCommand; use tedge_api::SoftwareModule; use tracing::warn; +use super::message_ids::*; + pub type SmartRest = String; -pub fn request_pending_operations() -> &'static str { - "500" +pub fn request_pending_operations() -> SmartrestPayload { + SmartrestPayload::serialize(GET_PENDING_OPERATIONS) + .expect("shouldn't put payload over size limit") } /// Generates a SmartREST message to set the provided operation to executing pub fn set_operation_executing_with_name(operation: impl C8yOperation) -> SmartrestPayload { - SmartrestPayload::serialize(("501", operation.name())) + SmartrestPayload::serialize((SET_OPERATION_TO_EXECUTING, operation.name())) .expect("operation name shouldn't put payload over size limit") } /// Generates a SmartREST message to set the provided operation ID to executing pub fn set_operation_executing_with_id(op_id: &str) -> SmartrestPayload { - SmartrestPayload::serialize(("504", op_id)) + SmartrestPayload::serialize((SET_OPERATION_TO_EXECUTING_ID, op_id)) .expect("op_id shouldn't put payload over size limit") } /// Generates a SmartREST message to set the provided operation to failed with the provided reason pub fn fail_operation_with_name(operation: impl C8yOperation, reason: &str) -> SmartrestPayload { - fail_operation("502", operation.name(), reason) + fail_operation(SET_OPERATION_TO_FAILED, operation.name(), reason) } /// Generates a SmartREST message to set the provided operation ID to failed with the provided reason pub fn fail_operation_with_id(op_id: &str, reason: &str) -> SmartrestPayload { - fail_operation("505", op_id, reason) + fail_operation(SET_OPERATION_TO_FAILED_ID, op_id, reason) } -fn fail_operation(template_id: &str, operation: &str, reason: &str) -> SmartrestPayload { +fn fail_operation(template_id: usize, operation: &str, reason: &str) -> SmartrestPayload { // If the failure reason exceeds 500 bytes, truncate it if reason.len() <= 500 { SmartrestPayload::serialize((template_id, operation, reason)) @@ -62,7 +65,7 @@ pub fn succeed_static_operation_with_name( operation: CumulocitySupportedOperations, payload: Option>, ) -> SmartrestPayload { - succeed_static_operation("503", operation.name(), payload) + succeed_static_operation(SET_OPERATION_TO_SUCCESSFUL, operation.name(), payload) } /// Generates a SmartREST message to set the provided operation ID to successful without a payload @@ -75,11 +78,11 @@ pub fn succeed_static_operation_with_id( op_id: &str, payload: Option>, ) -> SmartrestPayload { - succeed_static_operation("506", op_id, payload) + succeed_static_operation(SET_OPERATION_TO_SUCCESSFUL_ID, op_id, payload) } fn succeed_static_operation( - template_id: &str, + template_id: usize, operation: &str, payload: Option>, ) -> SmartrestPayload { @@ -106,7 +109,7 @@ fn succeed_static_operation( /// # Errors /// This will return an error if the payload is a CSV with multiple records, or an empty CSV. pub fn succeed_operation( - template_id: &str, + template_id: usize, operation: &str, reason: impl Into, ) -> Result { @@ -123,7 +126,9 @@ pub fn succeed_operation( } // payload too big, need to trim - let prefix = super::csv::fields_to_csv_string([template_id, operation]); + let prefix = SmartrestPayload::serialize((template_id, operation)) + .unwrap() + .into_inner(); let trim_indicator = "..."; @@ -165,14 +170,14 @@ pub fn succeed_operation_with_name( operation: &str, reason: impl Into, ) -> Result { - succeed_operation("503", operation, reason) + succeed_operation(SET_OPERATION_TO_SUCCESSFUL, operation, reason) } pub fn succeed_operation_with_id( operation: &str, reason: impl Into, ) -> Result { - succeed_operation("506", operation, reason) + succeed_operation(SET_OPERATION_TO_SUCCESSFUL_ID, operation, reason) } #[derive(Debug, Clone)] @@ -203,7 +208,8 @@ impl CumulocitySupportedOperations { } pub fn declare_supported_operations(ops: &[&str]) -> SmartrestPayload { - SmartrestPayload::serialize((114, ops)).expect("TODO: ops list can increase payload over limit") + SmartrestPayload::serialize((SET_SUPPORTED_OPERATIONS, ops)) + .expect("TODO: ops list can increase payload over limit") } #[derive(Debug, Clone, PartialEq)] @@ -238,17 +244,21 @@ pub enum AdvancedSoftwareList { impl AdvancedSoftwareList { fn smartrest_payload(self) -> String { let vec = match self { - AdvancedSoftwareList::Set(items) => Self::create_software_list("140", items), - AdvancedSoftwareList::Append(items) => Self::create_software_list("141", items), + AdvancedSoftwareList::Set(items) => { + Self::create_software_list(SET_ADVANCED_SOFTWARE_LIST, items) + } + AdvancedSoftwareList::Append(items) => { + Self::create_software_list(APPEND_ADVANCED_SOFTWARE_ITEMS, items) + } }; let list: Vec<&str> = vec.iter().map(std::ops::Deref::deref).collect(); fields_to_csv_string(list.as_slice()) } - fn create_software_list(id: &str, items: Vec) -> Vec { + fn create_software_list(id: usize, items: Vec) -> Vec { if items.is_empty() { - vec![id.into(), "".into(), "".into(), "".into(), "".into()] + vec![id.to_string(), "".into(), "".into(), "".into(), "".into()] } else { let mut vec = vec![id.to_string()]; for item in items { @@ -408,7 +418,7 @@ mod tests { #[test] fn serialize_smartrest_get_pending_operations() { let smartrest = request_pending_operations(); - assert_eq!(smartrest, "500"); + assert_eq!(smartrest.as_str(), "500"); } #[test] @@ -639,7 +649,8 @@ mod tests { let mut reason: String = "a".repeat(message_len - prefix_len - 2); reason.push('"'); - let smartrest = succeed_operation("503", "c8y_Command", reason).unwrap(); + let smartrest = + succeed_operation(SET_OPERATION_TO_SUCCESSFUL, "c8y_Command", reason).unwrap(); // assert message is under size limit and has expected structure assert!( diff --git a/crates/core/c8y_api/src/utils.rs b/crates/core/c8y_api/src/utils.rs index 9a8108480c7..ff1ae5f9c57 100644 --- a/crates/core/c8y_api/src/utils.rs +++ b/crates/core/c8y_api/src/utils.rs @@ -1,4 +1,5 @@ pub mod child_device { + use crate::smartrest::message_ids::CHILD_DEVICE_CREATION; use crate::smartrest::topic::C8yTopic; use mqtt_channel::MqttMessage; use tedge_config::TopicPrefix; @@ -6,7 +7,7 @@ pub mod child_device { pub fn new_child_device_message(child_id: &str, prefix: &TopicPrefix) -> MqttMessage { MqttMessage::new( &C8yTopic::upstream_topic(prefix), - format!("101,{child_id},{child_id},thin-edge.io-child"), + format!("{CHILD_DEVICE_CREATION},{child_id},{child_id},thin-edge.io-child"), ) } } diff --git a/crates/core/tedge/src/cli/connect/c8y_direct_connection.rs b/crates/core/tedge/src/cli/connect/c8y_direct_connection.rs index 8ae941de2db..6a1bff353d6 100644 --- a/crates/core/tedge/src/cli/connect/c8y_direct_connection.rs +++ b/crates/core/tedge/src/cli/connect/c8y_direct_connection.rs @@ -146,12 +146,13 @@ fn publish_device_create_message( device_id: &str, device_type: &str, ) -> Result<(), ConnectError> { + use c8y_api::smartrest::message_ids::DEVICE_CREATION; const DEVICE_CREATE_PUBLISH_TOPIC: &str = "s/us"; client.publish( DEVICE_CREATE_PUBLISH_TOPIC, QoS::ExactlyOnce, false, - format!("100,{},{}", device_id, device_type).as_bytes(), + format!("{DEVICE_CREATION},{},{}", device_id, device_type).as_bytes(), )?; Ok(()) } diff --git a/crates/core/tedge/src/cli/connect/command.rs b/crates/core/tedge/src/cli/connect/command.rs index dacbc8d2a61..fbc3922d1e7 100644 --- a/crates/core/tedge/src/cli/connect/command.rs +++ b/crates/core/tedge/src/cli/connect/command.rs @@ -18,6 +18,8 @@ use crate::ConfigError; use anyhow::anyhow; use anyhow::bail; use c8y_api::http_proxy::read_c8y_credentials; +use c8y_api::smartrest::message::get_smartrest_template_id; +use c8y_api::smartrest::message_ids::JWT_TOKEN; use camino::Utf8PathBuf; use mqtt_channel::Topic; use rumqttc::Event; @@ -507,9 +509,9 @@ fn check_device_status_c8y( Ok(Event::Incoming(Packet::Publish(response))) => { if response.topic == c8y_topic_builtin_jwt_token_downstream { // We got a response - let token = String::from_utf8(response.payload.to_vec()).unwrap(); - // FIXME: what does this magic number mean? - if token.contains("71") { + let response = std::str::from_utf8(&response.payload).unwrap(); + let message_id = get_smartrest_template_id(response); + if message_id.parse() == Ok(JWT_TOKEN) { break; } } else if is_bridge_health_up_message(&response, &built_in_bridge_health) { diff --git a/crates/extensions/c8y_firmware_manager/src/actor.rs b/crates/extensions/c8y_firmware_manager/src/actor.rs index 80a16cd6430..00869fd3441 100644 --- a/crates/extensions/c8y_firmware_manager/src/actor.rs +++ b/crates/extensions/c8y_firmware_manager/src/actor.rs @@ -10,6 +10,7 @@ use crate::worker::OperationOutcome; use async_trait::async_trait; use c8y_api::smartrest::message::collect_smartrest_messages; use c8y_api::smartrest::message::get_smartrest_template_id; +use c8y_api::smartrest::message_ids::FIRMWARE; use c8y_api::smartrest::smartrest_deserializer::SmartRestFirmwareRequest; use c8y_api::smartrest::smartrest_deserializer::SmartRestRequestGeneric; use log::error; @@ -131,18 +132,21 @@ impl FirmwareManagerActor { message: MqttMessage, ) -> Result<(), FirmwareManagementError> { for smartrest_message in collect_smartrest_messages(message.payload_str()?) { - let result = match get_smartrest_template_id(&smartrest_message).as_str() { - "515" => match SmartRestFirmwareRequest::from_smartrest(&smartrest_message) { - Ok(firmware_request) => { - // Addressing a new firmware operation to further step. - self.handle_firmware_download_request(firmware_request) - .await - } - Err(_) => { - error!("Incorrect c8y_Firmware SmartREST payload: {smartrest_message}"); - Ok(()) + let smartrest_template_id = get_smartrest_template_id(&smartrest_message); + let result = match smartrest_template_id.as_str().parse::() { + Ok(id) if id == FIRMWARE => { + match SmartRestFirmwareRequest::from_smartrest(&smartrest_message) { + Ok(firmware_request) => { + // Addressing a new firmware operation to further step. + self.handle_firmware_download_request(firmware_request) + .await + } + Err(_) => { + error!("Incorrect c8y_Firmware SmartREST payload: {smartrest_message}"); + Ok(()) + } } - }, + } _ => { // Ignore operation messages not meant for this plugin Ok(()) diff --git a/crates/extensions/c8y_firmware_manager/src/tests.rs b/crates/extensions/c8y_firmware_manager/src/tests.rs index 16369135eb9..8c91abad758 100644 --- a/crates/extensions/c8y_firmware_manager/src/tests.rs +++ b/crates/extensions/c8y_firmware_manager/src/tests.rs @@ -3,6 +3,7 @@ use assert_json_diff::assert_json_include; use c8y_api::http_proxy::C8yEndPoint; use c8y_api::proxy_url::Protocol; use c8y_api::proxy_url::ProxyUrlGenerator; +use c8y_api::smartrest::message_ids::FIRMWARE; use c8y_api::smartrest::topic::C8yTopic; use serde_json::json; use sha256::digest; @@ -575,7 +576,7 @@ async fn publish_smartrest_firmware_operation( ) -> Result<(), DynError> { let c8y_firmware_update_msg = MqttMessage::new( &Topic::new_unchecked("c8y/s/ds"), - format!("515,{CHILD_DEVICE_ID},{FIRMWARE_NAME},{FIRMWARE_VERSION},{DOWNLOAD_URL}"), + format!("{FIRMWARE},{CHILD_DEVICE_ID},{FIRMWARE_NAME},{FIRMWARE_VERSION},{DOWNLOAD_URL}"), ); mqtt_message_box.send(c8y_firmware_update_msg).await?; Ok(()) diff --git a/crates/extensions/c8y_firmware_manager/src/worker.rs b/crates/extensions/c8y_firmware_manager/src/worker.rs index 09c9cdb11f3..786e806b333 100644 --- a/crates/extensions/c8y_firmware_manager/src/worker.rs +++ b/crates/extensions/c8y_firmware_manager/src/worker.rs @@ -5,6 +5,7 @@ use crate::mpsc; use crate::operation::FirmwareOperationEntry; use crate::operation::OperationKey; use crate::FirmwareManagerConfig; +use c8y_api::smartrest::message_ids::GET_PENDING_OPERATIONS; use c8y_api::smartrest::smartrest_deserializer::SmartRestFirmwareRequest; use c8y_api::smartrest::smartrest_serializer::fail_operation_with_name; use c8y_api::smartrest::smartrest_serializer::set_operation_executing_with_name; @@ -398,10 +399,11 @@ impl FirmwareManagerWorker { &mut self, operation_entry: &FirmwareOperationEntry, ) -> Result<(), FirmwareManagementError> { + use c8y_api::smartrest::message_ids::SET_FIRMWARE; let c8y_child_topic = C8yTopic::ChildSmartRestResponse(operation_entry.child_id.clone()) .to_topic(&self.config.c8y_prefix)?; let installed_firmware_payload = format!( - "115,{},{},{}", + "{SET_FIRMWARE},{},{},{}", operation_entry.name, operation_entry.version, operation_entry.server_url ); let installed_firmware_message = @@ -437,7 +439,7 @@ impl FirmwareManagerWorker { ) -> Result<(), FirmwareManagementError> { let message = MqttMessage::new( &C8yTopic::SmartRestResponse.to_topic(&self.config.c8y_prefix)?, - "500", + GET_PENDING_OPERATIONS.to_string(), ); self.mqtt_publisher.send(message).await?; Ok(()) diff --git a/crates/extensions/c8y_mapper_ext/src/operations/convert.rs b/crates/extensions/c8y_mapper_ext/src/operations/convert.rs index de1a56ebd56..fab5f996e76 100644 --- a/crates/extensions/c8y_mapper_ext/src/operations/convert.rs +++ b/crates/extensions/c8y_mapper_ext/src/operations/convert.rs @@ -5,6 +5,8 @@ use c8y_api::json_c8y_deserializer::C8yDownloadConfigFile; use c8y_api::json_c8y_deserializer::C8yFirmware; use c8y_api::json_c8y_deserializer::C8yLogfileRequest; use c8y_api::json_c8y_deserializer::C8yUploadConfigFile; +use c8y_api::smartrest::message_ids::SET_SUPPORTED_CONFIGURATIONS; +use c8y_api::smartrest::message_ids::SET_SUPPORTED_LOGS; use serde_json::Value; use std::sync::Arc; use tedge_api::commands::CommandStatus; @@ -173,7 +175,7 @@ impl CumulocityConverter { let mut types = metadata.types; types.sort(); let supported_log_types = types.join(","); - let payload = format!("118,{supported_log_types}"); + let payload = format!("{SET_SUPPORTED_LOGS},{supported_log_types}"); let c8y_topic = self.smartrest_publish_topic_for_entity(topic_id)?; messages.push(MqttMessage::new(&c8y_topic, payload)); @@ -306,7 +308,7 @@ impl CumulocityConverter { let mut types = metadata.types; types.sort(); let supported_config_types = types.join(","); - let payload = format!("119,{supported_config_types}"); + let payload = format!("{SET_SUPPORTED_CONFIGURATIONS},{supported_config_types}"); let sm_topic = self.smartrest_publish_topic_for_entity(topic_id)?; messages.push(MqttMessage::new(&sm_topic, payload));