Commit 3b15cbc2 authored by martin hou's avatar martin hou

feat: added compatibility with eason bluetooth

parent 9b63e1a5
......@@ -18,6 +18,11 @@ export type FileInfo = {
signature: string;
};
export type BluetoothDevice = {
name: string;
mac: string;
}
export const enum OS {
Windows = 'Windows',
Linux = 'Linux',
......@@ -114,6 +119,9 @@ declare class Jensen {
setBluetoothPromptPlay: (state: boolean, seconds?: number) => Promise<ReturnStruct['common']>;
writeSerialNumber: (sn: string) => Promise<ReturnStruct['common']>;
sendScheduleInfo: (info: ScheduleInfo[]) => Promise<ReturnStruct['common']>;
scanDevices: (seconds?: number) => Promise<BluetoothDevice[]>;
connectBTDevice: (mac: string, seconds?: number) => Promise<ReturnStruct['common']>;
disconnectBTDevice: (seconds?: number) => Promise<ReturnStruct['common']>;
}
export = Jensen;
{
"name": "jensen",
"version": "1.0.1",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "jensen",
"version": "1.0.1",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"react": "^19.0.0",
......
import { useEffect, useState } from 'react';
import Jensen from '..';
import Jensen, { BluetoothDevice } from '..';
import './index.css';
const jensen = new Jensen();
......@@ -28,6 +28,28 @@ export function Home() {
});
};
let bluetoothDevices: BluetoothDevice[] = [];
const bluetoothScan = async () => {
let devices = await jensen.scanDevices();
console.log(devices);
bluetoothDevices = devices;
}
const connectBTDevice = async () => {
let idstr = prompt('请输入需要连接的设备序号(从0开始):', '');
let did = parseInt(idstr || '');
if (isNaN(did)) return alert('已取消');
let dinfo = bluetoothDevices[did];
if (dinfo == null || dinfo == undefined) return alert('无效序号');
let r = await jensen.connectBTDevice(dinfo.mac);
console.log(r);
}
const disconnectBTDevice = async () => {
let r = await jensen.disconnectBTDevice();
console.log(r);
}
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', alignItems: 'center' }}>
<button style={{ width: '200px', height: '50px' }} onClick={() => jensen.connect()}>
......@@ -36,6 +58,9 @@ export function Home() {
<button style={{ width: '200px', height: '50px' }} onClick={getFilePart}>
get File Part
</button>
<button style={{ width : '200px', height : '50px' }} onClick={bluetoothScan}>Bluetooth Scan</button>
<button style={{ width : '200px', height : '50px' }} onClick={connectBTDevice}>Bluetooth Connect</button>
<button style={{ width : '200px', height : '50px' }} onClick={disconnectBTDevice}>Bluetooth Disconnect</button>
</div>
);
}
......@@ -22,6 +22,9 @@ const SET_SETTINGS = 0x0c;
const GET_FILE_BLOCK = 0x0d;
const FACTORY_RESET = 0xf00b;
const BLUETOOTH_SCAN = 0x1001;
const BLUETOOTH_CMD = 0x1002;
const TEST_SN_WRITE = 0xf007;
const RECORD_TEST_START = 0xf008;
const RECORD_TEST_END = 0xf009;
......@@ -50,7 +53,9 @@ const COMMAND_NAMES = {
[FACTORY_RESET]: 'factory reset',
[TEST_SN_WRITE]: 'test sn write',
[RECORD_TEST_START]: 'record test start',
[RECORD_TEST_END]: 'record test end'
[RECORD_TEST_END]: 'record test end',
[BLUETOOTH_SCAN]: 'bluetooth-scan',
[BLUETOOTH_CMD]: 'bluetooth-cmd'
};
let Logger = null;
......@@ -560,6 +565,25 @@ Jensen.prototype.restoreFactorySettings = async function (seconds) {
return this.send(new Command(RESTORE_FACTORY_SETTINGS).body([0x01, 0x02, 0x03, 0x04]), seconds);
};
Jensen.prototype.scanDevices = async function(seconds) {
if (this.model != 'hidock-p1') return null;
return this.send(new Command(BLUETOOTH_SCAN), seconds || 20);
}
Jensen.prototype.connectBTDevice = async function(mac, seconds) {
if (this.model != 'hidock-p1') return null;
let marr = mac.split('-');
if (marr.length != 6) throw new Error('invalid mac');
let addr = [];
for (let i = 0; i < marr.length; i++) addr[i] = parseInt(marr[i], 16);
return this.send(new Command(BLUETOOTH_CMD).body([0x00].concat(addr)), seconds);
}
Jensen.prototype.disconnectBTDevice = async function(seconds) {
if (this.model != 'hidock-p1') return null;
return this.send(new Command(BLUETOOTH_CMD).body([0x01]), seconds);
}
Jensen.prototype.listFiles = async function () {
let tag = 'filelist';
if (this[tag] != null) return null;
......@@ -1109,11 +1133,40 @@ Jensen.registerHandler(GET_RECORDING_FILE, (msg) => {
};
}
});
Jensen.registerHandler(BLUETOOTH_SCAN, (msg) => {
let nums = ((msg.body[0] & 0xff) << 8) | (msg.body[1] & 0xff);
let devices = [];
let decoder = new TextDecoder('UTF-8');
for (let i = 0, k = 2; i < nums; i++)
{
let len = ((msg.body[k++] & 0xff) << 8) | (msg.body[k++] & 0xff);
let sname = new Uint8Array(len);
for (let f = 0; f < len; f++)
{
sname[f] = msg.body[k++] & 0xff;
}
let mac = [];
for (let f = 0; f < 6; f++)
{
let m = (msg.body[k++]).toString(16).toUpperCase();
mac.push(m.length == 1 ? '0' + m : m);
}
devices.push({
name : decoder.decode(sname),
mac : mac.join('-')
});
}
return devices;
});
Jensen.registerHandler(RECORD_TEST_START, commonMessageParser);
Jensen.registerHandler(RECORD_TEST_END, commonMessageParser);
Jensen.registerHandler(DEVICE_MSG_TEST, commonMessageParser);
Jensen.registerHandler(GET_FILE_BLOCK, commonMessageParser);
Jensen.registerHandler(TEST_SN_WRITE, commonMessageParser);
Jensen.registerHandler(SCHEDULE_INFO, commonMessageParser);
Jensen.registerHandler(BLUETOOTH_CMD, commonMessageParser);
export { Jensen };
......@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react-swc';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: { open: true, hmr: true, port: 6300 }
server: { open: true, hmr: true, port: 6300, host: '0.0.0.0' }
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment