tinkerforge_async/bindings/
io4_v2_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//! 4-channel digital input/output.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/IO4V2_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 Io4V2BrickletFunction {
24    SetValue,
25    GetValue,
26    SetSelectedValue,
27    SetConfiguration,
28    GetConfiguration,
29    SetInputValueCallbackConfiguration,
30    GetInputValueCallbackConfiguration,
31    SetAllInputValueCallbackConfiguration,
32    GetAllInputValueCallbackConfiguration,
33    SetMonoflop,
34    GetMonoflop,
35    GetEdgeCount,
36    SetEdgeCountConfiguration,
37    GetEdgeCountConfiguration,
38    SetPwmConfiguration,
39    GetPwmConfiguration,
40    GetSpitfpErrorCount,
41    SetBootloaderMode,
42    GetBootloaderMode,
43    SetWriteFirmwarePointer,
44    WriteFirmware,
45    SetStatusLedConfig,
46    GetStatusLedConfig,
47    GetChipTemperature,
48    Reset,
49    WriteUid,
50    ReadUid,
51    GetIdentity,
52    CallbackInputValue,
53    CallbackAllInputValue,
54    CallbackMonoflopDone,
55}
56impl From<Io4V2BrickletFunction> for u8 {
57    fn from(fun: Io4V2BrickletFunction) -> Self {
58        match fun {
59            Io4V2BrickletFunction::SetValue => 1,
60            Io4V2BrickletFunction::GetValue => 2,
61            Io4V2BrickletFunction::SetSelectedValue => 3,
62            Io4V2BrickletFunction::SetConfiguration => 4,
63            Io4V2BrickletFunction::GetConfiguration => 5,
64            Io4V2BrickletFunction::SetInputValueCallbackConfiguration => 6,
65            Io4V2BrickletFunction::GetInputValueCallbackConfiguration => 7,
66            Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration => 8,
67            Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration => 9,
68            Io4V2BrickletFunction::SetMonoflop => 10,
69            Io4V2BrickletFunction::GetMonoflop => 11,
70            Io4V2BrickletFunction::GetEdgeCount => 12,
71            Io4V2BrickletFunction::SetEdgeCountConfiguration => 13,
72            Io4V2BrickletFunction::GetEdgeCountConfiguration => 14,
73            Io4V2BrickletFunction::SetPwmConfiguration => 15,
74            Io4V2BrickletFunction::GetPwmConfiguration => 16,
75            Io4V2BrickletFunction::GetSpitfpErrorCount => 234,
76            Io4V2BrickletFunction::SetBootloaderMode => 235,
77            Io4V2BrickletFunction::GetBootloaderMode => 236,
78            Io4V2BrickletFunction::SetWriteFirmwarePointer => 237,
79            Io4V2BrickletFunction::WriteFirmware => 238,
80            Io4V2BrickletFunction::SetStatusLedConfig => 239,
81            Io4V2BrickletFunction::GetStatusLedConfig => 240,
82            Io4V2BrickletFunction::GetChipTemperature => 242,
83            Io4V2BrickletFunction::Reset => 243,
84            Io4V2BrickletFunction::WriteUid => 248,
85            Io4V2BrickletFunction::ReadUid => 249,
86            Io4V2BrickletFunction::GetIdentity => 255,
87            Io4V2BrickletFunction::CallbackInputValue => 17,
88            Io4V2BrickletFunction::CallbackAllInputValue => 18,
89            Io4V2BrickletFunction::CallbackMonoflopDone => 19,
90        }
91    }
92}
93pub const IO4_V2_BRICKLET_DIRECTION_IN: char = 'i';
94pub const IO4_V2_BRICKLET_DIRECTION_OUT: char = 'o';
95pub const IO4_V2_BRICKLET_EDGE_TYPE_RISING: u8 = 0;
96pub const IO4_V2_BRICKLET_EDGE_TYPE_FALLING: u8 = 1;
97pub const IO4_V2_BRICKLET_EDGE_TYPE_BOTH: u8 = 2;
98pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
99pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
100pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
101pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
102pub const IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
103pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
104pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
105pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
106pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
107pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
108pub const IO4_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
109pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
110pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
111pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
112pub const IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
113
114#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
115pub struct Configuration {
116    pub direction: char,
117    pub value: bool,
118}
119impl FromByteSlice for Configuration {
120    fn bytes_expected() -> usize {
121        2
122    }
123    fn from_le_byte_slice(bytes: &[u8]) -> Configuration {
124        Configuration { direction: <char>::from_le_byte_slice(&bytes[0..1]), value: <bool>::from_le_byte_slice(&bytes[1..2]) }
125    }
126}
127
128#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
129pub struct InputValueCallbackConfiguration {
130    pub period: u32,
131    pub value_has_to_change: bool,
132}
133impl FromByteSlice for InputValueCallbackConfiguration {
134    fn bytes_expected() -> usize {
135        5
136    }
137    fn from_le_byte_slice(bytes: &[u8]) -> InputValueCallbackConfiguration {
138        InputValueCallbackConfiguration {
139            period: <u32>::from_le_byte_slice(&bytes[0..4]),
140            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
141        }
142    }
143}
144
145#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
146pub struct AllInputValueCallbackConfiguration {
147    pub period: u32,
148    pub value_has_to_change: bool,
149}
150impl FromByteSlice for AllInputValueCallbackConfiguration {
151    fn bytes_expected() -> usize {
152        5
153    }
154    fn from_le_byte_slice(bytes: &[u8]) -> AllInputValueCallbackConfiguration {
155        AllInputValueCallbackConfiguration {
156            period: <u32>::from_le_byte_slice(&bytes[0..4]),
157            value_has_to_change: <bool>::from_le_byte_slice(&bytes[4..5]),
158        }
159    }
160}
161
162#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
163pub struct Monoflop {
164    pub value: bool,
165    pub time: u32,
166    pub time_remaining: u32,
167}
168impl FromByteSlice for Monoflop {
169    fn bytes_expected() -> usize {
170        9
171    }
172    fn from_le_byte_slice(bytes: &[u8]) -> Monoflop {
173        Monoflop {
174            value: <bool>::from_le_byte_slice(&bytes[0..1]),
175            time: <u32>::from_le_byte_slice(&bytes[1..5]),
176            time_remaining: <u32>::from_le_byte_slice(&bytes[5..9]),
177        }
178    }
179}
180
181#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
182pub struct EdgeCountConfiguration {
183    pub edge_type: u8,
184    pub debounce: u8,
185}
186impl FromByteSlice for EdgeCountConfiguration {
187    fn bytes_expected() -> usize {
188        2
189    }
190    fn from_le_byte_slice(bytes: &[u8]) -> EdgeCountConfiguration {
191        EdgeCountConfiguration { edge_type: <u8>::from_le_byte_slice(&bytes[0..1]), debounce: <u8>::from_le_byte_slice(&bytes[1..2]) }
192    }
193}
194
195#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
196pub struct PwmConfiguration {
197    pub frequency: u32,
198    pub duty_cycle: u16,
199}
200impl FromByteSlice for PwmConfiguration {
201    fn bytes_expected() -> usize {
202        6
203    }
204    fn from_le_byte_slice(bytes: &[u8]) -> PwmConfiguration {
205        PwmConfiguration { frequency: <u32>::from_le_byte_slice(&bytes[0..4]), duty_cycle: <u16>::from_le_byte_slice(&bytes[4..6]) }
206    }
207}
208
209#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
210pub struct InputValueEvent {
211    pub channel: u8,
212    pub changed: bool,
213    pub value: bool,
214}
215impl FromByteSlice for InputValueEvent {
216    fn bytes_expected() -> usize {
217        3
218    }
219    fn from_le_byte_slice(bytes: &[u8]) -> InputValueEvent {
220        InputValueEvent {
221            channel: <u8>::from_le_byte_slice(&bytes[0..1]),
222            changed: <bool>::from_le_byte_slice(&bytes[1..2]),
223            value: <bool>::from_le_byte_slice(&bytes[2..3]),
224        }
225    }
226}
227
228#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
229pub struct AllInputValueEvent {
230    pub changed: [bool; 4],
231    pub value: [bool; 4],
232}
233impl FromByteSlice for AllInputValueEvent {
234    fn bytes_expected() -> usize {
235        2
236    }
237    fn from_le_byte_slice(bytes: &[u8]) -> AllInputValueEvent {
238        AllInputValueEvent { changed: <[bool; 4]>::from_le_byte_slice(&bytes[0..1]), value: <[bool; 4]>::from_le_byte_slice(&bytes[1..2]) }
239    }
240}
241
242#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
243pub struct MonoflopDoneEvent {
244    pub channel: u8,
245    pub value: bool,
246}
247impl FromByteSlice for MonoflopDoneEvent {
248    fn bytes_expected() -> usize {
249        2
250    }
251    fn from_le_byte_slice(bytes: &[u8]) -> MonoflopDoneEvent {
252        MonoflopDoneEvent { channel: <u8>::from_le_byte_slice(&bytes[0..1]), value: <bool>::from_le_byte_slice(&bytes[1..2]) }
253    }
254}
255
256#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
257pub struct SpitfpErrorCount {
258    pub error_count_ack_checksum: u32,
259    pub error_count_message_checksum: u32,
260    pub error_count_frame: u32,
261    pub error_count_overflow: u32,
262}
263impl FromByteSlice for SpitfpErrorCount {
264    fn bytes_expected() -> usize {
265        16
266    }
267    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
268        SpitfpErrorCount {
269            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
270            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
271            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
272            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
273        }
274    }
275}
276
277#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
278pub struct Identity {
279    pub uid: String,
280    pub connected_uid: String,
281    pub position: char,
282    pub hardware_version: [u8; 3],
283    pub firmware_version: [u8; 3],
284    pub device_identifier: u16,
285}
286impl FromByteSlice for Identity {
287    fn bytes_expected() -> usize {
288        25
289    }
290    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
291        Identity {
292            uid: <String>::from_le_byte_slice(&bytes[0..8]),
293            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
294            position: <char>::from_le_byte_slice(&bytes[16..17]),
295            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
296            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
297            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
298        }
299    }
300}
301
302/// 4-channel digital input/output
303#[derive(Clone)]
304pub struct Io4V2Bricklet {
305    device: Device,
306}
307impl Io4V2Bricklet {
308    pub const DEVICE_IDENTIFIER: u16 = 2111;
309    pub const DEVICE_DISPLAY_NAME: &'static str = "IO-4 Bricklet 2.0";
310    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
311    pub fn new(uid: Uid, connection: AsyncIpConnection) -> Io4V2Bricklet {
312        let mut result = Io4V2Bricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
313        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetValue) as usize] = ResponseExpectedFlag::False;
314        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetValue) as usize] = ResponseExpectedFlag::AlwaysTrue;
315        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetSelectedValue) as usize] = ResponseExpectedFlag::False;
316        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetConfiguration) as usize] = ResponseExpectedFlag::False;
317        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetConfiguration) as usize] = ResponseExpectedFlag::AlwaysTrue;
318        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetInputValueCallbackConfiguration) as usize] =
319            ResponseExpectedFlag::True;
320        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetInputValueCallbackConfiguration) as usize] =
321            ResponseExpectedFlag::AlwaysTrue;
322        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration) as usize] =
323            ResponseExpectedFlag::True;
324        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration) as usize] =
325            ResponseExpectedFlag::AlwaysTrue;
326        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetMonoflop) as usize] = ResponseExpectedFlag::False;
327        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetMonoflop) as usize] = ResponseExpectedFlag::AlwaysTrue;
328        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetEdgeCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
329        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetEdgeCountConfiguration) as usize] = ResponseExpectedFlag::False;
330        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetEdgeCountConfiguration) as usize] =
331            ResponseExpectedFlag::AlwaysTrue;
332        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetPwmConfiguration) as usize] = ResponseExpectedFlag::False;
333        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetPwmConfiguration) as usize] = ResponseExpectedFlag::AlwaysTrue;
334        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetSpitfpErrorCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
335        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
336        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
337        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetWriteFirmwarePointer) as usize] = ResponseExpectedFlag::False;
338        result.device.response_expected[u8::from(Io4V2BrickletFunction::WriteFirmware) as usize] = ResponseExpectedFlag::AlwaysTrue;
339        result.device.response_expected[u8::from(Io4V2BrickletFunction::SetStatusLedConfig) as usize] = ResponseExpectedFlag::False;
340        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetStatusLedConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
341        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetChipTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
342        result.device.response_expected[u8::from(Io4V2BrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
343        result.device.response_expected[u8::from(Io4V2BrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
344        result.device.response_expected[u8::from(Io4V2BrickletFunction::ReadUid) as usize] = ResponseExpectedFlag::AlwaysTrue;
345        result.device.response_expected[u8::from(Io4V2BrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
346        result
347    }
348
349    /// Returns the response expected flag for the function specified by the function ID parameter.
350    /// It is true if the function is expected to send a response, false otherwise.
351    ///
352    /// For getter functions this is enabled by default and cannot be disabled, because those
353    /// functions will always send a response. For callback configuration functions it is enabled
354    /// by default too, but can be disabled by [`set_response_expected`](crate::io4_v2_bricklet::Io4V2Bricklet::set_response_expected).
355    /// For setter functions it is disabled by default and can be enabled.
356    ///
357    /// Enabling the response expected flag for a setter function allows to detect timeouts
358    /// and other error conditions calls of this setter as well. The device will then send a response
359    /// for this purpose. If this flag is disabled for a setter function then no response is sent
360    /// and errors are silently ignored, because they cannot be detected.
361    ///
362    /// See [`set_response_expected`](crate::io4_v2_bricklet::Io4V2Bricklet::set_response_expected) for the list of function ID constants available for this function.
363    pub fn get_response_expected(&mut self, fun: Io4V2BrickletFunction) -> Result<bool, GetResponseExpectedError> {
364        self.device.get_response_expected(u8::from(fun))
365    }
366
367    /// Changes the response expected flag of the function specified by the function ID parameter.
368    /// This flag can only be changed for setter (default value: false) and callback configuration
369    /// functions (default value: true). For getter functions it is always enabled.
370    ///
371    /// Enabling the response expected flag for a setter function allows to detect timeouts and
372    /// other error conditions calls of this setter as well. The device will then send a response
373    /// for this purpose. If this flag is disabled for a setter function then no response is sent
374    /// and errors are silently ignored, because they cannot be detected.
375    pub fn set_response_expected(&mut self, fun: Io4V2BrickletFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
376        self.device.set_response_expected(u8::from(fun), response_expected)
377    }
378
379    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
380    pub fn set_response_expected_all(&mut self, response_expected: bool) {
381        self.device.set_response_expected_all(response_expected)
382    }
383
384    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
385    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
386    pub fn get_api_version(&self) -> [u8; 3] {
387        self.device.api_version
388    }
389
390    /// This receiver is triggered periodically according to the configuration set by
391    /// [`set_input_value_callback_configuration`].
392    ///
393    /// The parameters are the channel, a value-changed indicator and the actual value
394    /// for the channel. The `changed` parameter is true if the value has changed since
395    /// the last receiver.
396    ///
397    /// [`set_input_value_callback_configuration`]: #method.set_input_value_callback_configuration
398    pub async fn get_input_value_callback_receiver(&mut self) -> impl Stream<Item = InputValueEvent> {
399        self.device
400            .get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackInputValue))
401            .await
402            .map(|p| InputValueEvent::from_le_byte_slice(p.body()))
403    }
404
405    /// This receiver is triggered periodically according to the configuration set by
406    /// [`set_all_input_value_callback_configuration`].
407    ///
408    /// The parameters are the same as [`get_value`]. Additional the
409    /// `changed` parameter is true if the value has changed since
410    /// the last receiver.
411    pub async fn get_all_input_value_callback_receiver(&mut self) -> impl Stream<Item = AllInputValueEvent> {
412        self.device
413            .get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackAllInputValue))
414            .await
415            .map(|p| AllInputValueEvent::from_le_byte_slice(p.body()))
416    }
417
418    /// This receiver is triggered whenever a monoflop timer reaches 0. The
419    /// parameters contain the channel and the current value of the channel
420    /// (the value after the monoflop).
421    pub async fn get_monoflop_done_callback_receiver(&mut self) -> impl Stream<Item = MonoflopDoneEvent> {
422        self.device
423            .get_callback_receiver(u8::from(Io4V2BrickletFunction::CallbackMonoflopDone))
424            .await
425            .map(|p| MonoflopDoneEvent::from_le_byte_slice(p.body()))
426    }
427
428    /// Sets the output value of all four channels. A value of *true* or *false* outputs
429    /// logic 1 or logic 0 respectively on the corresponding channel.
430    ///
431    /// Use [`set_selected_value`] to change only one output channel state.
432    ///
433    /// For example: (True, True, False, False) will turn the channels 0-1 high and the
434    /// channels 2-3 low.
435    ///
436    /// All running monoflop timers and PWMs will be aborted if this function is called.
437    ///
438    /// # Note
439    ///  This function does nothing for channels that are configured as input. Pull-up
440    ///  resistors can be switched on with [`set_configuration`].
441    pub async fn set_value(&mut self, value: &[bool; 4]) -> Result<(), TinkerforgeError> {
442        let mut payload = [0; 1];
443        value.write_to_slice(&mut payload[0..1]);
444
445        #[allow(unused_variables)]
446        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetValue), &payload).await?;
447        Ok(())
448    }
449
450    /// Returns the logic levels that are currently measured on the channels.
451    /// This function works if the channel is configured as input as well as if it is
452    /// configured as output.
453    pub async fn get_value(&mut self) -> Result<Box<[bool; 4]>, TinkerforgeError> {
454        let payload = [0; 0];
455
456        #[allow(unused_variables)]
457        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetValue), &payload).await?;
458        Ok(Box::<[bool; 4]>::from_le_byte_slice(result.body()))
459    }
460
461    /// Sets the output value of a specific channel without affecting the other channels.
462    ///
463    /// A running monoflop timer or PWM for the specific channel will be aborted if this
464    /// function is called.
465    ///
466    /// # Note
467    ///  This function does nothing for channels that are configured as input. Pull-up
468    ///  resistors can be switched on with [`set_configuration`].
469    pub async fn set_selected_value(&mut self, channel: u8, value: bool) -> Result<(), TinkerforgeError> {
470        let mut payload = [0; 2];
471        channel.write_to_slice(&mut payload[0..1]);
472        value.write_to_slice(&mut payload[1..2]);
473
474        #[allow(unused_variables)]
475        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetSelectedValue), &payload).await?;
476        Ok(())
477    }
478
479    /// Configures the value and direction of a specific channel. Possible directions
480    /// are 'i' and 'o' for input and output.
481    ///
482    /// If the direction is configured as output, the value is either high or low
483    /// (set as *true* or *false*).
484    ///
485    /// If the direction is configured as input, the value is either pull-up or
486    /// default (set as *true* or *false*).
487    ///
488    /// For example:
489    ///
490    /// * (0, 'i', true) will set channel 0 as input pull-up.
491    /// * (1, 'i', false) will set channel 1 as input default (floating if nothing is connected).
492    /// * (2, 'o', true) will set channel 2 as output high.
493    /// * (3, 'o', false) will set channel 3 as output low.
494    ///
495    /// A running monoflop timer or PWM for the specific channel will be aborted if this
496    /// function is called.
497    ///
498    /// Associated constants:
499    /// * IO4_V2_BRICKLET_DIRECTION_IN
500    ///	* IO4_V2_BRICKLET_DIRECTION_OUT
501    pub async fn set_configuration(&mut self, channel: u8, direction: char, value: bool) -> Result<(), TinkerforgeError> {
502        let mut payload = [0; 3];
503        channel.write_to_slice(&mut payload[0..1]);
504        direction.write_to_slice(&mut payload[1..2]);
505        value.write_to_slice(&mut payload[2..3]);
506
507        #[allow(unused_variables)]
508        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetConfiguration), &payload).await?;
509        Ok(())
510    }
511
512    /// Returns the channel configuration as set by [`set_configuration`].
513    ///
514    /// Associated constants:
515    /// * IO4_V2_BRICKLET_DIRECTION_IN
516    ///	* IO4_V2_BRICKLET_DIRECTION_OUT
517    pub async fn get_configuration(&mut self, channel: u8) -> Result<Configuration, TinkerforgeError> {
518        let mut payload = [0; 1];
519        channel.write_to_slice(&mut payload[0..1]);
520
521        #[allow(unused_variables)]
522        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetConfiguration), &payload).await?;
523        Ok(Configuration::from_le_byte_slice(result.body()))
524    }
525
526    /// This receiver can be configured per channel.
527    ///
528    /// The period is the period with which the [`get_input_value_callback_receiver`]
529    /// receiver is triggered periodically. A value of 0 turns the receiver off.
530    ///
531    /// If the `value has to change`-parameter is set to true, the receiver is only
532    /// triggered after the value has changed. If the value didn't change within the
533    /// period, the receiver is triggered immediately on change.
534    ///
535    /// If it is set to false, the receiver is continuously triggered with the period,
536    /// independent of the value.
537    pub async fn set_input_value_callback_configuration(
538        &mut self,
539        channel: u8,
540        period: u32,
541        value_has_to_change: bool,
542    ) -> Result<(), TinkerforgeError> {
543        let mut payload = [0; 6];
544        channel.write_to_slice(&mut payload[0..1]);
545        period.write_to_slice(&mut payload[1..5]);
546        value_has_to_change.write_to_slice(&mut payload[5..6]);
547
548        #[allow(unused_variables)]
549        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetInputValueCallbackConfiguration), &payload).await?;
550        Ok(())
551    }
552
553    /// Returns the receiver configuration for the given channel as set by
554    /// [`set_input_value_callback_configuration`].
555    pub async fn get_input_value_callback_configuration(
556        &mut self,
557        channel: u8,
558    ) -> Result<InputValueCallbackConfiguration, TinkerforgeError> {
559        let mut payload = [0; 1];
560        channel.write_to_slice(&mut payload[0..1]);
561
562        #[allow(unused_variables)]
563        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetInputValueCallbackConfiguration), &payload).await?;
564        Ok(InputValueCallbackConfiguration::from_le_byte_slice(result.body()))
565    }
566
567    /// The period is the period with which the [`get_all_input_value_callback_receiver`]
568    /// receiver is triggered periodically. A value of 0 turns the receiver off.
569    ///
570    /// If the `value has to change`-parameter is set to true, the receiver is only
571    /// triggered after the value has changed. If the value didn't change within the
572    /// period, the receiver is triggered immediately on change.
573    ///
574    /// If it is set to false, the receiver is continuously triggered with the period,
575    /// independent of the value.
576    pub async fn set_all_input_value_callback_configuration(
577        &mut self,
578        period: u32,
579        value_has_to_change: bool,
580    ) -> Result<(), TinkerforgeError> {
581        let mut payload = [0; 5];
582        period.write_to_slice(&mut payload[0..4]);
583        value_has_to_change.write_to_slice(&mut payload[4..5]);
584
585        #[allow(unused_variables)]
586        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetAllInputValueCallbackConfiguration), &payload).await?;
587        Ok(())
588    }
589
590    /// Returns the receiver configuration as set by
591    /// [`set_all_input_value_callback_configuration`].
592    pub async fn get_all_input_value_callback_configuration(&mut self) -> Result<AllInputValueCallbackConfiguration, TinkerforgeError> {
593        let payload = [0; 0];
594
595        #[allow(unused_variables)]
596        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetAllInputValueCallbackConfiguration), &payload).await?;
597        Ok(AllInputValueCallbackConfiguration::from_le_byte_slice(result.body()))
598    }
599
600    /// The first parameter is the desired state of the channel (*true* means output *high*
601    /// and *false* means output *low*). The second parameter indicates the time that
602    /// the channel should hold the state.
603    ///
604    /// If this function is called with the parameters (true, 1500):
605    /// The channel will turn on and in 1.5s it will turn off again.
606    ///
607    /// A PWM for the selected channel will be aborted if this function is called.
608    ///
609    /// A monoflop can be used as a failsafe mechanism. For example: Lets assume you
610    /// have a RS485 bus and a IO-4 Bricklet 2.0 is connected to one of the slave
611    /// stacks. You can now call this function every second, with a time parameter
612    /// of two seconds. The channel will be *high* all the time. If now the RS485
613    /// connection is lost, the channel will turn *low* in at most two seconds.
614    pub async fn set_monoflop(&mut self, channel: u8, value: bool, time: u32) -> Result<(), TinkerforgeError> {
615        let mut payload = [0; 6];
616        channel.write_to_slice(&mut payload[0..1]);
617        value.write_to_slice(&mut payload[1..2]);
618        time.write_to_slice(&mut payload[2..6]);
619
620        #[allow(unused_variables)]
621        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetMonoflop), &payload).await?;
622        Ok(())
623    }
624
625    /// Returns (for the given channel) the current value and the time as set by
626    /// [`set_monoflop`] as well as the remaining time until the value flips.
627    ///
628    /// If the timer is not running currently, the remaining time will be returned
629    /// as 0.
630    pub async fn get_monoflop(&mut self, channel: u8) -> Result<Monoflop, TinkerforgeError> {
631        let mut payload = [0; 1];
632        channel.write_to_slice(&mut payload[0..1]);
633
634        #[allow(unused_variables)]
635        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetMonoflop), &payload).await?;
636        Ok(Monoflop::from_le_byte_slice(result.body()))
637    }
638
639    /// Returns the current value of the edge counter for the selected channel. You can
640    /// configure the edges that are counted with [`set_edge_count_configuration`].
641    ///
642    /// If you set the reset counter to *true*, the count is set back to 0
643    /// directly after it is read.
644    ///
645    /// # Note
646    ///  Calling this function is only allowed for channels configured as input.
647    pub async fn get_edge_count(&mut self, channel: u8, reset_counter: bool) -> Result<u32, TinkerforgeError> {
648        let mut payload = [0; 2];
649        channel.write_to_slice(&mut payload[0..1]);
650        reset_counter.write_to_slice(&mut payload[1..2]);
651
652        #[allow(unused_variables)]
653        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetEdgeCount), &payload).await?;
654        Ok(u32::from_le_byte_slice(result.body()))
655    }
656
657    /// Configures the edge counter for a specific channel.
658    ///
659    /// The edge type parameter configures if rising edges, falling edges or
660    /// both are counted if the channel is configured for input. Possible edge types are:
661    ///
662    /// * 0 = rising
663    /// * 1 = falling
664    /// * 2 = both
665    ///
666    /// Configuring an edge counter resets its value to 0.
667    ///
668    /// If you don't know what any of this means, just leave it at default. The
669    /// default configuration is very likely OK for you.
670    ///
671    /// # Note
672    ///  Calling this function is only allowed for channels configured as input.
673    ///
674    /// Associated constants:
675    /// * IO4_V2_BRICKLET_EDGE_TYPE_RISING
676    ///	* IO4_V2_BRICKLET_EDGE_TYPE_FALLING
677    ///	* IO4_V2_BRICKLET_EDGE_TYPE_BOTH
678    pub async fn set_edge_count_configuration(&mut self, channel: u8, edge_type: u8, debounce: u8) -> Result<(), TinkerforgeError> {
679        let mut payload = [0; 3];
680        channel.write_to_slice(&mut payload[0..1]);
681        edge_type.write_to_slice(&mut payload[1..2]);
682        debounce.write_to_slice(&mut payload[2..3]);
683
684        #[allow(unused_variables)]
685        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetEdgeCountConfiguration), &payload).await?;
686        Ok(())
687    }
688
689    /// Returns the edge type and debounce time for the selected channel as set by
690    /// [`set_edge_count_configuration`].
691    ///
692    /// # Note
693    ///  Calling this function is only allowed for channels configured as input.
694    ///
695    /// Associated constants:
696    /// * IO4_V2_BRICKLET_EDGE_TYPE_RISING
697    ///	* IO4_V2_BRICKLET_EDGE_TYPE_FALLING
698    ///	* IO4_V2_BRICKLET_EDGE_TYPE_BOTH
699    pub async fn get_edge_count_configuration(&mut self, channel: u8) -> Result<EdgeCountConfiguration, TinkerforgeError> {
700        let mut payload = [0; 1];
701        channel.write_to_slice(&mut payload[0..1]);
702
703        #[allow(unused_variables)]
704        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetEdgeCountConfiguration), &payload).await?;
705        Ok(EdgeCountConfiguration::from_le_byte_slice(result.body()))
706    }
707
708    /// Activates a PWM for the given channel.
709    ///
710    /// You need to set the channel to output before you call this function, otherwise it will
711    /// report an invalid parameter error. To turn the PWM off again, you can set the frequency to 0 or any other
712    /// function that changes a value of the channel (e.g. [`set_selected_value`]).
713    ///
714    /// A running monoflop timer for the given channel will be aborted if this function
715    /// is called.
716    pub async fn set_pwm_configuration(&mut self, channel: u8, frequency: u32, duty_cycle: u16) -> Result<(), TinkerforgeError> {
717        let mut payload = [0; 7];
718        channel.write_to_slice(&mut payload[0..1]);
719        frequency.write_to_slice(&mut payload[1..5]);
720        duty_cycle.write_to_slice(&mut payload[5..7]);
721
722        #[allow(unused_variables)]
723        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetPwmConfiguration), &payload).await?;
724        Ok(())
725    }
726
727    /// Returns the PWM configuration as set by [`set_pwm_configuration`].
728    pub async fn get_pwm_configuration(&mut self, channel: u8) -> Result<PwmConfiguration, TinkerforgeError> {
729        let mut payload = [0; 1];
730        channel.write_to_slice(&mut payload[0..1]);
731
732        #[allow(unused_variables)]
733        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetPwmConfiguration), &payload).await?;
734        Ok(PwmConfiguration::from_le_byte_slice(result.body()))
735    }
736
737    /// Returns the error count for the communication between Brick and Bricklet.
738    ///
739    /// The errors are divided into
740    ///
741    /// * ACK checksum errors,
742    /// * message checksum errors,
743    /// * framing errors and
744    /// * overflow errors.
745    ///
746    /// The errors counts are for errors that occur on the Bricklet side. All
747    /// Bricks have a similar function that returns the errors on the Brick side.
748    pub async fn get_spitfp_error_count(&mut self) -> Result<SpitfpErrorCount, TinkerforgeError> {
749        let payload = [0; 0];
750
751        #[allow(unused_variables)]
752        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetSpitfpErrorCount), &payload).await?;
753        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
754    }
755
756    /// Sets the bootloader mode and returns the status after the requested
757    /// mode change was instigated.
758    ///
759    /// You can change from bootloader mode to firmware mode and vice versa. A change
760    /// from bootloader mode to firmware mode will only take place if the entry function,
761    /// device identifier and CRC are present and correct.
762    ///
763    /// This function is used by Brick Viewer during flashing. It should not be
764    /// necessary to call it in a normal user program.
765    ///
766    /// Associated constants:
767    /// * IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
768    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
769    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
770    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
771    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
772    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_OK
773    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
774    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
775    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
776    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
777    ///	* IO4_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
778    pub async fn set_bootloader_mode(&mut self, mode: u8) -> Result<u8, TinkerforgeError> {
779        let mut payload = [0; 1];
780        mode.write_to_slice(&mut payload[0..1]);
781
782        #[allow(unused_variables)]
783        let result = self.device.get(u8::from(Io4V2BrickletFunction::SetBootloaderMode), &payload).await?;
784        Ok(u8::from_le_byte_slice(result.body()))
785    }
786
787    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
788    ///
789    /// Associated constants:
790    /// * IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
791    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
792    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
793    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
794    ///	* IO4_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
795    pub async fn get_bootloader_mode(&mut self) -> Result<u8, TinkerforgeError> {
796        let payload = [0; 0];
797
798        #[allow(unused_variables)]
799        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetBootloaderMode), &payload).await?;
800        Ok(u8::from_le_byte_slice(result.body()))
801    }
802
803    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
804    /// to be increased by chunks of size 64. The data is written to flash
805    /// every 4 chunks (which equals to one page of size 256).
806    ///
807    /// This function is used by Brick Viewer during flashing. It should not be
808    /// necessary to call it in a normal user program.
809    pub async fn set_write_firmware_pointer(&mut self, pointer: u32) -> Result<(), TinkerforgeError> {
810        let mut payload = [0; 4];
811        pointer.write_to_slice(&mut payload[0..4]);
812
813        #[allow(unused_variables)]
814        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetWriteFirmwarePointer), &payload).await?;
815        Ok(())
816    }
817
818    /// Writes 64 Bytes of firmware at the position as written by
819    /// [`set_write_firmware_pointer`] before. The firmware is written
820    /// to flash every 4 chunks.
821    ///
822    /// You can only write firmware in bootloader mode.
823    ///
824    /// This function is used by Brick Viewer during flashing. It should not be
825    /// necessary to call it in a normal user program.
826    pub async fn write_firmware(&mut self, data: &[u8; 64]) -> Result<u8, TinkerforgeError> {
827        let mut payload = [0; 64];
828        data.write_to_slice(&mut payload[0..64]);
829
830        #[allow(unused_variables)]
831        let result = self.device.get(u8::from(Io4V2BrickletFunction::WriteFirmware), &payload).await?;
832        Ok(u8::from_le_byte_slice(result.body()))
833    }
834
835    /// Sets the status LED configuration. By default the LED shows
836    /// communication traffic between Brick and Bricklet, it flickers once
837    /// for every 10 received data packets.
838    ///
839    /// You can also turn the LED permanently on/off or show a heartbeat.
840    ///
841    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
842    ///
843    /// Associated constants:
844    /// * IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF
845    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON
846    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
847    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
848    pub async fn set_status_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
849        let mut payload = [0; 1];
850        config.write_to_slice(&mut payload[0..1]);
851
852        #[allow(unused_variables)]
853        let result = self.device.set(u8::from(Io4V2BrickletFunction::SetStatusLedConfig), &payload).await?;
854        Ok(())
855    }
856
857    /// Returns the configuration as set by [`set_status_led_config`]
858    ///
859    /// Associated constants:
860    /// * IO4_V2_BRICKLET_STATUS_LED_CONFIG_OFF
861    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_ON
862    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
863    ///	* IO4_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
864    pub async fn get_status_led_config(&mut self) -> Result<u8, TinkerforgeError> {
865        let payload = [0; 0];
866
867        #[allow(unused_variables)]
868        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetStatusLedConfig), &payload).await?;
869        Ok(u8::from_le_byte_slice(result.body()))
870    }
871
872    /// Returns the temperature as measured inside the microcontroller. The
873    /// value returned is not the ambient temperature!
874    ///
875    /// The temperature is only proportional to the real temperature and it has bad
876    /// accuracy. Practically it is only useful as an indicator for
877    /// temperature changes.
878    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
879        let payload = [0; 0];
880
881        #[allow(unused_variables)]
882        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetChipTemperature), &payload).await?;
883        Ok(i16::from_le_byte_slice(result.body()))
884    }
885
886    /// Calling this function will reset the Bricklet. All configurations
887    /// will be lost.
888    ///
889    /// After a reset you have to create new device objects,
890    /// calling functions on the existing ones will result in
891    /// undefined behavior!
892    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
893        let payload = [0; 0];
894
895        #[allow(unused_variables)]
896        let result = self.device.set(u8::from(Io4V2BrickletFunction::Reset), &payload).await?;
897        Ok(())
898    }
899
900    /// Writes a new UID into flash. If you want to set a new UID
901    /// you have to decode the Base58 encoded UID string into an
902    /// integer first.
903    ///
904    /// We recommend that you use Brick Viewer to change the UID.
905    pub async fn write_uid(&mut self, uid: u32) -> Result<(), TinkerforgeError> {
906        let mut payload = [0; 4];
907        uid.write_to_slice(&mut payload[0..4]);
908
909        #[allow(unused_variables)]
910        let result = self.device.set(u8::from(Io4V2BrickletFunction::WriteUid), &payload).await?;
911        Ok(())
912    }
913
914    /// Returns the current UID as an integer. Encode as
915    /// Base58 to get the usual string version.
916    pub async fn read_uid(&mut self) -> Result<u32, TinkerforgeError> {
917        let payload = [0; 0];
918
919        #[allow(unused_variables)]
920        let result = self.device.get(u8::from(Io4V2BrickletFunction::ReadUid), &payload).await?;
921        Ok(u32::from_le_byte_slice(result.body()))
922    }
923
924    /// Returns the UID, the UID where the Bricklet is connected to,
925    /// the position, the hardware and firmware version as well as the
926    /// device identifier.
927    ///
928    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
929    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
930    /// position 'z'.
931    ///
932    /// The device identifier numbers can be found [here](device_identifier).
933    /// |device_identifier_constant|
934    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
935        let payload = [0; 0];
936
937        #[allow(unused_variables)]
938        let result = self.device.get(u8::from(Io4V2BrickletFunction::GetIdentity), &payload).await?;
939        Ok(Identity::from_le_byte_slice(result.body()))
940    }
941}