bio photo

Email

Background

As previously noted I was in Callback hell learning how to operate Node with my program to send SMS’s via HTTP/REST protocols. I learnt Node concepts and how it makes use of frameworks like Express to use Twilio but was still having trouble implementing it in my code.

When I reached out for help, I got it. Thanks to Tom Igoe and John Farell. With a bit of encouragement and showing me the ropes I was able to get my program looking like this.

Process - Declare

We created a server file which had most of the Node.js code in it. We declare and call in Serial port library, declare a portname (this is adapted from Tom Igoe’s labs).

Then I declared and called my Twilio details and Express. We’ll make use of the Body Parsers, a middleware of Node, which we will use to parse SMS:to:body:from variables coming in the form of JSON values.

var path = require('path');
var serialport = require('serialport'),
SerialPort = serialport.SerialPort,
portname = process.argv[2];
client = require('twilio')('<--[removed]-->', '<--[removed]-->');
express = require('express');
bodyParser = require('body-parser');

//SMS values in JSON form

var msgOptions = {

    to:'+17185701757', // Any number Twilio can deliver to
    from: '+17182159247', // A number bought from Twilio for outbound communication (do not change)
    body: 'Hello Osama - this is a test message.' // body of the SMS message

};

Next - Express

Using Express() and bodyParser we read the key : value pairs in our JSON object (SMS body:to:from in our case). Being specific about bodyParser.json and .urlencoded and saying Extended:true is best practice to avoid deprecated error with bodyparser.

var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
    extended:true
}));

The code below is put in to let Express know that we’ve got static files in folder ‘public’ (this is a directory structure Node and Express like). The __dirname is to give the absolute path for express to run from (if you have express installed in a separate folder from your project folder).

app.use(express.static(path.join(__dirname,'public')));
app.listen(8080);
console.log("app listening");

Now, we get into HTTP : REST protocols (which is why we used Express in the first place). ‘app.post’ is posting data to the server. By running an anonymous function with objects ‘req’ and ‘res’, ‘req’ is our POST request, the bodyParser library parses the request which is why it’s written as’req.body’ and looks for the :to:from:body keys in the JSON object. If you’re not keeping track, this JSON object is going to be passed from a separate file (dashboard.js) which I’m going to talk about in a minute. The (body) parsed POST requests are then passed to msgOptions, which is called when Serial data is received. res.end() is good practice to send an empty response, because sometimes a response is expected and when not given hangs the program. I’m not sending an unempty response right now but I want to later (a trigger that runs a Starburst function on dashboard.js), but I will need help figuring that out!

app.post('/sms', function (req, res){
   
    msgOptions.to = req.body.to
    msgOptions.from = req.body.from
    msgOptions.body = req.body.body
    console.log(req.body);
    res.end();

Next - Serial Data and calling Twilio client.sendMessage()

The baudrate, options, parser are sensor dependent and were borrowed from the labs. myPort.on function takes incoming serial data and triggers client.sendMessage (Twilio) function. The msgOptions parameter passes values we rceived from the POST (app.post) request.

//setup port
var myPort = new SerialPort(portname, {
	baudRate: 9600,
	options: false,
	parser: serialport.parsers.readline("\n")
});

myPort.on('open', function(){
	console.log('port is open');
});

myPort.on('close', function(){
	console.log('port is closed');
});

myPort.on('error', function(){
	console.log('there is an error');
});

//An IF statement saying if myPort.on('data', function(data)) is returning values, client.sendMessage should execute

myPort.on('data', function(data){
	console.log(data);
    client.sendMessage(msgOptions, success);
	myPort.write('x');
    
});

Dashboard.js

We have our server (powered by Node) ready. What’s next? Yes, we need an interface where the user inputs their SMS and have that interface communicate with the server. Here’s how that works:

We declare our variables and in setup() put in a title “who are we texting today?”, enter sample numeric values, put it into a variable and then position it on the DOM. Next, we ask for the SMS body and put in a button which when pressed (mousePressed) calls the function sendData(). Here’s how it looks.

var h1; //header text for SMS
var setSMS; //button
var inputSMS; //input SMS text 
var setPhoneNumber; // input phone number
var to, from, body;
var lon, lat, weather, temp, cityName;
var thunder, drizzle, rain, snow, atmosphere, clear, clouds, shit;

function setup() {
//"Who are you texting today?"
  h1 = createElement('h3', "Who are you texting today?");
  h1.position(500, 250);

  setPhoneNumber = createInput("+1718");
  setPhoneNumber.position(550, 300);

  //"Get the ball rolling with the weather"
  h2 = createElement('h5', "Get the ball rolling with the weather");
  h2.position(510, 310);

  inputSMS = createInput("");
  inputSMS.position(550, 360);

  //button
  setSMS = createButton("Done");
  setSMS.position(590, 390);

  setSMS.mousePressed(function(){
    sendData();

    //mo.js starburst displayed on mousePressed
    //This can also be sent as res.end(); in app.post?
    var burst = new Burst({
    shape:    'circle',
    fill:     [ 'deeppink', 'cyan', 'orange' ],
    x: '50%', y: '50%'
    });
  });
}

new Burst is a function from mojs.io who do these pre-packaged funky graphics in Javascript. sendData() is playing an important role, it’s creating a JSON object from the DOM inputs and passing it via HTTP Post to Express in the server file (above). This is where the magic happens.

function sendData() {
  var params = {
    to: setPhoneNumber.value(),
    from: '+17182159247', //Twilio assigned number (Do not change)
    body: inputSMS.value()
  }

var expressPost = httpPost('/sms', params, "json", success);

function success() {
  println("I send the data");
}
}

This worked. Success! And marked the end of my callback hell. It looks super easy, well it is, but in a way it’s really not. Somethings look very obvious when you look at the final code but when you’re building it out, they’re not. For example, it wasn’t apparent we were going to sendData() would compile data as a JSON object. Earlier we were trying to send the data as strings from URL.

 // //var dataString = "?to=" + to + "&from=" + from + "&body=" + body;
  // var dataString = "?to=" + to + "&from=test"+ "&body=" + body;
  // console.log("here"); 
  // var test= httpPost("/sms", dataString, text, success);

And a lot of things, like what bodyParser does, or doesn’t do isn’t very obvious from documentation. Neither are app.post or app.get functions in Express especially when we were figuring out earlier logic of receiving data we used app.get. It wasn’t working. This app, while not perfect, works. I receive an SMS sent from the browser when prompted by my sensor.