Go Down

Topic: Using BridgeClient in Python Scripts. (Read 27187 times) previous topic - next topic

e-existence

Sep 20, 2013, 04:00 am Last Edit: Sep 20, 2013, 04:29 pm by e-existence Reason: 1
This took me an afternoon to figure out, so I figured I would post it here hoping that others could use it. I have a project where I plan to pass values between the Arduino and the Linino environments and BridgeClient.py seemed to be the right way to go about it...


Code: [Select]

#!/usr/bin/python

import sys    
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
                                               
from bridgeclient import BridgeClient as bridgeclient
                                                   
value = bridgeclient()                              
                                                   
value.put('key','value')
                         
print value.get('key')



dreggy

Nice, this is very useful.
This seems to be the less memory eating method to access variables in every environment (Arduino, python and javascript using ajax)

scrot

Do you have the sketch that goes along with this?  I'm having a heck of a time setting up 2 way communications between a sketch and a python program.  The Process library "write" function doesn't appear to work.  Also its missing several of the variations mentioned in the documentation (i.e. ability to write strings, ...).

Thanks in advance.  The software doesn't feel quick baked yet.  I'm trying to basically make the arduino be a slave to the lineo side so that I can do all of my programming in Python.

e-existence

The Arduino code that I am currently using is as follows (I can't make any claims to it completeness, but it is working... )

Code: [Select]

#include <Bridge.h>

char D12value[2];

void setup() {
  pinMode(12,OUTPUT);
  Bridge.begin();
}

void loop() {
  Bridge.get("D12",D12value,2);
  int D12int = atoi(D12value);
  digitalWrite(12,D12int);
  delay(50); 
}


On the Linino/Python side `value.put('D12','0')` or `value.put('D12','1')` will set the mode of Pin D12 on the Arduino...

There is an example of Bridge.put() in the "Bridge" example included with the Ardunio IDE.

For what its worth... this is all early proof of concept code... ultimately I am looking for

Android App -> HTTPS/cgi-bin/python -> bridge -> Arduino/D12 -> Power Switch Tail -> Grundfos Hot Water Loop Pump.

I am currently learning just enough Android Application Development to trigger the HTTPS calls....

scrot

Excellent.  Thank you.  Now for a more difficult question.   :)

Can you do a Bridge.put() back up to your Python program?  I have not been successful at this.  I've read all of the source code for the Arduino Bridge, the Linio Bridge, and the Python BridgeClient, and no luck. 

Thanks again.

e-existence

I have not written anything that uses Bridge.put() on the Arduino side. It is used in the Bridge example included with the Arduino IDE.

Code: [Select]

  if (client.read() == '/') {
    // Read value and execute command
    value = client.parseInt();
    analogWrite(pin, value);

    // Send feedback to client
    client.print(F("Pin D"));
    client.print(pin);
    client.print(F(" set to analog "));
    client.println(value);

    // Update datastore key with the current pin value
    String key = "D";
    key += pin;
    Bridge.put(key, String(value));
  }

scrot

Just for you information.  I kind of got the Bridge.put() code to work... kind of.  It is very flakey and only works some of the time.  Also I found that it is easy to crash the Bridge process running on linino.  Just put a non-string and it will crash.  There isn't much in the way of exception handling.  I'm continuing to see if I can make it more reliable.  Its very difficult since the serial monitor behaves more erratically on Yun than on Uno.

e-existence

Interesting, for what its worth, I am "reading" ie: bridge.get() on the Arduino side ever half second and "writing" value.put() at least twice a day and am having no trouble.

Just checked uptime, 7 days now.. no issues...

If you can provide code examples, I wouldn't mind looking it over/testing.


scrot

Ok.  I've now gotten it to work reliably.  However it is very, very slow.  I'm only seeing about 4 get/puts per second, or a little over 1 transaction per second between my python program and my sketch.  Is there a faster way other than writing my own bridge?

I'm asking because I want to do all of my programming using the arduino as a slave to my python program.  I want to do my programming in Python on the Linino side.  To do this I need at least 10 transactions per second, I'd like 100 if I could.

When I looked at the BridgeClient.py I found that in the end it was setting up a new socket to the local port for every get or put.  Very inefficient.  Indeed it isn't much faster than using the Bridge REST interface from a remote computer.

