pokeys_thread/worker.rs
1use crate::commands::DeviceCommand;
2use crate::error::{Result, ThreadError};
3use crate::logging::ThreadLogger;
4use crate::state::{SharedDeviceState, ThreadStatus};
5use crate::sync::DeviceSync;
6use crossbeam_channel::{Receiver, Sender, TryRecvError};
7use log::{debug, error, info, warn, LevelFilter};
8use pokeys_lib::{
9 connect_to_device, connect_to_network_device, NetworkDeviceSummary, PoKeysDevice,
10};
11use std::convert::TryInto;
12use std::sync::Arc;
13use std::thread::{self, JoinHandle};
14use std::time::Duration;
15
16/// Device connection type
17#[derive(Debug, Clone)]
18pub enum DeviceType {
19 /// USB device with device index
20 Usb(u32),
21 /// Network device with device summary
22 Network(NetworkDeviceSummary),
23}
24
25/// Device worker that runs in its own thread
26pub trait DeviceWorker {
27 /// Start the worker thread
28 fn start(&mut self) -> Result<()>;
29
30 /// Stop the worker thread
31 fn stop(&mut self) -> Result<()>;
32
33 /// Pause the worker thread
34 fn pause(&mut self) -> Result<()>;
35
36 /// Resume the worker thread
37 fn resume(&mut self) -> Result<()>;
38
39 /// Get the status of the worker thread
40 fn status(&self) -> ThreadStatus;
41
42 /// Get the shared state
43 fn shared_state(&self) -> Arc<SharedDeviceState>;
44
45 /// Send a command to the worker thread
46 fn send_command(&self, command: DeviceCommand) -> Result<()>;
47
48 /// Get the command sender
49 fn command_sender(&self) -> &Sender<DeviceCommand>;
50
51 /// Set the log level
52 fn set_log_level(&mut self, level: LevelFilter) -> Result<()>;
53}
54
55/// Device worker implementation
56pub struct DeviceWorkerImpl {
57 /// Thread ID
58 thread_id: u32,
59 /// Thread handle
60 thread_handle: Option<JoinHandle<()>>,
61 /// Command sender
62 command_tx: Sender<DeviceCommand>,
63 /// Command receiver
64 command_rx: Option<Receiver<DeviceCommand>>,
65 /// Shared device state
66 shared_state: Arc<SharedDeviceState>,
67 /// Refresh interval in milliseconds
68 refresh_interval: u64,
69 /// Device type for reconnection
70 device_type: DeviceType,
71 /// Logger
72 logger: Option<Arc<ThreadLogger>>,
73}
74
75impl DeviceWorkerImpl {
76 /// Create a new device worker for USB device
77 pub fn new_usb(
78 thread_id: u32,
79 device: &PoKeysDevice,
80 device_index: u32,
81 refresh_interval: u64,
82 ) -> Result<(Self, Receiver<DeviceCommand>)> {
83 Self::new(
84 thread_id,
85 device,
86 DeviceType::Usb(device_index),
87 refresh_interval,
88 )
89 }
90
91 /// Create a new device worker for network device
92 pub fn new_network(
93 thread_id: u32,
94 device: &PoKeysDevice,
95 device_summary: NetworkDeviceSummary,
96 refresh_interval: u64,
97 ) -> Result<(Self, Receiver<DeviceCommand>)> {
98 Self::new(
99 thread_id,
100 device,
101 DeviceType::Network(device_summary),
102 refresh_interval,
103 )
104 }
105
106 /// Create a new device worker
107 fn new(
108 thread_id: u32,
109 device: &PoKeysDevice,
110 device_type: DeviceType,
111 refresh_interval: u64,
112 ) -> Result<(Self, Receiver<DeviceCommand>)> {
113 let (command_tx, command_rx) = crossbeam_channel::unbounded();
114
115 let shared_state = Arc::new(SharedDeviceState::new(
116 device.info.clone(),
117 device.device_data.clone(),
118 ));
119
120 // Initialize the shared state with the device data
121 shared_state.update(|state| {
122 state.pins = device.pins.clone();
123 state.encoders = device.encoders.clone();
124 state.pwm = device.pwm.clone();
125 });
126
127 // Create a second receiver for the worker
128 let worker_rx = command_rx.clone();
129
130 Ok((
131 Self {
132 thread_id,
133 thread_handle: None,
134 command_tx,
135 command_rx: Some(worker_rx),
136 shared_state,
137 refresh_interval,
138 device_type,
139 logger: None,
140 },
141 command_rx,
142 ))
143 }
144
145 /// Set the logger
146 pub fn with_logger(mut self, logger: Arc<ThreadLogger>) -> Self {
147 self.logger = Some(logger);
148 self
149 }
150
151 /// Run the worker thread
152 fn run_thread(
153 thread_id: u32,
154 device_type: DeviceType,
155 command_rx: Receiver<DeviceCommand>,
156 shared_state: Arc<SharedDeviceState>,
157 refresh_interval: u64,
158 logger: Option<Arc<ThreadLogger>>,
159 ) {
160 // Use logger if available, otherwise use standard log macros
161 let device_description = match &device_type {
162 DeviceType::Usb(index) => format!("USB device index {}", index),
163 DeviceType::Network(summary) => {
164 format!("network device serial {}", summary.serial_number)
165 }
166 };
167
168 if let Some(logger) = &logger {
169 logger.info(&format!(
170 "Device thread {thread_id} started for {device_description}"
171 ));
172 } else {
173 info!("Device thread {thread_id} started for {device_description}");
174 }
175
176 // Connect to the device
177 let mut device = match &device_type {
178 DeviceType::Usb(device_index) => match connect_to_device(*device_index) {
179 Ok(device) => device,
180 Err(e) => {
181 if let Some(logger) = &logger {
182 logger.error(&format!(
183 "Failed to connect to USB device {device_index}: {e}"
184 ));
185 } else {
186 error!("Failed to connect to USB device {device_index}: {e}");
187 }
188
189 shared_state.update(|state| {
190 state.error_message = Some(format!("Failed to connect to device: {e}"));
191 });
192 shared_state.set_running(false);
193 return;
194 }
195 },
196 DeviceType::Network(device_summary) => {
197 match connect_to_network_device(device_summary) {
198 Ok(device) => device,
199 Err(e) => {
200 if let Some(logger) = &logger {
201 logger.error(&format!(
202 "Failed to connect to network device {}: {e}",
203 device_summary.serial_number
204 ));
205 } else {
206 error!(
207 "Failed to connect to network device {}: {e}",
208 device_summary.serial_number
209 );
210 }
211
212 shared_state.update(|state| {
213 state.error_message = Some(format!("Failed to connect to device: {e}"));
214 });
215 shared_state.set_running(false);
216 return;
217 }
218 }
219 }
220 };
221
222 // Set the thread as running
223 shared_state.set_running(true);
224 shared_state.set_paused(false);
225
226 // Create a device sync
227 let mut device_sync = DeviceSync::new(thread_id, shared_state.clone(), refresh_interval);
228
229 // Initial sync
230 if let Err(e) = device_sync.sync(&mut device) {
231 if let Some(logger) = &logger {
232 logger.error(&format!("Failed to perform initial sync: {}", e));
233 } else {
234 error!("Failed to perform initial sync: {}", e);
235 }
236
237 shared_state.update(|state| {
238 state.error_message = Some(format!("Failed to perform initial sync: {}", e));
239 });
240 }
241
242 // Main loop
243 loop {
244 // Check for commands
245 match command_rx.try_recv() {
246 Ok(command) => {
247 if let Some(logger) = &logger {
248 logger.debug(&format!(
249 "Device thread {} received command: {:?}",
250 thread_id, command
251 ));
252 } else {
253 debug!(
254 "Device thread {} received command: {:?}",
255 thread_id, command
256 );
257 }
258
259 match command {
260 DeviceCommand::Terminate => {
261 if let Some(logger) = &logger {
262 logger.info(&format!("Device thread {} terminating", thread_id));
263 } else {
264 info!("Device thread {} terminating", thread_id);
265 }
266
267 shared_state.set_running(false);
268 break;
269 }
270 DeviceCommand::Pause => {
271 if let Some(logger) = &logger {
272 logger.info(&format!("Device thread {} paused", thread_id));
273 } else {
274 info!("Device thread {} paused", thread_id);
275 }
276
277 shared_state.set_paused(true);
278 }
279 DeviceCommand::Start | DeviceCommand::Restart => {
280 if let Some(logger) = &logger {
281 logger.info(&format!(
282 "Device thread {} started/restarted",
283 thread_id
284 ));
285 } else {
286 info!("Device thread {} started/restarted", thread_id);
287 }
288
289 shared_state.set_running(true);
290 shared_state.set_paused(false);
291 }
292 DeviceCommand::GetStatus => {
293 // Just update the status in the shared state
294 if let Some(logger) = &logger {
295 logger.debug(&format!(
296 "Device thread {} status: {:?}",
297 thread_id,
298 shared_state.status()
299 ));
300 } else {
301 debug!(
302 "Device thread {} status: {:?}",
303 thread_id,
304 shared_state.status()
305 );
306 }
307 }
308 DeviceCommand::SetDigitalOutput { pin, value } => {
309 if let Some(logger) = &logger {
310 logger.debug(&format!(
311 "Setting digital output pin {} to {}",
312 pin, value
313 ));
314 } else {
315 debug!("Setting digital output pin {} to {}", pin, value);
316 }
317
318 if let Err(e) = device.set_digital_output(pin, value) {
319 if let Some(logger) = &logger {
320 logger.error(&format!("Failed to set digital output: {}", e));
321 } else {
322 error!("Failed to set digital output: {}", e);
323 }
324
325 shared_state.update(|state| {
326 state.error_message =
327 Some(format!("Failed to set digital output: {}", e));
328 });
329 } else {
330 // Update the pin state in the shared state
331 shared_state.set_digital_output(pin, value);
332 }
333 }
334 DeviceCommand::SetAnalogOutput { pin, value } => {
335 if let Some(logger) = &logger {
336 logger.debug(&format!(
337 "Setting analog output pin {} to {}",
338 pin, value
339 ));
340 } else {
341 debug!("Setting analog output pin {} to {}", pin, value);
342 }
343
344 if let Err(e) = device.set_analog_output(pin, value) {
345 if let Some(logger) = &logger {
346 logger.error(&format!("Failed to set analog output: {}", e));
347 } else {
348 error!("Failed to set analog output: {}", e);
349 }
350
351 shared_state.update(|state| {
352 state.error_message =
353 Some(format!("Failed to set analog output: {}", e));
354 });
355 } else {
356 // Update the pin state in the shared state
357 shared_state.set_analog_output(pin, value);
358 }
359 }
360 DeviceCommand::SetPwmDuty { channel, duty } => {
361 if let Some(logger) = &logger {
362 logger.debug(&format!(
363 "Setting PWM channel {} duty to {}",
364 channel, duty
365 ));
366 } else {
367 debug!("Setting PWM channel {} duty to {}", channel, duty);
368 }
369
370 // Convert channel (0-5) to pin number (17-22)
371 // PWM channels map: 0->22, 1->21, 2->20, 3->19, 4->18, 5->17
372 let pin = match channel {
373 0 => 22,
374 1 => 21,
375 2 => 20,
376 3 => 19,
377 4 => 18,
378 5 => 17,
379 _ => {
380 if let Some(logger) = &logger {
381 logger.error(&format!("Invalid PWM channel: {}", channel));
382 } else {
383 error!("Invalid PWM channel: {}", channel);
384 }
385 continue;
386 }
387 };
388
389 if let Err(e) = device.set_pwm_duty_cycle_for_pin(pin, duty) {
390 if let Some(logger) = &logger {
391 logger.error(&format!("Failed to set PWM duty cycle: {}", e));
392 } else {
393 error!("Failed to set PWM duty cycle: {}", e);
394 }
395
396 shared_state.update(|state| {
397 state.error_message =
398 Some(format!("Failed to set PWM duty cycle: {}", e));
399 });
400 } else {
401 // Update the PWM state in the shared state
402 shared_state.set_pwm_duty_cycle(channel, duty);
403 }
404 }
405 DeviceCommand::ConfigureServo { pin, config } => {
406 if let Some(logger) = &logger {
407 logger.debug(&format!("Configuring servo on pin {}", pin));
408 } else {
409 debug!("Configuring servo on pin {}", pin);
410 }
411
412 // Store servo configuration in device state
413 // Note: This would typically be stored in a servo configuration map
414 // For now, we'll just log the configuration
415 if let Some(logger) = &logger {
416 logger.info(&format!(
417 "Servo configured on pin {} with config: {:?}",
418 pin, config
419 ));
420 } else {
421 info!("Servo configured on pin {} with config: {:?}", pin, config);
422 }
423 }
424 DeviceCommand::SetServoAngle { pin, angle } => {
425 if let Some(logger) = &logger {
426 logger.debug(&format!(
427 "Setting servo angle on pin {} to {}",
428 pin, angle
429 ));
430 } else {
431 debug!("Setting servo angle on pin {} to {}", pin, angle);
432 }
433
434 // For now, convert angle to PWM duty cycle (simplified implementation)
435 // In a full implementation, this would use stored servo configuration
436 let duty = ((angle / 180.0) * 4095.0) as u32;
437
438 if let Err(e) = device.set_pwm_duty_cycle_for_pin(pin, duty) {
439 if let Some(logger) = &logger {
440 logger.error(&format!("Failed to set servo angle: {}", e));
441 } else {
442 error!("Failed to set servo angle: {}", e);
443 }
444 }
445 }
446 DeviceCommand::SetServoSpeed { pin, speed } => {
447 if let Some(logger) = &logger {
448 logger.debug(&format!(
449 "Setting servo speed on pin {} to {}",
450 pin, speed
451 ));
452 } else {
453 debug!("Setting servo speed on pin {} to {}", pin, speed);
454 }
455
456 // Convert speed (-100 to 100) to PWM duty cycle
457 let duty = (((speed + 100.0) / 200.0) * 4095.0) as u32;
458
459 if let Err(e) = device.set_pwm_duty_cycle_for_pin(pin, duty) {
460 if let Some(logger) = &logger {
461 logger.error(&format!("Failed to set servo speed: {}", e));
462 } else {
463 error!("Failed to set servo speed: {}", e);
464 }
465 }
466 }
467 DeviceCommand::StopServo { pin } => {
468 if let Some(logger) = &logger {
469 logger.debug(&format!("Stopping servo on pin {}", pin));
470 } else {
471 debug!("Stopping servo on pin {}", pin);
472 }
473
474 // Set to neutral position (1.5ms pulse = ~1500 duty cycle)
475 let duty = 1500;
476
477 if let Err(e) = device.set_pwm_duty_cycle_for_pin(pin, duty) {
478 if let Some(logger) = &logger {
479 logger.error(&format!("Failed to stop servo: {}", e));
480 } else {
481 error!("Failed to stop servo: {}", e);
482 }
483 }
484 }
485 DeviceCommand::I2cWrite { address, data } => {
486 if let Some(logger) = &logger {
487 logger.debug(&format!("I2C write to address 0x{:02X}", address));
488 } else {
489 debug!("I2C write to address 0x{:02X}", address);
490 }
491
492 if let Err(e) =
493 pokeys_lib::i2c_write_simple(&mut device, address, &data)
494 {
495 if let Some(logger) = &logger {
496 logger.error(&format!("Failed to write I2C: {}", e));
497 } else {
498 error!("Failed to write I2C: {}", e);
499 }
500 }
501 }
502 DeviceCommand::I2cRead { address, length } => {
503 if let Some(logger) = &logger {
504 logger.debug(&format!("I2C read from address 0x{:02X}", address));
505 } else {
506 debug!("I2C read from address 0x{:02X}", address);
507 }
508
509 match pokeys_lib::i2c_read_simple(&mut device, address, length) {
510 Ok(data) => {
511 if let Some(logger) = &logger {
512 logger.debug(&format!("I2C read {} bytes", data.len()));
513 } else {
514 debug!("I2C read {} bytes", data.len());
515 }
516 }
517 Err(e) => {
518 if let Some(logger) = &logger {
519 logger.error(&format!("Failed to read I2C: {}", e));
520 } else {
521 error!("Failed to read I2C: {}", e);
522 }
523 }
524 }
525 }
526 DeviceCommand::I2cWriteRead {
527 address,
528 write_data,
529 read_length,
530 } => {
531 if let Some(logger) = &logger {
532 logger
533 .debug(&format!("I2C write-read to address 0x{:02X}", address));
534 } else {
535 debug!("I2C write-read to address 0x{:02X}", address);
536 }
537
538 // Perform write then read operation
539 if let Err(e) =
540 pokeys_lib::i2c_write_simple(&mut device, address, &write_data)
541 {
542 if let Some(logger) = &logger {
543 logger.error(&format!("Failed to write I2C: {}", e));
544 } else {
545 error!("Failed to write I2C: {}", e);
546 }
547 } else {
548 match pokeys_lib::i2c_read_simple(&mut device, address, read_length)
549 {
550 Ok(data) => {
551 if let Some(logger) = &logger {
552 logger.debug(&format!("I2C read {} bytes", data.len()));
553 } else {
554 debug!("I2C read {} bytes", data.len());
555 }
556 }
557 Err(e) => {
558 if let Some(logger) = &logger {
559 logger.error(&format!("Failed to read I2C: {}", e));
560 } else {
561 error!("Failed to read I2C: {}", e);
562 }
563 }
564 }
565 }
566 }
567 DeviceCommand::I2cScan => {
568 if let Some(logger) = &logger {
569 logger.debug("Scanning I2C bus");
570 } else {
571 debug!("Scanning I2C bus");
572 }
573
574 // Scan I2C addresses 0x08 to 0x77
575 for addr in 0x08..=0x77 {
576 if pokeys_lib::i2c_read_simple(&mut device, addr, 1).is_ok() {
577 if let Some(logger) = &logger {
578 logger.info(&format!(
579 "Found I2C device at address 0x{:02X}",
580 addr
581 ));
582 } else {
583 info!("Found I2C device at address 0x{:02X}", addr);
584 }
585 }
586 }
587 }
588 DeviceCommand::ConfigureUSPIBridge { config } => {
589 if let Some(logger) = &logger {
590 logger.debug("Configuring uSPIBridge");
591 } else {
592 debug!("Configuring uSPIBridge");
593 }
594
595 // For now, just log the configuration
596 // Full implementation would configure the uSPIBridge hardware
597 if let Some(logger) = &logger {
598 logger.info(&format!(
599 "uSPIBridge configured with {} devices",
600 config.device_count
601 ));
602 } else {
603 info!("uSPIBridge configured with {} devices", config.device_count);
604 }
605 }
606 DeviceCommand::USPIBridgeCommand { command } => {
607 if let Some(logger) = &logger {
608 logger.debug("Sending uSPIBridge command");
609 } else {
610 debug!("Sending uSPIBridge command");
611 }
612
613 // For now, just log the command
614 // Full implementation would send the command via uSPIBridge
615 if let Some(logger) = &logger {
616 logger
617 .debug(&format!("uSPIBridge command: {} bytes", command.len()));
618 } else {
619 debug!("uSPIBridge command: {} bytes", command.len());
620 }
621 }
622 DeviceCommand::SetDigitalOutputsBulk { pin_states } => {
623 if let Some(logger) = &logger {
624 logger.debug(&format!(
625 "Bulk setting {} digital outputs",
626 pin_states.len()
627 ));
628 } else {
629 debug!("Bulk setting {} digital outputs", pin_states.len());
630 }
631
632 for (pin, state) in pin_states {
633 if let Err(e) = device.set_digital_output(pin, state) {
634 if let Some(logger) = &logger {
635 logger.error(&format!(
636 "Failed to set digital output pin {}: {}",
637 pin, e
638 ));
639 } else {
640 error!("Failed to set digital output pin {}: {}", pin, e);
641 }
642 } else {
643 shared_state.set_digital_output(pin, state);
644 }
645 }
646 }
647 DeviceCommand::SetPwmDutiesBulk { channel_duties } => {
648 if let Some(logger) = &logger {
649 logger.debug(&format!(
650 "Bulk setting {} PWM duties",
651 channel_duties.len()
652 ));
653 } else {
654 debug!("Bulk setting {} PWM duties", channel_duties.len());
655 }
656
657 for (channel, duty) in channel_duties {
658 let pin = match channel {
659 0 => 22,
660 1 => 21,
661 2 => 20,
662 3 => 19,
663 4 => 18,
664 5 => 17,
665 _ => continue,
666 };
667
668 if let Err(e) = device.set_pwm_duty_cycle_for_pin(pin, duty) {
669 if let Some(logger) = &logger {
670 logger.error(&format!(
671 "Failed to set PWM channel {}: {}",
672 channel, e
673 ));
674 } else {
675 error!("Failed to set PWM channel {}: {}", channel, e);
676 }
677 } else {
678 shared_state.set_pwm_duty_cycle(channel, duty);
679 }
680 }
681 }
682 DeviceCommand::ReadAnalogInputsBulk { pins } => {
683 if let Some(logger) = &logger {
684 logger.debug(&format!("Bulk reading {} analog inputs", pins.len()));
685 } else {
686 debug!("Bulk reading {} analog inputs", pins.len());
687 }
688
689 // Analog inputs are read during regular refresh cycle
690 // This command just logs the request
691 }
692 DeviceCommand::CheckPinCapability { pin, capability } => {
693 if let Some(logger) = &logger {
694 logger.debug(&format!(
695 "Checking pin {} capability: {}",
696 pin, capability
697 ));
698 } else {
699 debug!("Checking pin {} capability: {}", pin, capability);
700 }
701 }
702 DeviceCommand::ValidatePinOperation { pin, operation } => {
703 if let Some(logger) = &logger {
704 logger.debug(&format!(
705 "Validating pin {} for operation: {}",
706 pin, operation
707 ));
708 } else {
709 debug!("Validating pin {} for operation: {}", pin, operation);
710 }
711 }
712 DeviceCommand::ConfigureEncoder {
713 encoder_index,
714 pin_a,
715 pin_b,
716 enabled,
717 sampling_4x,
718 } => {
719 if let Some(logger) = &logger {
720 logger.debug(&format!(
721 "Configuring encoder {} on pins {} and {}",
722 encoder_index, pin_a, pin_b
723 ));
724 } else {
725 debug!(
726 "Configuring encoder {} on pins {} and {}",
727 encoder_index, pin_a, pin_b
728 );
729 }
730
731 let mut options = pokeys_lib::encoders::EncoderOptions::new();
732 options.enabled = enabled;
733 options.sampling_4x = sampling_4x;
734
735 // Convert u32 to u8 for pin_a and pin_b
736 let pin_a_u8: u8 = match pin_a.try_into() {
737 Ok(val) => val,
738 Err(_) => {
739 if let Some(logger) = &logger {
740 logger.error(&format!(
741 "Pin A value {} is out of range for u8",
742 pin_a
743 ));
744 } else {
745 error!("Pin A value {} is out of range for u8", pin_a);
746 }
747
748 shared_state.update(|state| {
749 state.error_message = Some(format!(
750 "Pin A value {} is out of range for u8",
751 pin_a
752 ));
753 });
754 continue;
755 }
756 };
757
758 let pin_b_u8: u8 = match pin_b.try_into() {
759 Ok(val) => val,
760 Err(_) => {
761 if let Some(logger) = &logger {
762 logger.error(&format!(
763 "Pin B value {} is out of range for u8",
764 pin_b
765 ));
766 } else {
767 error!("Pin B value {} is out of range for u8", pin_b);
768 }
769
770 shared_state.update(|state| {
771 state.error_message = Some(format!(
772 "Pin B value {} is out of range for u8",
773 pin_b
774 ));
775 });
776 continue;
777 }
778 };
779
780 if let Err(e) = device.configure_encoder(
781 encoder_index as u8,
782 pin_a_u8,
783 pin_b_u8,
784 options,
785 ) {
786 if let Some(logger) = &logger {
787 logger.error(&format!("Failed to configure encoder: {}", e));
788 } else {
789 error!("Failed to configure encoder: {}", e);
790 }
791
792 shared_state.update(|state| {
793 state.error_message =
794 Some(format!("Failed to configure encoder: {}", e));
795 });
796 } else {
797 // The encoder state will be updated in the next sync
798 }
799 }
800 DeviceCommand::ResetDigitalCounter { pin } => {
801 if let Some(logger) = &logger {
802 logger.debug(&format!("Resetting digital counter for pin {}", pin));
803 } else {
804 debug!("Resetting digital counter for pin {}", pin);
805 }
806
807 if let Err(e) = device.reset_digital_counter(pin) {
808 if let Some(logger) = &logger {
809 logger
810 .error(&format!("Failed to reset digital counter: {}", e));
811 } else {
812 error!("Failed to reset digital counter: {}", e);
813 }
814
815 shared_state.update(|state| {
816 state.error_message =
817 Some(format!("Failed to reset digital counter: {}", e));
818 });
819 }
820 }
821 DeviceCommand::Custom {
822 request_type,
823 param1,
824 param2,
825 param3,
826 param4,
827 } => {
828 if let Some(logger) = &logger {
829 logger.debug(&format!(
830 "Sending custom request: {:02X} {:02X} {:02X} {:02X} {:02X}",
831 request_type, param1, param2, param3, param4
832 ));
833 } else {
834 debug!(
835 "Sending custom request: {:02X} {:02X} {:02X} {:02X} {:02X}",
836 request_type, param1, param2, param3, param4
837 );
838 }
839
840 if let Err(e) =
841 device.custom_request(request_type, param1, param2, param3, param4)
842 {
843 if let Some(logger) = &logger {
844 logger.error(&format!("Failed to send custom request: {}", e));
845 } else {
846 error!("Failed to send custom request: {}", e);
847 }
848
849 shared_state.update(|state| {
850 state.error_message =
851 Some(format!("Failed to send custom request: {}", e));
852 });
853 }
854 }
855 DeviceCommand::SetLogLevel(level) => {
856 if let Some(logger) = &logger {
857 logger.info(&format!("Setting log level to {:?}", level));
858 } else {
859 info!("Setting log level to {:?}", level);
860 }
861 // The actual log level change is handled by the controller
862 }
863 DeviceCommand::SetPinFunction { pin, pin_function } => {
864 if let Some(logger) = &logger {
865 logger.debug(&format!(
866 "Setting pin {} function to {:?}",
867 pin, pin_function
868 ));
869 } else {
870 debug!("Setting pin {} function to {:?}", pin, pin_function);
871 }
872
873 if let Err(e) = device.set_pin_function(pin, pin_function) {
874 if let Some(logger) = &logger {
875 logger.error(&format!("Failed to set pin function: {}", e));
876 } else {
877 error!("Failed to set pin function: {}", e);
878 }
879
880 shared_state.update(|state| {
881 state.error_message =
882 Some(format!("Failed to set pin function: {}", e));
883 });
884 } else if let Some(logger) = &logger {
885 logger.info(&format!(
886 "Successfully configured pin {} as {:?}",
887 pin, pin_function
888 ));
889 } else {
890 info!("Successfully configured pin {} as {:?}", pin, pin_function);
891 }
892 }
893 DeviceCommand::UpdateModel(model) => {
894 if let Some(logger) = &logger {
895 logger.info(&format!("Updating device model to {}", model.name));
896 } else {
897 info!("Updating device model to {}", model.name);
898 }
899
900 // Update the model in the device
901 device.model = Some(model.clone());
902
903 // Update the model in the shared state
904 shared_state.update(|state| {
905 state.model = Some(model);
906 });
907
908 // Restart the device to apply the new model
909 if let Some(logger) = &logger {
910 logger.info("Restarting device to apply new model");
911 } else {
912 info!("Restarting device to apply new model");
913 }
914
915 // Temporarily set paused to true to avoid device operations during restart
916 shared_state.set_paused(true);
917
918 // Reconnect to the device
919 match device_type {
920 DeviceType::Usb(index) => {
921 match connect_to_device(index) {
922 Ok(new_device) => {
923 device = new_device;
924 // Transfer the model to the new device
925 device.model = shared_state
926 .with_state(|state| state.model.clone());
927
928 if let Some(logger) = &logger {
929 logger.info("Device reconnected successfully");
930 } else {
931 info!("Device reconnected successfully");
932 }
933 }
934 Err(e) => {
935 if let Some(logger) = &logger {
936 logger.error(&format!(
937 "Failed to reconnect to device: {}",
938 e
939 ));
940 } else {
941 error!("Failed to reconnect to device: {}", e);
942 }
943
944 shared_state.update(|state| {
945 state.error_message = Some(format!(
946 "Failed to reconnect to device: {}",
947 e
948 ));
949 });
950 }
951 }
952 }
953 DeviceType::Network(ref summary) => {
954 match connect_to_network_device(summary) {
955 Ok(new_device) => {
956 device = new_device;
957 // Transfer the model to the new device
958 device.model = shared_state
959 .with_state(|state| state.model.clone());
960
961 if let Some(logger) = &logger {
962 logger.info("Device reconnected successfully");
963 } else {
964 info!("Device reconnected successfully");
965 }
966 }
967 Err(e) => {
968 if let Some(logger) = &logger {
969 logger.error(&format!(
970 "Failed to reconnect to device: {}",
971 e
972 ));
973 } else {
974 error!("Failed to reconnect to device: {}", e);
975 }
976
977 shared_state.update(|state| {
978 state.error_message = Some(format!(
979 "Failed to reconnect to device: {}",
980 e
981 ));
982 });
983 }
984 }
985 }
986 }
987
988 // Resume device operations
989 shared_state.set_paused(false);
990 }
991 }
992 }
993 Err(TryRecvError::Empty) => {
994 // No command available, continue
995 }
996 Err(TryRecvError::Disconnected) => {
997 // Command channel disconnected, terminate thread
998 if let Some(logger) = &logger {
999 logger.warn(&format!(
1000 "Device thread {} command channel disconnected, terminating",
1001 thread_id
1002 ));
1003 } else {
1004 warn!(
1005 "Device thread {} command channel disconnected, terminating",
1006 thread_id
1007 );
1008 }
1009
1010 shared_state.set_running(false);
1011 break;
1012 }
1013 }
1014
1015 // If paused, skip the sync
1016 if shared_state.status() == ThreadStatus::Paused {
1017 thread::sleep(Duration::from_millis(100));
1018 continue;
1019 }
1020
1021 // Check if it's time to sync the device state
1022 if device_sync.should_sync() {
1023 if let Err(e) = device_sync.sync(&mut device) {
1024 if let Some(logger) = &logger {
1025 logger.error(&format!("Failed to sync device state: {}", e));
1026 } else {
1027 error!("Failed to sync device state: {}", e);
1028 }
1029 // Continue running even if sync fails
1030 }
1031 }
1032
1033 // Sleep a bit to avoid busy-waiting
1034 thread::sleep(Duration::from_millis(10));
1035 }
1036
1037 if let Some(logger) = &logger {
1038 logger.info(&format!("Device thread {} terminated", thread_id));
1039 } else {
1040 info!("Device thread {} terminated", thread_id);
1041 }
1042 }
1043}
1044
1045impl DeviceWorker for DeviceWorkerImpl {
1046 fn start(&mut self) -> Result<()> {
1047 // Check if the thread is already running
1048 if self.thread_handle.is_some() {
1049 return Err(ThreadError::ThreadAlreadyExists(self.thread_id));
1050 }
1051
1052 // Clone the necessary data for the thread
1053 let thread_id = self.thread_id;
1054 let device_type = self.device_type.clone();
1055 let command_rx = match self.command_rx.take() {
1056 Some(rx) => rx,
1057 None => {
1058 return Err(ThreadError::CommandSendFailed(
1059 "Command receiver already taken".to_string(),
1060 ))
1061 }
1062 };
1063 let shared_state = self.shared_state.clone();
1064 let refresh_interval = self.refresh_interval;
1065 let logger = self.logger.clone();
1066
1067 // Start the thread
1068 let handle = thread::spawn(move || {
1069 Self::run_thread(
1070 thread_id,
1071 device_type,
1072 command_rx,
1073 shared_state,
1074 refresh_interval,
1075 logger,
1076 );
1077 });
1078
1079 self.thread_handle = Some(handle);
1080
1081 Ok(())
1082 }
1083
1084 fn stop(&mut self) -> Result<()> {
1085 // Send terminate command
1086 self.send_command(DeviceCommand::Terminate)?;
1087
1088 // Wait for the thread to finish
1089 if let Some(handle) = self.thread_handle.take() {
1090 handle.join().map_err(|_| ThreadError::ThreadJoinError)?;
1091 }
1092
1093 Ok(())
1094 }
1095
1096 fn pause(&mut self) -> Result<()> {
1097 self.send_command(DeviceCommand::Pause)
1098 }
1099
1100 fn resume(&mut self) -> Result<()> {
1101 self.send_command(DeviceCommand::Start)
1102 }
1103
1104 fn status(&self) -> ThreadStatus {
1105 self.shared_state.status()
1106 }
1107
1108 fn shared_state(&self) -> Arc<SharedDeviceState> {
1109 self.shared_state.clone()
1110 }
1111
1112 fn send_command(&self, command: DeviceCommand) -> Result<()> {
1113 self.command_tx
1114 .send(command)
1115 .map_err(|e| ThreadError::CommandSendFailed(e.to_string()))
1116 }
1117
1118 fn command_sender(&self) -> &Sender<DeviceCommand> {
1119 &self.command_tx
1120 }
1121
1122 fn set_log_level(&mut self, level: LevelFilter) -> Result<()> {
1123 self.send_command(DeviceCommand::SetLogLevel(level))
1124 }
1125}