#![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 CalendarType {
Buddhist = 0,
Chinese = 1,
Coptic = 2,
Ethiopian = 3,
Gregorian = 4,
Hebrew = 5,
Indian = 6,
Islamic = 7,
Japanese = 8,
Korean = 9,
Persian = 10,
Taiwanese = 11,
Useactivelocale = 255,
}
impl CalendarType {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(CalendarType::Buddhist),
1 => Some(CalendarType::Chinese),
2 => Some(CalendarType::Coptic),
3 => Some(CalendarType::Ethiopian),
4 => Some(CalendarType::Gregorian),
5 => Some(CalendarType::Hebrew),
6 => Some(CalendarType::Indian),
7 => Some(CalendarType::Islamic),
8 => Some(CalendarType::Japanese),
9 => Some(CalendarType::Korean),
10 => Some(CalendarType::Persian),
11 => Some(CalendarType::Taiwanese),
255 => Some(CalendarType::Useactivelocale),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<CalendarType> for u8 {
fn from(val: CalendarType) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum HourFormat {
_12hr = 0,
_24hr = 1,
Useactivelocale = 255,
}
impl HourFormat {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(HourFormat::_12hr),
1 => Some(HourFormat::_24hr),
255 => Some(HourFormat::Useactivelocale),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<HourFormat> for u8 {
fn from(val: HourFormat) -> Self {
val as u8
}
}
pub fn decode_hour_format(inp: &tlv::TlvItemValue) -> anyhow::Result<HourFormat> {
if let tlv::TlvItemValue::Int(v) = inp {
HourFormat::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_active_calendar_type(inp: &tlv::TlvItemValue) -> anyhow::Result<CalendarType> {
if let tlv::TlvItemValue::Int(v) = inp {
CalendarType::from_u8(*v as u8).ok_or_else(|| anyhow::anyhow!("Invalid enum value"))
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_supported_calendar_types(inp: &tlv::TlvItemValue) -> anyhow::Result<Vec<CalendarType>> {
let mut res = Vec::new();
if let tlv::TlvItemValue::List(v) = inp {
for item in v {
if let tlv::TlvItemValue::Int(i) = &item.value {
if let Some(enum_val) = CalendarType::from_u8(*i as u8) {
res.push(enum_val);
}
}
}
}
Ok(res)
}
pub fn decode_attribute_json(cluster_id: u32, attribute_id: u32, tlv_value: &crate::tlv::TlvItemValue) -> String {
if cluster_id != 0x002C {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x002C, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_hour_format(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_active_calendar_type(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_supported_calendar_types(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, "HourFormat"),
(0x0001, "ActiveCalendarType"),
(0x0002, "SupportedCalendarTypes"),
]
}
pub async fn read_hour_format(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<HourFormat> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_TIME_FORMAT_LOCALIZATION, crate::clusters::defs::CLUSTER_TIME_FORMAT_LOCALIZATION_ATTR_ID_HOURFORMAT).await?;
decode_hour_format(&tlv)
}
pub async fn read_active_calendar_type(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<CalendarType> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_TIME_FORMAT_LOCALIZATION, crate::clusters::defs::CLUSTER_TIME_FORMAT_LOCALIZATION_ATTR_ID_ACTIVECALENDARTYPE).await?;
decode_active_calendar_type(&tlv)
}
pub async fn read_supported_calendar_types(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Vec<CalendarType>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_TIME_FORMAT_LOCALIZATION, crate::clusters::defs::CLUSTER_TIME_FORMAT_LOCALIZATION_ATTR_ID_SUPPORTEDCALENDARTYPES).await?;
decode_supported_calendar_types(&tlv)
}