Commit 7a1aaa43 authored by martin hou's avatar martin hou

feat: 整理测试页面UI,增加自动连接管理

parent 5ebd2b7a
......@@ -11,31 +11,68 @@ button {
outline: none;
border: 1px solid #ccc;
}
#root
{
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
button:hover
{
cursor: pointer;
border: solid 1px #999;
}
.result-container {
.btn-container {
display: flex;
flex-direction: row;
gap: 16px;
padding: 16px;
align-items: center;
flex-wrap: wrap;
/* 移除高度限制,保持自适应 */
}
/* 让#root成为flex容器,纵向排列,撑满body */
#root {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
/* result-container占据剩余空间 */
.result-container {
display: flex;
flex-direction: row;
flex: 1 1 0%; /* 占据剩余空间 */
width: 100%;
min-height: 0; /* 防止溢出 */
padding: 20px;
box-sizing: border-box;
}
.list-container, .log-container {
height: 100%;
}
.list-container {
width: 50%;
height: 100%;
overflow: scroll;
}
.log-container {
width: 50%;
height: 100%;
display: flex;
flex-direction: column;
}
.log-container textarea {
width: 100%;
height: 100%;
min-height: 800px;
min-height: 0;
border: solid 1px #ccc;
border-radius: 5px;
outline: none;
......
......@@ -2,10 +2,13 @@ import { useEffect, useState } from 'react';
import Jensen, { BluetoothDevice } from '..';
import './index.css';
import { Logger } from './Logger'
import { mgr } from './utils/mgr';
const jensen = new Jensen(Logger);
const firmwareVersions = [
{ model: 'hidock-p1:mini', version: '2.1.0', url: 'https://jensen.test.hidock.com/firmwares/mini-2.1.0.bin' },
{ model: 'hidock-h1', version: '5.2.9', url: 'https://jensen.test.hidock.com/firmwares/hidock-h1-5.2.9.bin' },
{ model: 'hidock-h1e', version: '6.2.9', url: 'https://jensen.test.hidock.com/firmwares/hidock-h1e-6.2.9.bin' },
{ model: 'hidock-p1', version: '1.3.4', url: 'https://jensen.test.hidock.com/firmwares/hidock-p1-1.3.4.bin' },
{ model: 'hidock-p1', version: '1.2.18', url: 'https://jensen.test.hidock.com/firmwares/eason-1.2.18.bin' },
{ model: 'hidock-p1', version: '1.2.14', url: 'https://jensen.test.hidock.com/firmwares/eason-v1.2.14.bin' }
];
......@@ -17,8 +20,30 @@ export function Home() {
const [greeting, setGreeting] = useState<string|null>(null);
const [firmwares, setFirmwares] = useState<typeof firmwareVersions|null>(null);
const [logs, setLogs] = useState<string[]>([]);
const [sn, setSn] = useState<string|null>(null);
mgr.onconnectionstatechanged((state, dinfo) => {
console.log('onconnectionstatechanged', state, dinfo);
// alert(JSON.stringify(dinfo));
});
mgr.onautoconnect((dinfo) => {
// console.log('onautoconnect', dinfo);
setSn(dinfo.sn);
// alert(JSON.stringify(dinfo));
});
const getJensen = () => {
if (sn == null) return alert('Please connect to a device first'), null;
return mgr.getInstance(sn);
}
useEffect(() => {
// console.log(mgr);
mgr.tryconnect();
}, []);
useEffect(() => {
/*
jensen.connect();
jensen.onconnect = () => {
console.log('connect successfully');
......@@ -32,6 +57,7 @@ export function Home() {
console.log('getDeviceInfo error', e);
});
};
*/
// jensen.onerror = (e) => {
// console.log('onerror', e);
// alert('此设备已经在其它已打开的HiNotes网页上建立连接');
......@@ -54,19 +80,20 @@ export function Home() {
};
}, []);
const getFilePart = () => {
const file = files[4];
const secondsLength = Math.ceil(file.length / file.duration) * 1000;
console.time('!!!time');
jensen.getFilePart(file.name, secondsLength * 600, (res) => {
if (res instanceof Uint8Array) {
console.timeEnd('!!!time');
const info = async () => {
// alert(sn);
let jensen = getJensen();
if (jensen == null) return;
// console.log('jensen -> ', jensen);
let info = await jensen?.getDeviceInfo();
// alert(JSON.stringify(info));
Logger.info('jensen', 'info', 'Device Info: ' + JSON.stringify(info));
}
});
};
let bluetoothDevices: BluetoothDevice[] = [];
const bluetoothScan = async () => {
let jensen = getJensen();
if (jensen == null) return;
setDevices([]);
setGreeting('scan started at: ' + new Date().toLocaleString());
let devices = await jensen.scanDevices();
......@@ -74,32 +101,25 @@ export function Home() {
setDevices(devices);
setGreeting(null)
}
const connecty = async () => {
const usb = (navigator as any).usb;
let conn = await usb.requestDevice({
filters: [{ vendorId: 0x10d6 }, { vendorId: 0x3887 }]
});
if (conn == null) return null;
// if (conn.opened) throw new Error('device_already_opened');
await conn.open();
let jensen = new Jensen(Logger, conn);
jensen.onerror = (e) => {
console.log('onerror', e);
alert('This device has already been connected to another HiNotes webpage');
};
await jensen.initialize();
let dinfo = await jensen.getDeviceInfo();
if (dinfo)
console.log('dinfo', dinfo);
return null;
}
const connect = async () => {
await jensen.connect();
alert(jensen.getModel() + ' connected')
// await jensen.connect();
// alert(jensen.getModel() + ' connected')
let info = await mgr.connect();
if (info && info.sn)
{
setSn(info.sn);
Logger.info('jensen', 'connect', info.sn + ' connected');
}
else
{
alert('connect failed');
}
}
const disconnectBTDevice = async () => {
let jensen = getJensen();
if (jensen == null) return;
let r = await jensen.disconnectBTDevice();
console.log(r);
}
......@@ -127,24 +147,23 @@ export function Home() {
}
const doConnectBluetooth = async (mac:string) => {
// alert(mac);
let jensen = getJensen();
if (jensen == null) return;
let rst = await jensen.connectBTDevice(mac, 10);
alert('connect: ' + rst.result);
}
const getTime = async () => {
let jensen = getJensen();
if (jensen == null) return;
let time = await jensen.getTime();
// alert(JSON.stringify(time));
Logger.info('jensen', 'getTime', 'Time: ' + JSON.stringify(time));
}
const info = async () => {
let info = await jensen.getDeviceInfo();
// alert(JSON.stringify(info));
Logger.info('jensen', 'info', 'Device Info: ' + JSON.stringify(info));
}
const listFiles = async () => {
let jensen = getJensen();
if (jensen == null) return;
let fc = await jensen.getFileCount();
// alert(fc?.count);
let files = await jensen.listFiles();
......@@ -153,11 +172,14 @@ export function Home() {
}
const getBluetoothStatus = async () => {
let jensen = getJensen();
if (jensen == null) return;
let info = await jensen.getBluetoothStatus();
// alert(JSON.stringify(info));
Logger.info('jensen', 'getBluetoothStatus', 'Bluetooth: ' + JSON.stringify(info));
}
/*
const readFilePartial = async() => {
if (files.length == 0) return alert('You don\'t have any recording files, or you haven\'t queried the file list');
let s0 = prompt('Please Input the File Index (Start from 0):', '0');
......@@ -176,8 +198,11 @@ export function Home() {
let data = await jensen.readFile(file.name, offset, length);
console.log(data);
}
*/
const updateDeviceTone = async () => {
let jensen = getJensen();
if (jensen == null) return;
let resp = await jensen.requestToneUpdate('826d9bac0b535e7babe02b389327a9f2', 1050688);
if (resp.code != 0x00) return alert(resp.result);
......@@ -197,7 +222,8 @@ export function Home() {
}
const updateUAC = async () => {
// 92e66fd8cfd36f09c83fc61491899307 1024
let jensen = getJensen();
if (jensen == null) return;
let resp = await jensen.requestUACUpdate('92e66fd8cfd36f09c83fc61491899307', 1024);
if (resp.code != 0x00) return alert(resp.result);
......@@ -217,6 +243,8 @@ export function Home() {
}
const batteryStatus = async () => {
let jensen = getJensen();
if (jensen == null) return;
let status = await jensen.getBatteryStatus(5);
// alert(JSON.stringify(status));
Logger.info('jensen', 'batteryStatus', 'Battery: ' + JSON.stringify(status));
......@@ -239,6 +267,8 @@ export function Home() {
}
const get_file = () => {
let jensen = getJensen();
if (jensen == null) return;
let recvBytes = 0;
let stime = new Date().getTime();
jensen.getFile(filename, filelength, function(data) {
......@@ -254,64 +284,48 @@ export function Home() {
});
}
const writeSN = async () => {
let nsn = prompt('Please Input the New SN:', '');
if (nsn && nsn.match(/^HD(H1|1E|P1|PM)\w{9}$/gi))
{
let rst = await jensen.writeSerialNumber(nsn);
alert(rst.result);
}
}
const connectx = async () => {
const usb = (navigator as any).usb;
usb.onconnect = (evt: any) => {
console.log(evt);
}
usb.getDevices().then(async (devices: any[]) => {
for (let i = 0; i < devices.length; i++)
{
let dev = devices[i];
await dev.open();
let jensen = new Jensen(Logger, dev);
await jensen.initialize();
let rst = await jensen.getDeviceInfo();
console.log(rst);
}
});
}
/*
const test = async () => {
await jensen.reconnect();
let rst = await jensen.getDeviceInfo();
if (rst) alert(rst.sn + ' reconnected...');
else alert('Something went wrong...');
}
*/
const setWebUSBTimeout = async () => {
let jensen = getJensen();
if (jensen == null) return;
let ts = prompt('Please Input the Timeout (ms):', '10000');
if (ts === undefined || ts === null) return;
let timeout = parseInt(ts);
if (isNaN(timeout) || timeout <= 0) return alert('Please Input the Correct Timeout');
await jensen.setWebUSBTimeout(timeout, 30);
alert('Set Timeout Success');
Logger.info('jensen', 'setWebUSBTimeout', 'Set Timeout Success');
}
const getWebUSBTimeout = async () => {
let jensen = getJensen();
if (jensen == null) return;
let rst = await jensen.getWebUSBTimeout(5);
alert(JSON.stringify(rst));
// alert(JSON.stringify(rst));
Logger.info('jensen', 'getWebUSBTimeout', 'WebUSB Timeout: ' + JSON.stringify(rst));
}
const listFirmwares = async () => {
let jensen = getJensen();
if (jensen == null) return;
let model = jensen.getModel();
let versions = firmwareVersions.filter((item) => item.model == model);
setFirmwares(versions);
}
const updateFirmware = async (version: string, url: string) => {
let jensen = getJensen();
if (jensen == null) return;
// let rst = await jensen.requestFirmwareUpgrade(version, url);
// alert(JSON.stringify(rst));
alert('ready to update firmware, do not close/refresh this page, and wait for the update to complete');
if (!confirm('Ready to update firmware, DO NOT close/refresh this page, and wait for the update to complete.\n\n Confirm to continue')) return;
// 版本号类似于1.2.3,需要转换为0x010203
// 将类似于"1.2.3"的字符串转换为0x010203的数值
let versionNumber = 0;
......@@ -362,9 +376,21 @@ export function Home() {
xhr.send();
}
const turnPopupOn = async () => {
let jensen = getJensen();
if (jensen == null) return;
// await jensen.();
}
const turnPopupOff = async () => {
let jensen = getJensen();
if (jensen == null) return;
// await jensen.turnPopupOff();
}
return (
<>
<div style={{ display: 'flex', flexDirection: 'row', gap: '16px', padding: '16px', alignItems: 'center', flexWrap: 'wrap' }}>
<div className="btn-container" style={{ display: 'flex', flexDirection: 'row', gap: '16px', padding: '16px', alignItems: 'center', flexWrap: 'wrap' }}>
<button onClick={connect}>Connect</button>
<button onClick={info}>Info</button>
<button onClick={getTime}>Get Time</button>
......@@ -379,6 +405,8 @@ export function Home() {
<button onClick={setWebUSBTimeout}>Set Timeout</button>
<button onClick={getWebUSBTimeout}>Get Timeout</button>
<button onClick={listFirmwares}>Firmewares</button>
<button onClick={turnPopupOn}>Turn Popup On</button>
<button onClick={turnPopupOff}>Turn Popup Off</button>
</div>
<div className="result-container">
<div className="list-container">
......
import Jensen, { DeviceInfo, ScheduleInfo } from "../../";
import { Logger } from "../Logger";
// 指令参数
export type CommandOptions = {
exclusive?: boolean; // 是否排它性的,在排它性的事务执行期间,其它所有的新事务都不再等待而是直接返回错误
expires?: number; // 超时时长
retry?: number; // 重试次数
wait?: number; // 等待前一个事务完结的最大时长
reconnect?: boolean; // 是否重连来确保事务的成功
params?: any[]; // 原方法的参数
}
// 指令代理函数
export type CommandProxy = (jensen: Jensen | null) => Promise<any> | undefined;
// 指令请求
export type CommandRequest = {
id: string;
command: CommandProxy;
options: CommandOptions;
createTime: number;
}
export type CommandPromise = {
id: string;
resolve: (value:any) => void;
reject: (error:any) => void;
timeout: number;
}
// 定时任务
export type ScheduledTask = {
interval: number;
command: CommandProxy;
onComplete?: (data: any) => void;
}
// 定时任务信息,增加了执行结果的记录
type ScheduledTaskInfo = {
interval: number;
lastExecuteTime: number;
executedCount: number;
command: CommandProxy;
onComplete?: (data: any) => void;
}
type AutoConnectEventHandler = (dinfo: DeviceInfo) => void;
type ConnectionEventHandler = (state: ConnectionStatus, dinfo: DeviceInfo | string | null) => void;
// 连接状态枚举
export type ConnectionStatus = 'connect-timeout' | 'init' | 'connected' | 'reconnected' | 'disconnected';
// exec('set-time', { exclusive: false, expires: 5, })
// setTime(false, true, new Date(), 5)
//
// 连接管理
export class ConnectionManager
{
private logger: typeof Logger;
private connections: Map<string, Jensen>;
private onautoconnectEventListener: AutoConnectEventHandler | null = null;
private onconnectionstatechangedListener: ConnectionEventHandler | null = null;
constructor (_logger: typeof Logger) {
this.logger = _logger;
this.connections = new Map<string, Jensen>();
this.registerUSBEventListener();
}
async registerUSBEventListener () {
const usb = (navigator as any).usb;
const self = this;
usb.onconnect = (evt: any) => {
try
{
let dev = evt.device;
if (dev.vendorId != 0x10d6 && dev.vendorId != 0x3887) return;
self._connect(dev);
}
catch(ex)
{
this.logger.error('jensen', 'onconnect', String(ex));
}
}
usb.ondisconnect = (evt: any) => {
try
{
let dev = evt.device;
if (dev.vendorId != 0x10d6 && dev.vendorId != 0x3887) return;
self._disconnect(dev);
}
catch(ex)
{
this.logger.error('jensen', 'ondisconnect', String(ex));
}
}
}
// 尝试连接,遍历所有的WebUSB设备,如果是HiDock设备,则直接建立连接,并且还要
async tryconnect () {
const usb = (navigator as any).usb;
const self = this;
usb.getDevices().then(async (devices: any[]) => {
for (let i = 0; i < devices.length; i++)
{
let dev = devices[i];
if (dev.opend) continue;
if (dev.vendorId != 0x10d6 && dev.vendorId != 0x3887) continue;
// console.log('auto connect', dev);
self.logger.info('jensen', 'tryconnect', 'VID: ' + dev.vendorId + ', PID: ' + dev.productId);
// 使用dev创建新的Jensen实例
try
{
self._connect(dev);
}
catch(ex)
{
self.logger.error('jensen', 'tryconnect', String(ex));
}
}
});
}
// 连接事件
private async _onstatechanged (state: ConnectionStatus, jensen: Jensen) {
}
// 当设备断开连接时触发,如果设备是之前已经连接过的,那还需要触发ondisconnect事件
private async _disconnect(dev: any) {
let self = this;
this.connections.forEach((j, k) => {
let ud = j.getUSBDevice();
if (ud == dev)
{
// console.log(k + ' disconnected...');
self.logger.info('jensen', 'ondisconnect', k + ' disconnected');
self.onconnectionstatechangedListener?.('disconnected', k);
}
});
}
// 当设备连接时触发,如果设备是之前已经连接过的,那还需要触发onconnect事件
private async _connect (dev: any) {
await dev.open();
let inst = new Jensen(Logger, dev);
this.logger.info('jensen', 'auto-connect', 'initialize');
await inst.initialize();
this.onconnectionstatechangedListener?.('init', inst.getModel());
let dinfo: DeviceInfo | null = null;
for (let i = 0; i < 30; i++)
{
try
{
dinfo = await inst.getDeviceInfo(5);
if (dinfo == null)
{
inst.reconnect();
await sleep(100);
continue;
}
break;
}
catch(e)
{
// ...
}
}
if(dinfo == null) {
console.log('dinfo is null', dev);
}
if(dinfo == null && dev.opened) {
this.onconnectionstatechangedListener?.('connect-timeout', inst.getModel());
try {
dev.close();
dev.forget();
} catch (error) {
// do nothing
}
return;
}
this.logger.info('jensen', 'auto-connect', JSON.stringify(dinfo));
if (dinfo)
{
// 如果是之前已连接的设备,那就需要触发onconnect事件
if (this.connections.has(dinfo.sn))
{
this.connections.set(
dinfo.sn,
// new CommandManager(dinfo, inst)
inst
);
this.logger.info('jensen', 'onconnect', dinfo.sn + ' reconnected');
// let jensen = this.connections.get(dinfo.sn);
// jensen?.setUSBDevice(dev);
this.onconnectionstatechangedListener?.('reconnected', dinfo);
return;
}
this.connections.set(
dinfo.sn,
// new CommandManager(dinfo, inst)
inst
);
try
{
this.onautoconnectEventListener?.(dinfo);
this.onconnectionstatechangedListener?.('connected', dinfo);
}
catch(err)
{
this.logger.error('jensen', 'autoconnect', String(err));
}
}
}
onautoconnect (eventListener: AutoConnectEventHandler) {
this.onautoconnectEventListener = eventListener;
}
// 这个方法用于管理 连接/断开连接 的回调
onconnectionstatechanged (eventHandler: ConnectionEventHandler)
{
this.onconnectionstatechangedListener = eventHandler;
}
// 获取一个Jensen实例
getInstance(tag: string) {
return this.connections.get(tag);
}
// 设置一个Jensen实例
setInstance(tag: string, jensen: Jensen, oldTag: string | null = null) {
if (oldTag) this.connections.delete(oldTag);
this.connections.set(tag, jensen);
}
// 主动连接新设备,如果没有连接成功或是未连接,则直接返回null,如果用户选择的是已连接的设备,则直接抛出异常
// 但是异常的表现形式需要另外商量沟通
async connect () {
const usb = (navigator as any).usb;
let self = this;
let conn = await usb.requestDevice({
filters: [{ vendorId: 0x10d6 }, { vendorId: 0x3887 }]
});
if (conn == null) return null;
if (conn.opened) return Logger.error('jensen', 'connect', 'device already opened');
await conn.open();
let jensen = new Jensen(self.logger, conn);
jensen.onerror = (err) => {
self.logger.error('jensen', 'connect error', String(err));
// myMessage.error(i18n.t('connection.error'), 10000);
}
await jensen.initialize();
let dinfo = await jensen.getDeviceInfo();
// @ts-ignore
jensen.onerror = null;
if (dinfo)
{
self.connections.set(
dinfo.sn,
// new CommandManager(dinfo, inst)
jensen
);
return dinfo
}
return null;
}
// 关闭连接
async close (sn: string) {
let jensen = this.getInstance(sn);
if (jensen) jensen.disconnect();
this.connections.delete(sn);
}
}
// 指令管理/代理
class CommandManager
{
// 设备信息
private serialNumber: string | null = null;
// 命令队列
private commands:CommandRequest[] = [];
// 指令Promise响应
private directives: Map<string, CommandPromise> = new Map<string, CommandPromise>();
// 定时任务
private tasks: ScheduledTaskInfo[] = [];
// 是否暂停定时任务
private suspendTimer: boolean = false;
// Jensen实例
private jensen: Jensen | null = null;
// 当前事务
private currentTask: String | null = null;
constructor(dinfo: DeviceInfo, jensen: Jensen)
{
// TODO: 要不要完全保存deviceInfo?
this.serialNumber = dinfo.sn;
this.jensen = jensen;
// 开启定时器
let self = this;
window.setInterval(function() {
self._executeTimer();
}, 1000);
}
dump () {
// TODO: 完成内部成员的状态输出,用于跟踪连接和事务状态
console.log('###############################################################');
console.log('SerialNumber', this.serialNumber);
console.log('Tasks', this.tasks);
console.log('Commands', this.commands);
console.log('SuspendTimer', this.suspendTimer);
console.log('Jensen Instance', this.jensen);
}
setup () {
// 在连接初次建立时需要做的初始化工作,是不是放在这里还没有想好
}
// onconnect事件如何触发?
// 是不是应该全局唯一触发?好像至少多少时间上就应该重新触发一次
// 或者是每次触发,然后可以被别的地方接管走
// 另外,还有一个问题,如果断开了连接再次连接上来,会话都不同了,还是要按SN做标识,否则多连接管理会出问题
// 增加一个新指令消息
// 怎么样触发新指令呢?
async getDeviceInfo(secs?: number) {
// 当前是否可以执行?
// 我是不是要分一下组?
// 我是不是要加一个模式转换的方法?
return this.jensen?.getDeviceInfo(secs);
// return this.request((jensen) => jensen?.getDeviceInfo(), { reconnect: false });
}
getSerialNumber () {
return this.serialNumber;
}
// 更改模式,要不要超时时长?在超过多长时间后要销毁或者说是恢复过去?
// 1. 当前是什么模式
// 2. 请求指令的是来自于哪个模式?
// 3. 整一个事务控制吧
// 事务开始或结束,不传参数就是事务结束了
// 对于每一个事务而言,应该要尽量确保它执行的成功的,包括重连尝试
async begin(secs: number = 5) {
// 如果应用端尝试变更事务切换不过去,那就应该一直等
// 这里是不是要弄一个可以打断的?如果事务与当前事务一致,又应该怎么办?还是要阻止吧?
// 结束事务
if (this.currentTask)
{
throw new Error("pending task: " + this.currentTask);
}
let tid = this.uuid();
this.currentTask = tid;
return tid;
}
end (id: string) {
if (this.currentTask != id) throw new Error('invalid task: ' + this.currentTask + ' --> ' + id);
this.currentTask = null;
}
// 开始/停止定时任务
// 但是如果停止的话,也只是停止下一轮的执行,要不要等待全部停止完成再说?
startTimer () {
this.suspendTimer = false;
}
stopTimer() {
this.suspendTimer = true;
}
private async _executeTimer () {
if (this.suspendTimer) return;
// 遍历所有的定时器任务
for (let i = 0; i < this.tasks.length; i++)
{
let item = this.tasks[i];
let now = new Date().getTime() / 1000;
if (now - item.lastExecuteTime < item.interval) continue;
try
{
let rst = await item.command.apply(null, [this.jensen]);
item.onComplete?.apply(null, [rst]);
/*
item.command.apply(null, [this.jensen])?.then((rst) => {
item.onComplete?.apply(null, [ rst ]);
});
*/
}
catch(ex)
{
console.error(ex);
}
finally
{
item.lastExecuteTime = now;
}
}
}
// 注册定时任务,返回值为它在列表中的索引位置,可能后面有要解除定时执行的需要,先预留一下
// 这里有个问题,我要如何完成回调呢?
async registerTimer(task: ScheduledTask) {
let len = this.tasks.length;
this.tasks.push({
interval: task.interval,
command: task.command,
lastExecuteTime: 0,
executedCount: 0
});
return len;
}
// 指令分两种,有复杂结构的返回值的或是普通boolean类型的两种
async request (func: CommandProxy, opts: CommandOptions) {
// TODO: 需要在这里注册一个Promise
let self = this;
let rid = this.uuid();
let future = new Promise((resolve, reject) => {
self.directives.set(rid, {
id: rid,
resolve: resolve,
reject: reject,
timeout: opts.expires || 5
});
});
this.commands.push({ command: func, id: rid, options: opts, createTime: new Date().getTime() });
return future;
}
// 需要怎么样持续的执行呢?
async execute(func: CommandProxy, opts: CommandOptions) {
let tid = await this.begin(opts.wait);
try
{
let args: any[] | undefined = opts.params;
let execCount = 0;
let maxTries = (opts.retry || 0) + 1;
do {
execCount += 1;
try
{
let rst: any = await func(this.jensen);
if (rst) return rst;
if (opts.reconnect)
{
// TODO: 连接重新建立
this.logger.info('jensen', 'execute', 'try reconnect');
}
}
catch(ex)
{
console.error(ex);
}
}
while (execCount < maxTries);
}
finally
{
this.end(tid);
}
}
private async tryReconnect()
{
try
{
// TODO: 需要准备一个新的reconnect方法,使用同一个WebUSB实例来close/open来实现重连,否则必然会乱掉
this.jensen?.reconnect();
}
catch(ex)
{
console.error(ex);
}
}
async getTime (timeout?: number) {
return this.jensen?.getTime(timeout);
}
async setTime (date: Date, timeout?: number) {
return this.jensen?.setTime(date, timeout);
}
async getRecordingFile () {
return this.jensen?.getRecordingFile();
}
async getFileCount (timeout?: number) {
return this.jensen?.getFileCount(timeout);
}
async listFiles (timeout?: number) {
return this.jensen?.listFiles(timeout);
}
async readFile (fname: string, offset: number, length: number) {
return this.jensen?.readFile(fname, offset, length);
}
async getFile (fileName: string, length: number, on?: (msg: Uint8Array | 'fail') => void, onprogress?: (size: number) => void) {
return this.jensen?.getFile(fileName, length, on, onprogress);
}
async getFilePart (fileName: string, length: number, on?: (msg: Uint8Array | 'fail') => void, onprogress?: (size: number) => void) {
return this.jensen?.getFilePart(fileName, length, on, onprogress);
}
async getFileBlock (fileName: string, length: number, on?: (msg: Uint8Array | 'fail') => void) {
return this.jensen?.getFileBlock(fileName, length, on);
}
async requestFirmwareUpgrade (vn: number, length: number, timeout?: number) {
return this.jensen?.requestFirmwareUpgrade(vn, length, timeout);
}
async uploadFirmware (data: number[], timeout?: number, onProgress?: (cur: number, total: number) => void) {
return this.jensen?.uploadFirmware(data, timeout, onProgress);
}
async beginBNC (timeout?: number) {
return this.jensen?.beginBNC(timeout);
}
async endBNC (timeout?: number) {
return this.jensen?.endBNC(timeout);
}
async deleteFile (fileName: string) {
return this.jensen?.deleteFile(fileName);
}
async getSettings (timeout?: number) {
return this.jensen?.getSettings(timeout);
}
async setAutoRecord (enable: boolean, timeout?: number) {
return this.jensen?.setAutoRecord(enable, timeout);
}
async setAutoPlay (enable: boolean, timeout?: number) {
return this.jensen?.setAutoPlay(enable, timeout);
}
async setNotification (enable: boolean, timeout?: number) {
return this.jensen?.setNotification(enable, timeout);
}
async setBluetoothPromptPlay (enable: boolean, timeout?: number) {
return this.jensen?.setBluetoothPromptPlay(enable, timeout);
}
async getCardInfo (timeout?: number) {
return this.jensen?.getCardInfo(timeout);
}
async formatCard (timeout?: number) {
return this.jensen?.formatCard(timeout);
}
async factoryReset (timeout?: number) {
return this.jensen?.factoryReset(timeout);
}
async restoreFactorySettings (timeout?: number) {
return this.jensen?.restoreFactorySettings(timeout);
}
async recordTestStart (type: number, timeout?: number) {
return this.jensen?.recordTestStart(type, timeout);
}
async recordTestEnd (type: number, timeout?: number) {
return this.jensen?.recordTestEnd(type, timeout);
}
async test (timeout?: number) {
return this.jensen?.test(timeout);
}
async writeSerialNumber (sn: string) {
return this.jensen?.writeSerialNumber(sn);
}
async getRealtimeSettings () {
return this.jensen?.getRealtimeSettings();
}
async startRealtime () {
return this.jensen?.startRealtime();
}
async pauseRealtime () {
return this.jensen?.pauseRealtime();
}
async stopRealtime () {
return this.jensen?.stopRealtime();
}
async getRealtime (frames: number) {
return this.jensen?.getRealtime(frames);
}
async scanDevices (timeout?: number) {
return this.jensen?.scanDevices(timeout);
}
async connectBTDevice (mac: string, timeout?: number) {
return this.jensen?.connectBTDevice(mac, timeout);
}
async disconnectBTDevice (timeout?: number) {
return this.jensen?.disconnectBTDevice(timeout);
}
async getBluetoothStatus (timeout?: number) {
return this.jensen?.getBluetoothStatus(timeout);
}
async requestToneUpdate (signature: string, size: number, timeout?: number) {
return this.jensen?.requestToneUpdate(signature, size, timeout);
}
async updateTone (data: Uint8Array, timeout?: number) {
return this.jensen?.updateTone(data, timeout);
}
async requestUACUpdate (signature: string, size: number, timeout?: number) {
return this.jensen?.requestUACUpdate(signature, size, timeout);
}
async updateUAC (data: Uint8Array, timeout?: number) {
return this.jensen?.updateUAC(data, timeout);
}
async sendScheduleInfo (info: ScheduleInfo[]) {
return this.jensen?.sendScheduleInfo(info);
}
// 生成唯一id,暂时用随机数生成,后面最好用顺序递增的整数比较好
private uuid () {
return String(Math.floor(1000_0000_0000_0000 + Math.random() * 1000_0000_0000_0000));
}
}
function sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
export const mgr = new ConnectionManager(Logger);
\ No newline at end of file
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