Lack of documentation for Bridge class, esp Bridge.Get

Hello all.

I've been working with the Bridge class a lot lately, it's really handy and very powerful. Thanks Yun team!

However; there is a surprising lack of documentation about many of the functions within the Bridge class. Bridge.put is the only function which has an example. I spent nearly an hour figuring out that Bridge.get only accepts character arrays and literals as key parameters (which seems very silly to me, why not string consts? or even string variables?) and I haven't even touched Bridge.transfer, and wouldn't know where to start.

With the functionality being so high, I seems like a little more documentation might be in order.

Those are just my thoughts - all in all the Yun is such a sweet device, I'm so glad I get to play with it. I would only hope that future users might not have to struggle with some of its quirks. Online resources also help keep forum questions low! :wink:

Respect and regards,
-kiobod

P.S. - If I'm totally off base and there's resources beyond http://arduino.cc/en/Reference/YunBridgeLibrary then I sincerely apologize. That's all I was able to find.

EDIT: Additionally, I thought I had solved the problem but probably haven't. I'm trying to dynamically alter the key for a Bridge.get call (within a function that gets passed a struct containing the (const) key). Any thoughts on how best to do that?

Honestly, I am not quite sure what your actual problems and/or what exactly you are trying to achieve.

As the key needs to be the same on the AVR/sketch side of the bridge and on the Linino side, how do you intend to synchronize that the keys are matching on both sides? :astonished:

It almost seems to me as if you are trying to (ab)use the bridge mechanism not to exchange data between a sketch and corresponding Python/Lua/C(++) script/program on the Linux side, but instead using it as a (temporary) data storage for your sketch....

Ralf

Thanks for the response.

What I'm trying to achieve is a website that communicates with the ATmega via /data/.

I have an HTML page with jQuery to send the proper commands (n.n.n.n/data/get & /put/key/value).
Because /data/ is set up as a JSON string I would've assumed this would be part of the intended use for the Bridge class.

As to your questions:
I want to dynamically set the key value (see code below) because I have a lot of LED's, and I want to be able to write to the Bridge within a function. This function will grab the key (pre)defined in my LED data struct, so that I can simply pass the data struct, without having to write a separate function for each of my LED's.

PCWorxLA:
how do you intend to synchronize that the keys are matching on both sides?

The keys are predefined both in the sketch, and on my website. There isn't any ambiguity for the compiler - I've even tried set the struct value to const.

PCWorxLA:
It almost seems to me as if you are trying to (ab)use the bridge mechanism not to exchange data between a sketch and corresponding Python/Lua/C(++) script/program on the Linux side, but instead using it as a (temporary) data storage for your sketch....

I am not building anything on the linino, I'm only using whatever access automatically ensues when you instantiate the Bridge class. If this is wrong/abusive, I'm sorry. This is where some more documentation about Bridge would be great. All I'm trying to do is create an asynchronous communication between my website and my Yun.

PCWorxLA:
Honestly, I am not quite sure what your actual problems and/or what exactly you are trying to achieve.

My problem is that I can't have any sort of a non-constant within my Bridge.get call. This is very frustrating, and means I probably can't finish the project without running out of memory on the Mega. Here's my sketch:

#include "functEval.h"
#include <Bridge.h>

LEDSTRU pin7 = {true, false, false,
                 true, false, false, false, false,  7
                };
LEDSTRU pin8 = {true, false, false,
                 true, false, false, false, false, 8
                };
LEDSTRU pin9 = {true, false, false,
                 true, false, false, false, false, 9
                };
LEDSTRU pin10 = {true, false, false,
                 true, false, false, false, false, 10
                };
LEDSTRU pin11 = {true, false, false,
                 true, false, false, false, false, 11
                };
LEDSTRU pin12 = {true, false, false,
                 true, false, false, false, false, 12
                };
LEDSTRU pin13 = {true, false, false,
                 true, false, false, false, false, 13
                };            
                
char chBuff[10];
bool BlinkTest = false;

String placeholder;
char notherBuff[6];
void setup() {
  digitalWrite(13, LOW);
  Bridge.begin();
  digitalWrite(13, HIGH);
  pinMode(13, OUTPUT);
}

void loop() {
  
  pin13.AutoCallOn = true;
  checkManual(pin12);
  eval(pin12);
  
}

