From a927e404d2e3dbdeb767a555e6f983943d62868e Mon Sep 17 00:00:00 2001 From: Marcel Guzik Date: Mon, 16 Dec 2024 22:16:47 +0100 Subject: [PATCH 1/2] Revert "Rename `collect_smartrest_messages` to `collect_c8y_messages`" This reverts commit 6748f0e7c9212514424d4a577491d136a6793aa9. --- crates/core/c8y_api/src/smartrest/message.rs | 10 +++++----- crates/extensions/c8y_firmware_manager/src/actor.rs | 4 ++-- crates/extensions/c8y_mapper_ext/src/converter.rs | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/crates/core/c8y_api/src/smartrest/message.rs b/crates/core/c8y_api/src/smartrest/message.rs index 0e1b68452d6..b466789ed25 100644 --- a/crates/core/c8y_api/src/smartrest/message.rs +++ b/crates/core/c8y_api/src/smartrest/message.rs @@ -78,13 +78,13 @@ pub fn get_failure_reason_for_smartrest(input: &[u8], max_size: usize) -> String /// Split MQTT message payload to multiple SmartREST messages. /// /// ``` -/// use c8y_api::smartrest::message::collect_c8y_messages; +/// use c8y_api::smartrest::message::collect_smartrest_messages; /// let data = "511,device,echo hello\n511,device,\"echo hello\necho world\""; -/// let messages = collect_c8y_messages(data); +/// let messages = collect_smartrest_messages(data); /// assert_eq!(messages[0], "511,device,echo hello"); /// assert_eq!(messages[1], "511,device,\"echo hello\necho world\""); /// ``` -pub fn collect_c8y_messages(data: &str) -> Vec { +pub fn collect_smartrest_messages(data: &str) -> Vec { let mut stack: Vec = Vec::new(); let mut smartrest_messages: Vec = Vec::new(); let mut is_inside = false; // Inside an outermost double quote block or not. @@ -228,7 +228,7 @@ mod tests { #[test] fn split_single_smartrest_message() { let data = r#"528,DeviceSerial,softwareA,1.0,url1,install,softwareB,2.0,url2,install"#; - let message = collect_c8y_messages(data); + let message = collect_smartrest_messages(data); assert_eq!( message[0], r#"528,DeviceSerial,softwareA,1.0,url1,install,softwareB,2.0,url2,install"# @@ -250,7 +250,7 @@ echo world" 524,DeviceSerial,"something",http://www.my.url,type 511,device,511,rina0005,echo \\\"#; - let messages = collect_c8y_messages(data); + let messages = collect_smartrest_messages(data); assert_eq!(messages[0], r#"511,device,echo hello"#); assert_eq!( diff --git a/crates/extensions/c8y_firmware_manager/src/actor.rs b/crates/extensions/c8y_firmware_manager/src/actor.rs index 3d886c7a2ba..00869fd3441 100644 --- a/crates/extensions/c8y_firmware_manager/src/actor.rs +++ b/crates/extensions/c8y_firmware_manager/src/actor.rs @@ -8,7 +8,7 @@ use crate::worker::IdDownloadRequest; use crate::worker::IdDownloadResult; use crate::worker::OperationOutcome; use async_trait::async_trait; -use c8y_api::smartrest::message::collect_c8y_messages; +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; @@ -131,7 +131,7 @@ impl FirmwareManagerActor { &mut self, message: MqttMessage, ) -> Result<(), FirmwareManagementError> { - for smartrest_message in collect_c8y_messages(message.payload_str()?) { + for smartrest_message in collect_smartrest_messages(message.payload_str()?) { let smartrest_template_id = get_smartrest_template_id(&smartrest_message); let result = match smartrest_template_id.as_str().parse::() { Ok(id) if id == FIRMWARE => { diff --git a/crates/extensions/c8y_mapper_ext/src/converter.rs b/crates/extensions/c8y_mapper_ext/src/converter.rs index 0e8adce2dee..f02fba41cfc 100644 --- a/crates/extensions/c8y_mapper_ext/src/converter.rs +++ b/crates/extensions/c8y_mapper_ext/src/converter.rs @@ -28,7 +28,7 @@ use c8y_api::json_c8y_deserializer::C8ySoftwareUpdate; use c8y_api::smartrest::error::SmartRestDeserializerError; use c8y_api::smartrest::inventory::child_device_creation_message; use c8y_api::smartrest::inventory::service_creation_message; -use c8y_api::smartrest::message::collect_c8y_messages; +use c8y_api::smartrest::message::collect_smartrest_messages; use c8y_api::smartrest::message::get_failure_reason_for_smartrest; use c8y_api::smartrest::message::get_smartrest_device_id; use c8y_api::smartrest::message::get_smartrest_template_id; @@ -634,7 +634,7 @@ impl CumulocityConverter { ) -> Result, ConversionError> { // JSON over MQTT messages on c8y/devicecontrol/notifications can contain multiple operations in a single MQTT // message, so split them - let operation_payloads = collect_c8y_messages(message.payload_str()?); + let operation_payloads = collect_smartrest_messages(message.payload_str()?); let mut output = vec![]; for operation_payload in operation_payloads { @@ -884,7 +884,7 @@ impl CumulocityConverter { message: &MqttMessage, ) -> Result, ConversionError> { let mut output: Vec = Vec::new(); - for smartrest_message in collect_c8y_messages(message.payload_str()?) { + for smartrest_message in collect_smartrest_messages(message.payload_str()?) { let result = self.process_smartrest(smartrest_message.as_str()).await; let mut msgs = self.handle_c8y_operation_result(&result, None); output.append(&mut msgs) From 9eee7cebf065318fe20b3b0c6452e06f6734316f Mon Sep 17 00:00:00 2001 From: Marcel Guzik Date: Mon, 16 Dec 2024 22:18:22 +0100 Subject: [PATCH 2/2] Simply split JSON over MQTT over \n Instead of using a function made for splitting smartrest, just split on \n since that function will unescape \" sequences which we want to do in smartrest but avoid in JSON over MQTT. Signed-off-by: Marcel Guzik --- .../c8y_mapper_ext/src/converter.rs | 4 +-- crates/extensions/c8y_mapper_ext/src/tests.rs | 26 ++++++++++++++----- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/crates/extensions/c8y_mapper_ext/src/converter.rs b/crates/extensions/c8y_mapper_ext/src/converter.rs index f02fba41cfc..d8daa339cab 100644 --- a/crates/extensions/c8y_mapper_ext/src/converter.rs +++ b/crates/extensions/c8y_mapper_ext/src/converter.rs @@ -634,11 +634,11 @@ impl CumulocityConverter { ) -> Result, ConversionError> { // JSON over MQTT messages on c8y/devicecontrol/notifications can contain multiple operations in a single MQTT // message, so split them - let operation_payloads = collect_smartrest_messages(message.payload_str()?); + let operation_payloads = message.payload_str()?.lines(); let mut output = vec![]; for operation_payload in operation_payloads { - let operation = C8yOperation::from_json(operation_payload.as_str())?; + let operation = C8yOperation::from_json(operation_payload)?; let device_xid = operation.external_source.external_id; let cmd_id = self.command_id.new_id_with_str(&operation.op_id); diff --git a/crates/extensions/c8y_mapper_ext/src/tests.rs b/crates/extensions/c8y_mapper_ext/src/tests.rs index 4996e5cfae0..a944ae8b689 100644 --- a/crates/extensions/c8y_mapper_ext/src/tests.rs +++ b/crates/extensions/c8y_mapper_ext/src/tests.rs @@ -2047,7 +2047,7 @@ async fn json_custom_operation_status_multiple_operations_in_one_mqtt_message() "status":"PENDING", "id": "111", "c8y_Command": { - "text": "do something 1" + "text": "do something \"1\"" }, "externalSource":{ "externalId":"test-device", @@ -2059,7 +2059,7 @@ async fn json_custom_operation_status_multiple_operations_in_one_mqtt_message() "status":"PENDING", "id": "222", "c8y_Command": { - "text": "do something 2" + "text": "do something \"2\"" }, "externalSource":{ "externalId":"test-device", @@ -2071,7 +2071,7 @@ async fn json_custom_operation_status_multiple_operations_in_one_mqtt_message() "status":"PENDING", "id": "333", "c8y_Command": { - "text": "do something 3" + "text": "do something \"3\"" }, "externalSource":{ "externalId":"test-device", @@ -2090,9 +2090,23 @@ async fn json_custom_operation_status_multiple_operations_in_one_mqtt_message() assert_received_contains_str(&mut mqtt, [("c8y/s/us", "504,222")]).await; assert_received_contains_str(&mut mqtt, [("c8y/s/us", "504,333")]).await; - assert_received_contains_str(&mut mqtt, [("c8y/s/us", "506,111,\"do something 1\n\"")]).await; - assert_received_contains_str(&mut mqtt, [("c8y/s/us", "506,222,\"do something 2\n\"")]).await; - assert_received_contains_str(&mut mqtt, [("c8y/s/us", "506,333,\"do something 3\n\"")]).await; + // escapes: we input JSON over MQTT, but emit Smartrest, thus initial: `do something "1"` becomes `"do something + // ""1""\n"` (outer "" for the Smartrest record field, and then inside double quotes escape a single quote) + assert_received_contains_str( + &mut mqtt, + [("c8y/s/us", "506,111,\"do something \"\"1\"\"\n\"")], + ) + .await; + assert_received_contains_str( + &mut mqtt, + [("c8y/s/us", "506,222,\"do something \"\"2\"\"\n\"")], + ) + .await; + assert_received_contains_str( + &mut mqtt, + [("c8y/s/us", "506,333,\"do something \"\"3\"\"\n\"")], + ) + .await; } #[tokio::test]