diff --git a/packages/usb/set-variable.ts b/packages/usb/set-variable.ts index 14e6cb1c745..c323cc8c9a8 100755 --- a/packages/usb/set-variable.ts +++ b/packages/usb/set-variable.ts @@ -1,39 +1,53 @@ #!/usr/bin/env -S node --loader ts-node/esm --no-warnings=ExperimentalWarning -import Uhk, { errorHandler, yargs } from './src/index.js'; -import { UsbVariables } from 'uhk-usb'; - -(async () => { - try { - const keys = Object.keys(UsbVariables) - .filter((key: any) => isNaN(key)) - .join(', '); - - const argv = yargs - .scriptName('./set-variable.ts') - .usage('Usage: $0 ') - .demandCommand(1, `Variable is required. Specify one of: ${keys}`) - .argv as any; - - const variable = argv._[0] as string; - - if (!Object.values(UsbVariables).includes(variable)) { - console.error(`The specified variable does not exist. Specify one of: ${keys}`); - process.exit(1); - } +import { + UhkHidDevice, + UhkOperations, + UsbVariables, +} from 'uhk-usb'; + +import Uhk, { errorHandler, getHidDevicesFromDeviceArg, yargs } from './src/index.js'; + +try { + const keys = Object.keys(UsbVariables) + .filter((key: any) => isNaN(key)) + .join(', '); + + const argv = yargs + .scriptName('./set-variable.ts') + .usage('Usage: $0 ') + .demandCommand(2, `Variable is required. Specify one of: ${keys}`) + .argv as any; + + const variable = argv._[0] as string; + + if (!Object.values(UsbVariables).includes(variable)) { + console.error(`The specified variable does not exist. Specify one of: ${keys}`); + process.exit(1); + } - const value = parseInt(argv._[1]); + const value = parseInt(argv._[1]); - if (isNaN(value)) { - console.error(`Value must be a number.`); - process.exit(1); - } + if (isNaN(value)) { + console.error(`Value must be a number.`); + process.exit(1); + } + if (argv.device) { + const hidDevices = await getHidDevicesFromDeviceArg(argv.device); + const { logger, rootDir } = Uhk(argv); + + for (const hidDevice of hidDevices) { + const uhkHidDevice = new UhkHidDevice(logger, argv, rootDir, hidDevice); + const uhkOperations = new UhkOperations(logger, uhkHidDevice); + await uhkOperations.setVariable(UsbVariables[variable], value); + } + } + else { const { operations } = Uhk(argv); await operations.setVariable(UsbVariables[variable], value); - - } catch (error) { - await errorHandler(error); } -})(); +} catch (error) { + await errorHandler(error); +} diff --git a/packages/usb/src/command-line.ts b/packages/usb/src/command-line.ts index 61e85218599..cccbcaaeb8a 100644 --- a/packages/usb/src/command-line.ts +++ b/packages/usb/src/command-line.ts @@ -1,17 +1,25 @@ +import { ALL_UHK_DEVICES } from 'uhk-common'; import { assertCommandLineOptions } from 'uhk-usb'; import Yargs from 'yargs'; import { hideBin } from 'yargs/helpers'; +import { getDevicesOptions } from './util/index.js'; + +const deviceOptions = getDevicesOptions(ALL_UHK_DEVICES); + export const yargs = Yargs(hideBin(process.argv)) .showHelpOnFail(true) + .option('device', { + description: `Run the command on the specified device(s) --device=uhk80-left,uhk80-right. Options: {${deviceOptions}}`, + type: 'string', + }) .option('help', { description: 'Display help message' }) .option('log', { - description: 'Set logging categories. --log=misc,usb. Default is "none"', + description: 'Set logging categories. --log=misc,usb. Options: {all|config|misc|none|usb} Default is "none"', type: 'string', default: 'none', - choices: ['all', 'config', 'misc', 'none', 'usb'] }) .option('no-report-id', { description: "Don't use report id for USB communication. The default value depends on the UHK device. You can not set --report-id and --no-report-id at the same time.", diff --git a/packages/usb/src/util/get-uhk-device-product-from-arg.ts b/packages/usb/src/util/get-uhk-device-product-from-arg.ts index dbf84dd41c5..5a06c2c3d3f 100644 --- a/packages/usb/src/util/get-uhk-device-product-from-arg.ts +++ b/packages/usb/src/util/get-uhk-device-product-from-arg.ts @@ -1,6 +1,9 @@ +import { Device, devicesAsync } from 'node-hid'; import { + ALL_UHK_DEVICES, UhkDeviceProduct, } from 'uhk-common'; +import { isUhkCommunicationUsage } from 'uhk-usb/dist/src/index.js'; export function getUhkDeviceProductFromArg(uhkDevices: UhkDeviceProduct[], deviceArg: string): UhkDeviceProduct { const uhkDeviceProduct = uhkDevices.find(uhkDevice => uhkDevice.asCliArg === deviceArg); @@ -17,3 +20,38 @@ export function getUhkDeviceProductFromArg(uhkDevices: UhkDeviceProduct[], devic export function getDevicesOptions(uhkDevices: UhkDeviceProduct[]): string { return uhkDevices.map(uhkDevice => uhkDevice.asCliArg).join('|'); } + +export async function getHidDevicesFromDeviceArg(deviceArg: string): Promise { + if (!deviceArg) { + return []; + } + + const result: Device[] = []; + + const hidDevices = await devicesAsync(); + + const deviceClas = deviceArg.split(','); + for (const deviceCla of deviceClas) { + const uhkDeviceProduct = getUhkDeviceProductFromArg(ALL_UHK_DEVICES, deviceCla); + + const devices = hidDevices.filter(hidDevice => uhkDeviceProduct.keyboard.some(vidPid => { + return vidPid.vid === hidDevice.vendorId + && vidPid.pid == hidDevice.productId + && isUhkCommunicationUsage(hidDevice); + })); + + if (devices.length === 0) { + console.error(`Can not find connected device: ${deviceArg}.`); + process.exit(1); + } + + if (devices.length > 1) { + console.error(`Multiple ${deviceArg} device connected.`); + process.exit(1); + } + + result.push(devices[0]); + } + + return result; +}