void checkManual (LEDSTRU& LED) {
  
  placeholder = String(LED.PinNum) + "cmnd";
  placeholder.toCharArray(notherBuff, 6);
  
  Bridge.get(notherBuff, chBuff, 9);
  if (chBuff[0] == 'M') {
    pin13.AutoModeOffReq = true;
  }
  if (chBuff[0] == 'A') {
    pin13.AutoModeOnReq = true;
  }
  
  placeholder = String(LED.PinNum);
  placeholder.toCharArray(notherBuff, 6);
  Bridge.get(notherBuff, chBuff, 9);
  if (chBuff[1] == 'N') {
    pin13.ManCallOn = true;
  }
  if (chBuff[1] == 'F') {
    pin13.ManCallOff = true;
  }
  
  
}

void eval(LEDSTRU& LED) {
  if (LED.AutoModeOnReq == true) { //if input says listen to automatic processes
    LED.AutoManMode = true; //run input from higher logic
    LED.AutoModeOnReq = false; //reset bool so it doesn't get stuck
  }
  if (LED.AutoModeOffReq == true) { //if input says listen to manual
    LED.AutoManMode = false; //run input from manual
    LED.AutoModeOffReq = false; //reset bool
  }

  if (LED.AutoManMode == true) { //if we're running input from auto processes
    if (LED.AutoCallOn == true) { //if auto says turn on
      digitalWrite(LED.PinNum, HIGH); //turn on
      LED.LEDon = true; //record status
      LED.AutoCallOn = false; //reset bool
    }
    if (LED.AutoCallOff == true) { //if auto says turn off
      digitalWrite(LED.PinNum, LOW); //turn off
      LED.LEDon = false; //record status
      LED.AutoCallOff = false; //reset bool
    }
  }

  if (LED.AutoManMode == false) { //if we're listening to manual input
    if (LED.ManCallOn == true) { //if manual input says turn on
      digitalWrite(LED.PinNum, HIGH);//turn on
      LED.LEDon = true; //record status
      LED.ManCallOn = false; //reset bool
    }
    if (LED.ManCallOff == true) {//if manual input says turn off
      digitalWrite(LED.PinNum, LOW); //turn off
      LED.LEDon = false; //record status
      LED.ManCallOff = false; //reset bool
    }
  }
}

This function is the one that is broken.

void checkManual (LEDSTRU& LED) {
  
  placeholder = String(LED.PinNum) + "cmnd";
  placeholder.toCharArray(notherBuff, 6);
  
  Bridge.get(notherBuff, chBuff, 9); //This line and the one below throw exceptions no matter what I put there, excepting a " " literal
//and a char array, but I'm having trouble with the char array
  if (chBuff[0] == 'M') {
    pin13.AutoModeOffReq = true;
  }
  if (chBuff[0] == 'A') {
    pin13.AutoModeOnReq = true;
  }
  
  placeholder = String(LED.PinNum);
  placeholder.toCharArray(notherBuff, 6);
  Bridge.get(notherBuff, chBuff, 9);//This is where I'm having issues, I can't put any value here which isn't a literal 
//or a char array. Why?
//Are there any workarounds?
  if (chBuff[1] == 'N') {
    pin13.ManCallOn = true;
  }
  if (chBuff[1] == 'F') {
    pin13.ManCallOff = true;
  }

I also have a .h folder containing my struct, which is totally legal and has worked in other cases.

Any thoughts?

Again, I need a proxy data table for the ATmega & the website to access because #1 - the mega needs to be able to be running processes separately without the interference of waiting for a client, #2 - it should be accessible from multiples webpages at the same time.

Sorry but I am going to be away from my Yun until Monday, so I can not check on the code pieces you posted.
But this part of you reply

I am not building anything on the linino, I'm only using whatever access automatically ensues when you instantiate the Bridge class. If this is wrong/abusive, I'm sorry. This is where some more documentation about Bridge would be great. All I'm trying to do is create an asynchronous communication between my website and my Yun.

is what I am referring to when I used the term "(ab)use".
It's because you are trying to use the bridge in a way it is not intended/designed to be used. It is a communication tool between a sketch running on the AVR part and a program/script running on the Linux side. The "buffer" where the Bridge library, on either side of this communication, is putting/getting the data is not something that is directly accessible from a web site on the Yun, unless a script/program on the Linux side is accessing it via it's equivalent Bridge library...

Ralf

Thanks again for the responses-

While I don't know how the Bridge is intended to be used exactly (I understand it's more for access by the linino) I can indeed access any information stored through bridge.put by using n.n.n.n/data/get and n.n.n.n/data/put/key/value. I can change the status of pins by altering data from a website.

