Commit fdfb03b7 authored by Skye's avatar Skye

feat: send schedule info api

parent 55ef423c
import { Jensen as Jen } from "./src/jensen";
import { Logger } from "./src/utils/utils";
import { Jensen as Jen } from './src/jensen';
import { Logger } from './src/utils/utils';
export type DeviceInfo = {
sn: string;
......@@ -8,7 +8,7 @@ export type DeviceInfo = {
};
export type ReturnStruct = {
common: { result: "failed" | "success" };
common: { result: 'failed' | 'success' };
};
export type FileInfo = {
......@@ -24,10 +24,8 @@ export type FileInfo = {
export type ScheduleInfo = {
startDate: Date;
endDate: Date;
keyAnswer?: string;
keyHangup?: string;
keyReject?: string;
keyMicMute?: string;
os: 'Windows' | 'Linux' | 'Mac';
platform: string;
};
declare class JensenType {
......@@ -39,33 +37,20 @@ declare class JensenType {
getDeviceInfo: (time?: number) => Promise<DeviceInfo>;
listFiles: (time?: number) => Promise<FileInfo[]>;
tryconnect: (disableOnConnect?: boolean) => Promise<boolean>;
getFile: (
fileName: string,
length: number,
on?: (msg: Uint8Array | "fail") => void,
onprogress?: (size: number) => void,
) => void;
getFileBlock: (
fileName: string,
length: number,
on?: (msg: Uint8Array | "fail") => void,
) => Promise<ReturnStruct["common"]>;
getFile: (fileName: string, length: number, on?: (msg: Uint8Array | 'fail') => void, onprogress?: (size: number) => void) => void;
getFileBlock: (fileName: string, length: number, on?: (msg: Uint8Array | 'fail') => void) => Promise<ReturnStruct['common']>;
requestFirmwareUpgrade: (
vn: number,
length: number,
time?: number,
time?: number
) => Promise<{
result: "accepted" | "fail";
result: 'accepted' | 'fail';
}>;
beginBNC: (time?: number) => Promise<ReturnStruct["common"]>;
endBNC: (time?: number) => Promise<ReturnStruct["common"]>;
setTime: (date: Date, timeout?: number) => Promise<ReturnStruct["common"]>;
beginBNC: (time?: number) => Promise<ReturnStruct['common']>;
endBNC: (time?: number) => Promise<ReturnStruct['common']>;
setTime: (date: Date, timeout?: number) => Promise<ReturnStruct['common']>;
deleteFile: (fileName: string) => Promise<{ result: string }>;
uploadFirmware: (
data: number[],
seconds?: number,
onProgress?: (cur: number, total: number) => void,
) => Promise<ReturnStruct["common"]>;
uploadFirmware: (data: number[], seconds?: number, onProgress?: (cur: number, total: number) => void) => Promise<ReturnStruct['common']>;
getTime: (time?: number) => Promise<{
time: string;
}>;
......@@ -74,19 +59,10 @@ declare class JensenType {
autoPlay: boolean;
notification?: boolean;
} | null>;
setAutoRecord: (
enable: boolean,
time?: number,
) => Promise<ReturnStruct["common"]>;
setAutoPlay: (
enable: boolean,
time?: number,
) => Promise<ReturnStruct["common"]>;
setAutoRecord: (enable: boolean, time?: number) => Promise<ReturnStruct['common']>;
setAutoPlay: (enable: boolean, time?: number) => Promise<ReturnStruct['common']>;
isConnected: () => boolean;
setNotification: (
state: boolean,
time?: number,
) => Promise<ReturnStruct["common"]>;
setNotification: (state: boolean, time?: number) => Promise<ReturnStruct['common']>;
ondisconnect?: Function;
isStopConnectionCheck: boolean;
getRecordingFile: () => Promise<{
......@@ -94,29 +70,18 @@ declare class JensenType {
createTime: string;
createDate: string;
}>;
getCardInfo: (
seconds?: number,
) => Promise<{ used: number; capacity: number; status: string }>;
formatCard: (seconds?: number) => Promise<ReturnStruct["common"]>;
factoryReset: (seconds?: number) => Promise<ReturnStruct["common"]>;
restoreFactorySettings: (seconds?: number) => Promise<ReturnStruct["common"]>;
getCardInfo: (seconds?: number) => Promise<{ used: number; capacity: number; status: string }>;
formatCard: (seconds?: number) => Promise<ReturnStruct['common']>;
factoryReset: (seconds?: number) => Promise<ReturnStruct['common']>;
restoreFactorySettings: (seconds?: number) => Promise<ReturnStruct['common']>;
getModel: () => string;
getFileCount: (seconds?: number) => Promise<{ count: number } | null>;
recordTestStart: (
type: number,
seconds?: number,
) => Promise<ReturnStruct["common"]>;
recordTestEnd: (
type: number,
seconds?: number,
) => Promise<ReturnStruct["common"]>;
test: (seconds?: number) => Promise<ReturnStruct["common"]>;
setBluetoothPromptPlay: (
state: boolean,
seconds?: number,
) => Promise<ReturnStruct["common"]>;
writeSerialNumber: (sn: string) => Promise<ReturnStruct["common"]>;
sendScheduleInfo: (info: ScheduleInfo) => Promise<ReturnStruct["common"]>;
recordTestStart: (type: number, seconds?: number) => Promise<ReturnStruct['common']>;
recordTestEnd: (type: number, seconds?: number) => Promise<ReturnStruct['common']>;
test: (seconds?: number) => Promise<ReturnStruct['common']>;
setBluetoothPromptPlay: (state: boolean, seconds?: number) => Promise<ReturnStruct['common']>;
writeSerialNumber: (sn: string) => Promise<ReturnStruct['common']>;
sendScheduleInfo: (info: ScheduleInfo) => Promise<ReturnStruct['common']>;
}
//@ts-ignore
......
{
"name": "jensen",
"version": "1.1.3",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "jensen",
"version": "1.1.3",
"version": "1.0.0",
"license": "ISC",
"devDependencies": {
"prettier": "^3.3.3"
......
import { Logger, Logger as internalLogger, getTimeStr } from './utils/utils';
import { Logger, Logger as internalLogger, getTimeStr, shortcutKeys } from './utils/utils';
const QUERY_DEVICE_INFO = 0x01;
const QUERY_DEVICE_TIME = 0x02;
......@@ -25,200 +25,196 @@ const TEST_SN_WRITE = 0xf007;
const RECORD_TEST_START = 0xf008; // 录音测试开始
const RECORD_TEST_END = 0xf009; // 录音测试结束
const COMMAND_NAMES = [
'invalid-0',
'get-device-info',
'get-device-time',
'set-device-time',
'get-file-list',
'transfer-file',
'get-file-count',
'delete-file',
'request-firmware-upgrade',
'firmware-upload',
'read card info',
'format card',
'get recording file',
'restore factory settings',
'device msg test',
'bnc demo test',
'get-settings',
'set-settings',
'get file block',
'factory reset',
'invalid-0',
'get-device-info',
'get-device-time',
'set-device-time',
'get-file-list',
'transfer-file',
'get-file-count',
'delete-file',
'request-firmware-upgrade',
'firmware-upload',
'read card info',
'format card',
'get recording file',
'restore factory settings',
'device msg test',
'bnc demo test',
'get-settings',
'set-settings',
'get file block',
'factory reset'
];
function Jensen(log) {
const Logger = log || internalLogger
let device = null;
let actions = {};
let buffer = [];
let blocks = [];
let sequence = 0;
let current = null;
let commands = [];
let handlers = [];
let statusTimeout = null;
let recv = false;
let ready = false;
let totalBytes = 0;
let self = this;
this.data = {};
// 消息
this.decodeTimeout = 0;
this.timewait = 1;
this.ondisconnect = null;
this.isStopConnectionCheck = false;
this.onconnect = null;
this.onreceive = null;
const RECV_BUFF_SIZE = 51200;
const _check_conn_status = () => {
if (device?.opened === false) {
try {
clearTimeout(statusTimeout);
const audio = document.getElementById('test_audio');
audio && audio.pause() && audio.remove();
if (this.ondisconnect && !this.isStopConnectionCheck) this.ondisconnect();
} catch (e) {
console.log(e);
}
}
statusTimeout = setTimeout(() => {
_check_conn_status();
}, 100);
};
const Logger = log || internalLogger;
let device = null;
let actions = {};
let buffer = [];
let blocks = [];
let sequence = 0;
let current = null;
let commands = [];
let handlers = [];
let statusTimeout = null;
let recv = false;
let ready = false;
let totalBytes = 0;
let self = this;
this.data = {};
// 消息
this.decodeTimeout = 0;
this.timewait = 1;
this.ondisconnect = null;
this.isStopConnectionCheck = false;
this.onconnect = null;
this.onreceive = null;
const RECV_BUFF_SIZE = 51200;
const _check_conn_status = () => {
if (device?.opened === false) {
try {
clearTimeout(statusTimeout);
const audio = document.getElementById('test_audio');
audio && audio.pause() && audio.remove();
if (this.ondisconnect && !this.isStopConnectionCheck) this.ondisconnect();
} catch (e) {
console.log(e);
}
}
statusTimeout = setTimeout(() => {
_check_conn_status();
}, 100);
};
const crash = async function (procedure, error) {
Logger.error('jensen', procedure, String(error));
self.versionCode = null;
self.versionNumber = null;
};
const crash = async function (procedure, error) {
Logger.error('jensen', procedure, String(error));
self.versionCode = null;
self.versionNumber = null;
};
const setup = async function (disableOnConnect) {
self.versionCode = null;
self.versionNumber = null;
commands.length = 0;
try {
await device.selectConfiguration(1);
await device.claimInterface(0);
await device.selectAlternateInterface(0, 0);
self.model = device.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
} catch (e) {
Logger.error('jensen', 'setup', String(e));
}
if (!disableOnConnect) _check_conn_status();
current = null;
recv = false;
ready = true;
Logger.debug('jensen', 'setup', 'setup webusb connection');
try {
if (!disableOnConnect && !self.isStopConnectionCheck) self.onconnect?.();
} catch (err) {
Logger.error('jensen', 'setup', err);
}
};
const setup = async function (disableOnConnect) {
self.versionCode = null;
self.versionNumber = null;
commands.length = 0;
try {
await device.selectConfiguration(1);
await device.claimInterface(0);
await device.selectAlternateInterface(0, 0);
self.model = device.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
} catch (e) {
Logger.error('jensen', 'setup', String(e));
}
if (!disableOnConnect) _check_conn_status();
current = null;
recv = false;
ready = true;
Logger.debug('jensen', 'setup', 'setup webusb connection');
try {
if (!disableOnConnect && !self.isStopConnectionCheck) self.onconnect?.();
} catch (err) {
Logger.error('jensen', 'setup', err);
}
};
this.connect = async function () {
Logger.debug('jensen', 'connect', 'connect');
let r = await self.tryconnect();
if (r) return;
let conn = await navigator.usb.requestDevice({
filters: [{ vendorId: 0x10d6 }],
});
await conn.open();
self.model = conn.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
device = conn;
await setup();
};
this.connect = async function () {
Logger.debug('jensen', 'connect', 'connect');
let r = await self.tryconnect();
if (r) return;
this.getModel = function () {
return this.model;
};
let conn = await navigator.usb.requestDevice({
filters: [{ vendorId: 0x10d6 }]
});
await conn.open();
self.model = conn.productId == 45069 ? 'hidock-h1e' : 'hidock-h1';
device = conn;
await setup();
};
this.init = async function _init() {
if (!navigator.usb) {
Logger.error('jensen', 'init', 'webusb not supported');
return;
}
navigator.usb.onconnect = function (e) {
self.tryconnect();
};
await self.connect();
};
this.getModel = function () {
return this.model;
};
this.tryconnect = async function (disableOnConnect) {
await this.disconnect();
let devices = await navigator.usb.getDevices();
for (let i = 0; i < devices.length; i++) {
let item = devices[i];
if (item.productName.indexOf('HiDock') > -1) {
Logger.debug('jensen', 'tryconnect', 'detected: ' + item.productName);
await item.open();
device = item;
await setup(disableOnConnect);
return true;
}
}
Logger.debug('jensen', 'tryconnect', 'no HiDock found');
return false;
this.init = async function _init() {
if (!navigator.usb) {
Logger.error('jensen', 'init', 'webusb not supported');
return;
}
navigator.usb.onconnect = function (e) {
self.tryconnect();
};
await self.connect();
};
this.isConnected = function () {
return device != null;
};
this.tryconnect = async function (disableOnConnect) {
await this.disconnect();
let devices = await navigator.usb.getDevices();
for (let i = 0; i < devices.length; i++) {
let item = devices[i];
if (item.productName.indexOf('HiDock') > -1) {
Logger.debug('jensen', 'tryconnect', 'detected: ' + item.productName);
await item.open();
device = item;
await setup(disableOnConnect);
return true;
}
}
Logger.debug('jensen', 'tryconnect', 'no HiDock found');
return false;
};
this.disconnect = async function () {
Logger.info('jensen', 'disconnect', 'disconnect');
try {
await device?.close();
} catch (e) {
}
};
this.isConnected = function () {
return device != null;
};
this.send = function (cmd, seconds, onprogress) {
cmd.sequence(sequence++);
cmd.onprogress = onprogress;
if (seconds) cmd.expireAfter(seconds);
commands.push(cmd);
sendNext();
return register(cmd, seconds);
};
this.disconnect = async function () {
Logger.info('jensen', 'disconnect', 'disconnect');
try {
await device?.close();
} catch (e) {}
};
const sendNext = async function () {
if (current) {
// Logger.info('jensen', 'sendNext', 'return cuz current is: ' + current);
return;
}
this.send = function (cmd, seconds, onprogress) {
cmd.sequence(sequence++);
cmd.onprogress = onprogress;
if (seconds) cmd.expireAfter(seconds);
commands.push(cmd);
sendNext();
return register(cmd, seconds);
};
let cmd = null;
let now = new Date().getTime();
while (true) {
if (commands.length == 0) return;
cmd = commands.shift();
if (cmd.expireTime > 0 && cmd.expireTime < now) {
Logger.info('jensen', 'sendNext', 'expired: cmd-' + cmd.command + '-' + cmd.index + ', ' + COMMAND_NAMES[cmd.command]);
continue;
}
break;
}
const sendNext = async function () {
if (current) {
// Logger.info('jensen', 'sendNext', 'return cuz current is: ' + current);
return;
}
let cmd = null;
let now = new Date().getTime();
while (true) {
if (commands.length == 0) return;
cmd = commands.shift();
if (cmd.expireTime > 0 && cmd.expireTime < now) {
Logger.info('jensen', 'sendNext', 'expired: cmd-' + cmd.command + '-' + cmd.index + ', ' + COMMAND_NAMES[cmd.command]);
continue;
}
break;
}
let data = cmd.make();
current = 'cmd-' + cmd.command + '-' + cmd.index;
Logger.debug('jensen', 'sendNext', 'command: ' + COMMAND_NAMES[cmd.command] + ', data bytes: ' + data.byteLength);
let data = cmd.make();
current = 'cmd-' + cmd.command + '-' + cmd.index;
Logger.debug('jensen', 'sendNext', 'command: ' + COMMAND_NAMES[cmd.command] + ', data bytes: ' + data.byteLength);
self.timewait = cmd.command == TRANSFER_FILE ? 1000 : 10;
self.timewait = cmd.command == TRANSFER_FILE ? 1000 : 10;
await device.transferOut(1, data).catch((e) => crash('sendNext', e));
if (cmd.onprogress) cmd.onprogress(1, 1);
/*
await device.transferOut(1, data).catch((e) => crash('sendNext', e));
if (cmd.onprogress) cmd.onprogress(1, 1);
/*
if (data.byteLength < 1000) await device.transferOut(1, data).catch((e) => crash('sendNext', e));
else
{
......@@ -240,321 +236,309 @@ function Jensen(log) {
}
}
*/
totalBytes = 0;
if (recv == false) tryReceive();
else recv = true;
};
totalBytes = 0;
if (recv == false) tryReceive();
else recv = true;
};
const register = function (cmd, seconds) {
let tag = 'cmd-' + cmd.command + '-' + cmd.index;
let t = seconds
? setTimeout(() => {
timeout(tag);
}, seconds * 1000)
: null;
return new Promise((resolve, reject) => {
actions[tag] = {
tag: tag,
resolve: resolve,
reject: reject,
timeout: t,
};
});
};
const register = function (cmd, seconds) {
let tag = 'cmd-' + cmd.command + '-' + cmd.index;
let t = seconds
? setTimeout(() => {
timeout(tag);
}, seconds * 1000)
: null;
return new Promise((resolve, reject) => {
actions[tag] = {
tag: tag,
resolve: resolve,
reject: reject,
timeout: t
};
});
};
const trigger = function (resp, msgid) {
if (current == null) return;
Logger.debug('jensen', 'trigger', 'trigger - ' + current.substring(0, current.lastIndexOf('-')) + ' <---> cmd-' + msgid);
if (current.substring(0, current.lastIndexOf('-')) != 'cmd-' + msgid) {
current = null;
return;
}
if (current in actions == false) {
Logger.debug('jensen', 'trigger', 'no action registered');
return;
}
let p = actions[current];
if (p.timeout) clearTimeout(p.timeout);
p.resolve(resp);
delete actions[current];
current = null;
};
const trigger = function (resp, msgid) {
if (current == null) return;
Logger.debug('jensen', 'trigger', 'trigger - ' + current.substring(0, current.lastIndexOf('-')) + ' <---> cmd-' + msgid);
if (current.substring(0, current.lastIndexOf('-')) != 'cmd-' + msgid) {
current = null;
return;
}
if (current in actions == false) {
Logger.debug('jensen', 'trigger', 'no action registered');
return;
}
let p = actions[current];
if (p.timeout) clearTimeout(p.timeout);
p.resolve(resp);
delete actions[current];
current = null;
};
const timeout = function (tag) {
Logger.debug('jensen', 'timeout', 'timeout ' + tag);
let p = actions[tag];
p.resolve(null);
delete actions[tag];
};
const timeout = function (tag) {
Logger.debug('jensen', 'timeout', 'timeout ' + tag);
let p = actions[tag];
p.resolve(null);
delete actions[tag];
};
this.dump = function () {
console.log('actions', actions);
console.log('pending commands', commands);
console.log('current', current);
console.log('device', device);
};
this.dump = function () {
console.log('actions', actions);
console.log('pending commands', commands);
console.log('current', current);
console.log('device', device);
};
const tryReceive = function () {
if (device)
device.transferIn(2, RECV_BUFF_SIZE).then((r) => {
Logger.save?.('jensen', 'tryReceive', r?.data);
receive(r);
});
};
const tryReceive = function () {
if (device)
device.transferIn(2, RECV_BUFF_SIZE).then((r) => {
Logger.save?.('jensen', 'tryReceive', r?.data);
receive(r);
});
};
const read_int = function (a, b, c, d) {
if (arguments.length === 2) {
return ((a & 0xff) << 8) | (b & 0xff);
} else if (arguments.length === 4) {
return ((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff);
}
};
const read_int = function (a, b, c, d) {
if (arguments.length === 2) {
return ((a & 0xff) << 8) | (b & 0xff);
} else if (arguments.length === 4) {
return ((a & 0xff) << 24) | ((b & 0xff) << 16) | ((c & 0xff) << 8) | (d & 0xff);
}
};
const receive = function (result) {
totalBytes += result.data.byteLength;
// 做一个回调,怎么样找到它呢?
blocks.push(result.data);
tryReceive();
tryDecode();
if (self.onreceive) {
try {
self.onreceive(totalBytes);
} catch (e) {
}
} else {
// if (self.decodeTimeout) clearTimeout(self.decodeTimeout);
// self.decodeTimeout = setTimeout(function () {
// tryDecode();
// }, self.timewait);
}
};
const receive = function (result) {
totalBytes += result.data.byteLength;
// 做一个回调,怎么样找到它呢?
blocks.push(result.data);
tryReceive();
tryDecode();
if (self.onreceive) {
try {
self.onreceive(totalBytes);
} catch (e) {}
} else {
// if (self.decodeTimeout) clearTimeout(self.decodeTimeout);
// self.decodeTimeout = setTimeout(function () {
// tryDecode();
// }, self.timewait);
}
};
// 持续解码
const continueDecode = (block) => {
const buff = new ArrayBuffer(RECV_BUFF_SIZE * 2);
let bview = new Uint8Array(buff);
for (let k = 0; k < block.byteLength; k++) {
bview[k] = block.getInt8(k);
}
let result = null;
try {
result = decodeMessage(bview, 0, block.byteLength);
} catch (err) {
console.error('ci decode', err);
}
sendNext();
const msg = result.message;
return result && msg.id === TRANSFER_FILE ? msg.body : null;
};
// 持续解码
const continueDecode = (block) => {
const buff = new ArrayBuffer(RECV_BUFF_SIZE * 2);
let bview = new Uint8Array(buff);
for (let k = 0; k < block.byteLength; k++) {
bview[k] = block.getInt8(k);
const tryDecode = function () {
// 一个容器,比单独任意一个小包要大一点儿,好像还差一点儿
let stime = new Date();
let buff = new ArrayBuffer(RECV_BUFF_SIZE * 2);
let bview = new Uint8Array(buff);
// buff中实际使用的字节数,有效字节数
let buffLength = 0;
let crash = false;
for (let i = 0, l = blocks.length; i < l; i++) {
let block = blocks.shift();
// 把block加到buff的最末尾
for (let k = 0; k < block.byteLength; k++) {
bview[k + buffLength] = block.getInt8(k);
}
buffLength += block.byteLength;
let startIndex = 0;
while (true) {
let rst = null;
try {
rst = decodeMessage(bview, startIndex, buffLength);
} catch (e) {
crash = true;
break;
}
if (rst == null) {
break;
}
startIndex += rst.length;
let msg = rst.message;
// WARN: 接下来怎么整
let cname = msg.id === FACTORY_RESET ? 'factory-reset' : COMMAND_NAMES[msg.id];
let heading = [];
for (let x = 0; x < msg.body?.byteLength && x < 32; x++) {
heading.push('0' + (msg.body[x] & 0xff).toString(16).replace(/^0(\w{2})$/gi, '$1'));
}
let result = null;
if (msg.id !== TRANSFER_FILE)
Logger.debug(
'jensen',
'receive',
'recv: ' + cname + ', seq: ' + msg.sequence + ', data bytes: ' + msg.body?.byteLength + ', data: ' + heading.join(' ')
);
try {
result = decodeMessage(bview, 0, block.byteLength);
} catch (err) {
console.error('ci decode', err);
let handler = Jensen.handlers[msg.id];
let r = handler(msg, self);
if (r) trigger(r, msg.id);
} catch (e) {
trigger(e);
Logger.error('jensen', 'receive', 'recv: ' + COMMAND_NAMES[msg.id] + ', seq: ' + msg.sequence + ', error: ' + String(e));
}
sendNext();
const msg = result.message;
return result && msg.id === TRANSFER_FILE ? msg.body : null;
}
const tryDecode = function () {
// 一个容器,比单独任意一个小包要大一点儿,好像还差一点儿
let stime = new Date();
let buff = new ArrayBuffer(RECV_BUFF_SIZE * 2);
let bview = new Uint8Array(buff);
// buff中实际使用的字节数,有效字节数
let buffLength = 0;
let crash = false;
for (let i = 0, l = blocks.length; i < l; i++) {
let block = blocks.shift();
// 把block加到buff的最末尾
for (let k = 0; k < block.byteLength; k++) {
bview[k + buffLength] = block.getInt8(k);
}
buffLength += block.byteLength;
let startIndex = 0;
while (true) {
let rst = null;
try {
rst = decodeMessage(bview, startIndex, buffLength);
} catch (e) {
crash = true;
break;
}
if (rst == null) {
break;
}
startIndex += rst.length;
let msg = rst.message;
// WARN: 接下来怎么整
let cname = msg.id === FACTORY_RESET ? 'factory-reset' : COMMAND_NAMES[msg.id];
let heading = [];
for (let x = 0; x < msg.body?.byteLength && x < 32; x++) {
heading.push('0' + (msg.body[x] & 0xff).toString(16).replace(/^0(\w{2})$/gi, '$1'));
}
if (msg.id !== TRANSFER_FILE)
Logger.debug(
'jensen',
'receive',
'recv: ' +
cname +
', seq: ' +
msg.sequence +
', data bytes: ' +
msg.body?.byteLength +
', data: ' +
heading.join(' '),
);
try {
let handler = Jensen.handlers[msg.id];
let r = handler(msg, self);
if (r) trigger(r, msg.id);
} catch (e) {
trigger(e);
Logger.error(
'jensen',
'receive',
'recv: ' + COMMAND_NAMES[msg.id] + ', seq: ' + msg.sequence + ', error: ' + String(e),
);
}
sendNext();
}
// 是否已经崩溃了?
if (crash) {
// cmd-5-42
// 5是msgid
let msgid = parseInt(current.replace(/^cmd-(\d+)-(\d+)$/gi, '$1'));
try {
let handler = Jensen.handlers[msgid];
handler(null, self);
} catch (e) {
trigger(e);
Logger.error('jensen', 'decode', 'decode error: ' + String(e));
}
trigger(null, msgid);
blocks.length = 0;
break;
}
// WARN: 需要把剩余的字节数挪到最前面去
// startIndex已经抵达最后的位置,startIndex -> buffLength就是需要移到最前面去的字节内容了
for (let k = 0, bs = buffLength - startIndex; k < bs; k++) {
bview[k] = bview[k + startIndex];
}
buffLength = buffLength - startIndex;
}
// 是否已经崩溃了?
if (crash) {
// cmd-5-42
// 5是msgid
let msgid = parseInt(current.replace(/^cmd-(\d+)-(\d+)$/gi, '$1'));
try {
let handler = Jensen.handlers[msgid];
handler(null, self);
} catch (e) {
trigger(e);
Logger.error('jensen', 'decode', 'decode error: ' + String(e));
}
console.error('Decode: ' + (new Date().getTime() - stime.getTime()) + 'ms');
};
trigger(null, msgid);
blocks.length = 0;
break;
}
// WARN: 需要把剩余的字节数挪到最前面去
// startIndex已经抵达最后的位置,startIndex -> buffLength就是需要移到最前面去的字节内容了
for (let k = 0, bs = buffLength - startIndex; k < bs; k++) {
bview[k] = bview[k + startIndex];
}
buffLength = buffLength - startIndex;
}
console.error('Decode: ' + (new Date().getTime() - stime.getTime()) + 'ms');
};
const decodeMessage = function (dataView, startIndex, buffLength) {
let dataLen = buffLength - startIndex;
if (dataLen < 12) return null;
if (dataView[startIndex + 0] !== 0x12 || dataView[startIndex + 1] !== 0x34) throw new Error('invalid header');
// 2 字节的指令id
let idx = 2;
// let cmdid = this.nextShort(idx);
let cmdid = read_int(dataView[startIndex + idx], dataView[startIndex + idx + 1]);
idx += 2;
let sequeue = read_int(
dataView[startIndex + idx + 0],
dataView[startIndex + idx + 1],
dataView[startIndex + idx + 2],
dataView[startIndex + idx + 3],
);
idx += 4;
let len = read_int(
dataView[startIndex + idx + 0],
dataView[startIndex + idx + 1],
dataView[startIndex + idx + 2],
dataView[startIndex + idx + 3],
);
let padding = (len >> 24) & 0xff;
len = len & 0xffffff;
idx += 4;
// 需要去除的字节数
var cutLen = 0;
// 数据还没有完全准备好
if (dataLen < 12 + len + padding) return null;
// 去掉header部分
// 下面这一行做什么用的?
// for (let i = 0; i < 12; i++) this.buffer[i + cutLen];
cutLen += 12;
// 取走body部分
// 数据体部分
// let body = new Uint8Array(new ArrayBuffer(len));
// for (let i = 0; i < len; i++) body.push(this.buffer[i + cutLen]);
let body = dataView.slice(startIndex + cutLen, startIndex + cutLen + len);
cutLen += len;
// 干掉补上来的数据
// 下面这一行做什么用的?
// for (let i = 0; i < padding; i++) this.buffer[i + cutLen];
cutLen += padding;
// self.buffer = self.buffer.slice(cutLen);
return { message: new Message(cmdid, sequeue, body), length: cutLen };
};
const decodeMessage = function (dataView, startIndex, buffLength) {
let dataLen = buffLength - startIndex;
if (dataLen < 12) return null;
if (dataView[startIndex + 0] !== 0x12 || dataView[startIndex + 1] !== 0x34) throw new Error('invalid header');
// 2 字节的指令id
let idx = 2;
// let cmdid = this.nextShort(idx);
let cmdid = read_int(dataView[startIndex + idx], dataView[startIndex + idx + 1]);
idx += 2;
let sequeue = read_int(
dataView[startIndex + idx + 0],
dataView[startIndex + idx + 1],
dataView[startIndex + idx + 2],
dataView[startIndex + idx + 3]
);
idx += 4;
let len = read_int(
dataView[startIndex + idx + 0],
dataView[startIndex + idx + 1],
dataView[startIndex + idx + 2],
dataView[startIndex + idx + 3]
);
let padding = (len >> 24) & 0xff;
len = len & 0xffffff;
idx += 4;
// 需要去除的字节数
var cutLen = 0;
// 数据还没有完全准备好
if (dataLen < 12 + len + padding) return null;
// 去掉header部分
// 下面这一行做什么用的?
// for (let i = 0; i < 12; i++) this.buffer[i + cutLen];
cutLen += 12;
// 取走body部分
// 数据体部分
// let body = new Uint8Array(new ArrayBuffer(len));
// for (let i = 0; i < len; i++) body.push(this.buffer[i + cutLen]);
let body = dataView.slice(startIndex + cutLen, startIndex + cutLen + len);
cutLen += len;
// 干掉补上来的数据
// 下面这一行做什么用的?
// for (let i = 0; i < padding; i++) this.buffer[i + cutLen];
cutLen += padding;
// self.buffer = self.buffer.slice(cutLen);
return { message: new Message(cmdid, sequeue, body), length: cutLen };
};
this.to_bcd = function (str) {
let x = [];
for (let i = 0; i < str.length; i += 2) {
let h = (str.charCodeAt(i) - 48) & 0xff;
let l = (str.charCodeAt(i + 1) - 48) & 0xff;
x.push((h << 4) | l);
}
return x;
};
this.to_bcd = function (str) {
let x = [];
for (let i = 0; i < str.length; i += 2) {
let h = (str.charCodeAt(i) - 48) & 0xff;
let l = (str.charCodeAt(i + 1) - 48) & 0xff;
x.push((h << 4) | l);
}
return x;
};
this.from_bcd = function () {
let str = '';
for (let i = 0; i < arguments.length; i++) {
let v = arguments[i] & 0xff;
str += (v >> 4) & 0x0f;
str += v & 0x0f;
}
return str;
};
this.from_bcd = function () {
let str = '';
for (let i = 0; i < arguments.length; i++) {
let v = arguments[i] & 0xff;
str += (v >> 4) & 0x0f;
str += v & 0x0f;
}
return str;
};
}
function Command(id) {
this.command = id;
this.msgBody = [];
this.index = 0;
this.expireTime = 0;
this.timeout = 0;
this.body = function (data) {
this.msgBody = data;
return this;
};
this.expireAfter = function (seconds) {
this.expireTime = new Date().getTime() + seconds * 1000;
};
this.sequence = function (seq) {
this.index = seq;
return this;
};
this.make = function () {
let msg = new Uint8Array(2 + 2 + 4 + 4 + this.msgBody.length);
let idx = 0;
// msg header
msg[idx++] = 0x12;
msg[idx++] = 0x34;
// msg command id
msg[idx++] = (this.command >> 8) & 0xff;
msg[idx++] = (this.command >> 0) & 0xff;
// msg sequence id
msg[idx++] = (this.index >> 24) & 0xff;
msg[idx++] = (this.index >> 16) & 0xff;
msg[idx++] = (this.index >> 8) & 0xff;
msg[idx++] = (this.index >> 0) & 0xff;
// msg body length
let len = this.msgBody.length;
msg[idx++] = (len >> 24) & 0xff;
msg[idx++] = (len >> 16) & 0xff;
msg[idx++] = (len >> 8) & 0xff;
msg[idx++] = (len >> 0) & 0xff;
// msg body
for (let i = 0; i < this.msgBody.length; i++) msg[idx++] = this.msgBody[i] & 0xff;
return msg;
};
this.command = id;
this.msgBody = [];
this.index = 0;
this.expireTime = 0;
this.timeout = 0;
this.body = function (data) {
this.msgBody = data;
return this;
};
this.expireAfter = function (seconds) {
this.expireTime = new Date().getTime() + seconds * 1000;
};
this.sequence = function (seq) {
this.index = seq;
return this;
};
this.make = function () {
let msg = new Uint8Array(2 + 2 + 4 + 4 + this.msgBody.length);
let idx = 0;
// msg header
msg[idx++] = 0x12;
msg[idx++] = 0x34;
// msg command id
msg[idx++] = (this.command >> 8) & 0xff;
msg[idx++] = (this.command >> 0) & 0xff;
// msg sequence id
msg[idx++] = (this.index >> 24) & 0xff;
msg[idx++] = (this.index >> 16) & 0xff;
msg[idx++] = (this.index >> 8) & 0xff;
msg[idx++] = (this.index >> 0) & 0xff;
// msg body length
let len = this.msgBody.length;
msg[idx++] = (len >> 24) & 0xff;
msg[idx++] = (len >> 16) & 0xff;
msg[idx++] = (len >> 8) & 0xff;
msg[idx++] = (len >> 0) & 0xff;
// msg body
for (let i = 0; i < this.msgBody.length; i++) msg[idx++] = this.msgBody[i] & 0xff;
return msg;
};
}
function Message(id, sequence, body) {
this.id = id;
this.sequence = sequence;
this.body = body;
this.id = id;
this.sequence = sequence;
this.body = body;
}
/**
......@@ -562,496 +546,500 @@ function Message(id, sequence, body) {
* @param {*} handler callback function for response processing, return `non-undefined` means command ended
*/
Jensen.registerHandler = function (cmdid, handler) {
if (typeof Jensen.handlers == 'undefined') Jensen.handlers = {};
Jensen.handlers[cmdid] = handler;
if (typeof Jensen.handlers == 'undefined') Jensen.handlers = {};
Jensen.handlers[cmdid] = handler;
};
Jensen.prototype.getDeviceInfo = async function (seconds) {
return this.send(new Command(QUERY_DEVICE_INFO), seconds);
return this.send(new Command(QUERY_DEVICE_INFO), seconds);
};
Jensen.prototype.getTime = async function (seconds) {
return this.send(new Command(QUERY_DEVICE_TIME), seconds);
return this.send(new Command(QUERY_DEVICE_TIME), seconds);
};
Jensen.prototype.getFileCount = async function (seconds) {
return this.send(new Command(QUERY_FILE_COUNT), seconds);
return this.send(new Command(QUERY_FILE_COUNT), seconds);
};
Jensen.prototype.factoryReset = async function (seconds) {
if (this.versionNumber < 327705) return null;
return this.send(new Command(FACTORY_RESET), seconds);
if (this.versionNumber < 327705) return null;
return this.send(new Command(FACTORY_RESET), seconds);
};
Jensen.prototype.restoreFactorySettings = async function (seconds) {
if (this.model === 'hidock-h1e' && this.versionNumber < 393476) return null;
if (this.model === 'hidock-h1' && this.versionNumber < 327944) return null;
return this.send(new Command(RESTORE_FACTORY_SETTINGS).body([0x01, 0x02, 0x03, 0x04]), seconds);
if (this.model === 'hidock-h1e' && this.versionNumber < 393476) return null;
if (this.model === 'hidock-h1' && this.versionNumber < 327944) return null;
return this.send(new Command(RESTORE_FACTORY_SETTINGS).body([0x01, 0x02, 0x03, 0x04]), seconds);
};
Jensen.prototype.listFiles = async function () {
let tag = 'filelist';
if (this[tag] != null) return null;
let fc = null;
if (typeof this.versionNumber == 'undefined' || this.versionNumber <= 327722) {
fc = await this.getFileCount(5);
if (fc == null) return null;
let tag = 'filelist';
if (this[tag] != null) return null;
let fc = null;
if (typeof this.versionNumber == 'undefined' || this.versionNumber <= 327722) {
fc = await this.getFileCount(5);
if (fc == null) return null;
}
if (fc && fc.count == 0) return null;
let self = this;
// let tag = 'data_' + new Date().getTime();
this[tag] = [];
Jensen.registerHandler(QUERY_FILE_LIST, (msg, jensen) => {
if (msg.body.length == 0) {
jensen[tag] = null;
return [];
}
jensen[tag].push(msg.body);
let data = [];
let files = [];
let fcount = -1;
let start = 0;
for (let i = 0; i < jensen[tag].length; i++) {
for (let k = 0; k < jensen[tag][i].length; k++) data.push(jensen[tag][i][k]);
}
if ((data[0] & 0xff) == 0xff && (data[1] & 0xff) == 0xff) {
fcount = ((data[2] & 0xff) << 24) | ((data[3] & 0xff) << 16) | ((data[4] & 0xff) << 8) | (data[5] & 0xff);
start += 6;
}
let fnpad = function (v) {
return v > 9 ? v : '0' + v;
};
for (let i = start; i < data.length; ) {
let len = 0;
let fname = [];
if (i + 4 >= data.length) break;
let ver = data[i++] & 0xff;
let nameLen = ((data[i++] & 0xff) << 16) | ((data[i++] & 0xff) << 8) | (data[i++] & 0xff);
for (let k = 0; k < nameLen && i < data.length; k++) {
let c = data[i++] & 0xff;
if (c > 0) fname.push(String.fromCharCode(c));
}
// 4 + nameLen + 4 + 6 + 16
if (i + 4 + 6 + 16 > data.length) {
break;
}
let flen = ((data[i++] & 0xff) << 24) | ((data[i++] & 0xff) << 16) | ((data[i++] & 0xff) << 8) | (data[i++] & 0xff);
i += 6;
let sign = [];
for (let k = 0; k < 16; k++, i++) {
let h = (data[i] & 0xff).toString(16);
sign.push(h.length == 1 ? '0' + h : h);
}
let ftime = fname.join('');
let duration = 0;
if (ftime.match(/^\d{14}REC\d+\.wav$/gi)) {
ftime = ftime.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})REC.*$/gi, '$1-$2-$3 $4:$5:$6');
ftime = new Date(ftime);
duration = flen / 32;
} else if (ftime.match(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi)) {
// 2024Mar19-110932-Rec00.hda
ftime = ftime.replace(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi, '20$2 $3 $4 $5:$6:$7');
ftime = new Date(ftime);
duration = (flen / 32) * 4;
} else {
ftime = null;
}
if (ver == 1) {
duration = duration * 2;
}
let createDate = '';
let createTime = '';
if (ftime) {
createDate = ftime.getFullYear() + '/' + fnpad(ftime.getMonth() + 1) + '/' + fnpad(ftime.getDate());
createTime = fnpad(ftime.getHours()) + ':' + fnpad(ftime.getMinutes()) + ':' + fnpad(ftime.getSeconds());
}
files.push({
name: fname.join(''),
createDate: createDate,
createTime: createTime,
time: ftime,
duration: duration,
length: flen,
signature: sign.join('')
});
}
// if (fcount == -1 && (fc))
// 如果没有判断数量的依据
if (fcount == -1) {
// return [];
}
if ((fc && files.length >= fc.count) || (fcount > -1 && files.length >= fcount)) {
// delete jensen[tag];
jensen[tag] = null;
return files.filter((f) => {
return Boolean(f.time);
});
}
});
if (fc && fc.count == 0) return null;
let self = this;
// let tag = 'data_' + new Date().getTime();
this[tag] = [];
Jensen.registerHandler(QUERY_FILE_LIST, (msg, jensen) => {
if (msg.body.length == 0) {
jensen[tag] = null;
return [];
}
jensen[tag].push(msg.body);
let data = [];
let files = [];
let fcount = -1;
let start = 0;
for (let i = 0; i < jensen[tag].length; i++) {
for (let k = 0; k < jensen[tag][i].length; k++) data.push(jensen[tag][i][k]);
}
if ((data[0] & 0xff) == 0xff && (data[1] & 0xff) == 0xff) {
fcount = ((data[2] & 0xff) << 24) | ((data[3] & 0xff) << 16) | ((data[4] & 0xff) << 8) | (data[5] & 0xff);
start += 6;
}
let fnpad = function (v) {
return v > 9 ? v : '0' + v;
};
for (let i = start; i < data.length;) {
let len = 0;
let fname = [];
if (i + 4 >= data.length) break;
let ver = data[i++] & 0xff;
let nameLen = ((data[i++] & 0xff) << 16) | ((data[i++] & 0xff) << 8) | (data[i++] & 0xff);
for (let k = 0; k < nameLen && i < data.length; k++) {
let c = data[i++] & 0xff;
if (c > 0) fname.push(String.fromCharCode(c));
}
// 4 + nameLen + 4 + 6 + 16
if (i + 4 + 6 + 16 > data.length) {
break;
}
let flen = ((data[i++] & 0xff) << 24) | ((data[i++] & 0xff) << 16) | ((data[i++] & 0xff) << 8) | (data[i++] & 0xff);
i += 6;
let sign = [];
for (let k = 0; k < 16; k++, i++) {
let h = (data[i] & 0xff).toString(16);
sign.push(h.length == 1 ? '0' + h : h);
}
let ftime = fname.join('');
let duration = 0;
if (ftime.match(/^\d{14}REC\d+\.wav$/gi)) {
ftime = ftime.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})REC.*$/gi, '$1-$2-$3 $4:$5:$6');
ftime = new Date(ftime);
duration = flen / 32;
} else if (ftime.match(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi)) {
// 2024Mar19-110932-Rec00.hda
ftime = ftime.replace(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi, '20$2 $3 $4 $5:$6:$7');
ftime = new Date(ftime);
duration = (flen / 32) * 4;
} else {
ftime = null;
}
if (ver == 1) {
duration = duration * 2;
}
let createDate = '';
let createTime = '';
if (ftime) {
createDate = ftime.getFullYear() + '/' + fnpad(ftime.getMonth() + 1) + '/' + fnpad(ftime.getDate());
createTime = fnpad(ftime.getHours()) + ':' + fnpad(ftime.getMinutes()) + ':' + fnpad(ftime.getSeconds());
}
files.push({
name: fname.join(''),
createDate: createDate,
createTime: createTime,
time: ftime,
duration: duration,
length: flen,
signature: sign.join(''),
});
}
// if (fcount == -1 && (fc))
// 如果没有判断数量的依据
if (fcount == -1) {
// return [];
}
if ((fc && files.length >= fc.count) || (fcount > -1 && files.length >= fcount)) {
// delete jensen[tag];
jensen[tag] = null;
return files.filter((f) => {
return Boolean(f.time);
});
}
});
return this.send(new Command(QUERY_FILE_LIST));
return this.send(new Command(QUERY_FILE_LIST));
};
Jensen.prototype.deleteFile = async function (filename, seconds) {
let fname = [];
for (let i = 0; i < filename.length; i++) fname.push(filename.charCodeAt(i));
return this.send(new Command(DELETE_FILE).body(fname), seconds);
let fname = [];
for (let i = 0; i < filename.length; i++) fname.push(filename.charCodeAt(i));
return this.send(new Command(DELETE_FILE).body(fname), seconds);
};
Jensen.prototype.setTime = async function (time, seconds) {
let str =
time.getFullYear() +
'-0' +
(time.getMonth() + 1) +
'-0' +
time.getDate() +
'-0' +
time.getHours() +
'-0' +
time.getMinutes() +
'-0' +
time.getSeconds();
str = str.replace(/(\d{4})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})/gi, '$1$2$3$4$5$6');
return this.send(new Command(SET_DEVICE_TIME).body(this.to_bcd(str)), seconds);
let str =
time.getFullYear() +
'-0' +
(time.getMonth() + 1) +
'-0' +
time.getDate() +
'-0' +
time.getHours() +
'-0' +
time.getMinutes() +
'-0' +
time.getSeconds();
str = str.replace(/(\d{4})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})/gi, '$1$2$3$4$5$6');
return this.send(new Command(SET_DEVICE_TIME).body(this.to_bcd(str)), seconds);
};
Jensen.prototype.getFile = async function (filename, length, ondata, onprogress) {
if (typeof length != 'number') throw new Error('parameter `length` required');
if (length <= 0) throw new Error('parameter `length` must greater than zero');
Logger.info('jensen', 'getFile', `file download start. filename: ${filename}, length: ${length} `);
let fname = [];
for (let i = 0; i < filename.length; i++) fname.push(filename.charCodeAt(i));
let wakeLock = null;
function visibilitychange() {
let audio = document.getElementById('test_audio');
if (!audio) {
audio = document.createElement('audio');
audio.id = 'test_audio'
audio.src = 'https://audionotes.hidock.com/test/test.aac';
audio.loop = true;
audio.controls = false;
audio.autoplay = true;
audio.muted = true;
document.body.appendChild(audio);
}
if (document.visibilityState === 'hidden') {
console.log('Page is hidden');
audio.play();
} else {
audio.pause();
console.log('Page is visible');
wakeLock && wakeLock.release();
}
if (typeof length != 'number') throw new Error('parameter `length` required');
if (length <= 0) throw new Error('parameter `length` must greater than zero');
Logger.info('jensen', 'getFile', `file download start. filename: ${filename}, length: ${length} `);
let fname = [];
for (let i = 0; i < filename.length; i++) fname.push(filename.charCodeAt(i));
let wakeLock = null;
function visibilitychange() {
let audio = document.getElementById('test_audio');
if (!audio) {
audio = document.createElement('audio');
audio.id = 'test_audio';
audio.src = 'https://audionotes.hidock.com/test/test.aac';
audio.loop = true;
audio.controls = false;
audio.autoplay = true;
audio.muted = true;
document.body.appendChild(audio);
}
if ('wakeLock' in navigator) {
try {
wakeLock = await navigator.wakeLock.request('screen');
console.log('Wake lock activated');
} catch (err) {
console.error('Failed to acquire wake lock:', err);
}
if (document.visibilityState === 'hidden') {
console.log('Page is hidden');
audio.play();
} else {
audio.pause();
console.log('Page is visible');
wakeLock && wakeLock.release();
}
function clearEventAndTask() {
const audio = document.getElementById('test_audio');
audio && audio.remove();
wakeLock && wakeLock.release();
console.log('Clear event and task.');
}
if ('wakeLock' in navigator) {
try {
wakeLock = await navigator.wakeLock.request('screen');
console.log('Wake lock activated');
} catch (err) {
console.error('Failed to acquire wake lock:', err);
}
visibilitychange();
document.addEventListener('visibilitychange', visibilitychange);
let flen = 0;
let handler = (msg) => {
if (msg != null) {
flen += msg.body.length || msg.body.byteLength;
ondata(msg.body);
Logger.info('jensen', 'getFile length', `${length} ${flen}`)
if (flen >= length) {
document.removeEventListener('visibilitychange', visibilitychange);
Logger.info('jensen', 'getFile', 'file download finish.')
clearEventAndTask();
// return OK indicates all file blocks received
return 'OK';
}
} else {
document.removeEventListener('visibilitychange', visibilitychange);
clearEventAndTask();
Logger.info('jensen', 'getFile', 'file download fail.')
ondata('fail');
}
};
this.onreceive = onprogress;
Jensen.registerHandler(TRANSFER_FILE, handler);
this.send(new Command(TRANSFER_FILE).body(fname));
}
function clearEventAndTask() {
const audio = document.getElementById('test_audio');
audio && audio.remove();
wakeLock && wakeLock.release();
console.log('Clear event and task.');
}
visibilitychange();
document.addEventListener('visibilitychange', visibilitychange);
let flen = 0;
let handler = (msg) => {
if (msg != null) {
flen += msg.body.length || msg.body.byteLength;
ondata(msg.body);
Logger.info('jensen', 'getFile length', `${length} ${flen}`);
if (flen >= length) {
document.removeEventListener('visibilitychange', visibilitychange);
Logger.info('jensen', 'getFile', 'file download finish.');
clearEventAndTask();
// return OK indicates all file blocks received
return 'OK';
}
} else {
document.removeEventListener('visibilitychange', visibilitychange);
clearEventAndTask();
Logger.info('jensen', 'getFile', 'file download fail.');
ondata('fail');
}
};
this.onreceive = onprogress;
Jensen.registerHandler(TRANSFER_FILE, handler);
this.send(new Command(TRANSFER_FILE).body(fname));
};
Jensen.prototype.requestFirmwareUpgrade = async function (versionNumber, fileSize, seconds) {
let data = [];
data[0] = (versionNumber >> 24) & 0xff;
data[1] = (versionNumber >> 16) & 0xff;
data[2] = (versionNumber >> 8) & 0xff;
data[3] = (versionNumber >> 0) & 0xff;
data[4] = (fileSize >> 24) & 0xff;
data[5] = (fileSize >> 16) & 0xff;
data[6] = (fileSize >> 8) & 0xff;
data[7] = (fileSize >> 0) & 0xff;
return this.send(new Command(REQUEST_FIRMWARE_UPGRADE).body(data), seconds);
let data = [];
data[0] = (versionNumber >> 24) & 0xff;
data[1] = (versionNumber >> 16) & 0xff;
data[2] = (versionNumber >> 8) & 0xff;
data[3] = (versionNumber >> 0) & 0xff;
data[4] = (fileSize >> 24) & 0xff;
data[5] = (fileSize >> 16) & 0xff;
data[6] = (fileSize >> 8) & 0xff;
data[7] = (fileSize >> 0) & 0xff;
return this.send(new Command(REQUEST_FIRMWARE_UPGRADE).body(data), seconds);
};
Jensen.prototype.uploadFirmware = async function (data, seconds, onprogress) {
return this.send(new Command(FIRMWARE_UPLOAD).body(data), seconds, onprogress);
return this.send(new Command(FIRMWARE_UPLOAD).body(data), seconds, onprogress);
};
Jensen.prototype.beginBNC = async function (seconds) {
return this.send(new Command(BNC_DEMO_TEST).body([0x01]), seconds);
return this.send(new Command(BNC_DEMO_TEST).body([0x01]), seconds);
};
Jensen.prototype.endBNC = async function (seconds) {
return this.send(new Command(BNC_DEMO_TEST).body([0x00]), seconds);
return this.send(new Command(BNC_DEMO_TEST).body([0x00]), seconds);
};
Jensen.prototype.getSettings = async function (seconds) {
if (this.versionNumber < 327714) {
return { autoRecord: false, autoPlay: false };
}
return this.send(new Command(GET_SETTINGS), seconds);
if (this.versionNumber < 327714) {
return { autoRecord: false, autoPlay: false };
}
return this.send(new Command(GET_SETTINGS), seconds);
};
Jensen.prototype.setAutoRecord = function (enable, seconds) {
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, enable ? 1 : 2]), seconds);
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, enable ? 1 : 2]), seconds);
};
Jensen.prototype.setAutoPlay = function (enable, seconds) {
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, enable ? 1 : 2,]), seconds);
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, enable ? 1 : 2]), seconds);
};
Jensen.prototype.setNotification = function (enable, seconds) {
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, enable ? 1 : 2]), seconds);
if (this.versionNumber < 327714) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, enable ? 1 : 2]), seconds);
};
Jensen.prototype.setBluetoothPromptPlay = function (enable, seconds) {
// h1e 6.1.4 393476
// h1 5.1.4 327940
if (this.model === 'hidock-h1e' && this.versionNumber < 393476) return { result: false }
if (this.model === 'hidock-h1' && this.versionNumber < 327940) return { result: false }
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, enable ? 2 : 1]), seconds);
}
// h1e 6.1.4 393476
// h1 5.1.4 327940
if (this.model === 'hidock-h1e' && this.versionNumber < 393476) return { result: false };
if (this.model === 'hidock-h1' && this.versionNumber < 327940) return { result: false };
return this.send(new Command(SET_SETTINGS).body([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, enable ? 2 : 1]), seconds);
};
Jensen.prototype.getCardInfo = function (seconds) {
if (this.versionNumber < 327733) return null;
return this.send(new Command(READ_CARD_INFO), seconds);
if (this.versionNumber < 327733) return null;
return this.send(new Command(READ_CARD_INFO), seconds);
};
Jensen.prototype.formatCard = function (seconds) {
if (this.versionNumber < 327733) return null;
return this.send(new Command(FORMAT_CARD).body([0x01, 0x02, 0x03, 0x04]), seconds);
if (this.versionNumber < 327733) return null;
return this.send(new Command(FORMAT_CARD).body([0x01, 0x02, 0x03, 0x04]), seconds);
};
Jensen.prototype.getRecordingFile = function (seconds) {
if (this.versionNumber < 327733) return null;
return this.send(new Command(GET_RECORDING_FILE), seconds);
if (this.versionNumber < 327733) return null;
return this.send(new Command(GET_RECORDING_FILE), seconds);
};
Jensen.prototype.recordTestStart = async function (type, seconds) {
return this.send(new Command(0xf008).body([type]), seconds);
return this.send(new Command(0xf008).body([type]), seconds);
};
Jensen.prototype.recordTestEnd = async function (type, seconds) {
return this.send(new Command(0xf009).body([type]), seconds);
return this.send(new Command(0xf009).body([type]), seconds);
};
Jensen.prototype.test = async function (seconds) {
return this.send(new Command(DEVICE_MSG_TEST), seconds);
return this.send(new Command(DEVICE_MSG_TEST), seconds);
};
Jensen.prototype.getFileBlock = async function (filename, length, ondata) {
if (typeof (length) != 'number') throw new Error('parameter `length` required');
if (length <= 0) throw new Error('parameter `length` must greater than zero');
if (this.fileLength > 0) return null;
let data = [];
data.push((length >> 24) & 0xff);
data.push((length >> 16) & 0xff);
data.push((length >> 8) & 0xff);
data.push((length >> 0) & 0xff);
for (let i = 0; i < filename.length; i++) data.push(filename.charCodeAt(i));
this.onFileRecvHandler = ondata;
this.fileLength = length;
this.fileReadBytes = 0;
return this.send(new Command(GET_FILE_BLOCK).body(data));
}
if (typeof length != 'number') throw new Error('parameter `length` required');
if (length <= 0) throw new Error('parameter `length` must greater than zero');
if (this.fileLength > 0) return null;
let data = [];
data.push((length >> 24) & 0xff);
data.push((length >> 16) & 0xff);
data.push((length >> 8) & 0xff);
data.push((length >> 0) & 0xff);
for (let i = 0; i < filename.length; i++) data.push(filename.charCodeAt(i));
this.onFileRecvHandler = ondata;
this.fileLength = length;
this.fileReadBytes = 0;
return this.send(new Command(GET_FILE_BLOCK).body(data));
};
Jensen.prototype.writeSerialNumber = async function (sn) {
let data = [];
for (let i = 0; i < sn.length; i++) {
data.push(sn.charCodeAt(i));
}
return this.send(new Command(TEST_SN_WRITE).body(data));
}
let data = [];
for (let i = 0; i < sn.length; i++) {
data.push(sn.charCodeAt(i));
}
return this.send(new Command(TEST_SN_WRITE).body(data));
};
const commonMessageParser = (msg) => {
return { result: msg.body[0] === 0x00 ? 'success' : 'failed' };
return { result: msg.body[0] === 0x00 ? 'success' : 'failed' };
};
Jensen.prototype.sendScheduleInfo = function (info) {
const startDate = this.to_bcd(getTimeStr(info.startDate));
const endDate = this.to_bcd(getTimeStr(info.endDate));
const keyAnswer = [3, 7, 4, 0, 0, 0, 0, 0];
const keyHangup = [3, 7, 5, 0, 0, 0, 0, 0];
const keyReject = [3, 7, 6, 0, 0, 0, 0, 0];
const keyMicMute = [3, 7, 7, 0, 0, 0, 0, 0];
const body = [...startDate, ...endDate, 0, 0, ...keyAnswer, ...keyHangup, ...keyReject, ...keyMicMute];
console.log('send schedule info', info, body);
return this.send(new Command(SCHEDULE_INFO).body(body));
};
let codes = new Array(33).fill(0);
if (shortcutKeys[info.platform] && shortcutKeys[info.platform][info.os]) {
codes = shortcutKeys[info.platform][info.os];
}
let startDate = new Array(7).fill(0);
let endDate = new Array(7).fill(0);
if (info.startDate && info.endDate) {
startDate = this.to_bcd(getTimeStr(info.startDate));
endDate = this.to_bcd(getTimeStr(info.endDate));
}
const reserved = 0x00; // 预留
const body = [...startDate, ...endDate, 0x00, ...codes];
console.log('send schedule info', info, body);
return this.send(new Command(SCHEDULE_INFO).body(body));
};
Jensen.registerHandler(SET_DEVICE_TIME, commonMessageParser);
Jensen.registerHandler(BNC_DEMO_TEST, commonMessageParser);
Jensen.registerHandler(DELETE_FILE, (msg) => {
let rst = 'failed';
if (msg.body[0] === 0x00) rst = 'success';
else if (msg.body[0] === 0x01) rst = 'not-exists';
else if (msg.body[0] === 0x02) rst = 'failed';
return { result: rst };
let rst = 'failed';
if (msg.body[0] === 0x00) rst = 'success';
else if (msg.body[0] === 0x01) rst = 'not-exists';
else if (msg.body[0] === 0x02) rst = 'failed';
return { result: rst };
});
Jensen.registerHandler(QUERY_DEVICE_INFO, (msg, jensen) => {
let vc = [],
vn = 0;
let sn = [];
for (let i = 0; i < 4; i++) {
let b = msg.body[i] & 0xff;
if (i > 0) {
vc.push(String(b));
}
vn = vn | (b << ((4 - i - 1) * 8));
}
for (let i = 0; i < 16; i++) {
let chr = msg.body[i + 4];
if (chr > 0) sn.push(String.fromCharCode(chr));
let vc = [],
vn = 0;
let sn = [];
for (let i = 0; i < 4; i++) {
let b = msg.body[i] & 0xff;
if (i > 0) {
vc.push(String(b));
}
jensen.versionCode = vc.join('.');
jensen.versionNumber = vn;
sn = sn.join('');
jensen.serialNumber = sn;
return {
versionCode: vc.join('.'),
versionNumber: vn,
sn: sn,
};
vn = vn | (b << ((4 - i - 1) * 8));
}
for (let i = 0; i < 16; i++) {
let chr = msg.body[i + 4];
if (chr > 0) sn.push(String.fromCharCode(chr));
}
jensen.versionCode = vc.join('.');
jensen.versionNumber = vn;
sn = sn.join('');
jensen.serialNumber = sn;
return {
versionCode: vc.join('.'),
versionNumber: vn,
sn: sn
};
});
Jensen.registerHandler(QUERY_DEVICE_TIME, (msg, jensen) => {
let time = jensen.from_bcd(
msg.body[0] & 0xff,
msg.body[1] & 0xff,
msg.body[2] & 0xff,
msg.body[3] & 0xff,
msg.body[4] & 0xff,
msg.body[5] & 0xff,
msg.body[6] & 0xff,
);
return {
time: time === '00000000000000' ? 'unknown' : time.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/gi, '$1-$2-$3 $4:$5:$6'),
};
let time = jensen.from_bcd(
msg.body[0] & 0xff,
msg.body[1] & 0xff,
msg.body[2] & 0xff,
msg.body[3] & 0xff,
msg.body[4] & 0xff,
msg.body[5] & 0xff,
msg.body[6] & 0xff
);
return {
time: time === '00000000000000' ? 'unknown' : time.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})$/gi, '$1-$2-$3 $4:$5:$6')
};
});
Jensen.registerHandler(QUERY_FILE_COUNT, (msg) => {
if (msg.body.length === 0) return { count: 0 };
let c = 0;
for (let i = 0; i < 4; i++) {
let b = msg.body[i] & 0xff;
c = c | (b << ((4 - i - 1) * 8));
}
return { count: c };
if (msg.body.length === 0) return { count: 0 };
let c = 0;
for (let i = 0; i < 4; i++) {
let b = msg.body[i] & 0xff;
c = c | (b << ((4 - i - 1) * 8));
}
return { count: c };
});
Jensen.registerHandler(GET_SETTINGS, (msg) => {
let r1 = msg.body[3];
let r2 = msg.body[7];
let r4 = msg.body[15];
let rst = { autoRecord: r1 === 1, autoPlay: r2 === 1, bluetoothTone: !(r4 === 1) };
if (msg.body.length >= 12) {
let r3 = msg.body[11] === 1;
rst['notification'] = r3;
}
return rst;
let r1 = msg.body[3];
let r2 = msg.body[7];
let r4 = msg.body[15];
let rst = { autoRecord: r1 === 1, autoPlay: r2 === 1, bluetoothTone: !(r4 === 1) };
if (msg.body.length >= 12) {
let r3 = msg.body[11] === 1;
rst['notification'] = r3;
}
return rst;
});
Jensen.registerHandler(SET_SETTINGS, commonMessageParser);
Jensen.registerHandler(FACTORY_RESET, commonMessageParser);
Jensen.registerHandler(RESTORE_FACTORY_SETTINGS, commonMessageParser);
Jensen.registerHandler(REQUEST_FIRMWARE_UPGRADE, (msg) => {
let rst = '';
let c = msg.body[0];
if (c === 0x00) rst = 'accepted';
if (c === 0x01) rst = 'wrong-version';
if (c === 0x02) rst = 'busy';
if (c === 0x03) return 'unknown';
return { result: rst };
let rst = '';
let c = msg.body[0];
if (c === 0x00) rst = 'accepted';
if (c === 0x01) rst = 'wrong-version';
if (c === 0x02) rst = 'busy';
if (c === 0x03) return 'unknown';
return { result: rst };
});
Jensen.registerHandler(FIRMWARE_UPLOAD, (msg) => {
let c = msg.body[0];
return { result: c === 0x00 ? 'success' : 'failed' };
let c = msg.body[0];
return { result: c === 0x00 ? 'success' : 'failed' };
});
Jensen.registerHandler(READ_CARD_INFO, (msg) => {
let i = 0;
let used = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
let capacity = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
let status = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
let i = 0;
let used = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
let capacity = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
let status = ((msg.body[i++] & 0xff) << 24) | ((msg.body[i++] & 0xff) << 16) | ((msg.body[i++] & 0xff) << 8) | (msg.body[i++] & 0xff);
return { used: used, capacity: capacity, status: status.toString(16) };
return { used: used, capacity: capacity, status: status.toString(16) };
});
Jensen.registerHandler(FORMAT_CARD, commonMessageParser);
Jensen.registerHandler(GET_RECORDING_FILE, (msg) => {
if (msg.body == null || msg.body.length === 0) return { recording: null };
else {
let fname = [];
for (var i = 0; i < msg.body.length; i++) {
fname.push(String.fromCharCode(msg.body[i]));
}
let fnpad = function (v) {
return v > 9 ? v : '0' + v;
};
let ftime = fname.join('');
if (ftime.match(/^\d{14}REC\d+\.wav$/gi)) {
ftime = ftime.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})REC.*$/gi, '$1-$2-$3 $4:$5:$6');
ftime = new Date(ftime);
} else if (ftime.match(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi)) {
// 2024Mar19-110932-Rec00.hda
ftime = ftime.replace(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi, '20$2 $3 $4 $5:$6:$7');
ftime = new Date(ftime);
} else {
ftime = null;
}
let createDate = '';
let createTime = '';
if (ftime) {
createDate = ftime.getFullYear() + '/' + fnpad(ftime.getMonth() + 1) + '/' + fnpad(ftime.getDate());
createTime = fnpad(ftime.getHours()) + ':' + fnpad(ftime.getMinutes()) + ':' + fnpad(ftime.getSeconds());
}
return {
recording: fname.join(''),
name: fname.join(''),
createDate: createDate,
createTime: createTime,
time: ftime,
duration: 0,
length: 0,
signature: '0'.repeat(32),
};
if (msg.body == null || msg.body.length === 0) return { recording: null };
else {
let fname = [];
for (var i = 0; i < msg.body.length; i++) {
fname.push(String.fromCharCode(msg.body[i]));
}
let fnpad = function (v) {
return v > 9 ? v : '0' + v;
};
let ftime = fname.join('');
if (ftime.match(/^\d{14}REC\d+\.wav$/gi)) {
ftime = ftime.replace(/^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})REC.*$/gi, '$1-$2-$3 $4:$5:$6');
ftime = new Date(ftime);
} else if (ftime.match(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi)) {
// 2024Mar19-110932-Rec00.hda
ftime = ftime.replace(/^(\d{2})?(\d{2})(\w{3})(\d{2})-(\d{2})(\d{2})(\d{2})-.*\.hda$/gi, '20$2 $3 $4 $5:$6:$7');
ftime = new Date(ftime);
} else {
ftime = null;
}
let createDate = '';
let createTime = '';
if (ftime) {
createDate = ftime.getFullYear() + '/' + fnpad(ftime.getMonth() + 1) + '/' + fnpad(ftime.getDate());
createTime = fnpad(ftime.getHours()) + ':' + fnpad(ftime.getMinutes()) + ':' + fnpad(ftime.getSeconds());
}
return {
recording: fname.join(''),
name: fname.join(''),
createDate: createDate,
createTime: createTime,
time: ftime,
duration: 0,
length: 0,
signature: '0'.repeat(32)
};
}
});
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(TEST_SN_WRITE, commonMessageParser);
Jensen.registerHandler(SCHEDULE_INFO, commonMessageParser);
export { Jensen };
const Level = {
debug: "debug",
info: "info",
error: "error",
debug: 'debug',
info: 'info',
error: 'error'
};
export const Logger = {
......@@ -22,7 +22,7 @@ export const Logger = {
module,
procedure,
message: String(message),
time: new Date().getTime(),
time: new Date().getTime()
};
this.messages.push(log);
if (this.consoleOutput) {
......@@ -33,22 +33,20 @@ export const Logger = {
_print(log) {
let time = new Date(log.time);
console.info(
"[" +
(log.level === "error" ? "x" : "*") +
"][" +
'[' +
(log.level === 'error' ? 'x' : '*') +
'][' +
time.toLocaleString() +
"](" +
'](' +
log.module +
" - " +
' - ' +
log.procedure +
") " +
log.message,
') ' +
log.message
);
},
filter(module, procedure) {
return this.messages.filter(
(i) => i.module === module && i.procedure === procedure,
);
return this.messages.filter((i) => i.module === module && i.procedure === procedure);
},
enableConsoleOutput() {
this.consoleOutput = true;
......@@ -71,25 +69,250 @@ export const Logger = {
}
return true;
});
},
}
};
export const getTimeStr = (date: Date) => {
let str =
date.getFullYear() +
"-0" +
'-0' +
(date.getMonth() + 1) +
"-0" +
'-0' +
date.getDate() +
"-0" +
'-0' +
date.getHours() +
"-0" +
'-0' +
date.getMinutes() +
"-0" +
'-0' +
date.getSeconds();
str = str.replace(
/(\d{4})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})/gi,
"$1$2$3$4$5$6",
);
str = str.replace(/(\d{4})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})\-0*(\d{2})/gi, '$1$2$3$4$5$6');
return str;
};
const keyMap: { [key: string]: number } = {
A: 0x04,
B: 0x05,
C: 0x06,
D: 0x07,
E: 0x08,
F: 0x09,
G: 0x0a,
H: 0x0b,
I: 0x0c,
J: 0x0d,
K: 0x0e,
L: 0x0f,
M: 0x10,
N: 0x11,
O: 0x12,
P: 0x13,
Q: 0x14,
R: 0x15,
S: 0x16,
T: 0x17,
U: 0x18,
V: 0x19,
W: 0x1a,
X: 0x1b,
Y: 0x1c,
Z: 0x1b,
ENTER: 0x28,
ESCAPE: 0x29,
SPACE: 0x2c
};
const HotKeyBuilder = {
control: false,
shift: false,
alt: false,
guiKey: false,
keys: [],
withControl: () => {
HotKeyBuilder.control = true;
return HotKeyBuilder;
},
withShift: () => {
HotKeyBuilder.shift = true;
return HotKeyBuilder;
},
withAlt: () => {
HotKeyBuilder.alt = true;
return HotKeyBuilder;
},
withGuiKey: () => {
HotKeyBuilder.guiKey = true;
return HotKeyBuilder;
},
withKey: (key: string) => {
if (HotKeyBuilder.keys.length >= 2) throw new Error('exceed max key bindings');
HotKeyBuilder.keys.push(HotKeyBuilder.__mapping(key));
return HotKeyBuilder;
},
__mapping: (key: string) => {
return keyMap[key];
},
build: () => {
let key1 = 0;
if (HotKeyBuilder.control) key1 |= 0x01 << 0;
if (HotKeyBuilder.shift) key1 |= 0x01 << 1;
if (HotKeyBuilder.alt) key1 |= 0x01 << 2;
if (HotKeyBuilder.guiKey) key1 |= 0x01 << 3;
let codes = [
0x03,
key1,
HotKeyBuilder.keys.length ? HotKeyBuilder.keys[0] : 0x00,
HotKeyBuilder.keys.length > 1 ? HotKeyBuilder.keys[1] : 0x00,
0x00,
0x00,
0x00,
0x00
];
HotKeyBuilder.control = false;
HotKeyBuilder.shift = false;
HotKeyBuilder.alt = false;
HotKeyBuilder.guiKey = false;
HotKeyBuilder.keys = [];
return codes;
}
};
const enterKeyCode = (answer: 0 | 1 = 0, hangup: 0 | 1 = 0, reject: 0 | 1 = 0, micMute: 0 | 1 = 0) => {
let code = 0;
if (answer) code |= 0x01 << 0;
if (hangup) code |= 0x01 << 1;
if (reject) code |= 0x01 << 2;
if (micMute) code |= 0x01 << 3;
return code;
};
const emptyCodes = [0, 0, 0, 0, 0, 0, 0, 0];
export const shortcutKeys = {
Zoom: {
Windows: [
enterKeyCode(0, 1),
...emptyCodes,
HotKeyBuilder.withAlt().withKey('Q').build(),
...emptyCodes,
HotKeyBuilder.withAlt().withKey('A').build()
],
Mac: [
enterKeyCode(0, 1),
...emptyCodes,
HotKeyBuilder.withGuiKey().withKey('W').build(),
...emptyCodes,
HotKeyBuilder.withGuiKey().withShift().withKey('A').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Teams: {
Windows: [
enterKeyCode(),
HotKeyBuilder.withControl().withShift().withKey('A').build(),
HotKeyBuilder.withControl().withShift().withKey('H').build(),
HotKeyBuilder.withControl().withShift().withKey('D').build(),
HotKeyBuilder.withControl().withShift().withKey('M').build()
],
Mac: [
enterKeyCode(),
HotKeyBuilder.withGuiKey().withShift().withKey('A').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('H').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('D').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('M').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
'Google Meetings': {
Windows: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withControl().withKey('D').build()],
Mac: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withGuiKey().withKey('D').build()],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Webex: {
Windows: [
enterKeyCode(),
HotKeyBuilder.withControl().withShift().withKey('C').build(),
HotKeyBuilder.withControl().withKey('L').build(),
HotKeyBuilder.withControl().withKey('D').build(),
HotKeyBuilder.withControl().withKey('M').build()
],
Mac: [
enterKeyCode(),
HotKeyBuilder.withControl().withShift().withKey('C').build(),
HotKeyBuilder.withGuiKey().withKey('L').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('D').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('M').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Feishu: {
Windows: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withControl().withShift().withKey('D').build()],
Mac: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withGuiKey().withShift().withKey('D').build()],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Lark: {
Windows: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withControl().withShift().withKey('D').build()],
Mac: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withGuiKey().withShift().withKey('D').build()],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
WeChat: {
Windows: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes],
Mac: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Line: {
Windows: [
enterKeyCode(0, 1, 1),
...emptyCodes,
HotKeyBuilder.withKey('ESCAPE').build(),
HotKeyBuilder.withKey('ESCAPE').build(),
HotKeyBuilder.withControl().withShift().withKey('A').build()
],
Mac: [
enterKeyCode(0, 1, 1),
...emptyCodes,
HotKeyBuilder.withKey('ESCAPE').build(),
HotKeyBuilder.withKey('ESCAPE').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('A').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
WhatsApp: {
Windows: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes],
Mac: [
enterKeyCode(),
...emptyCodes,
HotKeyBuilder.withGuiKey().withKey('W').build(),
HotKeyBuilder.withGuiKey().withKey('W').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('M').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Slack: {
Windows: [
enterKeyCode(),
...emptyCodes,
...emptyCodes,
...emptyCodes,
HotKeyBuilder.withControl().withShift().withKey('SPACE').build()
],
Mac: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, HotKeyBuilder.withGuiKey().withShift().withKey('SPACE').build()],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
},
Discord: {
Windows: [
enterKeyCode(),
HotKeyBuilder.withControl().withKey('ENTER').build(),
...emptyCodes,
HotKeyBuilder.withKey('ESCAPE').build(),
HotKeyBuilder.withControl().withShift().withKey('M').build()
],
Mac: [
enterKeyCode(),
HotKeyBuilder.withGuiKey().withKey('ENTER').build(),
...emptyCodes,
HotKeyBuilder.withGuiKey().withKey('ESCAPE').build(),
HotKeyBuilder.withGuiKey().withShift().withKey('M').build()
],
Linux: [enterKeyCode(), ...emptyCodes, ...emptyCodes, ...emptyCodes, ...emptyCodes]
}
};
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