Proper Usage of io.intercept and passing data back to <Incoming>

Part of the problem with luup.io.intercept() is that it’s full of race conditions by design. If you’re communicating with a serial device that sends its response in bursts, then you may only get part of the response in luup.io.read(). Sure, you can call luup.io.intercept() again, but there’s a window in between where the serial device might have tried to send more data. Where that data goes is unspecified.

Every plugin that I’ve written that uses a serial connection I’ve eventually given up on using luup.io.intercept() and ported it to a state machine with transitions controlled by handlers. Yes, a state machine adds complexity. But your plugin will probably evolve through the same stages of development and you’ll end up doing the same thing. Save yourself refactoring the code later by designing in the state machine now.

For example code, see my Caddx alarm plugin. The general idea is:

[ul][li]When the plugin receives an action from a scene or UI, the implementation file’s code sends the outgoing serial data, and adds to a global table that I’m expecting a response. Then it returns.[/li]
[li]Handle all serial responses through the section (there is no luup.io.read()). For each response, act on it, then remove it from the “expected” table if it was there.[/li][/ul]