1use crate::protocol as proto;
9
10#[derive(Debug, thiserror::Error)]
12pub enum Error {
13 #[error(transparent)]
15 Protocol(#[from] proto::Error),
16
17 #[error(transparent)]
19 ModbusException(#[from] tokio_modbus::ExceptionCode),
20
21 #[error(transparent)]
23 Modbus(#[from] tokio_modbus::Error),
24}
25
26pub(crate) type Result<T> = std::result::Result<T, Error>;
28
29pub const DATA_BITS: &tokio_serial::DataBits = &tokio_serial::DataBits::Eight;
31
32pub fn serial_port_builder(
49 device: &str,
50 baud_rate: &proto::BaudRate,
51 parity_and_stop_bits: &proto::ParityAndStopBit,
52) -> tokio_serial::SerialPortBuilder {
53 let (parity, stop_bits) = match parity_and_stop_bits {
54 proto::ParityAndStopBit::NoParityOneStopBit => {
55 (tokio_serial::Parity::None, tokio_serial::StopBits::One)
56 }
57 proto::ParityAndStopBit::EvenParityOneStopBit => {
58 (tokio_serial::Parity::Even, tokio_serial::StopBits::One)
59 }
60 proto::ParityAndStopBit::OddParityOneStopBit => {
61 (tokio_serial::Parity::Odd, tokio_serial::StopBits::One)
62 }
63 proto::ParityAndStopBit::NoParityTwoStopBits => {
64 (tokio_serial::Parity::None, tokio_serial::StopBits::Two)
65 }
66 };
67 tokio_serial::new(device, u16::from(baud_rate) as u32)
68 .parity(parity)
69 .stop_bits(stop_bits)
70 .data_bits(*DATA_BITS)
71 .flow_control(tokio_serial::FlowControl::None)
73}
74
75#[derive(Debug, Clone, Copy, PartialEq)]
77#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78pub struct AllSettings {
79 pub system_type: proto::SystemType,
80 pub pulse_width: proto::PulseWidth,
81 pub kppa: proto::KPPA,
82 pub parity_and_stop_bit: proto::ParityAndStopBit,
83 pub address: proto::Address,
84 pub pulse_constant: proto::PulseConstant,
85 pub password: proto::Password,
86 pub baud_rate: proto::BaudRate,
87 pub auto_scroll_time: proto::AutoScrollTime,
88 pub backlight_time: proto::BacklightTime,
89 pub pulse_energy_type: proto::PulseEnergyType,
90 pub serial_number: proto::SerialNumber,
91 pub meter_code: proto::MeterCode,
92 pub software_version: proto::SoftwareVersion,
93}
94impl std::fmt::Display for AllSettings {
95 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
96 writeln!(fmt, "System type: {}", self.system_type)?;
97 writeln!(fmt, "Pulse width: {}", self.pulse_width)?;
98 writeln!(fmt, "KPPA: {}", self.kppa)?;
99 writeln!(fmt, "Parity and stop bit: {}", self.parity_and_stop_bit)?;
100 writeln!(fmt, "Address: {}", self.address)?;
101 writeln!(fmt, "Pulse constant: {}", self.pulse_constant)?;
102 writeln!(fmt, "Password: {}", self.password)?;
103 writeln!(fmt, "Baud rate: {}", self.baud_rate)?;
104 writeln!(fmt, "Auto scroll time: {}", self.auto_scroll_time)?;
105 writeln!(fmt, "Backlight time: {}", self.backlight_time)?;
106 writeln!(fmt, "Pulse energy type: {}", self.pulse_energy_type)?;
107 writeln!(fmt, "Serial number: {}", self.serial_number)?;
108 writeln!(fmt, "Meter code: {}", self.meter_code)?;
109 write!(fmt, "Software version: {}", self.software_version)?;
110 Ok(())
111 }
112}
113
114#[derive(Debug, Clone, Copy, PartialEq)]
116#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
117pub struct AllValues {
118 pub l1_voltage: proto::L1Voltage,
120 pub l2_voltage: proto::L2Voltage,
121 pub l3_voltage: proto::L3Voltage,
122 pub l1_current: proto::L1Current,
123 pub l2_current: proto::L2Current,
124 pub l3_current: proto::L3Current,
125 pub l1_power_active: proto::L1PowerActive,
126 pub l2_power_active: proto::L2PowerActive,
127 pub l3_power_active: proto::L3PowerActive,
128 pub l1_power_apparent: proto::L1PowerApparent,
129 pub l2_power_apparent: proto::L2PowerApparent,
130 pub l3_power_apparent: proto::L3PowerApparent,
131 pub l1_power_reactive: proto::L1PowerReactive,
132 pub l2_power_reactive: proto::L2PowerReactive,
133 pub l3_power_reactive: proto::L3PowerReactive,
134 pub l1_power_factor: proto::L1PowerFactor,
135 pub l2_power_factor: proto::L2PowerFactor,
136 pub l3_power_factor: proto::L3PowerFactor,
137 #[cfg_attr(feature = "serde", serde(rename = "l-n_average_voltage"))]
138 pub ln_average_voltage: proto::LtoNAverageVoltage,
139 #[cfg_attr(feature = "serde", serde(rename = "l-n_average_current"))]
140 pub ln_average_current: proto::LtoNAverageCurrent,
141 pub total_line_current: proto::TotalLineCurrent,
142 pub total_power: proto::TotalPower,
143 pub total_power_apparent: proto::TotalPowerApparent,
144 pub total_power_reactive: proto::TotalPowerReactive,
145 pub total_power_factor: proto::TotalPowerFactor,
146 pub frequency: proto::Frequency,
147 pub import_energy_active: proto::ImportEnergyActive,
148 pub export_energy_active: proto::ExportEnergyActive,
149
150 #[cfg_attr(feature = "serde", serde(rename = "l1-l2_voltage"))]
151 pub l1l2_voltage: proto::L1ToL2Voltage,
152 #[cfg_attr(feature = "serde", serde(rename = "l2-l3_voltage"))]
153 pub l2l3_voltage: proto::L2ToL3Voltage,
154 #[cfg_attr(feature = "serde", serde(rename = "l3-l1_voltage"))]
155 pub l3l1_voltage: proto::L3ToL1Voltage,
156 #[cfg_attr(feature = "serde", serde(rename = "l-l_average_voltage"))]
157 pub ll_average_voltage: proto::LtoLAverageVoltage,
158 pub neutral_current: proto::NeutralCurrent,
159
160 pub total_energy_active: proto::TotalEnergyActive,
161 pub total_energy_reactive: proto::TotalEnergyReactive,
162 pub resettable_total_energy_active: proto::ResettableTotalEnergyActive,
163 pub resettable_total_energy_reactive: proto::ResettableTotalEnergyReactive,
164 pub resettable_import_energy_active: proto::ResettableImportEnergyActive,
165 pub resettable_export_energy_active: proto::ResettableExportEnergyActive,
166 #[cfg_attr(feature = "serde", serde(rename = "net_kwh_import_-_export"))]
167 pub net_kwh: proto::NetKwh,
168
169 pub import_total_energy_active: proto::ImportTotalPowerActive,
170 pub export_total_energy_active: proto::ExportTotalPowerActive,
171}
172impl std::fmt::Display for AllValues {
173 fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
174 writeln!(fmt, "L1 Voltage: {}", self.l1_voltage)?;
175 writeln!(fmt, "L2 Voltage: {}", self.l2_voltage)?;
176 writeln!(fmt, "L3 Voltage: {}", self.l3_voltage)?;
177 writeln!(fmt, "L1 Current: {}", self.l1_current)?;
178 writeln!(fmt, "L2 Current: {}", self.l2_current)?;
179 writeln!(fmt, "L3 Current: {}", self.l3_current)?;
180 writeln!(fmt, "L1 Power Active: {}", self.l1_power_active)?;
181 writeln!(fmt, "L2 Power Active: {}", self.l2_power_active)?;
182 writeln!(fmt, "L3 Power Active: {}", self.l3_power_active)?;
183 writeln!(fmt, "L1 Power Apparent: {}", self.l1_power_apparent)?;
184 writeln!(fmt, "L2 Power Apparent: {}", self.l2_power_apparent)?;
185 writeln!(fmt, "L3 Power Apparent: {}", self.l3_power_apparent)?;
186 writeln!(fmt, "L1 Power Reactive: {}", self.l1_power_reactive)?;
187 writeln!(fmt, "L2 Power Reactive: {}", self.l2_power_reactive)?;
188 writeln!(fmt, "L3 Power Reactive: {}", self.l3_power_reactive)?;
189 writeln!(fmt, "L1 Power Factor: {}", self.l1_power_factor)?;
190 writeln!(fmt, "L2 Power Factor: {}", self.l2_power_factor)?;
191 writeln!(fmt, "L3 Power Factor: {}", self.l3_power_factor)?;
192 writeln!(fmt, "L-N average Voltage: {}", self.ln_average_voltage)?;
193 writeln!(fmt, "L-N average Current: {}", self.ln_average_current)?;
194 writeln!(fmt, "Total Line Current: {}", self.total_line_current)?;
195 writeln!(fmt, "Total Power: {}", self.total_power)?;
196 writeln!(fmt, "Total Power Apparent: {}", self.total_power_apparent)?;
197 writeln!(fmt, "Total Power Reactive: {}", self.total_power_reactive)?;
198 writeln!(fmt, "Total Power Factor: {}", self.total_power_factor)?;
199 writeln!(fmt, "Frequency: {}", self.frequency)?;
200 writeln!(fmt, "Import Energy Active: {}", self.import_energy_active)?;
201 writeln!(fmt, "Export Energy Active: {}", self.export_energy_active)?;
202
203 writeln!(fmt, "L1-L2 Voltage: {}", self.l1l2_voltage)?;
204 writeln!(fmt, "L2-L3 Voltage: {}", self.l2l3_voltage)?;
205 writeln!(fmt, "L3-L1 Voltage: {}", self.l3l1_voltage)?;
206 writeln!(fmt, "L-L average Voltage: {}", self.ll_average_voltage)?;
207 writeln!(fmt, "Neutral Current: {}", self.neutral_current)?;
208
209 writeln!(fmt, "Total Energy Active: {}", self.total_energy_active)?;
210 writeln!(fmt, "Total Energy Reactive: {}", self.total_energy_reactive)?;
211 writeln!(
212 fmt,
213 "Resettable Total Energy Active: {}",
214 self.resettable_total_energy_active
215 )?;
216 writeln!(
217 fmt,
218 "Resettable Total Energy Reactive: {}",
219 self.resettable_total_energy_reactive
220 )?;
221 writeln!(
222 fmt,
223 "Resettable Import Energy Active: {}",
224 self.resettable_import_energy_active
225 )?;
226 writeln!(
227 fmt,
228 "Resettable Export Energy Active: {}",
229 self.resettable_export_energy_active
230 )?;
231 writeln!(fmt, "Net kWh (Import - Export): {}", self.net_kwh)?;
232
233 writeln!(
234 fmt,
235 "Import Total Energy Active: {}",
236 self.import_total_energy_active
237 )?;
238 write!(
239 fmt,
240 "Export Total Energy Active: {}",
241 self.export_total_energy_active
242 )?;
243
244 Ok(())
245 }
246}