YUN POST HANG UP

Hello,

USING : Arduino YUN Firmware 1.5.3, Browser: Google CHROME, USING WAMP 2.5 for Apache Web Server, MY SQL and PHP.

Arduino Project Sketch
Reads sensors using Analog Read, SPI, Interrupts.
Data is printed into a String.
Using BridgeClient POSTs are made to PHP/HTML page.
This is looped on one second intervals.

MySQL table shows timestamped posts every 3 or 4 seconds.

So there appears to be a lag between the Arduino Sketch Looping interval and the actual Posting. I am not crazy about the lag but I can live with it.

The Problem is that after so many posts( ~200) the posts stop and the sketch will not reconnect to server. Resets will not correct the problem but power cycling of the YUN does.

I am trying to figure out why the connection drops and why it wont reconnect.

The Polling of the sensors needs to happen every second to not miss any data.

I am attaching my Sketch and the PHP side that receives the posts.

This is all on a local network.

Water_Meter_Web.ino (2.15 KB)

Hello sm09la,

I do not use BridgeClient client, but the following setup and I can maken easy 1 entry per second in a mysql DB on another server.

My setup: arduino yun using curl - internal lan - webserver with restfull api

#include <Process.h>

void setup(void) {
  Bridge.begin();
}


void loop(void) {
  String curlCmd;

  String resultConcentration;
  String resultTemperature;

  
  resultConcentration=5.5;
  resultTemperature=20.0;
  
  curlCmd = "curl -H \"Content-Type: application/json\" -X POST -d \'{\"concentration\": "+resultConcentration+", \"temperature\": "+resultTemperature+"}\' http://192.168.x.xx:8080/measurement";

  Process database;
  database.runShellCommand(curlCmd);
  delay(1000);
}

I'm using nodejs on the webserver. So it makes no sense to upload the js file for you as you are developing in php. With curl you can also do a post towards your php script.

Good luck!

Excellent. Many Thanks.

For completeness and to show this all works, the Syntax for the curl command to post a string (not a JSON) to php is:

String curlCmd = "curl --data "yourdata="+variable+"" http://192.168.X.XX:8081/yourfile.php";

Process database;
database.runShellCommand(curlCmd);
database.close();

This is combination of both my and Feedbacks projects.

Thank you again Feedback. I am posting with the 1 second frequency and it has not dropped out or hung up yet. Although in my searches for the above curl syntax, I found this Yun CURL command fails to work after a while - Arduino Yún - Arduino Forum where it seems memory leak issues occur after awhile even with the curl commands. The main poster of the thread has very similar issues as I had where only a full power cycling cures the issue. I did both resets individually (YUN and 32U4) as ShapeShifter and Jesse allude to.

If I notice more issues I will POST them here.

sm09la:
The Problem is that after so many posts( ~200) the posts stop and the sketch will not reconnect to server.

I'll bet the problem happens right at 256 connections.

I didn't study your code in depth, but at the top of loop(), you process incoming client connections: if you have a connection, you process it, and then call client.stop(). This is good, because without it I've seen the Yun stop responding to incoming connections at connection 256. I guess some resources are not being freed up.

Then, loop() goes on to make an outgoing client connection. But there you don't call client.stop(). I think it is required for an outgoing connection, just like an incoming connection. You likely need to wait for a response, make sure the connection is done, and then call client.stop().

Also, it looks curious that if the client doesn't make the outgoing connection, the else clause attempts to make the same connection again, but then doesn't check the result of the connection, nor does it do anything with the connection. What are you trying to do here?

Resets will not correct the problem but power cycling of the YUN does.

Resets of what? Just the '32U4? I believe the problem is on the Linux side, so it doesn't surprise me that resetting the sketch has no effect. I think a Linux reboot is required (either by using the reboot command, or cycling power.)

Feedback:
My setup: arduino yun using curl

This is a very good suggestion and is the way I would recommend doing it.

The curl command in Linux is faster and more powerful that anything you can write in the sketch. My general feeling is that a good Yun system design is to do as much as possible on the Linux side, and use the sketch side as a minimalist I/O controller, passing data to/from the Linux side.

Plan B:

Bypass Apache and PHP at WAMP, directly access Mysql server.

Python & MySQL for Process Class

