Page Requests Info from Propeller

Up to this point, your page has been sending information to the microcontroller host with HTTP POST requests.  There’s also a way for the page to ask the microcontroller for information with HTTP GET requests.  Here is an example where each time you click the Update button, the JavaScript in the page makes the browser ask for, get, and display a new value from the Propeller.

Reminder: If you followed the instructions in the Join Another Wi-Fi Network section, you’ll have to replace 192.168.4.1 with your IP address.

  • Go to your Wi-Fi module’s Files page at http://192.168.4.1/update-ffs.html.
  • Use the Choose file button to upload val-from-micro.html to your Wi-Fi module.
  • In your web browser, open 192.168.4.1/files/val-from-micro.html.
  • Use SimpleIDE to open Val from Micro Host.bs2.
  • Run Val from Micro Host.bs2.
  • Click the web page’s update button and check the number by value.
  • Wait a few seconds and click Update again.  

Since the Propeller C program counts upwards at several times per second, the number should be higher each time you click the button.

 

Try This - Automatic

Don’t want to have to click the button to see the value updated?  The page can do it automatically.  Here’s an example that updates every 3 seconds.

  • Add this line line to the JavaScript: var myTimer = setInterval(getFromMcu, 3000).
  • Upload the modified page to the Wi-Fi module
  • Refresh 192.168.4.1/files/val-from-micro.html in your browser.

Note: it’s probably not a good idea to try to see how fast you can make this go, because it can end up making the application unresponsive.  We have WebSockets (introduced soon) to establish a communication line that’s much more streamlined than HTTP requests.

 

How it Works

The HTML has a button with an onclick event to call a function in the JavaScript called getFromMCU.  The JavaScript updates the paragraph with the value ID as soon as it gets the reply from the microcontroller.

Using this JavaScript is pretty easy.  In getFromMcu, you give it the path, “/tpfm” in this case, which is an abbreviation of “to page from microcontroller."  The reply from the Propeller will appear inside the response parameter of useMcuReply(response) when it’s ready.  The “when it’s ready” part depends on network traffic and also how long the Propeller takes to get around to answering.  For more info on how this code works, there’s an Advanced Topic after an explanation of the Propeller C code.

Keep this in mind: The path name you choose for the GET request has to be the same as the listener the Propeller C code sets up. 

The declarations and initializations are about the same as they were with the HTTP POST examples.  The getFromPageId variable is unique, and val is a counting variable that stores values that will be sent to the browser every time the button is clicked.  After wifi_start, the getFromPageId = wifi_listen(HTTP, "/tpfm") call sets up an HTTP listener.  Since POST and GET requests are both part of the same (HTTP) protocol, the same type of listener will hold either POST or GET requests with the listener's path. 

#include "simpletools.h"
#include "wifi.h"

int event, id, handle;
int getFromPageId;
int val;

int main()
{
  wifi_start(31, 30, 115200, WX_ALL_COM);

  getFromPageId = wifi_listen(HTTP, "/tpfm");
  print("getFromPageId = %d\n", getFromPageId);

Inside the main loop, the code adds 1 to a variable named val every 1/2 second.  Like all the examples to this point, the main loop also calls the wifi_poll function.  Instead of checking for a 'P' (for POST request) in the event variable, this loop checks for a 'G' (for GET request).  When event stores 'G' and id matches getFromPageId, it's time to respond to the GET request.  Just as wifi_scan loads data from a POST request it receives into variables, wifi_print assembles variable values into a string of characters and sends it to the browser as a response string.  In wifi_print(GET, handle, "%d", val), note that there's no name before "d".  It's not necessary to respond with a name=value pair, the JavaScript code is only looking for the value. 

  while(1)
  {
    val++;
    wifi_poll(&event, &id, &handle);
    print("event = %c, id = %d, handle = %d\r", event, id, handle);
    if(event == 'G')
    {
      if(id == getFromPageId)
      {
        print("Incoming GET request, sending %d\r", val);
        wifi_print(GET, handle, "%d", val);
      }        
    }
    pause(500);
  }    
}

 

Advanced Topic: What’s Really Happening in That JavaScript?

The true inside req.open(“GET, path, true) means that the request will get processed asynchronously.  Processing asynchronously means that the the httpGet function won’t wait till everything is ready because other parts of the page and/or JavaScript might need attention in the meantime.  In other words, asynchronous processing is what prevents web pages from becoming unresponsive.  The main thread actually executes everything inside the httpGet function right away and returns.  However, after the httpGet function is done, req.onreadystatechange contains a function that gets run each time the readyState property advances through its five states.

According to AJAX - The onreadystatechange Event, the readyState property advances through five states: (0) request not yet initialized, (1) server connection established, (2) request received, (3) processing request, (4) request finished and response ready.  There’s also a status property that’s 200 for “OK” or 404 for “page not found”. 

The important thing to keep in mind is that each time the readyState changes, the function inside onreadystatechange automatically executes, checking if readyState has reached state 4 and a status of 200.  When both of those are true, the response is ready.

When the response IS finally ready, the callback parameter contains useMcuReply.  That’s the function the httpGet(“/tpfm”, useMcuReply) passed when it called httpGet, with the understanding that it would “call back” that usMcuReply function at some later time (when readyState is 4 and status is 200).  At that point, callback(req.responseText) becomes useMcuReply(req.responseText)

If the Propeller's response was “42”, that’s what req.responseText will contain, and also what gets passed to the useMcuReply function’s response parameter.  Inside useMcuReply, there’s JavaScript that would display “Value: 42” in the paragraph with the value label.