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