Braduenyo
Braduenyo

Reputation: 11

Serial Push to Server Sent Script

I have a LAMP web server with a Python script continuously monitoring a serial port for incoming data. This is part of a home automation system (with Arduino Yun and a bunch of Pro Minis each with nrf24L01+ RF transceivers).

My goals are to:

  1. Save the incoming data to MySQL in the appropriate location, like 'door open' or 'temp = 72F'. I believe the Python script can handle this.
  2. Use Server Sent Events (SSE) to push new data to a client browser (when a client is connected).

I realize I could use AJAX, but pushing the data seems better than polling. The wrinkle is that I somehow have to get the SSE bound data from the python script over to PHP, but only when the SSE PHP script is running. Also, I believe a new instance of the SSE PHP script is created with each client - so there won't even be a 1:1 ratio of python to PHP. I thought about having the SSE PHP monitor the MySQL database, but that is essentially back to polling, albeit likely very high frequency polling.

Alternatively, I was thinking that the SSE PHP script could monitor the serial port, but I think the serial data can only be read once, so multiple scripts would be competing for the data, which would not work either.

What is the best way to achieve these two goals of saving the incoming data to my datase and using SSE as a transport layer?

Upvotes: 0

Views: 334

Answers (2)

Braduenyo
Braduenyo

Reputation: 11

So here is what I ended up doing:

  • Python daemon runs on Arduino Yun monitoring ttyATH0 serial port for new data. When a new string is received (I choose to terminate strings with a ~ character), it parses it and stores it to a MySQL database. The update of a MySQL entry automatically updates the time stamp on that row. This is a configuration of the table.
  • Loading the html page starts a browser subscription to the server sent events from a .php script running on the server
  • The script searches the MySQL database for entries newer than a couple seconds old and passes a JSON to the webpage which is parsed by javascript to animate the page.

I decided that the 3 second refresh time of the Server Sent script was sufficient for my needs. It could in theory run continuously, but it would likely flood the webpage and reduce performance. The script could also be configured to run every 1 second - perhaps I'll make that update someday.

...Anyways, that's how I did it, no websockets required! I also think it is more elegant than a hanging AJAX query.

Upvotes: 1

Adam Link
Adam Link

Reputation: 2793

From what I understand about SSE, the issue here is having the long running PHP script pick up on the changes that the Python script will enter into the database.

Let's assume that your Python script is properly adding data to the MySQL database.

Then your PHP script would simply pick up the data and send it via SSE. You'd want a long-running script, but you'll also want to look into the timeout period for your PHP scripts using set_time_limit() as defined on php.net.

I'd try something like this:

$link = mysqli_connect("myhost","myuser","mypassw","mybd");

$number_of_times = 1;
/*
 * Ideally figure out how many times you want to query per consistent
 * connection, knowing that your script will eventually time out and
 * that EventSource will reconnect within 3 seconds
 */

for ($i=0;$i<$number_of_times;$i++) {
    $query = "SELECT name FROM mytable" or die("Error in query: " . mysqli_error($link)); 
    $result = $link->query($query); 

    while($row = mysqli_fetch_array($result)) { 
      // echo your SSE data here
    } 
}

Your concern is not that the ratio isn't 1:1 for your scripts, since the webpage that uses EventSource will connect to the PHP script and the Python script is monitoring a different source for incoming data and writing that to the shared DB that both scripts will utilize.

Also, read up on the limits for EventSource

Upvotes: 0

Related Questions