BFFT Techblog January: Node how to Express yourself with Angular
01/01/2017

BFFT Techblog January: Node how to Express yourself with Angular

Subject: How to develop an application for the visualization of real-time data using Node.js, AngularJS and Socket.IO.

In the following I would like to briefly address the individual technologies and tools that could be used to quickly build a web application for displaying real-time data. Additional implementation details can be found in a demo project. The source code can be found on Github.

Node.js

In recent years, JavaScript script language has basically become standard on pages of web clients and has prevailed against its competitors such as Flash and Java. Node.js1 is a JavaScript runtime environment that enables the creation of a large ecosystem in order to use JavaScript on the server side.

Node.js works with a single thread and uses non-blocking I/O calls. As a result, thousands of parallel connections can be processed in one thread. Unlike Node.js, classic web servers such as Apache create a new thread for each connection. Each of these threads uses main memory. Context switching between threads and the administration binds resources.

Thanks to the event-driven architecture and asynchronous processing of I/O tasks, Node.js is ideal for real-time web applications with many I/O operations. In order to correctly use the event-driven architecture of Node.js, each function that performs I/O operations must use callbacks. The event-driven programming paradigm helps avoid blockages.

A web server implemented using Node.js saves resources and also runs on devices with low-performing processors. Node.js runs on many operating systems such as Raspberry PI or TTX DataLogger2 developed by TTTech.

A simpler and resource-saving web server can be quickly implemented using Node.js and the Express library.

npm Packet Manager

Node.js is very lightweight and contains only the most important functions. However, the functionality can be extended as necessary using additional packages that can be obtained via the  npm3 package manager.

You can also create your own packages and provide these to the community via npm.

Each Node.js project has a package.json file where the project is configured. The required additional packages can be entered into this configuration file as a dependency. Packages can be downloaded and integrated into the Node.js project using the npm install command-line command. npm creates a separate folder for each package in the node_modules directory. The packages can then be download via require (“paketname”).

package.json
 {
 "name": "bfft_blog",
 "version": "1.0.0",
 "description": "Demo application to visualize real-time data with AngularJS, Node.js and Socket.IO",
 "main": "server.js",
 "scripts": {
 "test": "echo \"Error: no test specified\" && exit 1"
 },
 "dependencies": {
 "body-parser": "^1.15.2",
 "bower": "^1.8.0",
 "ejs": "^2.5.2",
 "express": "^4.14.0",
 "express-session": "^1.14.2",
 "morgan": "^1.7.0",
 "socket.io": "^1.6.0"
 },
 "author": "Tobias Dörner",
 "license": "MIT",
 "repository": {
 "type": "git",
 "url": "https://github.com/bfft/201701_techblog_angular_node.git"
 }
 }

Socket.IO

Socket.IO4 is a JavaScript library that enables real-time, bi-directional communication between the web client and the web server. The WebSocket protocol is used for communication. Socket.IO encapsulates the WebSocket protocol and uses fallback options in the event that the clients don’t support the WebSocket protocol.

Express

Express5 is a very flexible framework for Node.js web applications that can be extended through middleware almost without restriction. This means that a lightweight HTTP server that e.g. supplies static HTML, CSS, and JavaScript files to a client can be implemented with just a few code lines. Socket.IO can also be integrated just as easily in order to communicate with clients via WebSockets (see demo project).

AngularJS

In recent years, there has been a lot of hype around client-side JavaScript web frameworks such as AngularJS that are used for developing single-page web applications. AngularJS6 is developed by Google as open source under the MIT license. Version 1.x is now well-documented and fully developed for productive use. A large community is available for help with any issues. AngularJS is used by Netflix, Vevo, Sky Store, Google Mail and others.

This framework can be used to generate the individual HTML views client-side. With a classic AngularJS application, you work server-side with a REST interface that consumes and produces JSON. The REST interface is then queried client-side in order to retrieve the relevant data. Afterwards, the AngularJS application creates the HTML page directly in the web client. DOM manipulations via jQuery become redundant.

