Files
agent/packages/uhk-usb/src/util.ts
Róbert Kiss 653465f0e0 feat: device recovery mode (#642)
* add new page and ipc processing

* refactor: remove unused references from uhk.js

* feat: add device recovery route

* refactor: device permission

* feat: write firmware update log to the screen

* fix: xterm height

* feat: add reload button to the recovery page

* refactor: deviceConnectionState.hasPermission in appStartInfo

* refactor: use correct imports

* refactor: move .ok-button css class to the main style.scss

* feat: add bootload active route guard

* style: move RecoveryDeviceAction into new line

* feat: delete reload button

* feat: start device polling after device recovery
2018-05-19 17:22:46 +02:00

104 lines
3.1 KiB
TypeScript

import { Constants, UsbCommand } from './constants';
import { DeviceConnectionState, LogService } from 'uhk-common';
export const snooze = ms => new Promise(resolve => setTimeout(resolve, ms));
/**
* Convert the Buffer to number[]
* @param {Buffer} buffer
* @returns {number[]}
* @private
* @static
*/
export function convertBufferToIntArray(buffer: Buffer): number[] {
return Array.prototype.slice.call(buffer, 0);
}
/**
* Split the communication package into 64 byte fragments
* @param {UsbCommand} usbCommand
* @param {Buffer} configBuffer
* @returns {Buffer[]}
* @private
*/
export function getTransferBuffers(usbCommand: UsbCommand, configBuffer: Buffer): Buffer[] {
const fragments: Buffer[] = [];
const MAX_SENDING_PAYLOAD_SIZE = Constants.MAX_PAYLOAD_SIZE - 4;
for (let offset = 0; offset < configBuffer.length; offset += MAX_SENDING_PAYLOAD_SIZE) {
const length = offset + MAX_SENDING_PAYLOAD_SIZE < configBuffer.length
? MAX_SENDING_PAYLOAD_SIZE
: configBuffer.length - offset;
const header = new Buffer([usbCommand, length, offset & 0xFF, offset >> 8]);
fragments.push(Buffer.concat([header, configBuffer.slice(offset, offset + length)]));
}
return fragments;
}
/**
* Create the communication package that will send over USB and
* @param {Buffer} buffer
* @returns {number[]}
* @private
* @static
*/
export function getTransferData(buffer: Buffer): number[] {
const data = convertBufferToIntArray(buffer);
data.unshift(0);
return data;
}
/**
* Convert buffer to space separated hexadecimal string
* @param {Buffer} buffer
* @returns {string}
* @private
* @static
*/
export function bufferToString(buffer: Array<number>): string {
let str = '';
for (let i = 0; i < buffer.length; i++) {
let hex = buffer[i].toString(16) + ' ';
if (hex.length <= 2) {
hex = '0' + hex;
}
str += hex;
}
return str;
}
export async function retry(command: Function, maxTry = 3, logService?: LogService): Promise<any> {
let retryCount = 0;
while (true) {
try {
// logService.debug(`[retry] try to run FUNCTION:\n ${command}, \n retry: ${retryCount}`);
await command();
await snooze(100);
// logService.debug(`[retry] success FUNCTION:\n ${command}, \n retry: ${retryCount}`);
return;
} catch (err) {
retryCount++;
if (retryCount >= maxTry) {
if (logService) {
// logService.error(`[retry] failed and no try rerun FUNCTION:\n ${command}, \n retry: ${retryCount}`);
}
throw err;
} else {
if (logService) {
logService.info(`[retry] failed, but try run FUNCTION:\n ${command}, \n retry: ${retryCount}`);
}
}
}
}
}
export const deviceConnectionStateComparer = (a: DeviceConnectionState, b: DeviceConnectionState): boolean => {
return a.hasPermission === b.hasPermission
&& a.connected === b.connected
&& a.bootloaderActive === b.bootloaderActive;
};