I'm looking for performance similar to what I was seeing in my old Raspberry Pi <-> Uno combination using Firmata.

Any ideas?  (Just so you know I'm having a blast regardless of how it sounds.)

wpunkts

I might have an idea....

I've spent the last couple of days on the same problem. The goal is to have a Python script that listens to OSC messages from an application on my phone, and to pass on values retrieved from some of the messages to control PWM pins. Getting the Python script to run properly was surprisingly straightforward, given my (lack of) Linux and Python skills. So far, the script reads floats between -127 and +127 from two faders and sends the values back to the phone, where they're displayed in two text boxes as feedback.

All this works very fast and smooth. Excellent.

Then I tried to pass on the values to the Arduino sketch. I had been hoping that runShellCommandAsynchronously() would do the job, but apparently that's not possible. At least I couldn't get it to work.

After many, many hours of trying all kinds of things I found this thread. I managed to get it working, but, as mentioned above, the speed is simply unacceptable. However, using code from bridgeclient.py I was able to speed it up significantly. Adding
Code: [Select]
from bridgeclient import BridgeClient as bridgeclient
json = TCPJSONClient('127.0.0.1', 5700)
to the script, and replacing
Code: [Select]
value.put('D13','%i' % (fader1Feedback)) with
Code: [Select]
json.send({'command':'put', 'key':'D13', 'value':'%i' % (fader1Feedback)}) did the trick. Avoiding opening and closing a socket for every put is the key.

This will need a lot more testing and refining, but so far it looks promising.

Here's the relevant part of the script. Hope it's helpful.

Code: [Select]
#!/usr/bin/python

import OSC
import time, threading
import sys   
sys.path.insert(0, '/usr/lib/python2.7/bridge/')
                                               
from bridgeclient import BridgeClient as bridgeclient
from tcp import TCPJSONClient
                                                     
value = bridgeclient()
json = TCPJSONClient('127.0.0.1', 5700)

receive_address = ('192.168.1.144', 12345)

s = OSC.OSCServer(receive_address)

client = OSC.OSCClient()

s.addDefaultHandlers()

fader1Feedback = 0

# define a message-handler function for the server to call.
def printing_handler(addr, tags, stuff, source):
    global fader1Feedback
    global fader2Feedback
    if addr=="/1/fader1":
    fader1Feedback = int(stuff[0])
    msg = OSC.OSCMessage("/1/label2")
    msg.append('0')
    msg.insert(0, fader1Feedback)
    client.sendto(msg, ('192.168.1.109', 1234))
    print "%i" % fader1Feedback
    #value.put('D13','%i' % (fader1Feedback))
    json.send({'command':'put', 'key':'D13', 'value':'%i' % (fader1Feedback)})

       

federicofissore

I've just opened an issue on bridge github https://github.com/arduino/YunBridge/issues/4
Anyone willing to code something similar and provide a pull request?

mrk_b

Hi everyone.
I'm working on a project and i would like to implement all the control law and filters in the faster AR9331 microprocessor on a python script rather than in the mcu, but I'm fighting with the issue of the laggy "bridge method" to excange data between the mcu and the linino side.
It would be really a pity if I could not use the powerful microprocessor to do computation just because of the latency in the comunication between the linino side and the atmega.
I tried the advice posted by wpunkts, it enhances the performance respect the built-in "BridgeClient" method, but not enough.
Did someone figure out how to speed up the bridge?
Anyone have some other hints?
Thank you!

federicofissore

Is the delay you're experiencing happening on the mcu or cpu side? If it's the mcu, take a look at this http://forum.arduino.cc//index.php?topic=192823.msg1448287#msg1448287

mrk_b

Thank you Federico for answered me.
Yes, i think the delay that i'm experiencing is on the mcu side.
I'm looking at your suggestion, isn't it related to the REST call?
Does it works even if I wanna use directily the bridge acces trough a Python script?
Sorry I'm a little bit confused about REST call (via browser?) and the lets say "normal use" of the bridge (bridge.get, bridge.put).
Thank you!

federicofissore

My suggestion is related to the use of YunClient and YunServer. Bridge.get and put are not affected

Go Up