1use std::collections::HashMap;
7use std::sync::Arc;
8
9use parking_lot::RwLock;
10
11use crate::config::DeviceConfig;
12use crate::device::BoxedDevice;
13use crate::error::{Error, Result};
14use crate::protocol::Protocol;
15use crate::tags::Tags;
16
17pub trait DeviceFactory: Send + Sync {
37 fn protocol(&self) -> Protocol;
39
40 fn create(&self, config: DeviceConfig) -> Result<BoxedDevice>;
42
43 fn create_batch(&self, configs: Vec<DeviceConfig>) -> Result<Vec<BoxedDevice>> {
45 configs.into_iter().map(|c| self.create(c)).collect()
46 }
47
48 fn validate(&self, config: &DeviceConfig) -> Result<()> {
50 if config.id.is_empty() {
51 return Err(Error::Config("Device ID cannot be empty".into()));
52 }
53 if config.name.is_empty() {
54 return Err(Error::Config("Device name cannot be empty".into()));
55 }
56 if config.protocol != self.protocol() {
57 return Err(Error::Config(format!(
58 "Protocol mismatch: expected {:?}, got {:?}",
59 self.protocol(),
60 config.protocol
61 )));
62 }
63 Ok(())
64 }
65
66 fn metadata(&self) -> FactoryMetadata {
68 FactoryMetadata {
69 protocol: self.protocol(),
70 version: "1.0.0".to_string(),
71 description: format!("{:?} device factory", self.protocol()),
72 capabilities: Vec::new(),
73 }
74 }
75}
76
77#[derive(Debug, Clone)]
79pub struct FactoryMetadata {
80 pub protocol: Protocol,
82 pub version: String,
84 pub description: String,
86 pub capabilities: Vec<String>,
88}
89
90pub type BoxedFactory = Box<dyn DeviceFactory>;
92
93pub struct FactoryRegistry {
108 factories: RwLock<HashMap<Protocol, Arc<BoxedFactory>>>,
109}
110
111impl FactoryRegistry {
112 pub fn new() -> Self {
114 Self {
115 factories: RwLock::new(HashMap::new()),
116 }
117 }
118
119 pub fn register<F: DeviceFactory + 'static>(&self, factory: F) -> Result<()> {
121 let protocol = factory.protocol();
122 let mut factories = self.factories.write();
123
124 if factories.contains_key(&protocol) {
125 return Err(Error::Config(format!(
126 "Factory already registered for protocol {:?}",
127 protocol
128 )));
129 }
130
131 factories.insert(protocol, Arc::new(Box::new(factory)));
132 Ok(())
133 }
134
135 pub fn register_boxed(&self, factory: BoxedFactory) -> Result<()> {
137 let protocol = factory.protocol();
138 let mut factories = self.factories.write();
139
140 if factories.contains_key(&protocol) {
141 return Err(Error::Config(format!(
142 "Factory already registered for protocol {:?}",
143 protocol
144 )));
145 }
146
147 factories.insert(protocol, Arc::new(factory));
148 Ok(())
149 }
150
151 pub fn unregister(&self, protocol: Protocol) -> bool {
153 self.factories.write().remove(&protocol).is_some()
154 }
155
156 pub fn get(&self, protocol: Protocol) -> Option<Arc<BoxedFactory>> {
158 self.factories.read().get(&protocol).cloned()
159 }
160
161 pub fn has(&self, protocol: Protocol) -> bool {
163 self.factories.read().contains_key(&protocol)
164 }
165
166 pub fn protocols(&self) -> Vec<Protocol> {
168 self.factories.read().keys().copied().collect()
169 }
170
171 pub fn all_metadata(&self) -> Vec<FactoryMetadata> {
173 self.factories
174 .read()
175 .values()
176 .map(|f| f.metadata())
177 .collect()
178 }
179
180 pub fn create_device(&self, config: DeviceConfig) -> Result<BoxedDevice> {
182 let factory = self
183 .get(config.protocol)
184 .ok_or_else(|| Error::NotSupported(format!("Protocol {:?}", config.protocol)))?;
185
186 factory.validate(&config)?;
187 factory.create(config)
188 }
189
190 pub fn create_devices(&self, configs: Vec<DeviceConfig>) -> Result<Vec<BoxedDevice>> {
192 configs
193 .into_iter()
194 .map(|c| self.create_device(c))
195 .collect()
196 }
197}
198
199impl Default for FactoryRegistry {
200 fn default() -> Self {
201 Self::new()
202 }
203}
204
205pub trait Plugin: Send + Sync {
209 fn name(&self) -> &str;
211
212 fn version(&self) -> &str {
214 "1.0.0"
215 }
216
217 fn description(&self) -> &str {
219 ""
220 }
221
222 fn initialize(&mut self) -> Result<()> {
224 Ok(())
225 }
226
227 fn register_factories(&self, _registry: &FactoryRegistry) -> Result<()> {
229 Ok(())
230 }
231
232 fn shutdown(&mut self) -> Result<()> {
234 Ok(())
235 }
236}
237
238pub type BoxedPlugin = Box<dyn Plugin>;
240
241pub struct PluginManager {
243 plugins: RwLock<Vec<BoxedPlugin>>,
244 registry: Arc<FactoryRegistry>,
245}
246
247impl PluginManager {
248 pub fn new(registry: Arc<FactoryRegistry>) -> Self {
250 Self {
251 plugins: RwLock::new(Vec::new()),
252 registry,
253 }
254 }
255
256 pub fn load<P: Plugin + 'static>(&self, mut plugin: P) -> Result<()> {
258 plugin.initialize()?;
259 plugin.register_factories(&self.registry)?;
260
261 self.plugins.write().push(Box::new(plugin));
262 Ok(())
263 }
264
265 pub fn load_boxed(&self, mut plugin: BoxedPlugin) -> Result<()> {
267 plugin.initialize()?;
268 plugin.register_factories(&self.registry)?;
269
270 self.plugins.write().push(plugin);
271 Ok(())
272 }
273
274 pub fn plugin_count(&self) -> usize {
276 self.plugins.read().len()
277 }
278
279 pub fn plugin_info(&self) -> Vec<PluginInfo> {
281 self.plugins
282 .read()
283 .iter()
284 .map(|p| PluginInfo {
285 name: p.name().to_string(),
286 version: p.version().to_string(),
287 description: p.description().to_string(),
288 })
289 .collect()
290 }
291
292 pub fn registry(&self) -> &Arc<FactoryRegistry> {
294 &self.registry
295 }
296
297 pub fn shutdown_all(&self) -> Result<()> {
299 for plugin in self.plugins.write().iter_mut() {
300 plugin.shutdown()?;
301 }
302 Ok(())
303 }
304}
305
306#[derive(Debug, Clone)]
308pub struct PluginInfo {
309 pub name: String,
311 pub version: String,
313 pub description: String,
315}
316
317#[cfg(test)]
318mod tests {
319 use super::*;
320 use crate::device::{Device, DeviceInfo, DeviceStatistics};
321 use crate::types::{DataPoint, DataPointDef, DataPointId};
322 use crate::value::Value;
323 use async_trait::async_trait;
324
325 struct MockDevice {
327 info: DeviceInfo,
328 }
329
330 impl MockDevice {
331 fn new(id: &str, name: &str) -> Self {
332 Self {
333 info: DeviceInfo::new(id, name, Protocol::ModbusTcp),
334 }
335 }
336 }
337
338 #[async_trait]
339 impl Device for MockDevice {
340 fn info(&self) -> &DeviceInfo {
341 &self.info
342 }
343
344 async fn initialize(&mut self) -> Result<()> {
345 Ok(())
346 }
347
348 async fn start(&mut self) -> Result<()> {
349 Ok(())
350 }
351
352 async fn stop(&mut self) -> Result<()> {
353 Ok(())
354 }
355
356 async fn tick(&mut self) -> Result<()> {
357 Ok(())
358 }
359
360 fn point_definitions(&self) -> Vec<&DataPointDef> {
361 vec![]
362 }
363
364 fn point_definition(&self, _point_id: &str) -> Option<&DataPointDef> {
365 None
366 }
367
368 async fn read(&self, point_id: &str) -> Result<DataPoint> {
369 Ok(DataPoint::new(
370 DataPointId::new(&self.info.id, point_id),
371 Value::F64(0.0),
372 ))
373 }
374
375 async fn write(&mut self, _point_id: &str, _value: Value) -> Result<()> {
376 Ok(())
377 }
378
379 fn statistics(&self) -> DeviceStatistics {
380 DeviceStatistics::default()
381 }
382 }
383
384 struct MockFactory;
386
387 impl DeviceFactory for MockFactory {
388 fn protocol(&self) -> Protocol {
389 Protocol::ModbusTcp
390 }
391
392 fn create(&self, config: DeviceConfig) -> Result<BoxedDevice> {
393 Ok(Box::new(MockDevice::new(&config.id, &config.name)))
394 }
395 }
396
397 struct MockPlugin {
399 name: String,
400 }
401
402 impl MockPlugin {
403 fn new(name: &str) -> Self {
404 Self {
405 name: name.to_string(),
406 }
407 }
408 }
409
410 impl Plugin for MockPlugin {
411 fn name(&self) -> &str {
412 &self.name
413 }
414
415 fn description(&self) -> &str {
416 "Mock plugin for testing"
417 }
418
419 fn register_factories(&self, registry: &FactoryRegistry) -> Result<()> {
420 registry.register(MockFactory)
421 }
422 }
423
424 #[test]
425 fn test_factory_registry() {
426 let registry = FactoryRegistry::new();
427
428 assert!(!registry.has(Protocol::ModbusTcp));
429
430 registry.register(MockFactory).unwrap();
431
432 assert!(registry.has(Protocol::ModbusTcp));
433 assert!(registry.protocols().contains(&Protocol::ModbusTcp));
434 }
435
436 #[test]
437 fn test_factory_create_device() {
438 let registry = FactoryRegistry::new();
439 registry.register(MockFactory).unwrap();
440
441 let config = DeviceConfig {
442 id: "test-001".to_string(),
443 name: "Test Device".to_string(),
444 description: String::new(),
445 protocol: Protocol::ModbusTcp,
446 address: None,
447 points: vec![],
448 metadata: Default::default(),
449 tags: Tags::new(),
450 };
451
452 let device = registry.create_device(config).unwrap();
453 assert_eq!(device.id(), "test-001");
454 }
455
456 #[test]
457 fn test_factory_validation() {
458 let factory = MockFactory;
459
460 let config = DeviceConfig {
462 id: String::new(),
463 name: "Test".to_string(),
464 description: String::new(),
465 protocol: Protocol::ModbusTcp,
466 address: None,
467 points: vec![],
468 metadata: Default::default(),
469 tags: Tags::new(),
470 };
471 assert!(factory.validate(&config).is_err());
472
473 let config = DeviceConfig {
475 id: "test".to_string(),
476 name: "Test".to_string(),
477 description: String::new(),
478 protocol: Protocol::OpcUa,
479 address: None,
480 points: vec![],
481 metadata: Default::default(),
482 tags: Tags::new(),
483 };
484 assert!(factory.validate(&config).is_err());
485 }
486
487 #[test]
488 fn test_plugin_manager() {
489 let registry = Arc::new(FactoryRegistry::new());
490 let manager = PluginManager::new(registry.clone());
491
492 assert_eq!(manager.plugin_count(), 0);
493
494 manager.load(MockPlugin::new("test-plugin")).unwrap();
495
496 assert_eq!(manager.plugin_count(), 1);
497 assert!(registry.has(Protocol::ModbusTcp));
498
499 let info = manager.plugin_info();
500 assert_eq!(info[0].name, "test-plugin");
501 }
502
503 #[test]
504 fn test_duplicate_factory_registration() {
505 let registry = FactoryRegistry::new();
506
507 registry.register(MockFactory).unwrap();
508 let result = registry.register(MockFactory);
509
510 assert!(result.is_err());
511 }
512}