1use crate::channel::Channel;
6use crate::error::{CanError, CanOkError};
7use crate::peak_lib;
8use crate::peak_can;
9use std::ffi::c_void;
10use std::mem::size_of;
11use std::net::Ipv4Addr;
12use std::os::raw::c_char;
13
14#[derive(Debug, PartialEq)]
15pub enum ChannelConditionStatus {
16 Unavailable,
17 Available,
18 Occupied,
19 CanView,
20}
21
22impl From<ChannelConditionStatus> for u32 {
23 fn from(value: ChannelConditionStatus) -> Self {
24 match value {
25 ChannelConditionStatus::Unavailable => peak_can::PEAK_CHANNEL_UNAVAILABLE,
26 ChannelConditionStatus::Available => peak_can::PEAK_CHANNEL_AVAILABLE,
27 ChannelConditionStatus::Occupied => peak_can::PEAK_CHANNEL_OCCUPIED,
28 ChannelConditionStatus::CanView => peak_can::PEAK_CHANNEL_PEAKVIEW,
29 }
30 }
31}
32
33impl TryFrom<u32> for ChannelConditionStatus {
34 type Error = ();
35
36 fn try_from(value: u32) -> Result<Self, Self::Error> {
37 match value {
38 peak_can::PEAK_CHANNEL_AVAILABLE => Ok(ChannelConditionStatus::Available),
39 peak_can::PEAK_CHANNEL_UNAVAILABLE => Ok(ChannelConditionStatus::Unavailable),
40 peak_can::PEAK_CHANNEL_OCCUPIED => Ok(ChannelConditionStatus::Occupied),
41 peak_can::PEAK_CHANNEL_PEAKVIEW => Ok(ChannelConditionStatus::CanView),
42 _ => Err(()),
43 }
44 }
45}
46
47pub(crate) trait HasChannelCondition {}
50
51pub trait ChannelCondition {
52 fn channel_condition(&self) -> Result<ChannelConditionStatus, CanError>;
53}
54
55impl<T: HasChannelCondition + Channel> ChannelCondition for T {
56 fn channel_condition(&self) -> Result<ChannelConditionStatus, CanError> {
57 let mut data = [0u8; 4];
58 let code = unsafe {
59 peak_lib()?.CAN_GetValue(
60 self.channel(),
61 peak_can::PEAK_CHANNEL_CONDITION as u8,
62 data.as_mut_ptr() as *mut c_void,
63 4,
64 )
65 };
66
67 let value: u32 = u32::from_le_bytes(data);
68 match CanOkError::try_from(code) {
69 Ok(CanOkError::Ok) => match ChannelConditionStatus::try_from(value) {
70 Ok(status) => Ok(status),
71 Err(_) => Err(CanError::Unknown),
72 },
73 Ok(CanOkError::Err(err)) => Err(err),
74 Err(_) => Err(CanError::Unknown),
75 }
76 }
77}
78
79pub(crate) trait HasChannelIdentifying {}
82
83pub trait ChannelIdentifying {
84 fn set_channel_identifying(&self, value: bool) -> Result<(), CanError>;
85 fn is_channel_identifying(&self) -> Result<bool, CanError>;
86}
87
88impl<T: HasChannelIdentifying + Channel> ChannelIdentifying for T {
89 fn set_channel_identifying(&self, value: bool) -> Result<(), CanError> {
90 let mut data = match value {
91 true => peak_can::PEAK_PARAMETER_ON.to_le_bytes(),
92 false => peak_can::PEAK_PARAMETER_OFF.to_le_bytes(),
93 };
94
95 let code = unsafe {
96 peak_lib()?.CAN_SetValue(
97 self.channel(),
98 peak_can::PEAK_CHANNEL_IDENTIFYING as u8,
99 data.as_mut_ptr() as *mut c_void,
100 data.len() as u32,
101 )
102 };
103
104 match CanOkError::try_from(code) {
105 Ok(CanOkError::Ok) => Ok(()),
106 Ok(CanOkError::Err(err)) => Err(err),
107 Err(_) => Err(CanError::Unknown),
108 }
109 }
110
111 fn is_channel_identifying(&self) -> Result<bool, CanError> {
112 let mut data = [0u8; 4];
113 let code = unsafe {
114 peak_lib()?.CAN_GetValue(
115 self.channel(),
116 peak_can::PEAK_CHANNEL_IDENTIFYING as u8,
117 data.as_mut_ptr() as *mut c_void,
118 data.len() as u32,
119 )
120 };
121
122 match CanOkError::try_from(code) {
123 Ok(CanOkError::Ok) => {
124 let value = u32::from_le_bytes(data);
125 if value & peak_can::PEAK_PARAMETER_ON == peak_can::PEAK_PARAMETER_ON {
126 Ok(true)
127 } else {
128 Ok(false)
129 }
130 }
131 Ok(CanOkError::Err(err)) => Err(err),
132 Err(_) => Err(CanError::Unknown),
133 }
134 }
135}
136
137pub(crate) trait HasDeviceId {}
140
141pub trait DeviceId {
142 fn device_id(&self) -> Result<u32, CanError>;
143}
144
145impl<T: HasDeviceId + Channel> DeviceId for T {
146 fn device_id(&self) -> Result<u32, CanError> {
147 let mut data = [0u8; 4];
148 let code = unsafe {
149 peak_lib()?.CAN_GetValue(
150 self.channel(),
151 peak_can::PEAK_DEVICE_ID as u8,
152 data.as_mut_ptr() as *mut c_void,
153 data.len() as u32,
154 )
155 };
156
157 match CanOkError::try_from(code) {
158 Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
159 Ok(CanOkError::Err(err)) => Err(err),
160 Err(_) => Err(CanError::Unknown),
161 }
162 }
163}
164
165pub(crate) trait HasSetDeviceId {}
166
167pub trait SetDeviceId {
168 type Item;
169 fn set_device_id(&self, value: Self::Item) -> Result<(), CanError>;
170}
171
172impl<T: HasSetDeviceId + Channel> SetDeviceId for T {
173 type Item = u32;
174 fn set_device_id(&self, value: Self::Item) -> Result<(), CanError> {
175 let mut data = value.to_le_bytes();
176 let code = unsafe {
177 peak_lib()?.CAN_SetValue(
178 self.channel(),
179 peak_can::PEAK_DEVICE_ID as u8,
180 data.as_mut_ptr() as *mut c_void,
181 data.len() as u32,
182 )
183 };
184
185 match CanOkError::try_from(code) {
186 Ok(CanOkError::Ok) => Ok(()),
187 Ok(CanOkError::Err(err)) => Err(err),
188 Err(_) => Err(CanError::Unknown),
189 }
190 }
191}
192
193pub(crate) trait HasHardwareName {}
196
197pub trait HardwareName {
198 fn hardware_name(&self) -> Result<String, CanError>;
199}
200
201impl<T: HasHardwareName + Channel> HardwareName for T {
202 fn hardware_name(&self) -> Result<String, CanError> {
203 let mut data = [0u8; peak_can::MAX_LENGTH_HARDWARE_NAME as usize];
204 let code = unsafe {
205 peak_lib()?.CAN_GetValue(
206 self.channel(),
207 peak_can::PEAK_HARDWARE_NAME as u8,
208 data.as_mut_ptr() as *mut c_void,
209 data.len() as u32,
210 )
211 };
212
213 match CanOkError::try_from(code) {
214 Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
215 Ok(s) => {
216 let s = s.trim_matches(char::from(0));
217 Ok(String::from(s))
218 }
219 Err(_) => Err(CanError::Unknown),
220 },
221 Ok(CanOkError::Err(err)) => Err(err),
222 Err(_) => Err(CanError::Unknown),
223 }
224 }
225}
226
227pub(crate) trait HasControllerNumber {}
230
231pub trait ControllerNumber {
232 fn controller_number(&self) -> Result<u32, CanError>;
233}
234
235impl<T: HasControllerNumber + Channel> ControllerNumber for T {
236 fn controller_number(&self) -> Result<u32, CanError> {
237 let mut data = [0u8; 4];
238 let code = unsafe {
239 peak_lib()?.CAN_GetValue(
240 self.channel(),
241 peak_can::PEAK_CONTROLLER_NUMBER as u8,
242 data.as_mut_ptr() as *mut c_void,
243 data.len() as u32,
244 )
245 };
246
247 match CanOkError::try_from(code) {
248 Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
249 Ok(CanOkError::Err(err)) => Err(err),
250 Err(_) => Err(CanError::Unknown),
251 }
252 }
253}
254
255pub(crate) trait HasSetControllerNumber {}
256
257pub trait SetControllerNumber {
258 type Item;
259 fn set_controller_number(&self, value: Self::Item) -> Result<(), CanError>;
260}
261
262impl<T: HasSetControllerNumber + Channel> SetControllerNumber for T {
263 type Item = u32;
264 fn set_controller_number(&self, value: Self::Item) -> Result<(), CanError> {
265 let mut data = value.to_le_bytes();
266 let code = unsafe {
267 peak_lib()?.CAN_SetValue(
268 self.channel(),
269 peak_can::PEAK_CONTROLLER_NUMBER as u8,
270 data.as_mut_ptr() as *mut c_void,
271 data.len() as u32,
272 )
273 };
274
275 match CanOkError::try_from(code) {
276 Ok(CanOkError::Ok) => Ok(()),
277 Ok(CanOkError::Err(err)) => Err(err),
278 Err(_) => Err(CanError::Unknown),
279 }
280 }
281}
282
283pub(crate) trait HasIpAddress {}
286
287pub trait IpAddress {
288 fn ip_address(&self) -> Result<Ipv4Addr, CanError>;
289}
290
291impl<T: HasIpAddress + Channel> IpAddress for T {
292 fn ip_address(&self) -> Result<Ipv4Addr, CanError> {
293 let mut data = [0u8; 20];
294 let code = unsafe {
295 peak_lib()?.CAN_GetValue(
296 self.channel(),
297 peak_can::PEAK_IP_ADDRESS as u8,
298 data.as_mut_ptr() as *mut c_void,
299 data.len() as u32,
300 )
301 };
302
303 match CanOkError::try_from(code) {
304 Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
305 Ok(s) => {
306 let s = s.trim_matches(char::from(0));
307 match s.parse() {
308 Ok(ip) => Ok(ip),
309 Err(_) => Err(CanError::Unknown),
310 }
311 }
312 Err(_) => Err(CanError::Unknown),
313 },
314 Ok(CanOkError::Err(err)) => Err(err),
315 _ => Err(CanError::Unknown),
316 }
317 }
318}
319
320pub fn attached_channels_count() -> Result<u32, CanError> {
323 let mut data = [0u8; 4];
324 let code = unsafe {
325 peak_lib()?.CAN_GetValue(
326 peak_can::PEAK_NONEBUS as u16,
327 peak_can::PEAK_ATTACHED_CHANNELS_COUNT as u8,
328 data.as_mut_ptr() as *mut c_void,
329 data.len() as u32,
330 )
331 };
332
333 match CanOkError::try_from(code) {
334 Ok(CanOkError::Ok) => Ok(u32::from_le_bytes(data)),
335 Ok(CanOkError::Err(err)) => Err(err),
336 Err(_) => Err(CanError::Unknown),
337 }
338}
339
340#[derive(Debug)]
343pub struct ChannelInformation {
344 pub channel_information: peak_can::tagTPEAKChannelInformation,
345}
346
347impl ChannelInformation {
348 pub fn new() -> Self {
349 ChannelInformation {
350 channel_information: peak_can::tagTPEAKChannelInformation {
351 channel_handle: 0,
352 device_type: 0,
353 controller_number: 0,
354 device_features: 0,
355 device_name: [c_char::default(); 33usize],
356 device_id: 0,
357 channel_condition: 0,
358 },
359 }
360 }
361
362 pub fn device_name(&self) -> String {
363 let string = self
364 .channel_information
365 .device_name
366 .as_slice()
367 .iter()
368 .map(|c| char::from(*c as u8))
369 .collect::<Vec<_>>()
370 .as_slice()
371 .iter()
372 .collect::<String>();
373
374 let s = string.trim_matches(char::from(0));
375 String::from(s)
376 }
377
378 pub fn is_fd_capable(&self) -> bool {
379 (self.channel_information.device_features & peak_can::FEATURE_FD_CAPABLE) != 0
380 }
381}
382
383pub fn attached_channels() -> Result<Vec<ChannelInformation>, CanError> {
384 let attached_channels_count = attached_channels_count()?;
385 let mut channel_information_list = Vec::new();
386
387 for _ in 0..attached_channels_count {
388 channel_information_list.push(ChannelInformation::new());
389 }
390
391 let code = unsafe {
392 peak_lib()?.CAN_GetValue(
393 peak_can::PEAK_NONEBUS as u16,
394 peak_can::PEAK_ATTACHED_CHANNELS as u8,
395 channel_information_list.as_mut_ptr() as *mut c_void,
396 attached_channels_count * size_of::<peak_can::tagTPEAKChannelInformation>() as u32,
397 )
398 };
399
400 match CanOkError::try_from(code) {
401 Ok(CanOkError::Ok) => Ok(channel_information_list),
402 Ok(CanOkError::Err(err)) => Err(err),
403 Err(_) => Err(CanError::Unknown),
404 }
405}
406
407pub(crate) trait HasDevicePartNumber {}
410
411pub trait DevicePartNumber {
412 fn device_part_number(&self) -> Result<String, CanError>;
413}
414
415impl<T: HasDevicePartNumber + Channel> DevicePartNumber for T {
416 fn device_part_number(&self) -> Result<String, CanError> {
417 let mut data = [0u8; 100];
418 let code = unsafe {
419 peak_lib()?.CAN_GetValue(
420 self.channel(),
421 peak_can::PEAK_DEVICE_NUMBER as u8,
422 data.as_mut_ptr() as *mut c_void,
423 data.len() as u32,
424 )
425 };
426
427 match CanOkError::try_from(code) {
428 Ok(CanOkError::Ok) => match std::str::from_utf8(&data) {
429 Ok(s) => {
430 let s = s.trim_matches(char::from(0));
431 Ok(String::from(s))
432 }
433 Err(_) => Err(CanError::Unknown),
434 },
435 Ok(CanOkError::Err(err)) => Err(err),
436 Err(_) => Err(CanError::Unknown),
437 }
438 }
439}