Code Monkey home page Code Monkey logo

xkeys's Introduction

xkeys

Node CI

A Node.js module to interact with the X-keys panels.

Licence: MIT

The project is based on the documentation available here: http://xkeys.com/PISupport/DeveloperHIDDataReports.php

Demo

If you are using a browser that supports WebHID, you can try out the library right away, in the browser: Demo.

Installation

To use in Node.js

$ npm install --save xkeys
or
$ yarn add xkeys

To use in browser

$ npm install --save xkeys-webhid
or
$ yarn add xkeys-webhid

Linux

On linux, the udev subsystem blocks access for non-root users to the X-keys without some special configuration. Save the following to /etc/udev/rules.d/50-xkeys.rules and reload the rules with sudo udevadm control --reload-rules

SUBSYSTEM=="input", GROUP="input", MODE="0666"
SUBSYSTEM=="usb", ATTRS{idVendor}=="05f3", MODE:="666", GROUP="plugdev"
KERNEL=="hidraw*", ATTRS{idVendor}=="05f3", MODE="0666", GROUP="plugdev"

Note: If you need more than 4 panels connected simultaneously, you might also have to set your env-var UV_THREADPOOL_SIZE:

var { env } = require('process')
env.UV_THREADPOOL_SIZE = 8 // Allow up to 8 panels

BREAKING CHANGES

Please note that version 2.0.0 is a BREAKING CHANGE, as most of the API have changed. If you're upgrading from <2.0.0, please read the Migrations section below.

Getting started - Node.js

See examples folder for more examples.

Watch for connected X-keys (recommended)

This is the recommended way to use this library, to automatically be connected or reconnected to the panel.

Note: The watcher depends on the node-usb library, which might be unsupported on some platforms.

const { XKeysWatcher } = require('xkeys')

/*
	This example connects to any connected x-keys panels and logs
	whenever a button is pressed or analog thing is moved
*/

// Set up the watcher for xkeys:
const watcher = new XKeysWatcher({
	// automaticUnitIdMode: false
	// usePolling: false
	// pollingInterval= 1000
})
watcher.on('error', (e) => {
	console.log('Error in XKeysWatcher', e)
})

watcher.on('connected', (xkeysPanel) => {
	console.log(`X-keys panel of type ${xkeysPanel.info.name} connected`)

	xkeysPanel.on('disconnected', () => {
		console.log(`X-keys panel of type ${xkeysPanel.info.name} was disconnected`)
		// Clean up stuff
		xkeysPanel.removeAllListeners()
	})
	xkeysPanel.on('error', (...errs) => {
		console.log('X-keys error:', ...errs)
	})

	// Listen to pressed buttons:
	xkeysPanel.on('down', (keyIndex, metadata) => {
		console.log('Button pressed ', keyIndex, metadata)

		// Light up a button when pressed:
		xkeysPanel.setBacklight(keyIndex, 'red')
	})
	// Listen to released buttons:
	xkeysPanel.on('up', (keyIndex, metadata) => {
		console.log('Button released', keyIndex, metadata)

		// Turn off button light when released:
		xkeysPanel.setBacklight(keyIndex, false)
	})

	// Listen to jog wheel changes:
	xkeysPanel.on('jog', (index, deltaPos, metadata) => {
		console.log(`Jog ${index} position has changed`, deltaPos, metadata)
	})
	// Listen to shuttle changes:
	xkeysPanel.on('shuttle', (index, shuttlePos, metadata) => {
		console.log(`Shuttle ${index} position has changed`, shuttlePos, metadata)
	})
	// Listen to joystick changes:

	xkeysPanel.on('joystick', (index, position, metadata) => {
		console.log(`Joystick ${index} position has changed`, position, metadata) // {x, y, z}
	})
	// Listen to t-bar changes:
	xkeysPanel.on('tbar', (index, position, metadata) => {
		console.log(`T-bar ${index} position has changed`, position, metadata)
	})
})

// To stop watching, call
// watcher.stop().catch(console.error)

Connect to a devices manually

const { setupXkeysPanel } = require('xkeys')

/*
	This example shows how to use XKeys.setupXkeysPanel()
	directly, instead of going via XKeysWatcher()
*/

// Connect to an xkeys-panel:
setupXkeysPanel()
	.then((xkeysPanel) => {
		xkeysPanel.on('disconnected', () => {
			console.log(`X-keys panel of type ${xkeysPanel.info.name} was disconnected`)
			// Clean up stuff
			xkeysPanel.removeAllListeners()
		})
		xkeysPanel.on('error', (...errs) => {
			console.log('X-keys error:', ...errs)
		})

		xkeysPanel.on('down', (keyIndex, metadata) => {
			console.log('Button pressed', keyIndex, metadata)
		})

		// ...
	})
	.catch(console.log) // Handle error

or

const { listAllConnectedPanels, setupXkeysPanel } = require('xkeys')

