Question

I have a question that ultimately (hopefully?) comes down to JS, but since I'm working on an Arduino Yún, I think it might be best to show that side of the problem so as to not leave anything out. Those willing to read my completely unentertaining explanation of something that doesn't really have much to do with the problem at hand, feel free to do so. Everybody else, follow me! +skips to JS Problem+

Yún side

Here's the deal: I want to change the css properties of a webpage hosted on the Yún based on some switches connecting PIN2 and PIN3 to GND.

I used the Bridge example as a basis to my code on the Arduino side of the thing, and I believe that's set up as it should be:

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
//variable constante que guarda la cantidad de puertas

#define CANT_PUERTAS 2

//variable tipo array que guarda los estados de las diferentes puertas
int estado[CANT_PUERTAS];

YunServer server;

void setup() {
  Serial.begin(9600);

  // Bridge startup
  Bridge.begin();

  //Pines que van a monitorear las puertas
  pinMode(2, INPUT_PULLUP);
  pinMode(3, INPUT_PULLUP);

  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  //hacer poll de estado de puertas
  pollPuertas(estado, CANT_PUERTAS);

  YunClient client = server.accept();

  if (client) {
    process(client);
    client.stop();
  }

  delay(50); 
}

...with

void pollPuertas(int estado[], int arraySize) {
  for (int i = 0; i < arraySize; i++) {
        estado[i] = digitalRead(2 + i);
  }
}

...and

void process(YunClient client) {
  String command = client.readStringUntil('/');
  if (command == "estado") {
    int puerta = client.parseInt();
    client.print(estado[puerta]);
  }
}

So, the basic idea behind the code is as follows: CANT_PUERTAS is the amount of PINs I want to monitor, and estado[] is an array where I will save the values of those pins.

