Of course, no sooner did I get to creating the first plugin module (Modbus) than I hit a hurdle: The
libmodbus library takes care of all it's own communication. One of the first examples it provides reads:
modbus_t *ctx;
ctx = modbus_new_tcp("127.0.0.1", 1502);
Thinking about it deeper though, this may not be a problem at all. CLI handling will need to be modified somewhat, but a series of hooks and callback functions ought to modularize this aspect nicely. For example, I could have the base command handler function check to see if we have a module type installed matching the value of arg[0], and pass off cmd processing to that plugin's command parser.
Another problem I encountered is that under the present system the
channels run in their own threads, talking to whatever devices are associated with them. If we create a Modbus RTU device, it will not be associated with any channel, and therefore will not have any thread to work in. We have a couple of options then, we could:
- Make it a plugin option to create a thread for the module, passing control to a module worker function tasked with looking after the communication of all that module's devices.
- Make an option per device to have a dedicated worker function managing that device's communication, each of which runs in it's own thread.
- Something else?
I'm leaning towards option #2 personally, since this gives the most flexibility. This way, a device can be put on a communication channel, or it can
do it's own thing. Of course, each module could define it's own communication requirements as part of the API. A module for DSC panels may specify that it's devi ...
BREAKING THOUGHT We could add a parameter to the channel structure so that it designates what each channel is for. Channels may be unreserved, IE: Are not linked or tied down to any one module (such as they presently are.) They could also be reserved for a specific module type (this would help clarify their purpose / function when listing the channels and would also prevent the user from inadvertently placing devices from two or more different modules on the same channel.
We now return you to your previously scheduled programming thoughts... Back to the DSC panel example, we could create a Plugin for DSC panels. (Maxsys, Power Series and Neo). This plugin would indicate that it's communication is handled at the channel level, and would provide a function pointer to it's main worker thread, one worker for each channel thread. The panel structures would be shared within the plugin code, but protected from multi-threaded access by rwlocks as we have gotten very good at writing, Thus each worker thread would scan the plugin's array of devices, acting only on devices registered for communication on that specific channel.
That approach would then be complimented by the modbus mode, whereby the plugin's devices do not need to associate with any channels on their own (maybe we could even prohibit this (or at least ensure it does not become and option for selection) and enabling a modbus plugin device would create a new thread specifically for handling that device. I think this makes sense, it's becoming clear in my mind -- now to try to implement it!