The two-way data binding is one of the most important features of AngularJS. The scope service detects changes in the model and updates the view using the expressions in HTML. On the contrary, any changes in the view are updated directly in the model.

AngularJS uses the Model-View-ViewModel (MVVM) software architecture pattern. The web application can be structured using modules, controllers, services, view templates, scopes, etc. Dependency injection is firmly integrated into AngularJS, enabling the testability of the individual components. Tests can be created and carried out using tools such as Karma7 and Jasmine8.

Bower

Bower9 is a package manager for JavaScript frameworks, libraries and assets that are used in the web client such as jQuery, AngularJS or Bootstrap. Bower is used similar to npm. The required packages are defined in a configuration file with the name bower.json. The destination directory where the packages are downloaded can be specified using another configuration file named .bowerrc.

bower.json
{
  "name": "201701_techblog_angular_node",
  "version": "1.0.0",
  "description": "Demo application to visualize real-time data with AngularJS, Node.js and Socket.IO",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "dependencies": {
    "body-parser": "^1.15.2",
    "bower": "^1.8.0",
    "ejs": "^2.5.2",
    "express": "^4.14.0",
    "express-session": "^1.14.2",
    "morgan": "^1.7.0",
    "socket.io": "^1.6.0"
  },
  "author": "Tobias Dörner",
  "license": "MIT",
  "repository": {
        "type": "git",
        "url": "https://github.com/bfft/201701_techblog_angular_node.git"
  },
  "private": true
}
.bowerrc
{
  "directory": "public/libs"
}

The bower install console command downloads the specified packages and their dependencies and creates a directory for each package in the specified destination directory.

 

Figure 1: Bower console output

The use of package managers such as Bower and npm has the great advantage since we no longer need to check in the libraries in the repository. The package manager also automatically resolves package dependencies. E.g., AngularJS requires jQuery in a specific version number. This is automatically downloaded by Bower, and the developer doesn’t have to worry about it.

Bootstrap

The growing market of smartphones and tablets increases the number of users who use web applications on mobile devices. Developers are now facing the challenge to develop web applications that can be operated on both desktop and mobile devices.

Bootstrap 10, an open-source CSS framework developed by Twitter, enables the development of websites in terms of responsive web design. Bootstrap contains design templates for typography, forms, tables, navigation bars and buttons.

Bootstrap is especially useful when a prototype needs to be developed in a short time and there is little time for a separate interface design. Bootstrap is still flexible enough to allow the users to adapt themes to their own needs.

Rickshaw

Rickshaw11 is an open-source JavaScript library for displaying interactive graphs and charts. The library is based on the d3 framework. The graphs are drawn in SVG elements and can be customized via CSS. Rickshaw lets you quickly draw visually appealing graphs and charts without any d3 knowledge. The only disadvantage is that Rickshaw can only render its graphs in SVG elements, which is not always desirable.

The HTML 5 standard knows canvas and SVG elements where objects can be rendered. Canvas and SVG are supported by d3. For example, if you want to use an SVG element for several thousand items, the performance of the web browser will most likely decline dramatically. Canvas is preferable if many elements need to be rendered.

Demo

I have prepared a small example in order to demonstrate the interaction of the above technologies, frameworks and libraries.

Typically, the web application developed using AngularJS communicates with the server through a REST interface. This demo has been specifically created to show how data can be exchanged between the client and the server in real time via Socket.IO using AngularJS.

The demo application is divided into two areas: a client that is running user-side in the browser and a lightweight server that can also run on a resource-deficient platform. The server can query the current CPU utilization via a module and transmit the data to the client in real time. The client displays the data in real time for the user as a text and as a graph. The application can be operated in a web browser and also on mobile devices such as smartphones and tablets.

Figure 2: Browser view on a desktop PC

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 3: Browser view on a smartphone

Using Express, we first implement a web server that is listening on port 3000. Then we set up our socket server that is running under the created web server. When a client connects with the connection event via Socket.IO, we issue a debugging message on the console. The same goes for the disconnect event if a client terminates the connection.