Function pollPuertas is a simple for loop that reads the states of the PINs (in my case, I'm reserving PIN0 and PIN1 for future communication, so I start with PIN2) and saves those states to estado[].

Function process handles the REST calls. My calls are organized like this COMMAND/NUMBER, although I only mean to use one command right now. So, if my command is "estado", I simply use the NUMBER as the index of my array and print the value of that PIN to the client.

There are no issues with this code. If I access arduinoyun.local/arduino/estado/NUMBER, I get the expected results:

  • a 1 for an open switch, or
  • a 0 for a closed switch.

The JS Problem

Still with me? wow. Thanks :D.

For those who didn't read the previous part, here is a really simple review:

  • I have two switches (as in light switches, not networking switches) I am monitoring.
  • I've set up two "webpages" (one for each switch) whose contents change according to whether or not the switches are closed. These are hosted on the local network.
  • The content of the "webpages" is either a 1 or a 0. ASCII. No HTML headers or anything, which is why I call them "webpages".

Now comes the actual problem. I'm pretty new to HTML, JS, and JQuery so please bear with me.

I want to host a simple website on the Arduino Yún, whose CSS properties change according to the status of the switches. My idea was to write a script that would use an if conditional to evaluate how to change these properties. This script would be called on periodically so that the website reflects the changes in the switches' states in "real-time".

Here's my attempt at this:

<!DOCTYPE html>
<html>

  <head>
    <title>Poll de Puertas</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-latest.js">    </script>
<!--    <script type="text/javascript"     src="https://code.angularjs.org/1.2.9/angular.js"></script>-->

    <script type="text/javascript">        
        function cambiarColor(){
        //  if($http.get("arduinoyun.local/arduino/estado/1") === 0){
            if(1==0){
                $('p:nth-child(1)').css('color','green');
            } else{
                $('p:nth-child(1)').css('color','red');
            }

            $('p:nth-child(2)').css('color','blue');
        }
    </script>

  </head>
    <body onload ="setInterval(cambiarColor,3000);">
    <p id="puerta1">Puerta 1</p>
    <p id="puerta2">Puerta 2</p>
  </body>

</html>

In the body I have 2 <p> elements, one for each switch. Function cambiarColor is my script in charge of changing the colors of the <p>s using the if conditional and some simple JQuery.

In this attempt, I managed to at least get the logic working: the first <p> is always changed to red because the if always evaluates to FALSE. Also, the function is called on periodically as well. The second <p> I just left out of the party because he called me a fattie ;(

Now, what I don't know, and the real question behind this long-arse post, is what to put inside the if() in my script so that it pulls the value from the "webpage" I've set up (be it a 1 or a 0) so that the script responds to the states of the switches.

Thanks in advance for all the help.

Was it helpful?

Solution 2

First of all, many thanks to Q_ro for his help.

Here's how I managed to solve my problem: In the same order as last time, first comes the Arduino code

#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>

//variable constante que guarda la cantidad de puertas
#define CANT_PUERTAS 2

//variable tipo array que guarda los estados de las diferentes puertas
int estado[CANT_PUERTAS];

// Listen on default port 5555, the webserver on the Yun
// will forward there all the HTTP requests for us.
YunServer server;

void setup() {
  Serial.begin(9600);
  // Bridge startup
  Bridge.begin();
  //Pines que van a monitorear las puertas a partir de D2
  for (int i = 0; i < CANT_PUERTAS; i++) {
    pinMode(2 + i, INPUT_PULLUP);
  }
  // Listen for incoming connection only from localhost
  // (no one from the external network could connect)
  server.listenOnLocalhost();
  server.begin();
}

void loop() {
  //hacer poll de estado de puertas
  pollPuertas(estado);

  // Get clients coming from server
  YunClient client = server.accept();

  // There is a new client?
  if (client) {
    // Process request
    process(client);

    // Close connection and free resources.
    client.stop();
  }

  delay(50); // Poll every 50ms
}

My only changes here were in void setup(){}, where instead of manually declaring the pins to monitor, I created a for loop to automatically set them up based on the amount of pins to monitor; and in pollPuertas, where I changed the arguments passed to it.

void pollPuertas(int estado[]) {
  for (int i = 0; i < CANT_PUERTAS; i++) {
    estado[i] = digitalRead(2 + i);
  }
}

Like I said before, I changed the arguments to this function. Decided to just go with my previously defined constant.

void process(YunClient client) {
  // read the command
  String command = client.readStringUntil('/');
  command.trim();
  //confirmar que el comando recibido es el correcto
  if (command == "estado") {
    client.println("Status: 200");
    client.println("Content-type: application/json");
    client.println();
    //Inicio del array JSON
    client.print("[");
    //Valores del array
    for (int i = 0; i < CANT_PUERTAS; i++) {
      client.print(estado[i]);
      //Si no es el ultimo valor del array, intercalar una coma
      if (i < (CANT_PUERTAS - 1)) client.print(",");
    }
    //Cerrar array JSON
    client.print("]");
  }
}

And last but certainly not least, my process(YunClient client). Here is where the biggest changes happened (at least Arduino-side).

Taking the link Q_ro suggested as a guide, changed my REST calls from my original structure (arduinoyun.local/arduino/estado/PIN) where I had an individual "webpage" per PIN, to a new structure (arduinoyun.local/arduino/estado) where I would put all my currently monitored PINs in a single "webpage" as a JSON object (an array, in this case).

I want to make a special remark here: during my testing, I came to realize (the hard way) the importance of trimming whitespaces. Don't know why so don't ask me, but it wasn't until I did command.trim(); that my code worked. Maybe the browser inserts some whitespaces when querying the page or something, I dunno. What I do know is that was already banging my head against the wall trying to figure out why arduinoyun.local/arduino/estado wouldn't bring out anything by the time I noticed the trim() in Grallator's code.

Anyway, after the command is properly verified, I print a header that tells the browser this is a JSON object.

After that, I just print out an array with this form: [value, value, value]. You can get all the details in the Sources.

And that's about it on this side of the equation.

HTML and JavaScript

<!DOCTYPE html>
<html>

  <head>
    <title>Cambio de CSS con JSON</title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-2.1.1.js"></script>
    <script type="text/javascript">
    var Timer =setInterval(function(){cambiarColor()},500);
        function cambiarColor(){
        var i=0;
        $.getJSON("/arduino/estado/",function(json){
            var LENGTH = json.length;
            for(i; i < LENGTH; i++){
                if(json[i]==0){
                    $("#puerta"+i).css("color","green");
                } else{
                    $("#puerta"+i).css("color","red");
                }//cierra if
            }//cierra for
        }); //cierra $.getJSON
    } //cierra cambiarColor();
    </script>

  </head>
    <body>
    <p id="puerta0">Puerta 1</p>
    <p id="puerta1">Puerta 2</p>
  </body>

</html>

var Timer =setInterval(function(){cambiarColor()},500); simply sets up a timer so that function cambiarColor() is called upon periodically.

As per cambiarColor() itself, it's changed quite a bit. You can read up on the details of how function $.getJSON works in the Sources, but here's the gist:

  • assuming the JSON object is properly formatted server-side, $-getJSON() returns either a JS object or a JS array (an array in my case)
  • pass the array to variable json
  • create a variable to hold the length of the json array
  • do a for loop to go through the values inside of json
  • change CSS values using jQuery based on the values of the JSON object, obtained from the Arduino yaaaayyy

@Q_ro I found out how to concatenate the i to the jQuery selector so that I could work by IDs! Wooo!

So there you go. Once again, bunch of thanks to Q_ro for helping me out. Hope that this is useful to somebody else in the future.

One tip to remember (I know I forgot about this for longer than I care to admit): the $.getJSON section of the code is closed with a });, not just a }.

