Hey Chris (and John),
History of MW IO Devices
Originally, MW had an elaborate model for IO devices where a complex negotiation between capabilities and requests could be managed. This was modeled roughly on the USB HID negotiation process. This snowballed out of control and became more general and complex than anyone needed or wanted to deal with. The ITC18 plugin (which Jim wrote) is a good example of why this structure isn’t a good idea. In a perfect world, this kind of complex negotiation could make a ton of sense if you wanted to write protocols that could port easily to new setups without necessarily knowing what IO device would be used, or if you wanted to expose as much flexibility in the device as possible. In reality, you usually know exactly what IO device you’ll be using and how, and you perhaps just want to target that device as simply as possible.
Current state of things
The more “modern” IO devices that I have written (e.g. NE500), technically still descend from the IODevice base class, but they mostly just override and ignore the formalities of the base class. I included NE500 in the public distribution of MW (and not in my private plugin repository) specifically to serve as an example of a simpler, less fussy IO device.
The current thinking is that since all IODevices are implemented as plugins (which didn’t exist when we spec’ed the origin IODevice base class), then you really ought to be able to do whatever configuration you need to do in the ComponentFactory when the object is created (when the XML is parsed). You can still be guaranteed that all of the IODevice base class calls will be called in the same order as before (e.g. attachPhysicalDevice gets called after parsing, but before your paradigm starts), but there is no obligation on your part to use any of these methods, and there is rarely a strong reason to do so. That said, the base class IO device negotiation stuff does work exactly as advertised, and you can certainly use it if you find it helpful.
At some point, as long as there aren’t strong objections from users, I’d like to refactor everything except for the “start” and “stop” calls into a subclass, so general/complex implementations such as the ITC18 won’t need to be rewritten (except superficially), while at the same time, allowing simpler IO devices to avoid being burdened with that extra bloat. Maybe 0.4.5 will be a good time to do that.
Upshot for how I’d recommend you write IO plugins
Handle the configuration of the IODevice object however you like in the plugin factory object and the object’s constructor. Your object should descend from IODevice, but I’d encourage you to “hollow-out” everything except startDeviceIO/stopDeviceIO. Your object should respond to these start/stop methods (these are driven by the stock StartDeviceIO and StopDeviceIO actions), presuming it makes sense for them to do so. This gives the user the opportunity to mark sections where they want IO active, e.g. in case the device clock drifts over time and resyncing is needed, or if there would be too much data saved to disk if the device were running constantly.
This also implies that you can safely ignore the IOChannel, IOChannelRequest, etc. classes, unless they are specifically useful to you. The addChild() call that gets called during parsing allow you to associate whatever custom channel (or other) objects you’d like with the IO device. NE500 works this way.
I’d also recommend building something only at the level of generality that you actually need right now (e.g. no need to implement features of the hardware you don’t anticipate actually using; you can always implement that later if needed).
Everything else is up to you. As with all plugins, you can interact with special features of your particular device via custom actions (e.g. “OpenBombBayDoorsAction” or “ActivateLaserAction”, whose sole purpose in life would be to call a custom method on your IO device class); these custom actions would also be packaged up in the same plugin as the IO device component. Data passing can happen via Variables / VariableNotifications, just as everywhere else in MW.
Let me know if any of this doesn’t make sense. Hope this helps,
Dave