I've just developed a nice method for communicating between two different programs on the same Pi.
- Performant, uses a RAM drive, is self-cleaning after reboot/restart of either end
- Pipes-like behavior, but a custom set of code to implement it
- Python 3—compatible
- Pairs of pipe files are created after bootup in the RAM drive for
- Can respond with
stringor Python objects like
- Assumes client-initiated conversations with optional responses
- Incorporates a mechanism for determining that the other side has read/consumed the message sent
- tcp-like delivery of messages in order and with sequencing
- Works across different programs (doesn't need to be a child process)
- Could also work from a remote computer as well, in theory
- handshake mechanism
- the RAM drive lives under the
/home/pisubtree and is owned by
pi:pi, making life easy
- I think this could be optimized to sub-second roundtrips to the server and back; I've currently set a timeout of two seconds for development purposes
- The naming standard allows messages to easily be processed in the order sent by sorting the directory listing
- Can support multiple services (pipe pairs)
serverafter either end of the communications comes up.
Hello\nas the content; deletion of the file indicates reception and that the communication pipe is in-place
./servicename/server/YYYYMMDDHHMMSS_2created by the client with
someOctoPrintVerb\nwhich then results in the server deleting that, creating
./client/YYYYMMDDHHMMSS_2.picklewith a pickled dict object response from OctoPrint from the plugin side of things in this case; the client unpickles the response, deletes the file and has the dict object
- essentially, the client creates a new file in
serverand polls the
clientfolder for the matched response; the server polls
server, runs the report and responds to the
clientfolder by creating the match filename
FIFOs ("named pipes"), couldn't use Queue and other parent/child process sort of solutions... I just kept finding that they wouldn't work at all or wouldn't work well in a fault-tolerant way if both or either end of the communication restarted. The more I worked with them, the more complicated the fault-tolerance code became. So I decided to roll my own on this one.
It behaves like a queue metaphor in that requests are time-stamped, sequenced and consumed. It behaves like
rpc in that binary objects can be shared across programs. It behaves like named pipes in that it includes the service name as part of the path. It includes handshaking, timeouts and pipe-rebuilding after loss of either end.
I've created a RAM drive—based named-pipes replacement for inter-process communication to make it easy to separate TFT screen programming, for example, from the OctoPrint plugin interface.