1use std::collections::HashMap;
18use std::path::{Path, PathBuf};
19use std::sync::{Arc, Mutex};
20
21use serde_json::Value;
22use tokio::task::JoinHandle;
23
24use super::rfid::r700::R700;
25use super::rfid::x714::X714;
26
27pub type EventHandler = dyn FnMut(&str, &str, Option<Value>) + Send + 'static;
31pub type SharedEventHandler = Arc<Mutex<Box<EventHandler>>>;
33
34pub enum Device {
39 X714(X714),
40 R700(R700),
41}
42
43impl Clone for Device {
44 fn clone(&self) -> Self {
45 match self {
46 Self::X714(d) => Self::X714(d.clone()),
47 Self::R700(d) => Self::R700(d.clone()),
48 }
49 }
50}
51
52impl Device {
53 pub fn name(&self) -> &str {
54 match self {
55 Self::X714(d) => &d.config.name,
56 Self::R700(d) => &d.config.name,
57 }
58 }
59
60 pub fn device_type(&self) -> &'static str {
61 match self {
62 Self::X714(_) => "X714",
63 Self::R700(_) => "R700_IOT",
64 }
65 }
66
67 pub fn is_connected(&self) -> bool {
68 match self {
69 Self::X714(d) => d.is_connected(),
70 Self::R700(d) => d.is_connected(),
71 }
72 }
73
74 pub fn is_reading(&self) -> bool {
75 match self {
76 Self::X714(d) => d.is_reading(),
77 Self::R700(d) => d.is_reading(),
78 }
79 }
80
81 pub fn serial_number(&self) -> Option<String> {
82 match self {
83 Self::X714(d) => d.serial_number(),
84 Self::R700(d) => d.serial_number(),
85 }
86 }
87
88 pub fn connect_instruction(&self) -> String {
89 match self {
90 Self::X714(d) => d.connect_instruction(),
91 Self::R700(d) => d.connect_instruction(),
92 }
93 }
94
95 pub fn set_event_handler(&mut self, handler: SharedEventHandler) {
96 match self {
97 Self::X714(d) => d.set_event_handler(handler),
98 Self::R700(d) => d.set_event_handler(handler),
99 }
100 }
101
102 pub async fn connect(&self) {
103 match self {
104 Self::X714(d) => d.connect().await,
105 Self::R700(d) => d.connect().await,
106 }
107 }
108
109 pub async fn close(&self) {
110 match self {
111 Self::X714(d) => d.close().await,
112 Self::R700(d) => d.close().await,
113 }
114 }
115
116 pub async fn start_inventory(&self) -> Result<(), String> {
117 match self {
118 Self::X714(d) => d.start_inventory().await,
119 Self::R700(d) => d.start_inventory().await,
120 }
121 }
122
123 pub async fn stop_inventory(&self) -> Result<(), String> {
124 match self {
125 Self::X714(d) => d.stop_inventory().await,
126 Self::R700(d) => d.stop_inventory().await,
127 }
128 }
129
130 pub async fn write_epc(
131 &self,
132 target_identifier: Option<&str>,
133 target_value: Option<&str>,
134 new_epc: &str,
135 password: &str,
136 ) -> Result<(), String> {
137 match self {
138 Self::X714(d) => {
139 d.write_epc(target_identifier, target_value, new_epc, password)
140 .await
141 }
142 Self::R700(d) => {
143 d.write_epc(target_identifier, target_value, new_epc, password)
144 .await
145 }
146 }
147 }
148
149 pub async fn write_gpo(
150 &self,
151 pin: u8,
152 state: bool,
153 control: &str,
154 time_ms: u64,
155 ) -> Result<(), String> {
156 match self {
157 Self::X714(d) => d.write_gpo(pin, state, control, time_ms).await,
158 Self::R700(d) => d.write_gpo(pin, state, control, time_ms as u32).await,
159 }
160 }
161}
162
163#[derive(Debug, Clone)]
167pub struct DeviceInfo {
168 pub name: String,
169 pub device_type: String,
170 pub is_connected: bool,
171 pub is_reading: bool,
172 pub serial_number: Option<String>,
173 pub connect_instruction: String,
174}
175
176pub struct DeviceManager {
192 pub devices: Vec<Device>,
194 devices_path: PathBuf,
196 event_handler: Option<SharedEventHandler>,
198 connect_tasks: Vec<JoinHandle<()>>,
200}
201
202impl DeviceManager {
203 pub fn new<P: AsRef<Path>>(devices_path: P) -> Self {
207 Self {
208 devices: Vec::new(),
209 devices_path: devices_path.as_ref().to_path_buf(),
210 event_handler: None,
211 connect_tasks: Vec::new(),
212 }
213 }
214
215 pub fn with_event_handler(mut self, handler: SharedEventHandler) -> Self {
217 self.event_handler = Some(handler);
218 self
219 }
220
221 pub fn set_event_handler(&mut self, handler: SharedEventHandler) {
223 self.event_handler = Some(handler);
224 }
225
226 pub fn load_devices(&mut self) {
235 self.devices.clear();
236
237 if !self.devices_path.exists() {
239 match std::fs::create_dir_all(&self.devices_path) {
240 Ok(_) => eprintln!("📁 Diretório criado: {}", self.devices_path.display()),
241 Err(e) => {
242 eprintln!(
243 "❌ Não foi possível criar diretório '{}': {e}",
244 self.devices_path.display()
245 );
246 return;
247 }
248 }
249 }
250
251 let entries = match std::fs::read_dir(&self.devices_path) {
252 Ok(e) => e,
253 Err(e) => {
254 eprintln!("❌ Erro ao listar '{}': {e}", self.devices_path.display());
255 return;
256 }
257 };
258
259 for entry in entries.flatten() {
260 let path = entry.path();
261 if path.extension().and_then(|e| e.to_str()) != Some("json") {
262 continue;
263 }
264
265 let filename = path
266 .file_name()
267 .unwrap_or_default()
268 .to_string_lossy()
269 .to_string();
270 let name = filename.trim_end_matches(".json").to_string();
271
272 eprintln!("📄 Lendo '{}'…", filename);
273
274 let content = match std::fs::read_to_string(&path) {
275 Ok(s) => s,
276 Err(e) => {
277 eprintln!("❌ Erro ao ler '{}': {e}", filename);
278 continue;
279 }
280 };
281
282 let raw: HashMap<String, Value> = match serde_json::from_str(&content) {
283 Ok(d) => d,
284 Err(e) => {
285 eprintln!("❌ JSON inválido em '{}': {e}", filename);
286 continue;
287 }
288 };
289
290 let data: HashMap<String, Value> = raw
292 .into_iter()
293 .map(|(k, v)| (k.to_lowercase(), v))
294 .collect();
295
296 let reader_type = match data.get("reader").and_then(|v| v.as_str()) {
297 Some(t) => t.to_string(),
298 None => {
299 eprintln!("⚠️ '{}' não tem campo 'reader' — ignorado", filename);
300 continue;
301 }
302 };
303
304 self.add_device(&name, &reader_type, data);
305 }
306
307 self.assign_event_handler();
308 eprintln!("✅ {} device(s) carregado(s)", self.devices.len());
309 }
310
311 pub fn add_device(&mut self, name: &str, device_type: &str, mut data: HashMap<String, Value>) {
316 data.insert("name".to_string(), Value::String(name.to_string()));
318
319 match device_type.to_uppercase().as_str() {
320 "X714" => match X714::from_map(data) {
321 Ok(d) => {
322 eprintln!(" ✅ X714 '{}' → {}", name, d.connect_instruction());
323 self.devices.push(Device::X714(d));
324 }
325 Err(e) => eprintln!(" ❌ X714 '{}' erro de config: {e}", name),
326 },
327 "R700_IOT" | "R700" => match R700::from_map(data) {
328 Ok(d) => {
329 eprintln!(" ✅ R700 '{}' → {}", name, d.connect_instruction());
330 self.devices.push(Device::R700(d));
331 }
332 Err(e) => eprintln!(" ❌ R700 '{}' erro de config: {e}", name),
333 },
334 other => {
335 eprintln!(
336 " ⚠️ Tipo desconhecido '{}' para '{}' — ignorado",
337 other, name
338 );
339 }
340 }
341 }
342
343 pub fn assign_event_handler(&mut self) {
347 let Some(handler) = &self.event_handler else {
348 return;
349 };
350 for device in &mut self.devices {
351 device.set_event_handler(Arc::clone(handler));
352 }
353 }
354
355 pub async fn connect_devices(&mut self, force: bool) {
363 let active = self
364 .connect_tasks
365 .iter()
366 .filter(|t| !t.is_finished())
367 .count();
368
369 if active > 0 && !force {
370 eprintln!(
371 "ℹ️ {} task(s) de conexão ativas — use force=true para reiniciar",
372 active
373 );
374 return;
375 }
376
377 self.cancel_connect_tasks().await;
378 self.disconnect_devices().await;
379 self.load_devices();
380
381 let mut tasks = Vec::new();
382 for device in &self.devices {
383 let d = device.clone();
384 let name_display = d.connect_instruction();
385 eprintln!("🚀 Conectando '{}'… ({})", d.name(), name_display);
386 let handle = tokio::spawn(async move { d.connect().await });
387 tasks.push(handle);
388 }
389
390 eprintln!("ℹ️ {} task(s) de conexão iniciadas", tasks.len());
391 self.connect_tasks = tasks;
392 }
393
394 pub async fn cancel_connect_tasks(&mut self) {
396 let n = self.connect_tasks.len();
397 for task in self.connect_tasks.drain(..) {
398 task.abort();
399 }
400 if n > 0 {
401 eprintln!("🛑 {} task(s) cancelada(s)", n);
402 }
403 }
404
405 pub async fn disconnect_devices(&mut self) {
407 for device in &self.devices {
408 device.close().await;
409 }
410 self.devices.clear();
411 }
412
413 pub fn len(&self) -> usize {
416 self.devices.len()
417 }
418
419 pub fn is_empty(&self) -> bool {
420 self.devices.is_empty()
421 }
422
423 pub fn get_device_names(&self) -> Vec<String> {
425 self.devices.iter().map(|d| d.name().to_string()).collect()
426 }
427
428 pub fn get_device(&self, name: &str) -> Option<&Device> {
430 self.devices.iter().find(|d| d.name() == name)
431 }
432
433 pub fn get_device_mut(&mut self, name: &str) -> Option<&mut Device> {
435 self.devices.iter_mut().find(|d| d.name() == name)
436 }
437
438 pub fn get_device_info(&self, name: Option<&str>) -> Vec<DeviceInfo> {
442 match name {
443 Some(n) => self
444 .get_device(n)
445 .map(|d| vec![Self::build_info(d)])
446 .unwrap_or_default(),
447 None => self.devices.iter().map(Self::build_info).collect(),
448 }
449 }
450
451 fn build_info(d: &Device) -> DeviceInfo {
452 DeviceInfo {
453 name: d.name().to_string(),
454 device_type: d.device_type().to_string(),
455 is_connected: d.is_connected(),
456 is_reading: d.is_reading(),
457 serial_number: d.serial_number(),
458 connect_instruction: d.connect_instruction(),
459 }
460 }
461
462 pub fn any_device_reading(&self) -> bool {
464 self.devices
465 .iter()
466 .any(|d| d.is_connected() && d.is_reading())
467 }
468
469 pub fn get_serial_number(&self, name: &str) -> Option<String> {
471 let d = self.get_device(name)?;
472 if !d.is_connected() {
473 return None;
474 }
475 d.serial_number()
476 }
477
478 pub async fn start_inventory(&self, name: &str) -> Result<(), String> {
482 let d = self
483 .get_device(name)
484 .ok_or_else(|| format!("device '{}' não encontrado", name))?;
485 if !d.is_connected() {
486 return Err(format!("device '{}' não está conectado", name));
487 }
488 d.start_inventory().await.map_err(|e| {
489 eprintln!("❌ start_inventory '{}': {e}", name);
490 e
491 })
492 }
493
494 pub async fn stop_inventory(&self, name: &str) -> Result<(), String> {
496 let d = self
497 .get_device(name)
498 .ok_or_else(|| format!("device '{}' não encontrado", name))?;
499 if !d.is_connected() {
500 return Err(format!("device '{}' não está conectado", name));
501 }
502 d.stop_inventory().await.map_err(|e| {
503 eprintln!("❌ stop_inventory '{}': {e}", name);
504 e
505 })
506 }
507
508 pub async fn start_inventory_all(&self) -> HashMap<String, bool> {
511 let mut results = HashMap::new();
512 for d in &self.devices {
513 if d.is_connected() {
514 let ok = d.start_inventory().await.is_ok();
515 results.insert(d.name().to_string(), ok);
516 }
517 }
518 results
519 }
520
521 pub async fn stop_inventory_all(&self) -> HashMap<String, bool> {
524 let mut results = HashMap::new();
525 for d in &self.devices {
526 if d.is_connected() {
527 let ok = d.stop_inventory().await.is_ok();
528 results.insert(d.name().to_string(), ok);
529 }
530 }
531 results
532 }
533
534 pub async fn write_epc(
541 &self,
542 name: &str,
543 target_identifier: Option<&str>,
544 target_value: Option<&str>,
545 new_epc: &str,
546 password: &str,
547 ) -> Result<(), String> {
548 let d = self
549 .get_device(name)
550 .ok_or_else(|| format!("device '{}' não encontrado", name))?;
551 if !d.is_connected() {
552 return Err(format!("device '{}' não está conectado", name));
553 }
554 d.write_epc(target_identifier, target_value, new_epc, password)
555 .await
556 }
557
558 pub async fn write_gpo(
563 &self,
564 name: &str,
565 pin: u8,
566 state: bool,
567 control: &str,
568 time_ms: u64,
569 ) -> Result<(), String> {
570 let d = self
571 .get_device(name)
572 .ok_or_else(|| format!("device '{}' não encontrado", name))?;
573 if !d.is_connected() {
574 return Err(format!("device '{}' não está conectado", name));
575 }
576 d.write_gpo(pin, state, control, time_ms).await
577 }
578}