diff options
author | Albin Suresh <albin.suresh@softwareag.com> | 2021-12-22 15:02:24 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-12-22 15:02:24 +0530 |
commit | 0d61811849ce9931b91b65a7e94865d99f4bb394 (patch) | |
tree | 5b6e2b4d3d44be2f1256842fb4b9d16c9e7ca2df /crates/core/c8y_smartrest | |
parent | 888a4e70ca44d9b41d645148b7a24d89a984da7c (diff) |
Closes #667 Thin Edge JSON alarm support (#726)
* Closes #667 Thin Edge JSON alarm support
Diffstat (limited to 'crates/core/c8y_smartrest')
-rw-r--r-- | crates/core/c8y_smartrest/Cargo.toml | 2 | ||||
-rw-r--r-- | crates/core/c8y_smartrest/src/alarm.rs | 137 | ||||
-rw-r--r-- | crates/core/c8y_smartrest/src/error.rs | 3 | ||||
-rw-r--r-- | crates/core/c8y_smartrest/src/lib.rs | 1 |
4 files changed, 143 insertions, 0 deletions
diff --git a/crates/core/c8y_smartrest/Cargo.toml b/crates/core/c8y_smartrest/Cargo.toml index 8b91157b..f98f0d34 100644 --- a/crates/core/c8y_smartrest/Cargo.toml +++ b/crates/core/c8y_smartrest/Cargo.toml @@ -5,6 +5,8 @@ authors = ["thin-edge.io team <info@thin-edge.io>"] edition = "2018" [dependencies] +thin_edge_json = { path = "../thin_edge_json" } +time = { version = "0.3", features = ["macros"] } chrono = { version = "0.4", features = ["serde"] } csv = "1.1" json_sm = { path = "../json_sm" } diff --git a/crates/core/c8y_smartrest/src/alarm.rs b/crates/core/c8y_smartrest/src/alarm.rs new file mode 100644 index 00000000..630debe9 --- /dev/null +++ b/crates/core/c8y_smartrest/src/alarm.rs @@ -0,0 +1,137 @@ +use thin_edge_json::alarm::{AlarmSeverity, ThinEdgeAlarm}; +use time::{format_description::well_known::Rfc3339, OffsetDateTime}; + +use crate::error::SmartRestSerializerError; + +/// Converts from thin-edge alarm to C8Y alarm SmartREST message +pub fn serialize_alarm(alarm: ThinEdgeAlarm) -> Result<String, SmartRestSerializerError> { + match alarm.data { + None => Ok(format!("306,{}", alarm.name)), + Some(alarm_data) => { + let smartrest_code = match alarm.severity { + AlarmSeverity::Critical => 301, + AlarmSeverity::Major => 302, + AlarmSeverity::Minor => 303, + AlarmSeverity::Warning => 304, + }; + + let current_timestamp = OffsetDateTime::now_utc(); + + let smartrest_message = format!( + "{},{},\"{}\",{}", + smartrest_code, + alarm.name, + alarm_data.message.unwrap_or_default(), + alarm_data.time.map_or_else( + || current_timestamp.format(&Rfc3339), + |timestamp| timestamp.format(&Rfc3339) + )? + ); + + Ok(smartrest_message) + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use assert_matches::assert_matches; + use serde::Deserialize; + use test_case::test_case; + use thin_edge_json::alarm::ThinEdgeAlarmData; + use time::macros::datetime; + + #[test_case( + ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Critical, + data: Some(ThinEdgeAlarmData { + message: Some("I raised it".into()), + time: Some(datetime!(2021-04-23 19:00:00 +05:00)), + }), + }, + "301,temperature_alarm,\"I raised it\",2021-04-23T19:00:00+05:00" + ;"critical alarm translation" + )] + #[test_case( + ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Major, + data: Some(ThinEdgeAlarmData { + message: Some("I raised it".into()), + time: Some(datetime!(2021-04-23 19:00:00 +05:00)), + }), + }, + "302,temperature_alarm,\"I raised it\",2021-04-23T19:00:00+05:00" + ;"major alarm translation" + )] + #[test_case( + ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Minor, + data: Some(ThinEdgeAlarmData { + message: None, + time: Some(datetime!(2021-04-23 19:00:00 +05:00)), + }), + }, + "303,temperature_alarm,\"\",2021-04-23T19:00:00+05:00" + ;"minor alarm translation without message" + )] + #[test_case( + ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Warning, + data: Some(ThinEdgeAlarmData { + message: Some("I, raised, it".into()), + time: Some(datetime!(2021-04-23 19:00:00 +05:00)), + }), + }, + "304,temperature_alarm,\"I, raised, it\",2021-04-23T19:00:00+05:00" + ;"warning alarm translation with commas in message" + )] + #[test_case( + ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Minor, + data: None, + }, + "306,temperature_alarm" + ;"clear alarm translation" + )] + fn check_alarm_translation(alarm: ThinEdgeAlarm, expected_smartrest_msg: &str) { + let result = serialize_alarm(alarm); + + assert_eq!(result.unwrap(), expected_smartrest_msg); + } + + #[derive(Debug, Deserialize)] + struct SmartRestAlarm { + pub code: i32, + pub name: String, + pub message: Option<String>, + pub time: Option<OffsetDateTime>, + } + + #[test] + fn alarm_translation_empty_json_payload_generates_timestamp() { + let alarm = ThinEdgeAlarm { + name: "temperature_alarm".into(), + severity: AlarmSeverity::Warning, + data: Some(ThinEdgeAlarmData { + message: Some("I raised it".into()), + time: None, + }), + }; + + let smartrest_message = serialize_alarm(alarm).unwrap(); + let mut reader = csv::Reader::from_reader(smartrest_message.as_bytes()); + for result in reader.deserialize() { + let smartrest_alarm: SmartRestAlarm = result.unwrap(); + assert_eq!(smartrest_alarm.code, 301); + assert_eq!(smartrest_alarm.name, "empty_alarm".to_string()); + assert_eq!(smartrest_alarm.message, None); + assert_matches!(smartrest_alarm.time, Some(_)) + } + } +} diff --git a/crates/core/c8y_smartrest/src/error.rs b/crates/core/c8y_smartrest/src/error.rs index 4539ac02..d7463c1a 100644 --- a/crates/core/c8y_smartrest/src/error.rs +++ b/crates/core/c8y_smartrest/src/error.rs @@ -13,6 +13,9 @@ pub enum SmartRestSerializerError { #[error(transparent)] FromUtf8Error(#[from] std::string::FromUtf8Error), + + #[error(transparent)] + FromTimeFormatError(#[from] time::error::Format), } #[derive(thiserror::Error, Debug)] diff --git a/crates/core/c8y_smartrest/src/lib.rs b/crates/core/c8y_smartrest/src/lib.rs index 596af9be..4479f304 100644 --- a/crates/core/c8y_smartrest/src/lib.rs +++ b/crates/core/c8y_smartrest/src/lib.rs @@ -1,3 +1,4 @@ +pub mod alarm; pub mod error; pub mod smartrest_deserializer; pub mod smartrest_serializer; |