tinkerforge_async/bindings/
industrial_digital_out_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 outputs.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/IndustrialDigitalOut4_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 IndustrialDigitalOut4BrickletFunction {
24    SetValue,
25    GetValue,
26    SetMonoflop,
27    GetMonoflop,
28    SetGroup,
29    GetGroup,
30    GetAvailableForGroup,
31    SetSelectedValues,
32    GetIdentity,
33    CallbackMonoflopDone,
34}
35impl From<IndustrialDigitalOut4BrickletFunction> for u8 {
36    fn from(fun: IndustrialDigitalOut4BrickletFunction) -> Self {
37        match fun {
38            IndustrialDigitalOut4BrickletFunction::SetValue => 1,
39            IndustrialDigitalOut4BrickletFunction::GetValue => 2,
40            IndustrialDigitalOut4BrickletFunction::SetMonoflop => 3,
41            IndustrialDigitalOut4BrickletFunction::GetMonoflop => 4,
42            IndustrialDigitalOut4BrickletFunction::SetGroup => 5,
43            IndustrialDigitalOut4BrickletFunction::GetGroup => 6,
44            IndustrialDigitalOut4BrickletFunction::GetAvailableForGroup => 7,
45            IndustrialDigitalOut4BrickletFunction::SetSelectedValues => 9,
46            IndustrialDigitalOut4BrickletFunction::GetIdentity => 255,
47            IndustrialDigitalOut4BrickletFunction::CallbackMonoflopDone => 8,
48        }
49    }
50}
51
52#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
53pub struct Monoflop {
54    pub value: u16,
55    pub time: u32,
56    pub time_remaining: u32,
57}
58impl FromByteSlice for Monoflop {
59    fn bytes_expected() -> usize {
60        10
61    }
62    fn from_le_byte_slice(bytes: &[u8]) -> Monoflop {
63        Monoflop {
64            value: <u16>::from_le_byte_slice(&bytes[0..2]),
65            time: <u32>::from_le_byte_slice(&bytes[2..6]),
66            time_remaining: <u32>::from_le_byte_slice(&bytes[6..10]),
67        }
68    }
69}
70
71#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
72pub struct MonoflopDoneEvent {
73    pub selection_mask: u16,
74    pub value_mask: u16,
75}
76impl FromByteSlice for MonoflopDoneEvent {
77    fn bytes_expected() -> usize {
78        4
79    }
80    fn from_le_byte_slice(bytes: &[u8]) -> MonoflopDoneEvent {
81        MonoflopDoneEvent { selection_mask: <u16>::from_le_byte_slice(&bytes[0..2]), value_mask: <u16>::from_le_byte_slice(&bytes[2..4]) }
82    }
83}
84
85#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
86pub struct Identity {
87    pub uid: String,
88    pub connected_uid: String,
89    pub position: char,
90    pub hardware_version: [u8; 3],
91    pub firmware_version: [u8; 3],
92    pub device_identifier: u16,
93}
94impl FromByteSlice for Identity {
95    fn bytes_expected() -> usize {
96        25
97    }
98    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
99        Identity {
100            uid: <String>::from_le_byte_slice(&bytes[0..8]),
101            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
102            position: <char>::from_le_byte_slice(&bytes[16..17]),
103            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
104            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
105            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
106        }
107    }
108}
109
110/// 4 galvanically isolated digital outputs
111#[derive(Clone)]
112pub struct IndustrialDigitalOut4Bricklet {
113    device: Device,
114}
115impl IndustrialDigitalOut4Bricklet {
116    pub const DEVICE_IDENTIFIER: u16 = 224;
117    pub const DEVICE_DISPLAY_NAME: &'static str = "Industrial Digital Out 4 Bricklet";
118    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
119    pub fn new(uid: Uid, connection: AsyncIpConnection) -> IndustrialDigitalOut4Bricklet {
120        let mut result = IndustrialDigitalOut4Bricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
121        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::SetValue) as usize] = ResponseExpectedFlag::False;
122        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::GetValue) as usize] =
123            ResponseExpectedFlag::AlwaysTrue;
124        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::SetMonoflop) as usize] =
125            ResponseExpectedFlag::False;
126        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::GetMonoflop) as usize] =
127            ResponseExpectedFlag::AlwaysTrue;
128        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::SetGroup) as usize] = ResponseExpectedFlag::False;
129        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::GetGroup) as usize] =
130            ResponseExpectedFlag::AlwaysTrue;
131        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::GetAvailableForGroup) as usize] =
132            ResponseExpectedFlag::AlwaysTrue;
133        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::SetSelectedValues) as usize] =
134            ResponseExpectedFlag::False;
135        result.device.response_expected[u8::from(IndustrialDigitalOut4BrickletFunction::GetIdentity) as usize] =
136            ResponseExpectedFlag::AlwaysTrue;
137        result
138    }
139
140    /// Returns the response expected flag for the function specified by the function ID parameter.
141    /// It is true if the function is expected to send a response, false otherwise.
142    ///
143    /// For getter functions this is enabled by default and cannot be disabled, because those
144    /// functions will always send a response. For callback configuration functions it is enabled
145    /// by default too, but can be disabled by [`set_response_expected`](crate::industrial_digital_out_4_bricklet::IndustrialDigitalOut4Bricklet::set_response_expected).
146    /// For setter functions it is disabled by default and can be enabled.
147    ///
148    /// Enabling the response expected flag for a setter function allows to detect timeouts
149    /// and other error conditions calls of this setter as well. The device will then send a response
150    /// for this purpose. If this flag is disabled for a setter function then no response is sent
151    /// and errors are silently ignored, because they cannot be detected.
152    ///
153    /// See [`set_response_expected`](crate::industrial_digital_out_4_bricklet::IndustrialDigitalOut4Bricklet::set_response_expected) for the list of function ID constants available for this function.
154    pub fn get_response_expected(&mut self, fun: IndustrialDigitalOut4BrickletFunction) -> Result<bool, GetResponseExpectedError> {
155        self.device.get_response_expected(u8::from(fun))
156    }
157
158    /// Changes the response expected flag of the function specified by the function ID parameter.
159    /// This flag can only be changed for setter (default value: false) and callback configuration
160    /// functions (default value: true). For getter functions it is always enabled.
161    ///
162    /// Enabling the response expected flag for a setter function allows to detect timeouts and
163    /// other error conditions calls of this setter as well. The device will then send a response
164    /// for this purpose. If this flag is disabled for a setter function then no response is sent
165    /// and errors are silently ignored, because they cannot be detected.
166    pub fn set_response_expected(
167        &mut self,
168        fun: IndustrialDigitalOut4BrickletFunction,
169        response_expected: bool,
170    ) -> Result<(), SetResponseExpectedError> {
171        self.device.set_response_expected(u8::from(fun), response_expected)
172    }
173
174    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
175    pub fn set_response_expected_all(&mut self, response_expected: bool) {
176        self.device.set_response_expected_all(response_expected)
177    }
178
179    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
180    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
181    pub fn get_api_version(&self) -> [u8; 3] {
182        self.device.api_version
183    }
184
185    /// This receiver is triggered whenever a monoflop timer reaches 0. The
186    /// parameters contain the involved pins and the current value of the pins
187    /// (the value after the monoflop).
188    pub async fn get_monoflop_done_callback_receiver(&mut self) -> impl Stream<Item = MonoflopDoneEvent> {
189        self.device
190            .get_callback_receiver(u8::from(IndustrialDigitalOut4BrickletFunction::CallbackMonoflopDone))
191            .await
192            .map(|p| MonoflopDoneEvent::from_le_byte_slice(p.body()))
193    }
194
195    /// Sets the output value with a bitmask (16bit). A 1 in the bitmask means high
196    /// and a 0 in the bitmask means low.
197    ///
198    /// For example: The value 3 or 0b0011 will turn pins 0-1 high and the other pins
199    /// low.
200    ///
201    /// If no groups are used (see [`set_group`]), the pins correspond to the
202    /// markings on the Industrial Digital Out 4 Bricklet.
203    ///
204    /// If groups are used, the pins correspond to the element in the group.
205    /// Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
206    /// pins 8-11 and element 4 pins 12-15.
207    ///
208    /// All running monoflop timers will be aborted if this function is called.
209    pub async fn set_value(&mut self, value_mask: u16) -> Result<(), TinkerforgeError> {
210        let mut payload = [0; 2];
211        value_mask.write_to_slice(&mut payload[0..2]);
212
213        #[allow(unused_variables)]
214        let result = self.device.set(u8::from(IndustrialDigitalOut4BrickletFunction::SetValue), &payload).await?;
215        Ok(())
216    }
217
218    /// Returns the bitmask as set by [`set_value`].
219    pub async fn get_value(&mut self) -> Result<u16, TinkerforgeError> {
220        let payload = [0; 0];
221
222        #[allow(unused_variables)]
223        let result = self.device.get(u8::from(IndustrialDigitalOut4BrickletFunction::GetValue), &payload).await?;
224        Ok(u16::from_le_byte_slice(result.body()))
225    }
226
227    /// Configures a monoflop of the pins specified by the first parameter
228    /// bitmask.
229    ///
230    /// The second parameter is a bitmask with the desired value of the specified
231    /// pins. A 1 in the bitmask means high and a 0 in the bitmask means low.
232    ///
233    /// The third parameter indicates the time that the pins should hold
234    /// the value.
235    ///
236    /// If this function is called with the parameters (9, 1, 1500) or
237    /// (0b1001, 0b0001, 1500): Pin 0 will get high and pin 3 will get low. In 1.5s
238    /// pin 0 will get low and pin 3 will get high again.
239    ///
240    /// A monoflop can be used as a fail-safe mechanism. For example: Lets assume you
241    /// have a RS485 bus and a Digital Out 4 Bricklet connected to one of the slave
242    /// stacks. You can now call this function every second, with a time parameter
243    /// of two seconds and pin 0 high. Pin 0 will be high all the time. If now
244    /// the RS485 connection is lost, then pin 0 will turn low in at most two seconds.
245    pub async fn set_monoflop(&mut self, selection_mask: u16, value_mask: u16, time: u32) -> Result<(), TinkerforgeError> {
246        let mut payload = [0; 8];
247        selection_mask.write_to_slice(&mut payload[0..2]);
248        value_mask.write_to_slice(&mut payload[2..4]);
249        time.write_to_slice(&mut payload[4..8]);
250
251        #[allow(unused_variables)]
252        let result = self.device.set(u8::from(IndustrialDigitalOut4BrickletFunction::SetMonoflop), &payload).await?;
253        Ok(())
254    }
255
256    /// Returns (for the given pin) the current value and the time as set by
257    /// [`set_monoflop`] as well as the remaining time until the value flips.
258    ///
259    /// If the timer is not running currently, the remaining time will be returned
260    /// as 0.
261    pub async fn get_monoflop(&mut self, pin: u8) -> Result<Monoflop, TinkerforgeError> {
262        let mut payload = [0; 1];
263        pin.write_to_slice(&mut payload[0..1]);
264
265        #[allow(unused_variables)]
266        let result = self.device.get(u8::from(IndustrialDigitalOut4BrickletFunction::GetMonoflop), &payload).await?;
267        Ok(Monoflop::from_le_byte_slice(result.body()))
268    }
269
270    /// Sets a group of Digital Out 4 Bricklets that should work together. You can
271    /// find Bricklets that can be grouped together with [`get_available_for_group`].
272    ///
273    /// The group consists of 4 elements. Element 1 in the group will get pins 0-3,
274    /// element 2 pins 4-7, element 3 pins 8-11 and element 4 pins 12-15.
275    ///
276    /// Each element can either be one of the ports ('a' to 'd') or 'n' if it should
277    /// not be used.
278    ///
279    /// For example: If you have two Digital Out 4 Bricklets connected to port A and
280    /// port B respectively, you could call with ``['a', 'b', 'n', 'n']``.
281    ///
282    /// Now the pins on the Digital Out 4 on port A are assigned to 0-3 and the
283    /// pins on the Digital Out 4 on port B are assigned to 4-7. It is now possible
284    /// to call [`set_value`] and control two Bricklets at the same time.
285    pub async fn set_group(&mut self, group: &[char; 4]) -> Result<(), TinkerforgeError> {
286        let mut payload = [0; 4];
287        group.write_to_slice(&mut payload[0..4]);
288
289        #[allow(unused_variables)]
290        let result = self.device.set(u8::from(IndustrialDigitalOut4BrickletFunction::SetGroup), &payload).await?;
291        Ok(())
292    }
293
294    /// Returns the group as set by [`set_group`]
295    pub async fn get_group(&mut self) -> Result<Box<[char; 4]>, TinkerforgeError> {
296        let payload = [0; 0];
297
298        #[allow(unused_variables)]
299        let result = self.device.get(u8::from(IndustrialDigitalOut4BrickletFunction::GetGroup), &payload).await?;
300        Ok(Box::<[char; 4]>::from_le_byte_slice(result.body()))
301    }
302
303    /// Returns a bitmask of ports that are available for grouping. For example the
304    /// value 5 or 0b0101 means: Port A and port C are connected to Bricklets that
305    /// can be grouped together.
306    pub async fn get_available_for_group(&mut self) -> Result<u8, TinkerforgeError> {
307        let payload = [0; 0];
308
309        #[allow(unused_variables)]
310        let result = self.device.get(u8::from(IndustrialDigitalOut4BrickletFunction::GetAvailableForGroup), &payload).await?;
311        Ok(u8::from_le_byte_slice(result.body()))
312    }
313
314    /// Sets the output value with a bitmask, according to the selection mask.
315    /// The bitmask is 16 bit long, *true* refers to high and *false* refers to
316    /// low.
317    ///
318    /// For example: The values (3, 1) or (0b0011, 0b0001) will turn pin 0 high, pin 1
319    /// low the other pins remain untouched.
320    ///
321    /// If no groups are used (see [`set_group`]), the pins correspond to the
322    /// markings on the Industrial Digital Out 4 Bricklet.
323    ///
324    /// If groups are used, the pins correspond to the element in the group.
325    /// Element 1 in the group will get pins 0-3, element 2 pins 4-7, element 3
326    /// pins 8-11 and element 4 pins 12-15.
327    ///
328    /// Running monoflop timers for the selected pins will be aborted if this function
329    /// is called.
330    pub async fn set_selected_values(&mut self, selection_mask: u16, value_mask: u16) -> Result<(), TinkerforgeError> {
331        let mut payload = [0; 4];
332        selection_mask.write_to_slice(&mut payload[0..2]);
333        value_mask.write_to_slice(&mut payload[2..4]);
334
335        #[allow(unused_variables)]
336        let result = self.device.set(u8::from(IndustrialDigitalOut4BrickletFunction::SetSelectedValues), &payload).await?;
337        Ok(())
338    }
339
340    /// Returns the UID, the UID where the Bricklet is connected to,
341    /// the position, the hardware and firmware version as well as the
342    /// device identifier.
343    ///
344    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
345    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
346    /// position 'z'.
347    ///
348    /// The device identifier numbers can be found [here](device_identifier).
349    /// |device_identifier_constant|
350    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
351        let payload = [0; 0];
352
353        #[allow(unused_variables)]
354        let result = self.device.get(u8::from(IndustrialDigitalOut4BrickletFunction::GetIdentity), &payload).await?;
355        Ok(Identity::from_le_byte_slice(result.body()))
356    }
357}