tinkerforge_async/bindings/
industrial_dual_ac_relay_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//! Two relays to switch AC devices.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/IndustrialDualACRelay_Bricklet_Rust.html).
14#[allow(unused_imports)]
15use crate::{
16    base58::Uid, byte_converter::*, device::*, error::TinkerforgeError, ip_connection::async_io::AsyncIpConnection,
17    low_level_traits::LowLevelRead,
18};
19#[allow(unused_imports)]
20use futures_core::Stream;
21#[allow(unused_imports)]
22use tokio_stream::StreamExt;
23pub enum IndustrialDualAcRelayBrickletFunction {
24    SetValue,
25    GetValue,
26    SetChannelLedConfig,
27    GetChannelLedConfig,
28    SetMonoflop,
29    GetMonoflop,
30    SetSelectedValue,
31    GetSpitfpErrorCount,
32    SetBootloaderMode,
33    GetBootloaderMode,
34    SetWriteFirmwarePointer,
35    WriteFirmware,
36    SetStatusLedConfig,
37    GetStatusLedConfig,
38    GetChipTemperature,
39    Reset,
40    WriteUid,
41    ReadUid,
42    GetIdentity,
43    CallbackMonoflopDone,
44}
45impl From<IndustrialDualAcRelayBrickletFunction> for u8 {
46    fn from(fun: IndustrialDualAcRelayBrickletFunction) -> Self {
47        match fun {
48            IndustrialDualAcRelayBrickletFunction::SetValue => 1,
49            IndustrialDualAcRelayBrickletFunction::GetValue => 2,
50            IndustrialDualAcRelayBrickletFunction::SetChannelLedConfig => 3,
51            IndustrialDualAcRelayBrickletFunction::GetChannelLedConfig => 4,
52            IndustrialDualAcRelayBrickletFunction::SetMonoflop => 5,
53            IndustrialDualAcRelayBrickletFunction::GetMonoflop => 6,
54            IndustrialDualAcRelayBrickletFunction::SetSelectedValue => 8,
55            IndustrialDualAcRelayBrickletFunction::GetSpitfpErrorCount => 234,
56            IndustrialDualAcRelayBrickletFunction::SetBootloaderMode => 235,
57            IndustrialDualAcRelayBrickletFunction::GetBootloaderMode => 236,
58            IndustrialDualAcRelayBrickletFunction::SetWriteFirmwarePointer => 237,
59            IndustrialDualAcRelayBrickletFunction::WriteFirmware => 238,
60            IndustrialDualAcRelayBrickletFunction::SetStatusLedConfig => 239,
61            IndustrialDualAcRelayBrickletFunction::GetStatusLedConfig => 240,
62            IndustrialDualAcRelayBrickletFunction::GetChipTemperature => 242,
63            IndustrialDualAcRelayBrickletFunction::Reset => 243,
64            IndustrialDualAcRelayBrickletFunction::WriteUid => 248,
65            IndustrialDualAcRelayBrickletFunction::ReadUid => 249,
66            IndustrialDualAcRelayBrickletFunction::GetIdentity => 255,
67            IndustrialDualAcRelayBrickletFunction::CallbackMonoflopDone => 7,
68        }
69    }
70}
71pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_OFF: u8 = 0;
72pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_ON: u8 = 1;
73pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
74pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS: u8 = 3;
75pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
76pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
77pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
78pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
79pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
80pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
81pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
82pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
83pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
84pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
85pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
86pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
87pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
88pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
89pub const INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
90
91#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
92pub struct Value {
93    pub channel0: bool,
94    pub channel1: bool,
95}
96impl FromByteSlice for Value {
97    fn bytes_expected() -> usize {
98        2
99    }
100    fn from_le_byte_slice(bytes: &[u8]) -> Value {
101        Value { channel0: <bool>::from_le_byte_slice(&bytes[0..1]), channel1: <bool>::from_le_byte_slice(&bytes[1..2]) }
102    }
103}
104
105#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
106pub struct Monoflop {
107    pub value: bool,
108    pub time: u32,
109    pub time_remaining: u32,
110}
111impl FromByteSlice for Monoflop {
112    fn bytes_expected() -> usize {
113        9
114    }
115    fn from_le_byte_slice(bytes: &[u8]) -> Monoflop {
116        Monoflop {
117            value: <bool>::from_le_byte_slice(&bytes[0..1]),
118            time: <u32>::from_le_byte_slice(&bytes[1..5]),
119            time_remaining: <u32>::from_le_byte_slice(&bytes[5..9]),
120        }
121    }
122}
123
124#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
125pub struct MonoflopDoneEvent {
126    pub channel: u8,
127    pub value: bool,
128}
129impl FromByteSlice for MonoflopDoneEvent {
130    fn bytes_expected() -> usize {
131        2
132    }
133    fn from_le_byte_slice(bytes: &[u8]) -> MonoflopDoneEvent {
134        MonoflopDoneEvent { channel: <u8>::from_le_byte_slice(&bytes[0..1]), value: <bool>::from_le_byte_slice(&bytes[1..2]) }
135    }
136}
137
138#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
139pub struct SpitfpErrorCount {
140    pub error_count_ack_checksum: u32,
141    pub error_count_message_checksum: u32,
142    pub error_count_frame: u32,
143    pub error_count_overflow: u32,
144}
145impl FromByteSlice for SpitfpErrorCount {
146    fn bytes_expected() -> usize {
147        16
148    }
149    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
150        SpitfpErrorCount {
151            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
152            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
153            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
154            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
155        }
156    }
157}
158
159#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
160pub struct Identity {
161    pub uid: String,
162    pub connected_uid: String,
163    pub position: char,
164    pub hardware_version: [u8; 3],
165    pub firmware_version: [u8; 3],
166    pub device_identifier: u16,
167}
168impl FromByteSlice for Identity {
169    fn bytes_expected() -> usize {
170        25
171    }
172    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
173        Identity {
174            uid: <String>::from_le_byte_slice(&bytes[0..8]),
175            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
176            position: <char>::from_le_byte_slice(&bytes[16..17]),
177            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
178            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
179            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
180        }
181    }
182}
183
184/// Two relays to switch AC devices
185#[derive(Clone)]
186pub struct IndustrialDualAcRelayBricklet {
187    device: Device,
188}
189impl IndustrialDualAcRelayBricklet {
190    pub const DEVICE_IDENTIFIER: u16 = 2162;
191    pub const DEVICE_DISPLAY_NAME: &'static str = "Industrial Dual AC Relay Bricklet";
192    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
193    pub fn new(uid: Uid, connection: AsyncIpConnection) -> IndustrialDualAcRelayBricklet {
194        let mut result = IndustrialDualAcRelayBricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
195        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetValue) as usize] = ResponseExpectedFlag::False;
196        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetValue) as usize] =
197            ResponseExpectedFlag::AlwaysTrue;
198        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetChannelLedConfig) as usize] =
199            ResponseExpectedFlag::False;
200        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetChannelLedConfig) as usize] =
201            ResponseExpectedFlag::AlwaysTrue;
202        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetMonoflop) as usize] =
203            ResponseExpectedFlag::False;
204        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetMonoflop) as usize] =
205            ResponseExpectedFlag::AlwaysTrue;
206        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetSelectedValue) as usize] =
207            ResponseExpectedFlag::False;
208        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetSpitfpErrorCount) as usize] =
209            ResponseExpectedFlag::AlwaysTrue;
210        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetBootloaderMode) as usize] =
211            ResponseExpectedFlag::AlwaysTrue;
212        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetBootloaderMode) as usize] =
213            ResponseExpectedFlag::AlwaysTrue;
214        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetWriteFirmwarePointer) as usize] =
215            ResponseExpectedFlag::False;
216        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::WriteFirmware) as usize] =
217            ResponseExpectedFlag::AlwaysTrue;
218        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::SetStatusLedConfig) as usize] =
219            ResponseExpectedFlag::False;
220        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetStatusLedConfig) as usize] =
221            ResponseExpectedFlag::AlwaysTrue;
222        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetChipTemperature) as usize] =
223            ResponseExpectedFlag::AlwaysTrue;
224        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
225        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
226        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::ReadUid) as usize] =
227            ResponseExpectedFlag::AlwaysTrue;
228        result.device.response_expected[u8::from(IndustrialDualAcRelayBrickletFunction::GetIdentity) as usize] =
229            ResponseExpectedFlag::AlwaysTrue;
230        result
231    }
232
233    /// Returns the response expected flag for the function specified by the function ID parameter.
234    /// It is true if the function is expected to send a response, false otherwise.
235    ///
236    /// For getter functions this is enabled by default and cannot be disabled, because those
237    /// functions will always send a response. For callback configuration functions it is enabled
238    /// by default too, but can be disabled by [`set_response_expected`](crate::industrial_dual_ac_relay_bricklet::IndustrialDualAcRelayBricklet::set_response_expected).
239    /// For setter functions it is disabled by default and can be enabled.
240    ///
241    /// Enabling the response expected flag for a setter function allows to detect timeouts
242    /// and other error conditions calls of this setter as well. The device will then send a response
243    /// for this purpose. If this flag is disabled for a setter function then no response is sent
244    /// and errors are silently ignored, because they cannot be detected.
245    ///
246    /// See [`set_response_expected`](crate::industrial_dual_ac_relay_bricklet::IndustrialDualAcRelayBricklet::set_response_expected) for the list of function ID constants available for this function.
247    pub fn get_response_expected(&mut self, fun: IndustrialDualAcRelayBrickletFunction) -> Result<bool, GetResponseExpectedError> {
248        self.device.get_response_expected(u8::from(fun))
249    }
250
251    /// Changes the response expected flag of the function specified by the function ID parameter.
252    /// This flag can only be changed for setter (default value: false) and callback configuration
253    /// functions (default value: true). For getter functions it is always enabled.
254    ///
255    /// Enabling the response expected flag for a setter function allows to detect timeouts and
256    /// other error conditions calls of this setter as well. The device will then send a response
257    /// for this purpose. If this flag is disabled for a setter function then no response is sent
258    /// and errors are silently ignored, because they cannot be detected.
259    pub fn set_response_expected(
260        &mut self,
261        fun: IndustrialDualAcRelayBrickletFunction,
262        response_expected: bool,
263    ) -> Result<(), SetResponseExpectedError> {
264        self.device.set_response_expected(u8::from(fun), response_expected)
265    }
266
267    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
268    pub fn set_response_expected_all(&mut self, response_expected: bool) {
269        self.device.set_response_expected_all(response_expected)
270    }
271
272    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
273    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
274    pub fn get_api_version(&self) -> [u8; 3] {
275        self.device.api_version
276    }
277
278    /// This receiver is triggered whenever a monoflop timer reaches 0. The
279    /// parameters contain the relay and the current state of the relay
280    /// (the state after the monoflop).
281    pub async fn get_monoflop_done_callback_receiver(&mut self) -> impl Stream<Item = MonoflopDoneEvent> {
282        self.device
283            .get_callback_receiver(u8::from(IndustrialDualAcRelayBrickletFunction::CallbackMonoflopDone))
284            .await
285            .map(|p| MonoflopDoneEvent::from_le_byte_slice(p.body()))
286    }
287
288    /// Sets the state of the relays, *true* means on and *false* means off.
289    /// For example: (true, false) turns relay 0 on and relay 1 off.
290    ///
291    /// If you just want to set one of the relays and don't know the current state
292    /// of the other relay, you can get the state with [`get_value`] or you
293    /// can use [`set_selected_value`].
294    ///
295    /// All running monoflop timers will be aborted if this function is called.
296    pub async fn set_value(&mut self, channel0: bool, channel1: bool) -> Result<(), TinkerforgeError> {
297        let mut payload = [0; 2];
298        channel0.write_to_slice(&mut payload[0..1]);
299        channel1.write_to_slice(&mut payload[1..2]);
300
301        #[allow(unused_variables)]
302        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetValue), &payload).await?;
303        Ok(())
304    }
305
306    /// Returns the state of the relays, *true* means on and *false* means off.
307    pub async fn get_value(&mut self) -> Result<Value, TinkerforgeError> {
308        let payload = [0; 0];
309
310        #[allow(unused_variables)]
311        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetValue), &payload).await?;
312        Ok(Value::from_le_byte_slice(result.body()))
313    }
314
315    /// Each channel has a corresponding LED. You can turn the LED off, on or show a
316    /// heartbeat. You can also set the LED to Channel Status. In this mode the
317    /// LED is on if the channel is high and off otherwise.
318    ///
319    /// Associated constants:
320    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_OFF
321    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_ON
322    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_HEARTBEAT
323    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS
324    pub async fn set_channel_led_config(&mut self, channel: u8, config: u8) -> Result<(), TinkerforgeError> {
325        let mut payload = [0; 2];
326        channel.write_to_slice(&mut payload[0..1]);
327        config.write_to_slice(&mut payload[1..2]);
328
329        #[allow(unused_variables)]
330        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetChannelLedConfig), &payload).await?;
331        Ok(())
332    }
333
334    /// Returns the channel LED configuration as set by [`set_channel_led_config`]
335    ///
336    /// Associated constants:
337    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_OFF
338    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_ON
339    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_HEARTBEAT
340    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_CHANNEL_LED_CONFIG_SHOW_CHANNEL_STATUS
341    pub async fn get_channel_led_config(&mut self, channel: u8) -> Result<u8, TinkerforgeError> {
342        let mut payload = [0; 1];
343        channel.write_to_slice(&mut payload[0..1]);
344
345        #[allow(unused_variables)]
346        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetChannelLedConfig), &payload).await?;
347        Ok(u8::from_le_byte_slice(result.body()))
348    }
349
350    /// The first parameter can be 0 or 1 (relay 0 or relay 1). The second parameter
351    /// is the desired state of the relay (*true* means on and *false* means off).
352    /// The third parameter indicates the time that the relay should hold
353    /// the state.
354    ///
355    /// If this function is called with the parameters (1, true, 1500):
356    /// Relay 1 will turn on and in 1.5s it will turn off again.
357    ///
358    /// A monoflop can be used as a failsafe mechanism. For example: Lets assume you
359    /// have a RS485 bus and a Industrial Dual AC Relay Bricklet connected to one of the
360    /// slave stacks. You can now call this function every second, with a time parameter
361    /// of two seconds. The relay will be on all the time. If now the RS485
362    /// connection is lost, the relay will turn off in at most two seconds.
363    pub async fn set_monoflop(&mut self, channel: u8, value: bool, time: u32) -> Result<(), TinkerforgeError> {
364        let mut payload = [0; 6];
365        channel.write_to_slice(&mut payload[0..1]);
366        value.write_to_slice(&mut payload[1..2]);
367        time.write_to_slice(&mut payload[2..6]);
368
369        #[allow(unused_variables)]
370        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetMonoflop), &payload).await?;
371        Ok(())
372    }
373
374    /// Returns (for the given relay) the current state and the time as set by
375    /// [`set_monoflop`] as well as the remaining time until the state flips.
376    ///
377    /// If the timer is not running currently, the remaining time will be returned
378    /// as 0.
379    pub async fn get_monoflop(&mut self, channel: u8) -> Result<Monoflop, TinkerforgeError> {
380        let mut payload = [0; 1];
381        channel.write_to_slice(&mut payload[0..1]);
382
383        #[allow(unused_variables)]
384        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetMonoflop), &payload).await?;
385        Ok(Monoflop::from_le_byte_slice(result.body()))
386    }
387
388    /// Sets the state of the selected relay, *true* means on and *false*
389    /// means off.
390    ///
391    /// A running monoflop timer for the selected relay will be aborted if this function
392    /// is called.
393    ///
394    /// The other relay remains untouched.
395    pub async fn set_selected_value(&mut self, channel: u8, value: bool) -> Result<(), TinkerforgeError> {
396        let mut payload = [0; 2];
397        channel.write_to_slice(&mut payload[0..1]);
398        value.write_to_slice(&mut payload[1..2]);
399
400        #[allow(unused_variables)]
401        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetSelectedValue), &payload).await?;
402        Ok(())
403    }
404
405    /// Returns the error count for the communication between Brick and Bricklet.
406    ///
407    /// The errors are divided into
408    ///
409    /// * ACK checksum errors,
410    /// * message checksum errors,
411    /// * framing errors and
412    /// * overflow errors.
413    ///
414    /// The errors counts are for errors that occur on the Bricklet side. All
415    /// Bricks have a similar function that returns the errors on the Brick side.
416    pub async fn get_spitfp_error_count(&mut self) -> Result<SpitfpErrorCount, TinkerforgeError> {
417        let payload = [0; 0];
418
419        #[allow(unused_variables)]
420        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetSpitfpErrorCount), &payload).await?;
421        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
422    }
423
424    /// Sets the bootloader mode and returns the status after the requested
425    /// mode change was instigated.
426    ///
427    /// You can change from bootloader mode to firmware mode and vice versa. A change
428    /// from bootloader mode to firmware mode will only take place if the entry function,
429    /// device identifier and CRC are present and correct.
430    ///
431    /// This function is used by Brick Viewer during flashing. It should not be
432    /// necessary to call it in a normal user program.
433    ///
434    /// Associated constants:
435    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
436    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE
437    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
438    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
439    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
440    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_OK
441    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
442    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
443    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
444    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
445    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
446    pub async fn set_bootloader_mode(&mut self, mode: u8) -> Result<u8, TinkerforgeError> {
447        let mut payload = [0; 1];
448        mode.write_to_slice(&mut payload[0..1]);
449
450        #[allow(unused_variables)]
451        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::SetBootloaderMode), &payload).await?;
452        Ok(u8::from_le_byte_slice(result.body()))
453    }
454
455    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
456    ///
457    /// Associated constants:
458    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
459    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE
460    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
461    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
462    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
463    pub async fn get_bootloader_mode(&mut self) -> Result<u8, TinkerforgeError> {
464        let payload = [0; 0];
465
466        #[allow(unused_variables)]
467        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetBootloaderMode), &payload).await?;
468        Ok(u8::from_le_byte_slice(result.body()))
469    }
470
471    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
472    /// to be increased by chunks of size 64. The data is written to flash
473    /// every 4 chunks (which equals to one page of size 256).
474    ///
475    /// This function is used by Brick Viewer during flashing. It should not be
476    /// necessary to call it in a normal user program.
477    pub async fn set_write_firmware_pointer(&mut self, pointer: u32) -> Result<(), TinkerforgeError> {
478        let mut payload = [0; 4];
479        pointer.write_to_slice(&mut payload[0..4]);
480
481        #[allow(unused_variables)]
482        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetWriteFirmwarePointer), &payload).await?;
483        Ok(())
484    }
485
486    /// Writes 64 Bytes of firmware at the position as written by
487    /// [`set_write_firmware_pointer`] before. The firmware is written
488    /// to flash every 4 chunks.
489    ///
490    /// You can only write firmware in bootloader mode.
491    ///
492    /// This function is used by Brick Viewer during flashing. It should not be
493    /// necessary to call it in a normal user program.
494    pub async fn write_firmware(&mut self, data: &[u8; 64]) -> Result<u8, TinkerforgeError> {
495        let mut payload = [0; 64];
496        data.write_to_slice(&mut payload[0..64]);
497
498        #[allow(unused_variables)]
499        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::WriteFirmware), &payload).await?;
500        Ok(u8::from_le_byte_slice(result.body()))
501    }
502
503    /// Sets the status LED configuration. By default the LED shows
504    /// communication traffic between Brick and Bricklet, it flickers once
505    /// for every 10 received data packets.
506    ///
507    /// You can also turn the LED permanently on/off or show a heartbeat.
508    ///
509    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
510    ///
511    /// Associated constants:
512    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_OFF
513    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_ON
514    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
515    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
516    pub async fn set_status_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
517        let mut payload = [0; 1];
518        config.write_to_slice(&mut payload[0..1]);
519
520        #[allow(unused_variables)]
521        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::SetStatusLedConfig), &payload).await?;
522        Ok(())
523    }
524
525    /// Returns the configuration as set by [`set_status_led_config`]
526    ///
527    /// Associated constants:
528    /// * INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_OFF
529    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_ON
530    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
531    ///	* INDUSTRIAL_DUAL_AC_RELAY_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
532    pub async fn get_status_led_config(&mut self) -> Result<u8, TinkerforgeError> {
533        let payload = [0; 0];
534
535        #[allow(unused_variables)]
536        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetStatusLedConfig), &payload).await?;
537        Ok(u8::from_le_byte_slice(result.body()))
538    }
539
540    /// Returns the temperature as measured inside the microcontroller. The
541    /// value returned is not the ambient temperature!
542    ///
543    /// The temperature is only proportional to the real temperature and it has bad
544    /// accuracy. Practically it is only useful as an indicator for
545    /// temperature changes.
546    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
547        let payload = [0; 0];
548
549        #[allow(unused_variables)]
550        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetChipTemperature), &payload).await?;
551        Ok(i16::from_le_byte_slice(result.body()))
552    }
553
554    /// Calling this function will reset the Bricklet. All configurations
555    /// will be lost.
556    ///
557    /// After a reset you have to create new device objects,
558    /// calling functions on the existing ones will result in
559    /// undefined behavior!
560    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
561        let payload = [0; 0];
562
563        #[allow(unused_variables)]
564        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::Reset), &payload).await?;
565        Ok(())
566    }
567
568    /// Writes a new UID into flash. If you want to set a new UID
569    /// you have to decode the Base58 encoded UID string into an
570    /// integer first.
571    ///
572    /// We recommend that you use Brick Viewer to change the UID.
573    pub async fn write_uid(&mut self, uid: u32) -> Result<(), TinkerforgeError> {
574        let mut payload = [0; 4];
575        uid.write_to_slice(&mut payload[0..4]);
576
577        #[allow(unused_variables)]
578        let result = self.device.set(u8::from(IndustrialDualAcRelayBrickletFunction::WriteUid), &payload).await?;
579        Ok(())
580    }
581
582    /// Returns the current UID as an integer. Encode as
583    /// Base58 to get the usual string version.
584    pub async fn read_uid(&mut self) -> Result<u32, TinkerforgeError> {
585        let payload = [0; 0];
586
587        #[allow(unused_variables)]
588        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::ReadUid), &payload).await?;
589        Ok(u32::from_le_byte_slice(result.body()))
590    }
591
592    /// Returns the UID, the UID where the Bricklet is connected to,
593    /// the position, the hardware and firmware version as well as the
594    /// device identifier.
595    ///
596    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
597    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
598    /// position 'z'.
599    ///
600    /// The device identifier numbers can be found [here](device_identifier).
601    /// |device_identifier_constant|
602    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
603        let payload = [0; 0];
604
605        #[allow(unused_variables)]
606        let result = self.device.get(u8::from(IndustrialDualAcRelayBrickletFunction::GetIdentity), &payload).await?;
607        Ok(Identity::from_le_byte_slice(result.body()))
608    }
609}