wissel.net

Usability - Productivity - Business - The web - Singapore & Twins

Let there be a light - Angular, nodeRED and Websockets


NodeRED has conquered a place in my permanent toolbox. I run an instance in Bluemix, on my local machine and on a Raspberry PI. I build a little demo where a light connected to a Particle lights up based on an event reaching a NodeRED instance. However I don't carry my IoT gear every time (got lots of funny looks at airport security for it), but I still want to demo the app. The NodeRED side is easy. I just added a websocket output node and the server side is ready to roll.
Web socket in NodeRED
On the browser side I decided to use angular.js and one of its web socket libraries ng-websocket. The application code is just about 50 lines, so here it goes:
'use strict';

var websocketEndpoint = 'wss://'+window.location.hostname+'/ws/bulb';

console.log('Application loading ...');
// Declare app level module which depends on views, and components
var myApp = angular.module('myApp', ['ngWebsocket','ngRoute']);


myApp.config(['$routeProvider', function($routeProvider) {
    console.log('Routes loading... ');
    $routeProvider.when('/bulbon', {
        templateUrl: 'bulbs/bulb-on.html'
    }).when('/bulboff', {
        templateUrl: 'bulbs/bulb-off.html'
    }).when('/bulbunknown', {
        templateUrl: 'bulbs/bulb-unknown.html'
    }).otherwise({redirectTo: '/bulbunknown'});
}]);

myApp.run(function ($websocket, $location) {
    console.log('run');
    var ws = $websocket.$new({
        url: websocketEndpoint,
        reconnect: true
    }); // instance of ngWebsocket, handled by $websocket service

    ws.$on('$open', function () {
        console.log('Websocket connection open');
    });

    ws.$on('$message', function (data) {
        console.log('data arrived');
        console.log(data);
        var newlocation = '#/bulbunknown';
        if (data.bulb === 1) {
            newlocation = '#/bulbon';
        } else if (data.bulb === 0) {
            newlocation = '#/bulboff';
        }

        window.location = newlocation;
    });

    ws.$on('$close', function () {
        console.log('Websocket connection closed');
    });
});

console.log('Done');

The HTML is simple. I split it into the main file and 3 status files. One could easily put the statuses into a script template section or inside the app.This would reduce the number of http requests. For the bulb I used font-awesome, so no image has been harmed in creating this demo.

The bower.json

{
  "name": "iotlightbulb",
  "description": "A simple lightbulb show from a websocket",
  "version": "0.1.0",
  "license": "APACHE2.0",
  "private": true,
  "dependencies": {
    "angular": "~1.4.0",
    "angular-route": "~1.4.0",
    "html5-boilerplate": "~5.2.0",
    "ng-websocket": "~0.2.1",
    "components-font-awesome": "components/font-awesome#~4.3.0"
  }
}

index.html

<!DOCTYPE html>
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>The Socket bulb</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/normalize.css">
    <link rel="stylesheet" href="bower_components/html5-boilerplate/dist/css/main.css">
    <link rel="stylesheet" href="bower_components/components-font-awesome/css/font-awesome.min.css">
    <link rel="stylesheet" href="app.css">
    <script src="bower_components/html5-boilerplate/dist/js/vendor/modernizr-2.8.3.min.js"></script>
</head>
<body ng-app="myApp">
<div class="container">
<!--[if lt IE 9]>
<p class="browsehappy">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p>
<![endif]-->
<h1>Angular Lightbulb App</h1>

<div ng-view>Let there be light</div>
    <ul class="menu">
        <li><a href="#/bulbunknown">unknown</a></li>
        <li><a href="#/bulbon">ON</a></li>
        <li><a href="#/bulboff">OFF</a></li>
    </ul>
</div>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/angular-route/angular-route.js"></script>
<script src="bower_components/ng-websocket/ng-websocket.js"></script>
<script src="app.js"></script>
</body>
</html>

bulb-unknown.html

<p>The light <br/>
    <span class="fa-stack fa-5x">
        <i class="fa fa-lightbulb-o  fa-stack-2x" style="color :  #000044"></i>
        <i class="fa fa-question-circle fa-stack-1x" style="color :  red"></i>
    </span>
</p>

bulb-on.html

<p>The light <br/>
    <span class="fa-stack fa-5x">
        <i class="fa fa-cog fa-stack-2x" style="color :  yellow"></i>
        <i class="fa fa-lightbulb-o  fa-stack-2x" style="color :  #FFAB00"></i>
    </span>
</p>

bulb-off.html

<p>The light <br/>
    <span class="fa-stack fa-5x">
      <i class="fa fa-ban fa-stack-2x" style="color: red;"></i>
        <i class="fa fa-lightbulb-o  fa-stack-2x"> </i>
    </span>
</p>

The CSS

/* app css stylesheet */
.container {
  margin : 25%;
  width : 50%;
  text-align: center;
}

.menu {
  list-style: none;
  border-top: 0.1em solid black;
  margin-top: 2em;
  padding: 0 0 0.5em;
}

.menu:before {
  content: "[";
}

.menu:after {
  content: "]";
}

.menu > li {
  display: inline;
}

.menu > li:before {
  content: "|";
  padding-right: 0.3em;
}

.menu > li:nth-child(1):before {
  content: "";
  padding: 0;
}

As usual: YMMV

Posted by on 24 August 2015 | Comments (0) | categories: Bluemix JavaScript NodeRED WebDevelopment

Comments

  1. No comments yet, be the first to comment