Julusian / node-xencelabs-quick-keys

A Node.js library for interfacing with the Xencelabs Quick Keys https://julusian.github.io/node-xencelabs-quick-keys/
https://www.npmjs.com/org/xencelabs-quick-keys
MIT License
33 stars 4 forks source link

Device is "readonly" when using wireless dongle #1

Closed jimbuck closed 2 years ago

jimbuck commented 2 years ago

Hey there! I just got my Quick Keys a week ago and already have plans to build a custom config editor. I saw this project and tested out the demo but it was only partially working.

I can select my device and see it log the buttons/scroll, but the sliders don't change anything and neither does the overlay.

Also, I was able to get the demo running in StackBlitz, which means it can be edited and debugged by anyone. The key is the "Open in New Window" feature, that allows the HID functionality to work. image

jimbuck commented 2 years ago

I figured it out! I use the included wireless dongle so when I select a device it says "Xencelabs Dongle - Paired". Unplugged the dongle and connected via USB and it showed up as "Xencelabs Quick Keys - Paired", which did update when I changed colors/overlays/etc. on the demo page.

Any ideas on how to get it working via the dongle?

Julusian commented 2 years ago

I've got a fix for this, as well as detecting when the surface connects and disconnects to the dongle and hopefully battery level monitoring too

Julusian commented 2 years ago

Demo site is updated, and 0.3.0 is published with the fixes

jimbuck commented 2 years ago

I see the battery level being displayed, but I still can't show an overlay/change the color using wireless. Any special instructions for the app/order to activate things?

Julusian commented 2 years ago

Strange.. are you on mac or windows? And have you made sure that the xencekeys software is not running?

jimbuck commented 2 years ago

I'm on Windows 10. I will double check that I stopped the Xencelabs software, that might have been it.

jimbuck commented 2 years ago

So it's still not working for me via the dongle-only. I did try the node version and I get the same outcome, button presses/wheel turns are read, but setting text/colors doesn't update.

What do you use to debug the data sent back and forth between the device. I'm happy to capture traffic/logs (and learn how to read them).

Julusian commented 2 years ago

I have been using wireshark with usbcap (I think usbcap is offered as one of the installer steps). If possible it is best to do it on a machine where you dont have anything else usb plugged in, as it avoids the need to filter out data in wireshark. After figuring out which usbcap interface to listen on (trial and error), make sure the xencelabs software is running and the dongle unplugged. Start wireshark listening, and plug in the dongle. Once the panel is connected you should have a load of usb packets in wireshark.

Reading the data is tricky. The main thing is to look at the URB_INTERRUPT out and URB_INTERRUPT in lines. out are messages sent from the computer to the device, and in the other way. Each one is formed of a message and an acknowledgement (which are not interesting). Inside those is a HID Data blob of hex, which is the data we are interested in.

If you skim through the URB_INTERRUPT out messages, you should be able to visibly see the text labels from your device. If you could share a capture of this data that would be helpful so that I can try and look into what it is doing differently. There are 6 bytes in the middle of most of the messages which are required, but I dont know what they mean. Perhaps that is a device id? That would explain why it works for mine but not for others. I did miss it on one command for a bit meaning it worked wired but not wireless

jimbuck commented 2 years ago

Sounds good, I will setup wireshark on a laptop and give it a shot (I tried it on my desktop, waaaay too much USB traffic, haha).

Thanks for your help!!

jimbuck commented 2 years ago

So, without getting a full dump, I already see one major difference. These are the bytes when setting five for the bottom left button:

  XenceLabs: 1b 00 e0 47 24 cb 0f d1 ff ff 00 00 00 00 09 00 00 01 00 25 00 03 01 20 00 00 00 02 b1 00 05 00 08 00 00 00 00 ed 74 0e 8a 95 dd 66 00 69 00 76 00 65 00 00 00 00 00 00 00 00 00
WebHID Demo: 1b 00 e0 47 2a c1 0f d1 ff ff 00 00 00 00 09 00 00 01 00 25 00 03 01 20 00 00 00 02 b1 00 05 00 08 00 00 00 00 eb 4f 49 bd d7 fa 66 00 69 00 76 00 65 00 00 00 00 00 00 00 00 00
                         ^^ ^^                                                                                              ^^ ^^ ^^ ^^ ^^ ^^

