#![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 MoveMode {
Up = 0,
Down = 1,
}
impl MoveMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(MoveMode::Up),
1 => Some(MoveMode::Down),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<MoveMode> for u8 {
fn from(val: MoveMode) -> Self {
val as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
#[repr(u8)]
pub enum StepMode {
Up = 0,
Down = 1,
}
impl StepMode {
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(StepMode::Up),
1 => Some(StepMode::Down),
_ => None,
}
}
pub fn to_u8(self) -> u8 {
self as u8
}
}
impl From<StepMode> for u8 {
fn from(val: StepMode) -> Self {
val as u8
}
}
pub type Options = u8;
pub mod options {
pub const EXECUTE_IF_OFF: u8 = 0x01;
pub const COUPLE_COLOR_TEMP_TO_LEVEL: u8 = 0x02;
}
pub fn encode_move_to_level(level: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(level)).into(),
(1, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_(move_mode: MoveMode, rate: Option<u8>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(rate.unwrap_or(0))).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_step(step_mode: StepMode, step_size: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_stop(options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_level_with_on_off(level: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(level)).into(),
(1, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_with_on_off(move_mode: MoveMode, rate: Option<u8>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(move_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(rate.unwrap_or(0))).into(),
(2, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_step_with_on_off(step_mode: StepMode, step_size: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(step_mode.to_u8())).into(),
(1, tlv::TlvItemValueEnc::UInt8(step_size)).into(),
(2, tlv::TlvItemValueEnc::UInt16(transition_time.unwrap_or(0))).into(),
(3, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(4, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_stop_with_on_off(options_mask: Options, options_override: Options) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt8(options_mask)).into(),
(1, tlv::TlvItemValueEnc::UInt8(options_override)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn encode_move_to_closest_frequency(frequency: u16) -> anyhow::Result<Vec<u8>> {
let tlv = tlv::TlvItemEnc {
tag: 0,
value: tlv::TlvItemValueEnc::StructInvisible(vec![
(0, tlv::TlvItemValueEnc::UInt16(frequency)).into(),
]),
};
Ok(tlv.encode()?)
}
pub fn decode_current_level(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_remaining_time(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_min_level(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_max_level(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_frequency(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_min_frequency(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_max_frequency(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_options(inp: &tlv::TlvItemValue) -> anyhow::Result<Options> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(*v as u8)
} else {
Err(anyhow::anyhow!("Expected Integer"))
}
}
pub fn decode_on_off_transition_time(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_on_level(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_on_transition_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u16))
} else {
Ok(None)
}
}
pub fn decode_off_transition_time(inp: &tlv::TlvItemValue) -> anyhow::Result<Option<u16>> {
if let tlv::TlvItemValue::Int(v) = inp {
Ok(Some(*v as u16))
} else {
Ok(None)
}
}
pub fn decode_default_move_rate(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_start_up_current_level(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 != 0x0008 {
return format!("{{\"error\": \"Invalid cluster ID. Expected 0x0008, got {}\"}}", cluster_id);
}
match attribute_id {
0x0000 => {
match decode_current_level(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0001 => {
match decode_remaining_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0002 => {
match decode_min_level(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0003 => {
match decode_max_level(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0004 => {
match decode_current_frequency(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0005 => {
match decode_min_frequency(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0006 => {
match decode_max_frequency(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x000F => {
match decode_options(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0010 => {
match decode_on_off_transition_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0011 => {
match decode_on_level(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0012 => {
match decode_on_transition_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0013 => {
match decode_off_transition_time(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x0014 => {
match decode_default_move_rate(tlv_value) {
Ok(value) => serde_json::to_string(&value).unwrap_or_else(|_| "null".to_string()),
Err(e) => format!("{{\"error\": \"{}\"}}", e),
}
}
0x4000 => {
match decode_start_up_current_level(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, "CurrentLevel"),
(0x0001, "RemainingTime"),
(0x0002, "MinLevel"),
(0x0003, "MaxLevel"),
(0x0004, "CurrentFrequency"),
(0x0005, "MinFrequency"),
(0x0006, "MaxFrequency"),
(0x000F, "Options"),
(0x0010, "OnOffTransitionTime"),
(0x0011, "OnLevel"),
(0x0012, "OnTransitionTime"),
(0x0013, "OffTransitionTime"),
(0x0014, "DefaultMoveRate"),
(0x4000, "StartUpCurrentLevel"),
]
}
pub fn get_command_list() -> Vec<(u32, &'static str)> {
vec![
(0x00, "MoveToLevel"),
(0x01, "Move"),
(0x02, "Step"),
(0x03, "Stop"),
(0x04, "MoveToLevelWithOnOff"),
(0x05, "MoveWithOnOff"),
(0x06, "StepWithOnOff"),
(0x07, "StopWithOnOff"),
(0x08, "MoveToClosestFrequency"),
]
}
pub fn get_command_name(cmd_id: u32) -> Option<&'static str> {
match cmd_id {
0x00 => Some("MoveToLevel"),
0x01 => Some("Move"),
0x02 => Some("Step"),
0x03 => Some("Stop"),
0x04 => Some("MoveToLevelWithOnOff"),
0x05 => Some("MoveWithOnOff"),
0x06 => Some("StepWithOnOff"),
0x07 => Some("StopWithOnOff"),
0x08 => Some("MoveToClosestFrequency"),
_ => None,
}
}
pub fn get_command_schema(cmd_id: u32) -> Option<Vec<crate::clusters::codec::CommandField>> {
match cmd_id {
0x00 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "level", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x01 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Up"), (1, "Down")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x02 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(0, "Up"), (1, "Down")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x03 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x04 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "level", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x05 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "move_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "MoveMode", variants: &[(0, "Up"), (1, "Down")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "rate", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 2, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 3, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x06 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "step_mode", kind: crate::clusters::codec::FieldKind::Enum { name: "StepMode", variants: &[(0, "Up"), (1, "Down")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "step_size", kind: crate::clusters::codec::FieldKind::U8, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 2, name: "transition_time", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: true },
crate::clusters::codec::CommandField { tag: 3, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 4, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x07 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "options_mask", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
crate::clusters::codec::CommandField { tag: 1, name: "options_override", kind: crate::clusters::codec::FieldKind::Bitmap { name: "Options", bits: &[(1, "EXECUTE_IF_OFF"), (2, "COUPLE_COLOR_TEMP_TO_LEVEL")] }, optional: false, nullable: false },
]),
0x08 => Some(vec![
crate::clusters::codec::CommandField { tag: 0, name: "frequency", kind: crate::clusters::codec::FieldKind::U16, optional: false, nullable: false },
]),
_ => None,
}
}
pub fn encode_command_json(cmd_id: u32, args: &serde_json::Value) -> anyhow::Result<Vec<u8>> {
match cmd_id {
0x00 => {
let level = crate::clusters::codec::json_util::get_u8(args, "level")?;
let transition_time = crate::clusters::codec::json_util::get_opt_u16(args, "transition_time")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_move_to_level(level, transition_time, options_mask, options_override)
}
0x01 => {
let move_mode = {
let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
};
let rate = crate::clusters::codec::json_util::get_opt_u8(args, "rate")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_move_(move_mode, rate, options_mask, options_override)
}
0x02 => {
let step_mode = {
let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
};
let step_size = crate::clusters::codec::json_util::get_u8(args, "step_size")?;
let transition_time = crate::clusters::codec::json_util::get_opt_u16(args, "transition_time")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_step(step_mode, step_size, transition_time, options_mask, options_override)
}
0x03 => {
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_stop(options_mask, options_override)
}
0x04 => {
let level = crate::clusters::codec::json_util::get_u8(args, "level")?;
let transition_time = crate::clusters::codec::json_util::get_opt_u16(args, "transition_time")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_move_to_level_with_on_off(level, transition_time, options_mask, options_override)
}
0x05 => {
let move_mode = {
let n = crate::clusters::codec::json_util::get_u64(args, "move_mode")?;
MoveMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid MoveMode: {}", n))?
};
let rate = crate::clusters::codec::json_util::get_opt_u8(args, "rate")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_move_with_on_off(move_mode, rate, options_mask, options_override)
}
0x06 => {
let step_mode = {
let n = crate::clusters::codec::json_util::get_u64(args, "step_mode")?;
StepMode::from_u8(n as u8).ok_or_else(|| anyhow::anyhow!("invalid StepMode: {}", n))?
};
let step_size = crate::clusters::codec::json_util::get_u8(args, "step_size")?;
let transition_time = crate::clusters::codec::json_util::get_opt_u16(args, "transition_time")?;
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_step_with_on_off(step_mode, step_size, transition_time, options_mask, options_override)
}
0x07 => {
let options_mask = crate::clusters::codec::json_util::get_u8(args, "options_mask")?;
let options_override = crate::clusters::codec::json_util::get_u8(args, "options_override")?;
encode_stop_with_on_off(options_mask, options_override)
}
0x08 => {
let frequency = crate::clusters::codec::json_util::get_u16(args, "frequency")?;
encode_move_to_closest_frequency(frequency)
}
_ => Err(anyhow::anyhow!("unknown command ID: 0x{:02X}", cmd_id)),
}
}
pub async fn move_to_level(conn: &crate::controller::Connection, endpoint: u16, level: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVETOLEVEL, &encode_move_to_level(level, transition_time, options_mask, options_override)?).await?;
Ok(())
}
pub async fn move_(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: Option<u8>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVE, &encode_move_(move_mode, rate, options_mask, options_override)?).await?;
Ok(())
}
pub async fn step(conn: &crate::controller::Connection, endpoint: u16, step_mode: StepMode, step_size: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_STEP, &encode_step(step_mode, step_size, transition_time, options_mask, options_override)?).await?;
Ok(())
}
pub async fn stop(conn: &crate::controller::Connection, endpoint: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_STOP, &encode_stop(options_mask, options_override)?).await?;
Ok(())
}
pub async fn move_to_level_with_on_off(conn: &crate::controller::Connection, endpoint: u16, level: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVETOLEVELWITHONOFF, &encode_move_to_level_with_on_off(level, transition_time, options_mask, options_override)?).await?;
Ok(())
}
pub async fn move_with_on_off(conn: &crate::controller::Connection, endpoint: u16, move_mode: MoveMode, rate: Option<u8>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVEWITHONOFF, &encode_move_with_on_off(move_mode, rate, options_mask, options_override)?).await?;
Ok(())
}
pub async fn step_with_on_off(conn: &crate::controller::Connection, endpoint: u16, step_mode: StepMode, step_size: u8, transition_time: Option<u16>, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_STEPWITHONOFF, &encode_step_with_on_off(step_mode, step_size, transition_time, options_mask, options_override)?).await?;
Ok(())
}
pub async fn stop_with_on_off(conn: &crate::controller::Connection, endpoint: u16, options_mask: Options, options_override: Options) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_STOPWITHONOFF, &encode_stop_with_on_off(options_mask, options_override)?).await?;
Ok(())
}
pub async fn move_to_closest_frequency(conn: &crate::controller::Connection, endpoint: u16, frequency: u16) -> anyhow::Result<()> {
conn.invoke_request(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_CMD_ID_MOVETOCLOSESTFREQUENCY, &encode_move_to_closest_frequency(frequency)?).await?;
Ok(())
}
pub async fn read_current_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_CURRENTLEVEL).await?;
decode_current_level(&tlv)
}
pub async fn read_remaining_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_REMAININGTIME).await?;
decode_remaining_time(&tlv)
}
pub async fn read_min_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_MINLEVEL).await?;
decode_min_level(&tlv)
}
pub async fn read_max_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u8> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_MAXLEVEL).await?;
decode_max_level(&tlv)
}
pub async fn read_current_frequency(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_CURRENTFREQUENCY).await?;
decode_current_frequency(&tlv)
}
pub async fn read_min_frequency(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_MINFREQUENCY).await?;
decode_min_frequency(&tlv)
}
pub async fn read_max_frequency(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_MAXFREQUENCY).await?;
decode_max_frequency(&tlv)
}
pub async fn read_options(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Options> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_OPTIONS).await?;
decode_options(&tlv)
}
pub async fn read_on_off_transition_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<u16> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_ONOFFTRANSITIONTIME).await?;
decode_on_off_transition_time(&tlv)
}
pub async fn read_on_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_ONLEVEL).await?;
decode_on_level(&tlv)
}
pub async fn read_on_transition_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_ONTRANSITIONTIME).await?;
decode_on_transition_time(&tlv)
}
pub async fn read_off_transition_time(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u16>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_OFFTRANSITIONTIME).await?;
decode_off_transition_time(&tlv)
}
pub async fn read_default_move_rate(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_DEFAULTMOVERATE).await?;
decode_default_move_rate(&tlv)
}
pub async fn read_start_up_current_level(conn: &crate::controller::Connection, endpoint: u16) -> anyhow::Result<Option<u8>> {
let tlv = conn.read_request2(endpoint, crate::clusters::defs::CLUSTER_ID_LEVEL_CONTROL, crate::clusters::defs::CLUSTER_LEVEL_CONTROL_ATTR_ID_STARTUPCURRENTLEVEL).await?;
decode_start_up_current_level(&tlv)
}