Files
HomeAgent/cmd/gui/devicebridge_dll.js
JianFeeeee a024dc3f5f feat: 设备桥共享库 + CLI全能力补齐 + GUI omniparse/computeruse 重构
- 抽取设备桥 WS 协议层为共享库 (internal/devicebridge/client/)
- CLI 补齐 11 项 caps 能力(screensee/screensue/speakeruse/camerasue/...)
- GUI 新增 omniparse 能力(Windows UIA 窗口解析)
- GUI computeruse 改用 koffi 直接调用 user32.dll,不再依赖 PowerShell C# 编译
- GUI computeruse JSON 解析兼容非标准格式 {x:500,y:300}
- 新增 mock-server 用于本地测试设备桥协议
- 新增 GUI DLL 桥接模块 (devicebridge_dll.js)
2026-08-23 20:17:38 +08:00

126 lines
3.5 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// DeviceBridge DLL 桥接模块
// 提供设备桥共享库的 Node.js 封装GUI 通过 FFI 调用 Go 编译的 DLL。
// 优先尝试加载 DLL失败则回退到纯 JS 实现(保留兼容)。
const path = require('path');
const os = require('os');
let koffi = null;
let bridgeLib = null;
let _handle = null;
// DLL 路径
function dllPath() {
const dir = __dirname;
const plat = os.platform();
if (plat === 'win32') {
return path.join(dir, 'devicebridge.dll');
}
// Linux/Mac 使用 .so/.dylib
const ext = plat === 'darwin' ? 'dylib' : 'so';
return path.join(dir, `devicebridge.${ext}`);
}
// 尝试加载 FFI 库
async function loadFFI() {
try {
koffi = require('koffi');
return true;
} catch (e) {
try {
const ffi = require('ffi-napi');
const ref = require('ref-napi');
// 使用 ffi-napi 作为备选
return true;
} catch (e2) {
return false;
}
}
}
// 加载 DLL
function loadDLL() {
const dll = dllPath();
try {
if (koffi) {
return koffi.load(dll);
}
const ffi = require('ffi-napi');
const ref = require('ref-napi');
return ffi.Library(dll, {
'devicebridge_new': ['pointer', ['string', 'string', 'string', 'string', 'pointer', 'int']],
'devicebridge_start': ['int', ['pointer']],
'devicebridge_stop': ['void', ['pointer']],
'devicebridge_free': ['void', ['pointer']],
'devicebridge_connected': ['int', ['pointer']],
'devicebridge_device_id': ['string', ['pointer']],
'devicebridge_send_result': ['int', ['pointer', 'string', 'string', 'string', 'string']],
'devicebridge_send_event': ['void', ['pointer', 'string', 'string']],
'devicebridge_send_status': ['void', ['pointer', 'string']],
'devicebridge_send_data_start': ['void', ['pointer', 'string', 'string', 'string', 'int']],
'devicebridge_send_data_chunk': ['int', ['pointer', 'pointer', 'int']],
'devicebridge_send_data_end': ['void', ['pointer', 'string', 'string', 'string']],
});
} catch (e) {
console.error('[devicebridge-dll] load failed:', e.message);
return null;
}
}
// 设备桥封装
class DeviceBridgeDLL {
constructor() {
this.connected = false;
this.deviceId = '';
this._onCmd = null;
this._onData = null;
}
// 初始化并连接
async start(gateway, token, deviceId, deviceName, caps, info) {
bridgeLib = loadDLL();
if (!bridgeLib) {
throw new Error('DLL not loaded');
}
// 构建 caps 数组
const capsArr = caps.map(c => Buffer.from(c + '\0'));
const capsPtr = Buffer.alloc(8 * capsArr.length);
// 简化:实际 FFI 调用需要更复杂的参数处理
// 这里使用 koffi 方式
if (koffi) {
// 使用 koffi 调用
try {
// TODO: 实现 koffi 调用
throw new Error('koffi not fully implemented');
} catch (e) {
throw e;
}
}
throw new Error('FFI library not available. Install koffi or ffi-napi');
}
stop() {
if (bridgeLib && _handle) {
try {
bridgeLib.devicebridge_stop(_handle);
bridgeLib.devicebridge_free(_handle);
} catch (e) {}
_handle = null;
this.connected = false;
}
}
sendResult(reqId, status, output, error) {
if (!bridgeLib || !_handle) return;
try {
bridgeLib.devicebridge_send_result(_handle, reqId, status, output || '', error || '');
} catch (e) {
console.error('[devicebridge-dll] sendResult error:', e);
}
}
}
module.exports = { DeviceBridgeDLL, loadFFI };