Skip to content

Commit 8f6a786

Browse files
committed
WIP
1 parent b9fad2d commit 8f6a786

15 files changed

Lines changed: 914 additions & 595 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
anyhow = "1.0.99"
8+
arrayvec = "0.7.6"
89
bitflags = "2.9.1"
910
color_space = "0.5.4"
1011
crc = "3.3.0"

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,2 @@
1-
#![allow(missing_docs)] // TODO
2-
31
pub mod misc;
42
pub mod protocol;

src/main.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(missing_docs)] // TODO
2-
31
use std::io::stdin;
42
use std::mem::take;
53
use std::num::ParseIntError;

src/misc/binary_io.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
#![allow(missing_docs, clippy::missing_errors_doc)] // TODO
2-
31
use std::convert::Infallible;
42
use std::fmt::Display;
53
use std::io::{Error as IoError, Read, Write};
64
use std::marker::PhantomData;
75

8-
use smallvec::{Array, SmallVec};
6+
use arrayvec::ArrayVec;
97
use thiserror::Error;
108

119
use crate::misc::wrapped::RangeError;
@@ -216,10 +214,9 @@ impl BinaryRead for i16 {
216214
impl<T, const N: usize> BinaryRead for [T; N]
217215
where
218216
T: BinaryRead,
219-
[T; N]: Array<Item = T>,
220217
{
221218
fn decode<R: Reader>(reader: &mut R) -> Result<ReaderOutput<R, Self>, Error> {
222-
let mut data = R::guard(|_| SmallVec::<[T; N]>::new());
219+
let mut data = R::guard(|_| ArrayVec::<T, N>::new());
223220

224221
for _ in 0..N {
225222
let item = T::decode(reader)?;

src/misc/mod.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(missing_docs)] // TODO
2-
31
mod binary_io;
42
mod crc;
53
mod wrapped;

src/misc/wrapped.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#![allow(missing_docs, clippy::missing_errors_doc)] // TODO
2-
31
use std::fmt::{Debug, Display};
42
use std::marker::PhantomData;
53
use std::ops::Deref;
@@ -10,9 +8,11 @@ use crate::misc::{BinaryIoError, BinaryRead, Guard, Reader, ReaderOutput};
108

119
#[macro_export]
1210
macro_rules! define_wrapped {
13-
($name:ident<$base:ty, $tag:ident>) => {
11+
($(#[$meta:meta])* $name:ident<$base:ty, $tag:ident>) => {
12+
$(#[$meta])*
1413
pub type $name = $crate::misc::Wrapped<$base, $tag>;
1514

15+
#[allow(missing_docs)]
1616
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
1717
pub struct $tag;
1818
};

src/protocol/mod.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
#![allow(missing_docs)] // TODO
2-
3-
pub mod sensor_values;
1+
pub mod settings;
42

53
use crate::misc::{BinaryIoError, BinaryRead, CrcReader, Guard, Reader, ReaderOutput};
64

7-
pub use self::sensor_values::SensorValues;
5+
pub use self::settings::Settings;
86

97
#[derive(Debug, Clone, Eq, PartialEq)]
108
pub enum Frame {
11-
SensorValues(SensorValues),
9+
SensorValues(Settings),
1210
}
1311

1412
impl BinaryRead for Frame {
@@ -18,7 +16,7 @@ impl BinaryRead for Frame {
1816

1917
let ret = match op_code {
2018
0x03 => {
21-
let ret = SensorValues::decode(&mut crc)?;
19+
let ret = Settings::decode(&mut crc)?;
2220

2321
R::guard(|x| Self::SensorValues(x.extract(ret)))
2422
}

src/protocol/settings/alarm.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use bitflags::bitflags;
2+
3+
use crate::{define_wrapped, impl_ranged, misc::{BinaryIoError, BinaryRead, Guard, Reader, ReaderOutput}};
4+
5+
use super::{Flow, flag_set};
6+
7+
/// Alarm related settings for a high flow NEXT device.
8+
#[derive(Debug, Clone, Eq, PartialEq)]
9+
pub struct AlarmSettings {
10+
/// Different flags.
11+
pub flags: AlarmFlags,
12+
13+
/// Time to disable the alarms after boot to give the system time to start.
14+
pub startup_delay: StartupDelay,
15+
16+
/// Whether to raise an alarm if the flow of the device drops below the
17+
/// configured value or not.
18+
pub flow_alarm_limit: Option<Flow>,
19+
20+
/// Whether to raise an alarm if the water temperature of the device raises
21+
/// above the configured value or not.
22+
pub water_temperature_limit: Option<Temperature>,
23+
24+
/// Whether to raise an alarm if the external temperature of the device raises
25+
/// above the configured value or not.
26+
pub external_temperature_limit: Option<Temperature>,
27+
28+
/// Whether to raise an alarm if the water quality of the device drops below
29+
/// the configured value or not.
30+
pub water_quality_limit: Option<WaterQuality>,
31+
32+
/// Signal to output at the signal output connector.
33+
pub output_signal: OutputSignal,
34+
}
35+
36+
impl BinaryRead for AlarmSettings {
37+
fn decode<R: Reader>(reader: &mut R) -> Result<ReaderOutput<R, Self>, BinaryIoError> {
38+
let flags = AlarmFlags::decode(reader)?;
39+
let alarms = reader.read_u8()?;
40+
reader.skip::<1>()?;
41+
let startup_delay = StartupDelay::decode(reader)?;
42+
let flow_alarm_limit = Flow::decode_opt(reader, flag_set(alarms, 0x01))?;
43+
let water_temperature_limit = Temperature::decode_opt(reader, flag_set(alarms, 0x02))?;
44+
let external_temperature_limit = Temperature::decode_opt(reader, flag_set(alarms, 0x04))?;
45+
let water_quality_limit = WaterQuality::decode_opt(reader, flag_set(alarms, 0x08))?;
46+
let output_signal = OutputSignal::decode(reader)?;
47+
48+
Ok(R::guard(|x| Self {
49+
flags: x.extract(flags),
50+
startup_delay: x.extract(startup_delay),
51+
flow_alarm_limit: x.extract(flow_alarm_limit),
52+
water_temperature_limit: x.extract(water_temperature_limit),
53+
external_temperature_limit: x.extract(external_temperature_limit),
54+
water_quality_limit: x.extract(water_quality_limit),
55+
output_signal: x.extract(output_signal),
56+
}))
57+
}
58+
}
59+
60+
/// Signal to output at the signal output connector.
61+
///
62+
/// Used in [`AlarmSettings::output_signal`].
63+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
64+
pub enum OutputSignal {
65+
/// Generate a constant speed signal.
66+
ConstantSpeed,
67+
68+
/// Generate high flow sensor (53069) signal.
69+
HighFlowSensor,
70+
71+
/// Generate a fan speed signal from the flow rate (1000rpm = 100l/h).
72+
FanFromFlow,
73+
74+
/// Power switch for 1 seconds at alarm.
75+
PulseOnAlarm,
76+
77+
/// Permanently switch on the output signal.
78+
PermanentOn,
79+
80+
/// Permanently switch off the output signal
81+
PermanentOff,
82+
}
83+
84+
impl BinaryRead for OutputSignal {
85+
fn decode<R: Reader>(reader: &mut R) -> Result<ReaderOutput<R, Self>, BinaryIoError> {
86+
match reader.read_u8()? {
87+
0x00 => Ok(R::guard(|_| Self::ConstantSpeed)),
88+
0x01 => Ok(R::guard(|_| Self::HighFlowSensor)),
89+
0x02 => Ok(R::guard(|_| Self::FanFromFlow)),
90+
0x03 => Ok(R::guard(|_| Self::PulseOnAlarm)),
91+
0x04 => Ok(R::guard(|_| Self::PermanentOn)),
92+
0x05 => Ok(R::guard(|_| Self::PermanentOff)),
93+
x => Err(BinaryIoError::InvalidValue("OutputSignal", x.into())),
94+
}
95+
}
96+
}
97+
98+
bitflags! {
99+
/// Different flags uses in [`AlarmSettings::flags`].
100+
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
101+
pub struct AlarmFlags: u8 {
102+
/// Disable signal output during alarm.
103+
const DISABLE_SIGNAL_OUTPUT_DURING_ALARM = 0x20;
104+
105+
/// Enable optical indicator during alarm (red ring flashing).
106+
const ENABLE_OPTICAL_INDICATOR = 0x40;
107+
108+
/// Enable acustic indicator during alarm (beep tone).
109+
const ENABLE_ACUSTIC_INDICATOR = 0x80;
110+
}
111+
}
112+
113+
impl BinaryRead for AlarmFlags {
114+
fn decode<R: Reader>(reader: &mut R) -> Result<ReaderOutput<R, Self>, BinaryIoError> {
115+
let bits = reader.read_u8()?;
116+
117+
Ok(R::guard(|_| Self::from_bits_truncate(bits)))
118+
}
119+
}
120+
121+
define_wrapped! {
122+
/// Time to disable the alarms after boot to give the system time to start.
123+
///
124+
/// Used in [`AlarmSettings::startup_delay`].
125+
///
126+
/// Valid value range: 0..100 in seconds
127+
StartupDelay<u8, StartupDelayTag>
128+
}
129+
impl_ranged!(StartupDelay<u8, StartupDelayTag>, 0, 100);
130+
131+
define_wrapped! {
132+
/// Temperature value.
133+
///
134+
/// Valid value range: 0..10000 in 1/100 degree celsius / fahrenheit (1/100 °C / °F)
135+
Temperature<u16, TemperatureTag>
136+
}
137+
impl_ranged!(Temperature<u16, TemperatureTag>, 0, 10_000);
138+
139+
define_wrapped! {
140+
/// Water quality value.
141+
///
142+
/// Valid value range: 0..10000 in 1/100 percent (1/100 %)
143+
WaterQuality<u16, WaterQualityTag>
144+
}
145+
impl_ranged!(WaterQuality<u16, WaterQualityTag>, 0, 10000);

0 commit comments

Comments
 (0)