1#![allow(clippy::too_many_arguments)]
7
8use crate::tlv;
9use anyhow;
10use serde_json;
11
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
16#[repr(u8)]
17pub enum MeasurementType {
18 Unspecified = 0,
19 Voltage = 1,
21 Activecurrent = 2,
23 Reactivecurrent = 3,
25 Apparentcurrent = 4,
27 Activepower = 5,
29 Reactivepower = 6,
31 Apparentpower = 7,
33 Rmsvoltage = 8,
35 Rmscurrent = 9,
37 Rmspower = 10,
39 Frequency = 11,
41 Powerfactor = 12,
43 Neutralcurrent = 13,
45 Electricalenergy = 14,
47 Reactiveenergy = 15,
49 Apparentenergy = 16,
51}
52
53impl MeasurementType {
54 pub fn from_u8(value: u8) -> Option<Self> {
56 match value {
57 0 => Some(MeasurementType::Unspecified),
58 1 => Some(MeasurementType::Voltage),
59 2 => Some(MeasurementType::Activecurrent),
60 3 => Some(MeasurementType::Reactivecurrent),
61 4 => Some(MeasurementType::Apparentcurrent),
62 5 => Some(MeasurementType::Activepower),
63 6 => Some(MeasurementType::Reactivepower),
64 7 => Some(MeasurementType::Apparentpower),
65 8 => Some(MeasurementType::Rmsvoltage),
66 9 => Some(MeasurementType::Rmscurrent),
67 10 => Some(MeasurementType::Rmspower),
68 11 => Some(MeasurementType::Frequency),
69 12 => Some(MeasurementType::Powerfactor),
70 13 => Some(MeasurementType::Neutralcurrent),
71 14 => Some(MeasurementType::Electricalenergy),
72 15 => Some(MeasurementType::Reactiveenergy),
73 16 => Some(MeasurementType::Apparentenergy),
74 _ => None,
75 }
76 }
77
78 pub fn to_u8(self) -> u8 {
80 self as u8
81 }
82}
83
84impl From<MeasurementType> for u8 {
85 fn from(val: MeasurementType) -> Self {
86 val as u8
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
91#[repr(u8)]
92pub enum PowerMode {
93 Unknown = 0,
94 Dc = 1,
96 Ac = 2,
98}
99
100impl PowerMode {
101 pub fn from_u8(value: u8) -> Option<Self> {
103 match value {
104 0 => Some(PowerMode::Unknown),
105 1 => Some(PowerMode::Dc),
106 2 => Some(PowerMode::Ac),
107 _ => None,
108 }
109 }
110
111 pub fn to_u8(self) -> u8 {
113 self as u8
114 }
115}
116
117impl From<PowerMode> for u8 {
118 fn from(val: PowerMode) -> Self {
119 val as u8
120 }
121}
122
123#[derive(Debug, serde::Serialize)]
126pub struct HarmonicMeasurement {
127 pub order: Option<u8>,
128 pub measurement: Option<i64>,
129}
130
131#[derive(Debug, serde::Serialize)]
132pub struct MeasurementAccuracyRange {
133 pub range_min: Option<i64>,
134 pub range_max: Option<i64>,
135 pub percent_max: Option<u8>,
136 pub percent_min: Option<u8>,
137 pub percent_typical: Option<u8>,
138 pub fixed_max: Option<u64>,
139 pub fixed_min: Option<u64>,
140 pub fixed_typical: Option<u64>,
141}
142
143#[derive(Debug, serde::Serialize)]
144pub struct MeasurementAccuracy {
145 pub measurement_type: Option<MeasurementType>,
146 pub measured: Option<bool>,
147 pub min_measured_value: Option<i64>,
148 pub max_measured_value: Option<i64>,
149 pub accuracy_ranges: Option<Vec<MeasurementAccuracyRange>>,
150}
151
152#[derive(Debug, serde::Serialize)]
153pub struct MeasurementRange {
154 pub measurement_type: Option<MeasurementType>,
155 pub min: Option<i64>,
156 pub max: Option<i64>,
157 pub start_timestamp: Option<u64>,
158 pub end_timestamp: Option<u64>,
159 pub min_timestamp: Option<u64>,
160 pub max_timestamp: Option<u64>,
161 pub start_systime: Option<u8>,
162 pub end_systime: Option<u8>,
163 pub min_systime: Option<u8>,
164 pub max_systime: Option<u8>,
165}
166
167pub fn decode_power_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<PowerMode> {
171 if let tlv::TlvItemValue::Int(v) = inp {
172 PowerMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
173 } else {
174 Err(anyhow::anyhow!("Expected Integer"))
175 }
176}
177
178pub fn decode_number_of_measurement_types(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
180 if let tlv::TlvItemValue::Int(v) = inp {
181 Ok(*v as u8)
182 } else {
183 Err(anyhow::anyhow!("Expected UInt8"))
184 }
185}
186
187pub fn decode_accuracy(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeasurementAccuracy>> {
189 let mut res = Vec::new();
190 if let tlv::TlvItemValue::List(v) = inp {
191 for item in v {
192 res.push(MeasurementAccuracy {
193 measurement_type: item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
194 measured: item.get_bool(&[1]),
195 min_measured_value: item.get_int(&[2]).map(|v| v as i64),
196 max_measured_value: item.get_int(&[3]).map(|v| v as i64),
197 accuracy_ranges: {
198 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[4]) {
199 let mut items = Vec::new();
200 for list_item in l {
201 items.push(MeasurementAccuracyRange {
202 range_min: list_item.get_int(&[0]).map(|v| v as i64),
203 range_max: list_item.get_int(&[1]).map(|v| v as i64),
204 percent_max: list_item.get_int(&[2]).map(|v| v as u8),
205 percent_min: list_item.get_int(&[3]).map(|v| v as u8),
206 percent_typical: list_item.get_int(&[4]).map(|v| v as u8),
207 fixed_max: list_item.get_int(&[5]),
208 fixed_min: list_item.get_int(&[6]),
209 fixed_typical: list_item.get_int(&[7]),
210 });
211 }
212 Some(items)
213 } else {
214 None
215 }
216 },
217 });
218 }
219 }
220 Ok(res)
221}
222
223pub fn decode_ranges(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeasurementRange>> {
225 let mut res = Vec::new();
226 if let tlv::TlvItemValue::List(v) = inp {
227 for item in v {
228 res.push(MeasurementRange {
229 measurement_type: item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
230 min: item.get_int(&[1]).map(|v| v as i64),
231 max: item.get_int(&[2]).map(|v| v as i64),
232 start_timestamp: item.get_int(&[3]),
233 end_timestamp: item.get_int(&[4]),
234 min_timestamp: item.get_int(&[5]),
235 max_timestamp: item.get_int(&[6]),
236 start_systime: item.get_int(&[7]).map(|v| v as u8),
237 end_systime: item.get_int(&[8]).map(|v| v as u8),
238 min_systime: item.get_int(&[9]).map(|v| v as u8),
239 max_systime: item.get_int(&[10]).map(|v| v as u8),
240 });
241 }
242 }
243 Ok(res)
244}
245
246pub fn decode_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
248 if let tlv::TlvItemValue::Int(v) = inp {
249 Ok(Some(*v as u8))
250 } else {
251 Ok(None)
252 }
253}
254
255pub fn decode_active_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
257 if let tlv::TlvItemValue::Int(v) = inp {
258 Ok(Some(*v as u8))
259 } else {
260 Ok(None)
261 }
262}
263
264pub fn decode_reactive_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
266 if let tlv::TlvItemValue::Int(v) = inp {
267 Ok(Some(*v as u8))
268 } else {
269 Ok(None)
270 }
271}
272
273pub fn decode_apparent_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
275 if let tlv::TlvItemValue::Int(v) = inp {
276 Ok(Some(*v as u8))
277 } else {
278 Ok(None)
279 }
280}
281
282pub fn decode_active_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
284 if let tlv::TlvItemValue::Int(v) = inp {
285 Ok(Some(*v as u32))
286 } else {
287 Ok(None)
288 }
289}
290
291pub fn decode_reactive_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
293 if let tlv::TlvItemValue::Int(v) = inp {
294 Ok(Some(*v as u8))
295 } else {
296 Ok(None)
297 }
298}
299
300pub fn decode_apparent_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
302 if let tlv::TlvItemValue::Int(v) = inp {
303 Ok(Some(*v as u8))
304 } else {
305 Ok(None)
306 }
307}
308
309pub fn decode_rms_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
311 if let tlv::TlvItemValue::Int(v) = inp {
312 Ok(Some(*v as u8))
313 } else {
314 Ok(None)
315 }
316}
317
318pub fn decode_rms_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
320 if let tlv::TlvItemValue::Int(v) = inp {
321 Ok(Some(*v as u8))
322 } else {
323 Ok(None)
324 }
325}
326
327pub fn decode_rms_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
329 if let tlv::TlvItemValue::Int(v) = inp {
330 Ok(Some(*v as u32))
331 } else {
332 Ok(None)
333 }
334}
335
336pub fn decode_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
338 if let tlv::TlvItemValue::Int(v) = inp {
339 Ok(Some(*v as i64))
340 } else {
341 Ok(None)
342 }
343}
344
345pub fn decode_harmonic_currents(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
347 let mut res = Vec::new();
348 if let tlv::TlvItemValue::List(v) = inp {
349 for item in v {
350 res.push(HarmonicMeasurement {
351 order: item.get_int(&[0]).map(|v| v as u8),
352 measurement: item.get_int(&[1]).map(|v| v as i64),
353 });
354 }
355 }
356 Ok(res)
357}
358
359pub fn decode_harmonic_phases(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
361 let mut res = Vec::new();
362 if let tlv::TlvItemValue::List(v) = inp {
363 for item in v {
364 res.push(HarmonicMeasurement {
365 order: item.get_int(&[0]).map(|v| v as u8),
366 measurement: item.get_int(&[1]).map(|v| v as i64),
367 });
368 }
369 }
370 Ok(res)
371}
372
373pub fn decode_power_factor(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
375 if let tlv::TlvItemValue::Int(v) = inp {
376 Ok(Some(*v as i64))
377 } else {
378 Ok(None)
379 }
380}
381
382pub fn decode_neutral_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
384 if let tlv::TlvItemValue::Int(v) = inp {
385 Ok(Some(*v as u8))
386 } else {
387 Ok(None)
388 }
389}
390
391
392pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
404 if cluster_id != 0x0090 {
406 return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0090, got {}\"}}", cluster_id);
407 }
408
409 match attribute_id {
410 0x0000 => {
411 match decode_power_mode(tlv_value) {
412 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
413 Err(e) => format!("{{\"error\": \"{}\"}}", e),
414 }
415 }
416 0x0001 => {
417 match decode_number_of_measurement_types(tlv_value) {
418 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
419 Err(e) => format!("{{\"error\": \"{}\"}}", e),
420 }
421 }
422 0x0002 => {
423 match decode_accuracy(tlv_value) {
424 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
425 Err(e) => format!("{{\"error\": \"{}\"}}", e),
426 }
427 }
428 0x0003 => {
429 match decode_ranges(tlv_value) {
430 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
431 Err(e) => format!("{{\"error\": \"{}\"}}", e),
432 }
433 }
434 0x0004 => {
435 match decode_voltage(tlv_value) {
436 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
437 Err(e) => format!("{{\"error\": \"{}\"}}", e),
438 }
439 }
440 0x0005 => {
441 match decode_active_current(tlv_value) {
442 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
443 Err(e) => format!("{{\"error\": \"{}\"}}", e),
444 }
445 }
446 0x0006 => {
447 match decode_reactive_current(tlv_value) {
448 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
449 Err(e) => format!("{{\"error\": \"{}\"}}", e),
450 }
451 }
452 0x0007 => {
453 match decode_apparent_current(tlv_value) {
454 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
455 Err(e) => format!("{{\"error\": \"{}\"}}", e),
456 }
457 }
458 0x0008 => {
459 match decode_active_power(tlv_value) {
460 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
461 Err(e) => format!("{{\"error\": \"{}\"}}", e),
462 }
463 }
464 0x0009 => {
465 match decode_reactive_power(tlv_value) {
466 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
467 Err(e) => format!("{{\"error\": \"{}\"}}", e),
468 }
469 }
470 0x000A => {
471 match decode_apparent_power(tlv_value) {
472 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
473 Err(e) => format!("{{\"error\": \"{}\"}}", e),
474 }
475 }
476 0x000B => {
477 match decode_rms_voltage(tlv_value) {
478 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
479 Err(e) => format!("{{\"error\": \"{}\"}}", e),
480 }
481 }
482 0x000C => {
483 match decode_rms_current(tlv_value) {
484 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
485 Err(e) => format!("{{\"error\": \"{}\"}}", e),
486 }
487 }
488 0x000D => {
489 match decode_rms_power(tlv_value) {
490 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
491 Err(e) => format!("{{\"error\": \"{}\"}}", e),
492 }
493 }
494 0x000E => {
495 match decode_frequency(tlv_value) {
496 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
497 Err(e) => format!("{{\"error\": \"{}\"}}", e),
498 }
499 }
500 0x000F => {
501 match decode_harmonic_currents(tlv_value) {
502 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
503 Err(e) => format!("{{\"error\": \"{}\"}}", e),
504 }
505 }
506 0x0010 => {
507 match decode_harmonic_phases(tlv_value) {
508 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
509 Err(e) => format!("{{\"error\": \"{}\"}}", e),
510 }
511 }
512 0x0011 => {
513 match decode_power_factor(tlv_value) {
514 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
515 Err(e) => format!("{{\"error\": \"{}\"}}", e),
516 }
517 }
518 0x0012 => {
519 match decode_neutral_current(tlv_value) {
520 Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
521 Err(e) => format!("{{\"error\": \"{}\"}}", e),
522 }
523 }
524 _ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
525 }
526}
527
528pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
533 vec![
534 (0x0000, "PowerMode"),
535 (0x0001, "NumberOfMeasurementTypes"),
536 (0x0002, "Accuracy"),
537 (0x0003, "Ranges"),
538 (0x0004, "Voltage"),
539 (0x0005, "ActiveCurrent"),
540 (0x0006, "ReactiveCurrent"),
541 (0x0007, "ApparentCurrent"),
542 (0x0008, "ActivePower"),
543 (0x0009, "ReactivePower"),
544 (0x000A, "ApparentPower"),
545 (0x000B, "RMSVoltage"),
546 (0x000C, "RMSCurrent"),
547 (0x000D, "RMSPower"),
548 (0x000E, "Frequency"),
549 (0x000F, "HarmonicCurrents"),
550 (0x0010, "HarmonicPhases"),
551 (0x0011, "PowerFactor"),
552 (0x0012, "NeutralCurrent"),
553 ]
554}
555
556pub async fn read_power_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<PowerMode> {
560 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_POWERMODE).await?;
561 decode_power_mode(&tlv)
562}
563
564pub async fn read_number_of_measurement_types(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
566 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_NUMBEROFMEASUREMENTTYPES).await?;
567 decode_number_of_measurement_types(&tlv)
568}
569
570pub async fn read_accuracy(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MeasurementAccuracy>> {
572 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_ACCURACY).await?;
573 decode_accuracy(&tlv)
574}
575
576pub async fn read_ranges(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MeasurementRange>> {
578 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_RANGES).await?;
579 decode_ranges(&tlv)
580}
581
582pub async fn read_voltage(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
584 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_VOLTAGE).await?;
585 decode_voltage(&tlv)
586}
587
588pub async fn read_active_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
590 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_ACTIVECURRENT).await?;
591 decode_active_current(&tlv)
592}
593
594pub async fn read_reactive_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
596 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_REACTIVECURRENT).await?;
597 decode_reactive_current(&tlv)
598}
599
600pub async fn read_apparent_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
602 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_APPARENTCURRENT).await?;
603 decode_apparent_current(&tlv)
604}
605
606pub async fn read_active_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
608 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_ACTIVEPOWER).await?;
609 decode_active_power(&tlv)
610}
611
612pub async fn read_reactive_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
614 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_REACTIVEPOWER).await?;
615 decode_reactive_power(&tlv)
616}
617
618pub async fn read_apparent_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
620 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_APPARENTPOWER).await?;
621 decode_apparent_power(&tlv)
622}
623
624pub async fn read_rms_voltage(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
626 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_RMSVOLTAGE).await?;
627 decode_rms_voltage(&tlv)
628}
629
630pub async fn read_rms_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
632 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_RMSCURRENT).await?;
633 decode_rms_current(&tlv)
634}
635
636pub async fn read_rms_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
638 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_RMSPOWER).await?;
639 decode_rms_power(&tlv)
640}
641
642pub async fn read_frequency(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<i64>> {
644 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_FREQUENCY).await?;
645 decode_frequency(&tlv)
646}
647
648pub async fn read_harmonic_currents(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<HarmonicMeasurement>> {
650 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_HARMONICCURRENTS).await?;
651 decode_harmonic_currents(&tlv)
652}
653
654pub async fn read_harmonic_phases(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<HarmonicMeasurement>> {
656 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_HARMONICPHASES).await?;
657 decode_harmonic_phases(&tlv)
658}
659
660pub async fn read_power_factor(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<i64>> {
662 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_POWERFACTOR).await?;
663 decode_power_factor(&tlv)
664}
665
666pub async fn read_neutral_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
668 let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_ELECTRICAL_POWER_MEASUREMENT, crate::clusters::defs::CLUSTER_ELECTRICAL_POWER_MEASUREMENT_ATTR_ID_NEUTRALCURRENT).await?;
669 decode_neutral_current(&tlv)
670}
671
672#[derive(Debug, serde::Serialize)]
673pub struct MeasurementPeriodRangesEvent {
674 pub ranges: Option<Vec<MeasurementRange>>,
675}
676
677pub fn decode_measurement_period_ranges_event(inp: &tlv::TlvItemValue) -> anyhow::Result<MeasurementPeriodRangesEvent> {
681 if let tlv::TlvItemValue::List(_fields) = inp {
682 let item = tlv::TlvItem { tag: 0, value: inp.clone() };
683 Ok(MeasurementPeriodRangesEvent {
684 ranges: {
685 if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
686 let mut items = Vec::new();
687 for list_item in l {
688 items.push(MeasurementRange {
689 measurement_type: list_item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
690 min: list_item.get_int(&[1]).map(|v| v as i64),
691 max: list_item.get_int(&[2]).map(|v| v as i64),
692 start_timestamp: list_item.get_int(&[3]),
693 end_timestamp: list_item.get_int(&[4]),
694 min_timestamp: list_item.get_int(&[5]),
695 max_timestamp: list_item.get_int(&[6]),
696 start_systime: list_item.get_int(&[7]).map(|v| v as u8),
697 end_systime: list_item.get_int(&[8]).map(|v| v as u8),
698 min_systime: list_item.get_int(&[9]).map(|v| v as u8),
699 max_systime: list_item.get_int(&[10]).map(|v| v as u8),
700 });
701 }
702 Some(items)
703 } else {
704 None
705 }
706 },
707 })
708 } else {
709 Err(anyhow::anyhow!("Expected struct fields"))
710 }
711}
712