Skip to main content

cimstructs/
Quality61850.rs

1/// Quality flags in this class are as defined in IEC 61850, except for estimatorReplaced, which has been included in this class for convenience.
2#[derive(Debug, Default, Clone, serde::Serialize, serde::Deserialize)]
3pub struct Quality61850 {
4    pub id: String,
5    /// Measurement value may be incorrect due to a reference being out of calibration.
6    #[serde(skip_serializing_if = "Option::is_none")]
7    pub bad_reference: Option<bool>,
8    /// Value has been replaced by State Estimator. estimatorReplaced is not an IEC61850 quality bit but has been put in this class for convenience.
9    #[serde(skip_serializing_if = "Option::is_none")]
10    pub estimator_replaced: Option<bool>,
11    /// This identifier indicates that a supervision function has detected an internal or external failure, e.g. communication failure.
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub failure: Option<bool>,
14    /// Measurement value is old and possibly invalid, as it has not been successfully updated during a specified time interval.
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub old_data: Option<bool>,
17    /// Measurement value is blocked and hence unavailable for transmission.
18    #[serde(skip_serializing_if = "Option::is_none")]
19    pub operator_blocked: Option<bool>,
20    /// To prevent some overload of the communication it is sensible to detect and suppress oscillating (fast changing) binary inputs. If a signal changes in a defined time twice in the same direction (from 0 to 1 or from 1 to 0) then oscillation is detected and the detail quality identifier 'oscillatory' is set. If it is detected a configured numbers of transient changes could be passed by. In this time the validity status 'questionable' is set. If after this defined numbers of changes the signal is still in the oscillating state the value shall be set either to the opposite state of the previous stable value or to a defined default value. In this case the validity status 'questionable' is reset and 'invalid' is set as long as the signal is oscillating. If it is configured such that no transient changes should be passed by then the validity status 'invalid' is set immediately in addition to the detail quality identifier 'oscillatory' (used for status information only).
21    #[serde(skip_serializing_if = "Option::is_none")]
22    pub oscillatory: Option<bool>,
23    /// Measurement value is beyond a predefined range of value.
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub out_of_range: Option<bool>,
26    /// Measurement value is beyond the capability of being represented properly. For example, a counter value overflows from maximum count back to a value of zero.
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub over_flow: Option<bool>,
29    /// Source gives information related to the origin of a value. The value may be acquired from the process, defaulted or substituted.
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub source: Option<super::base::UriRef>,
32    /// A correlation function has detected that the value is not consistent with other values. Typically set by a network State Estimator.
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub suspect: Option<bool>,
35    /// Measurement value is transmitted for test purposes.
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub test: Option<bool>,
38    /// Validity of the measurement value.
39    #[serde(skip_serializing_if = "Option::is_none")]
40    pub validity: Option<super::base::UriRef>,
41}
42impl crate::base::CimElement for Quality61850 {
43    fn mrid(&self) -> &str { &self.id }
44    fn type_name(&self) -> &'static str { "Quality61850" }
45    fn as_any(&self) -> &dyn std::any::Any { self }
46    fn to_json_value(&self) -> serde_json::Value {
47        serde_json::to_value(self).unwrap_or(serde_json::Value::Null)
48    }
49    fn to_block(&self) -> crate::base::RdfBlock {
50        let mut block = crate::base::RdfBlock {
51            type_name: "Quality61850".to_string(),
52            mrid: self.id.clone(),
53            fields: std::collections::HashMap::new(),
54            duplicate_fields: std::collections::HashSet::new(),
55        };
56        if let Some(v) = self.bad_reference {
57            block.fields.insert("Quality61850.badReference".into(), crate::base::FieldValue::Text(v.to_string()));
58        }
59        if let Some(v) = self.estimator_replaced {
60            block.fields.insert("Quality61850.estimatorReplaced".into(), crate::base::FieldValue::Text(v.to_string()));
61        }
62        if let Some(v) = self.failure {
63            block.fields.insert("Quality61850.failure".into(), crate::base::FieldValue::Text(v.to_string()));
64        }
65        if let Some(v) = self.old_data {
66            block.fields.insert("Quality61850.oldData".into(), crate::base::FieldValue::Text(v.to_string()));
67        }
68        if let Some(v) = self.operator_blocked {
69            block.fields.insert("Quality61850.operatorBlocked".into(), crate::base::FieldValue::Text(v.to_string()));
70        }
71        if let Some(v) = self.oscillatory {
72            block.fields.insert("Quality61850.oscillatory".into(), crate::base::FieldValue::Text(v.to_string()));
73        }
74        if let Some(v) = self.out_of_range {
75            block.fields.insert("Quality61850.outOfRange".into(), crate::base::FieldValue::Text(v.to_string()));
76        }
77        if let Some(v) = self.over_flow {
78            block.fields.insert("Quality61850.overFlow".into(), crate::base::FieldValue::Text(v.to_string()));
79        }
80        if let Some(ref v) = self.source {
81            block.fields.insert("Quality61850.source".into(), crate::base::FieldValue::Resource(v.uri.clone()));
82        }
83        if let Some(v) = self.suspect {
84            block.fields.insert("Quality61850.suspect".into(), crate::base::FieldValue::Text(v.to_string()));
85        }
86        if let Some(v) = self.test {
87            block.fields.insert("Quality61850.test".into(), crate::base::FieldValue::Text(v.to_string()));
88        }
89        if let Some(ref v) = self.validity {
90            block.fields.insert("Quality61850.validity".into(), crate::base::FieldValue::Resource(v.uri.clone()));
91        }
92        block
93    }
94}
95
96impl Quality61850 {
97    pub fn from_block(b: &crate::base::RdfBlock) -> Self {
98        let mut obj = Self::default();
99        obj.id.clone_from(&b.mrid);
100        for (key, val) in &b.fields {
101            match key.as_str() {
102                "Quality61850.badReference" => {
103                    match val {
104                        crate::base::FieldValue::Text(sv) => { obj.bad_reference = Some(sv.trim() == "true"); }
105                        crate::base::FieldValue::TextList(svs) => {
106                            if let Some(sv) = svs.last() { obj.bad_reference = Some(sv.trim() == "true"); }
107                        }
108                        _ => {}
109                    }
110                }
111                "Quality61850.estimatorReplaced" => {
112                    match val {
113                        crate::base::FieldValue::Text(sv) => { obj.estimator_replaced = Some(sv.trim() == "true"); }
114                        crate::base::FieldValue::TextList(svs) => {
115                            if let Some(sv) = svs.last() { obj.estimator_replaced = Some(sv.trim() == "true"); }
116                        }
117                        _ => {}
118                    }
119                }
120                "Quality61850.failure" => {
121                    match val {
122                        crate::base::FieldValue::Text(sv) => { obj.failure = Some(sv.trim() == "true"); }
123                        crate::base::FieldValue::TextList(svs) => {
124                            if let Some(sv) = svs.last() { obj.failure = Some(sv.trim() == "true"); }
125                        }
126                        _ => {}
127                    }
128                }
129                "Quality61850.oldData" => {
130                    match val {
131                        crate::base::FieldValue::Text(sv) => { obj.old_data = Some(sv.trim() == "true"); }
132                        crate::base::FieldValue::TextList(svs) => {
133                            if let Some(sv) = svs.last() { obj.old_data = Some(sv.trim() == "true"); }
134                        }
135                        _ => {}
136                    }
137                }
138                "Quality61850.operatorBlocked" => {
139                    match val {
140                        crate::base::FieldValue::Text(sv) => { obj.operator_blocked = Some(sv.trim() == "true"); }
141                        crate::base::FieldValue::TextList(svs) => {
142                            if let Some(sv) = svs.last() { obj.operator_blocked = Some(sv.trim() == "true"); }
143                        }
144                        _ => {}
145                    }
146                }
147                "Quality61850.oscillatory" => {
148                    match val {
149                        crate::base::FieldValue::Text(sv) => { obj.oscillatory = Some(sv.trim() == "true"); }
150                        crate::base::FieldValue::TextList(svs) => {
151                            if let Some(sv) = svs.last() { obj.oscillatory = Some(sv.trim() == "true"); }
152                        }
153                        _ => {}
154                    }
155                }
156                "Quality61850.outOfRange" => {
157                    match val {
158                        crate::base::FieldValue::Text(sv) => { obj.out_of_range = Some(sv.trim() == "true"); }
159                        crate::base::FieldValue::TextList(svs) => {
160                            if let Some(sv) = svs.last() { obj.out_of_range = Some(sv.trim() == "true"); }
161                        }
162                        _ => {}
163                    }
164                }
165                "Quality61850.overFlow" => {
166                    match val {
167                        crate::base::FieldValue::Text(sv) => { obj.over_flow = Some(sv.trim() == "true"); }
168                        crate::base::FieldValue::TextList(svs) => {
169                            if let Some(sv) = svs.last() { obj.over_flow = Some(sv.trim() == "true"); }
170                        }
171                        _ => {}
172                    }
173                }
174                "Quality61850.source" => {
175                    if let crate::base::FieldValue::Resource(sv) = val {
176                        obj.source = Some(crate::base::UriRef { uri: sv.clone() });
177                    }
178                }
179                "Quality61850.suspect" => {
180                    match val {
181                        crate::base::FieldValue::Text(sv) => { obj.suspect = Some(sv.trim() == "true"); }
182                        crate::base::FieldValue::TextList(svs) => {
183                            if let Some(sv) = svs.last() { obj.suspect = Some(sv.trim() == "true"); }
184                        }
185                        _ => {}
186                    }
187                }
188                "Quality61850.test" => {
189                    match val {
190                        crate::base::FieldValue::Text(sv) => { obj.test = Some(sv.trim() == "true"); }
191                        crate::base::FieldValue::TextList(svs) => {
192                            if let Some(sv) = svs.last() { obj.test = Some(sv.trim() == "true"); }
193                        }
194                        _ => {}
195                    }
196                }
197                "Quality61850.validity" => {
198                    if let crate::base::FieldValue::Resource(sv) = val {
199                        obj.validity = Some(crate::base::UriRef { uri: sv.clone() });
200                    }
201                }
202                _ => {}
203            }
204        }
205        obj
206    }
207}