http://www.ibuyopenwrt.com/index.php/2-uncategorised/206-python-mysql-for-process-class

PHP & MySQL for Process Class

http://www.ibuyopenwrt.com/index.php/2-uncategorised/205-php-mysql-for-process-class

Lua and Mysql

http://www.ibuyopenwrt.com/index.php/8-yun-compatible/44-lua-and-mysql

C and Mysql

http://www.ibuyopenwrt.com/index.php/16-yun-compatible/openwrt-sdk-yun/42-mysql-c-example

Shell script and Mysql

http://www.ibuyopenwrt.com/index.php/8-yun-compatible/47-shell-script-and-mysql

Hello all,

Update.

@Shapeshifter- The "else" clause I was trying to reestablish a connection in case there was not one. As a result of not closing the connection, I assumed the following loop iteration the connection would still be opened.
-I have removed all this business of connecting with the client and instead I am doing the Process curl cmd option and havent had any issues.

  • With the client.connect(server) option the amount of posts varied and did not necessarily lock up right at 256, sometimes it was less, sometimes more.
  • I was resetting both the 32U4 and the YUN side. Also, I toggled the wifi reset as a last ditch effort to see if I could get something. The only cure was the Power Cycling of the whole board.
    I could try using the same code as I uploaded above and try doing the client.close() in order to make sure it closes each time but the lag was a real drag. (No pun intended). Like you have suggested the passing of info to the Linux side is far superior.

@sonnyyu
I really appreciate the other options. I will take the time to investigate all of them.

Thank all of you for your help.
As of right now everything is working as I would like, which is not to say it is the best.

sm09la:
@Shapeshifter- The "else" clause I was trying to reestablish a connection in case there was not one. As a result of not closing the connection, I assumed the following loop iteration the connection would still be opened.

Of course, this is a moot point since you are not doing it this way any more, and you are using a better method. But for the sake of learning, both for yourself and anyone else that may see this topic in the future, it's worth analyzing this. Not just for this particular problem, but as a general approach for figuring out future problems with other code. This is an object lifespan and reuse issue, and not specific to BridgeClient objects.

If the client object were defined inside the loop() function, then the client object would not stay open for the next iteration, because it would be destroyed at the end of the function when the client object goes out of scope. In that case, it would be constructed again at the top of the loop (assuming that the call to the constructor was at the top of the loop along with the object declaration.)

But the client object is declared and constructed outside of the loop() function, so it would indeed still be valid and potentially open at the top of the next loop() iteration. However, the first thing you do at the top of the loop is call server.accept() and assign the result to the client object. That call to server.accept() returns a new client object, which may or may not have a valid connection (most of the time it will NOT be connected, it will only be connected to the server if the server had just accepted an incoming connection.) Either way, the existing client object, which may have been connected from the previous loop iteration, is lost and overwritten by the new client object. If that overwritten client was open at the time, it will not have been properly closed, resulting in resource leakage, and eventually causing a failure to make connections or a crash of the system.

Now, if the server.accept() call returned a connected client, you process that connection, and then clean up the client by calling client.stop. This is just as it should be.

Later on in loop() you then tell the client object to connect to the server. This is no longer the client object that was around at the end of the prior loop, it is a new one that was assigned from the server.accept() call. That client may have had a connection and been stopped in the earlier code (no problem) or it could've been an unconnected client if there was no pending connection (still not a problem.) So it's valid to try and make a connection, and at the same time it really doesn't matter whether that prior object was still connected - it's gone, and your code doesn't try to reuse that open connection, it unconditionally attempts a new connection.

If you really want to try and re-use a connection that is active from a previous loop, you need to do a few things:

  • Use two client objects so that one can be used for incoming connections without stomping on the outgoing connection
  • Check whether the existing client object is connected (and make use of that connection) before attempting to open a new connection.
  • Instead of using the "Connection: close" header, which may cause the remote server to unilaterally close the connection when done, use the "Connection: keep-alive" header to ask the remote server to keep the connection open and look for another incoming request.
  • And you will probably also have to read (and discard?) the incoming data from the client or else the internal buffers may fill up and not be able to accept any more data from the server.

Yes, taking all of this into account, it's definitely easier to just call the Linux curl command! 8)