// List and connect to all xkeys-panels:
listAllConnectedPanels().forEach((connectedPanel) => {
	setupXkeysPanel(connectedPanel)
		.then((xkeysPanel) => {
			console.log(`Connected to ${xkeysPanel.info.name}`)

			// ...
		})
		.catch(console.log) // Handle error

Getting started - Browser (WebHID)

See the example implementation at packages/webhid-demo.

Demo

If you are using a Chromium v89+ based browser, you can try out the webhid demo.

API documentation

XKeysWatcher (Node.js only)

The XKeysWatcher has a few different options that can be set upon initialization:

const { XKeysWatcher } = require('xkeys')
const watcher = new XKeysWatcher({
	// automaticUnitIdMode: false
	// usePolling: false
	// pollingInterval= 1000
})
watcher.on('error', (e) => {
	console.log('Error in XKeysWatcher', e)
})
watcher.on('connected', (xkeysPanel) => {
	// xkeysPanel connected...
})

automaticUnitIdMode

When this is set to true, the XKeysWatcher will enable the "reconnected" event for the xkeysPanels.

By default, there is no unique identifier stored on the X-keys panel that can be used to differ between "reconnecting a previously known panel" or "connecting a new panel". The automaticUnitIdMode fixes this by writing a pseudo-unique id to the unitId of the panel, if none has been set previously.

usePolling

When this is set, the XKeysWatcher will not use the usb library for detecting connected panels, but instead resort to polling at an interval (pollingInterval). This is compatible with more systems and OS:es, but might result in slower detection of new panels.

xkeysPanel Events

// Example:
xkeysPanel.on('down', (keyIndex, metadata) => {
	console.log('Button pressed', keyIndex, metadata)
})
Event Description
"error" Triggered on error. Emitted with (error).
"down", "up" Triggered when a button is pressed/released. Emitted with (keyIndex, metadata).
"jog" Triggered when the jog wheel is moved. Emitted with (index, jogValue, metadata)
"shuttle" Triggered when the shuttle is moved. Emitted with (index, shuttleValue, metadata)
"joystick" Triggered when the joystick is moved. Emitted with (index, {x, y, z, deltaZ})
"tbar" Triggered when the T-bar is moved. Emitted with (index, tbarPosition, metadata)
"disconnected" Triggered when panel is disconnected.
"reconnected" Triggered when panel is reconnection. Only emitted when automaticUnitIdMode is enabled.

xkeysPanel Methods

Setting the backlight of a button

xkeysPanel.setBacklight(keyIndex, color)

// Examples:
// Set blue light
xkeysPanel.setBacklight(keyIndex, '0000ff')
// Set any available default light
xkeysPanel.setBacklight(keyIndex, true)
// Turn off light
xkeysPanel.setBacklight(keyIndex, false)
// Set flashing light
xkeysPanel.setBacklight(keyIndex, 'red', true)

// Set color (for RGB-supported devices)
xkeysPanel.setBacklight(keyIndex, 'ff3300')

Set the indicator LEDs (the red/green status LED's)

xkeysPanel.setIndicatorLED(ledIndex, on, flashing)

// Examples:
// Light up the green LED
xkeysPanel.setIndicatorLED(1, true)
// Flash the red LED
xkeysPanel.setIndicatorLED(2, true, true)

Set backlight intensity

xkeysPanel.setBacklightIntensity(intensity)

// Example:
// Set max intensity
xkeysPanel.setBacklightIntensity(255)

Set all backlights on or off

xkeysPanel.setAllBacklights(color)

// Example:
// Light up all buttons
xkeysPanel.setAllBacklights(true)
// Light up all buttons in a nice color
xkeysPanel.setAllBacklights('ff33ff')
// Turn of all buttons
xkeysPanel.setAllBacklights(false)

Set flashing frequency

// The frequency can be set to 1-255, where 1 is fastest and 255 is the slowest.
// 255 is approximately 4 seconds between flashes.
xkeysPanel.setFrequency(frequency)

// Example:
// Set the frequency to a pretty fast flash
xkeysPanel.setFrequency(8)

** Set unit ID **

// Sets the UID (unit Id) value in the X-keys hardware
// Note: This writes to the EEPROM, don't call this function too often, or you'll kill the EEPROM! (An EEPROM only support a few thousands of write operations.)
xkeysPanel.setUnitId(unitId)

** Save backlights **

// Save the backlights (so they are restored to this after a power cycle).
// Note: This writes to the EEPROM, don't call this function too often, or you'll kill the EEPROM! (An EEPROM only support a few thousands of write operations.)
xkeysPanel.saveBackLights()

Other functionality

See the XKeys-class for more functionality.

Supported devices

Thanks to official support from P.I Enginneering, the X-keys manufacturer, there is support for all official (and some experimental) devices.

See the full list in products.ts.

Migrations

2.0.0

Version 2.0.0 is a breaking changes, which requires several changes in how to use the library.

The most notable changes are:

Before, <2.0.0 Changes in >=2.0.0
let myXkeys = new XKeys() let myXkeys = await XKeys.setupXkeysPanel()
myXkeys.on('down', (keyIndex) => {} ) The numbering of keyIndexes has changed:
_ The PS-button is on index 0.
_ Other buttons start on index 1.
* Numbering of buttons have changed for some models.
myXkeys.on('downKey', (keyIndex) => {} ) Use .on('down') instead
myXkeys.on('upKey', (keyIndex) => {} ) Use .on('up') instead
myXkeys.on('downAlt', (keyIndex) => {} ) Use .on('down') instead (PS-button is on index 0)
myXkeys.on('upAlt', (keyIndex) => {} ) Use .on('up') instead (PS-button is on index 0)
myXkeys.on('jog', (position) => {} ) myXkeys.on('jog', (index, position) => {} )
myXkeys.on('shuttle', (position) => {} ) myXkeys.on('shuttle', (index, position) => {} )
myXkeys.on('tbar', (position, rawPosition) => {} ) myXkeys.on('tbar', (index, position) => {} )
myXkeys.on('joystick', (position) => {} ) myXkeys.on('joystick', (index, position) => {} )
myXkeys.setBacklight(...) Arguments have changed, see docs
myXkeys.setAllBacklights(...) Arguments have changed, see docs
myXkeys.setLED(index, ...) myXkeys.setIndicatorLED(index, ...) (index 1 = the red, 2 = the green one)

2.1.1

Version 2.1.1 has a minor change for when stopping the XKeysWatcher instance:

const watcher = new XKeysWatcher()
await watcher.stop() // Now returns a promise

For developers

This is a mono-repo, using Lerna and Yarn.

Setting up your local environment

This repo is using Yarn. If you don't want to use it, replace yarn xyz with npm run xyz below.

To install Yarn, just run npm install -g yarn.

Setting up the repo

  • Clone the repo and cd into it.
  • Install all dependencies: yarn.
  • Do an initial build: yarn build

Running and testing local changes

If you'd like to run and test your local changes, yarn link is a useful tool to symlink your local xkeys dependency into your test repo.

# To set up the xkeys-repo for linking:
cd your/xkeys/repo
yarn lerna exec yarn link # This runs "yarn link" in all of the mono-repo packages
yarn build

# Every time after you've made any changes to the xkeys-repo you need to rebuild
cd your/xkeys/repo
yarn build

# Set up your local test repo to used the linked xkeys libraries:
cd your/test/repo
yarn add xkeys
yarn link xkeys
yarn link @xkeys-lib/core

# To unlink the xkeys-lib from your local test repo:
cd your/test/repo
yarn unlink xkeys
yarn unlink @xkeys-lib/core
yarn --force # So that it reinstalls the ordinary dependencies

Contribution guidelines

If you have any questions or want to report a bug, please open an issue at Github.

If you want to contribute a bug fix or improvement, we'd happily accept Pull Requests. (If you're planning something big, please open an issue to announce it first, and spark discussions.

Coding style and tests

Please follow the same coding style as the rest of the repository as you type. :)

Before committing your code to git, be sure to run these commands:

yarn # To ensure the right dependencies are installed
yarn build # To ensure that there are no syntax or build errors
yarn lint # To ensure that the formatting follows the right rules
yarn test # To ensure that your code passes the unit tests.

If you're adding a new functionality, adding unit tests for it is much appreciated.

Notes for maintainers

Making a nightly build

Making a Pre-release

  • Update the branch (preferably the master branch)
  • yarn release:bump-prerelease and push the changes (including the tag)
  • Trigger a run of CI: publish-prerelease

Making a Release

License

By contributing, you agree that your contributions will be licensed under the MIT License.

xkeys's People

Contributors

arunsathiya avatar cwilling avatar cyraxx avatar dependabot[bot] avatar julusian avatar michaelhatpiengineering avatar nytamin avatar peternewman avatar superflytvab avatar taijavuh avatar zoton2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

xkeys's Issues

Handling of USB disconnect/reconnect

Been using the library for a while, works great!

...Except when a) you're on mac OS, and at the same time b) the panel is connected far down the USB tree, in a USB hub connected to a USB hub connected to a ...
Due to some limitation in mac OS APIs the path field will come back empty from node-hid, making the panel unusable.
There is ongoing work over at node-hid re this, and this issue is not in any way caused by the xkeys lib.

One thing is still an issue with the xkeys lib though: If a panel is disconnected while in use, the lib will loose track of the panel even if it's reconnected a minute (or a second) later.

That's fine really, but it would be nice with a solid process for handling disconnects/reconnects.

First idea:

  1. The app should keep track of the USB path of the panel it uses, as well as keep a variable myXkeysPanel for interacting with the panel in question.
  2. Set up USB listeners for add/remove events, maybe using https://github.com/MadLittleMods/node-usb-detection
  3. In the "removed" event handler, check if it was the panel in use that was removed. If so set the corresponding myXkeysPanel variable to null. The rest of the app must be smart enough to realize that null means "panel not connected".
  4. In the "add" event handler do the reverse of 3. I.e. determine whether it was the panel-in-use that was reconnected, and if so do a new HID enumeration, get connected panels and eventually something like a myXkeysPanel = new XKeys(pathToPanel)

Should work I think. One possible issue is that I'd introduce a new state (and tracking of that state) in the app ("panel available status") which is always a source of headaches.

Or: Have you achieved this in some other/better way?

Cheers,
Gรถran

XK-8 support

Hello,

Thanks for this great library!
I have an XK-8 connected to a Linux PC and get this error with node-hid not able to open it after trying to initiate it :

> var myXkeysPanel = new XKeys()
Uncaught TypeError: cannot open device with path /dev/hidraw2
    at new HID (/home/jg/projects/xkeys_test/node_modules/node-hid/nodehid.js:49:17)
    at new XKeys (/home/jg/projects/xkeys_test/node_modules/xkeys/dist/xkeys.js:48:28)

In HID.devices, it shows 4 devices from PI engineering (with a wrong product label ), all give the same error when trying to access them through nodehid.

Running as root then gives this error:

> var myXkeysPanel = new XKeys()
node: symbol lookup error: /home/jg/projects/xkeys_test/node_modules/node-hid/build/Release/HID_hidraw.node: undefined symbol: napi_add_env_cleanup_hook

any suggestions?

Thanks,

jean

XK-68 Jog+Shuttle support

Hey man

I have an XK-68 Jog+Shuttle that I'd really like to get working with a nodejs app that I use. I've installed your test script, and added a config line for my device manually, but the settings have been somewhat guesswork

Using the following lines, I'm able to read button presses from the device fine, and the button/joystick signals from the jogwheel, but the shuttle only reads 7 steps to the right and not to the left.

		XK68JOG: {	// This has not been tested
		identifier: 'XK-68 Jog-Shuttle',
		productId: [1114],
		columns: 	10,
		rows: 		8,
		hasPS: 		true,
		hasJoystick: 1,
		bankSize: 	32,
	},

This could be me being hacky and guessing parameters, or just that you've never had a chance to develop and bugfix that side because you don't own a device with the jogwheel.

Is this library something you have time to revisit and work with me to get working?

setBacklightIntensity always disables red back-lights

setBackLightIntensity checks for a 'banks' property of this.deviceType that is not defined in the [PRODUCTS] object. Since the property doesn't exists it always sets the red bank to 0 intensity.

Simple solution, add the banks property to the [PRODUCT] object:

XK24: {
		identifier: "XK-24",
		productId: [1029,1028,1027,1249],
		columns: 	4,
		rows: 		6,
		hasPS: 		true,
		bankSize: 	32,
		banks:		2 //added the banks property
	}

A more complex solution would be to add a red bank parameter to the function:

setBacklightIntensity(blueIntensity, redIntensity) {
    	blueIntensity = Math.max(Math.min(blueIntensity,255),0);
	redIntensity = Math.max(Math.min(redIntensity,255),0);
    	var message = [];
    	if (this.deviceType.banks === 2 ) {
    		message = this.padMessage([0,187,blueIntensity, redIntensity]); //added redIntensity
    	} else {
    		message = this.padMessage([0,187,blueIntensity]);
    	}

    	this.write(message);
	}

How to dispose of an xkeysPanel?

After finding some bad interactions between node-usb-detection library and XKeysWatcher when >3 devices are attached, I've been trying to simulate new device detection with the plain XKeys module by doing periodic calls to listAllConnectedPanels(). This gives me an up to date list of devices OK, however I'm unsure how to dispose of the panels listed and set up previously. I've tried running removeAllListeners() on all previous panels but this doesn't seem to do much. For instance a single button press is logged multiple times, seemingly dependent on the number of times devices have been listed and setup, as if the old panels are still active and receiving events.

I feel like I need the opposite of XKeys.setupXkeysPanel(connectedPanel) - is there such a thing?

XK-12 Joystick using wrong bits

It appears the wrong bits are being queried for the joystick, at least based on my XK-12 Joystick's output. The z-axis is also being modified incorrectly. My preference is also to have (-128,-128) be bottom-left and (128,128) be top-right so I added a *-1 to the Y-axis line.

Original Code:
(line 109 in current release of xkeys.js via npm or 163 in the ts re-write on github)

var d = data.readUInt32LE(7); // Joystick X
analogStates.joystick_x = (d < 128 ? d : d - 256);
d = data.readUInt32LE(8); // Joystick Y
analogStates.joystick_y = (d < 128 ? d : d - 256); 
d = data.readUInt32LE(9); // Joystick Z (twist of joystick)
analogStates.joystick_z = (d < 128 ? d : d - 256);

Proposed fix:

var d = data[6]; // Joystick X
analogStates.joystick_x = (d < 128 ? d : d - 256);
d = data[7]; // Joystick Y
analogStates.joystick_y = (d < 128 ? d : d - 256) *-1; 
d = data[8];// Joystick Z (twist of joystick)
analogStates.joystick_z = d; //0-255 then loops

Please find attached 4 files:
"logHMI_XK-12Joystick_Output.txt" - Raw output from the logHMI script

When running the test code from "Getting Started" I generated these logs:
"XK-12Joystick_OrigCode.txt" - Original output using current code
"XK-12Joystick_ProposedFix.txt" - Output from same file but with my proposed modification.
"XK-12Joystick_Z-Axis.txt" - Output just showing the z-axis being rotated all the way in both directions.

I see that @michaelhatPIengineering has started collaborating on this, hopefully he can verify/test my solution with his hardware.

Cheers,
-Jonathan Wyett

XK-12Joystick_ProposedFix.txt
XK-12Joystick_Z-Axis.txt
logHMI_XK-12Joystick_Output.txt
XK-12Joystick_OrigCode.txt

yarn build-record-test doesn't work in root of repo

yarn build-record-test
yarn run v1.22.19
$ lerna exec build-record-test
lerna notice cli v4.0.0
lerna info Executing command in 5 packages: "build-record-test"
/bin/sh: 1: build-record-test: not found
lerna ERR! build-record-test exited 127 in '@xkeys-lib/core'
lerna ERR! build-record-test exited 127 in '@xkeys-lib/core'
error Command failed with exit code 127.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

Instead I have to cd packages/node-record-test; yarn build; node dist/index.js

Or ts-node packages/node-record-test/src/index.ts

npm packages have a lot of 'junk' files

@xkeys-lib/core is publishing everything in the folder including src and jest config

xkeys is publishing the tests and mocks:

julus@julus-thinkpad:~/Projects/companion2a/node_modules/xkeys$ find .
.
./package.json
./README.md
./dist
./dist/lib.js.map
./dist/api.js.map
./dist/index.js
./dist/index.d.ts.map
./dist/api.d.ts
./dist/watcher.js.map
./dist/index.js.map
./dist/lib.js
./dist/__mocks__
./dist/__mocks__/node-hid.js.map
./dist/__mocks__/node-hid.js
./dist/__mocks__/node-hid.d.ts
./dist/__mocks__/node-hid.d.ts.map
./dist/methods.js.map
./dist/methods.js
./dist/api.d.ts.map
./dist/node-hid-wrapper.d.ts.map
./dist/watcher.d.ts.map
./dist/lib.d.ts
./dist/lib.d.ts.map
./dist/methods.d.ts.map
./dist/index.d.ts
./dist/node-hid-wrapper.js
./dist/watcher.js
./dist/watcher.d.ts
./dist/node-hid-wrapper.js.map
./dist/api.js
./dist/node-hid-wrapper.d.ts
./dist/methods.d.ts
./dist/__tests__
./dist/__tests__/recordings.spec.d.ts.map
./dist/__tests__/lib.js.map
./dist/__tests__/lib.js
./dist/__tests__/xkeys.spec.d.ts.map
./dist/__tests__/xkeys.spec.d.ts
./dist/__tests__/products.spec.js.map
./dist/__tests__/products.spec.js
./dist/__tests__/recordings.spec.js.map
./dist/__tests__/lib.d.ts
./dist/__tests__/lib.d.ts.map
./dist/__tests__/xkeys.spec.js
./dist/__tests__/recordings.spec.js
./dist/__tests__/products.spec.d.ts.map
./dist/__tests__/recordings.spec.d.ts
./dist/__tests__/products.spec.d.ts
./dist/__tests__/xkeys.spec.js.map
./LICENSE

I expect the webhid is doing similarly

Can XKeysWatcher handle existing connections?

In my Device Finder app., an XKeysWatcher handles connections & disconnections just fine. However, to deal with existing connections (devices already connected when the app starts), I also added `XKeys.listAllConnectedPanels().forEach(() => {...}). That seems to work but entails lots of duplicate code handling exactly the same events as for the watcher.

Is there any way for a watcher to detect existing connections? I'm guessing not but then is there a way that panels detected with listAllConnectedPanels() could be passed on to a watcher for event handling?

Thanks,
chris

Backlight methods

I see the api has various methods for setting backlights - including writing to the eeprom to make changes stick. Is there any way to retrieve the currently stored settings?

UnhandledPromiseRejectionWarning when watcher fails to open device

Running the basic-log-all-events.js example, if I plug in an xkeys that node-hid is unable to open for some reason, it results in an UnhandledPromiseRejectionWarning.

It would be good to have these emitted as an 'error' event on the watcher, so that is is possible to catch them.

Full stack:

(node:482681) UnhandledPromiseRejectionWarning: TypeError: cannot open device with path /dev/hidraw1
    at new HID (/home/julus/Projects/xkeys/node_modules/node-hid/nodehid.js:49:17)
    at setupXkeysPanel (/home/julus/Projects/xkeys/packages/node/dist/methods.js:49:18)
    at XKeysWatcher.handleNewDevice (/home/julus/Projects/xkeys/packages/node/dist/watcher.js:201:32)
    at XKeysWatcher.updateConnectedDevices (/home/julus/Projects/xkeys/packages/node/dist/watcher.js:186:22)
    at Timeout._onTimeout (/home/julus/Projects/xkeys/packages/node/dist/watcher.js:141:22)
    at listOnTimeout (internal/timers.js:557:17)
    at processTimers (internal/timers.js:500:7)
(node:482681) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 6)

XKeys.listAllConnectedPanels is not a function

I'm trying to incorporate listAllConnectedPanels to reset a local list of devices following problem of some hardware not supporting rebootDevice() correctly. However it doesn't seem to work. Here is output using CLI example on repo homepage:

chris@d8:~/src/xkeys-server$ node
Welcome to Node.js v14.17.6.
Type ".help" for more information.
> const { XKeys } = require('xkeys')
undefined
> XKeys.listAllConnectedPanels().forEach(() => {
... XKeys.setupXkeysPanel()
... then((xkeysPanel) => {
..... console.log(`X-keys panel of type ${xkeysPanel.info.name} listed`)
..... })
... .catch(console.log)
... })
Uncaught TypeError: XKeys.listAllConnectedPanels is not a function

Same result on different hardwares & node versions.

Any ideas why?

Multiple devices

Previously (version 2.0.0), I used xkeysPanel.devicePath to keep track of multiple devices. However it is no longer available in 2.1.1 (or 2.1.0). Could it be restored? Alternatively is there another way to distinguish between multiple connections of a particular device type?

Feature: WebHID

I'm planning to work on adding support for WebHID, since it is now included in Chrome (as of version 89).
If anyone has any best-practices or ideas for how it's best implemented, I'm all ears.

My first problem to tackle: How should I go about with the Node-HID dependency, since that should be omitted in the web-version.
@Julusian has solved it with the streamdeck by publishing 2 separate npm-packages. Perhaps that is the way to go?

Log.txt for XK-4 HDI keys

2020-10-15 09:10:32.989 Listening to device (1):
2020-10-15 09:10:32.999 manufacturer P. I. Engineering
2020-10-15 09:10:32.999 product XK-16 HID
2020-10-15 09:10:33.003 vendorId 1523
2020-10-15 09:10:33.004 productId 1049
2020-10-15 09:10:33.016 usage 1
npm run

Works but gets index 0,8,16,32 for buttons but diode index is 0,1,2,3

Intermittent "NotAllowedError: Failed to write the report." on Chrome v115+

The following uncaught exception (or promise rejection, not sure) "NotAllowedError: Failed to write the report." gets thrown from within function setupXkeysPanel.

On Chrome versions 117+ (tested on 117, 118, 120), this happens consistently until Chrome is restarted* ( can use chrome://restart ). *The issue gets resolved only after a random number of Chrome restarts and sometimes requiring XKeys to be replugged. The issue can then be reintroduced after a certain random number of Chrome restarts again.

The issue is never reproduced on Chrome v115 and below. Chrome v116 behaviour is untested.

In Chrome device log ( chrome://device-log/ ) I see either one of these 2 errors when the issue occurs when calling setupXkeysPanel:

  • Output report buffer too long (36 > 2).
  • This device does not support output reports.

Reproduced with:

  • XKeys: vendorId=1523, productId=1089, name='XK-80 HID'

Any ideas?

Any known problems with Raspberry Pi?

I'm using the xkeys library for a project on Raspberry Pi. Everything is going well but recently have wanted to use rebootDevice() function which doesn't seem to do anything on the Raspberry Pi. I've added some logging statements directly in the library code and see them executed when rebootDevice() is called but the watcher registers no 'disconnected' and 'connected' events triggered by the reboot (as would occur on a normal, non-raspberrypi, machine). I use those events to track what devices are currently attached to the machine, so missing those events is a big problem.

In case it's a hardware issue due to running on a Raspberry Pi 3 which is now not so recent, I've ordered a Raspberry Pi 4 in the hope that the newer hardware may have better USB implementation.

In the meantime I thought of refactoring my app so that after such a rebootDevice() call, I could just restart the watcher and therefore have an accurate accounting of the attached devices. However there is then a problem with stopping the current watcher. Here is CLI output of setting up a watcher, then immediately stopping it:

xkeys@pi3b:~/xkeys-server $ node
Welcome to Node.js v14.18.1.
Type ".help" for more information.
> const { XKeysWatcher } = require('xkeys')
undefined
> const watcher = new XKeysWatcher()
undefined
> watcher.on('connected', (xkeysPanel) => {
...     console.log(`X-keys panel of type ${xkeysPanel.info.name} connected`)
... })
XKeysWatcher {
  _events: [Object: null prototype] { connected: [Function (anonymous)] },
  _eventsCount: 1,
  _maxListeners: undefined,
  options: undefined,
  seenDevicePaths: { '/dev/hidraw0': { xkeys: [XKeys] } },
  isMonitoring: true,
  updateConnectedDevicesTimeout: null,
  shouldFindChangedReTries: 0,
  debug: false,
  setupXkeysPanels: [
    XKeys {
      _events: [Object: null prototype],
      _eventsCount: 1,
      _maxListeners: undefined,
      device: [NodeHIDDevice],
      deviceInfo: [Object],
      _devicePath: '/dev/hidraw0',
      _buttonStates: [Map],
      _analogStates: [Object],
      _initialized: true,
      _unidId: 13,
      _firmwareVersion: 14,
      _disconnected: false,
      product: [Object],
      receivedVersionResolve: [Function (anonymous)],
      receivedGenerateDataResolve: [Function (anonymous)],
      [Symbol(kCapture)]: false
    }
  ],
  prevConnectedIdentifiers: {},
  uniqueIds: Map(0) {},
  onAddedUSBDevice: [Function (anonymous)],
  onRemovedUSBDevice: [Function (anonymous)],
  [Symbol(kCapture)]: false
}
> watcher.stop().then( ()=> { console.log("stopping..."); }).catch(console.error)
Promise {
  <pending>,
  [Symbol(async_id_symbol)]: 120,
  [Symbol(trigger_async_id_symbol)]: 5,
  [Symbol(destroyed)]: { destroyed: false }
}
> Segmentation fault

whereas, if I run the same node commands on a non-raspberrypi machine, the .stop() function works as expected:

> watcher.stop().then( ()=> { console.log("stopping..."); }).catch(console.error)
Promise { <pending> }
> stopping...

>

Any ideas, insights on either of these issues?

Log for XKE-128

Passing on the log for the XKE-128 devices. FYI, I ran examples/xkeys.js and each button lit up when pressed as expected. Thanks for making a useful module.

2021-2-26 09:34:49.651 Listening to device (1):
2021-2-26 09:34:49.652 manufacturer P. I. Engineering
2021-2-26 09:34:49.652 product XK128Pi4
2021-2-26 09:34:49.653 vendorId 1523
2021-2-26 09:34:49.653 productId 1230
2021-2-26 09:34:49.653 interface 0
2021-2-26 09:34:53.095 // I pressed button 0 here (Row 0, Col 0) (Top Left Button)
2021-2-26 09:34:53.096 1 data 0100010000000000000000000000000000000100000000000000000000000014862bdf03
2021-2-26 09:34:53.155 1 data 0100000000000000000000000000000000000100000000000000000000000014862c1a03
2021-2-26 09:34:53.690 // I pressed button 1 here (Row 1, Col 0)
2021-2-26 09:34:53.690 1 data 0100020000000000000000000000000000000100000000000000000000000014862e2d03
2021-2-26 09:34:53.741 1 data 0100000000000000000000000000000000000100000000000000000000000014862e5d03
2021-2-26 09:34:54.348 // I pressed button 2 here (Row 2, Col 0)
2021-2-26 09:34:54.348 1 data 01000400000000000000000000000000000001000000000000000000000000148630ba03
2021-2-26 09:34:54.406 1 data 01000000000000000000000000000000000001000000000000000000000000148630f403
2021-2-26 09:34:54.957 // I pressed button 3 here (Row 3, Col 0)
2021-2-26 09:34:54.957 1 data 010008000000000000000000000000000000010000000000000000000000001486331803
2021-2-26 09:34:55.014 1 data 010000000000000000000000000000000000010000000000000000000000001486335103
2021-2-26 09:34:55.577 // I pressed button 4 here (Row 4, Col 0)
2021-2-26 09:34:55.577 1 data 010010000000000000000000000000000000010000000000000000000000001486357e03
2021-2-26 09:34:55.636 1 data 01000000000000000000000000000000000001000000000000000000000000148635b903
2021-2-26 09:34:56.191 // I pressed button 5 here (Row 5, Col 0)
2021-2-26 09:34:56.191 1 data 01002000000000000000000000000000000001000000000000000000000000148637e003
2021-2-26 09:34:56.260 1 data 010000000000000000000000000000000000010000000000000000000000001486382403
2021-2-26 09:34:56.744 // I pressed button 6 here (Row 6, Col 0)
2021-2-26 09:34:56.744 1 data 0100400000000000000000000000000000000100000000000000000000000014863a0503
2021-2-26 09:34:56.807 1 data 0100000000000000000000000000000000000100000000000000000000000014863a3c03
2021-2-26 09:34:57.284 // I pressed button 7 here (Row 7, Col 0) (Bottom Left Button)
2021-2-26 09:34:57.284 1 data 0100800000000000000000000000000000000100000000000000000000000014863c1e03
2021-2-26 09:34:57.335 1 data 0100000000000000000000000000000000000100000000000000000000000014863c5203
2021-2-26 09:34:58.027 // I pressed button 8 here (Row 0, Col 1)
2021-2-26 09:34:58.027 1 data 0100000100000000000000000000000000000100000000000000000000000014863f0003
2021-2-26 09:34:58.083 1 data 0100000000000000000000000000000000000100000000000000000000000014863f3603
2021-2-26 09:34:58.500 // I pressed button 9 here (Row 1, Col 1)
2021-2-26 09:34:58.500 1 data 01000002000000000000000000000000000001000000000000000000000000148640d803
2021-2-26 09:34:58.559 1 data 010000000000000000000000000000000000010000000000000000000000001486411303
2021-2-26 09:34:58.993 // I pressed button 10 here (Row 2, Col 1)
2021-2-26 09:34:58.993 1 data 01000004000000000000000000000000000001000000000000000000000000148642c003
2021-2-26 09:34:59.050 1 data 01000000000000000000000000000000000001000000000000000000000000148642f603
2021-2-26 09:34:59.406 // I pressed button 11 here (Row 3, Col 1)
2021-2-26 09:34:59.406 1 data 010000080000000000000000000000000000010000000000000000000000001486445c03
2021-2-26 09:34:59.469 1 data 010000000000000000000000000000000000010000000000000000000000001486449903
2021-2-26 09:34:59.815 // I pressed button 12 here (Row 4, Col 1)
2021-2-26 09:34:59.815 1 data 01000010000000000000000000000000000001000000000000000000000000148645f303
2021-2-26 09:34:59.884 1 data 010000000000000000000000000000000000010000000000000000000000001486463803
2021-2-26 09:35:00.214 // I pressed button 13 here (Row 5, Col 1)
2021-2-26 09:35:00.214 1 data 010000200000000000000000000000000000010000000000000000000000001486477f03
2021-2-26 09:35:00.278 1 data 01000000000000000000000000000000000001000000000000000000000000148647bf03
2021-2-26 09:35:00.624 // I pressed button 14 here (Row 6, Col 1)
2021-2-26 09:35:00.624 1 data 010000400000000000000000000000000000010000000000000000000000001486491703
2021-2-26 09:35:00.689 1 data 010000000000000000000000000000000000010000000000000000000000001486495803
2021-2-26 09:35:01.011 // I pressed button 15 here (Row 7, Col 1)
2021-2-26 09:35:01.011 1 data 0100008000000000000000000000000000000100000000000000000000000014864a9703
2021-2-26 09:35:01.066 1 data 0100000000000000000000000000000000000100000000000000000000000014864acf03
2021-2-26 09:35:01.715 // I pressed button 16 here (Row 0, Col 2)
2021-2-26 09:35:01.715 1 data 0100000001000000000000000000000000000100000000000000000000000014864d5503
2021-2-26 09:35:01.775 1 data 0100000000000000000000000000000000000100000000000000000000000014864d8b03
2021-2-26 09:35:02.149 // I pressed button 17 here (Row 1, Col 2)
2021-2-26 09:35:02.149 1 data 0100000002000000000000000000000000000100000000000000000000000014864f0403
2021-2-26 09:35:02.200 1 data 0100000000000000000000000000000000000100000000000000000000000014864f3503
2021-2-26 09:35:02.543 // I pressed button 18 here (Row 2, Col 2)
2021-2-26 09:35:02.544 1 data 010000000400000000000000000000000000010000000000000000000000001486508b03
2021-2-26 09:35:02.590 1 data 01000000000000000000000000000000000001000000000000000000000000148650b903
2021-2-26 09:35:02.937 // I pressed button 19 here (Row 3, Col 2)
2021-2-26 09:35:02.937 1 data 010000000800000000000000000000000000010000000000000000000000001486521303
2021-2-26 09:35:02.997 1 data 010000000000000000000000000000000000010000000000000000000000001486524f03
2021-2-26 09:35:03.336 // I pressed button 20 here (Row 4, Col 2)
2021-2-26 09:35:03.336 1 data 010000001000000000000000000000000000010000000000000000000000001486539f03
2021-2-26 09:35:03.400 1 data 01000000000000000000000000000000000001000000000000000000000000148653df03
2021-2-26 09:35:03.704 // I pressed button 21 here (Row 5, Col 2)
2021-2-26 09:35:03.704 1 data 010000002000000000000000000000000000010000000000000000000000001486550d03
2021-2-26 09:35:03.772 1 data 010000000000000000000000000000000000010000000000000000000000001486555103
2021-2-26 09:35:04.091 // I pressed button 22 here (Row 6, Col 2)
2021-2-26 09:35:04.091 1 data 010000004000000000000000000000000000010000000000000000000000001486568d03
2021-2-26 09:35:04.156 1 data 01000000000000000000000000000000000001000000000000000000000000148656ce03
2021-2-26 09:35:04.475 // I pressed button 23 here (Row 7, Col 2)
2021-2-26 09:35:04.475 1 data 010000008000000000000000000000000000010000000000000000000000001486580b03
2021-2-26 09:35:04.544 1 data 010000000000000000000000000000000000010000000000000000000000001486585103
2021-2-26 09:35:05.361 // I pressed button 24 here (Row 0, Col 3)
2021-2-26 09:35:05.361 1 data 0100000000010000000000000000000000000100000000000000000000000014865b7d03
2021-2-26 09:35:05.434 1 data 0100000000000000000000000000000000000100000000000000000000000014865bc703
2021-2-26 09:35:05.731 // I pressed button 25 here (Row 1, Col 3)
2021-2-26 09:35:05.732 1 data 0100000000020000000000000000000000000100000000000000000000000014865ced03
2021-2-26 09:35:05.794 1 data 0100000000000000000000000000000000000100000000000000000000000014865d2b03
2021-2-26 09:35:06.139 // I pressed button 26 here (Row 2, Col 3)
2021-2-26 09:35:06.139 1 data 0100000000040000000000000000000000000100000000000000000000000014865e8103
2021-2-26 09:35:06.201 1 data 0100000000000000000000000000000000000100000000000000000000000014865ec003
2021-2-26 09:35:06.521 // I pressed button 27 here (Row 3, Col 3)
2021-2-26 09:35:06.521 1 data 0100000000080000000000000000000000000100000000000000000000000014865ffd03
2021-2-26 09:35:06.585 1 data 010000000000000000000000000000000000010000000000000000000000001486603d03
2021-2-26 09:35:06.930 // I pressed button 28 here (Row 4, Col 3)
2021-2-26 09:35:06.930 1 data 010000000010000000000000000000000000010000000000000000000000001486619303
2021-2-26 09:35:06.994 1 data 01000000000000000000000000000000000001000000000000000000000000148661d103
2021-2-26 09:35:07.326 // I pressed button 29 here (Row 5, Col 3)
2021-2-26 09:35:07.326 1 data 010000000020000000000000000000000000010000000000000000000000001486631c03
2021-2-26 09:35:07.389 1 data 010000000000000000000000000000000000010000000000000000000000001486635a03
2021-2-26 09:35:07.709 // I pressed button 30 here (Row 6, Col 3)
2021-2-26 09:35:07.709 1 data 010000000040000000000000000000000000010000000000000000000000001486649803
2021-2-26 09:35:07.770 1 data 01000000000000000000000000000000000001000000000000000000000000148664d503
2021-2-26 09:35:08.104 // I pressed button 31 here (Row 7, Col 3)
2021-2-26 09:35:08.104 1 data 010000000080000000000000000000000000010000000000000000000000001486662103
2021-2-26 09:35:08.169 1 data 010000000000000000000000000000000000010000000000000000000000001486666203
2021-2-26 09:35:08.818 // I pressed button 32 here (Row 0, Col 4)
2021-2-26 09:35:08.818 1 data 01000000000001000000000000000000000001000000000000000000000000148668e603
2021-2-26 09:35:08.904 1 data 010000000000000000000000000000000000010000000000000000000000001486693b03
2021-2-26 09:35:09.162 // I pressed button 33 here (Row 1, Col 4)
2021-2-26 09:35:09.162 1 data 0100000000000200000000000000000000000100000000000000000000000014866a3c03
2021-2-26 09:35:09.240 1 data 0100000000000000000000000000000000000100000000000000000000000014866a8903
2021-2-26 09:35:09.544 // I pressed button 34 here (Row 2, Col 4)
2021-2-26 09:35:09.544 1 data 0100000000000400000000000000000000000100000000000000000000000014866bb803
2021-2-26 09:35:09.618 1 data 0100000000000000000000000000000000000100000000000000000000000014866bff03
2021-2-26 09:35:09.905 // I pressed button 35 here (Row 3, Col 4)
2021-2-26 09:35:09.906 1 data 0100000000000800000000000000000000000100000000000000000000000014866d1d03
2021-2-26 09:35:09.989 1 data 0100000000000000000000000000000000000100000000000000000000000014866d7103
2021-2-26 09:35:10.362 // I pressed button 36 here (Row 4, Col 4)
2021-2-26 09:35:10.362 1 data 0100000000001000000000000000000000000100000000000000000000000014866ee303
2021-2-26 09:35:10.445 1 data 0100000000000000000000000000000000000100000000000000000000000014866f3703
2021-2-26 09:35:10.751 // I pressed button 37 here (Row 5, Col 4)
2021-2-26 09:35:10.752 1 data 010000000000200000000000000000000000010000000000000000000000001486706603
2021-2-26 09:35:10.841 1 data 01000000000000000000000000000000000001000000000000000000000000148670bf03
2021-2-26 09:35:11.133 // I pressed button 38 here (Row 6, Col 4)
2021-2-26 09:35:11.133 1 data 01000000000040000000000000000000000001000000000000000000000000148671e103
2021-2-26 09:35:11.216 1 data 010000000000000000000000000000000000010000000000000000000000001486723503
2021-2-26 09:35:11.494 // I pressed button 39 here (Row 7, Col 4)
2021-2-26 09:35:11.494 1 data 010000000000800000000000000000000000010000000000000000000000001486734803
2021-2-26 09:35:11.589 1 data 01000000000000000000000000000000000001000000000000000000000000148673a703
2021-2-26 09:35:12.230 // I pressed button 40 here (Row 0, Col 5)
2021-2-26 09:35:12.230 1 data 010000000000000100000000000000000000010000000000000000000000001486762403
2021-2-26 09:35:12.315 1 data 010000000000000000000000000000000000010000000000000000000000001486767803
2021-2-26 09:35:12.604 // I pressed button 41 here (Row 1, Col 5)
2021-2-26 09:35:12.605 1 data 010000000000000200000000000000000000010000000000000000000000001486779803
2021-2-26 09:35:12.687 1 data 01000000000000000000000000000000000001000000000000000000000000148677eb03
2021-2-26 09:35:12.985 // I pressed button 42 here (Row 2, Col 5)
2021-2-26 09:35:12.985 1 data 010000000000000400000000000000000000010000000000000000000000001486791303
2021-2-26 09:35:13.070 1 data 010000000000000000000000000000000000010000000000000000000000001486796703
2021-2-26 09:35:13.364 // I pressed button 43 here (Row 3, Col 5)
2021-2-26 09:35:13.364 1 data 0100000000000008000000000000000000000100000000000000000000000014867a8c03
2021-2-26 09:35:13.437 1 data 0100000000000000000000000000000000000100000000000000000000000014867ad503
2021-2-26 09:35:13.742 // I pressed button 44 here (Row 4, Col 5)
2021-2-26 09:35:13.742 1 data 0100000000000010000000000000000000000100000000000000000000000014867c0403
2021-2-26 09:35:13.822 1 data 0100000000000000000000000000000000000100000000000000000000000014867c5203
2021-2-26 09:35:14.157 // I pressed button 45 here (Row 5, Col 5)
2021-2-26 09:35:14.157 1 data 0100000000000020000000000000000000000100000000000000000000000014867da003
2021-2-26 09:35:14.231 1 data 0100000000000000000000000000000000000100000000000000000000000014867dea03
2021-2-26 09:35:14.519 // I pressed button 46 here (Row 6, Col 5)
2021-2-26 09:35:14.519 1 data 0100000000000040000000000000000000000100000000000000000000000014867f0903
2021-2-26 09:35:14.603 1 data 0100000000000000000000000000000000000100000000000000000000000014867f5d03
2021-2-26 09:35:14.883 // I pressed button 47 here (Row 7, Col 5)
2021-2-26 09:35:14.883 1 data 010000000000008000000000000000000000010000000000000000000000001486807303
2021-2-26 09:35:14.960 1 data 01000000000000000000000000000000000001000000000000000000000000148680c003
2021-2-26 09:35:16.182 // I pressed button 48 here (Row 0, Col 6)
2021-2-26 09:35:16.182 1 data 010000000000000001000000000000000000010000000000000000000000001486857c03
2021-2-26 09:35:16.263 1 data 01000000000000000000000000000000000001000000000000000000000000148685cd03
2021-2-26 09:35:16.556 // I pressed button 49 here (Row 1, Col 6)
2021-2-26 09:35:16.557 1 data 01000000000000000200000000000000000001000000000000000000000000148686f103
2021-2-26 09:35:16.628 1 data 010000000000000000000000000000000000010000000000000000000000001486873803
2021-2-26 09:35:16.955 // I pressed button 50 here (Row 2, Col 6)
2021-2-26 09:35:16.955 1 data 010000000000000004000000000000000000010000000000000000000000001486887e03
2021-2-26 09:35:17.039 1 data 01000000000000000000000000000000000001000000000000000000000000148688d103
2021-2-26 09:35:17.356 // I pressed button 51 here (Row 3, Col 6)
2021-2-26 09:35:17.356 1 data 0100000000000000080000000000000000000100000000000000000000000014868a0d03
2021-2-26 09:35:17.435 1 data 0100000000000000000000000000000000000100000000000000000000000014868a5b03
2021-2-26 09:35:17.724 // I pressed button 52 here (Row 4, Col 6)
2021-2-26 09:35:17.724 1 data 0100000000000000100000000000000000000100000000000000000000000014868b7903
2021-2-26 09:35:17.811 1 data 0100000000000000000000000000000000000100000000000000000000000014868bcf03
2021-2-26 09:35:18.098 // I pressed button 53 here (Row 5, Col 6)
2021-2-26 09:35:18.098 1 data 0100000000000000200000000000000000000100000000000000000000000014868ced03
2021-2-26 09:35:18.187 1 data 0100000000000000000000000000000000000100000000000000000000000014868d4603
2021-2-26 09:35:18.474 // I pressed button 54 here (Row 6, Col 6)
2021-2-26 09:35:18.474 1 data 0100000000000000400000000000000000000100000000000000000000000014868e6203
2021-2-26 09:35:18.561 1 data 0100000000000000000000000000000000000100000000000000000000000014868eb703
2021-2-26 09:35:18.872 // I pressed button 55 here (Row 7, Col 6)
2021-2-26 09:35:18.872 1 data 0100000000000000800000000000000000000100000000000000000000000014868fef03
2021-2-26 09:35:18.977 1 data 010000000000000000000000000000000000010000000000000000000000001486905703
2021-2-26 09:35:19.729 // I pressed button 56 here (Row 0, Col 7)
2021-2-26 09:35:19.729 1 data 010000000000000000010000000000000000010000000000000000000000001486934103
2021-2-26 09:35:19.818 1 data 010000000000000000000000000000000000010000000000000000000000001486939b03
2021-2-26 09:35:20.076 // I pressed button 57 here (Row 1, Col 7)
2021-2-26 09:35:20.076 1 data 010000000000000000020000000000000000010000000000000000000000001486949a03
2021-2-26 09:35:20.169 1 data 01000000000000000000000000000000000001000000000000000000000000148694f703
2021-2-26 09:35:20.464 // I pressed button 58 here (Row 2, Col 7)
2021-2-26 09:35:20.464 1 data 010000000000000000040000000000000000010000000000000000000000001486961b03
2021-2-26 09:35:20.550 1 data 010000000000000000000000000000000000010000000000000000000000001486967003
2021-2-26 09:35:20.807 // I pressed button 59 here (Row 3, Col 7)
2021-2-26 09:35:20.807 1 data 010000000000000000080000000000000000010000000000000000000000001486977103
2021-2-26 09:35:20.900 1 data 01000000000000000000000000000000000001000000000000000000000000148697cd03
2021-2-26 09:35:21.219 // I pressed button 60 here (Row 4, Col 7)
2021-2-26 09:35:21.219 1 data 010000000000000000100000000000000000010000000000000000000000001486990903
2021-2-26 09:35:21.311 1 data 010000000000000000000000000000000000010000000000000000000000001486996503
2021-2-26 09:35:21.621 // I pressed button 61 here (Row 5, Col 7)
2021-2-26 09:35:21.621 1 data 0100000000000000002000000000000000000100000000000000000000000014869a9903
2021-2-26 09:35:21.715 1 data 0100000000000000000000000000000000000100000000000000000000000014869af703
2021-2-26 09:35:22.009 // I pressed button 62 here (Row 6, Col 7)
2021-2-26 09:35:22.009 1 data 0100000000000000004000000000000000000100000000000000000000000014869c1b03
2021-2-26 09:35:22.094 1 data 0100000000000000000000000000000000000100000000000000000000000014869c7103
2021-2-26 09:35:22.356 // I pressed button 63 here (Row 7, Col 7)
2021-2-26 09:35:22.356 1 data 0100000000000000008000000000000000000100000000000000000000000014869d7403
2021-2-26 09:35:22.452 1 data 0100000000000000000000000000000000000100000000000000000000000014869dd303
2021-2-26 09:35:23.211 // I pressed button 64 here (Row 0, Col 8)
2021-2-26 09:35:23.211 1 data 010000000000000000000100000000000000010000000000000000000000001486a0c503
2021-2-26 09:35:23.313 1 data 010000000000000000000000000000000000010000000000000000000000001486a12a03
2021-2-26 09:35:23.582 // I pressed button 65 here (Row 1, Col 8)
2021-2-26 09:35:23.583 1 data 010000000000000000000200000000000000010000000000000000000000001486a23503
2021-2-26 09:35:23.686 1 data 010000000000000000000000000000000000010000000000000000000000001486a29d03
2021-2-26 09:35:23.971 // I pressed button 66 here (Row 2, Col 8)
2021-2-26 09:35:23.971 1 data 010000000000000000000400000000000000010000000000000000000000001486a3b903
2021-2-26 09:35:24.071 1 data 010000000000000000000000000000000000010000000000000000000000001486a41b03
2021-2-26 09:35:24.398 // I pressed button 67 here (Row 3, Col 8)
2021-2-26 09:35:24.399 1 data 010000000000000000000800000000000000010000000000000000000000001486a56103
2021-2-26 09:35:24.488 1 data 010000000000000000000000000000000000010000000000000000000000001486a5ba03
2021-2-26 09:35:24.796 // I pressed button 68 here (Row 4, Col 8)
2021-2-26 09:35:24.796 1 data 010000000000000000001000000000000000010000000000000000000000001486a6ed03
2021-2-26 09:35:24.885 1 data 010000000000000000000000000000000000010000000000000000000000001486a74503
2021-2-26 09:35:25.169 // I pressed button 69 here (Row 5, Col 8)
2021-2-26 09:35:25.169 1 data 010000000000000000002000000000000000010000000000000000000000001486a85e03
2021-2-26 09:35:25.267 1 data 010000000000000000000000000000000000010000000000000000000000001486a8be03
2021-2-26 09:35:25.560 // I pressed button 70 here (Row 6, Col 8)
2021-2-26 09:35:25.560 1 data 010000000000000000004000000000000000010000000000000000000000001486a9e303
2021-2-26 09:35:25.642 1 data 010000000000000000000000000000000000010000000000000000000000001486aa3503
2021-2-26 09:35:25.956 // I pressed button 71 here (Row 7, Col 8)
2021-2-26 09:35:25.956 1 data 010000000000000000008000000000000000010000000000000000000000001486ab6c03
2021-2-26 09:35:26.048 1 data 010000000000000000000000000000000000010000000000000000000000001486abc803
2021-2-26 09:35:27.125 // I pressed button 72 here (Row 0, Col 9)
2021-2-26 09:35:27.125 1 data 010000000000000000000001000000000000010000000000000000000000001486aff503
2021-2-26 09:35:27.219 1 data 010000000000000000000000000000000000010000000000000000000000001486b05203
2021-2-26 09:35:27.515 // I pressed button 73 here (Row 1, Col 9)
2021-2-26 09:35:27.515 1 data 010000000000000000000002000000000000010000000000000000000000001486b17a03
2021-2-26 09:35:27.603 1 data 010000000000000000000000000000000000010000000000000000000000001486b1d103
2021-2-26 09:35:27.874 // I pressed button 74 here (Row 2, Col 9)
2021-2-26 09:35:27.874 1 data 010000000000000000000004000000000000010000000000000000000000001486b2de03
2021-2-26 09:35:27.971 1 data 010000000000000000000000000000000000010000000000000000000000001486b33f03
2021-2-26 09:35:28.247 // I pressed button 75 here (Row 3, Col 9)
2021-2-26 09:35:28.247 1 data 010000000000000000000008000000000000010000000000000000000000001486b45103
2021-2-26 09:35:28.338 1 data 010000000000000000000000000000000000010000000000000000000000001486b4aa03
2021-2-26 09:35:28.656 // I pressed button 76 here (Row 4, Col 9)
2021-2-26 09:35:28.656 1 data 010000000000000000000010000000000000010000000000000000000000001486b5e703
2021-2-26 09:35:28.743 1 data 010000000000000000000000000000000000010000000000000000000000001486b63c03
2021-2-26 09:35:29.012 // I pressed button 77 here (Row 5, Col 9)
2021-2-26 09:35:29.012 1 data 010000000000000000000020000000000000010000000000000000000000001486b74703
2021-2-26 09:35:29.096 1 data 010000000000000000000000000000000000010000000000000000000000001486b79b03
2021-2-26 09:35:29.436 // I pressed button 78 here (Row 6, Col 9)
2021-2-26 09:35:29.437 1 data 010000000000000000000040000000000000010000000000000000000000001486b8ed03
2021-2-26 09:35:29.517 1 data 010000000000000000000000000000000000010000000000000000000000001486b93d03
2021-2-26 09:35:29.816 // I pressed button 79 here (Row 7, Col 9)
2021-2-26 09:35:29.816 1 data 010000000000000000000080000000000000010000000000000000000000001486ba6503
2021-2-26 09:35:29.927 1 data 010000000000000000000000000000000000010000000000000000000000001486bad403
2021-2-26 09:35:32.000 // I pressed button 80 here (Row 0, Col 10)
2021-2-26 09:35:32.000 1 data 010000000000000000000000010000000000010000000000000000000000001486c2de03
2021-2-26 09:35:32.085 1 data 010000000000000000000000000000000000010000000000000000000000001486c33103
2021-2-26 09:35:32.310 // I pressed button 81 here (Row 1, Col 10)
2021-2-26 09:35:32.310 1 data 010000000000000000000000020000000000010000000000000000000000001486c41203
2021-2-26 09:35:32.416 1 data 010000000000000000000000000000000000010000000000000000000000001486c47b03
2021-2-26 09:35:32.703 // I pressed button 82 here (Row 2, Col 10)
2021-2-26 09:35:32.704 1 data 010000000000000000000000040000000000010000000000000000000000001486c59a03
2021-2-26 09:35:32.802 1 data 010000000000000000000000000000000000010000000000000000000000001486c5fb03
2021-2-26 09:35:33.092 // I pressed button 83 here (Row 3, Col 10)
2021-2-26 09:35:33.092 1 data 010000000000000000000000080000000000010000000000000000000000001486c71c03
2021-2-26 09:35:33.189 1 data 010000000000000000000000000000000000010000000000000000000000001486c77e03
2021-2-26 09:35:33.451 // I pressed button 84 here (Row 4, Col 10)
2021-2-26 09:35:33.451 1 data 010000000000000000000000100000000000010000000000000000000000001486c88103
2021-2-26 09:35:33.544 1 data 010000000000000000000000000000000000010000000000000000000000001486c8de03
2021-2-26 09:35:33.831 // I pressed button 85 here (Row 5, Col 10)
2021-2-26 09:35:33.831 1 data 010000000000000000000000200000000000010000000000000000000000001486c9fa03
2021-2-26 09:35:33.914 1 data 010000000000000000000000000000000000010000000000000000000000001486ca4d03
2021-2-26 09:35:34.200 // I pressed button 86 here (Row 6, Col 10)
2021-2-26 09:35:34.200 1 data 010000000000000000000000400000000000010000000000000000000000001486cb6803
2021-2-26 09:35:34.265 1 data 010000000000000000000000000000000000010000000000000000000000001486cba903
2021-2-26 09:35:34.553 // I pressed button 87 here (Row 7, Col 10)
2021-2-26 09:35:34.553 1 data 010000000000000000000000800000000000010000000000000000000000001486ccc903
2021-2-26 09:35:34.616 1 data 010000000000000000000000000000000000010000000000000000000000001486cd0703
2021-2-26 09:35:35.560 // I pressed button 88 here (Row 0, Col 11)
2021-2-26 09:35:35.561 1 data 010000000000000000000000000100000000010000000000000000000000001486d0b103
2021-2-26 09:35:35.651 1 data 010000000000000000000000000000000000010000000000000000000000001486d10c03
2021-2-26 09:35:35.915 // I pressed button 89 here (Row 1, Col 11)
2021-2-26 09:35:35.915 1 data 010000000000000000000000000200000000010000000000000000000000001486d21003
2021-2-26 09:35:36.001 1 data 010000000000000000000000000000000000010000000000000000000000001486d26503
2021-2-26 09:35:36.322 // I pressed button 90 here (Row 2, Col 11)
2021-2-26 09:35:36.322 1 data 010000000000000000000000000400000000010000000000000000000000001486d3a503
2021-2-26 09:35:36.442 1 data 010000000000000000000000000000000000010000000000000000000000001486d41d03
2021-2-26 09:35:36.848 // I pressed button 91 here (Row 3, Col 11)
2021-2-26 09:35:36.848 1 data 010000000000000000000000000800000000010000000000000000000000001486d5b103
2021-2-26 09:35:36.944 1 data 010000000000000000000000000000000000010000000000000000000000001486d61103
2021-2-26 09:35:37.288 // I pressed button 92 here (Row 4, Col 11)
2021-2-26 09:35:37.288 1 data 010000000000000000000000001000000000010000000000000000000000001486d76803
2021-2-26 09:35:37.362 1 data 010000000000000000000000000000000000010000000000000000000000001486d7b103
2021-2-26 09:35:37.685 // I pressed button 93 here (Row 5, Col 11)
2021-2-26 09:35:37.685 1 data 010000000000000000000000002000000000010000000000000000000000001486d8f103
2021-2-26 09:35:37.761 1 data 010000000000000000000000000000000000010000000000000000000000001486d93d03
2021-2-26 09:35:38.055 // I pressed button 94 here (Row 6, Col 11)
2021-2-26 09:35:38.055 1 data 010000000000000000000000004000000000010000000000000000000000001486da6303
2021-2-26 09:35:38.130 1 data 010000000000000000000000000000000000010000000000000000000000001486daac03
2021-2-26 09:35:38.377 // I pressed button 95 here (Row 7, Col 11)
2021-2-26 09:35:38.377 1 data 010000000000000000000000008000000000010000000000000000000000001486dba303
2021-2-26 09:35:38.465 1 data 010000000000000000000000000000000000010000000000000000000000001486dbfb03
2021-2-26 09:35:39.191 // I pressed button 96 here (Row 0, Col 12)
2021-2-26 09:35:39.191 1 data 010000000000000000000000000001000000010000000000000000000000001486decd03
2021-2-26 09:35:39.283 1 data 010000000000000000000000000000000000010000000000000000000000001486df2803
2021-2-26 09:35:39.519 // I pressed button 97 here (Row 1, Col 12)
2021-2-26 09:35:39.519 1 data 010000000000000000000000000002000000010000000000000000000000001486e01203
2021-2-26 09:35:39.622 1 data 010000000000000000000000000000000000010000000000000000000000001486e07803
2021-2-26 09:35:39.906 // I pressed button 98 here (Row 2, Col 12)
2021-2-26 09:35:39.906 1 data 010000000000000000000000000004000000010000000000000000000000001486e19203
2021-2-26 09:35:39.997 1 data 010000000000000000000000000000000000010000000000000000000000001486e1ec03
2021-2-26 09:35:40.274 // I pressed button 99 here (Row 3, Col 12)
2021-2-26 09:35:40.274 1 data 010000000000000000000000000008000000010000000000000000000000001486e30103
2021-2-26 09:35:40.373 1 data 010000000000000000000000000000000000010000000000000000000000001486e36303
2021-2-26 09:35:40.721 // I pressed button 100 here (Row 4, Col 12)
2021-2-26 09:35:40.721 1 data 010000000000000000000000000010000000010000000000000000000000001486e4bd03
2021-2-26 09:35:40.818 1 data 010000000000000000000000000000000000010000000000000000000000001486e51c03
2021-2-26 09:35:41.182 // I pressed button 101 here (Row 5, Col 12)
2021-2-26 09:35:41.183 1 data 010000000000000000000000000020000000010000000000000000000000001486e68503
2021-2-26 09:35:41.253 1 data 010000000000000000000000000000000000010000000000000000000000001486e6cb03
2021-2-26 09:35:41.633 // I pressed button 102 here (Row 6, Col 12)
2021-2-26 09:35:41.634 1 data 010000000000000000000000000040000000010000000000000000000000001486e84403
2021-2-26 09:35:41.689 1 data 010000000000000000000000000000000000010000000000000000000000001486e87903
2021-2-26 09:35:42.005 // I pressed button 103 here (Row 7, Col 12)
2021-2-26 09:35:42.005 1 data 010000000000000000000000000080000000010000000000000000000000001486e9b503
2021-2-26 09:35:42.061 1 data 010000000000000000000000000000000000010000000000000000000000001486e9e403
2021-2-26 09:35:42.961 // I pressed button 104 here (Row 0, Col 13)
2021-2-26 09:35:42.961 1 data 010000000000000000000000000000010000010000000000000000000000001486ed6c03
2021-2-26 09:35:43.047 1 data 010000000000000000000000000000000000010000000000000000000000001486edc103
2021-2-26 09:35:43.295 // I pressed button 105 here (Row 1, Col 13)
2021-2-26 09:35:43.296 1 data 010000000000000000000000000000020000010000000000000000000000001486eeb703
2021-2-26 09:35:43.381 1 data 010000000000000000000000000000000000010000000000000000000000001486ef0c03
2021-2-26 09:35:43.687 // I pressed button 106 here (Row 2, Col 13)
2021-2-26 09:35:43.687 1 data 010000000000000000000000000000040000010000000000000000000000001486f03c03
2021-2-26 09:35:43.776 1 data 010000000000000000000000000000000000010000000000000000000000001486f09403
2021-2-26 09:35:44.084 // I pressed button 107 here (Row 3, Col 13)
2021-2-26 09:35:44.085 1 data 010000000000000000000000000000080000010000000000000000000000001486f1c603
2021-2-26 09:35:44.175 1 data 010000000000000000000000000000000000010000000000000000000000001486f22103
2021-2-26 09:35:44.453 // I pressed button 108 here (Row 4, Col 13)
2021-2-26 09:35:44.453 1 data 010000000000000000000000000000100000010000000000000000000000001486f33403
2021-2-26 09:35:44.531 1 data 010000000000000000000000000000000000010000000000000000000000001486f38203
2021-2-26 09:35:44.835 // I pressed button 109 here (Row 5, Col 13)
2021-2-26 09:35:44.836 1 data 010000000000000000000000000000200000010000000000000000000000001486f4af03
2021-2-26 09:35:44.920 1 data 010000000000000000000000000000000000010000000000000000000000001486f50403
2021-2-26 09:35:45.223 // I pressed button 110 here (Row 6, Col 13)
2021-2-26 09:35:45.223 1 data 010000000000000000000000000000400000010000000000000000000000001486f63203
2021-2-26 09:35:45.296 1 data 010000000000000000000000000000000000010000000000000000000000001486f67a03
2021-2-26 09:35:45.597 // I pressed button 111 here (Row 7, Col 13)
2021-2-26 09:35:45.597 1 data 010000000000000000000000000000800000010000000000000000000000001486f7a703
2021-2-26 09:35:45.683 1 data 010000000000000000000000000000000000010000000000000000000000001486f7fc03
2021-2-26 09:35:46.367 // I pressed button 112 here (Row 0, Col 14)
2021-2-26 09:35:46.367 1 data 010000000000000000000000000000000100010000000000000000000000001486faa303
2021-2-26 09:35:46.467 1 data 010000000000000000000000000000000000010000000000000000000000001486fb0603
2021-2-26 09:35:46.687 // I pressed button 113 here (Row 1, Col 14)
2021-2-26 09:35:46.688 1 data 010000000000000000000000000000000200010000000000000000000000001486fbe003
2021-2-26 09:35:46.804 1 data 010000000000000000000000000000000000010000000000000000000000001486fc5503
2021-2-26 09:35:47.126 // I pressed button 114 here (Row 2, Col 14)
2021-2-26 09:35:47.126 1 data 010000000000000000000000000000000400010000000000000000000000001486fd9403
2021-2-26 09:35:47.236 1 data 010000000000000000000000000000000000010000000000000000000000001486fe0203
2021-2-26 09:35:47.826 // I pressed button 115 here (Row 3, Col 14)
2021-2-26 09:35:47.826 1 data 010000000000000000000000000000000800010000000000000000000000001487004b03
2021-2-26 09:35:47.921 1 data 01000000000000000000000000000000000001000000000000000000000000148700aa03
2021-2-26 09:35:49.103 // I pressed button 116 here (Row 4, Col 14)
2021-2-26 09:35:49.104 1 data 010000000000000000000000000000001000010000000000000000000000001487054103
2021-2-26 09:35:49.187 1 data 010000000000000000000000000000000000010000000000000000000000001487059603
2021-2-26 09:35:49.475 // I pressed button 117 here (Row 5, Col 14)
2021-2-26 09:35:49.475 1 data 01000000000000000000000000000000200001000000000000000000000000148706b203
2021-2-26 09:35:49.543 1 data 01000000000000000000000000000000000001000000000000000000000000148706f703
2021-2-26 09:35:49.842 // I pressed button 118 here (Row 6, Col 14)
2021-2-26 09:35:49.843 1 data 010000000000000000000000000000004000010000000000000000000000001487081f03
2021-2-26 09:35:49.900 1 data 010000000000000000000000000000000000010000000000000000000000001487085703
2021-2-26 09:35:50.191 // I pressed button 119 here (Row 7, Col 14)
2021-2-26 09:35:50.192 1 data 010000000000000000000000000000008000010000000000000000000000001487097903
2021-2-26 09:35:50.259 1 data 01000000000000000000000000000000000001000000000000000000000000148709be03
2021-2-26 09:35:50.907 // I pressed button 120 here (Row 0, Col 15) (Top Right Button)
2021-2-26 09:35:50.908 1 data 0100000000000000000000000000000000010100000000000000000000000014870c4103
2021-2-26 09:35:50.994 1 data 0100000000000000000000000000000000000100000000000000000000000014870c9603
2021-2-26 09:35:51.206 // I pressed button 121 here (Row 1, Col 15)
2021-2-26 09:35:51.207 1 data 0100000000000000000000000000000000020100000000000000000000000014870d6903
2021-2-26 09:35:51.300 1 data 0100000000000000000000000000000000000100000000000000000000000014870dc703
2021-2-26 09:35:51.555 // I pressed button 122 here (Row 2, Col 15)
2021-2-26 09:35:51.556 1 data 0100000000000000000000000000000000040100000000000000000000000014870ec303
2021-2-26 09:35:51.652 1 data 0100000000000000000000000000000000000100000000000000000000000014870f2403
2021-2-26 09:35:51.971 // I pressed button 123 here (Row 3, Col 15)
2021-2-26 09:35:51.971 1 data 010000000000000000000000000000000008010000000000000000000000001487106103
2021-2-26 09:35:52.056 1 data 01000000000000000000000000000000000001000000000000000000000000148710b603
2021-2-26 09:35:52.352 // I pressed button 124 here (Row 4, Col 15)
2021-2-26 09:35:52.353 1 data 01000000000000000000000000000000001001000000000000000000000000148711db03
2021-2-26 09:35:52.429 1 data 010000000000000000000000000000000000010000000000000000000000001487122703
2021-2-26 09:35:52.748 // I pressed button 125 here (Row 5, Col 15)
2021-2-26 09:35:52.749 1 data 010000000000000000000000000000000020010000000000000000000000001487136603
2021-2-26 09:35:52.834 1 data 01000000000000000000000000000000000001000000000000000000000000148713b903
2021-2-26 09:35:53.226 // I pressed button 126 here (Row 6, Col 15)
2021-2-26 09:35:53.227 1 data 010000000000000000000000000000000040010000000000000000000000001487154003
2021-2-26 09:35:53.314 1 data 010000000000000000000000000000000000010000000000000000000000001487159603
2021-2-26 09:35:53.674 // I pressed button 127 here (Row 7, Col 15) (Bottom Right Button)
2021-2-26 09:35:53.675 1 data 01000000000000000000000000000000008001000000000000000000000000148716fc03
2021-2-26 09:35:53.737 1 data 010000000000000000000000000000000000010000000000000000000000001487173b03

Discussion: Major updates to the library

First, I want to thank SuperFlyTV and others who have contributed to this project.

I am new to node.js things and so it has taken me some time to understand and set up node.js and finally run some tests.

I have seen your requests for testing X-keys devices that you do not have.

I actually have ALL X-keys ever made, and many never made, and some to be made.

It seems that the manufacturer should be the first to volunteer to help out and I am sorry we have not done so sooner.

But my history and skill is really more at the single bit level and not multi-OS open source projects.

Usually, my only concern to deliver single key presses, 1 bit each, and my largest product is only 128 keys. Just 128 bits to worry about, how hard could that be?

I would love to help out here, if you do not mind, I need a bit of guidance here. I can see several issues that could be quickly fixed. And some that would take more time and testing.

Again, at the USB level we deliver a 36 byte message, where every bit is sacred, I do not have any experience using TypeScript, or how to compile and test the changes I propose. But I would like to learn.

Issues:

  1. many PIDs in the products.ts will not work because they do not send consumer endpoint data. I can edit this and include many more products. My test confirm this, I can set any device to any pid,
  2. The numbering of the key index for products with less than 8 rows is not correct.

for (let x: number = 0; x < this.deviceType.columns; x++) {
for (let y: number = 0; y < this.deviceType.rows; y++) {

	const keyIndex: number = x * 8 + y

	const d = data.readUInt32LE(2 + x)

	const bit = d & (1 << y) ? true : false

	buttonStates[keyIndex] = bit
}

}

Here the for loops are indexed on columns and rows, but the key index is created from X*8 + Y and that assumes each column has 8 rows. This can be easily fixed for some units like the XK24 but others like the stick keys are more complex.

In truth what we call columns is just the bytes in the message and the rows are the bits in that byte. Usually that is rows and columns and for our products with 8 rows it works out perfect.

Thanks for this work, if you can guide me I will try to help test and fix the minor issues that our more unique devices may cause.

Support for XKE-64 JogT-bar

2021-2-10 09:05:15.978 Listening to device (1):
2021-2-10 09:05:15.981 manufacturer   P. I. Engineering, Inc.
2021-2-10 09:05:15.986 product        XKE-64 JogT-bar
2021-2-10 09:05:15.989 vendorId       1523
2021-2-10 09:05:15.991 productId      1325
2021-2-10 09:05:15.994 interface      0

Console log statement becomes rather spammy

The console log statement here can become rather annoying at times.

I have an API on top of this NPM lib, with the API offering control of backlights - including intensity - via a single call.
At times the API is called frequently (many times every second) and the console then becomes just a long list of

this.deviceType.banks 2

Is there a reason to keep that console.log there, or should I send in a PR to get rid of it?

Love the lib btw - super useful!

Closing down neatly

As an experiment in using xkeys, I've made myself a replica of PIEng's Device Finder application. It works fine, including multiple device re-connections, so I'm quite pleased with it.

However when running from a terminal with npm start or $(npm bin)/electron ., closing the application window doesn't return to a prompt, rather waits until I do a Ctrl-c. I guess an event handler somewhere is still waiting for events without having been cancelled. My issue is how to close down cleanly?

If anyone is interested, the code is at devicefinder where you can see (in src/main.js) how I'm currently trying to close things down in app.on('window-all-closed', () => {...}) function.

Thanks,
chris

XK-24 EEPROM retaining code?

Having an issue with an XK-24 where it's hanging onto previous programming while I'm trying to update code - how do I overwrite the non-volatile internal code while developing? Not seeing a function for that...or is it just my keypad? Thanks for any pointers!

Xkeys Switches

I was looking for a way to use Xkeys Switches with node, http://xkeys.com/XkeysSwitches/index.php

I wanted to see if anyone had looked into this at all before I jumped in. I use this code to interface with the XK-12 with Jog and it's pretty slick and simple to use.

Support for XK124-Tbar

Good day,

Could you build in support for the XK124-T-bar?
I started with the following snippet in products.js which enabled all the buttons for me:

    XK124TBAR: {
        identifier: 'XK-124 T-Bar',
        productId: [1278],
        columns: 16,
        rows: 8,
        hasPS: false,
        banks: 2,
        bankSize: 128,
        disableKeys: [108, 109, 110, 111]
    },

If i am correct, support for the t-bar has to be built in seperatly, because it reuses the dataslots from the buttons 108-111?

i ran loghmi.js, i will try to
attach the exported logfile to this issue.
log.txt

call a xkeys function out of the watcher

Hi
thx for this new version 2.0.0.
I failed to call a setBacklight function from outside the watcher.
I have a webbased virtual keyboard that I sync to the xkeys panel:
No issue while clicking on a physical key, I can turn both on red color.
But when I click on my virtual key, how can I set my xkeys key on red color?

Help with building

I made a fresh clone, installed yarn and ran it to install the dependencies - as mentioned in the README. Before making any changes at all, I ran yarn lint but it gave some errors about not finding @xkeys-lib

chris@d8:~/src/xkeys$ yarn lint
yarn run v1.22.11
$ lerna exec --stream -- eslint . --ext .ts,.tsx
lerna notice cli v3.22.1
lerna info Executing command in 5 packages: "eslint . --ext .ts,.tsx"
xkeys-webhid: /home/chris/src/xkeys/packages/webhid/src/index.ts
xkeys-webhid:   1:15  error  "@xkeys-lib/core" is not found  node/no-missing-import
xkeys-webhid: /home/chris/src/xkeys/packages/webhid/src/methods.ts
xkeys-webhid:   1:40  error  "@xkeys-lib/core" is not found  node/no-missing-import
xkeys-webhid: /home/chris/src/xkeys/packages/webhid/src/web-hid-wrapper.ts
xkeys-webhid:   1:44  error  "@xkeys-lib/core" is not found  node/no-missing-import
xkeys-webhid: โœ– 3 problems (3 errors, 0 warnings)
lerna ERR! eslint . --ext .ts,.tsx exited 1 in 'xkeys-webhid'
lerna WARN complete Waiting for 1 child process to exit. CTRL-C to exit immediately.
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

I guess @xkeys-lib is produced when the source code is built but I'm not familiar with yarn - what's the procedure for building?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.