Additionally, because the data is stored in JSON format, it doesn't seem unreasonable to me to use the data in a website. However, if there are significant issues, I'm willing to move away from this approach. Could I set up a simple python script which would let me achieve the same results?

The issue I was having (and I think I've resolved it, not sure yet) was that I couldn't use Bridge.get dynamically, which regardless if I'm using a website or a script should respond the same way. My issue doesn't have anything to do with what's on the other side of the bridge, once I get there I'm scott free. I was having problems sending data to the other side of the bridge within a for loop, mostly because of data type issues. Again, I believe I've solved the problem although my sketch isn't working perfectly yet.

What I hope to point back to though, is the need for some more documentation about the Bridge class, I think it would be useful to include at least:

  1. the data types each function allows.
  2. limitations of the Bridge.
  3. examples of how to use each function.

If I knew all of these things, I'd be willing to write something up myself. As it stands though, I think the incoming community would appreciate a little more documentation. IMHO.

Regards & respect,
-kiobod

Hope you're having fun this summer!

It isn't entirely clear to me what you want to do, or what the problem is.
I have some pretty simple examples on: Yafa! How to make a fermentation controller using an Arduino Yun.: 6. Bridge stuff

I don't know if it is of any help, but I have built a very small wrapper around the bridge that imho simplifies the bridge communication. I expect it might offer similar functionality as the mailbox, I dont know. If you want to I can share the code, as well as some examples.

opkg update
opkg install php5 php5-cgi
opkg install php5-mod-sockets
opkg install php5-mod-json
nano /etc/config/uhttpd
list interpreter '.php=/usr/bin/php-cgi'
/etc/init.d/uhttpd restart
nano /www/phpinfo.php
<?php

// Show all information, defaults to INFO_ALL
phpinfo();

?>

Using browser http://arduinoip_address/phpinfo.php to confirm php, mod-sockets as well as mod-json is installed.

nano /www/bridge.php
<?php
require ("/usr/lib/php/bridge/bridgeclient.class.php");

$client = new bridgeclient();

$client->put("D12","Test");
$test= $client->get("D13");
echo $test;
?>

Arduino code:

#include <Bridge.h>
void setup()
{
    	Bridge.begin();    
}
void loop()
{
	char lbuffer[256]; 
	Bridge.get("D12", lbuffer, 256); 
     	Bridge.put("D13", String(random(1, 100)));
	delay(1000);	
}

Using browser http://arduinoip_address/bridge.php to test.

$_GET(): input parameter for bridge.php
json_encode() : output json for bridge.php

@NewLine -
Thanks for the link, I've actually found your site before :slight_smile:
I have managed to fix the problem, as I suspected it was a problem with data types. The reason I wasn't seeing expected behavior was because I naively forgot to set my pins to OUTPUT. Yeah, I feel pretty dumb.

Again, my problem had everything to do with the C code within the ATmega, once I got it to send stuff the other end had no problem getting it. The issue is that Bridge.get() only accepts character arrays and literals as parameters for (key). Does anyone know why this is? It seems awful strange to me. I fixed it through a couple of lines of code.

@sonnyyu -
Thank you also for the response. Unfortunately I've been using jQuery for my webpage, and I don't know much about php.
Also I am completely unversed in python. I'll have to do some studying up before I can understand your code. I'm sure it's great, I just don't know what is it yet :slight_smile:

Additionally, you've noted in previous posts that your first language isn't English (sorry to pry). With a username like sonnyyu, I'm curious what your native language is. I'm a language student and I'm studying Mandarin and Spanish right now. Obviously it's the internet so no problem if you don't want to share personal information.

@yun mods and website managers -
What I hoped to point out with this thread is the need for more online documentation for some of the built-in (and totally awesome) functions of the Arduino Yun. The amount of documentation doesn't line up with the functionality and complexity of these functions, especially for a hobby level device. I'm not trying to tell you what decision you should make, only pointing out a need which can be met.

Hope you're all enjoying your summer! (or winter, or dry/wet season!)

-kiobod

Here's the code I built, in case anyone's interested.

It runs a simple on/off blink with seven lights, and you can grab any one of those lights away from the on/off procedure and manually change their state. They only update every second though, currently looking into running a timer so that everything can be pseudo real-time, but I haven't found anything that works with the Yun yet.

I've also built a website so I don't have to manually input n.n.n.n/data/put/key/value. If you wanted to make pin13 manual, you'd use n.n.n.n/data/put/13cmd/MAN. To turn it on you'd use /data/put/13/ON, and /data/put/13/OFF would turn it off.

#include "functEval.h"
#include <Bridge.h>
//These are my LED structs, they contain bools signifying the status they should be in, and an int for their pin number
LEDSTRU pin7 = {true, false, false,
                 true, false, false, false, false,  7
                };
LEDSTRU pin8 = {true, false, false,
                 true, false, false, false, false, 8
                };
LEDSTRU pin9 = {true, false, false,
                 true, false, false, false, false, 9
                };
LEDSTRU pin10 = {true, false, false,
                 true, false, false, false, false, 10
                };
LEDSTRU pin11 = {true, false, false,
                 true, false, false, false, false, 11
                };
LEDSTRU pin12 = {true, false, false,
                 true, false, false, false, false, 12
                };
LEDSTRU pin13 = {true, false, false,
                 true, false, false, false, false, 13
                };            
               
bool autoBool = true; //this determines on or off for the lights
char chBuff[10]; //buffer 
String placeholder; //string placeholder to convert to char array
char fiveBuff[7]; //buffer of the correct size for numcmd
char twoBuff[4]; //buffer of the correct size for num
void setup() {
  
  Bridge.begin();
 
 
 
 pinMode(7, OUTPUT); //write those pins!
 pinMode(8, OUTPUT);
 pinMode(9, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(13, OUTPUT);
}

void loop() {
  
  if(autoBool == true){ //turn lights of if off
    pin7.AutoCallOn = true;
     pin8.AutoCallOn = true;
      pin9.AutoCallOn = true;
       pin10.AutoCallOn = true;
        pin11.AutoCallOn = true;
         pin12.AutoCallOn = true;
          pin13.AutoCallOn = true;
          autoBool = false;
    
    
  }
  else{ //turn lights off if on
     pin7.AutoCallOff = true;
     pin8.AutoCallOff = true;
     pin9.AutoCallOff = true;
     pin10.AutoCallOff = true;
     pin11.AutoCallOff = true;
     pin12.AutoCallOff = true;
     pin13.AutoCallOff = true;
     autoBool = true;
    
  }
  
  checkManual(pin7);//check status requests for each pin
  checkManual(pin8);
  checkManual(pin9);
  checkManual(pin10);
  checkManual(pin11);
  checkManual(pin12);
  checkManual(pin13);
    
  eval(pin7); //logic for turning pins on/off depending on manual/auto and subsequent on/off
  eval(pin8);
  eval(pin9);
  eval(pin10);
  eval(pin11);
  eval(pin12);
  eval(pin13);
  delay(1000); //delay so you can see the blink, working on using a timer. Anyone know how?
  
}
  


void checkManual (LEDSTRU &LED) { //gets passed an LED struct
  
  placeholder = String(LED.PinNum) + "cmd"; //here
  placeholder.toCharArray(fiveBuff, 6); //and here were where I had to modify data type
  

  Bridge.get(fiveBuff, chBuff, 6);
  if (chBuff[0] == 'M') { //if manual
   LED.AutoModeOffReq = true; //request manual on
  }
  if (chBuff[0] == 'A') { //if auto
    LED.AutoModeOnReq = true; //request auto on
  }
  
  placeholder = String(LED.PinNum); //same here as above
  placeholder.toCharArray(twoBuff, 3); // this is where my problem was
  
  Bridge.get(twoBuff, chBuff, 3);
  if (chBuff[1] == 'N') { //if on
    LED.ManCallOn = true; // set manual call on
  }
  if (chBuff[1] == 'F') { //if off
    LED.ManCallOff = true;//set manual call off
  }
  
  
}

void eval(LEDSTRU &LED) {
  if (LED.AutoModeOnReq == true) { //if input says listen to automatic processes
    LED.AutoManMode = true; //run input from higher logic
    LED.AutoModeOnReq = false; //reset bool so it doesn't get stuck
  }
  if (LED.AutoModeOffReq == true) { //if input says listen to manual
    LED.AutoManMode = false; //run input from manual
    LED.AutoModeOffReq = false; //reset bool
  }

  if (LED.AutoManMode == true) { //if we're running input from auto processes
    if (LED.AutoCallOn == true) { //if auto says turn on
      digitalWrite(LED.PinNum, HIGH); //turn on
      LED.LEDon = true; //record status
      LED.AutoCallOn = false; //reset bool
    }
    if (LED.AutoCallOff == true) { //if auto says turn off
      digitalWrite(LED.PinNum, LOW); //turn off
      LED.LEDon = false; //record status
      LED.AutoCallOff = false; //reset bool
    }
  }

  if (LED.AutoManMode == false) { //if we're listening to manual input
    if (LED.ManCallOn == true) { //if manual input says turn on
      digitalWrite(LED.PinNum, HIGH);//turn on
      LED.LEDon = true; //record status
      LED.ManCallOn = false; //reset bool
    }
    if (LED.ManCallOff == true) {//if manual input says turn off
      digitalWrite(LED.PinNum, LOW); //turn off
      LED.LEDon = false; //record status
      LED.ManCallOff = false; //reset bool
    }
  }
}

It's hack-y. Haven't gone through and placed everything in arrays yet, but that should simplify the code.

If anyone knows of any good online resources for learning how to use the linino, I'd be much obliged. I think I'll be needing to set up an additional non-volatile memory location so that I can maintain user input after a power cycle.

I.E. I'll need to write from the volatile /data/ storage to a permanent file whenever a /put/ arrives from a user, not from the mega because I'll need to conserve power consumption/usage. Don't want to burn out the Yun.

Anyone know how to do that? Willing to point me in the right direction? I don't know if I should be writing in python or C, I'd preferably work in C++ but I'm not sure if that's an option.

Thank you all for responding!

-kiobod

I simply write the last user settings to the sd card. I think that is also the only option if you want to store it on the Yun.
Do not store it on the Yun flash because it has a limited number of writes.

Linino is no longer used for the latest image. It is now an openwrt branch. So you can google on openwrt.

Standard there is no c (++) compiler on the Yun, so I would advice using python.

Note: the following 2 things are great 'upgrades' if you want to do things with the Yun:

  • move to the latest image
  • 'move' the openwrt from flash to the sd card (more space for packages and not wearing out the flash)

Note: also the sd has a Ltd number of writes, but I have no idea how quickly this can become a problem. Myself, I write all files that I don't need to maintain over a power cycle to Ramdisk. Only the user settings I store on the Sd.

NewLine:
Note: also the sd has a Ltd number of writes, but I have no idea how quickly this can become a problem. Myself, I write all files that I don't need to maintain over a power cycle to Ramdisk. Only the user settings I store on the Sd.

Indeed. I've once read a pdf (from samsung I think, but I can't find the link any more) saying that modern sd cards behave like SSD. They do wear leveling: in order to evenly consume the SD, they store the number of writes made on each block in a specific part of the SD (that is made to be written much more often than the rest). This way the SD card can distribute writes throughout all blocks

Thanks for the responses folks -

Sorry for the noobity - just to clarify I have openwrt on my machine right now.

As far as non-volatile goes, I've seen the documentation for file I/O, so I'm assuming I can figure that out (sketch write/read with file). How about accessing that same data file from my webpage? Is it stored off of /sd/"filename"/? Or just /"filename"/?

Also, I think the openwrt is on the sd card - mostly because I can't do anything to that SD card now, I'm using a USB drive to store any other extra stuff. I'm a hack, I know, I'm sorry.

Additionally, I would've thought constantly writing to non-volatile would've been a huge drain on the system. Is that not true?
And pardon my ignorance, but how would my USB fare vs the Yun?

Is there a better solution to the system I'm trying to set up? One that might not hinge on the number of writes any one device can handle?

I didn't realize there were issues with what I've set up. Thank you for enlightening me.

I will say this though, the code that I've posted has been working fine for over 24 hours (writing to yun 7 times every second). What is the threshold of the yun's writes? Is it improved because I'm on the sd? (maybe?)

Thank you NewLine & Federico for talking this through with me.

-kiobod

sonnyyu always got a solution! :slight_smile: