1use serde::{Deserialize, Serialize};
4use std::collections::{HashMap, HashSet};
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum DeviceConnectionType {
9 UsbDevice = 0,
10 NetworkDevice = 1,
11 FastUsbDevice = 2,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ConnectionParam {
17 Tcp = 0,
18 Udp = 1,
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq)]
23pub enum DeviceTypeId {
24 Bootloader55 = 3,
25 Bootloader56U = 15,
26 Bootloader56E = 16,
27 Bootloader58 = 41,
28
29 Device55v1 = 0,
30 Device55v2 = 1,
31 Device55v3 = 2,
32
33 Device56U = 10,
34 Device56E = 11,
35 Device27U = 20,
36 Device27E = 21,
37
38 Device57U = 30,
39 Device57E = 31,
40 PoKeys57CNC = 32,
41 PoKeys57CNCpro4x25 = 33,
42 PoKeys57CNCdb25 = 38,
43 PoKeys57Utest = 39,
44
45 LiniTester = 43,
46
47 Device57Uv0 = 28,
48 Device57Ev0 = 29,
49
50 Device58EU = 40,
51 PoPLC58 = 50,
52
53 OEM1 = 100,
54 SerialReader = 101,
55 X15_02_24 = 102,
56}
57
58#[derive(Debug, Clone, Copy)]
60pub struct DeviceTypeMask(pub u64);
61
62impl DeviceTypeMask {
63 pub const BOOTLOADER: Self = Self(1 << 0);
64 pub const BOOTLOADER55: Self = Self(1 << 1);
65 pub const BOOTLOADER56: Self = Self(1 << 2);
66 pub const BOOTLOADER56U: Self = Self(1 << 3);
67 pub const BOOTLOADER56E: Self = Self(1 << 4);
68 pub const BOOTLOADER58: Self = Self(1 << 5);
69
70 pub const DEVICE55: Self = Self(1 << 10);
71 pub const DEVICE55V1: Self = Self(1 << 11);
72 pub const DEVICE55V2: Self = Self(1 << 12);
73 pub const DEVICE55V3: Self = Self(1 << 13);
74
75 pub const DEVICE56: Self = Self(1 << 14);
76 pub const DEVICE56U: Self = Self(1 << 15);
77 pub const DEVICE56E: Self = Self(1 << 16);
78 pub const DEVICE27: Self = Self(1 << 17);
79 pub const DEVICE27U: Self = Self(1 << 18);
80 pub const DEVICE27E: Self = Self(1 << 19);
81
82 pub const DEVICE57: Self = Self(1 << 20);
83 pub const DEVICE57U: Self = Self(1 << 24);
84 pub const DEVICE57E: Self = Self(1 << 25);
85 pub const DEVICE57CNC: Self = Self(1 << 26);
86 pub const DEVICE57CNCDB25: Self = Self(1 << 27);
87 pub const DEVICE57UTEST: Self = Self(1 << 28);
88 pub const DEVICE57CNCPRO4X25: Self = Self(1 << 29);
89
90 pub const DEVICE58: Self = Self(1 << 21);
91 pub const POPLC58: Self = Self(1 << 22);
92
93 pub const POKEYS16RF: Self = Self(1 << 23);
94}
95
96#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub enum PulseEngineState {
99 Stopped = 0,
100 Internal = 1,
101 Buffer = 2,
102 Running = 3,
103
104 Jogging = 10,
105 Stopping = 11,
106
107 Home = 20,
108 Homing = 21,
109
110 ProbeComplete = 30,
111 Probe = 31,
112 ProbeError = 32,
113
114 HybridProbeStopping = 40,
115 HybridProbeComplete = 41,
116
117 StopLimit = 100,
118 StopEmergency = 101,
119}
120
121#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123pub enum PulseEngineAxisState {
124 Stopped = 0,
125 Ready = 1,
126 Running = 2,
127 Accelerating = 3,
128 Decelerating = 4,
129
130 HomingResetting = 8,
131 HomingBackingOff = 9,
132 Home = 10,
133 HomingStart = 11,
134 HomingSearch = 12,
135 HomingBack = 13,
136
137 Probed = 14,
138 ProbeStart = 15,
139 ProbeSearch = 16,
140
141 Error = 20,
142 Limit = 30,
143}
144
145#[derive(Debug, Clone, Copy, PartialEq, Eq)]
147pub enum I2cStatus {
148 Error = 0,
149 Ok = 1,
150 Complete = 2,
151 InProgress = 0x10,
152 Timeout = 0x20,
153 ChecksumError = 0x30, DeviceNotFound = 0x40, PacketTooLarge = 0x50, }
157
158#[derive(Debug, Clone)]
160pub struct I2cConfig {
161 pub max_packet_size: usize,
163 pub timeout_ms: u64,
164 pub retry_attempts: u32,
165
166 pub auto_fragment: bool,
168 pub fragment_delay_ms: u64,
169 pub validation_level: ValidationLevel,
170 pub performance_monitoring: bool,
171}
172
173impl Default for I2cConfig {
174 fn default() -> Self {
175 Self {
176 max_packet_size: 32,
177 timeout_ms: 1000,
178 retry_attempts: 3,
179 auto_fragment: false,
180 fragment_delay_ms: 10,
181 validation_level: ValidationLevel::None,
182 performance_monitoring: false,
183 }
184 }
185}
186
187#[derive(Debug, Clone)]
189pub struct RetryConfig {
190 pub max_attempts: u32,
191 pub base_delay_ms: u64,
192 pub max_delay_ms: u64,
193 pub backoff_multiplier: f64,
194 pub jitter: bool,
195}
196
197impl Default for RetryConfig {
198 fn default() -> Self {
199 Self {
200 max_attempts: 3,
201 base_delay_ms: 100,
202 max_delay_ms: 2000,
203 backoff_multiplier: 2.0,
204 jitter: true,
205 }
206 }
207}
208
209#[derive(Debug, Clone, PartialEq, Eq)]
211pub enum ValidationLevel {
212 None, Basic, Strict, Custom(ValidationConfig),
216}
217
218#[derive(Debug, Clone, PartialEq, Eq)]
220pub struct ValidationConfig {
221 pub validate_checksums: bool,
222 pub validate_command_ids: bool,
223 pub validate_device_ids: bool,
224 pub validate_packet_structure: bool,
225 pub max_device_id: u8,
226 pub valid_commands: HashSet<u8>,
227}
228
229impl Default for ValidationConfig {
230 fn default() -> Self {
231 Self {
232 validate_checksums: true,
233 validate_command_ids: true,
234 validate_device_ids: true,
235 validate_packet_structure: true,
236 max_device_id: 255,
237 valid_commands: HashSet::new(),
238 }
239 }
240}
241
242#[derive(Debug, Clone, Default)]
244pub struct I2cMetrics {
245 pub total_commands: u64,
246 pub successful_commands: u64,
247 pub failed_commands: u64,
248 pub average_response_time: std::time::Duration,
249 pub max_response_time: std::time::Duration,
250 pub min_response_time: std::time::Duration,
251 pub error_counts: HashMap<String, u32>,
252}
253
254#[derive(Debug, Clone)]
256pub struct HealthStatus {
257 pub connectivity: ConnectivityStatus,
258 pub i2c_health: I2cHealthStatus,
259 pub error_rate: f64,
260 pub performance: PerformanceSummary,
261}
262
263#[derive(Debug, Clone)]
265pub enum ConnectivityStatus {
266 Healthy,
267 Degraded(String),
268 Failed(String),
269}
270
271#[derive(Debug, Clone)]
273pub enum I2cHealthStatus {
274 Healthy,
275 Degraded(String),
276 Failed(String),
277}
278
279#[derive(Debug, Clone, Default)]
281pub struct PerformanceSummary {
282 pub avg_response_time_ms: f64,
283 pub success_rate: f64,
284 pub throughput_commands_per_sec: f64,
285}
286
287#[derive(Debug, Clone, Copy, PartialEq, Eq)]
289pub enum LcdMode {
290 Direct = 0,
291 Buffered = 1,
292}
293
294#[derive(Debug, Clone, Serialize, Deserialize)]
296pub struct DeviceInfo {
297 pub pin_count: u32,
298 pub pwm_count: u32,
299 pub basic_encoder_count: u32,
300 pub encoders_count: u32,
301 pub fast_encoders: u32,
302 pub ultra_fast_encoders: u32,
303 pub pwm_internal_frequency: u32,
304 pub analog_inputs: u32,
305
306 pub key_mapping: u32,
308 pub triggered_key_mapping: u32,
309 pub key_repeat_delay: u32,
310 pub digital_counters: u32,
311 pub joystick_button_axis_mapping: u32,
312 pub joystick_analog_to_digital_mapping: u32,
313 pub macros: u32,
314 pub matrix_keyboard: u32,
315 pub matrix_keyboard_triggered_mapping: u32,
316 pub lcd: u32,
317 pub matrix_led: u32,
318 pub connection_signal: u32,
319 pub po_ext_bus: u32,
320 pub po_net: u32,
321 pub analog_filtering: u32,
322 pub init_outputs_start: u32,
323 pub prot_i2c: u32,
324 pub prot_1wire: u32,
325 pub additional_options: u32,
326 pub load_status: u32,
327 pub custom_device_name: u32,
328 pub po_tlog27_support: u32,
329 pub sensor_list: u32,
330 pub web_interface: u32,
331 pub fail_safe_settings: u32,
332 pub joystick_hat_switch: u32,
333 pub pulse_engine: u32,
334 pub pulse_engine_v2: u32,
335 pub easy_sensors: u32,
336}
337
338#[derive(Debug, Clone, Serialize, Deserialize)]
340pub struct DeviceData {
341 pub device_type_id: u32,
342 pub serial_number: u32,
343 pub device_name: [u8; 30],
344 pub device_type_name: [u8; 30],
345 pub build_date: [u8; 12],
346 pub activation_code: [u8; 8],
347 pub firmware_version_major: u8,
348 pub firmware_version_minor: u8,
349 pub firmware_revision: u8,
350 pub user_id: u8,
351 pub device_type: u8,
352 pub activated_options: u8,
353 pub device_lock_status: u8,
354 pub hw_type: u8,
355 pub fw_type: u8,
356 pub product_id: u8,
357 pub secondary_firmware_version_major: u8,
358 pub secondary_firmware_version_minor: u8,
359 pub device_is_bootloader: u8,
360}
361
362#[derive(Debug, Clone, Serialize, Deserialize)]
364pub struct NetworkDeviceSummary {
365 pub serial_number: u32,
366 pub ip_address: [u8; 4],
367 pub host_ip: [u8; 4],
368 pub firmware_version_major: u8,
369 pub firmware_version_minor: u8,
370 pub firmware_revision: u8,
371 pub user_id: u8,
372 pub dhcp: u8,
373 pub hw_type: u8,
374 pub use_udp: u8,
375}
376
377#[derive(Debug, Clone, Serialize, Deserialize, Default)]
379pub struct NetworkDeviceInfo {
380 pub ip_address_current: [u8; 4],
381 pub ip_address_setup: [u8; 4],
382 pub subnet_mask: [u8; 4],
383 pub gateway_ip: [u8; 4],
384 pub tcp_timeout: u16,
385 pub additional_network_options: u8,
386 pub dhcp: u8,
387}
388
389#[derive(Debug, Clone, Serialize, Deserialize)]
391pub struct RealTimeClock {
392 pub sec: u8,
393 pub min: u8,
394 pub hour: u8,
395 pub dow: u8,
396 pub dom: u8,
397 pub tmp: u8,
398 pub doy: u16,
399 pub month: u16,
400 pub year: u16,
401}
402
403#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct CanMessage {
406 pub id: u32,
407 pub data: [u8; 8],
408 pub len: u8,
409 pub format: u8,
410 pub msg_type: u8,
411}
412
413pub const REQUEST_BUFFER_SIZE: usize = 68;
415pub const RESPONSE_BUFFER_SIZE: usize = 68;
416pub const MULTIPART_BUFFER_SIZE: usize = 448;
417
418impl Default for DeviceData {
420 fn default() -> Self {
421 Self {
422 device_type_id: 0,
423 serial_number: 0,
424 device_name: [0; 30],
425 device_type_name: [0; 30],
426 build_date: [0; 12],
427 activation_code: [0; 8],
428 firmware_version_major: 0,
429 firmware_version_minor: 0,
430 firmware_revision: 0,
431 user_id: 0,
432 device_type: 0,
433 activated_options: 0,
434 device_lock_status: 0,
435 hw_type: 0,
436 fw_type: 0,
437 product_id: 0,
438 secondary_firmware_version_major: 0,
439 secondary_firmware_version_minor: 0,
440 device_is_bootloader: 0,
441 }
442 }
443}
444
445impl DeviceData {
447 pub fn device_locked(&self) -> bool {
448 self.device_lock_status != 0
449 }
450
451 pub fn device_features(&self) -> u8 {
452 self.activated_options
453 }
454
455 pub fn software_version_string(&self) -> String {
460 let software_version_byte = self.firmware_version_major;
463 let revision_byte = self.firmware_version_minor;
464
465 let major = 1 + ((software_version_byte >> 4) & 0x0F);
467
468 let minor = software_version_byte & 0x0F;
470
471 let revision = revision_byte;
473
474 format!("{}.{}.{}", major, minor, revision)
475 }
476
477 pub fn device_name(&self) -> String {
478 String::from_utf8_lossy(&self.device_name)
479 .trim_end_matches('\0')
480 .to_string()
481 }
482
483 pub fn device_type_name(&self) -> String {
485 match self.hw_type {
489 1 => "PoKeys55".to_string(),
490 2 => "PoKeys55".to_string(),
491 3 => "PoKeys55".to_string(),
492 10 => "Pokeys56U".to_string(),
493 11 => "Pokeys56E".to_string(),
494 28 => "Pokeys57U".to_string(),
495 29 => "Pokeys57E".to_string(),
496 30 => "PoKeys57Uv1.1".to_string(),
497 31 => "PoKeys57Ev1.1".to_string(),
498 32 => "PoKeys57CNC".to_string(),
499 35 => "PoKeys57U OEM".to_string(),
500 36 => "PoKeys57U OEM".to_string(),
501 37 => "PoPLC57NG".to_string(),
502 38 => "PoKeys57CNCdb25 ".to_string(),
503 39 => "PoKeys57Utest ".to_string(),
504 40 => "PoKeys58EU".to_string(),
505 41 => "PoBootload (series 58)".to_string(),
506 43 => "LiniTester programmer".to_string(),
507 44 => "LiniTester calibrator ".to_string(),
508 45 => "PoKeys57Industrial1 ".to_string(),
509 50 => "PoPLC v1.0".to_string(),
510 60 => "PoKeys16".to_string(),
511 _ => {
513 format!(
515 "Unknown Device (ID: {}, HW: {})",
516 self.device_type_id, self.hw_type
517 )
518 }
519 }
520 }
521
522 pub fn build_date_string(&self) -> String {
524 String::from_utf8_lossy(&self.build_date)
525 .trim_end_matches('\0')
526 .to_string()
527 }
528}
529
530impl NetworkDeviceInfo {
531 pub fn ip_address(&self) -> [u8; 4] {
532 self.ip_address_current
533 }
534
535 pub fn gateway(&self) -> [u8; 4] {
536 self.gateway_ip
537 }
538
539 pub fn dns_server(&self) -> [u8; 4] {
540 [0; 4] }
542
543 pub fn mac_address(&self) -> [u8; 6] {
544 [0; 6] }
546
547 pub fn device_name(&self) -> String {
548 "".to_string() }
550
551 pub fn http_port(&self) -> u16 {
552 80 }
554
555 pub fn tcp_port(&self) -> u16 {
556 20055 }
558
559 pub fn udp_port(&self) -> u16 {
560 20055 }
562
563 pub fn dhcp_enabled(&self) -> bool {
564 self.dhcp != 0
565 }
566}
567
568pub const USB_VENDOR_ID: u16 = 0x1DC3;
570pub const USB_PRODUCT_ID_1: u16 = 0x1001;
571pub const USB_PRODUCT_ID_2: u16 = 0x1002;
572
573pub const REQUEST_HEADER: u8 = 0xBB;
575pub const RESPONSE_HEADER: u8 = 0xAA;
576pub const CHECKSUM_LENGTH: usize = 7;
577
578#[cfg(test)]
579mod tests {
580 use super::*;
581
582 #[test]
583 fn test_device_type_name() {
584 let mut device_data = DeviceData {
586 hw_type: 10,
587 ..Default::default()
588 };
589 assert_eq!(device_data.device_type_name(), "Pokeys56U");
590
591 device_data.hw_type = 11;
592 assert_eq!(device_data.device_type_name(), "Pokeys56E");
593
594 device_data.hw_type = 30;
595 assert_eq!(device_data.device_type_name(), "PoKeys57Uv1.1");
596
597 device_data.hw_type = 31;
598 assert_eq!(device_data.device_type_name(), "PoKeys57Ev1.1");
599
600 device_data.hw_type = 32;
601 assert_eq!(device_data.device_type_name(), "PoKeys57CNC");
602
603 device_data.hw_type = 0; device_data.device_type_id = 999999; device_data.device_name = [0; 30];
607 let test_name = b"Dec 11 2024PoKeys57E\0\0\0\0\0\0\0\0\0\0";
608 device_data.device_name[..test_name.len()].copy_from_slice(test_name);
609 assert_eq!(
610 device_data.device_type_name(),
611 "Unknown Device (ID: 999999, HW: 0)"
612 );
613
614 let test_name2 = b"Build PoKeys56U info\0\0\0\0\0\0\0\0\0";
616 device_data.device_name[..test_name2.len()].copy_from_slice(test_name2);
617 assert_eq!(
618 device_data.device_type_name(),
619 "Unknown Device (ID: 999999, HW: 0)"
620 );
621
622 device_data.device_type_id = 99;
624 device_data.hw_type = 0;
625 device_data.device_name = [0; 30];
626 let test_name3 = b"Some other text\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
627 device_data.device_name[..test_name3.len()].copy_from_slice(test_name3);
628 assert_eq!(
629 device_data.device_type_name(),
630 "Unknown Device (ID: 99, HW: 0)"
631 );
632 }
633}