#![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 Color {
Black = 0,
Navy = 1,
Green = 2,
Teal = 3,
Maroon = 4,
Purple = 5,
Olive = 6,
Gray = 7,
Blue = 8,
Lime = 9,
Aqua = 10,
Red = 11,
Fuchsia = 12,
Yellow = 13,
White = 14,
Nickel = 15,
Chrome = 16,
Brass = 17,
Copper = 18,
Silver = 19,
Gold = 20,
}
impl Color {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(Color::Black),
1 => Some(Color::Navy),
2 => Some(Color::Green),
3 => Some(Color::Teal),
4 => Some(Color::Maroon),
5 => Some(Color::Purple),
6 => Some(Color::Olive),
7 => Some(Color::Gray),
8 => Some(Color::Blue),
9 => Some(Color::Lime),
10 => Some(Color::Aqua),
11 => Some(Color::Red),
12 => Some(Color::Fuchsia),
13 => Some(Color::Yellow),
14 => Some(Color::White),
15 => Some(Color::Nickel),
16 => Some(Color::Chrome),
17 => Some(Color::Brass),
18 => Some(Color::Copper),
19 => Some(Color::Silver),
20 => Some(Color::Gold),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<Color> for u8 {
fn from(val: Color) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum ProductFinish {
Other = 0,
Matte = 1,
Satin = 2,
Polished = 3,
Rugged = 4,
Fabric = 5,
}
impl ProductFinish {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(ProductFinish::Other),
1 => Some(ProductFinish::Matte),
2 => Some(ProductFinish::Satin),
3 => Some(ProductFinish::Polished),
4 => Some(ProductFinish::Rugged),
5 => Some(ProductFinish::Fabric),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<ProductFinish> for u8 {
fn from(val: ProductFinish) -> Self {
val as u8
}
}
#[derive(Debug, serde::Serialize)]
pub struct CapabilityMinima {
pub case_sessions_per_fabric: Option<u16>,
pub subscriptions_per_fabric: Option<u16>,
}
#[derive(Debug, serde::Serialize)]
pub struct ProductAppearance {
pub finish: Option<ProductFinish>,
pub primary_color: Option<Color>,
}
pub fn decode_data_model_revision(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_vendor_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_vendor_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_product_name(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_product_id(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_node_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_location(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_hardware_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_hardware_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_software_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u32)
} else {
Err(anyhow::anyhow!("Expected UInt32"))
}
}
pub fn decode_software_version_string(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_manufacturing_date(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_part_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_product_url(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_product_label(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_serial_number(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_local_config_disabled(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
if let tlv::TlvItemValue::Bool(v) = inp {
Ok(*v)
} else {
Err(anyhow::anyhow!("Expected Bool"))
}
}
pub fn decode_reachable(inp: &tlv::TlvItemValue) -> anyhow::Result<bool> {
if let tlv::TlvItemValue::Bool(v) = inp {
Ok(*v)
} else {
Err(anyhow::anyhow!("Expected Bool"))
}
}
pub fn decode_unique_id(inp: &tlv::TlvItemValue) -> anyhow::Result<String> {
if let tlv::TlvItemValue::String(v) = inp {
Ok(v.clone())
} else {
Err(anyhow::anyhow!("Expected String"))
}
}
pub fn decode_capability_minima(inp: &tlv::TlvItemValue) -> anyhow::Result<CapabilityMinima> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(CapabilityMinima {
case_sessions_per_fabric: item.get_int(&[0]).map(|v| v as u16),
subscriptions_per_fabric: item.get_int(&[1]).map(|v| v as u16),
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}
pub fn decode_product_appearance(inp: &tlv::TlvItemValue) -> anyhow::Result<ProductAppearance> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(ProductAppearance {
finish: item.get_int(&[0]).and_then(|v| ProductFinish::from_u8(v as u8)),
primary_color: item.get_int(&[1]).and_then(|v| Color::from_u8(v as u8)),
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}
pub fn decode_specification_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u32)
} else {
Err(anyhow::anyhow!("Expected UInt32"))
}
}
pub fn decode_max_paths_per_invoke(inp: &tlv::TlvItemValue) -> anyhow::Result<u16> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u16)
} else {
Err(anyhow::anyhow!("Expected UInt16"))
}
}
pub fn decode_configuration_version(inp: &tlv::TlvItemValue) -> anyhow::Result<u32> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u32)
} else {
Err(anyhow::anyhow!("Expected UInt32"))
}
}
pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
if cluster_id != 0x0028 {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0028, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_data_model_revision(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_vendor_name(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_vendor_id(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0003 => {
match decode_product_name(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0004 => {
match decode_product_id(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0005 => {
match decode_node_label(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0006 => {
match decode_location(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0007 => {
match decode_hardware_version(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0008 => {
match decode_hardware_version_string(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0009 => {
match decode_software_version(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000A => {
match decode_software_version_string(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000B => {
match decode_manufacturing_date(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000C => {
match decode_part_number(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000D => {
match decode_product_url(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000E => {
match decode_product_label(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000F => {
match decode_serial_number(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0010 => {
match decode_local_config_disabled(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0011 => {
match decode_reachable(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0012 => {
match decode_unique_id(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0013 => {
match decode_capability_minima(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0014 => {
match decode_product_appearance(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0015 => {
match decode_specification_version(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0016 => {
match decode_max_paths_per_invoke(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0018 => {
match decode_configuration_version(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, "DataModelRevision"),
(0x0001, "VendorName"),
(0x0002, "VendorID"),
(0x0003, "ProductName"),
(0x0004, "ProductID"),
(0x0005, "NodeLabel"),
(0x0006, "Location"),
(0x0007, "HardwareVersion"),
(0x0008, "HardwareVersionString"),
(0x0009, "SoftwareVersion"),
(0x000A, "SoftwareVersionString"),
(0x000B, "ManufacturingDate"),
(0x000C, "PartNumber"),
(0x000D, "ProductURL"),
(0x000E, "ProductLabel"),
(0x000F, "SerialNumber"),
(0x0010, "LocalConfigDisabled"),
(0x0011, "Reachable"),
(0x0012, "UniqueID"),
(0x0013, "CapabilityMinima"),
(0x0014, "ProductAppearance"),
(0x0015, "SpecificationVersion"),
(0x0016, "MaxPathsPerInvoke"),
(0x0018, "ConfigurationVersion"),
]
}
pub async fn read_data_model_revision(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_DATAMODELREVISION).await?;
decode_data_model_revision(&tlv)
}
pub async fn read_vendor_name(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORNAME).await?;
decode_vendor_name(&tlv)
}
pub async fn read_vendor_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_VENDORID).await?;
decode_vendor_id(&tlv)
}
pub async fn read_product_name(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTNAME).await?;
decode_product_name(&tlv)
}
pub async fn read_product_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTID).await?;
decode_product_id(&tlv)
}
pub async fn read_node_label(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_NODELABEL).await?;
decode_node_label(&tlv)
}
pub async fn read_location(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCATION).await?;
decode_location(&tlv)
}
pub async fn read_hardware_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSION).await?;
decode_hardware_version(&tlv)
}
pub async fn read_hardware_version_string(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_HARDWAREVERSIONSTRING).await?;
decode_hardware_version_string(&tlv)
}
pub async fn read_software_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSION).await?;
decode_software_version(&tlv)
}
pub async fn read_software_version_string(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_SOFTWAREVERSIONSTRING).await?;
decode_software_version_string(&tlv)
}
pub async fn read_manufacturing_date(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_MANUFACTURINGDATE).await?;
decode_manufacturing_date(&tlv)
}
pub async fn read_part_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PARTNUMBER).await?;
decode_part_number(&tlv)
}
pub async fn read_product_url(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTURL).await?;
decode_product_url(&tlv)
}
pub async fn read_product_label(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTLABEL).await?;
decode_product_label(&tlv)
}
pub async fn read_serial_number(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_SERIALNUMBER).await?;
decode_serial_number(&tlv)
}
pub async fn read_local_config_disabled(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_LOCALCONFIGDISABLED).await?;
decode_local_config_disabled(&tlv)
}
pub async fn read_reachable(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<bool> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_REACHABLE).await?;
decode_reachable(&tlv)
}
pub async fn read_unique_id(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<String> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_UNIQUEID).await?;
decode_unique_id(&tlv)
}
pub async fn read_capability_minima(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<CapabilityMinima> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_CAPABILITYMINIMA).await?;
decode_capability_minima(&tlv)
}
pub async fn read_product_appearance(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<ProductAppearance> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_PRODUCTAPPEARANCE).await?;
decode_product_appearance(&tlv)
}
pub async fn read_specification_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_SPECIFICATIONVERSION).await?;
decode_specification_version(&tlv)
}
pub async fn read_max_paths_per_invoke(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_MAXPATHSPERINVOKE).await?;
decode_max_paths_per_invoke(&tlv)
}
pub async fn read_configuration_version(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u32> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_BASIC_INFORMATION, crate::clusters::defs::CLUSTER_BASIC_INFORMATION_ATTR_ID_CONFIGURATIONVERSION).await?;
decode_configuration_version(&tlv)
}
#[derive(Debug, serde::Serialize)]
pub struct StartUpEvent {
pub software_version: Option<u32>,
}
#[derive(Debug, serde::Serialize)]
pub struct LeaveEvent {
pub fabric_index: Option<u8>,
}
#[derive(Debug, serde::Serialize)]
pub struct ReachableChangedEvent {
pub reachable_new_value: Option<bool>,
}
pub fn decode_start_up_event(inp: &tlv::TlvItemValue) -> anyhow::Result<StartUpEvent> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(StartUpEvent {
software_version: item.get_int(&[0]).map(|v| v as u32),
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}
pub fn decode_leave_event(inp: &tlv::TlvItemValue) -> anyhow::Result<LeaveEvent> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(LeaveEvent {
fabric_index: item.get_int(&[0]).map(|v| v as u8),
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}
pub fn decode_reachable_changed_event(inp: &tlv::TlvItemValue) -> anyhow::Result<ReachableChangedEvent> {
if let tlv::TlvItemValue::List(_fields) = inp {
let item = tlv::TlvItem { tag: 0, value: inp.clone() };
Ok(ReachableChangedEvent {
reachable_new_value: item.get_bool(&[0]),
})
} else {
Err(anyhow::anyhow!("Expected struct fields"))
}
}