#![allow(clippy::too_many_arguments)]
use crate::tlv;
use anyhow;
use serde_json;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum MeasurementType {
Unspecified = 0,
Voltage = 1,
Activecurrent = 2,
Reactivecurrent = 3,
Apparentcurrent = 4,
Activepower = 5,
Reactivepower = 6,
Apparentpower = 7,
Rmsvoltage = 8,
Rmscurrent = 9,
Rmspower = 10,
Frequency = 11,
Powerfactor = 12,
Neutralcurrent = 13,
Electricalenergy = 14,
Reactiveenergy = 15,
Apparentenergy = 16,
}
impl MeasurementType {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(MeasurementType::Unspecified),
1 => Some(MeasurementType::Voltage),
2 => Some(MeasurementType::Activecurrent),
3 => Some(MeasurementType::Reactivecurrent),
4 => Some(MeasurementType::Apparentcurrent),
5 => Some(MeasurementType::Activepower),
6 => Some(MeasurementType::Reactivepower),
7 => Some(MeasurementType::Apparentpower),
8 => Some(MeasurementType::Rmsvoltage),
9 => Some(MeasurementType::Rmscurrent),
10 => Some(MeasurementType::Rmspower),
11 => Some(MeasurementType::Frequency),
12 => Some(MeasurementType::Powerfactor),
13 => Some(MeasurementType::Neutralcurrent),
14 => Some(MeasurementType::Electricalenergy),
15 => Some(MeasurementType::Reactiveenergy),
16 => Some(MeasurementType::Apparentenergy),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<MeasurementType> for u8 {
fn from(val: MeasurementType) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum PowerMode {
Unknown = 0,
Dc = 1,
Ac = 2,
}
impl PowerMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(PowerMode::Unknown),
1 => Some(PowerMode::Dc),
2 => Some(PowerMode::Ac),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<PowerMode> for u8 {
fn from(val: PowerMode) -> Self {
val as u8
}
}
#[derive(Debug, serde::Serialize)]
pub struct HarmonicMeasurement {
pub order: Option<u8>,
pub measurement: Option<i64>,
}
#[derive(Debug, serde::Serialize)]
pub struct MeasurementAccuracyRange {
pub range_min: Option<i64>,
pub range_max: Option<i64>,
pub percent_max: Option<u16>,
pub percent_min: Option<u16>,
pub percent_typical: Option<u16>,
pub fixed_max: Option<u64>,
pub fixed_min: Option<u64>,
pub fixed_typical: Option<u64>,
}
#[derive(Debug, serde::Serialize)]
pub struct MeasurementAccuracy {
pub measurement_type: Option<MeasurementType>,
pub measured: Option<bool>,
pub min_measured_value: Option<i64>,
pub max_measured_value: Option<i64>,
pub accuracy_ranges: Option<Vec<MeasurementAccuracyRange>>,
}
#[derive(Debug, serde::Serialize)]
pub struct MeasurementRange {
pub measurement_type: Option<MeasurementType>,
pub min: Option<i64>,
pub max: Option<i64>,
pub start_timestamp: Option<u64>,
pub end_timestamp: Option<u64>,
pub min_timestamp: Option<u64>,
pub max_timestamp: Option<u64>,
pub start_systime: Option<u8>,
pub end_systime: Option<u8>,
pub min_systime: Option<u8>,
pub max_systime: Option<u8>,
}
pub fn decode_power_mode(inp: &tlv::TlvItemValue) -> anyhow::Result<PowerMode> {
if let tlv::TlvItemValue::Int(v) = inp {
PowerMode::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_number_of_measurement_types(inp: &tlv::TlvItemValue) -> anyhow::Result<u8> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected UInt8"))
}
}
pub fn decode_accuracy(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeasurementAccuracy>> {
let mut res = Vec::new();
if let tlv::TlvItemValue::List(v) = inp {
for item in v {
res.push(MeasurementAccuracy {
measurement_type: item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
measured: item.get_bool(&[1]),
min_measured_value: item.get_int(&[2]).map(|v| v as i64),
max_measured_value: item.get_int(&[3]).map(|v| v as i64),
accuracy_ranges: {
if let Some(tlv::TlvItemValue::List(l)) = item.get(&[4]) {
let mut items = Vec::new();
for list_item in l {
items.push(MeasurementAccuracyRange {
range_min: list_item.get_int(&[0]).map(|v| v as i64),
range_max: list_item.get_int(&[1]).map(|v| v as i64),
percent_max: list_item.get_int(&[2]).map(|v| v as u16),
percent_min: list_item.get_int(&[3]).map(|v| v as u16),
percent_typical: list_item.get_int(&[4]).map(|v| v as u16),
fixed_max: list_item.get_int(&[5]),
fixed_min: list_item.get_int(&[6]),
fixed_typical: list_item.get_int(&[7]),
});
}
Some(items)
} else {
None
}
},
});
}
}
Ok(res)
}
pub fn decode_ranges(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<MeasurementRange>> {
let mut res = Vec::new();
if let tlv::TlvItemValue::List(v) = inp {
for item in v {
res.push(MeasurementRange {
measurement_type: item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
min: item.get_int(&[1]).map(|v| v as i64),
max: item.get_int(&[2]).map(|v| v as i64),
start_timestamp: item.get_int(&[3]),
end_timestamp: item.get_int(&[4]),
min_timestamp: item.get_int(&[5]),
max_timestamp: item.get_int(&[6]),
start_systime: item.get_int(&[7]).map(|v| v as u8),
end_systime: item.get_int(&[8]).map(|v| v as u8),
min_systime: item.get_int(&[9]).map(|v| v as u8),
max_systime: item.get_int(&[10]).map(|v| v as u8),
});
}
}
Ok(res)
}
pub fn decode_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_active_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_reactive_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_apparent_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_active_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u32))
} else {
Ok(None)
}
}
pub fn decode_reactive_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_apparent_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_rms_voltage(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_rms_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_rms_power(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u32>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u32))
} else {
Ok(None)
}
}
pub fn decode_frequency(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as i64))
} else {
Ok(None)
}
}
pub fn decode_harmonic_currents(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
let mut res = Vec::new();
if let tlv::TlvItemValue::List(v) = inp {
for item in v {
res.push(HarmonicMeasurement {
order: item.get_int(&[0]).map(|v| v as u8),
measurement: item.get_int(&[1]).map(|v| v as i64),
});
}
}
Ok(res)
}
pub fn decode_harmonic_phases(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<HarmonicMeasurement>> {
let mut res = Vec::new();
if let tlv::TlvItemValue::List(v) = inp {
for item in v {
res.push(HarmonicMeasurement {
order: item.get_int(&[0]).map(|v| v as u8),
measurement: item.get_int(&[1]).map(|v| v as i64),
});
}
}
Ok(res)
}
pub fn decode_power_factor(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<i64>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as i64))
} else {
Ok(None)
}
}
pub fn decode_neutral_current(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u8>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u8))
} else {
Ok(None)
}
}
pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
if cluster_id != 0x0090 {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0090, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_power_mode(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_number_of_measurement_types(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_accuracy(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0003 => {
match decode_ranges(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0004 => {
match decode_voltage(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0005 => {
match decode_active_current(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0006 => {
match decode_reactive_current(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0007 => {
match decode_apparent_current(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0008 => {
match decode_active_power(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0009 => {
match decode_reactive_power(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000A => {
match decode_apparent_power(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000B => {
match decode_rms_voltage(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000C => {
match decode_rms_current(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000D => {
match decode_rms_power(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000E => {
match decode_frequency(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000F => {
match decode_harmonic_currents(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0010 => {
match decode_harmonic_phases(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0011 => {
match decode_power_factor(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0012 => {
match decode_neutral_current(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
_ => format!("{{\"error\": \"Unknown attribute ID: {}\"}}", attribute_id),
}
}
pub fn get_attribute_list() -> Vec<(u32, &'static str)> {
vec![
(0x0000, "PowerMode"),
(0x0001, "NumberOfMeasurementTypes"),
(0x0002, "Accuracy"),
(0x0003, "Ranges"),
(0x0004, "Voltage"),
(0x0005, "ActiveCurrent"),
(0x0006, "ReactiveCurrent"),
(0x0007, "ApparentCurrent"),
(0x0008, "ActivePower"),
(0x0009, "ReactivePower"),
(0x000A, "ApparentPower"),
(0x000B, "RMSVoltage"),
(0x000C, "RMSCurrent"),
(0x000D, "RMSPower"),
(0x000E, "Frequency"),
(0x000F, "HarmonicCurrents"),
(0x0010, "HarmonicPhases"),
(0x0011, "PowerFactor"),
(0x0012, "NeutralCurrent"),
]
}
pub async fn read_power_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<PowerMode> {
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?;
decode_power_mode(&tlv)
}
pub async fn read_number_of_measurement_types(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
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?;
decode_number_of_measurement_types(&tlv)
}
pub async fn read_accuracy(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MeasurementAccuracy>> {
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?;
decode_accuracy(&tlv)
}
pub async fn read_ranges(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<MeasurementRange>> {
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?;
decode_ranges(&tlv)
}
pub async fn read_voltage(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_voltage(&tlv)
}
pub async fn read_active_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_active_current(&tlv)
}
pub async fn read_reactive_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_reactive_current(&tlv)
}
pub async fn read_apparent_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_apparent_current(&tlv)
}
pub async fn read_active_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
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?;
decode_active_power(&tlv)
}
pub async fn read_reactive_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_reactive_power(&tlv)
}
pub async fn read_apparent_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_apparent_power(&tlv)
}
pub async fn read_rms_voltage(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_rms_voltage(&tlv)
}
pub async fn read_rms_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_rms_current(&tlv)
}
pub async fn read_rms_power(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u32>> {
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?;
decode_rms_power(&tlv)
}
pub async fn read_frequency(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<i64>> {
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?;
decode_frequency(&tlv)
}
pub async fn read_harmonic_currents(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<HarmonicMeasurement>> {
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?;
decode_harmonic_currents(&tlv)
}
pub async fn read_harmonic_phases(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<HarmonicMeasurement>> {
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?;
decode_harmonic_phases(&tlv)
}
pub async fn read_power_factor(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<i64>> {
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?;
decode_power_factor(&tlv)
}
pub async fn read_neutral_current(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
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?;
decode_neutral_current(&tlv)
}
#[derive(Debug, serde::Serialize)]
pub struct MeasurementPeriodRangesEvent {
pub ranges: Option<Vec<MeasurementRange>>,
}
pub fn decode_measurement_period_ranges_event(inp: &tlv::TlvItemValue) -> anyhow::Result<MeasurementPeriodRangesEvent> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(MeasurementPeriodRangesEvent {
ranges: {
if let Some(tlv::TlvItemValue::List(l)) = item.get(&[0]) {
let mut items = Vec::new();
for list_item in l {
items.push(MeasurementRange {
measurement_type: list_item.get_int(&[0]).and_then(|v| MeasurementType::from_u8(v as u8)),
min: list_item.get_int(&[1]).map(|v| v as i64),
max: list_item.get_int(&[2]).map(|v| v as i64),
start_timestamp: list_item.get_int(&[3]),
end_timestamp: list_item.get_int(&[4]),
min_timestamp: list_item.get_int(&[5]),
max_timestamp: list_item.get_int(&[6]),
start_systime: list_item.get_int(&[7]).map(|v| v as u8),
end_systime: list_item.get_int(&[8]).map(|v| v as u8),
min_systime: list_item.get_int(&[9]).map(|v| v as u8),
max_systime: list_item.get_int(&[10]).map(|v| v as u8),
});
}
Some(items)
} else {
None
}
},
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}