1#![allow(
5 clippy::all,
6 clippy::pedantic,
7 dead_code,
8 unreachable_pub,
9 unused_imports
10)]
11
12use crate::datatypes::SemanticTagStruct;
13use crate::error::ClusterError;
14use crate::types::Nullable;
15use matter_codec::{ContainerKind, Element, Tag, TlvReader, TlvWriter, Value};
16
17pub const CLUSTER_ID: u32 = 0x0200;
19pub const CLUSTER_REVISION: u16 = 5;
21
22pub mod command_id {}
24
25pub mod attribute_id {
27 pub const MAX_PRESSURE: u32 = 0x0000;
29 pub const MAX_SPEED: u32 = 0x0001;
31 pub const MAX_FLOW: u32 = 0x0002;
33 pub const MIN_CONST_PRESSURE: u32 = 0x0003;
35 pub const MAX_CONST_PRESSURE: u32 = 0x0004;
37 pub const MIN_COMP_PRESSURE: u32 = 0x0005;
39 pub const MAX_COMP_PRESSURE: u32 = 0x0006;
41 pub const MIN_CONST_SPEED: u32 = 0x0007;
43 pub const MAX_CONST_SPEED: u32 = 0x0008;
45 pub const MIN_CONST_FLOW: u32 = 0x0009;
47 pub const MAX_CONST_FLOW: u32 = 0x000A;
49 pub const MIN_CONST_TEMP: u32 = 0x000B;
51 pub const MAX_CONST_TEMP: u32 = 0x000C;
53 pub const PUMP_STATUS: u32 = 0x0010;
55 pub const EFFECTIVE_OPERATION_MODE: u32 = 0x0011;
57 pub const EFFECTIVE_CONTROL_MODE: u32 = 0x0012;
59 pub const CAPACITY: u32 = 0x0013;
61 pub const SPEED: u32 = 0x0014;
63 pub const LIFETIME_RUNNING_HOURS: u32 = 0x0015;
65 pub const POWER: u32 = 0x0016;
67 pub const LIFETIME_ENERGY_CONSUMED: u32 = 0x0017;
69 pub const OPERATION_MODE: u32 = 0x0020;
71 pub const CONTROL_MODE: u32 = 0x0021;
73}
74
75bitflags::bitflags! {
76 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
78 pub struct Feature: u32 {
79 const PRSCONST = 1 << 0;
81 const PRSCOMP = 1 << 1;
83 const FLW = 1 << 2;
85 const SPD = 1 << 3;
87 const TEMP = 1 << 4;
89 const AUTO = 1 << 5;
91 const LOCAL = 1 << 6;
93 }
94}
95
96#[derive(Copy, Clone, Debug, PartialEq, Eq)]
98pub enum ControlModeEnum {
99 ConstantSpeed,
101 ConstantPressure,
103 ProportionalPressure,
105 ConstantFlow,
107 ConstantTemperature,
109 Automatic,
111 Unknown(u8),
113}
114
115impl ControlModeEnum {
116 #[must_use]
118 pub fn from_raw(v: u8) -> Self {
119 match v {
120 0 => Self::ConstantSpeed,
121 1 => Self::ConstantPressure,
122 2 => Self::ProportionalPressure,
123 3 => Self::ConstantFlow,
124 5 => Self::ConstantTemperature,
125 7 => Self::Automatic,
126 other => Self::Unknown(other),
127 }
128 }
129 #[must_use]
131 pub fn to_raw(self) -> u8 {
132 match self {
133 Self::ConstantSpeed => 0,
134 Self::ConstantPressure => 1,
135 Self::ProportionalPressure => 2,
136 Self::ConstantFlow => 3,
137 Self::ConstantTemperature => 5,
138 Self::Automatic => 7,
139 Self::Unknown(v) => v,
140 }
141 }
142}
143
144#[derive(Copy, Clone, Debug, PartialEq, Eq)]
146pub enum OperationModeEnum {
147 Normal,
149 Minimum,
151 Maximum,
153 Local,
155 Unknown(u8),
157}
158
159impl OperationModeEnum {
160 #[must_use]
162 pub fn from_raw(v: u8) -> Self {
163 match v {
164 0 => Self::Normal,
165 1 => Self::Minimum,
166 2 => Self::Maximum,
167 3 => Self::Local,
168 other => Self::Unknown(other),
169 }
170 }
171 #[must_use]
173 pub fn to_raw(self) -> u8 {
174 match self {
175 Self::Normal => 0,
176 Self::Minimum => 1,
177 Self::Maximum => 2,
178 Self::Local => 3,
179 Self::Unknown(v) => v,
180 }
181 }
182}
183
184bitflags::bitflags! {
185 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
187 pub struct PumpStatusBitmap: u16 {
188 const DEVICE_FAULT = 1 << 0;
190 const SUPPLY_FAULT = 1 << 1;
192 const SPEED_LOW = 1 << 2;
194 const SPEED_HIGH = 1 << 3;
196 const LOCAL_OVERRIDE = 1 << 4;
198 const RUNNING = 1 << 5;
200 const REMOTE_PRESSURE = 1 << 6;
202 const REMOTE_FLOW = 1 << 7;
204 const REMOTE_TEMPERATURE = 1 << 8;
206 }
207}
208
209pub fn decode_max_pressure(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
214 let mut r = TlvReader::new(tlv);
215 match r.next()? {
216 Some(Element::Scalar {
217 value: Value::Null, ..
218 }) => Ok(Nullable::Null),
219 Some(Element::Scalar {
220 value: Value::Int(v),
221 ..
222 }) => Ok(Nullable::Value(
223 i16::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxPressure"))?,
224 )),
225 _ => Err(ClusterError::UnexpectedType {
226 context: "MaxPressure",
227 }),
228 }
229}
230
231pub fn decode_max_speed(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
236 let mut r = TlvReader::new(tlv);
237 match r.next()? {
238 Some(Element::Scalar {
239 value: Value::Null, ..
240 }) => Ok(Nullable::Null),
241 Some(Element::Scalar {
242 value: Value::Uint(v),
243 ..
244 }) => Ok(Nullable::Value(
245 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxSpeed"))?,
246 )),
247 _ => Err(ClusterError::UnexpectedType {
248 context: "MaxSpeed",
249 }),
250 }
251}
252
253pub fn decode_max_flow(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
258 let mut r = TlvReader::new(tlv);
259 match r.next()? {
260 Some(Element::Scalar {
261 value: Value::Null, ..
262 }) => Ok(Nullable::Null),
263 Some(Element::Scalar {
264 value: Value::Uint(v),
265 ..
266 }) => Ok(Nullable::Value(
267 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("MaxFlow"))?,
268 )),
269 _ => Err(ClusterError::UnexpectedType { context: "MaxFlow" }),
270 }
271}
272
273pub fn decode_min_const_pressure(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
278 let mut r = TlvReader::new(tlv);
279 match r.next()? {
280 Some(Element::Scalar {
281 value: Value::Null, ..
282 }) => Ok(Nullable::Null),
283 Some(Element::Scalar {
284 value: Value::Int(v),
285 ..
286 }) => {
287 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
288 ClusterError::InvalidLength("MinConstPressure")
289 })?))
290 }
291 _ => Err(ClusterError::UnexpectedType {
292 context: "MinConstPressure",
293 }),
294 }
295}
296
297pub fn decode_max_const_pressure(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
302 let mut r = TlvReader::new(tlv);
303 match r.next()? {
304 Some(Element::Scalar {
305 value: Value::Null, ..
306 }) => Ok(Nullable::Null),
307 Some(Element::Scalar {
308 value: Value::Int(v),
309 ..
310 }) => {
311 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
312 ClusterError::InvalidLength("MaxConstPressure")
313 })?))
314 }
315 _ => Err(ClusterError::UnexpectedType {
316 context: "MaxConstPressure",
317 }),
318 }
319}
320
321pub fn decode_min_comp_pressure(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
326 let mut r = TlvReader::new(tlv);
327 match r.next()? {
328 Some(Element::Scalar {
329 value: Value::Null, ..
330 }) => Ok(Nullable::Null),
331 Some(Element::Scalar {
332 value: Value::Int(v),
333 ..
334 }) => {
335 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
336 ClusterError::InvalidLength("MinCompPressure")
337 })?))
338 }
339 _ => Err(ClusterError::UnexpectedType {
340 context: "MinCompPressure",
341 }),
342 }
343}
344
345pub fn decode_max_comp_pressure(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
350 let mut r = TlvReader::new(tlv);
351 match r.next()? {
352 Some(Element::Scalar {
353 value: Value::Null, ..
354 }) => Ok(Nullable::Null),
355 Some(Element::Scalar {
356 value: Value::Int(v),
357 ..
358 }) => {
359 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
360 ClusterError::InvalidLength("MaxCompPressure")
361 })?))
362 }
363 _ => Err(ClusterError::UnexpectedType {
364 context: "MaxCompPressure",
365 }),
366 }
367}
368
369pub fn decode_min_const_speed(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
374 let mut r = TlvReader::new(tlv);
375 match r.next()? {
376 Some(Element::Scalar {
377 value: Value::Null, ..
378 }) => Ok(Nullable::Null),
379 Some(Element::Scalar {
380 value: Value::Uint(v),
381 ..
382 }) => {
383 Ok(Nullable::Value(u16::try_from(v).map_err(|_| {
384 ClusterError::InvalidLength("MinConstSpeed")
385 })?))
386 }
387 _ => Err(ClusterError::UnexpectedType {
388 context: "MinConstSpeed",
389 }),
390 }
391}
392
393pub fn decode_max_const_speed(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
398 let mut r = TlvReader::new(tlv);
399 match r.next()? {
400 Some(Element::Scalar {
401 value: Value::Null, ..
402 }) => Ok(Nullable::Null),
403 Some(Element::Scalar {
404 value: Value::Uint(v),
405 ..
406 }) => {
407 Ok(Nullable::Value(u16::try_from(v).map_err(|_| {
408 ClusterError::InvalidLength("MaxConstSpeed")
409 })?))
410 }
411 _ => Err(ClusterError::UnexpectedType {
412 context: "MaxConstSpeed",
413 }),
414 }
415}
416
417pub fn decode_min_const_flow(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
422 let mut r = TlvReader::new(tlv);
423 match r.next()? {
424 Some(Element::Scalar {
425 value: Value::Null, ..
426 }) => Ok(Nullable::Null),
427 Some(Element::Scalar {
428 value: Value::Uint(v),
429 ..
430 }) => {
431 Ok(Nullable::Value(u16::try_from(v).map_err(|_| {
432 ClusterError::InvalidLength("MinConstFlow")
433 })?))
434 }
435 _ => Err(ClusterError::UnexpectedType {
436 context: "MinConstFlow",
437 }),
438 }
439}
440
441pub fn decode_max_const_flow(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
446 let mut r = TlvReader::new(tlv);
447 match r.next()? {
448 Some(Element::Scalar {
449 value: Value::Null, ..
450 }) => Ok(Nullable::Null),
451 Some(Element::Scalar {
452 value: Value::Uint(v),
453 ..
454 }) => {
455 Ok(Nullable::Value(u16::try_from(v).map_err(|_| {
456 ClusterError::InvalidLength("MaxConstFlow")
457 })?))
458 }
459 _ => Err(ClusterError::UnexpectedType {
460 context: "MaxConstFlow",
461 }),
462 }
463}
464
465pub fn decode_min_const_temp(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
470 let mut r = TlvReader::new(tlv);
471 match r.next()? {
472 Some(Element::Scalar {
473 value: Value::Null, ..
474 }) => Ok(Nullable::Null),
475 Some(Element::Scalar {
476 value: Value::Int(v),
477 ..
478 }) => {
479 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
480 ClusterError::InvalidLength("MinConstTemp")
481 })?))
482 }
483 _ => Err(ClusterError::UnexpectedType {
484 context: "MinConstTemp",
485 }),
486 }
487}
488
489pub fn decode_max_const_temp(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
494 let mut r = TlvReader::new(tlv);
495 match r.next()? {
496 Some(Element::Scalar {
497 value: Value::Null, ..
498 }) => Ok(Nullable::Null),
499 Some(Element::Scalar {
500 value: Value::Int(v),
501 ..
502 }) => {
503 Ok(Nullable::Value(i16::try_from(v).map_err(|_| {
504 ClusterError::InvalidLength("MaxConstTemp")
505 })?))
506 }
507 _ => Err(ClusterError::UnexpectedType {
508 context: "MaxConstTemp",
509 }),
510 }
511}
512
513pub fn decode_pump_status(tlv: &[u8]) -> Result<PumpStatusBitmap, ClusterError> {
518 let mut r = TlvReader::new(tlv);
519 match r.next()? {
520 Some(Element::Scalar {
521 value: Value::Uint(v),
522 ..
523 }) => Ok(PumpStatusBitmap::from_bits_retain(
524 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("PumpStatus"))?,
525 )),
526 _ => Err(ClusterError::UnexpectedType {
527 context: "PumpStatus",
528 }),
529 }
530}
531
532pub fn decode_effective_operation_mode(tlv: &[u8]) -> Result<OperationModeEnum, ClusterError> {
537 let mut r = TlvReader::new(tlv);
538 match r.next()? {
539 Some(Element::Scalar {
540 value: Value::Uint(v),
541 ..
542 }) => Ok(OperationModeEnum::from_raw(u8::try_from(v).map_err(
543 |_| ClusterError::InvalidLength("EffectiveOperationMode"),
544 )?)),
545 _ => Err(ClusterError::UnexpectedType {
546 context: "EffectiveOperationMode",
547 }),
548 }
549}
550
551pub fn decode_effective_control_mode(tlv: &[u8]) -> Result<ControlModeEnum, ClusterError> {
556 let mut r = TlvReader::new(tlv);
557 match r.next()? {
558 Some(Element::Scalar {
559 value: Value::Uint(v),
560 ..
561 }) => Ok(ControlModeEnum::from_raw(u8::try_from(v).map_err(
562 |_| ClusterError::InvalidLength("EffectiveControlMode"),
563 )?)),
564 _ => Err(ClusterError::UnexpectedType {
565 context: "EffectiveControlMode",
566 }),
567 }
568}
569
570pub fn decode_capacity(tlv: &[u8]) -> Result<Nullable<i16>, ClusterError> {
575 let mut r = TlvReader::new(tlv);
576 match r.next()? {
577 Some(Element::Scalar {
578 value: Value::Null, ..
579 }) => Ok(Nullable::Null),
580 Some(Element::Scalar {
581 value: Value::Int(v),
582 ..
583 }) => Ok(Nullable::Value(
584 i16::try_from(v).map_err(|_| ClusterError::InvalidLength("Capacity"))?,
585 )),
586 _ => Err(ClusterError::UnexpectedType {
587 context: "Capacity",
588 }),
589 }
590}
591
592pub fn decode_speed(tlv: &[u8]) -> Result<Nullable<u16>, ClusterError> {
597 let mut r = TlvReader::new(tlv);
598 match r.next()? {
599 Some(Element::Scalar {
600 value: Value::Null, ..
601 }) => Ok(Nullable::Null),
602 Some(Element::Scalar {
603 value: Value::Uint(v),
604 ..
605 }) => Ok(Nullable::Value(
606 u16::try_from(v).map_err(|_| ClusterError::InvalidLength("Speed"))?,
607 )),
608 _ => Err(ClusterError::UnexpectedType { context: "Speed" }),
609 }
610}
611
612pub fn decode_lifetime_running_hours(tlv: &[u8]) -> Result<Nullable<u32>, ClusterError> {
617 let mut r = TlvReader::new(tlv);
618 match r.next()? {
619 Some(Element::Scalar {
620 value: Value::Null, ..
621 }) => Ok(Nullable::Null),
622 Some(Element::Scalar {
623 value: Value::Uint(v),
624 ..
625 }) => Ok(Nullable::Value(u32::try_from(v).map_err(|_| {
626 ClusterError::InvalidLength("LifetimeRunningHours")
627 })?)),
628 _ => Err(ClusterError::UnexpectedType {
629 context: "LifetimeRunningHours",
630 }),
631 }
632}
633
634#[must_use]
636#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_lifetime_running_hours(value: Nullable<u32>) -> Vec<u8> {
638 let mut buf = Vec::new();
639 let mut w = TlvWriter::new(&mut buf);
640 match value {
641 Nullable::Null => w.put_null(Tag::Anonymous).expect("infallible: vec writer"),
642 Nullable::Value(value) => {
643 w.put_uint(Tag::Anonymous, u64::from(value))
644 .expect("infallible: vec writer");
645 }
646 }
647 buf
648}
649
650pub fn decode_power(tlv: &[u8]) -> Result<Nullable<u32>, ClusterError> {
655 let mut r = TlvReader::new(tlv);
656 match r.next()? {
657 Some(Element::Scalar {
658 value: Value::Null, ..
659 }) => Ok(Nullable::Null),
660 Some(Element::Scalar {
661 value: Value::Uint(v),
662 ..
663 }) => Ok(Nullable::Value(
664 u32::try_from(v).map_err(|_| ClusterError::InvalidLength("Power"))?,
665 )),
666 _ => Err(ClusterError::UnexpectedType { context: "Power" }),
667 }
668}
669
670pub fn decode_lifetime_energy_consumed(tlv: &[u8]) -> Result<Nullable<u32>, ClusterError> {
675 let mut r = TlvReader::new(tlv);
676 match r.next()? {
677 Some(Element::Scalar {
678 value: Value::Null, ..
679 }) => Ok(Nullable::Null),
680 Some(Element::Scalar {
681 value: Value::Uint(v),
682 ..
683 }) => Ok(Nullable::Value(u32::try_from(v).map_err(|_| {
684 ClusterError::InvalidLength("LifetimeEnergyConsumed")
685 })?)),
686 _ => Err(ClusterError::UnexpectedType {
687 context: "LifetimeEnergyConsumed",
688 }),
689 }
690}
691
692#[must_use]
694#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_lifetime_energy_consumed(value: Nullable<u32>) -> Vec<u8> {
696 let mut buf = Vec::new();
697 let mut w = TlvWriter::new(&mut buf);
698 match value {
699 Nullable::Null => w.put_null(Tag::Anonymous).expect("infallible: vec writer"),
700 Nullable::Value(value) => {
701 w.put_uint(Tag::Anonymous, u64::from(value))
702 .expect("infallible: vec writer");
703 }
704 }
705 buf
706}
707
708pub fn decode_operation_mode(tlv: &[u8]) -> Result<OperationModeEnum, ClusterError> {
713 let mut r = TlvReader::new(tlv);
714 match r.next()? {
715 Some(Element::Scalar {
716 value: Value::Uint(v),
717 ..
718 }) => Ok(OperationModeEnum::from_raw(
719 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("OperationMode"))?,
720 )),
721 _ => Err(ClusterError::UnexpectedType {
722 context: "OperationMode",
723 }),
724 }
725}
726
727#[must_use]
729#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_operation_mode(value: OperationModeEnum) -> Vec<u8> {
731 let mut buf = Vec::new();
732 let mut w = TlvWriter::new(&mut buf);
733 w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
734 .expect("infallible: vec writer");
735 buf
736}
737
738pub fn decode_control_mode(tlv: &[u8]) -> Result<ControlModeEnum, ClusterError> {
743 let mut r = TlvReader::new(tlv);
744 match r.next()? {
745 Some(Element::Scalar {
746 value: Value::Uint(v),
747 ..
748 }) => Ok(ControlModeEnum::from_raw(
749 u8::try_from(v).map_err(|_| ClusterError::InvalidLength("ControlMode"))?,
750 )),
751 _ => Err(ClusterError::UnexpectedType {
752 context: "ControlMode",
753 }),
754 }
755}
756
757#[must_use]
759#[allow(clippy::expect_used, clippy::missing_panics_doc)] pub fn encode_control_mode(value: ControlModeEnum) -> Vec<u8> {
761 let mut buf = Vec::new();
762 let mut w = TlvWriter::new(&mut buf);
763 w.put_uint(Tag::Anonymous, u64::from(value.to_raw()))
764 .expect("infallible: vec writer");
765 buf
766}