1use crate::{
15    byte_converter::*, converting_callback_receiver::ConvertingCallbackReceiver, converting_receiver::ConvertingReceiver, device::*,
16    ip_connection::GetRequestSender,
17};
18pub enum ThermocoupleBrickletFunction {
19    GetTemperature,
20    SetTemperatureCallbackPeriod,
21    GetTemperatureCallbackPeriod,
22    SetTemperatureCallbackThreshold,
23    GetTemperatureCallbackThreshold,
24    SetDebouncePeriod,
25    GetDebouncePeriod,
26    SetConfiguration,
27    GetConfiguration,
28    GetErrorState,
29    GetIdentity,
30    CallbackTemperature,
31    CallbackTemperatureReached,
32    CallbackErrorState,
33}
34impl From<ThermocoupleBrickletFunction> for u8 {
35    fn from(fun: ThermocoupleBrickletFunction) -> Self {
36        match fun {
37            ThermocoupleBrickletFunction::GetTemperature => 1,
38            ThermocoupleBrickletFunction::SetTemperatureCallbackPeriod => 2,
39            ThermocoupleBrickletFunction::GetTemperatureCallbackPeriod => 3,
40            ThermocoupleBrickletFunction::SetTemperatureCallbackThreshold => 4,
41            ThermocoupleBrickletFunction::GetTemperatureCallbackThreshold => 5,
42            ThermocoupleBrickletFunction::SetDebouncePeriod => 6,
43            ThermocoupleBrickletFunction::GetDebouncePeriod => 7,
44            ThermocoupleBrickletFunction::SetConfiguration => 10,
45            ThermocoupleBrickletFunction::GetConfiguration => 11,
46            ThermocoupleBrickletFunction::GetErrorState => 12,
47            ThermocoupleBrickletFunction::GetIdentity => 255,
48            ThermocoupleBrickletFunction::CallbackTemperature => 8,
49            ThermocoupleBrickletFunction::CallbackTemperatureReached => 9,
50            ThermocoupleBrickletFunction::CallbackErrorState => 13,
51        }
52    }
53}
54pub const THERMOCOUPLE_BRICKLET_THRESHOLD_OPTION_OFF: char = 'x';
55pub const THERMOCOUPLE_BRICKLET_THRESHOLD_OPTION_OUTSIDE: char = 'o';
56pub const THERMOCOUPLE_BRICKLET_THRESHOLD_OPTION_INSIDE: char = 'i';
57pub const THERMOCOUPLE_BRICKLET_THRESHOLD_OPTION_SMALLER: char = '<';
58pub const THERMOCOUPLE_BRICKLET_THRESHOLD_OPTION_GREATER: char = '>';
59pub const THERMOCOUPLE_BRICKLET_AVERAGING_1: u8 = 1;
60pub const THERMOCOUPLE_BRICKLET_AVERAGING_2: u8 = 2;
61pub const THERMOCOUPLE_BRICKLET_AVERAGING_4: u8 = 4;
62pub const THERMOCOUPLE_BRICKLET_AVERAGING_8: u8 = 8;
63pub const THERMOCOUPLE_BRICKLET_AVERAGING_16: u8 = 16;
64pub const THERMOCOUPLE_BRICKLET_TYPE_B: u8 = 0;
65pub const THERMOCOUPLE_BRICKLET_TYPE_E: u8 = 1;
66pub const THERMOCOUPLE_BRICKLET_TYPE_J: u8 = 2;
67pub const THERMOCOUPLE_BRICKLET_TYPE_K: u8 = 3;
68pub const THERMOCOUPLE_BRICKLET_TYPE_N: u8 = 4;
69pub const THERMOCOUPLE_BRICKLET_TYPE_R: u8 = 5;
70pub const THERMOCOUPLE_BRICKLET_TYPE_S: u8 = 6;
71pub const THERMOCOUPLE_BRICKLET_TYPE_T: u8 = 7;
72pub const THERMOCOUPLE_BRICKLET_TYPE_G8: u8 = 8;
73pub const THERMOCOUPLE_BRICKLET_TYPE_G32: u8 = 9;
74pub const THERMOCOUPLE_BRICKLET_FILTER_OPTION_50HZ: u8 = 0;
75pub const THERMOCOUPLE_BRICKLET_FILTER_OPTION_60HZ: u8 = 1;
76
77#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
78pub struct TemperatureCallbackThreshold {
79    pub option: char,
80    pub min: i32,
81    pub max: i32,
82}
83impl FromByteSlice for TemperatureCallbackThreshold {
84    fn bytes_expected() -> usize { 9 }
85    fn from_le_byte_slice(bytes: &[u8]) -> TemperatureCallbackThreshold {
86        TemperatureCallbackThreshold {
87            option: <char>::from_le_byte_slice(&bytes[0..1]),
88            min: <i32>::from_le_byte_slice(&bytes[1..5]),
89            max: <i32>::from_le_byte_slice(&bytes[5..9]),
90        }
91    }
92}
93
94#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
95pub struct Configuration {
96    pub averaging: u8,
97    pub thermocouple_type: u8,
98    pub filter: u8,
99}
100impl FromByteSlice for Configuration {
101    fn bytes_expected() -> usize { 3 }
102    fn from_le_byte_slice(bytes: &[u8]) -> Configuration {
103        Configuration {
104            averaging: <u8>::from_le_byte_slice(&bytes[0..1]),
105            thermocouple_type: <u8>::from_le_byte_slice(&bytes[1..2]),
106            filter: <u8>::from_le_byte_slice(&bytes[2..3]),
107        }
108    }
109}
110
111#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
112pub struct ErrorState {
113    pub over_under: bool,
114    pub open_circuit: bool,
115}
116impl FromByteSlice for ErrorState {
117    fn bytes_expected() -> usize { 2 }
118    fn from_le_byte_slice(bytes: &[u8]) -> ErrorState {
119        ErrorState { over_under: <bool>::from_le_byte_slice(&bytes[0..1]), open_circuit: <bool>::from_le_byte_slice(&bytes[1..2]) }
120    }
121}
122
123#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
124pub struct ErrorStateEvent {
125    pub over_under: bool,
126    pub open_circuit: bool,
127}
128impl FromByteSlice for ErrorStateEvent {
129    fn bytes_expected() -> usize { 2 }
130    fn from_le_byte_slice(bytes: &[u8]) -> ErrorStateEvent {
131        ErrorStateEvent { over_under: <bool>::from_le_byte_slice(&bytes[0..1]), open_circuit: <bool>::from_le_byte_slice(&bytes[1..2]) }
132    }
133}
134
135#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
136pub struct Identity {
137    pub uid: String,
138    pub connected_uid: String,
139    pub position: char,
140    pub hardware_version: [u8; 3],
141    pub firmware_version: [u8; 3],
142    pub device_identifier: u16,
143}
144impl FromByteSlice for Identity {
145    fn bytes_expected() -> usize { 25 }
146    fn from_le_byte_slice(bytes: &[u8]) -> Identity {
147        Identity {
148            uid: <String>::from_le_byte_slice(&bytes[0..8]),
149            connected_uid: <String>::from_le_byte_slice(&bytes[8..16]),
150            position: <char>::from_le_byte_slice(&bytes[16..17]),
151            hardware_version: <[u8; 3]>::from_le_byte_slice(&bytes[17..20]),
152            firmware_version: <[u8; 3]>::from_le_byte_slice(&bytes[20..23]),
153            device_identifier: <u16>::from_le_byte_slice(&bytes[23..25]),
154        }
155    }
156}
157
158#[derive(Clone)]
160pub struct ThermocoupleBricklet {
161    device: Device,
162}
163impl ThermocoupleBricklet {
164    pub const DEVICE_IDENTIFIER: u16 = 266;
165    pub const DEVICE_DISPLAY_NAME: &'static str = "Thermocouple Bricklet";
166    pub fn new<T: GetRequestSender>(uid: &str, req_sender: T) -> ThermocoupleBricklet {
168        let mut result = ThermocoupleBricklet { device: Device::new([2, 0, 0], uid, req_sender, 0) };
169        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetTemperature) as usize] = ResponseExpectedFlag::AlwaysTrue;
170        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::SetTemperatureCallbackPeriod) as usize] =
171            ResponseExpectedFlag::True;
172        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetTemperatureCallbackPeriod) as usize] =
173            ResponseExpectedFlag::AlwaysTrue;
174        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::SetTemperatureCallbackThreshold) as usize] =
175            ResponseExpectedFlag::True;
176        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetTemperatureCallbackThreshold) as usize] =
177            ResponseExpectedFlag::AlwaysTrue;
178        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::SetDebouncePeriod) as usize] = ResponseExpectedFlag::True;
179        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetDebouncePeriod) as usize] =
180            ResponseExpectedFlag::AlwaysTrue;
181        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::SetConfiguration) as usize] = ResponseExpectedFlag::False;
182        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetConfiguration) as usize] =
183            ResponseExpectedFlag::AlwaysTrue;
184        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetErrorState) as usize] = ResponseExpectedFlag::AlwaysTrue;
185        result.device.response_expected[u8::from(ThermocoupleBrickletFunction::GetIdentity) as usize] = ResponseExpectedFlag::AlwaysTrue;
186        result
187    }
188
189    pub fn get_response_expected(&mut self, fun: ThermocoupleBrickletFunction) -> Result<bool, GetResponseExpectedError> {
204        self.device.get_response_expected(u8::from(fun))
205    }
206
207    pub fn set_response_expected(
216        &mut self,
217        fun: ThermocoupleBrickletFunction,
218        response_expected: bool,
219    ) -> Result<(), SetResponseExpectedError> {
220        self.device.set_response_expected(u8::from(fun), response_expected)
221    }
222
223    pub fn set_response_expected_all(&mut self, response_expected: bool) { self.device.set_response_expected_all(response_expected) }
225
226    pub fn get_api_version(&self) -> [u8; 3] { self.device.api_version }
229
230    pub fn get_temperature_callback_receiver(&self) -> ConvertingCallbackReceiver<i32> {
240        self.device.get_callback_receiver(u8::from(ThermocoupleBrickletFunction::CallbackTemperature))
241    }
242
243    pub fn get_temperature_reached_callback_receiver(&self) -> ConvertingCallbackReceiver<i32> {
250        self.device.get_callback_receiver(u8::from(ThermocoupleBrickletFunction::CallbackTemperatureReached))
251    }
252
253    pub fn get_error_state_callback_receiver(&self) -> ConvertingCallbackReceiver<ErrorStateEvent> {
256        self.device.get_callback_receiver(u8::from(ThermocoupleBrickletFunction::CallbackErrorState))
257    }
258
259    pub fn get_temperature(&self) -> ConvertingReceiver<i32> {
265        let payload = vec![0; 0];
266
267        self.device.get(u8::from(ThermocoupleBrickletFunction::GetTemperature), payload)
268    }
269
270    pub fn set_temperature_callback_period(&self, period: u32) -> ConvertingReceiver<()> {
276        let mut payload = vec![0; 4];
277        payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(period));
278
279        self.device.set(u8::from(ThermocoupleBrickletFunction::SetTemperatureCallbackPeriod), payload)
280    }
281
282    pub fn get_temperature_callback_period(&self) -> ConvertingReceiver<u32> {
284        let payload = vec![0; 0];
285
286        self.device.get(u8::from(ThermocoupleBrickletFunction::GetTemperatureCallbackPeriod), payload)
287    }
288
289    pub fn set_temperature_callback_threshold(&self, option: char, min: i32, max: i32) -> ConvertingReceiver<()> {
308        let mut payload = vec![0; 9];
309        payload[0..1].copy_from_slice(&<char>::to_le_byte_vec(option));
310        payload[1..5].copy_from_slice(&<i32>::to_le_byte_vec(min));
311        payload[5..9].copy_from_slice(&<i32>::to_le_byte_vec(max));
312
313        self.device.set(u8::from(ThermocoupleBrickletFunction::SetTemperatureCallbackThreshold), payload)
314    }
315
316    pub fn get_temperature_callback_threshold(&self) -> ConvertingReceiver<TemperatureCallbackThreshold> {
325        let payload = vec![0; 0];
326
327        self.device.get(u8::from(ThermocoupleBrickletFunction::GetTemperatureCallbackThreshold), payload)
328    }
329
330    pub fn set_debounce_period(&self, debounce: u32) -> ConvertingReceiver<()> {
340        let mut payload = vec![0; 4];
341        payload[0..4].copy_from_slice(&<u32>::to_le_byte_vec(debounce));
342
343        self.device.set(u8::from(ThermocoupleBrickletFunction::SetDebouncePeriod), payload)
344    }
345
346    pub fn get_debounce_period(&self) -> ConvertingReceiver<u32> {
348        let payload = vec![0; 0];
349
350        self.device.get(u8::from(ThermocoupleBrickletFunction::GetDebouncePeriod), payload)
351    }
352
353    pub fn set_configuration(&self, averaging: u8, thermocouple_type: u8, filter: u8) -> ConvertingReceiver<()> {
396        let mut payload = vec![0; 3];
397        payload[0..1].copy_from_slice(&<u8>::to_le_byte_vec(averaging));
398        payload[1..2].copy_from_slice(&<u8>::to_le_byte_vec(thermocouple_type));
399        payload[2..3].copy_from_slice(&<u8>::to_le_byte_vec(filter));
400
401        self.device.set(u8::from(ThermocoupleBrickletFunction::SetConfiguration), payload)
402    }
403
404    pub fn get_configuration(&self) -> ConvertingReceiver<Configuration> {
425        let payload = vec![0; 0];
426
427        self.device.get(u8::from(ThermocoupleBrickletFunction::GetConfiguration), payload)
428    }
429
430    pub fn get_error_state(&self) -> ConvertingReceiver<ErrorState> {
442        let payload = vec![0; 0];
443
444        self.device.get(u8::from(ThermocoupleBrickletFunction::GetErrorState), payload)
445    }
446
447    pub fn get_identity(&self) -> ConvertingReceiver<Identity> {
458        let payload = vec![0; 0];
459
460        self.device.get(u8::from(ThermocoupleBrickletFunction::GetIdentity), payload)
461    }
462}