I'm not sure what's going on with that first part but the second set of differences is definitely an identifier. I checked and it matches the "Paired Devices" displayed in the Diagnostics screen of the Xencelabs App. So now the question is can we get that value programmatically?

(see the Paired Devices list below, the byte diff above includes ed 74 0e 8a 95 dd which matches Quick Keys#ed740e8a95dd image

Julusian commented 2 years ago

Perfect, that is exactly what I was suspecting. I already starting digging, and found where I think that is coming from, so I shall see if I can read that in properly

Julusian commented 2 years ago

So it turns out that the place where the device declares its id is not available through webhid at all, but could be made to be available in the node version, but will take some time for a couple of PRs upstream. Before I do that I shall see if I can find a weirder way of fetching the id, I am hopeful

jimbuck commented 2 years ago

You might have found it somewhere else, but it does look like the deviceId is sent with every button press. So one possible approach would be to add a "press any key on device to confirm" and then just extract and re-use that ID. It also includes it when "connected" emits, which could also work.

Julusian commented 2 years ago

Yeah, the 'proper' way to get the id is to use hid_get_indexed_string from the underlying library. That appears to be what the xencelabs software is doing. However, the underlying library has not implemented this on every platform, and there is not a matching way to do it for webhid.

When using the dongle, the software is doing what looks like a query for its connected status, with the response including the id, so that would be a good way to reliably get the id before attempting to do anything with the device.

For wired devices, the id isnt essential and I dont have an idea on how yet. But it would be really useful to have. Something to come back to once wireless is working properly

uffefrostbox commented 2 years ago

@jimbuck Thanks for looking into fixing this! I was trying to install your webhid-wireless-single-device fork using npm and tried a lot of different solutions looking around on how to install specific branches using npm but I couldn't get i to work. I much amit I am not that experienced :) I am building a remote using this node js module and also runs into the problems when I try to run Quickkeys wireless.

Julusian commented 2 years ago

I've been working on a rework of the library to better handle this id as well as having multiple panels connected to the one dongle. Its not done yet, its a complete rethink of how devices are handled/managed as opening the dongle can produce 0, 1 or 2 active panels https://github.com/Julusian/node-xencelabs-quick-keys/pull/5

I will finish this up when I can, I havent started using the panel I have yet because of this..

uffefrostbox commented 2 years ago

Great news, thanks Julian! Merry christmas by the way 😊

Julusian commented 2 years ago

I am happy with how #5 is behaving, I have updated the webhid-demo to handle multiple concurrent devices, and so it even handles a single panel on the one dongle. Wired devices also still work, but havent been tested in the nodeks implementation yet.

This is a pretty large rewrite of the api for opening devices. I havent added any device auto-detection into the api yet, but I am considering it

jimbuck commented 2 years ago

Happy New Year! 🥂

I will try to pull it down and test with it this week.

uffefrostbox commented 2 years ago

Hi. Just tried the 4.0 webhid-demo in newest Chrome on OS X 11.6 and seems to run just flawless but I don't get how to use this new 4.0 node js module? I am not that experienced. Could someone make a small example like the one in the NPM module frontpage for v3.0? Thanks again Julusian for this great addition of multi device support and by the way my feature request for graphics/icons to XenceLabs was kindly replied that they would forward it to their software team.... Here's for hoping!

Julusian commented 2 years ago

I don't have a simple example currently, but you can see the implementation I have written to use this in companion-satellite. The relevant bits are https://github.com/bitfocus/companion-satellite/blob/feat/satellite-api-v2/src/device-types/xencelabs-quick-keys.ts https://github.com/bitfocus/companion-satellite/blob/feat/satellite-api-v2/src/devices.ts#L39-L46 https://github.com/bitfocus/companion-satellite/blob/feat/satellite-api-v2/src/devices.ts#L168-L178

I do think the api for scanning/getting devices here is a bit unusual, but thats an unfortunate consequence of the wireless dongle supporting multiple panels..

I forgot to update the example in the docs, I shall try and do that soon https://github.com/Julusian/node-xencelabs-quick-keys/tree/main/packages/node#api