C# and USBReports / Asynchronicity and Loops
So, I think I've finally understood how those USB devices for measuring stuff are working. Now I have to implement something I'm not exactly too sure of how to do best. At the heart of the matter is this: The communication with the devices has to be done through raw USB packets and is thus asynchronous / event driven.
Basically, it works like this: I attach an
device.InputReportReceived += inputReportEventHandler;to the device and then do
await device.SendOutputReportAsync(outReport);where outReport is basically a 65 bytes long buffer. For this outReport there are two options: I can do a "broadcast" (like: Everybody, stop everything!) or I can do a targeted command. The former does not ever receive a reply while the targeted command will always yield a reply.
The command routine then follows this path, as far as I was able to discover:
a) Discovery command ("Is someone there?")
b) Recognition command ("What module are you?")
c) Initialization command ("Okay, I need you to measure Volts in the 30V range every 50 ms")
d) Time reset command ("Set timer to zero")
e) A loop of two commands - first the Status command ("What are you measuring?") and then the Time command ("When did you measure?")
f) followed by a reset, maybe.
Now, this loop there - this one may be a continuous loop (i.e. until the user presses the "Stop" button) or until a certain amount of measurements has been taken.
I was thinking of a List of Commands where each entry contains additional information on a) the amount of loops, b) the steps the iterator has to go back if still in loop and c) wether to wait for an answer for the command or not.
Thus the "outer loop" would iterate through the list, execute the command and either a) go immediately forward when no answer needed, b) go forward only after receiving a reply or c) go backward the specified amount of steps upon reaching a loop condition.
Or does anyone have a better idea?
@Rhywden is each operation an event or is it synchronous?
@lucas1 The command I'm sending is done through
await device.SendOutputReportAsync(outReport);- thus everything that goes to the device is directly under my control. I then may or may not receive an event in reply - though that is determined by the exact command I'm sending.
@Rhywden If you aren't sure if you will receive a reply you are better using reactive extensions.
I use similar in typescript and everything is done via a pub / sub pattern which allows you deal to with failure.
So in TypeScript / Angular 2 you would do in your "service class".
return this.device.Report.map(data => <some operation to map data>).catch(<some error delegate>).
That returns an observable.
so you would consume it as
doSomethingMethod would be a delegate in C# or an anonymous method.
I hope this made some sense. I am not 100% myself about Pub / Sub and Observables.
It is a bit of a head fuck to get your head around at first but once you know the pattern it is easy.
Or does anyone have a better idea?
It seems straightforward enough to implement and see if any problems with the approach pop up.
I'm not sure you actually need a generic list of commands if the actual list is going to be static - just run the initial setup routine, then loop continuously over the status-time loop with an optional exit condition.You'd probably abstract out a
SendAndMaybeWaitForReplyprocedure of some sorts (since it doesn't seem like you actually are doing any asynchronous processing) and just use it to implement the flow in code.