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}