tinkerforge_async/bindings/
servo_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//! Drives up to 10 RC Servos.
12//!
13//! See also the documentation [here](https://www.tinkerforge.com/en/doc/Software/Bricklets/ServoV2_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 ServoV2BrickletFunction {
24    GetStatus,
25    SetEnable,
26    GetEnabled,
27    SetPosition,
28    GetPosition,
29    GetCurrentPosition,
30    GetCurrentVelocity,
31    SetMotionConfiguration,
32    GetMotionConfiguration,
33    SetPulseWidth,
34    GetPulseWidth,
35    SetDegree,
36    GetDegree,
37    SetPeriod,
38    GetPeriod,
39    GetServoCurrent,
40    SetServoCurrentConfiguration,
41    GetServoCurrentConfiguration,
42    SetInputVoltageConfiguration,
43    GetInputVoltageConfiguration,
44    GetOverallCurrent,
45    GetInputVoltage,
46    SetCurrentCalibration,
47    GetCurrentCalibration,
48    SetPositionReachedCallbackConfiguration,
49    GetPositionReachedCallbackConfiguration,
50    GetSpitfpErrorCount,
51    SetBootloaderMode,
52    GetBootloaderMode,
53    SetWriteFirmwarePointer,
54    WriteFirmware,
55    SetStatusLedConfig,
56    GetStatusLedConfig,
57    GetChipTemperature,
58    Reset,
59    WriteUid,
60    ReadUid,
61    GetIdentity,
62    CallbackPositionReached,
63}
64impl From<ServoV2BrickletFunction> for u8 {
65    fn from(fun: ServoV2BrickletFunction) -> Self {
66        match fun {
67            ServoV2BrickletFunction::GetStatus => 1,
68            ServoV2BrickletFunction::SetEnable => 2,
69            ServoV2BrickletFunction::GetEnabled => 3,
70            ServoV2BrickletFunction::SetPosition => 4,
71            ServoV2BrickletFunction::GetPosition => 5,
72            ServoV2BrickletFunction::GetCurrentPosition => 6,
73            ServoV2BrickletFunction::GetCurrentVelocity => 7,
74            ServoV2BrickletFunction::SetMotionConfiguration => 8,
75            ServoV2BrickletFunction::GetMotionConfiguration => 9,
76            ServoV2BrickletFunction::SetPulseWidth => 10,
77            ServoV2BrickletFunction::GetPulseWidth => 11,
78            ServoV2BrickletFunction::SetDegree => 12,
79            ServoV2BrickletFunction::GetDegree => 13,
80            ServoV2BrickletFunction::SetPeriod => 14,
81            ServoV2BrickletFunction::GetPeriod => 15,
82            ServoV2BrickletFunction::GetServoCurrent => 16,
83            ServoV2BrickletFunction::SetServoCurrentConfiguration => 17,
84            ServoV2BrickletFunction::GetServoCurrentConfiguration => 18,
85            ServoV2BrickletFunction::SetInputVoltageConfiguration => 19,
86            ServoV2BrickletFunction::GetInputVoltageConfiguration => 20,
87            ServoV2BrickletFunction::GetOverallCurrent => 21,
88            ServoV2BrickletFunction::GetInputVoltage => 22,
89            ServoV2BrickletFunction::SetCurrentCalibration => 23,
90            ServoV2BrickletFunction::GetCurrentCalibration => 24,
91            ServoV2BrickletFunction::SetPositionReachedCallbackConfiguration => 25,
92            ServoV2BrickletFunction::GetPositionReachedCallbackConfiguration => 26,
93            ServoV2BrickletFunction::GetSpitfpErrorCount => 234,
94            ServoV2BrickletFunction::SetBootloaderMode => 235,
95            ServoV2BrickletFunction::GetBootloaderMode => 236,
96            ServoV2BrickletFunction::SetWriteFirmwarePointer => 237,
97            ServoV2BrickletFunction::WriteFirmware => 238,
98            ServoV2BrickletFunction::SetStatusLedConfig => 239,
99            ServoV2BrickletFunction::GetStatusLedConfig => 240,
100            ServoV2BrickletFunction::GetChipTemperature => 242,
101            ServoV2BrickletFunction::Reset => 243,
102            ServoV2BrickletFunction::WriteUid => 248,
103            ServoV2BrickletFunction::ReadUid => 249,
104            ServoV2BrickletFunction::GetIdentity => 255,
105            ServoV2BrickletFunction::CallbackPositionReached => 27,
106        }
107    }
108}
109pub const SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER: u8 = 0;
110pub const SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE: u8 = 1;
111pub const SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT: u8 = 2;
112pub const SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT: u8 = 3;
113pub const SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT: u8 = 4;
114pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_OK: u8 = 0;
115pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE: u8 = 1;
116pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE: u8 = 2;
117pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT: u8 = 3;
118pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT: u8 = 4;
119pub const SERVO_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH: u8 = 5;
120pub const SERVO_V2_BRICKLET_STATUS_LED_CONFIG_OFF: u8 = 0;
121pub const SERVO_V2_BRICKLET_STATUS_LED_CONFIG_ON: u8 = 1;
122pub const SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT: u8 = 2;
123pub const SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS: u8 = 3;
124
125#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
126pub struct Status {
127    pub enabled: [bool; 10],
128    pub current_position: [i16; 10],
129    pub current_velocity: [i16; 10],
130    pub current: [u16; 10],
131    pub input_voltage: u16,
132}
133impl FromByteSlice for Status {
134    fn bytes_expected() -> usize {
135        64
136    }
137    fn from_le_byte_slice(bytes: &[u8]) -> Status {
138        Status {
139            enabled: <[bool; 10]>::from_le_byte_slice(&bytes[0..2]),
140            current_position: <[i16; 10]>::from_le_byte_slice(&bytes[2..22]),
141            current_velocity: <[i16; 10]>::from_le_byte_slice(&bytes[22..42]),
142            current: <[u16; 10]>::from_le_byte_slice(&bytes[42..62]),
143            input_voltage: <u16>::from_le_byte_slice(&bytes[62..64]),
144        }
145    }
146}
147
148#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
149pub struct MotionConfiguration {
150    pub velocity: u32,
151    pub acceleration: u32,
152    pub deceleration: u32,
153}
154impl FromByteSlice for MotionConfiguration {
155    fn bytes_expected() -> usize {
156        12
157    }
158    fn from_le_byte_slice(bytes: &[u8]) -> MotionConfiguration {
159        MotionConfiguration {
160            velocity: <u32>::from_le_byte_slice(&bytes[0..4]),
161            acceleration: <u32>::from_le_byte_slice(&bytes[4..8]),
162            deceleration: <u32>::from_le_byte_slice(&bytes[8..12]),
163        }
164    }
165}
166
167#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
168pub struct PulseWidth {
169    pub min: u32,
170    pub max: u32,
171}
172impl FromByteSlice for PulseWidth {
173    fn bytes_expected() -> usize {
174        8
175    }
176    fn from_le_byte_slice(bytes: &[u8]) -> PulseWidth {
177        PulseWidth { min: <u32>::from_le_byte_slice(&bytes[0..4]), max: <u32>::from_le_byte_slice(&bytes[4..8]) }
178    }
179}
180
181#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
182pub struct Degree {
183    pub min: i16,
184    pub max: i16,
185}
186impl FromByteSlice for Degree {
187    fn bytes_expected() -> usize {
188        4
189    }
190    fn from_le_byte_slice(bytes: &[u8]) -> Degree {
191        Degree { min: <i16>::from_le_byte_slice(&bytes[0..2]), max: <i16>::from_le_byte_slice(&bytes[2..4]) }
192    }
193}
194
195#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
196pub struct PositionReachedEvent {
197    pub servo_channel: u16,
198    pub position: i16,
199}
200impl FromByteSlice for PositionReachedEvent {
201    fn bytes_expected() -> usize {
202        4
203    }
204    fn from_le_byte_slice(bytes: &[u8]) -> PositionReachedEvent {
205        PositionReachedEvent { servo_channel: <u16>::from_le_byte_slice(&bytes[0..2]), position: <i16>::from_le_byte_slice(&bytes[2..4]) }
206    }
207}
208
209#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
210pub struct SpitfpErrorCount {
211    pub error_count_ack_checksum: u32,
212    pub error_count_message_checksum: u32,
213    pub error_count_frame: u32,
214    pub error_count_overflow: u32,
215}
216impl FromByteSlice for SpitfpErrorCount {
217    fn bytes_expected() -> usize {
218        16
219    }
220    fn from_le_byte_slice(bytes: &[u8]) -> SpitfpErrorCount {
221        SpitfpErrorCount {
222            error_count_ack_checksum: <u32>::from_le_byte_slice(&bytes[0..4]),
223            error_count_message_checksum: <u32>::from_le_byte_slice(&bytes[4..8]),
224            error_count_frame: <u32>::from_le_byte_slice(&bytes[8..12]),
225            error_count_overflow: <u32>::from_le_byte_slice(&bytes[12..16]),
226        }
227    }
228}
229
230#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
231pub struct Identity {
232    pub uid: String,
233    pub connected_uid: String,
234    pub position: char,
235    pub hardware_version: [u8; 3],
236    pub firmware_version: [u8; 3],
237    pub device_identifier: u16,
238}
239impl FromByteSlice for Identity {
240    fn bytes_expected() -> usize {
241        25
242    }
243    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
244        Identity {
245            uid: <String>::from_le_byte_slice(&bytes[0..8]),
246            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
247            position: <char>::from_le_byte_slice(&bytes[16..17]),
248            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
249            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
250            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
251        }
252    }
253}
254
255/// Drives up to 10 RC Servos
256#[derive(Clone)]
257pub struct ServoV2Bricklet {
258    device: Device,
259}
260impl ServoV2Bricklet {
261    pub const DEVICE_IDENTIFIER: u16 = 2157;
262    pub const DEVICE_DISPLAY_NAME: &'static str = "Servo Bricklet 2.0";
263    /// Creates an object with the unique device ID `uid`. This object can then be used after the IP Connection `ip_connection` is connected.
264    pub fn new(uid: Uid, connection: AsyncIpConnection) -> ServoV2Bricklet {
265        let mut result = ServoV2Bricklet { device: Device::new([2, 0, 10], uid, connection, Self::DEVICE_DISPLAY_NAME) };
266        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetStatus) as usize] = ResponseExpectedFlag::AlwaysTrue;
267        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetEnable) as usize] = ResponseExpectedFlag::False;
268        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetEnabled) as usize] = ResponseExpectedFlag::AlwaysTrue;
269        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetPosition) as usize] = ResponseExpectedFlag::False;
270        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetPosition) as usize] = ResponseExpectedFlag::AlwaysTrue;
271        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetCurrentPosition) as usize] = ResponseExpectedFlag::AlwaysTrue;
272        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetCurrentVelocity) as usize] = ResponseExpectedFlag::AlwaysTrue;
273        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetMotionConfiguration) as usize] = ResponseExpectedFlag::False;
274        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetMotionConfiguration) as usize] =
275            ResponseExpectedFlag::AlwaysTrue;
276        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetPulseWidth) as usize] = ResponseExpectedFlag::False;
277        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetPulseWidth) as usize] = ResponseExpectedFlag::AlwaysTrue;
278        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetDegree) as usize] = ResponseExpectedFlag::False;
279        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetDegree) as usize] = ResponseExpectedFlag::AlwaysTrue;
280        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetPeriod) as usize] = ResponseExpectedFlag::False;
281        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetPeriod) as usize] = ResponseExpectedFlag::AlwaysTrue;
282        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetServoCurrent) as usize] = ResponseExpectedFlag::AlwaysTrue;
283        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetServoCurrentConfiguration) as usize] =
284            ResponseExpectedFlag::False;
285        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetServoCurrentConfiguration) as usize] =
286            ResponseExpectedFlag::AlwaysTrue;
287        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetInputVoltageConfiguration) as usize] =
288            ResponseExpectedFlag::False;
289        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetInputVoltageConfiguration) as usize] =
290            ResponseExpectedFlag::AlwaysTrue;
291        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetOverallCurrent) as usize] = ResponseExpectedFlag::AlwaysTrue;
292        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetInputVoltage) as usize] = ResponseExpectedFlag::AlwaysTrue;
293        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetCurrentCalibration) as usize] = ResponseExpectedFlag::False;
294        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetCurrentCalibration) as usize] =
295            ResponseExpectedFlag::AlwaysTrue;
296        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetPositionReachedCallbackConfiguration) as usize] =
297            ResponseExpectedFlag::True;
298        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetPositionReachedCallbackConfiguration) as usize] =
299            ResponseExpectedFlag::AlwaysTrue;
300        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetSpitfpErrorCount) as usize] = ResponseExpectedFlag::AlwaysTrue;
301        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
302        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetBootloaderMode) as usize] = ResponseExpectedFlag::AlwaysTrue;
303        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetWriteFirmwarePointer) as usize] = ResponseExpectedFlag::False;
304        result.device.response_expected[u8::from(ServoV2BrickletFunction::WriteFirmware) as usize] = ResponseExpectedFlag::AlwaysTrue;
305        result.device.response_expected[u8::from(ServoV2BrickletFunction::SetStatusLedConfig) as usize] = ResponseExpectedFlag::False;
306        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetStatusLedConfig) as usize] = ResponseExpectedFlag::AlwaysTrue;
307        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetChipTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
308        result.device.response_expected[u8::from(ServoV2BrickletFunction::Reset) as usize] = ResponseExpectedFlag::False;
309        result.device.response_expected[u8::from(ServoV2BrickletFunction::WriteUid) as usize] = ResponseExpectedFlag::False;
310        result.device.response_expected[u8::from(ServoV2BrickletFunction::ReadUid) as usize] = ResponseExpectedFlag::AlwaysTrue;
311        result.device.response_expected[u8::from(ServoV2BrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
312        result
313    }
314
315    /// Returns the response expected flag for the function specified by the function ID parameter.
316    /// It is true if the function is expected to send a response, false otherwise.
317    ///
318    /// For getter functions this is enabled by default and cannot be disabled, because those
319    /// functions will always send a response. For callback configuration functions it is enabled
320    /// by default too, but can be disabled by [`set_response_expected`](crate::servo_v2_bricklet::ServoV2Bricklet::set_response_expected).
321    /// For setter functions it is disabled by default and can be enabled.
322    ///
323    /// Enabling the response expected flag for a setter function allows to detect timeouts
324    /// and other error conditions calls of this setter as well. The device will then send a response
325    /// for this purpose. If this flag is disabled for a setter function then no response is sent
326    /// and errors are silently ignored, because they cannot be detected.
327    ///
328    /// See [`set_response_expected`](crate::servo_v2_bricklet::ServoV2Bricklet::set_response_expected) for the list of function ID constants available for this function.
329    pub fn get_response_expected(&mut self, fun: ServoV2BrickletFunction) -> Result<bool, GetResponseExpectedError> {
330        self.device.get_response_expected(u8::from(fun))
331    }
332
333    /// Changes the response expected flag of the function specified by the function ID parameter.
334    /// This flag can only be changed for setter (default value: false) and callback configuration
335    /// functions (default value: true). For getter functions it is always enabled.
336    ///
337    /// Enabling the response expected flag for a setter function allows to detect timeouts and
338    /// other error conditions calls of this setter as well. The device will then send a response
339    /// for this purpose. If this flag is disabled for a setter function then no response is sent
340    /// and errors are silently ignored, because they cannot be detected.
341    pub fn set_response_expected(&mut self, fun: ServoV2BrickletFunction, response_expected: bool) -> Result<(), SetResponseExpectedError> {
342        self.device.set_response_expected(u8::from(fun), response_expected)
343    }
344
345    /// Changes the response expected flag for all setter and callback configuration functions of this device at once.
346    pub fn set_response_expected_all(&mut self, response_expected: bool) {
347        self.device.set_response_expected_all(response_expected)
348    }
349
350    /// Returns the version of the API definition (major, minor, revision) implemented by this API bindings.
351    /// This is neither the release version of this API bindings nor does it tell you anything about the represented Brick or Bricklet.
352    pub fn get_api_version(&self) -> [u8; 3] {
353        self.device.api_version
354    }
355
356    /// This receiver is triggered when a position set by [`set_position`]
357    /// is reached. If the new position matches the current position then the
358    /// receiver is not triggered, because the servo didn't move.
359    /// The parameters are the servo and the position that is reached.
360    ///
361    /// You can enable this receiver with [`set_position_reached_callback_configuration`].
362    ///
363    /// # Note
364    ///  Since we can't get any feedback from the servo, this only works if the
365    ///  velocity (see [`set_motion_configuration`]) is set smaller or equal to the
366    ///  maximum velocity of the servo. Otherwise the servo will lag behind the
367    ///  control value and the receiver will be triggered too early.
368    ///
369    /// [`set_position`]: #method.set_position
370    /// [`set_motion_configuration`]: #method.set_motion_configuration
371    /// [`set_position_reached_callback_configuration`]: #method.set_position_reached_callback_configuration
372    pub async fn get_position_reached_callback_receiver(&mut self) -> impl Stream<Item = PositionReachedEvent> {
373        self.device
374            .get_callback_receiver(u8::from(ServoV2BrickletFunction::CallbackPositionReached))
375            .await
376            .map(|p| PositionReachedEvent::from_le_byte_slice(p.body()))
377    }
378
379    /// Returns the status information of the Servo Bricklet 2.0.
380    ///
381    /// The status includes
382    ///
383    /// * for each channel if it is enabled or disabled,
384    /// * for each channel the current position,
385    /// * for each channel the current velocity,
386    /// * for each channel the current usage and
387    /// * the input voltage.
388    ///
389    /// Please note that the position and the velocity is a snapshot of the
390    /// current position and velocity of the servo in motion.
391    pub async fn get_status(&mut self) -> Result<Status, TinkerforgeError> {
392        let payload = [0; 0];
393
394        #[allow(unused_variables)]
395        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetStatus), &payload).await?;
396        Ok(Status::from_le_byte_slice(result.body()))
397    }
398
399    /// Enables a servo channel (0 to 9). If a servo is enabled, the configured position,
400    /// velocity, acceleration, etc. are applied immediately.
401    pub async fn set_enable(&mut self, servo_channel: u16, enable: bool) -> Result<(), TinkerforgeError> {
402        let mut payload = [0; 3];
403        servo_channel.write_to_slice(&mut payload[0..2]);
404        enable.write_to_slice(&mut payload[2..3]);
405
406        #[allow(unused_variables)]
407        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetEnable), &payload).await?;
408        Ok(())
409    }
410
411    /// Returns *true* if the specified servo channel is enabled, *false* otherwise.
412    pub async fn get_enabled(&mut self, servo_channel: u16) -> Result<bool, TinkerforgeError> {
413        let mut payload = [0; 2];
414        servo_channel.write_to_slice(&mut payload[0..2]);
415
416        #[allow(unused_variables)]
417        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetEnabled), &payload).await?;
418        Ok(bool::from_le_byte_slice(result.body()))
419    }
420
421    /// Sets the position in °/100 for the specified servo channel.
422    ///
423    /// The default range of the position is -9000 to 9000, but it can be specified
424    /// according to your servo with [`set_degree`].
425    ///
426    /// If you want to control a linear servo or RC brushless motor controller or
427    /// similar with the Servo Brick, you can also define lengths or speeds with
428    /// [`set_degree`].
429    pub async fn set_position(&mut self, servo_channel: u16, position: i16) -> Result<(), TinkerforgeError> {
430        let mut payload = [0; 4];
431        servo_channel.write_to_slice(&mut payload[0..2]);
432        position.write_to_slice(&mut payload[2..4]);
433
434        #[allow(unused_variables)]
435        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetPosition), &payload).await?;
436        Ok(())
437    }
438
439    /// Returns the position of the specified servo channel as set by [`set_position`].
440    pub async fn get_position(&mut self, servo_channel: u16) -> Result<i16, TinkerforgeError> {
441        let mut payload = [0; 2];
442        servo_channel.write_to_slice(&mut payload[0..2]);
443
444        #[allow(unused_variables)]
445        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetPosition), &payload).await?;
446        Ok(i16::from_le_byte_slice(result.body()))
447    }
448
449    /// Returns the *current* position of the specified servo channel. This may not be the
450    /// value of [`set_position`] if the servo is currently approaching a
451    /// position goal.
452    pub async fn get_current_position(&mut self, servo_channel: u16) -> Result<i16, TinkerforgeError> {
453        let mut payload = [0; 2];
454        servo_channel.write_to_slice(&mut payload[0..2]);
455
456        #[allow(unused_variables)]
457        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetCurrentPosition), &payload).await?;
458        Ok(i16::from_le_byte_slice(result.body()))
459    }
460
461    /// Returns the *current* velocity of the specified servo channel. This may not be the
462    /// velocity specified by [`set_motion_configuration`]. if the servo is
463    /// currently approaching a velocity goal.
464    pub async fn get_current_velocity(&mut self, servo_channel: u16) -> Result<u16, TinkerforgeError> {
465        let mut payload = [0; 2];
466        servo_channel.write_to_slice(&mut payload[0..2]);
467
468        #[allow(unused_variables)]
469        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetCurrentVelocity), &payload).await?;
470        Ok(u16::from_le_byte_slice(result.body()))
471    }
472
473    /// Sets the maximum velocity of the specified servo channel in °/100s as well as
474    /// the acceleration and deceleration in °/100s²
475    ///
476    /// With a velocity of 0 °/100s the position will be set immediately (no velocity).
477    ///
478    /// With an acc-/deceleration of 0 °/100s² the velocity will be set immediately
479    /// (no acc-/deceleration).
480    pub async fn set_motion_configuration(
481        &mut self,
482        servo_channel: u16,
483        velocity: u32,
484        acceleration: u32,
485        deceleration: u32,
486    ) -> Result<(), TinkerforgeError> {
487        let mut payload = [0; 14];
488        servo_channel.write_to_slice(&mut payload[0..2]);
489        velocity.write_to_slice(&mut payload[2..6]);
490        acceleration.write_to_slice(&mut payload[6..10]);
491        deceleration.write_to_slice(&mut payload[10..14]);
492
493        #[allow(unused_variables)]
494        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetMotionConfiguration), &payload).await?;
495        Ok(())
496    }
497
498    /// Returns the motion configuration as set by [`set_motion_configuration`].
499    pub async fn get_motion_configuration(&mut self, servo_channel: u16) -> Result<MotionConfiguration, TinkerforgeError> {
500        let mut payload = [0; 2];
501        servo_channel.write_to_slice(&mut payload[0..2]);
502
503        #[allow(unused_variables)]
504        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetMotionConfiguration), &payload).await?;
505        Ok(MotionConfiguration::from_le_byte_slice(result.body()))
506    }
507
508    /// Sets the minimum and maximum pulse width of the specified servo channel in µs.
509    ///
510    /// Usually, servos are controlled with a
511    /// [PWM](https://en.wikipedia.org/wiki/Pulse-width_modulation)__, whereby the
512    /// length of the pulse controls the position of the servo. Every servo has
513    /// different minimum and maximum pulse widths, these can be specified with
514    /// this function.
515    ///
516    /// If you have a datasheet for your servo that specifies the minimum and
517    /// maximum pulse width, you should set the values accordingly. If your servo
518    /// comes without any datasheet you have to find the values via trial and error.
519    ///
520    /// Both values have a range from 1 to 65535 (unsigned 16-bit integer). The
521    /// minimum must be smaller than the maximum.
522    ///
523    /// The default values are 1000µs (1ms) and 2000µs (2ms) for minimum and
524    /// maximum pulse width.
525    pub async fn set_pulse_width(&mut self, servo_channel: u16, min: u32, max: u32) -> Result<(), TinkerforgeError> {
526        let mut payload = [0; 10];
527        servo_channel.write_to_slice(&mut payload[0..2]);
528        min.write_to_slice(&mut payload[2..6]);
529        max.write_to_slice(&mut payload[6..10]);
530
531        #[allow(unused_variables)]
532        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetPulseWidth), &payload).await?;
533        Ok(())
534    }
535
536    /// Returns the minimum and maximum pulse width for the specified servo channel as set by
537    /// [`set_pulse_width`].
538    pub async fn get_pulse_width(&mut self, servo_channel: u16) -> Result<PulseWidth, TinkerforgeError> {
539        let mut payload = [0; 2];
540        servo_channel.write_to_slice(&mut payload[0..2]);
541
542        #[allow(unused_variables)]
543        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetPulseWidth), &payload).await?;
544        Ok(PulseWidth::from_le_byte_slice(result.body()))
545    }
546
547    /// Sets the minimum and maximum degree for the specified servo channel (by default
548    /// given as °/100).
549    ///
550    /// This only specifies the abstract values between which the minimum and maximum
551    /// pulse width is scaled. For example: If you specify a pulse width of 1000µs
552    /// to 2000µs and a degree range of -90° to 90°, a call of [`set_position`]
553    /// with 0 will result in a pulse width of 1500µs
554    /// (-90° = 1000µs, 90° = 2000µs, etc.).
555    ///
556    /// Possible usage:
557    ///
558    /// * The datasheet of your servo specifies a range of 200° with the middle position
559    ///   at 110°. In this case you can set the minimum to -9000 and the maximum to 11000.
560    /// * You measure a range of 220° on your servo and you don't have or need a middle
561    ///   position. In this case you can set the minimum to 0 and the maximum to 22000.
562    /// * You have a linear servo with a drive length of 20cm, In this case you could
563    ///   set the minimum to 0 and the maximum to 20000. Now you can set the Position
564    ///   with [`set_position`] with a resolution of cm/100. Also the velocity will
565    ///   have a resolution of cm/100s and the acceleration will have a resolution of
566    ///   cm/100s².
567    /// * You don't care about units and just want the highest possible resolution. In
568    ///   this case you should set the minimum to -32767 and the maximum to 32767.
569    /// * You have a brushless motor with a maximum speed of 10000 rpm and want to
570    ///   control it with a RC brushless motor controller. In this case you can set the
571    ///   minimum to 0 and the maximum to 10000. [`set_position`] now controls the rpm.
572    ///
573    /// Both values have a possible range from -32767 to 32767
574    /// (signed 16-bit integer). The minimum must be smaller than the maximum.
575    ///
576    /// The default values are -9000 and 9000 for the minimum and maximum degree.
577    pub async fn set_degree(&mut self, servo_channel: u16, min: i16, max: i16) -> Result<(), TinkerforgeError> {
578        let mut payload = [0; 6];
579        servo_channel.write_to_slice(&mut payload[0..2]);
580        min.write_to_slice(&mut payload[2..4]);
581        max.write_to_slice(&mut payload[4..6]);
582
583        #[allow(unused_variables)]
584        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetDegree), &payload).await?;
585        Ok(())
586    }
587
588    /// Returns the minimum and maximum degree for the specified servo channel as set by
589    /// [`set_degree`].
590    pub async fn get_degree(&mut self, servo_channel: u16) -> Result<Degree, TinkerforgeError> {
591        let mut payload = [0; 2];
592        servo_channel.write_to_slice(&mut payload[0..2]);
593
594        #[allow(unused_variables)]
595        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetDegree), &payload).await?;
596        Ok(Degree::from_le_byte_slice(result.body()))
597    }
598
599    /// Sets the period of the specified servo channel in µs.
600    ///
601    /// Usually, servos are controlled with a
602    /// [PWM](https://en.wikipedia.org/wiki/Pulse-width_modulation)__. Different
603    /// servos expect PWMs with different periods. Most servos run well with a
604    /// period of about 20ms.
605    ///
606    /// If your servo comes with a datasheet that specifies a period, you should
607    /// set it accordingly. If you don't have a datasheet and you have no idea
608    /// what the correct period is, the default value (19.5ms) will most likely
609    /// work fine.
610    ///
611    /// The minimum possible period is 1µs and the maximum is 1000000µs.
612    ///
613    /// The default value is 19.5ms (19500µs).
614    pub async fn set_period(&mut self, servo_channel: u16, period: u32) -> Result<(), TinkerforgeError> {
615        let mut payload = [0; 6];
616        servo_channel.write_to_slice(&mut payload[0..2]);
617        period.write_to_slice(&mut payload[2..6]);
618
619        #[allow(unused_variables)]
620        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetPeriod), &payload).await?;
621        Ok(())
622    }
623
624    /// Returns the period for the specified servo channel as set by [`set_period`].
625    pub async fn get_period(&mut self, servo_channel: u16) -> Result<u32, TinkerforgeError> {
626        let mut payload = [0; 2];
627        servo_channel.write_to_slice(&mut payload[0..2]);
628
629        #[allow(unused_variables)]
630        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetPeriod), &payload).await?;
631        Ok(u32::from_le_byte_slice(result.body()))
632    }
633
634    /// Returns the current consumption of the specified servo channel in mA.
635    pub async fn get_servo_current(&mut self, servo_channel: u16) -> Result<u16, TinkerforgeError> {
636        let mut payload = [0; 2];
637        servo_channel.write_to_slice(&mut payload[0..2]);
638
639        #[allow(unused_variables)]
640        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetServoCurrent), &payload).await?;
641        Ok(u16::from_le_byte_slice(result.body()))
642    }
643
644    /// Sets the averaging duration of the current measurement for the specified servo channel in ms.
645    pub async fn set_servo_current_configuration(&mut self, servo_channel: u16, averaging_duration: u8) -> Result<(), TinkerforgeError> {
646        let mut payload = [0; 3];
647        servo_channel.write_to_slice(&mut payload[0..2]);
648        averaging_duration.write_to_slice(&mut payload[2..3]);
649
650        #[allow(unused_variables)]
651        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetServoCurrentConfiguration), &payload).await?;
652        Ok(())
653    }
654
655    /// Returns the servo current configuration for the specified servo channel as set
656    /// by [`set_servo_current_configuration`].
657    pub async fn get_servo_current_configuration(&mut self, servo_channel: u16) -> Result<u8, TinkerforgeError> {
658        let mut payload = [0; 2];
659        servo_channel.write_to_slice(&mut payload[0..2]);
660
661        #[allow(unused_variables)]
662        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetServoCurrentConfiguration), &payload).await?;
663        Ok(u8::from_le_byte_slice(result.body()))
664    }
665
666    /// Sets the averaging duration of the input voltage measurement for the specified servo channel in ms.
667    pub async fn set_input_voltage_configuration(&mut self, averaging_duration: u8) -> Result<(), TinkerforgeError> {
668        let mut payload = [0; 1];
669        averaging_duration.write_to_slice(&mut payload[0..1]);
670
671        #[allow(unused_variables)]
672        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetInputVoltageConfiguration), &payload).await?;
673        Ok(())
674    }
675
676    /// Returns the input voltage configuration as set by [`set_input_voltage_configuration`].
677    pub async fn get_input_voltage_configuration(&mut self) -> Result<u8, TinkerforgeError> {
678        let payload = [0; 0];
679
680        #[allow(unused_variables)]
681        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetInputVoltageConfiguration), &payload).await?;
682        Ok(u8::from_le_byte_slice(result.body()))
683    }
684
685    /// Returns the current consumption of all servos together in mA.
686    pub async fn get_overall_current(&mut self) -> Result<u16, TinkerforgeError> {
687        let payload = [0; 0];
688
689        #[allow(unused_variables)]
690        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetOverallCurrent), &payload).await?;
691        Ok(u16::from_le_byte_slice(result.body()))
692    }
693
694    /// Returns the input voltage in mV. The input voltage is
695    /// given via the black power input connector on the Servo Brick.
696    pub async fn get_input_voltage(&mut self) -> Result<u16, TinkerforgeError> {
697        let payload = [0; 0];
698
699        #[allow(unused_variables)]
700        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetInputVoltage), &payload).await?;
701        Ok(u16::from_le_byte_slice(result.body()))
702    }
703
704    /// Sets an offset value (in mA) for each channel.
705    ///
706    /// Note: On delivery the Servo Bricklet 2.0 is already calibrated.
707    pub async fn set_current_calibration(&mut self, offset: &[i16; 10]) -> Result<(), TinkerforgeError> {
708        let mut payload = [0; 20];
709        offset.write_to_slice(&mut payload[0..20]);
710
711        #[allow(unused_variables)]
712        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetCurrentCalibration), &payload).await?;
713        Ok(())
714    }
715
716    /// Returns the current calibration as set by [`set_current_calibration`].
717    pub async fn get_current_calibration(&mut self) -> Result<Box<[i16; 10]>, TinkerforgeError> {
718        let payload = [0; 0];
719
720        #[allow(unused_variables)]
721        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetCurrentCalibration), &payload).await?;
722        Ok(Box::<[i16; 10]>::from_le_byte_slice(result.body()))
723    }
724
725    /// Enable/Disable [`get_position_reached_callback_receiver`] receiver.
726    pub async fn set_position_reached_callback_configuration(&mut self, servo_channel: u16, enabled: bool) -> Result<(), TinkerforgeError> {
727        let mut payload = [0; 3];
728        servo_channel.write_to_slice(&mut payload[0..2]);
729        enabled.write_to_slice(&mut payload[2..3]);
730
731        #[allow(unused_variables)]
732        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetPositionReachedCallbackConfiguration), &payload).await?;
733        Ok(())
734    }
735
736    /// Returns the receiver configuration as set by
737    /// [`set_position_reached_callback_configuration`].
738    pub async fn get_position_reached_callback_configuration(&mut self, servo_channel: u16) -> Result<bool, TinkerforgeError> {
739        let mut payload = [0; 2];
740        servo_channel.write_to_slice(&mut payload[0..2]);
741
742        #[allow(unused_variables)]
743        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetPositionReachedCallbackConfiguration), &payload).await?;
744        Ok(bool::from_le_byte_slice(result.body()))
745    }
746
747    /// Returns the error count for the communication between Brick and Bricklet.
748    ///
749    /// The errors are divided into
750    ///
751    /// * ACK checksum errors,
752    /// * message checksum errors,
753    /// * framing errors and
754    /// * overflow errors.
755    ///
756    /// The errors counts are for errors that occur on the Bricklet side. All
757    /// Bricks have a similar function that returns the errors on the Brick side.
758    pub async fn get_spitfp_error_count(&mut self) -> Result<SpitfpErrorCount, TinkerforgeError> {
759        let payload = [0; 0];
760
761        #[allow(unused_variables)]
762        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetSpitfpErrorCount), &payload).await?;
763        Ok(SpitfpErrorCount::from_le_byte_slice(result.body()))
764    }
765
766    /// Sets the bootloader mode and returns the status after the requested
767    /// mode change was instigated.
768    ///
769    /// You can change from bootloader mode to firmware mode and vice versa. A change
770    /// from bootloader mode to firmware mode will only take place if the entry function,
771    /// device identifier and CRC are present and correct.
772    ///
773    /// This function is used by Brick Viewer during flashing. It should not be
774    /// necessary to call it in a normal user program.
775    ///
776    /// Associated constants:
777    /// * SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
778    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
779    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
780    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
781    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
782    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_OK
783    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_INVALID_MODE
784    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_NO_CHANGE
785    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_ENTRY_FUNCTION_NOT_PRESENT
786    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_DEVICE_IDENTIFIER_INCORRECT
787    ///	* SERVO_V2_BRICKLET_BOOTLOADER_STATUS_CRC_MISMATCH
788    pub async fn set_bootloader_mode(&mut self, mode: u8) -> Result<u8, TinkerforgeError> {
789        let mut payload = [0; 1];
790        mode.write_to_slice(&mut payload[0..1]);
791
792        #[allow(unused_variables)]
793        let result = self.device.get(u8::from(ServoV2BrickletFunction::SetBootloaderMode), &payload).await?;
794        Ok(u8::from_le_byte_slice(result.body()))
795    }
796
797    /// Returns the current bootloader mode, see [`set_bootloader_mode`].
798    ///
799    /// Associated constants:
800    /// * SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER
801    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE
802    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_BOOTLOADER_WAIT_FOR_REBOOT
803    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_REBOOT
804    ///	* SERVO_V2_BRICKLET_BOOTLOADER_MODE_FIRMWARE_WAIT_FOR_ERASE_AND_REBOOT
805    pub async fn get_bootloader_mode(&mut self) -> Result<u8, TinkerforgeError> {
806        let payload = [0; 0];
807
808        #[allow(unused_variables)]
809        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetBootloaderMode), &payload).await?;
810        Ok(u8::from_le_byte_slice(result.body()))
811    }
812
813    /// Sets the firmware pointer for [`write_firmware`]. The pointer has
814    /// to be increased by chunks of size 64. The data is written to flash
815    /// every 4 chunks (which equals to one page of size 256).
816    ///
817    /// This function is used by Brick Viewer during flashing. It should not be
818    /// necessary to call it in a normal user program.
819    pub async fn set_write_firmware_pointer(&mut self, pointer: u32) -> Result<(), TinkerforgeError> {
820        let mut payload = [0; 4];
821        pointer.write_to_slice(&mut payload[0..4]);
822
823        #[allow(unused_variables)]
824        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetWriteFirmwarePointer), &payload).await?;
825        Ok(())
826    }
827
828    /// Writes 64 Bytes of firmware at the position as written by
829    /// [`set_write_firmware_pointer`] before. The firmware is written
830    /// to flash every 4 chunks.
831    ///
832    /// You can only write firmware in bootloader mode.
833    ///
834    /// This function is used by Brick Viewer during flashing. It should not be
835    /// necessary to call it in a normal user program.
836    pub async fn write_firmware(&mut self, data: &[u8; 64]) -> Result<u8, TinkerforgeError> {
837        let mut payload = [0; 64];
838        data.write_to_slice(&mut payload[0..64]);
839
840        #[allow(unused_variables)]
841        let result = self.device.get(u8::from(ServoV2BrickletFunction::WriteFirmware), &payload).await?;
842        Ok(u8::from_le_byte_slice(result.body()))
843    }
844
845    /// Sets the status LED configuration. By default the LED shows
846    /// communication traffic between Brick and Bricklet, it flickers once
847    /// for every 10 received data packets.
848    ///
849    /// You can also turn the LED permanently on/off or show a heartbeat.
850    ///
851    /// If the Bricklet is in bootloader mode, the LED is will show heartbeat by default.
852    ///
853    /// Associated constants:
854    /// * SERVO_V2_BRICKLET_STATUS_LED_CONFIG_OFF
855    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_ON
856    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
857    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
858    pub async fn set_status_led_config(&mut self, config: u8) -> Result<(), TinkerforgeError> {
859        let mut payload = [0; 1];
860        config.write_to_slice(&mut payload[0..1]);
861
862        #[allow(unused_variables)]
863        let result = self.device.set(u8::from(ServoV2BrickletFunction::SetStatusLedConfig), &payload).await?;
864        Ok(())
865    }
866
867    /// Returns the configuration as set by [`set_status_led_config`]
868    ///
869    /// Associated constants:
870    /// * SERVO_V2_BRICKLET_STATUS_LED_CONFIG_OFF
871    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_ON
872    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_HEARTBEAT
873    ///	* SERVO_V2_BRICKLET_STATUS_LED_CONFIG_SHOW_STATUS
874    pub async fn get_status_led_config(&mut self) -> Result<u8, TinkerforgeError> {
875        let payload = [0; 0];
876
877        #[allow(unused_variables)]
878        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetStatusLedConfig), &payload).await?;
879        Ok(u8::from_le_byte_slice(result.body()))
880    }
881
882    /// Returns the temperature as measured inside the microcontroller. The
883    /// value returned is not the ambient temperature!
884    ///
885    /// The temperature is only proportional to the real temperature and it has bad
886    /// accuracy. Practically it is only useful as an indicator for
887    /// temperature changes.
888    pub async fn get_chip_temperature(&mut self) -> Result<i16, TinkerforgeError> {
889        let payload = [0; 0];
890
891        #[allow(unused_variables)]
892        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetChipTemperature), &payload).await?;
893        Ok(i16::from_le_byte_slice(result.body()))
894    }
895
896    /// Calling this function will reset the Bricklet. All configurations
897    /// will be lost.
898    ///
899    /// After a reset you have to create new device objects,
900    /// calling functions on the existing ones will result in
901    /// undefined behavior!
902    pub async fn reset(&mut self) -> Result<(), TinkerforgeError> {
903        let payload = [0; 0];
904
905        #[allow(unused_variables)]
906        let result = self.device.set(u8::from(ServoV2BrickletFunction::Reset), &payload).await?;
907        Ok(())
908    }
909
910    /// Writes a new UID into flash. If you want to set a new UID
911    /// you have to decode the Base58 encoded UID string into an
912    /// integer first.
913    ///
914    /// We recommend that you use Brick Viewer to change the UID.
915    pub async fn write_uid(&mut self, uid: u32) -> Result<(), TinkerforgeError> {
916        let mut payload = [0; 4];
917        uid.write_to_slice(&mut payload[0..4]);
918
919        #[allow(unused_variables)]
920        let result = self.device.set(u8::from(ServoV2BrickletFunction::WriteUid), &payload).await?;
921        Ok(())
922    }
923
924    /// Returns the current UID as an integer. Encode as
925    /// Base58 to get the usual string version.
926    pub async fn read_uid(&mut self) -> Result<u32, TinkerforgeError> {
927        let payload = [0; 0];
928
929        #[allow(unused_variables)]
930        let result = self.device.get(u8::from(ServoV2BrickletFunction::ReadUid), &payload).await?;
931        Ok(u32::from_le_byte_slice(result.body()))
932    }
933
934    /// Returns the UID, the UID where the Bricklet is connected to,
935    /// the position, the hardware and firmware version as well as the
936    /// device identifier.
937    ///
938    /// The position can be 'a', 'b', 'c', 'd', 'e', 'f', 'g' or 'h' (Bricklet Port).
939    /// A Bricklet connected to an [Isolator Bricklet](isolator_bricklet) is always at
940    /// position 'z'.
941    ///
942    /// The device identifier numbers can be found [here](device_identifier).
943    /// |device_identifier_constant|
944    pub async fn get_identity(&mut self) -> Result<Identity, TinkerforgeError> {
945        let payload = [0; 0];
946
947        #[allow(unused_variables)]
948        let result = self.device.get(u8::from(ServoV2BrickletFunction::GetIdentity), &payload).await?;
949        Ok(Identity::from_le_byte_slice(result.body()))
950    }
951}