Sources

There's a bunch of helpful tools at the end of that last page. jsoneditoronline(dot)org in particular proved quite useful to me; helped me visualize the JSON object structure a little better.

OTHER TIPS

EDIT 2

Well, since your last comment, i think it may be worth it for you to try this out and see what happens:

    var response ;
    var file_path = 'path/to/your/file.txt';

     $.ajax({
                url: file_path,
                method: 'GET',
                dataType: 'text',
                async: false,
                success: function (data) {
                    response = data;
                }
            });
    //this should, in theory get you the inner contents of your file, and assign it to the variable 
    "response".

    //now you can validate

    if(parseInt(response) == 0){
                        //i still think using $('#puerta1') as the DOM selector is better.
                        $('p:nth-child(1)').css('color','green');
                    } else{
                        $('p:nth-child(1)').css('color','red');
                    }

                    $('p:nth-child(2)').css('color','blue');
        });

//if nothin' happens, try and uncomment the next line to try and find what jquery is reading from your file:
//alert(response);

I think this should be it, or at least i'm getting closer to undertanding your problem and finding a possible solution.

EDIT

Reading your question once again, i think i finally undesrtood what you are trying to do here, and so, i think the answer to your problem is as follows :

//The url to the webpage where arduino is outputing the values
$.get( "URLTOMYWEBPAGE.HTML").done(function( data ) {
if( parseInt(data ) == 0){
                //i still think using $('#puerta1') as the DOM selector is better.
                $('p:nth-child(1)').css('color','green');
            } else{
                $('p:nth-child(1)').css('color','red');
            }

            $('p:nth-child(2)').css('color','blue');
});

Hope this is in fact the solution to your problem.

OLD

Im not sure of what you are tryign to do on this line "if(1==0)" that's always gonna be false, i also don't really undertand how you are getting the values you want to read and evaluate onto your web page, but, lets say, the values (1 and 0 from what i understood) are going to be inside the P elements, that is to say, your html is gonna look ad follows:

<!-- assuming this values where returned from arduino -->
<p id="puerta1">1</p>
<p id="puerta2">0</p>

Asuming, all of the above is true, your script would look as follows:

var puertaUNO = document.getElementById("puerta1").innerHTML;
var puertaDOS = document.getElementById("puerta2").innerHTML;

if( parseInt(puertaUNO) == 0){
                $('p:nth-child(1)').css('color','green');
            } else{
                $('p:nth-child(1)').css('color','red');
            }

            $('p:nth-child(2)').css('color','blue');

Or with Jquery

var puertaUNO = $('#puerta1').text();
 var puertaDOS = $('#puerta2').text();

if( parseInt(puertaUNO) == 0){
                    $('#puerta1').css('color','green');
                } else{
                    $('#puerta1').css('color','red');
                }

                $('#puerta2').css('color','blue');

Still not entirely to clear on what you wanna do, but i think this is it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top