Lotus what? Nah mate, the world has moved on.

Friday, 18 September 2015

wissel.net :: 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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
'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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
{
  "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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<!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

1
2
3
4
5
6
<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

1
2
3
4
5
6
<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

1
2
3
4
5
6
<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
wissel.net :: Let there be a light - Angular, nodeRED and Websockets:



'via Blog this'

0 comments :

Post a Comment

Thank you for taking the time to comment. Your opinion is important and of value and we appreciate the positive feedback! If you are "Negative Nancy" then please do us, and humanity, a favor, and piss off.

Total Pageviews

Google+ Followers

Pages

Blog Archive

Popular Posts

Recent Comments

Rays Twitter feed

Ads

Web sites come and go and information is lost and therefore some pages are archived. @rayd123 . Powered by Blogger.