tinkerforge_async/bindings/
industrial_digital_in_4_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 galvanically isolated digital inputs.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/IndustrialDigitalIn4_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 IndustrialDigitalIn4BrickletFunction {
24    GetValue,
25    SetGroup,
26    GetGroup,
27    GetAvailableForGroup,
28    SetDebouncePeriod,
29    GetDebouncePeriod,
30    SetInterrupt,
31    GetInterrupt,
32    GetEdgeCount,
33    SetEdgeCountConfig,
34    GetEdgeCountConfig,
35    GetIdentity,
36    CallbackInterrupt,
37}
38impl From<IndustrialDigitalIn4BrickletFunction> for u8 {
39    fn from(fun: IndustrialDigitalIn4BrickletFunction) -> Self {
40        match fun {
41            IndustrialDigitalIn4BrickletFunction::GetValue => 1,
42            IndustrialDigitalIn4BrickletFunction::SetGroup => 2,
43            IndustrialDigitalIn4BrickletFunction::GetGroup => 3,
44            IndustrialDigitalIn4BrickletFunction::GetAvailableForGroup => 4,
45            IndustrialDigitalIn4BrickletFunction::SetDebouncePeriod => 5,
46            IndustrialDigitalIn4BrickletFunction::GetDebouncePeriod => 6,
47            IndustrialDigitalIn4BrickletFunction::SetInterrupt => 7,
48            IndustrialDigitalIn4BrickletFunction::GetInterrupt => 8,
49            IndustrialDigitalIn4BrickletFunction::GetEdgeCount => 10,
50            IndustrialDigitalIn4BrickletFunction::SetEdgeCountConfig => 11,
51            IndustrialDigitalIn4BrickletFunction::GetEdgeCountConfig => 12,
52            IndustrialDigitalIn4BrickletFunction::GetIdentity => 255,
53            IndustrialDigitalIn4BrickletFunction::CallbackInterrupt => 9,
54        }
55    }
56}
57pub const INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_RISING: u8 = 0;
58pub const INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_FALLING: u8 = 1;
59pub const INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_BOTH: u8 = 2;
60
61#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
62pub struct InterruptEvent {
63    pub interrupt_mask: u16,
64    pub value_mask: u16,
65}
66impl FromByteSlice for InterruptEvent {
67    fn bytes_expected() -> usize {
68        4
69    }
70    fn from_le_byte_slice(bytes: &[u8]) -> InterruptEvent {
71        InterruptEvent { interrupt_mask: <u16>::from_le_byte_slice(&bytes[0..2]), value_mask: <u16>::from_le_byte_slice(&bytes[2..4]) }
72    }
73}
74
75#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
76pub struct EdgeCountConfig {
77    pub edge_type: u8,
78    pub debounce: u8,
79}
80impl FromByteSlice for EdgeCountConfig {
81    fn bytes_expected() -> usize {
82        2
83    }
84    fn from_le_byte_slice(bytes: &[u8]) -> EdgeCountConfig {
85        EdgeCountConfig { edge_type: <u8>::from_le_byte_slice(&bytes[0..1]), debounce: <u8>::from_le_byte_slice(&bytes[1..2]) }
86    }
87}
88
89#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
90pub struct Identity {
91    pub uid: String,
92    pub connected_uid: String,
93    pub position: char,
94    pub hardware_version: [u8; 3],
95    pub firmware_version: [u8; 3],
96    pub device_identifier: u16,
97}
98impl FromByteSlice for Identity {
99    fn bytes_expected() -> usize {
100        25
101    }
102    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
103        Identity {
104            uid: <String>::from_le_byte_slice(&bytes[0..8]),
105            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
106            position: <char>::from_le_byte_slice(&bytes[16..17]),
107            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
108            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
109            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
110        }
111    }
112}
113
114/// 4 galvanically isolated digital inputs
115#[derive(Clone)]
116pub struct IndustrialDigitalIn4Bricklet {
117    device: Device,
118}
119impl IndustrialDigitalIn4Bricklet {
120    pub const DEVICE_IDENTIFIER: u16 = 223;
121    pub const DEVICE_DISPLAY_NAME: &'static str = "Industrial Digital In 4 Bricklet";
122    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
123    pub fn new(uid: Uid, connection: AsyncIpConnection) -> IndustrialDigitalIn4Bricklet {
124        let mut result = IndustrialDigitalIn4Bricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
125        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetValue) as usize] =
126            ResponseExpectedFlag::AlwaysTrue;
127        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::SetGroup) as usize] = ResponseExpectedFlag::False;
128        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetGroup) as usize] =
129            ResponseExpectedFlag::AlwaysTrue;
130        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetAvailableForGroup) as usize] =
131            ResponseExpectedFlag::AlwaysTrue;
132        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::SetDebouncePeriod) as usize] =
133            ResponseExpectedFlag::True;
134        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetDebouncePeriod) as usize] =
135            ResponseExpectedFlag::AlwaysTrue;
136        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::SetInterrupt) as usize] = ResponseExpectedFlag::True;
137        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetInterrupt) as usize] =
138            ResponseExpectedFlag::AlwaysTrue;
139        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetEdgeCount) as usize] =
140            ResponseExpectedFlag::AlwaysTrue;
141        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::SetEdgeCountConfig) as usize] =
142            ResponseExpectedFlag::False;
143        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetEdgeCountConfig) as usize] =
144            ResponseExpectedFlag::AlwaysTrue;
145        result.device.response_expected[u8::from(IndustrialDigitalIn4BrickletFunction::GetIdentity) as usize] =
146            ResponseExpectedFlag::AlwaysTrue;
147        result
148    }
149
150    /// Returns the response expected flag for the function specified by the function ID parameter.
151    /// It is true if the function is expected to send a response, false otherwise.
152    ///
153    /// For getter functions this is enabled by default and cannot be disabled, because those
154    /// functions will always send a response. For callback configuration functions it is enabled
155    /// by default too, but can be disabled by [`set_response_expected`](crate::industrial_digital_in_4_bricklet::IndustrialDigitalIn4Bricklet::set_response_expected).
156    /// For setter functions it is disabled by default and can be enabled.
157    ///
158    /// Enabling the response expected flag for a setter function allows to detect timeouts
159    /// and other error conditions calls of this setter as well. The device will then send a response
160    /// for this purpose. If this flag is disabled for a setter function then no response is sent
161    /// and errors are silently ignored, because they cannot be detected.
162    ///
163    /// See [`set_response_expected`](crate::industrial_digital_in_4_bricklet::IndustrialDigitalIn4Bricklet::set_response_expected) for the list of function ID constants available for this function.
164    pub fn get_response_expected(&mut self, fun: IndustrialDigitalIn4BrickletFunction) -> Result<bool, GetResponseExpectedError> {
165        self.device.get_response_expected(u8::from(fun))
166    }
167
168    /// Changes the response expected flag of the function specified by the function ID parameter.
169    /// This flag can only be changed for setter (default value: false) and callback configuration
170    /// functions (default value: true). For getter functions it is always enabled.
171    ///
172    /// Enabling the response expected flag for a setter function allows to detect timeouts and
173    /// other error conditions calls of this setter as well. The device will then send a response
174    /// for this purpose. If this flag is disabled for a setter function then no response is sent
175    /// and errors are silently ignored, because they cannot be detected.
176    pub fn set_response_expected(
177        &mut self,
178        fun: IndustrialDigitalIn4BrickletFunction,
179        response_expected: bool,
180    ) -> Result<(), SetResponseExpectedError> {
181        self.device.set_response_expected(u8::from(fun), response_expected)
182    }
183
184    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
185    pub fn set_response_expected_all(&mut self, response_expected: bool) {
186        self.device.set_response_expected_all(response_expected)
187    }
188
189    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
190    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
191    pub fn get_api_version(&self) -> [u8; 3] {
192        self.device.api_version
193    }
194
195    /// This receiver is triggered whenever a change of the voltage level is detected
196    /// on pins where the interrupt was activated with [`set_interrupt`].
197    ///
198    /// The values are a bitmask that specifies which interrupts occurred
199    /// and the current value bitmask.
200    ///
201    /// For example:
202    ///
203    /// * (1, 1) or (0b0001, 0b0001) means that an interrupt on pin 0 occurred and
204    ///   currently pin 0 is high and pins 1-3 are low.
205    /// * (9, 14) or (0b1001, 0b1110) means that interrupts on pins 0 and 3
206    ///   occurred and currently pin 0 is low and pins 1-3 are high.
207    ///
208    /// The interrupts use the grouping as set by [`set_group`].
209    ///
210    /// [`set_group`]: #method.set_group
211    /// [`set_interrupt`]: #method.set_interrupt
212    pub async fn get_interrupt_callback_receiver(&mut self) -> impl Stream<Item = InterruptEvent> {
213        self.device
214            .get_callback_receiver(u8::from(IndustrialDigitalIn4BrickletFunction::CallbackInterrupt))
215            .await
216            .map(|p| InterruptEvent::from_le_byte_slice(p.body()))
217    }
218
219    /// Returns the input value with a bitmask. The bitmask is 16bit long, *true*
220    /// refers to high and *false* refers to low.
221    ///
222    /// For example: The value 3 or 0b0011 means that pins 0-1 are high and the other
223    /// pins are low.
224    ///
225    /// If no groups are used (see [`set_group`]), the pins correspond to the
226    /// markings on the IndustrialDigital In 4 Bricklet.
227    ///
228    /// If groups are used, the pins correspond to the element in the group.
229    /// Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
230    /// pins 8-11 and element 4 pins 12-15.
231    pub async fn get_value(&mut self) -> Result<u16, TinkerforgeError> {
232        let payload = [0; 0];
233
234        #[allow(unused_variables)]
235        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetValue), &payload).await?;
236        Ok(u16::from_le_byte_slice(result.body()))
237    }
238
239    /// Sets a group of Digital In 4 Bricklets that should work together. You can
240    /// find Bricklets that can be grouped together with [`get_available_for_group`].
241    ///
242    /// The group consists of 4 elements. Element 1 in the group will get pins 0-3,
243    /// element 2 pins 4-7, element 3 pins 8-11 and element 4 pins 12-15.
244    ///
245    /// Each element can either be one of the ports ('a' to 'd') or 'n' if it should
246    /// not be used.
247    ///
248    /// For example: If you have two Digital In 4 Bricklets connected to port A and
249    /// port B respectively, you could call with ``['a', 'b', 'n', 'n']``.
250    ///
251    /// Now the pins on the Digital In 4 on port A are assigned to 0-3 and the
252    /// pins on the Digital In 4 on port B are assigned to 4-7. It is now possible
253    /// to call [`get_value`] and read out two Bricklets at the same time.
254    ///
255    /// Changing the group configuration resets all edge counter configurations
256    /// and values.
257    pub async fn set_group(&mut self, group: &[char; 4]) -> Result<(), TinkerforgeError> {
258        let mut payload = [0; 4];
259        group.write_to_slice(&mut payload[0..4]);
260
261        #[allow(unused_variables)]
262        let result = self.device.set(u8::from(IndustrialDigitalIn4BrickletFunction::SetGroup), &payload).await?;
263        Ok(())
264    }
265
266    /// Returns the group as set by [`set_group`]
267    pub async fn get_group(&mut self) -> Result<Box<[char; 4]>, TinkerforgeError> {
268        let payload = [0; 0];
269
270        #[allow(unused_variables)]
271        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetGroup), &payload).await?;
272        Ok(Box::<[char; 4]>::from_le_byte_slice(result.body()))
273    }
274
275    /// Returns a bitmask of ports that are available for grouping. For example the
276    /// value 5 or 0b0101 means: Port A and port C are connected to Bricklets that
277    /// can be grouped together.
278    pub async fn get_available_for_group(&mut self) -> Result<u8, TinkerforgeError> {
279        let payload = [0; 0];
280
281        #[allow(unused_variables)]
282        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetAvailableForGroup), &payload).await?;
283        Ok(u8::from_le_byte_slice(result.body()))
284    }
285
286    /// Sets the debounce period of the [`get_interrupt_callback_receiver`] receiver.
287    ///
288    /// For example: If you set this value to 100, you will get the interrupt
289    /// maximal every 100ms. This is necessary if something that bounces is
290    /// connected to the Digital In 4 Bricklet, such as a button.
291    pub async fn set_debounce_period(&mut self, debounce: u32) -> Result<(), TinkerforgeError> {
292        let mut payload = [0; 4];
293        debounce.write_to_slice(&mut payload[0..4]);
294
295        #[allow(unused_variables)]
296        let result = self.device.set(u8::from(IndustrialDigitalIn4BrickletFunction::SetDebouncePeriod), &payload).await?;
297        Ok(())
298    }
299
300    /// Returns the debounce period as set by [`set_debounce_period`].
301    pub async fn get_debounce_period(&mut self) -> Result<u32, TinkerforgeError> {
302        let payload = [0; 0];
303
304        #[allow(unused_variables)]
305        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetDebouncePeriod), &payload).await?;
306        Ok(u32::from_le_byte_slice(result.body()))
307    }
308
309    /// Sets the pins on which an interrupt is activated with a bitmask.
310    /// Interrupts are triggered on changes of the voltage level of the pin,
311    /// i.e. changes from high to low and low to high.
312    ///
313    /// For example: An interrupt bitmask of 9 or 0b1001 will enable the interrupt for
314    /// pins 0 and 3.
315    ///
316    /// The interrupts use the grouping as set by [`set_group`].
317    ///
318    /// The interrupt is delivered with the [`get_interrupt_callback_receiver`] receiver.
319    pub async fn set_interrupt(&mut self, interrupt_mask: u16) -> Result<(), TinkerforgeError> {
320        let mut payload = [0; 2];
321        interrupt_mask.write_to_slice(&mut payload[0..2]);
322
323        #[allow(unused_variables)]
324        let result = self.device.set(u8::from(IndustrialDigitalIn4BrickletFunction::SetInterrupt), &payload).await?;
325        Ok(())
326    }
327
328    /// Returns the interrupt bitmask as set by [`set_interrupt`].
329    pub async fn get_interrupt(&mut self) -> Result<u16, TinkerforgeError> {
330        let payload = [0; 0];
331
332        #[allow(unused_variables)]
333        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetInterrupt), &payload).await?;
334        Ok(u16::from_le_byte_slice(result.body()))
335    }
336
337    /// Returns the current value of the edge counter for the selected pin. You can
338    /// configure the edges that are counted with [`set_edge_count_config`].
339    ///
340    /// If you set the reset counter to *true*, the count is set back to 0
341    /// directly after it is read.
342    ///
343    /// The edge counters use the grouping as set by [`set_group`].
344    ///
345    ///
346    /// .. versionadded:: 2.0.1$nbsp;(Plugin)
347    pub async fn get_edge_count(&mut self, pin: u8, reset_counter: bool) -> Result<u32, TinkerforgeError> {
348        let mut payload = [0; 2];
349        pin.write_to_slice(&mut payload[0..1]);
350        reset_counter.write_to_slice(&mut payload[1..2]);
351
352        #[allow(unused_variables)]
353        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetEdgeCount), &payload).await?;
354        Ok(u32::from_le_byte_slice(result.body()))
355    }
356
357    /// Configures the edge counter for the selected pins. A bitmask of 9 or 0b1001 will
358    /// enable the edge counter for pins 0 and 3.
359    ///
360    /// The edge type parameter configures if rising edges, falling edges or
361    /// both are counted if the pin is configured for input. Possible edge types are:
362    ///
363    /// * 0 = rising
364    /// * 1 = falling
365    /// * 2 = both
366    ///
367    /// Configuring an edge counter resets its value to 0.
368    ///
369    /// If you don't know what any of this means, just leave it at default. The
370    /// default configuration is very likely OK for you.
371    ///
372    /// The edge counters use the grouping as set by [`set_group`].
373    ///
374    ///
375    /// .. versionadded:: 2.0.1$nbsp;(Plugin)
376    ///
377    /// Associated constants:
378    /// * INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_RISING
379    ///	* INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_FALLING
380    ///	* INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_BOTH
381    pub async fn set_edge_count_config(&mut self, selection_mask: u16, edge_type: u8, debounce: u8) -> Result<(), TinkerforgeError> {
382        let mut payload = [0; 4];
383        selection_mask.write_to_slice(&mut payload[0..2]);
384        edge_type.write_to_slice(&mut payload[2..3]);
385        debounce.write_to_slice(&mut payload[3..4]);
386
387        #[allow(unused_variables)]
388        let result = self.device.set(u8::from(IndustrialDigitalIn4BrickletFunction::SetEdgeCountConfig), &payload).await?;
389        Ok(())
390    }
391
392    /// Returns the edge type and debounce time for the selected pin as set by
393    /// [`set_edge_count_config`].
394    ///
395    ///
396    /// .. versionadded:: 2.0.1$nbsp;(Plugin)
397    ///
398    /// Associated constants:
399    /// * INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_RISING
400    ///	* INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_FALLING
401    ///	* INDUSTRIAL_DIGITAL_IN_4_BRICKLET_EDGE_TYPE_BOTH
402    pub async fn get_edge_count_config(&mut self, pin: u8) -> Result<EdgeCountConfig, TinkerforgeError> {
403        let mut payload = [0; 1];
404        pin.write_to_slice(&mut payload[0..1]);
405
406        #[allow(unused_variables)]
407        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetEdgeCountConfig), &payload).await?;
408        Ok(EdgeCountConfig::from_le_byte_slice(result.body()))
409    }
410
411    /// Returns the UID, the UID where the Bricklet is connected to,
412    /// the position, the hardware and firmware version as well as the
413    /// device identifier.
414    ///
415    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
416    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
417    /// position 'z'.
418    ///
419    /// The device identifier numbers can be found [here](device_identifier).
420    /// |device_identifier_constant|
421    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
422        let payload = [0; 0];
423
424        #[allow(unused_variables)]
425        let result = self.device.get(u8::from(IndustrialDigitalIn4BrickletFunction::GetIdentity), &payload).await?;
426        Ok(Identity::from_le_byte_slice(result.body()))
427    }
428}