#![allow(clippy::too_many_arguments)]
use crate::tlv;
use anyhow;
use serde_json;
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u16)]
pub enum ModeTag {
Auto = 0,
Quick = 1,
Quiet = 2,
Lownoise = 3,
Lowenergy = 4,
Vacation = 5,
Min = 6,
Max = 7,
Night = 8,
Day = 9,
Rapidcool = 16384,
Rapidfreeze = 16385,
}
impl ModeTag {
pub fn from_u8(value: u8) -> Option<Self> {
Self::from_u16(value as u16)
}
pub fn from_u16(value: u16) -> Option<Self> {
match value {
0 => Some(ModeTag::Auto),
1 => Some(ModeTag::Quick),
2 => Some(ModeTag::Quiet),
3 => Some(ModeTag::Lownoise),
4 => Some(ModeTag::Lowenergy),
5 => Some(ModeTag::Vacation),
6 => Some(ModeTag::Min),
7 => Some(ModeTag::Max),
8 => Some(ModeTag::Night),
9 => Some(ModeTag::Day),
16384 => Some(ModeTag::Rapidcool),
16385 => Some(ModeTag::Rapidfreeze),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
pub fn to_u16(self) -> u16 {
self as u16
}
}
impl From<ModeTag> for u16 {
fn from(val: ModeTag) -> Self {
val as u16
}
}
#[derive(Debug, serde::Serialize)]
pub struct ModeOption {
pub label: Option<u8>,
pub mode: Option<u8>,
pub mode_tags: Option<u8>,
}
pub fn decode_supported_modes(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_current_mode(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_start_up_mode(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_on_mode(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_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
if cluster_id != 0x0052 {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0052, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_supported_modes(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_current_mode(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_start_up_mode(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0003 => {
match decode_on_mode(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, "SupportedModes"),
(0x0001, "CurrentMode"),
(0x0002, "StartUpMode"),
(0x0003, "OnMode"),
]
}
pub async fn read_supported_modes(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE, crate::clusters::defs::CLUSTER_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_ATTR_ID_SUPPORTEDMODES).await?;
decode_supported_modes(&tlv)
}
pub async fn read_current_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE, crate::clusters::defs::CLUSTER_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_ATTR_ID_CURRENTMODE).await?;
decode_current_mode(&tlv)
}
pub async fn read_start_up_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE, crate::clusters::defs::CLUSTER_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_ATTR_ID_STARTUPMODE).await?;
decode_start_up_mode(&tlv)
}
pub async fn read_on_mode(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE, crate::clusters::defs::CLUSTER_REFRIGERATOR_AND_TEMPERATURE_CONTROLLED_CABINET_MODE_ATTR_ID_ONMODE).await?;
decode_on_mode(&tlv)
}