Browse Source

优化代码,增加发送力反馈

caner 1 year ago
parent
commit
c04a86bc93
2 changed files with 77 additions and 18 deletions
  1. 25 5
      src-tauri/src/lib.rs
  2. 52 13
      src/services/logi.service.ts

+ 25 - 5
src-tauri/src/lib.rs

@@ -1,11 +1,11 @@
 use std::thread;
-use hidapi::HidApi;
+use hidapi::{HidApi,HidDevice};
 use tauri::{Emitter,Window};
 // 全局宏变量
 lazy_static::lazy_static! {
     static ref HIDAPI: HidApi = HidApi::new().expect("Failed to initialize HidApi");
 }
-// 变量
+// TODO PID列表可能不足
 const LOGITECH_VID: u16 = 0x046D;  // 罗技厂商ID
 const G923_PIDS: &[u16] = &[
     0xC262,  // G923 PlayStation
@@ -29,11 +29,12 @@ fn start_reading_data(window: Window) -> Result<(), String> {
     thread::spawn(move || {
         let mut buf = [0u8; 64];
         loop {
-            // 使用带超时的读取(100ms)
-            match device.read_timeout(&mut buf, 100) {
+            // 使用带超时的读取(100ms) match device.read_timeout(&mut buf, 100)
+            // 阻塞读取 match device.read(&mut buf)
+            match device.read_timeout(&mut buf, 100){
                 Ok(n) => {
                     // 处理&发送数据
-                    // TODO 会出现数据是空的情况,系统问题?不确定
+                    // TODO 会出现数据是空的情况,系统问题?不确定
                     let data = &buf[..n];
                     let _ = window.emit("g923-data", format!("{:?}", data));
                 },
@@ -48,6 +49,25 @@ fn start_reading_data(window: Window) -> Result<(), String> {
     Ok(())
 }
 
+// TODO 发送力反馈 暂时用不上
+#[tauri::command]
+fn send_force_feedback(device: HidDevice) {
+    // 构造输出报告缓冲区(64字节,兼容多数设备)
+    let mut buffer = [0u8; 64];
+    
+    // 填充关键字段(根据实际协议调整)
+    buffer[0] = 0x01;   // Report ID
+    buffer[1] = 0x08;   // 力反馈指令
+    buffer[2..4].copy_from_slice(&0x00FFu16.to_le_bytes()); // 强度
+    buffer[4..6].copy_from_slice(&0x0032u16.to_le_bytes()); // 频率
+
+    // 发送输出报告
+    match device.write(&buffer) {
+        Ok(len) => println!("Sent {} bytes: {:?}", len, &buffer[..len]),
+        Err(e) => eprintln!("Error sending output report: {}", e),
+    }
+}
+
 pub fn run() {
     tauri::Builder::default()
         .plugin(tauri_plugin_shell::init())

+ 52 - 13
src/services/logi.service.ts

@@ -10,26 +10,65 @@ export default class LogiService {
       listen('g923-data', (event: { payload: string }) => {
         console.log(' G923 数据:', event)
         const data = this.parseG923Data(event.payload)
+        console.log('解析后的数据:', data)
         this.store.setMqttMessage({ type: 'control', data })
       })
     }).catch((er) => {
-      window.$notification.error({ title: er, duration: 3000 })
+      console.log('罗技eror', er)
+      window.$notification.error({ title: er })
     })
   }
 
-  parseG923Data(data) {
-    // 假设数据是一个数组,例如 [128, 255, 0, 0, ...]
-    const buffer = new Uint8Array(JSON.parse(data))
-    console.log('buff长度', buffer.length)
-    // 解析转向值(假设存储在 buffer[0] 和 buffer[1] 中,小端序)
-    const steeringValue = (buffer[1] << 8) | buffer[0]
+  /**
+   * 解析数据
+   * @param data Array<string>
+   * @returns
+   */
+  parseG923Data(data: string) {
+    try {
+      // 数据: [8, 0, 0, 0, 66, 128, 255, 255, 255, 128, 128, 148]
+      // 下面都是在下标0是8的情况:
+      // 方向盘 :下标 4,5
+      // 左边拨挡: 下标1,值2
+      // 右边拨挡: 下标1,值1
+      // R3: 下标1,值64
+      // L3: 下标1,值128
+      // 回车:下标3,值8
+      // 油门:下标6,值0-255
+      // 刹车:下标7,值0-255
+      // 离合:下标8,值0-255
+      const buffer = new Uint8Array(JSON.parse(data))
+      // 创建DataView以处理字节序和符号
+      const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength)
+      // 解析转向:小端序有符号16位整数(buffer[4]和buffer[5])
+      const steering = view.getInt16(4, true) // true表示小端序
+      const steeringNormalized = steering / 32767 // 归一化到[-1, 1]
+      // 解析油门、刹车、离合:无符号8位整数(0-255 → 0-1)
+      const throttle = view.getUint8(6) / 255 // 油门
+      const brake = view.getUint8(7) / 255 // 刹车
+      const clutch = view.getUint8(8) / 255 // 离合
+      // 按键解析
+      const buffer1 = view.getUint8(1) // 按钮组1(左/右拨挡、R3、L3)
+      const buffer3 = view.getUint8(3) // 按钮组3(回车键)
 
-    // 解析刹车值(假设存储在 buffer[2] 中)
-    const brakeValue = buffer[2]
-
-    return {
-      steering: steeringValue,
-      brake: brakeValue
+      // 使用位掩码判断按键状态
+      const buttons = {
+        leftPaddle: (buffer1 & 0b00000010) !== 0, // 左拨挡(值2 → 二进制第2位)
+        rightPaddle: (buffer1 & 0b00000001) !== 0, // 右拨挡(值1 → 二进制第1位)
+        buttonR3: (buffer1 & 0b01000000) !== 0, // R3(值64 → 二进制第7位)
+        buttonL3: (buffer1 & 0b10000000) !== 0, // L3(值128 → 二进制第8位)
+        enterKey: (buffer3 & 0b00001000) !== 0 // 回车键(值8 → 二进制第4位)
+      }
+      return {
+        steering: steeringNormalized,
+        throttle,
+        brake,
+        clutch,
+        ...buttons
+      }
+    } catch (error) {
+      console.log('数据格式错误', error)
+      return null
     }
   }
 }