pokeys_thread/
builder.rs

1//! Builder for creating device threads
2
3use crate::error::{Result, ThreadError};
4use crate::logging::ThreadLogger;
5use crate::worker::{DeviceWorker, DeviceWorkerImpl};
6use log::info;
7use pokeys_lib::{
8    connect_to_device, connect_to_device_with_serial, connect_to_network_device,
9    NetworkDeviceSummary,
10};
11use std::sync::Arc;
12
13/// Builder for creating device threads
14pub struct ThreadWorkerBuilder {
15    /// Thread ID
16    thread_id: u32,
17    /// Refresh interval in milliseconds
18    refresh_interval: u64,
19    /// Logger
20    logger: Option<Arc<ThreadLogger>>,
21}
22
23impl ThreadWorkerBuilder {
24    /// Create a new thread worker builder
25    pub fn new(thread_id: u32) -> Self {
26        Self {
27            thread_id,
28            refresh_interval: 100, // Default refresh interval: 100ms
29            logger: None,
30        }
31    }
32
33    /// Set the refresh interval
34    pub fn refresh_interval(mut self, interval_ms: u64) -> Self {
35        self.refresh_interval = interval_ms;
36        self
37    }
38
39    /// Set the logger
40    pub fn with_logger(mut self, logger: Arc<ThreadLogger>) -> Self {
41        self.logger = Some(logger);
42        self
43    }
44
45    /// Build a device worker for a USB device
46    pub fn build_usb_device(self, device_index: u32) -> Result<Box<dyn DeviceWorker>> {
47        if let Some(logger) = &self.logger {
48            logger.info(&format!(
49                "Creating USB device thread for device index {}",
50                device_index
51            ));
52        } else {
53            info!(
54                "Creating USB device thread for device index {}",
55                device_index
56            );
57        }
58
59        // Connect to the device to get initial state
60        let device = connect_to_device(device_index).map_err(ThreadError::DeviceError)?;
61
62        // Create the device worker
63        let (mut worker, _command_rx) = DeviceWorkerImpl::new_usb(
64            self.thread_id,
65            &device,
66            device_index,
67            self.refresh_interval,
68        )?;
69
70        // Add logger if available
71        if let Some(logger) = self.logger {
72            worker = worker.with_logger(logger);
73        }
74
75        // Create a boxed worker
76        let mut boxed_worker: Box<dyn DeviceWorker> = Box::new(worker);
77
78        // Start the worker thread
79        boxed_worker.start()?;
80
81        Ok(boxed_worker)
82    }
83
84    /// Build a device worker for a network device
85    pub fn build_network_device(
86        self,
87        device_summary: NetworkDeviceSummary,
88    ) -> Result<Box<dyn DeviceWorker>> {
89        if let Some(logger) = &self.logger {
90            logger.info(&format!(
91                "Creating network device thread for device with serial {}",
92                device_summary.serial_number
93            ));
94        } else {
95            info!(
96                "Creating network device thread for device with serial {}",
97                device_summary.serial_number
98            );
99        }
100
101        // Connect to the device to get initial state
102        let device =
103            connect_to_network_device(&device_summary).map_err(ThreadError::DeviceError)?;
104
105        // Create the device worker
106        let (mut worker, _command_rx) = DeviceWorkerImpl::new_network(
107            self.thread_id,
108            &device,
109            device_summary,
110            self.refresh_interval,
111        )?;
112
113        // Add logger if available
114        if let Some(logger) = self.logger {
115            worker = worker.with_logger(logger);
116        }
117
118        // Create a boxed worker
119        let mut boxed_worker: Box<dyn DeviceWorker> = Box::new(worker);
120
121        // Start the worker thread
122        boxed_worker.start()?;
123
124        Ok(boxed_worker)
125    }
126
127    /// Build a device worker for a device with a specific serial number
128    pub fn build_device_by_serial(
129        self,
130        serial_number: u32,
131        check_network: bool,
132        timeout_ms: u32,
133    ) -> Result<Box<dyn DeviceWorker>> {
134        if let Some(logger) = &self.logger {
135            logger.info(&format!(
136                "Creating device thread for device with serial {}",
137                serial_number
138            ));
139        } else {
140            info!(
141                "Creating device thread for device with serial {}",
142                serial_number
143            );
144        }
145
146        // Connect to the device to get initial state
147        let device = connect_to_device_with_serial(serial_number, check_network, timeout_ms)
148            .map_err(ThreadError::DeviceError)?;
149
150        // Determine device type based on connection type
151        let (mut worker, _command_rx) = match device.get_connection_type() {
152            pokeys_lib::DeviceConnectionType::UsbDevice
153            | pokeys_lib::DeviceConnectionType::FastUsbDevice => {
154                // For USB devices, we need to find the device index
155                // This is a limitation of the current design - we should improve this
156                DeviceWorkerImpl::new_usb(self.thread_id, &device, 0, self.refresh_interval)?
157            }
158            pokeys_lib::DeviceConnectionType::NetworkDevice => {
159                // For network devices, create a summary from the device info
160                let device_summary = pokeys_lib::NetworkDeviceSummary {
161                    serial_number,
162                    ip_address: [0, 0, 0, 0], // This should be improved to get actual IP
163                    host_ip: [0, 0, 0, 0],
164                    firmware_version_major: device.device_data.firmware_version_major,
165                    firmware_version_minor: device.device_data.firmware_version_minor,
166                    firmware_revision: device.device_data.firmware_revision,
167                    user_id: device.device_data.user_id,
168                    dhcp: 0,
169                    hw_type: 0,
170                    use_udp: 0,
171                };
172                DeviceWorkerImpl::new_network(
173                    self.thread_id,
174                    &device,
175                    device_summary,
176                    self.refresh_interval,
177                )?
178            }
179        };
180
181        // Add logger if available
182        if let Some(logger) = self.logger {
183            worker = worker.with_logger(logger);
184        }
185
186        // Create a boxed worker
187        let mut boxed_worker: Box<dyn DeviceWorker> = Box::new(worker);
188
189        // Start the worker thread
190        boxed_worker.start()?;
191
192        Ok(boxed_worker)
193    }
194}