From ab312236b14cb8f961d0b0bf878c611487a5983f Mon Sep 17 00:00:00 2001 From: Johan Nyman Date: Thu, 18 Nov 2021 18:33:09 +0100 Subject: [PATCH] feat: add usePolling option to the XKeysWatcher to fall back to polling, since "usb-detection" might not work on all OS:es --- packages/node/examples/multiple-panels.js | 4 ++ packages/node/src/watcher.ts | 63 ++++++++++++++--------- 2 files changed, 44 insertions(+), 23 deletions(-) diff --git a/packages/node/examples/multiple-panels.js b/packages/node/examples/multiple-panels.js index 5d7323b..d93b1a9 100644 --- a/packages/node/examples/multiple-panels.js +++ b/packages/node/examples/multiple-panels.js @@ -18,6 +18,10 @@ const memory = {} // Set up the watcher for xkeys: const watcher = new XKeysWatcher({ automaticUnitIdMode: true, + + // If running on a system (such as some linux flavors) where the 'usb-detection' library doesn't work, enable usePolling instead: + // usePolling: true, + // pollingInterval: 1000, }) watcher.on('connected', (xkeysPanel) => { diff --git a/packages/node/src/watcher.ts b/packages/node/src/watcher.ts index 5008a2f..34ff22a 100644 --- a/packages/node/src/watcher.ts +++ b/packages/node/src/watcher.ts @@ -27,14 +27,12 @@ function USBDetect(): USBDetectType { // It's not installed } } - // else emit error: - throw `XKeysWatcher requires the dependency "usb-detection" to be installed, It might have been skipped due to your platform being unsupported (this is an issue with "usb-detection", not the X-keys library). - -You can try to install the depencency manually, by running "npm install usb-detection". - -If you're unable to install the "usb-detection" library, you can still connect to X-keys panels manually by using XKeys.setupXkeysPanel() instead. +Possible solutions are: +* You can try to install the depencency manually, by running "npm install usb-detection". +* Use the fallback "usePolling" functionality instead: new XKeysWatcher({ usePolling: true}) +* Otherwise you can still connect to X-keys panels manually by using XKeys.setupXkeysPanel(). ` } @@ -70,19 +68,26 @@ export class XKeysWatcher extends EventEmitter { private prevConnectedIdentifiers: { [key: string]: XKeys } = {} /** Unique unitIds grouped into productId groups. */ private uniqueIds = new Map() + private pollingInterval: NodeJS.Timeout | undefined = undefined constructor(private options?: XKeysWatcherOptions) { super() - watcherCount++ - if (watcherCount === 1) { - // We've just started watching - USBDetect().startMonitoring() - } + if (!this.options?.usePolling) { + watcherCount++ + if (watcherCount === 1) { + // We've just started watching + USBDetect().startMonitoring() + } - // Watch for added devices: - USBDetect().on(`add:${XKEYS_VENDOR_ID}`, this.onAddedUSBDevice) - USBDetect().on(`remove:${XKEYS_VENDOR_ID}`, this.onRemovedUSBDevice) + // Watch for added devices: + USBDetect().on(`add:${XKEYS_VENDOR_ID}`, this.onAddedUSBDevice) + USBDetect().on(`remove:${XKEYS_VENDOR_ID}`, this.onRemovedUSBDevice) + } else { + this.pollingInterval = setInterval(() => { + this.updateConnectedDevices() + }, this.options?.pollingInterval ?? 1000) + } // Also do a sweep for all currently connected X-keys panels: this.updateConnectedDevices() @@ -94,15 +99,22 @@ export class XKeysWatcher extends EventEmitter { public async stop(closeAllDevices = true): Promise { this.isMonitoring = false - // Remove the listeners: - // @ts-expect-error usb-detection exposes wrong types: - USBDetect().removeListener(`add:${XKEYS_VENDOR_ID}`, this.onAddedUSBDevice) - // @ts-expect-error usb-detection exposes wrong types: - USBDetect().removeListener(`remove:${XKEYS_VENDOR_ID}`, this.onRemovedUSBDevice) + if (!this.options?.usePolling) { + // Remove the listeners: + // @ts-expect-error usb-detection exposes wrong types: + USBDetect().removeListener(`add:${XKEYS_VENDOR_ID}`, this.onAddedUSBDevice) + // @ts-expect-error usb-detection exposes wrong types: + USBDetect().removeListener(`remove:${XKEYS_VENDOR_ID}`, this.onRemovedUSBDevice) + + watcherCount-- + if (watcherCount === 0) { + USBDetect().stopMonitoring() + } + } - watcherCount-- - if (watcherCount === 0) { - USBDetect().stopMonitoring() + if (this.pollingInterval) { + clearInterval(this.pollingInterval) + this.pollingInterval = undefined } if (closeAllDevices) { @@ -270,5 +282,10 @@ export interface XKeysWatcherOptions { * First, any x-keys panel with unitId===0 will be issued a (pseudo unique) unitId upon connection, in order for it to be uniquely identified. * This allows for the connection-events to work a bit differently, mainly enabling the "reconnected"-event for when a panel has been disconnected, then reconnected again. */ - automaticUnitIdMode: true + automaticUnitIdMode?: boolean + + /** If set, will use polling for devices instead of watching for them directly. Might be a bit slower, but is more compatible. */ + usePolling?: boolean + /** If usePolling is set, the interval to use for checking for new devices. */ + pollingInterval?: number }