import { Device , devices } from 'node-hid' ; import { readFile } from 'fs-extra' ; import { EOL } from 'os' ; import MemoryMap from 'nrf-intel-hex' ; import { Buffer , LogService , UHK_DEVICES , UhkDeviceProduct } from 'uhk-common' ; import { Constants , UsbCommand } from './constants' ; export const snooze = ms => new Promise ( resolve => setTimeout ( resolve , ms ) ) ; param { Buffer } buffer returns { number [ ] } private static export function convertBufferToIntArray ( buffer ) { return Array . prototype . slice . call ( buffer , 0 ) ; } param { UsbCommand } usbCommand param { Buffer } configBuffer returns { Buffer [ ] } private export function getTransferBuffers ( usbCommand , configBuffer ) { const fragments = [ ] ; 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 = Buffer . from ( [ usbCommand , length , offset & 0xFF , offset >> 8 ] ) ; fragments . push ( Buffer . concat ( [ header , configBuffer . slice ( offset , offset + length ) ] ) ) ; } return fragments ; } param { Buffer } buffer returns { number [ ] } private static export function getTransferData ( buffer ) { const data = convertBufferToIntArray ( buffer ) ; data . unshift ( 0 ) ; return data ; } param { Buffer } buffer returns { string } private static export function bufferToString ( buffer ) { 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 , maxTry = 3 , logService ? ) { let retryCount = 0 ; while ( true ) { try { await command ( ) ; return ; } catch ( err ) { retryCount ++ ; if ( retryCount >= maxTry ) { if ( logService ) { } throw err ; } else { if ( logService ) { logService . misc ( `[retry] failed, but try run FUNCTION:\n ${ command }, \n retry: ${ retryCount }` ) ; } await snooze ( 100 ) ; } } } } export const isUhkZeroInterface = ( dev ) : boolean => { return UHK_DEVICES . some ( device => dev . vendorId === device . vendorId && dev . productId === device . keyboardPid && dev . interface === 0 ) ; } ; export const getUhkDevice = ( dev ) : UhkDeviceProduct => { return UHK_DEVICES . find ( device => dev . vendorId === device . vendorId && ( dev . productId === device . keyboardPid || dev . productId === device . bootloaderPid ) ) ; } ; export const isBootloader = ( dev ) : boolean => { return UHK_DEVICES . some ( device => dev . vendorId === device . vendorId && dev . productId === device . bootloaderPid ) ; } ; export const getFileContentAsync = async ( filePath ) : Promise < Array < string > > => { const fileContent = await readFile ( filePath , { encoding : 'utf-8' } ) ; return fileContent . split ( EOL ) . map ( x => x . trim ( ) ) . filter ( x => ! x . startsWith ( '#' ) && x . length > 0 ) ; } ; export const readBootloaderFirmwareFromHexFileAsync = async ( hexFilePath ) : Promise < Map < any , any > > => { const fileContent = await readFile ( hexFilePath , { encoding : 'utf8' } ) ; const memoryMap = MemoryMap . fromHex ( fileContent ) ; return memoryMap ; } ; export const waitForDevice = async ( vendorId , productId ) : Promise < void > => { const startTime = new Date ( ) . getTime ( ) + 15000 ; while ( startTime > new Date ( ) . getTime ( ) ) { const isAvailable = devices ( ) . some ( dev => dev . vendorId === vendorId && dev . productId === productId ) ; if ( isAvailable ) { await snooze ( 1000 ) ; return ; } await snooze ( 250 ) ; } throw new Error ( `Cannot find device with vendorId: ${ vendorId }, productId: ${ productId }` ) ; } ;