code-scanner-driver 0.1.1

Driver for barcode scanners and keyboard input with GTIN validation, async streaming, and burst detection.
Documentation
use tokio::sync::mpsc::Sender;
use rdev::{Event, EventType, Key, listen};
use anyhow::Result;
use std::sync::{Arc, Mutex};
use std::thread;
use std::time::{Duration, Instant};
use crate::event::scanner_event::ScannerEvent;
use crate::event::source::Source;
use crate::util::time::now_ms;

pub fn start_keyboard_worker(tx: Sender<ScannerEvent>) -> Result<()> {
    let buffer = Arc::new(Mutex::new(String::new()));
    let burst_start = Arc::new(Mutex::new(None::<Instant>));
    let last_time = Arc::new(Mutex::new(Instant::now()));

    thread::spawn(move || {
        if let Err(e) = listen(move |event: Event| {
            if let EventType::KeyPress(key) = event.event_type {
                let now = Instant::now();
                let mut last = last_time.lock().unwrap();
                let mut buf = buffer.lock().unwrap();
                let mut start = burst_start.lock().unwrap();

                if now.duration_since(*last) > Duration::from_millis(200) && !buf.is_empty() {
                    buf.clear();
                    *start = None;
                }
                *last = now;

                if buf.is_empty() && key != Key::Return {
                    *start = Some(now);
                }

                if key == Key::Return {
                    if !buf.is_empty() {
                        let s = buf.clone();

                        let ev = ScannerEvent {
                            source: Source::Keyboard,
                            text: Some(s.clone()),
                            raw: s.as_bytes().to_vec(),
                            timestamp: now_ms(),
                        };

                        let _ = tx.blocking_send(ev);

                        buf.clear();
                        *start = None;
                    }
                    return;
                }

                if let Some(ch) = crate::keyboard::keymap::key_to_char(key, event.name.as_deref()) {
                    buf.push(ch);
                }
            }
        }) {
            eprintln!("keyboard listen error: {:?}", e);
        }
    });

    Ok(())
}