first commit
This commit is contained in:
35
crates/zcl/src/cluster/colorctrl.rs
Normal file
35
crates/zcl/src/cluster/colorctrl.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, _data: &[u8]) -> Option<String> {
|
||||
if frame.manufacturer_specific() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if frame.flags.direction != ZclFrameDirection::ClientToServer {
|
||||
return None;
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
0x00 => Some("MoveToHue".to_string()),
|
||||
0x01 => Some("MoveHue".to_string()),
|
||||
0x02 => Some("StepHue".to_string()),
|
||||
0x03 => Some("MoveToSaturation".to_string()),
|
||||
0x04 => Some("MoveSaturation".to_string()),
|
||||
0x05 => Some("StepSaturation".to_string()),
|
||||
0x06 => Some("MoveToHueAndSaturation".to_string()),
|
||||
0x07 => Some("MoveToColor".to_string()),
|
||||
0x08 => Some("MoveColor".to_string()),
|
||||
0x09 => Some("StepColor".to_string()),
|
||||
0x0a => Some("MoveToColorTemp".to_string()),
|
||||
0x40 => Some("EnhancedMoveToHue".to_string()),
|
||||
0x41 => Some("EnhancedMoveHue".to_string()),
|
||||
0x42 => Some("EnhancedStepHue".to_string()),
|
||||
0x43 => Some("EnhancedMoveToHueAndSaturation".to_string()),
|
||||
0x44 => Some("ColorLoopSet".to_string()),
|
||||
0x47 => Some("StopMoveStep".to_string()),
|
||||
0x4b => Some("MoveColorTemp".to_string()),
|
||||
0x4c => Some("StepColorTemp".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
20
crates/zcl/src/cluster/commissioning.rs
Normal file
20
crates/zcl/src/cluster/commissioning.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use crate::error::ZclResult;
|
||||
use crate::frame::ZclFrame;
|
||||
use hue::zigbee::HueEntFrame;
|
||||
|
||||
pub fn describe(frame: &ZclFrame, data: &[u8]) -> ZclResult<Option<String>> {
|
||||
if !frame.cluster_specific() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
0x00 => Ok(Some("ScanRequest".to_string())),
|
||||
0x02 => {
|
||||
let (data, csum) = data.split_at(data.len() - 4);
|
||||
let csum = u32::from_be_bytes([csum[0], csum[1], csum[2], csum[3]]);
|
||||
let hes = HueEntFrame::parse(data)?;
|
||||
Ok(Some(format!("{hes:x?} [PROXY, {csum:08x}]")))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
13
crates/zcl/src/cluster/effects.rs
Normal file
13
crates/zcl/src/cluster/effects.rs
Normal file
@@ -0,0 +1,13 @@
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, _data: &[u8]) -> Option<String> {
|
||||
if frame.flags.direction == ZclFrameDirection::ClientToServer {
|
||||
match frame.cmd {
|
||||
0x40 => Some("Trigger".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
18
crates/zcl/src/cluster/groups.rs
Normal file
18
crates/zcl/src/cluster/groups.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, _data: &[u8]) -> Option<String> {
|
||||
if frame.flags.direction == ZclFrameDirection::ClientToServer {
|
||||
match frame.cmd {
|
||||
0x00 => Some("Add".to_string()),
|
||||
0x02 => Some("GetMembership".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
match frame.cmd {
|
||||
0x00 => Some("AddResp".to_string()),
|
||||
0x02 => Some("GetMembershipResp".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
26
crates/zcl/src/cluster/hue_fc01.rs
Normal file
26
crates/zcl/src/cluster/hue_fc01.rs
Normal file
@@ -0,0 +1,26 @@
|
||||
use packed_struct::PackedStructSlice;
|
||||
|
||||
use crate::error::ZclResult;
|
||||
use crate::frame::ZclFrame;
|
||||
use hue::zigbee::{HueEntFrame, HueEntSegmentConfig, HueEntSegmentLayout, HueEntStop};
|
||||
|
||||
pub fn describe(frame: &ZclFrame, data: &[u8]) -> ZclResult<Option<String>> {
|
||||
if !frame.cluster_specific() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
1 => Ok(Some(format!("{:x?}", HueEntFrame::parse(data)?))),
|
||||
3 => Ok(Some(format!("{:x?}", HueEntStop::unpack_from_slice(data)?))),
|
||||
4 => {
|
||||
let res = if frame.c2s() && data.len() == 1 {
|
||||
"HueEntSegmentLayoutReq".to_string()
|
||||
} else {
|
||||
format!("{:x?}", HueEntSegmentLayout::parse(data)?)
|
||||
};
|
||||
Ok(Some(res))
|
||||
}
|
||||
7 => Ok(Some(format!("{:x?}", HueEntSegmentConfig::parse(data)?))),
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
18
crates/zcl/src/cluster/hue_fc03.rs
Normal file
18
crates/zcl/src/cluster/hue_fc03.rs
Normal file
@@ -0,0 +1,18 @@
|
||||
use hue::zigbee::Flags;
|
||||
|
||||
use crate::error::ZclResult;
|
||||
use crate::frame::ZclFrame;
|
||||
|
||||
pub fn describe(frame: &ZclFrame, data: &[u8]) -> ZclResult<Option<String>> {
|
||||
if !frame.cluster_specific() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
0x00 => {
|
||||
let zflags = Flags::from_bits(u16::from(data[0]) | (u16::from(data[1]) << 8)).unwrap();
|
||||
Ok(Some(format!("{:?} {}", zflags, hex::encode(&data[2..]))))
|
||||
}
|
||||
_ => Ok(None),
|
||||
}
|
||||
}
|
||||
24
crates/zcl/src/cluster/levelctrl.rs
Normal file
24
crates/zcl/src/cluster/levelctrl.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, _data: &[u8]) -> Option<String> {
|
||||
if frame.manufacturer_specific() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if frame.flags.direction != ZclFrameDirection::ClientToServer {
|
||||
return None;
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
0x00 => Some("MoveToLevel".to_string()),
|
||||
0x01 => Some("Move".to_string()),
|
||||
0x02 => Some("Step".to_string()),
|
||||
0x03 => Some("Stop".to_string()),
|
||||
0x04 => Some("MoveToLevelWithOnOff".to_string()),
|
||||
0x05 => Some("MoveWithOnOff".to_string()),
|
||||
0x06 => Some("StepWithOnOff".to_string()),
|
||||
0x07 => Some("StopWithOnOff".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
10
crates/zcl/src/cluster/mod.rs
Normal file
10
crates/zcl/src/cluster/mod.rs
Normal file
@@ -0,0 +1,10 @@
|
||||
pub mod colorctrl;
|
||||
pub mod commissioning;
|
||||
pub mod effects;
|
||||
pub mod groups;
|
||||
pub mod hue_fc01;
|
||||
pub mod hue_fc03;
|
||||
pub mod levelctrl;
|
||||
pub mod onoff;
|
||||
pub mod scenes;
|
||||
pub mod standard;
|
||||
19
crates/zcl/src/cluster/onoff.rs
Normal file
19
crates/zcl/src/cluster/onoff.rs
Normal file
@@ -0,0 +1,19 @@
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, _data: &[u8]) -> Option<String> {
|
||||
if frame.manufacturer_specific() {
|
||||
return None;
|
||||
}
|
||||
|
||||
if frame.flags.direction != ZclFrameDirection::ClientToServer {
|
||||
return None;
|
||||
}
|
||||
|
||||
match frame.cmd {
|
||||
0x00 => Some("Off".to_string()),
|
||||
0x01 => Some("On".to_string()),
|
||||
0x40 => Some("OffWithEffect".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
39
crates/zcl/src/cluster/scenes.rs
Normal file
39
crates/zcl/src/cluster/scenes.rs
Normal file
@@ -0,0 +1,39 @@
|
||||
#![allow(clippy::collapsible_else_if)]
|
||||
|
||||
use hue::zigbee::Flags;
|
||||
|
||||
use crate::frame::{ZclFrame, ZclFrameDirection};
|
||||
|
||||
#[must_use]
|
||||
pub fn describe(frame: &ZclFrame, data: &[u8]) -> Option<String> {
|
||||
if frame.manufacturer_specific() {
|
||||
if frame.flags.direction == ZclFrameDirection::ClientToServer {
|
||||
match frame.cmd {
|
||||
0x02 => Some(format!(
|
||||
"SetComposite {:?}",
|
||||
Flags::from_bits(u16::from(data[3]) | (u16::from(data[4]) << 8)).unwrap()
|
||||
)),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
match frame.cmd {
|
||||
0x02 => Some("SetCompositeOk".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if frame.flags.direction == ZclFrameDirection::ClientToServer {
|
||||
match frame.cmd {
|
||||
0x02 => Some("Remove".to_string()),
|
||||
0x05 => Some("Recall".to_string()),
|
||||
0x06 => Some("GetMembership".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
match frame.cmd {
|
||||
0x06 => Some("GetMembershipResp".to_string()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
41
crates/zcl/src/cluster/standard.rs
Normal file
41
crates/zcl/src/cluster/standard.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use packed_struct::PrimitiveEnum;
|
||||
|
||||
use crate::attr::{
|
||||
ZclCommand, ZclReadAttr, ZclReadAttrResp, ZclReportAttr, ZclWriteAttr, ZclWriteAttrResp,
|
||||
};
|
||||
use crate::error::ZclResult;
|
||||
use crate::frame::ZclFrame;
|
||||
|
||||
pub fn describe(frame: &ZclFrame, data: &[u8]) -> ZclResult<Option<String>> {
|
||||
let cmd = ZclCommand::from_primitive(frame.cmd);
|
||||
let desc = match cmd {
|
||||
Some(ZclCommand::ReadAttrib) => {
|
||||
let req = ZclReadAttr::parse(data)?;
|
||||
Some(format!("Attr rd -> {:04x?}", req.attr))
|
||||
}
|
||||
Some(ZclCommand::ReadAttribResp) => {
|
||||
let req = ZclReadAttrResp::parse(data)?;
|
||||
Some(format!("Attr rd <- {:?}", req.attr))
|
||||
}
|
||||
Some(ZclCommand::WriteAttrib) => {
|
||||
let req = ZclWriteAttr::parse(data)?;
|
||||
Some(format!("Attr wr -> {:?}", req.attr))
|
||||
}
|
||||
Some(ZclCommand::WriteAttribResp) => {
|
||||
let req = ZclWriteAttrResp::parse(data)?;
|
||||
Some(format!("Attr wr <- {:02x?}", req.attr))
|
||||
}
|
||||
Some(ZclCommand::ReportAttrib) => {
|
||||
let req = ZclReportAttr::parse(data)?;
|
||||
Some(format!("Attr rp <- {:02x?}", req.attr))
|
||||
}
|
||||
Some(ZclCommand::DefaultResp) => {
|
||||
/* let req = ZclDefaultResp::parse(data)?; */
|
||||
/* format!("Attr dr <- {:02x} {:02x}", req.cmd, req.stat) */
|
||||
return Ok(Some(String::new()));
|
||||
}
|
||||
_ => None,
|
||||
};
|
||||
|
||||
Ok(desc)
|
||||
}
|
||||
Reference in New Issue
Block a user