server.js
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(app.get('port'), app.get('ip'), function () {
    console.log('Express server listening on ' + app.get('ip') + ':' + app.get('port'));
});

io.on('connection', function (socket) {
    console.log('a user connected');
    socket.on('disconnect', function () {
        console.log('user disconnected');
    });
});

Every 50 milliseconds we send the value of the current CPU utilization over Socket.IO to clients who have subscribed to the cpuUtilization event.

server.js
setInterval(function () {
    io.emit('cpuUtilization', cpu.getUtilization());
}, 50);

In order to use the AngularJS dependency injection system, I am going to define a service with the name websocket and integrate the socket object from the Socket.IO library. I am going to build a WebSocket connection to the server in this service. Each socket callback is packed in a $scope.$apply. After the transferred callback has been called, AngularJS checks whether the status has changed and updates the view if required.

public/app/modules/cpu/cpuFactory.js
angular.module('cpu').factory('websocket', ['$rootScope', function ($rootScope) {
	var socket = io.connect();

	return {
		on: function (event, callback) {
			socket.on(event, function () {
				var args = arguments;
				$rootScope.$apply(function () {
					callback.apply(socket, args);
				});
			});
		}
	}
}]);

In the controller, we are going to set a callback function that is called when a new cpuUtilization event arrives via Socket.IO. The callback function inserts the new value in the graph and draws the graphs anew so that the change is visible in the browser.

public/app/modules/cpu/cpuController.js
    websocket.on('cpuUtilization', function (state) {
        $scope.graph.series.addData({ cpu: parseInt(state) });
        $scope.graph.render();
    });

And finally, a brief overview of the application. The application has a static navigation bar and a footer that always remain the same. The separate pages of AngularJS are rendered in between.

Figure 4: Division into modules and components

When the user navigates to the CPU page, the CpuCtrl (controller) get  activated and renders the page content using the template.

public/app/modules/cpu/cpu.html
<div id='cpu' class='container content_container' role='main' ng-controller='CpuCtrl'>
    <div class='panel panel-default'>
        <div class='panel-heading'>
            <h3 class='panel-title'>
               <cpu-info></cpu-info>
            </h3>
        </div>
        <div class='panel-body'>
            <cpu-graph renderer='area' color='#ff0000'></cpu-graph>
        </div>
    </div>
</div>

The template in turn uses the cpu-info and cpu-graph directives created by me.

public/app/components/cpu.js
angular.module('cpuComponent', [])
    .directive('cpuInfo', function () {
        return {
            restrict: 'E',
            template: '<b>Cpu Utilization:</b> {{state}}%'
        }
    })
    .directive('cpuGraph', function () {
        return {
            restrict: 'E',
            template: '<div id="chart"></div>',
            link: function (scope, el, attrs) {
                scope.graph = new Rickshaw.Graph({
                    element: document.querySelector('#chart'),
                    width: null,
                    height: 300,
                    renderer: attrs.renderer,
                    min: 0,
                    max: 100,
                    series: new Rickshaw.Series.FixedDuration([{ name: 'CPU', color: attrs.color }], undefined, {
                        timeInterval: 250,
                        maxDataPoints: 500,
                        timeBase: new Date().getTime() / 1000
                    })
                });

                scope.graph.render();
            }
        }
    });

The source code can be obtained via Github. The source code in the master branch contains a lot of comments for the detailed explanation of the application. A version without comments is located in the no_comment branch.

1.   https://nodejs.org/en/

2.   https://www.tttech.com/de/markets/automotive/projekte-referenzen/ttx-datalogger-mit-audi/ 

3.   https://www.npmjs.com/

4.   http://socket.io/

5.   http://expressjs.com/de/

6.   https://angularjs.org/

7.   http://karma-runner.github.io/1.0/index.html

8.   https://jasmine.github.io/1.3/introduction.html

9.   https://bower.io/

10. http://getbootstrap.com/

11.  http://code.shutterstock.com/rickshaw/


Author: Tobias D. (Concept development & Tooling)
Contact: techblog@bfft.de 
Picture source: Tobias D.


BFFT jobs: