Closed Julusian closed 1 year ago
Oh, so it does also get stuck even with that sleep sometimes...
Looking at wireshark from the official application, there is so much going on before it starts trying to draw anywhing. Perhaps some of that is necessary to help it start correctly?
I think I 'solved' this by making sure to only have one packet in flight at a time. Or I can solve it by never waiting for any responses, and simply relying on order of commands being pushed into the serial buffer to ensure things happen as I expect. Doing this makes the drawing much smoother than limiting packets in flight. I havent checked how that behaves when doing things like getting the serialnumber
Looking at the initial 'handshake' done by the loupedeck software, and wireshark shows a very sequential order of operations, being call and response. I dont know if this is necessary, but it definitely helped.
But this isnt possible without modifications, because things like setting button color doesnt return a promise, so I cant wait for it. Is there a reason that only some send messages are tracked?
An unrelated discovery is I can see a command 0x2302 being sent in wireshark. with the payload
07 00 28 00 / 08 ff 24 14 / 09 00 00 00 / 0a 00 00 00 / 0b 00 00 00 / 0c 00 00 00 / 0d 1e 00 50 / 0e 1e 00 50
. (slashes added based on a hunch)
That looked suspiciously like setting the button colours in bulk.
A quick test of sending 0x0b02 with 0x08, 0x00, 0xff, 0x00, 0x0a, 0xff, 0x00, 0xff
confirms that I can change two buttons at once.
Note that 0b matches the length of this packet (8 payload, 2 'header', 1 responseId).
So I am pretty sure that the HEADERS map while it works, is an over simplification. The first byte of them is the length of the packet, with the next byte being the 'commandId'. This is visible if you look at VERSION_OUT and VERSION_IN, as they both end in 07.
Thank you for doing this additional investigation!
But this isnt possible without modifications, because things like setting button color doesnt return a promise, so I cant wait for it. Is there a reason that only some send messages are tracked?
I believe that's what the official software does, but it doesn't mean we can't. In fact, if the device supports it, I would be a fan of tracking all requests so they can be await
ed. I will investigate later this week if the device is fine with that.
So I am pretty sure that the HEADERS map while it works, is an over simplification. The first byte of them is the length of the packet, with the next byte being the 'commandId'. This is visible if you look at VERSION_OUT and VERSION_IN, as they both end in 07.
Yes, you're right. I've noticed this pattern for many of the commands, but it wasn't always clear how to distinguish a request from a response. However, knowing that we generally are only and always dealing with responses when we process incoming data, there's definitely room for simplifying the way the message types are sent/received. I'll look into that as well.
I believe that's what the official software does, but it doesn't mean we can't. In fact, if the device supports it, I would be a fan of tracking all requests so they can be awaited. I will investigate later this week if the device is fine with that.
In my testing it looks like the device does ack everything. So I am doing this now Some complexity arises because of needing to ensure only one thing is in flight at a time, which requires some queue to be added for commands. Which sounds simple, but drawing a buffer and refreshing wants to be treated as one operation in this queue.
As part of investigating this I did start implementing it and quickly found that the scale of changes I was making resulted in a mostly rewritten library. I did consider doing some of it in the application instead, but I need to use this in two similar but different applications, so that would have been a lot of duplicated code for me.
So I have decided to embrace this and publish it as an alternate library. I am not bothered by the potential extra work here, I was originally expecting to have to do a lot of reverse engineering to get to this point, and in my experience libraries like this tend to only need changes to keep dependencies updates and to support newer models. This also lets me do things my way (typescript, class per model). I've already done some untested implementations of the razer one, and live-s based on https://github.com/CommandPost/CommandPost/blob/develop/src/extensions/hs/loupedeck/init.lua
Thank you for all your help and responding so quickly to me on each issue I have opened, and for the good discussions.
Thank you too for the great discussion. You're always welcome to provide extra feedback, discussions or collaborations.
Hopefully one of these days I can get my hand on one of the other Loupedeck devices and do more compatibility and testing.
Im getting some weird behaviour, that I'm not sure how to go about debugging. It only
My code is as follows:
And it works, but the
drawBuffer
call doesnt resolve until something else happens. I requires me press something on the device, for the response to be received and it will continue. Also of note, is that the circle button did not change colour correctly, but the rest did. It stays the wrong colour even the pending draws finish.Even more interesting, is that if I give it a few ms delay with setTimeout, then it appears to work reliably. So this seems like some race condition, but I can't see anything that would indicate as to why it needs that delay, or if there is anything the library could/should be waiting on instead of an arbitrary sleep.
Any ideas?