Week 12 - interface

Introduction:

This week is about experimenting different tools and designing a GUI. i decided to test NODE-JS im not implementing electronics or “data-collection” in this file but designing a gui for the user to see. using web server (node-js, php, html, js, JSON, JSONP). for me, i enjoyed this assignment because neil decided to make this week not related to electronics :D

in this post im putting my experiment with Node-js ..
the goal is to create a web service that gives real time data to users …
im just doing Sine wave from my server on Godaddy cloud hosting ..

so i’ve godaddy account which i decided to put node-js on it…

Deployment Stages:


NVM:

you can skip to CGI node

using SSH i connect to my server: SSH myuser@serverip

of course im not root on their server as its shared between many different website so im using NVM (node Version manager) soto install NPM (node package manager) Guide to install node js (Sudo free)

commands i’ve used on my godaddy server:


curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.31.0/install.sh | bash
nvm install node
npm list -g

Node works perfectly …


CGI-node:

i want to run node as part of the web server apache so im using CGI-node which is cool fast and easy to deploy

steps to install CGI-node:

  • added this code to the .htaccess file
    
    Action cgi-node /cgi-bin/cgi-node.js
    AddHandler cgi-node .jss
    
  • download CGI-node.js into cgi-bin folder
  • Update the first line within cgi-node.js to point to the location of the node executable you uploaded earlier.
  • chmod (755) to have execute for node and cgi-node files

Hello Node-js:

i wrote the following code which is writes hello to the user .. and output to a txt file in the server:


    var fs = require("fs");
    write("Welcome to nodeJS <br><b>Server TIME:");
    write(Date() + "</b>");
    write("Writing the info to Out.txt ...<br><br>")
    write("-----------------<br>");
    var x = "Hello NodeJS\r\n" + Date();

    /*Note: im writing the file to `(../out.txt)` because this runs on cgi-bin folder in the server..*/
    fs.writeFile("../out.txt", x, (err) => 
        {
        if (err) {write("--error occured<br>")};
        write("Done <a href=\"out.txt\">Click here to view the file</a>");
        });


here you can try to execute my server side node-js:
hsn93.com/index.jscript

and then here you try to access the txt file:
hsn93.com/out.txt


JSON:

i want to make sine wave from the server side .. parse it into JSON format and then plot it in the browser .. JSON

so i start to write Node.js code:


    //to fix later .. get frequency from other file.. 
    var c_time = Date.now(); //server time ..
    var datay = [];
    var datax = [];
    for (var i=c_time; i<100+c_time; i+=1) 
    {
        datay.push(Math.sin(i));
        datax.push(i);
    }
    var data = {datay, datax};
    write(JSON.stringify(data));


Plotly:

now im going to plot this live data:

using Javascript Plot.ly

i like to animate the graph so i went for examples, animation

you can see the code written … i just want to tweek it so i retrieve the data from my Node js application



<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<div id="graph"></div>
    <script>
    Plotly.plot('graph', [{
      x: [1, 2, 3],
      y: [0, 0.5, 1],
      line: {simplify: false},
    }]);


    var mytimeout =  setInterval( function(){randomize()}, 750);
    //setTimeout(function(){ alert("Hello"); }, 3000);

    function randomize() {
      Plotly.animate('graph', {
        data: [{y: [Math.random(), Math.random(), Math.random()]}],
        traces: [0],
        layout: {}
      }, {
        transition: {
          duration: 100,
          easing: 'cubic-in-out'
        }
      })

    }
    </script>

Result:

cool .. now i want to get the data from my server (node js)


AJAX is the soloution:

to start with lets fetch the JSON data .. todo that im going to use AJAX (Asynchronous JavaScript And XML)

i tried to make request but the connection doesnt establish.. getting (readyState = 0) means there is somthing wrong in the first stages ..

after research .. i found that AJAX doesnt work with different server ..

it turned out that AJAX is not the soloution ..


JSONP is a great hack !!

JSONP is really a simply trick to overcome XMLHttpRequest same domain policy. (As you know one cannot send AJAX (XMLHttpRequest) request to a different domain.)

Why JSONP : i’ve to use JSONP because this page is hosted on (fabacademy.org) while my node-js application that im trying to get data from is on my server.. :

lets try to fetch the data from my server:

well, i will only show the first element of the datax (the time in millis) .. and i will update it every one sec ..

Browser Side Javascript:


    < script>
    function refresh_jsonp_myfunc()
    {
        var ss = document.createElement("script");
        ss.src = "http://hsn93.com/i.jscript";
        document.getElementsByTagName('head')[0].appendChild(ss);
        
    }
    function jsonp_myfunc(myObj) 
    {
        document.getElementById("jsonp-fetch").innerHTML = myObj.datax[0];
    } 
    var mytimeout_datax1 =  setInterval( function(){refresh_jsonp_myfunc()}, 1000);
    < /script>

    < div id="jsonp-fetch" style="color:red;">a< /div>

