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