Display Pushbutton States

Now that we have a way for the page to make the browser ask the Propeller questions, let's make the page ask for sensor states.  In this example, the page makes the browser ask the Propeller about pushbutton states every 3 seconds and updates the states of radio buttons and text displaying the button states.  

  • Build the pushbutton circuit shown here.
  • Go to Check Pushbuttons and follow the instructions for testing the circuit, and come back here when you're done.

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 page-displays-buttons.html to your Wi-Fi module.
  • In your web browser, open 192.168.4.1/files/page-displays buttons.html.
  • Open Page Displays Buttons Host.side with SimpleIDE.
  • Click the web page’s refresh button.
  • Verify that it displays Value: 00 while no buttons are pressed (for at least 2 seconds).
  • Press and hold the P3 pushbutton on your Activity Board and wait for more than 2 seconds.
  • Verify that the page displays Value: 01 and the P3 radio button has a solid dot inside it.
  • Repeat this test for P4, and then for P3 and P4 at the same time.

 

Try This - Reduce the Sample Interval

To really speed things up, we’ll use WebSockets, but that’s in a later activity.  For the time being, we can speed it up a little without risking data loss due to unpredictable times it takes for HTTP requests to complete.    

  • Open page-displays-buttons.html with a text editor.
  • Change the 2000 to 1500 in this line : var myTimer = setInterval(getFromMcu, 2000).
  • Save the modified file and re-upload it to the Wi-Fi module.
  • Refresh 192.168.4.1/files/page-displays-buttons.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 - HTML & JavaScript

The HTML part of the page is just a couple of radio buttons.  You might have seen radio buttons from online quizzes and questionnaires.  You normally click them to select your answer or reply.  In this example, the JavaScript updates their selected/not selected states according to whether the BASIC Stamp sends a 1 (pressed) or 0 (not pressed) for a given pushbutton.  As with other elements, the radio buttons have IDs so that the JavaScript can act on one when a given button is pressed on the Propeller Activity Board.

  <body>

    <H2>Pushbutton States</H2>

    <p>P4: <input type="radio" id="P4"></p>
    <p>P3: <input type="radio" id="P3"></p>

    <p id="value">Waiting...</p>

    <script>

The var myTimer = setInterval(getFromMcu, 2000) is one way to tell a web page to repeatedly call a function.  There’s a lot more to this than meets the eye, but for now, just remember that this line causes the browser to automatically call the getFromMCU function every 2 seconds (2000 ms).  

      var myTimer = setInterval(getFromMcu, 2000);

The getFromMcu function, which now gets called every 2 seconds, calls the httpGet function.  Remember from the How it Works section in Page Requests Info from Propeller that the Propeller’s C program has code that detects when a GET request comes through with a path of “/tpfm” (to page from microcontroller).  Remember also that the GET request will take an unknown amount of time and is designed to take care of that in the background while the main thread moves on, and that its second argument is the function to call when it’s done.    

      function getFromMcu()
      {
        httpGet("/btns", useMcuReply);
      }

This is the httpGet function, which sends the GET request and then eventually reaches a readyState of 4 and calls the callback function, which in your program is useMcuReply.  For more info on how this works, revisit the Page Requests Info from Propeller activity’s Advanced Topic section. 

      function httpGet(path, callback)
      {
        var req = new XMLHttpRequest();
        req.open("GET", path, true);
        req.onreadystatechange = function()
        {
          if (req.readyState == 4)
            if(req.status == 200)
              callback(req.responseText);
            else
              callback("Waiting...");
        }
        req.send(null);
      }

The useMcuReply function is the one that gets called when the httpGet request is done and is really the only function that has changed since Page Requests Info from Propeller.  The response parameter is going to contain a reply from the Propeller, which is running Page Displays Buttons Host.c.  That program replies with a string that contains the characters representing two binary digits.  The four different strings that might come across are “11”, “10”, “01”, and “00”.  The left digit is 1 if the P4 pushbutton is pressed, or 0 if it’s not.  Likewise, the right digit is 1 if the P3 pushbutton is pressed, and 0 if it’s not.  Keep in mind that’s what response contains.  

      function useMcuReply(response)
      {
        var val = document.getElementById("value");
        val.innerHTML = "Value: " + response;

        if(response.charAt(1) == "1")
          P3.checked = true;
        else
          P3.checked = false;
        if(response.charAt(0) == "1")
          P4.checked = true;
        else
          P4.checked = false;
      }

The first thing useMcuReply does is change the HTML paragraph with the value ID to something like Value = 01.  (That would be if the P3 button is pressed and held down.)  The two lines that do that are var val = document.getElementById(“value”); and val.innerHTML = “Value: “ + response.  Assuming the response contained “01” that would cause Value = 01 to be displayed.

Next, a couple of if...else statements set the states of the radio buttons.  In the case of “01”, the response.charAt(0) gets the leftmost 0th character from the string.  Since it’s a “0”, the code sets the radio button with the P4 ID to false (unchecked or un-selected).  The second if condition is true since charAt(1), which is the second character in the string, really is “1”.  So it sets the checked property in the radio button object with the P3 ID to true, causing it to appear to be checked or selected.

 

How it Works - The Propeller C Code

The setup in Page Displays Buttons Host.c is very similar to Val from Micro Host.c from the Page Requests Info from Propeller tutorial.  When an HTTP GET request comes through requesting the resource from the “/btns” path, the wifi_poll function stores a value in the id variable that matches getsId.  When those two conditions are true, the buttonP4 and buttonP3 variables get values from input function calls that return 1 if a button is pressed or 0 if it is not.  Then, wifi_print(GET, handle, "%d%d\r", buttonP4, buttonP3) sends a string with the characters that represent the two binary states followed by a carriage return.  The first %d the will be "1" if buttonP4 is 1, or "0" if buttonP4 is 0.  The second %d will also be a "1" if buttonP3 is 1, or a "0" if buttonP3 is 0.  The result again is "11\r", "10\r", "01\r", or "00\r".  The Propeller transmits that to the Wi-Fi module, which relays it to the browser executing the JavaScript.  

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

int event, id, handle;
int buttonId;
int buttonP3, buttonP4;

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

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

  while(1)
  {
    wifi_poll(&event, &id, &handle);
    print("event = %c, id = %d, handle = %d\r", event, id, handle);
    if(event == 'G')
    {
      if(id == buttonId)
      {
        buttonP4 = input(4);
        buttonP3 = input(3);
        wifi_print(GET, handle, "%d%d\r", buttonP4, buttonP3);
        print("Incoming GET request, sending %d%d\r", buttonP3, buttonP4);
      }        
    }
    pause(500);
  }    
}