dagoch:
but I can find any documentation for the Python interface to Bridge.
I have also been unable to find any such documentation. Anything I've accomplished has been by trial and error, and by muddling through the source code.
Even this thread (HowTo: Write to Bridge Mailbox from Python - Arduino Yún - Arduino Forum) which seems to be closest to what I need doesn't close the loop: it shows how to send messages from Python to Arduino using the Mailbox, but not how to receive messages back from the Arduino.
Forum member sonnyyu has worked out quite a few tricks with the Yun, and has documented them on his site http://www.ibuyopenwrt.com/
One of his examples is MailboxWriteMessage which writes in the sketch, and reads with Python.
Also... can anyone provide instructions for setting up a persistent bidirectional socket for communication between a Python script and an Arduino sketch on the Yun?
Not specifically a socket, but when when I want to do bi-directional communications between the sketch and a Python script, I use a Process library object.
For example, this is what might be in a sketch (It's a copy/paste of several sections from a larger sketch, I don't promise that it compiles and runs as-is):
Process Proc; // Linux process manager object
void setup()
{
Proc.begin("/mnt/sda1/scanner/scannerProcess.py");
Proc.addParameter(ID);
Proc.runAsynchronously();
}
void loop()
{
Proc.println("Some data..."); // Write something to the process
while (Proc.available()) // As long as there is data from the process
{
char ch = Proc.read(); // Read a character from the process
process(ch); // Process the character
}
}
Then, on the Python side, one issue is that the printed output from a Python script is buffered. That means nothing will be received from the sketch until the process exits, or enough data is sent that it fills a buffer. I've used two ways to deal with this, the first being to start the script with the shebang [color=blue]#!/usr/bin/python -u[/color]
where the -u says to used unbuffered I/O. This works but using Python's print() function adds space between printed elements, and adds newline characters.
In my latest project, I wanted better control over the output so I didn't want to use Python's silly print statement, so I added this to the beginning of my Python code:
import sys
def write(value):
sys.stdout.write(str(value))
Unlike print(), sys.stdout.write() doesn't add any spaces between elements, and doesn't add newlines after each call. To make writing a little easier, and to make sure everything was strings that the sketch could read not send any binary data, I added that write function definition. So, to send something to the sketch, I could simply code something like:
write('Length: ' + str(len(code)))
To have the Python code read from the sketch, I used something like this:
# Process until the end of the world (or reset, whicever comes first.)
while True:
# wait for and read a line of text from the sketch (stdin)
# strip any whitespace characters
code = raw_input().strip().upper()
# Do something with the input value here...
raw_input() reads a line of text from stdin, ending with a newline (which is added by the println() call when writing to the Process object.) In my case, I wanted to ignore any leading/trailing whitespace so I added the trim() call, and I wanted everything uppercase so I added the upper() call. Your needs may vary.
I've run into issues where the Python script may crash due to coding stupidity on my part, so I've changed the launch logic around to make it relaunch automatically. Instead of starting the Process object in setup(), I have this code at the top of loop():
void loop(void)
{
if (!Proc.running()) // Is our Process object still running?
{
Proc.close(); // No, close the dead process to clean up resources
// Try to restart the process
Proc.begin("/mnt/sda1/scanner/scannerProcess.py");
Proc.addParameter(ID);
Proc.runAsynchronously();
}
// Continue on with the rest of loop()...
This way, if the process should stop for whatever reason, it is automatically restarted. While this last idea is new, I've used this basic Process communications method in several projects, and it has been very reliable. I also think it's fairly low overhead compared to some of the other methods (probably the only way to get more efficient is to bypass the Bridge altogether and implement Serial1 communications directly, but then you lose all of the other Bridge functions.) In the message thread you quoted, I only used the WriteMailbox idea because I had an independent process (not launched by the sketch) which I wanted to be able to send data to the sketch. It was easier to just use the Bridge's Mailbox class than it was to figure out how to send the data to the other Python process so it could forward it to the sketch.