使用 Tauri 应用程序从 Rust 读取 HID 设备

问题描述 投票:0回答:1

我正在尝试使用 Tauri 应用程序中的

hidapi
板条箱读取 HID 设备(条形码扫描仪)。

我想到了这个场景:

  • 在应用程序启动时扫描设备 -> 如果没有,则向 UI 发出事件:
    device-disconnected
  • 如果设备存在,则打开设备并在扫描发生时发出事件:
    device-data
    与有效负载
  • 如果设备断开连接,请从 UI 触发
    Tauri command
    重新扫描设备

现在我有了这个代码

// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

extern crate hidapi;

use hidapi::HidApi;
use tauri::Manager;

#[derive(Clone, serde::Serialize)]
struct Payload {
    message: String,
}

#[tauri::command]
fn detect_barcode_scanner(app: &mut tauri::App) -> () {

    let vid = 0x1234;
    let pid = 0x5678;

    match HidApi::new() {
        Ok(api) => {
            let mut device_found = false;
            
            for device_info in api.device_list() {
                // Check if the scanner is in the list
                if device_info.vendor_id() == vid && device_info.product_id() == pid {
                    device_found = true;
                    if let Ok(device) = device_info.open_device(&api) {
                        println!("Barcode scanner found & opened successfully.");

                        // Allocate mem buffer for data
                        let mut mem_buf = Vec::<u8>::with_capacity(256);

                        // Start reading data
                        loop {
                            match device.read(&mut mem_buf) {
                                Ok(count) => {
                                    let data = &mem_buf[..count];
                                    println!("Scanned data: {:?}", data);
                                    app.emit_all("scanner-data", Payload { message: "Tauri is awesome!".into() }).unwrap();
                                }
                                Err(e) => {
                                    eprintln!("Error reading from HID device: {:?}", e);
                                    break; 
                                } 
                            }
                        }
                    }
                }
            }
            
            if !device_found {
                println!("Barcode scanner not found.");
            }
        }
        Err(e) => {
            eprintln!("Error initializing HID API: {}", e);
        }
    }
}

fn main() {
  tauri::Builder::default()
    .setup(|app|{
        detect_barcode_scanner(app);
        Ok(())
    })
    .invoke_handler(tauri::generate_handler![detect_barcode_scanner])
    .run(tauri::generate_context!())
    .expect("failed to run app");
}

我现在遇到的问题是

emit_all
功能只能在应用程序句柄上使用,因此我从设置功能中调用功能Detect_barcode_scanner。

但这会导致

emit_all
函数发送的事件丢失,因为 UI 尚未准备好。

这也阻止我在设置后保持与设备的连接打开以继续接收消息。

有关如何解决此问题的任何指南/提示?

rust hid tauri
1个回答
0
投票

您希望以

async
的方式以不同的方式管理状态。

Rust 在不共享内存的情况下管理状态的范例与其他语言不同。

我建议做一个稍微简单的版本:

  1. 运行async设置函数来创建扫描仪的实例
  2. 将双工通道传递到您的设置函数中
  3. 从您的设置函数发出消息,您稍后将在设置函数中收到该消息,并通过发出所有(或存储在状态中)进一步传递到您的客户端。

这是一个快速代码(未经测试):

fn main() {
    let (in_tx, in_rx) = mpsc::channel(1);
    let (out_tx, mut out_rx) = mpsc::channel(1);

    tauri::Builder::default()
        .manage(AsyncProcInputTx {
            inner: Mutex::new(async_proc_input_tx),
        })
        .invoke_handler(tauri::generate_handler![your_function_here])
        .setup(|app| {
            tauri::async_runtime::spawn(async move {
                async_process_model(
                    input_rx,
                    out_tx,
                ).await
            });

            let app_handle = app.handle();
            tauri::async_runtime::spawn(async move {
                loop {
                    if let Some(hid_device) = out_rx.recv().await {
                        // your_function_here(hid_device, &app_handle);
                    }
                }
            });

            Ok(())
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}
© www.soinside.com 2019 - 2024. All rights reserved.