you can see in the browser, im defining a function that is called (jsonp_myfunc) and you call it by passing argument to it

now, im creating script tag which im loading the code from another webpage (this is common loading javascripts from everywhere) this script source is my node-js output ..

Server Side Node JS:


    var c_time = Date.now();
    var datay = [];
    var datax = [];
    for (var i = c_time; i< 100+c_time; i+=1)
    {
        datay.push(Math.sin(i));
        datax.push(i);
    }
    var data = {datay,datax};
    write("jsonp_myfunc("); //JSONP
    write(JSON.stringify(data)); //write actual JSON format
    write(" );"); //End of JSONP function

im loading the JSON data in a function call .. jsonp_myfunc(data); this goes to the web browser code and calls the function passing the data to it ..

Result:

MilliSeconds since Jan 01 1970

hsn93.com/i.jscript


Memmory Problem:

i really didnt like the code… i will show you why ..

the browser keeps creating new script tags which is how JSONP should work … but RAM doesnt like that ..

so i just added a trick to the client side code which destroys the function calling tag:


Final Code:

the function destroys its callback after it gets executed ..

Browser Side Javascript:


    < script>
    function refresh_jsonp_myfunc()
    {
        var ss = document.createElement("script");
        ss.src = "http://hsn93.com/i.jscript";
        ss.id = "jsnp_script0"; //added to distroy it self
        document.body.appendChild(ss);      
    }
    function jsonp_myfunc(myObj) 
    {
        document.getElementById("jsonp-fetch").innerHTML = myObj.datax[0];
            document.getElementById("jsnp_script0").remove(); // remove function callback
    } 
    var mytimeout_datax1 =  setInterval( function(){refresh_jsonp_myfunc()}, 1000);
    < /script>

    < div id="jsonp-fetch" style="color:red;">a< /div>

server Side node-js:

i edited the code in the server side as well, im exporting the sine with choosen frequency the code now gets the frequency from txt file in the server



so to let the user edit that txt file i just made php code:

  • Code html interface:

    
    <html>
    <body>
        <form action=“frequency.php” method=“post”>
            Frequency: <input type=“number” name=“frequency”><br>
            <input type=“submit”>
        </form>
    </body>
    </html>
    

  • PHP code to change frequency in the txt file:

    
    <?php
    $myfile = fopen(“cgi-bin/freq.txt”, “w”) or die(“Unable to open file!”);
    //$txt = “100”;
    $txt = $_POST[‘frequency’];
    fwrite($myfile, $txt);
    fclose($myfile);
    ?>
    


Real time SineWave

Change the Frequency dynamically

try changing frequency


interface with my circuit

until now the interfec was done on software only. i want to interface this with my circuit so i can change the frequency thro hardware using my own circuit.

to test how to connect the circuit to the website i went with processing. Processing is an open-source graphical library and integrated development environment built for the electronic arts, new media art, and visual design communities with the purpose of teaching non-programmers the fundamentals of computer programming in a visual context.

first step is to search for a way to conduct HTTP requests in processing. i found the following library that does that.

HTTP requests for processing

it is a small library that takes the pain out of doing HTTP requests in Processing.


import http.requests.*;

PostRequest post = new PostRequest("http://hsn93.com/frequency.php");
post.addData("frequency", "100");
post.send();

println("Reponse Content: " + post.getContent());
println("Reponse Content-Length Header: " + post.getHeader("Content-Length"));

The arduino code


#include 
#define RX PA1
#define TX PA0
const int buttonPin = PA2;
SoftwareSerial xSerial(RX, TX);
void setup()
{
xSerial.begin(9600);
xSerial.print("Initializing...");
pinMode(buttonPin, INPUT);
}
void loop() {
// read the state of the pushbutton value:
int buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
if (buttonState == HIGH) {
// send to serial 
xSerial.println("C"); //change 
} 
delay(150);
}

the processing code


import http.requests.*;
import processing.serial.*;
Serial myPort; // create object from serial class
boolean state; 

void setup(){
String portName = Serial.list()[0]; //0 is port number
myPort = new Serial(this, portName, 9600);
//char inByte = 'a';
}

void draw(){
while (myPort.available() > 0) {
char inByte = myPort.readChar();
if (inByte == 'C'){  
  PostRequest post = new PostRequest("http://hsn93.com/frequency.php");
  if (state == true) {
    ten(post);
  }
  else {
    hun(post);
  }
  post.send();
  println("Reponse Content: " + post.getContent());
  println("Reponse Content-Length Header: " + post.getHeader("Content-Length"));
  println(state);
 }
}
}

void ten(PostRequest post){
    post.addData("frequency", "10");
    state = false;
    println(state);
    delay(100);
}

void hun(PostRequest post){
    post.addData("frequency", "100");
    state = true;
    println(state);
    delay(100);
}