tinkerforge_async/bindings/
energy_monitor_bricklet.rs

1/* ***********************************************************
2 * This file was automatically generated on 2024-02-16.      *
3 *                                                           *
4 * Rust Bindings Version 2.0.20                              *
5 *                                                           *
6 * If you have a bugfix for this file and want to commit it, *
7 * please fix the bug in the generator. You can find a link  *
8 * to the generators git repository on tinkerforge.com       *
9 *************************************************************/
10
11//! Measures Voltage, Current, Energy, Real/Apparent/Reactive Power, Power Factor and Frequency.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/EnergyMonitor_Bricklet_Rust.html).
14#[allow(unused_imports)]
15use crate::{
16    base58::Uid, byte_converter::*, converting_receiver::BrickletRecvTimeoutError, device::*, error::TinkerforgeError,
17    ip_connection::async_io::AsyncIpConnection, low_level_traits::LowLevelRead,
18};
19#[allow(unused_imports)]
20use futures_core::Stream;
21#[allow(unused_imports)]
22use tokio_stream::StreamExt;
23pub enum EnergyMonitorBrickletFunction {
24    GetEnergyData,
25    ResetEnergy,
26    GetWaveformLowLevel,
27    GetTransformerStatus,
28    SetTransformerCalibration,
29    GetTransformerCalibration,
30    CalibrateOffset,
31    SetEnergyDataCallbackConfiguration,
32    GetEnergyDataCallbackConfiguration,
33    GetSpitfpErrorCount,
34    SetBootloaderMode,
35    GetBootloaderMode,
36    SetWriteFirmwarePointer,
37    WriteFirmware,
38    SetStatusLedConfig,
39    GetStatusLedConfig,
40    GetChipTemperature,
41    Reset,
42    WriteUid,
43    ReadUid,
44    GetIdentity,
45    CallbackEnergyData,
46}
47impl From<EnergyMonitorBrickletFunction> for u8 {
48    fn from(fun: EnergyMonitorBrickletFunction) -> Self {
49        match fun {
50            EnergyMonitorBrickletFunction::GetEnergyData => 1,
51            EnergyMonitorBrickletFunction::ResetEnergy => 2,
52            EnergyMonitorBrickletFunction::GetWaveformLowLevel => 3,
53            EnergyMonitorBrickletFunction::GetTransformerStatus => 4,
54            EnergyMonitorBrickletFunction::SetTransformerCalibration => 5,
55            EnergyMonitorBrickletFunction::GetTransformerCalibration => 6,
56            EnergyMonitorBrickletFunction::CalibrateOffset => 7,
57            EnergyMonitorBrickletFunction::SetEnergyDataCallbackConfiguration => 8,
58            EnergyMonitorBrickletFunction::GetEnergyDataCallbackConfiguration => 9,
59            EnergyMonitorBrickletFunction::GetSpitfpErrorCount => 234,
60            EnergyMonitorBrickletFunction::SetBootloaderMode => 235,
61            EnergyMonitorBrickletFunction::GetBootloaderMode => 236,
62            EnergyMonitorBrickletFunction::SetWriteFirmwarePointer => 237,
63            EnergyMonitorBrickletFunction::WriteFirmware => 238,
64            EnergyMonitorBrickletFunction::SetStatusLedConfig => 239,
65            EnergyMonitorBrickletFunction::GetStatusLedConfig => 240,
66            EnergyMonitorBrickletFunction::GetChipTemperature => 242,
67            EnergyMonitorBrickletFunction::Reset => 243,
68            EnergyMonitorBrickletFunction::WriteUid => 248,
69            EnergyMonitorBrickletFunction::ReadUid => 249,
70            EnergyMonitorBrickletFunction::GetIdentity => 255,
71            EnergyMonitorBrickletFunction::CallbackEnergyData => 10,
72        }
73    }
74}
75pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
76pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
77pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
78pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
79pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
80pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
81pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
82pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
83pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
84pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
85pub const ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
86pub const ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
87pub const ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
88pub const ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
89pub const ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
90
91#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
92pub struct EnergyData {
93    pub voltage: i32,
94    pub current: i32,
95    pub energy: i32,
96    pub real_power: i32,
97    pub apparent_power: i32,
98    pub reactive_power: i32,
99    pub power_factor: u16,
100    pub frequency: u16,
101}
102impl FromByteSlice for EnergyData {
103    fn bytes_expected() -> usize {
104        28
105    }
106    fn from_le_byte_slice(bytes: &[u8]) -> EnergyData {
107        EnergyData {
108            voltage: <i32>::from_le_byte_slice(&bytes[0..4]),
109            current: <i32>::from_le_byte_slice(&bytes[4..8]),
110            energy: <i32>::from_le_byte_slice(&bytes[8..12]),
111            real_power: <i32>::from_le_byte_slice(&bytes[12..16]),
112            apparent_power: <i32>::from_le_byte_slice(&bytes[16..20]),
113            reactive_power: <i32>::from_le_byte_slice(&bytes[20..24]),
114            power_factor: <u16>::from_le_byte_slice(&bytes[24..26]),
115            frequency: <u16>::from_le_byte_slice(&bytes[26..28]),
116        }
117    }
118}
119
120#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
121pub struct WaveformLowLevel {
122    pub waveform_chunk_offset: u16,
123    pub waveform_chunk_data: [i16; 30],
124}
125impl FromByteSlice for WaveformLowLevel {
126    fn bytes_expected() -> usize {
127        62
128    }
129    fn from_le_byte_slice(bytes: &[u8]) -> WaveformLowLevel {
130        WaveformLowLevel {
131            waveform_chunk_offset: <u16>::from_le_byte_slice(&bytes[0..2]),
132            waveform_chunk_data: <[i16; 30]>::from_le_byte_slice(&bytes[2..62]),
133        }
134    }
135}
136impl LowLevelRead<i16, WaveformResult> for WaveformLowLevel {
137    fn ll_message_length(&self) -> usize {
138        1536
139    }
140
141    fn ll_message_chunk_offset(&self) -> usize {
142        self.waveform_chunk_offset as usize
143    }
144
145    fn ll_message_chunk_data(&self) -> &[i16] {
146        &self.waveform_chunk_data
147    }
148
149    fn get_result(&self) -> WaveformResult {
150        WaveformResult {}
151    }
152}
153
154#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
155pub struct TransformerStatus {
156    pub voltage_transformer_connected: bool,
157    pub current_transformer_connected: bool,
158}
159impl FromByteSlice for TransformerStatus {
160    fn bytes_expected() -> usize {
161        2
162    }
163    fn from_le_byte_slice(bytes: &[u8]) -> TransformerStatus {
164        TransformerStatus {
165            voltage_transformer_connected: <bool>::from_le_byte_slice(&bytes[0..1]),
166            current_transformer_connected: <bool>::from_le_byte_slice(&bytes[1..2]),
167        }
168    }
169}
170
171#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
172pub struct TransformerCalibration {
173    pub voltage_ratio: u16,
174    pub current_ratio: u16,
175    pub phase_shift: i16,
176}
177impl FromByteSlice for TransformerCalibration {
178    fn bytes_expected() -> usize {
179        6
180    }
181    fn from_le_byte_slice(bytes: &[u8]) -> TransformerCalibration {
182        TransformerCalibration {
183            voltage_ratio: <u16>::from_le_byte_slice(&bytes[0..2]),
184            current_ratio: <u16>::from_le_byte_slice(&bytes[2..4]),
185            phase_shift: <i16>::from_le_byte_slice(&bytes[4..6]),
186        }
187    }
188}
189
190#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
191pub struct EnergyDataCallbackConfiguration {
192    pub period: u32,
193    pub value_has_to_change: bool,
194}
195impl FromByteSlice for EnergyDataCallbackConfiguration {
196    fn bytes_expected() -> usize {
197        5
198    }
199    fn from_le_byte_slice(bytes: &[u8]) -> EnergyDataCallbackConfiguration {
200        EnergyDataCallbackConfiguration {
201            period: <u32>::from_le_byte_slice(&bytes[0..4]),
202            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
203        }
204    }
205}
206
207#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
208pub struct EnergyDataEvent {
209    pub voltage: i32,
210    pub current: i32,
211    pub energy: i32,
212    pub real_power: i32,
213    pub apparent_power: i32,
214    pub reactive_power: i32,
215    pub power_factor: u16,
216    pub frequency: u16,
217}
218impl FromByteSlice for EnergyDataEvent {
219    fn bytes_expected() -> usize {
220        28
221    }
222    fn from_le_byte_slice(bytes: &[u8]) -> EnergyDataEvent {
223        EnergyDataEvent {
224            voltage: <i32>::from_le_byte_slice(&bytes[0..4]),
225            current: <i32>::from_le_byte_slice(&bytes[4..8]),
226            energy: <i32>::from_le_byte_slice(&bytes[8..12]),
227            real_power: <i32>::from_le_byte_slice(&bytes[12..16]),
228            apparent_power: <i32>::from_le_byte_slice(&bytes[16..20]),
229            reactive_power: <i32>::from_le_byte_slice(&bytes[20..24]),
230            power_factor: <u16>::from_le_byte_slice(&bytes[24..26]),
231            frequency: <u16>::from_le_byte_slice(&bytes[26..28]),
232        }
233    }
234}
235
236#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
237pub struct SpitfpErrorCount {
238    pub error_count_ack_checksum: u32,
239    pub error_count_message_checksum: u32,
240    pub error_count_frame: u32,
241    pub error_count_overflow: u32,
242}
243impl FromByteSlice for SpitfpErrorCount {
244    fn bytes_expected() -> usize {
245        16
246    }
247    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
248        SpitfpErrorCount {
249            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
250            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
251            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
252            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
253        }
254    }
255}
256
257#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
258pub struct Identity {
259    pub uid: String,
260    pub connected_uid: String,
261    pub position: char,
262    pub hardware_version: [u8; 3],
263    pub firmware_version: [u8; 3],
264    pub device_identifier: u16,
265}
266impl FromByteSlice for Identity {
267    fn bytes_expected() -> usize {
268        25
269    }
270    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
271        Identity {
272            uid: <String>::from_le_byte_slice(&bytes[0..8]),
273            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
274            position: <char>::from_le_byte_slice(&bytes[16..17]),
275            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
276            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
277            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
278        }
279    }
280}
281
282#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
283pub struct WaveformResult {}
284
285/// Measures Voltage, Current, Energy, Real/Apparent/Reactive Power, Power Factor and Frequency
286#[derive(Clone)]
287pub struct EnergyMonitorBricklet {
288    device: Device,
289}
290impl EnergyMonitorBricklet {
291    pub const DEVICE_IDENTIFIER: u16 = 2152;
292    pub const DEVICE_DISPLAY_NAME: &'static str = "Energy Monitor Bricklet";
293    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
294    pub fn new(uid: Uid, connection: AsyncIpConnection) -> EnergyMonitorBricklet {
295        let mut result = EnergyMonitorBricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
296        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetEnergyData) as usize] = ResponseExpectedFlag::AlwaysTrue;
297        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::ResetEnergy) as usize] = ResponseExpectedFlag::False;
298        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetWaveformLowLevel) as usize] =
299            ResponseExpectedFlag::AlwaysTrue;
300        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetTransformerStatus) as usize] =
301            ResponseExpectedFlag::AlwaysTrue;
302        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::SetTransformerCalibration) as usize] =
303            ResponseExpectedFlag::False;
304        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetTransformerCalibration) as usize] =
305            ResponseExpectedFlag::AlwaysTrue;
306        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::CalibrateOffset) as usize] = ResponseExpectedFlag::False;
307        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::SetEnergyDataCallbackConfiguration) as usize] =
308            ResponseExpectedFlag::True;
309        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetEnergyDataCallbackConfiguration) as usize] =
310            ResponseExpectedFlag::AlwaysTrue;
311        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetSpitfpErrorCount) as usize] =
312            ResponseExpectedFlag::AlwaysTrue;
313        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::SetBootloaderMode) as usize] =
314            ResponseExpectedFlag::AlwaysTrue;
315        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetBootloaderMode) as usize] =
316            ResponseExpectedFlag::AlwaysTrue;
317        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::SetWriteFirmwarePointer) as usize] =
318            ResponseExpectedFlag::False;
319        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::WriteFirmware) as usize] = ResponseExpectedFlag::AlwaysTrue;
320        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::SetStatusLedConfig) as usize] = ResponseExpectedFlag::False;
321        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetStatusLedConfig) as usize] =
322            ResponseExpectedFlag::AlwaysTrue;
323        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetChipTemperature) as usize] =
324            ResponseExpectedFlag::AlwaysTrue;
325        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
326        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
327        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::ReadUid) as usize] = ResponseExpectedFlag::AlwaysTrue;
328        result.device.response_expected[u8::from(EnergyMonitorBrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
329        result
330    }
331
332    /// Returns the response expected flag for the function specified by the function ID parameter.
333    /// It is true if the function is expected to send a response, false otherwise.
334    ///
335    /// For getter functions this is enabled by default and cannot be disabled, because those
336    /// functions will always send a response. For callback configuration functions it is enabled
337    /// by default too, but can be disabled by [`set_response_expected`](crate::energy_monitor_bricklet::EnergyMonitorBricklet::set_response_expected).
338    /// For setter functions it is disabled by default and can be enabled.
339    ///
340    /// Enabling the response expected flag for a setter function allows to detect timeouts
341    /// and other error conditions calls of this setter as well. The device will then send a response
342    /// for this purpose. If this flag is disabled for a setter function then no response is sent
343    /// and errors are silently ignored, because they cannot be detected.
344    ///
345    /// See [`set_response_expected`](crate::energy_monitor_bricklet::EnergyMonitorBricklet::set_response_expected) for the list of function ID constants available for this function.
346    pub fn get_response_expected(&mut self, fun: EnergyMonitorBrickletFunction) -> Result<bool, GetResponseExpectedError> {
347        self.device.get_response_expected(u8::from(fun))
348    }
349
350    /// Changes the response expected flag of the function specified by the function ID parameter.
351    /// This flag can only be changed for setter (default value: false) and callback configuration
352    /// functions (default value: true). For getter functions it is always enabled.
353    ///
354    /// Enabling the response expected flag for a setter function allows to detect timeouts and
355    /// other error conditions calls of this setter as well. The device will then send a response
356    /// for this purpose. If this flag is disabled for a setter function then no response is sent
357    /// and errors are silently ignored, because they cannot be detected.
358    pub fn set_response_expected(
359        &mut self,
360        fun: EnergyMonitorBrickletFunction,
361        response_expected: bool,
362    ) -> Result<(), SetResponseExpectedError> {
363        self.device.set_response_expected(u8::from(fun), response_expected)
364    }
365
366    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
367    pub fn set_response_expected_all(&mut self, response_expected: bool) {
368        self.device.set_response_expected_all(response_expected)
369    }
370
371    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
372    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
373    pub fn get_api_version(&self) -> [u8; 3] {
374        self.device.api_version
375    }
376
377    /// This receiver is triggered periodically according to the configuration set by
378    /// [`set_energy_data_callback_configuration`].
379    ///
380    /// The parameters are the same as [`get_energy_data`].
381    ///
382    /// [`get_energy_data`]: #method.get_energy_data
383    /// [`set_energy_data_callback_configuration`]: #method.set_energy_data_callback_configuration
384    pub async fn get_energy_data_callback_receiver(&mut self) -> impl Stream<Item = EnergyDataEvent> {
385        self.device
386            .get_callback_receiver(u8::from(EnergyMonitorBrickletFunction::CallbackEnergyData))
387            .await
388            .map(|p| EnergyDataEvent::from_le_byte_slice(p.body()))
389    }
390
391    /// Returns all of the measurements that are done by the Energy Monitor Bricklet.
392    ///
393    /// * Voltage RMS
394    /// * Current RMS
395    /// * Energy (integrated over time)
396    /// * Real Power
397    /// * Apparent Power
398    /// * Reactive Power
399    /// * Power Factor
400    /// * Frequency (AC Frequency of the mains voltage)
401    ///
402    /// The frequency is recalculated every 6 seconds.
403    ///
404    /// All other values are integrated over 10 zero-crossings of the voltage sine wave.
405    /// With a standard AC mains voltage frequency of 50Hz this results in a 5 measurements
406    /// per second (or an integration time of 200ms per measurement).
407    ///
408    /// If no voltage transformer is connected, the Bricklet will use the current waveform
409    /// to calculate the frequency and it will use an integration time of
410    /// 10 zero-crossings of the current waveform.
411    pub async fn get_energy_data(&mut self) -> Result<EnergyData, TinkerforgeError> {
412        let payload = [0; 0];
413
414        #[allow(unused_variables)]
415        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetEnergyData), &payload).await?;
416        Ok(EnergyData::from_le_byte_slice(result.body()))
417    }
418
419    /// Sets the energy value (see [`get_energy_data`]) back to 0Wh.
420    pub async fn reset_energy(&mut self) -> Result<(), TinkerforgeError> {
421        let payload = [0; 0];
422
423        #[allow(unused_variables)]
424        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::ResetEnergy), &payload).await?;
425        Ok(())
426    }
427
428    /// Returns a snapshot of the voltage and current waveform. The values
429    /// in the returned array alternate between voltage and current. The data from
430    /// one getter call contains 768 data points for voltage and current, which
431    /// correspond to about 3 full sine waves.
432    ///
433    /// The voltage is given with a resolution of 100mV and the current is given
434    /// with a resolution of 10mA.
435    ///
436    /// This data is meant to be used for a non-realtime graphical representation of
437    /// the voltage and current waveforms.
438    pub async fn get_waveform_low_level(&mut self) -> Result<WaveformLowLevel, TinkerforgeError> {
439        let payload = [0; 0];
440
441        #[allow(unused_variables)]
442        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetWaveformLowLevel), &payload).await?;
443        Ok(WaveformLowLevel::from_le_byte_slice(result.body()))
444    }
445
446    /// Returns *true* if a voltage/current transformer is connected to the Bricklet.
447    pub async fn get_transformer_status(&mut self) -> Result<TransformerStatus, TinkerforgeError> {
448        let payload = [0; 0];
449
450        #[allow(unused_variables)]
451        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetTransformerStatus), &payload).await?;
452        Ok(TransformerStatus::from_le_byte_slice(result.body()))
453    }
454
455    /// Sets the transformer ratio for the voltage and current transformer in 1/100 form.
456    ///
457    /// Example: If your mains voltage is 230V, you use 9V voltage transformer and a
458    /// 1V:30A current clamp your voltage ratio is 230/9 = 25.56 and your current ratio
459    /// is 30/1 = 30.
460    ///
461    /// In this case you have to set the values 2556 and 3000 for voltage ratio and current
462    /// ratio.
463    ///
464    /// The calibration is saved in non-volatile memory, you only have to set it once.
465    ///
466    /// Set the phase shift to 0. It is for future use and currently not supported by the Bricklet.
467    pub async fn set_transformer_calibration(
468        &mut self,
469        voltage_ratio: u16,
470        current_ratio: u16,
471        phase_shift: i16,
472    ) -> Result<(), TinkerforgeError> {
473        let mut payload = [0; 6];
474        voltage_ratio.write_to_slice(&mut payload[0..2]);
475        current_ratio.write_to_slice(&mut payload[2..4]);
476        phase_shift.write_to_slice(&mut payload[4..6]);
477
478        #[allow(unused_variables)]
479        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::SetTransformerCalibration), &payload).await?;
480        Ok(())
481    }
482
483    /// Returns the transformer calibration as set by [`set_transformer_calibration`].
484    pub async fn get_transformer_calibration(&mut self) -> Result<TransformerCalibration, TinkerforgeError> {
485        let payload = [0; 0];
486
487        #[allow(unused_variables)]
488        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetTransformerCalibration), &payload).await?;
489        Ok(TransformerCalibration::from_le_byte_slice(result.body()))
490    }
491
492    /// Calling this function will start an offset calibration. The offset calibration will
493    /// integrate the voltage and current waveform over a longer time period to find the 0
494    /// transition point in the sine wave.
495    ///
496    /// The Bricklet comes with a factory-calibrated offset value, you should not have to
497    /// call this function.
498    ///
499    /// If you want to re-calibrate the offset we recommend that you connect a load that
500    /// has a smooth sinusoidal voltage and current waveform. Alternatively you can also
501    /// short both inputs.
502    ///
503    /// The calibration is saved in non-volatile memory, you only have to set it once.
504    pub async fn calibrate_offset(&mut self) -> Result<(), TinkerforgeError> {
505        let payload = [0; 0];
506
507        #[allow(unused_variables)]
508        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::CalibrateOffset), &payload).await?;
509        Ok(())
510    }
511
512    /// The period is the period with which the [`get_energy_data_callback_receiver`]
513    /// receiver is triggered periodically. A value of 0 turns the receiver off.
514    ///
515    /// If the `value has to change`-parameter is set to true, the receiver is only
516    /// triggered after the value has changed. If the value didn't change within the
517    /// period, the receiver is triggered immediately on change.
518    ///
519    /// If it is set to false, the receiver is continuously triggered with the period,
520    /// independent of the value.
521    pub async fn set_energy_data_callback_configuration(&mut self, period: u32, value_has_to_change: bool) -> Result<(), TinkerforgeError> {
522        let mut payload = [0; 5];
523        period.write_to_slice(&mut payload[0..4]);
524        value_has_to_change.write_to_slice(&mut payload[4..5]);
525
526        #[allow(unused_variables)]
527        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::SetEnergyDataCallbackConfiguration), &payload).await?;
528        Ok(())
529    }
530
531    /// Returns the receiver configuration as set by
532    /// [`set_energy_data_callback_configuration`].
533    pub async fn get_energy_data_callback_configuration(&mut self) -> Result<EnergyDataCallbackConfiguration, TinkerforgeError> {
534        let payload = [0; 0];
535
536        #[allow(unused_variables)]
537        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetEnergyDataCallbackConfiguration), &payload).await?;
538        Ok(EnergyDataCallbackConfiguration::from_le_byte_slice(result.body()))
539    }
540
541    /// Returns the error count for the communication between Brick and Bricklet.
542    ///
543    /// The errors are divided into
544    ///
545    /// * ACK checksum errors,
546    /// * message checksum errors,
547    /// * framing errors and
548    /// * overflow errors.
549    ///
550    /// The errors counts are for errors that occur on the Bricklet side. All
551    /// Bricks have a similar function that returns the errors on the Brick side.
552    pub async fn get_spitfp_error_count(&mut self) -> Result<SpitfpErrorCount, TinkerforgeError> {
553        let payload = [0; 0];
554
555        #[allow(unused_variables)]
556        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetSpitfpErrorCount), &payload).await?;
557        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
558    }
559
560    /// Sets the bootloader mode and returns the status after the requested
561    /// mode change was instigated.
562    ///
563    /// You can change from bootloader mode to firmware mode and vice versa. A change
564    /// from bootloader mode to firmware mode will only take place if the entry function,
565    /// device identifier and CRC are present and correct.
566    ///
567    /// This function is used by Brick Viewer during flashing. It should not be
568    /// necessary to call it in a normal user program.
569    ///
570    /// Associated constants:
571    /// * ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
572    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE
573    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
574    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
575    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
576    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_OK
577    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
578    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
579    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
580    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
581    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
582    pub async fn set_bootloader_mode(&mut self, mode: u8) -> Result<u8, TinkerforgeError> {
583        let mut payload = [0; 1];
584        mode.write_to_slice(&mut payload[0..1]);
585
586        #[allow(unused_variables)]
587        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::SetBootloaderMode), &payload).await?;
588        Ok(u8::from_le_byte_slice(result.body()))
589    }
590
591    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
592    ///
593    /// Associated constants:
594    /// * ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
595    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE
596    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
597    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
598    ///	* ENERGY_MONITOR_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
599    pub async fn get_bootloader_mode(&mut self) -> Result<u8, TinkerforgeError> {
600        let payload = [0; 0];
601
602        #[allow(unused_variables)]
603        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetBootloaderMode), &payload).await?;
604        Ok(u8::from_le_byte_slice(result.body()))
605    }
606
607    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
608    /// to be increased by chunks of size 64. The data is written to flash
609    /// every 4 chunks (which equals to one page of size 256).
610    ///
611    /// This function is used by Brick Viewer during flashing. It should not be
612    /// necessary to call it in a normal user program.
613    pub async fn set_write_firmware_pointer(&mut self, pointer: u32) -> Result<(), TinkerforgeError> {
614        let mut payload = [0; 4];
615        pointer.write_to_slice(&mut payload[0..4]);
616
617        #[allow(unused_variables)]
618        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::SetWriteFirmwarePointer), &payload).await?;
619        Ok(())
620    }
621
622    /// Writes 64 Bytes of firmware at the position as written by
623    /// [`set_write_firmware_pointer`] before. The firmware is written
624    /// to flash every 4 chunks.
625    ///
626    /// You can only write firmware in bootloader mode.
627    ///
628    /// This function is used by Brick Viewer during flashing. It should not be
629    /// necessary to call it in a normal user program.
630    pub async fn write_firmware(&mut self, data: &[u8; 64]) -> Result<u8, TinkerforgeError> {
631        let mut payload = [0; 64];
632        data.write_to_slice(&mut payload[0..64]);
633
634        #[allow(unused_variables)]
635        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::WriteFirmware), &payload).await?;
636        Ok(u8::from_le_byte_slice(result.body()))
637    }
638
639    /// Sets the status LED configuration. By default the LED shows
640    /// communication traffic between Brick and Bricklet, it flickers once
641    /// for every 10 received data packets.
642    ///
643    /// You can also turn the LED permanently on/off or show a heartbeat.
644    ///
645    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
646    ///
647    /// Associated constants:
648    /// * ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_OFF
649    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_ON
650    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
651    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
652    pub async fn set_status_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
653        let mut payload = [0; 1];
654        config.write_to_slice(&mut payload[0..1]);
655
656        #[allow(unused_variables)]
657        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::SetStatusLedConfig), &payload).await?;
658        Ok(())
659    }
660
661    /// Returns the configuration as set by [`set_status_led_config`]
662    ///
663    /// Associated constants:
664    /// * ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_OFF
665    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_ON
666    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
667    ///	* ENERGY_MONITOR_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
668    pub async fn get_status_led_config(&mut self) -> Result<u8, TinkerforgeError> {
669        let payload = [0; 0];
670
671        #[allow(unused_variables)]
672        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetStatusLedConfig), &payload).await?;
673        Ok(u8::from_le_byte_slice(result.body()))
674    }
675
676    /// Returns the temperature as measured inside the microcontroller. The
677    /// value returned is not the ambient temperature!
678    ///
679    /// The temperature is only proportional to the real temperature and it has bad
680    /// accuracy. Practically it is only useful as an indicator for
681    /// temperature changes.
682    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
683        let payload = [0; 0];
684
685        #[allow(unused_variables)]
686        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetChipTemperature), &payload).await?;
687        Ok(i16::from_le_byte_slice(result.body()))
688    }
689
690    /// Calling this function will reset the Bricklet. All configurations
691    /// will be lost.
692    ///
693    /// After a reset you have to create new device objects,
694    /// calling functions on the existing ones will result in
695    /// undefined behavior!
696    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
697        let payload = [0; 0];
698
699        #[allow(unused_variables)]
700        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::Reset), &payload).await?;
701        Ok(())
702    }
703
704    /// Writes a new UID into flash. If you want to set a new UID
705    /// you have to decode the Base58 encoded UID string into an
706    /// integer first.
707    ///
708    /// We recommend that you use Brick Viewer to change the UID.
709    pub async fn write_uid(&mut self, uid: u32) -> Result<(), TinkerforgeError> {
710        let mut payload = [0; 4];
711        uid.write_to_slice(&mut payload[0..4]);
712
713        #[allow(unused_variables)]
714        let result = self.device.set(u8::from(EnergyMonitorBrickletFunction::WriteUid), &payload).await?;
715        Ok(())
716    }
717
718    /// Returns the current UID as an integer. Encode as
719    /// Base58 to get the usual string version.
720    pub async fn read_uid(&mut self) -> Result<u32, TinkerforgeError> {
721        let payload = [0; 0];
722
723        #[allow(unused_variables)]
724        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::ReadUid), &payload).await?;
725        Ok(u32::from_le_byte_slice(result.body()))
726    }
727
728    /// Returns the UID, the UID where the Bricklet is connected to,
729    /// the position, the hardware and firmware version as well as the
730    /// device identifier.
731    ///
732    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
733    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
734    /// position 'z'.
735    ///
736    /// The device identifier numbers can be found [here](device_identifier).
737    /// |device_identifier_constant|
738    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
739        let payload = [0; 0];
740
741        #[allow(unused_variables)]
742        let result = self.device.get(u8::from(EnergyMonitorBrickletFunction::GetIdentity), &payload).await?;
743        Ok(Identity::from_le_byte_slice(result.body()))
744    }
745}