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 = { ...@@ -18,6 +18,11 @@ export type FileInfo = {
signature: string; signature: string;
}; };
export type BluetoothDevice = {
name: string;
mac: string;
}
export const enum OS { export const enum OS {
Windows = 'Windows', Windows = 'Windows',
Linux = 'Linux', Linux = 'Linux',
...@@ -114,6 +119,9 @@ declare class Jensen { ...@@ -114,6 +119,9 @@ declare class Jensen {
setBluetoothPromptPlay: (state: boolean, seconds?: number) => Promise<ReturnStruct['common']>; setBluetoothPromptPlay: (state: boolean, seconds?: number) => Promise<ReturnStruct['common']>;
writeSerialNumber: (sn: string) => Promise<ReturnStruct['common']>; writeSerialNumber: (sn: string) => Promise<ReturnStruct['common']>;
sendScheduleInfo: (info: ScheduleInfo[]) => 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; export = Jensen;
{ {
"name": "jensen", "name": "jensen",
"version": "1.0.1", "version": "1.0.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "jensen", "name": "jensen",
"version": "1.0.1", "version": "1.0.0",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"react": "^19.0.0", "react": "^19.0.0",
......
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import Jensen from '..'; import Jensen, { BluetoothDevice } from '..';
import './index.css'; import './index.css';
const jensen = new Jensen(); const jensen = new Jensen();
...@@ -28,6 +28,28 @@ export function Home() { ...@@ -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 ( return (
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', alignItems: 'center' }}> <div style={{ display: 'flex', flexDirection: 'column', gap: '16px', padding: '16px', alignItems: 'center' }}>
<button style={{ width: '200px', height: '50px' }} onClick={() => jensen.connect()}> <button style={{ width: '200px', height: '50px' }} onClick={() => jensen.connect()}>
...@@ -36,6 +58,9 @@ export function Home() { ...@@ -36,6 +58,9 @@ export function Home() {
<button style={{ width: '200px', height: '50px' }} onClick={getFilePart}> <button style={{ width: '200px', height: '50px' }} onClick={getFilePart}>
get File Part get File Part
</button> </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> </div>
); );
} }
...@@ -22,6 +22,9 @@ const SET_SETTINGS = 0x0c; ...@@ -22,6 +22,9 @@ const SET_SETTINGS = 0x0c;
const GET_FILE_BLOCK = 0x0d; const GET_FILE_BLOCK = 0x0d;
const FACTORY_RESET = 0xf00b; const FACTORY_RESET = 0xf00b;
const BLUETOOTH_SCAN = 0x1001;
const BLUETOOTH_CMD = 0x1002;
const TEST_SN_WRITE = 0xf007; const TEST_SN_WRITE = 0xf007;
const RECORD_TEST_START = 0xf008; const RECORD_TEST_START = 0xf008;
const RECORD_TEST_END = 0xf009; const RECORD_TEST_END = 0xf009;
...@@ -50,7 +53,9 @@ const COMMAND_NAMES = { ...@@ -50,7 +53,9 @@ const COMMAND_NAMES = {
[FACTORY_RESET]: 'factory reset', [FACTORY_RESET]: 'factory reset',
[TEST_SN_WRITE]: 'test sn write', [TEST_SN_WRITE]: 'test sn write',
[RECORD_TEST_START]: 'record test start', [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; let Logger = null;
...@@ -560,6 +565,25 @@ Jensen.prototype.restoreFactorySettings = async function (seconds) { ...@@ -560,6 +565,25 @@ Jensen.prototype.restoreFactorySettings = async function (seconds) {
return this.send(new Command(RESTORE_FACTORY_SETTINGS).body([0x01, 0x02, 0x03, 0x04]), 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 () { Jensen.prototype.listFiles = async function () {
let tag = 'filelist'; let tag = 'filelist';
if (this[tag] != null) return null; if (this[tag] != null) return null;
...@@ -1109,11 +1133,40 @@ Jensen.registerHandler(GET_RECORDING_FILE, (msg) => { ...@@ -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_START, commonMessageParser);
Jensen.registerHandler(RECORD_TEST_END, commonMessageParser); Jensen.registerHandler(RECORD_TEST_END, commonMessageParser);
Jensen.registerHandler(DEVICE_MSG_TEST, commonMessageParser); Jensen.registerHandler(DEVICE_MSG_TEST, commonMessageParser);
Jensen.registerHandler(GET_FILE_BLOCK, commonMessageParser); Jensen.registerHandler(GET_FILE_BLOCK, commonMessageParser);
Jensen.registerHandler(TEST_SN_WRITE, commonMessageParser); Jensen.registerHandler(TEST_SN_WRITE, commonMessageParser);
Jensen.registerHandler(SCHEDULE_INFO, commonMessageParser); Jensen.registerHandler(SCHEDULE_INFO, commonMessageParser);
Jensen.registerHandler(BLUETOOTH_CMD, commonMessageParser);
export { Jensen }; export { Jensen };
...@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react-swc'; ...@@ -4,5 +4,5 @@ import react from '@vitejs/plugin-react-swc';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
plugins: [react()], 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