OpenMacroBoard / StreamDeckSharp

A simple .NET wrapper for Stream Deck
MIT License
351 stars 47 forks source link

Suggestions for how to diagnose a disconnection issue #32

Closed jskeet closed 2 years ago

jskeet commented 3 years ago

I'm using StreamDeckSharp for some church A/V presentation software - you select a hymn, reading, PowerPoint presentation or whatever, and the Stream Deck displays the individual pages/slides to present.

Until yesterday, everything was going fine... but with one style of presentation, I'm seeing the Stream Deck disconnect after I've set all the button bitmaps. No exceptions are thrown. Interestingly, all the code setting the bitmaps completes and then it disconnects, but only a subset of the buttons are displayed - and it's not always the last one that's failing to be shown.

I can always reproduce it by showing the "problematic" presentations multiple times, but any given time it has about a 50% chance of being absolutely fine.

This is a WPF app, and I'm calling SetKeyBitmap from the WPF thread, if that's relevant. If I sleep (in the WPF thread) for 100ms after each SetKeyBitmap call, that seems to sort things out, which suggests there may be a race condition (or buffer overflow) somewhere, but I don't know enough about the internals to diagnose things any further... and if I try to stress test it by setting bitmaps on all keys 100x over in a loop, that doesn't provoke the disconnection. It's infuriating!

Hardware: Stream Deck (but I can test on a Stream Deck XL as well) Versions: currently 3.0.0, but I first encountered this on 2.2.0 (with OpenMacroBoard.SDK 2.1.0)

wischi-chr commented 3 years ago

Hi Jon.

I'm honored seeing you here.

Background Story

Without going into too much detail, when I originally started this library, I wanted it to be able to handle basically anything you throw at it, without the consumer having to even think about the USB IO overhead for example when streaming a video to the device.

So with the default settings there is a long running background task (in CachedHidClient) that reads images from a queue that only remebers the most recent image for a given key, so if you throw a few hundred keys at it in succession not all of them are sent to the device (basically some sort of frame skip if the USB stream can't keep up). I'm not sure what would cause a race condition with the current implementation, because only a single thread ever writes to the device (unless I messed something up, which is entirely possible). I had similar issues in the past (see this wiki article) where the devices showed artifacts from bitmaps that weren't even sent and never showed up on the USB traffic (recorded by USBPcap). StreamDeckSharp internally uses HidSharp to communicate with the Stream Deck Device so I probably have to take another look if I used it wrong or missed something else.

Possible work-around

Long story short, there might already be a workaround if you don't need high frame rates and the frame skip feature. Depending on how you open the Device you can use StreamDeck.OpenDevice(devicePath, useWriteCache: false); or you can use StreamDeck.EnumerateDevices to enumerate the devices and set the property IStreamDeckRefHandle.UseWriteCache to false to disable the caching behaviour, before calling IStreamDeckRefHandle.Open();. This basically skips the cache and the long running background task and all (HID)-calls happen synchronously - My guess is that this will fix your disconnect issues but will block the WPF UI thread briefly while writing to the device.

Questions

Would be great if you have time to answer a few questions, so I can try to nail down the disconnect issue when using the cached connection mode.

  1. What do you mean with "disconnect" - Does the HID disappear in the device manager and also make the typical windows device disconnect sound, or is it still available as a device but can't be controlled by 'StreamDeckSharp'?
  2. Do you have the original or Rev2 of the Stream Deck? The original uses the product Id 0x0060 and the new hardware revision identifies as 0x006d. It can also be deduced from the firmware (1.0.xx --> rev1, 1.02.xx --> rev2)
  3. Does it happen on the StreamDeckXL as well?
  4. You mentioned that it's "one style" of presentation. What makes this kind of presentation unique compared to all the others that work?
  5. Are the WPF software and a sample presentation of a sensitive nature or is it possible that you can send them (e.g. by mail) so that I can try to reproduce the issue.
jskeet commented 3 years ago

Thanks so much for such a detailed write-up! (And for the library to start with, and for putting the effort into consumers not having to think about the USB IO overhead.)

To answer your questions:

In terms of diagnosing this, it's quite hard to describe what makes this presentation different - I strongly suspect it's around the timing of when things happen, but I haven't pinned that down yet. I can't easily share the app, not because of sensitive information but because it's somewhat sprawling (and expects other hardware and software to be available). When I get some time to look into this again, I'll try to recreate it in a brand new app, which is what I'd normally do after narrowing it down a bit in the full app. I'm hoping it will still fail in that small app, using the same code... the fact that it's so intermittent makes it all really tricky. Will get back to you when I have more information.

I'll try disabling caching, but I suspect the workaround of waiting a few milliseconds is just as simple for now - it'll be useful diagnostic information though, for sure.

Thanks again for the write-up, and I'll let you know when I have more information.

wischi-chr commented 2 years ago

I'm closing the ticket. If you still have those issues or have more information about it feel free to reopen the ticket or create a new one. I'd love to help.

jskeet commented 2 years ago

No problem, thanks. I've still had a few issues, but I'm beginning to think it may be something to do with my physical Stream Deck - there's definitely something fishy going on, in that after using it several times things get sluggish. I'd be very surprised if that's due to anything in your library.

wischi-chr commented 2 years ago

I also had a few issues with some of my devices (I've all Stream Deck variants).

Some of them seem pretty sensible to how the usb is connected (maybe a power issue, I don't know) and worked a lot better once I connected them directly to the PC (instead of using a USB hub - even though my USB hub has a separate power supply).

My StreamDeckXL for example sometimes randomly pressed some keys and I couldn't figure out why - but Elgato replaced the device once I sent them a video and the new seems fine for now.

I'm not certain about it, but I think Elgato works around some of the hardware issues with their official StreamDeck software - they have a software debounce mechanism for example.

jskeet commented 2 years ago

That's good to know, thanks - particularly the part about Elgato replacing the device. If I can reproduce the issue consistently, I might try to go the same route. But yes, I agree about the sensitivity to the USB connection. Thanks for the extra info!

hagronnestad commented 8 months ago

Sorry for reviving this thread, but there's definitely some issues related to certain USB-hubs/USB-port (controllers?) combinations and the Stream Deck.

I recently upgraded my PC and started having issues with my custom Stream Deck software. Still using the same USB3.0 hub as before, but started having intermittent connection issues when using the USB ports on my motherboard. Switched over to another controller (separate PCIe card) and it's working perfectly again.

All other USB devices (webcam, wireless headset dongle, SD-card reader etc.) worked fine on both the motherboard ports and the separate controller. It's only the Stream Deck that has issues.

(Thanks a lot for StreamDeckSharp!)