Nell’iperspazio con Rocket: il Framework Web di Rust!
Mastering the IoT With JavaScript and C++ - Günter Obiltschnig
1. Mastering The IoT
With JavaScript And C++
Günter Obiltschnig
Applied Informatics Software Engineering GmbH
guenter@appinf.com
@obiltschnig, @macchina_io
2. About Me
hard-core C++ developer (20+ years),
who also likes JavaScript
“full stack++”, embedded, hardware
to web frontend + cloud
POCO C++ Libraries (2004)
Applied Informatics GmbH (2006)
my-devices.net (2010)
AIS Radar for iOS (2011)
macchina.io (2013)
3. m .ioacchina
|‘makkina| – A modular open source toolkit for building
embedded IoT applications that connect sensors, devices
and cloud services.
4. IoT Gateway
devices.netCloud Services
AirVantage, Amazon,
Bluemix, Carriots, etc.
HTTP(S), REST
MQTT
Remote Access
my-devices.net
device apps
local“business logic”
web services
web visualization
database
discoverability
Mobile/Web
Clients
Devices/Sensor Networks
CoAP, IEEE 802.15.4,
Modbus, USB,
Bluetooth LE,
RS-232
5. POCO C++ LIBRARIES
platform abstraction, multithreading, XML and JSON processing, filesystem access,
stream, datagram and multicast sockets, HTTP server and client, crypto, SSL/TLS, etc.
Remoting
serialization, remote methods and events, IPC
Open Service Platform
dynamic module system
service registry
web application server
user authentication/authorization
Platform
JavaScript
V8 JavaScript engine and C++ bindings/bridging
Devices and Sensors
Sensors, Serial Port, GNSS/GPS, Accelerometer, I/O, …
Protocols
MQTT, CoAP, Modbus, Bluetooth LE, XBee, …
Services
WebEvent, DeviceStatus, NetworkEnvironment, …
WebUI
Login, Launcher, Bundles, Playground, etc.
IoT Components
6. > open source (Apache 2.0 License)
> built in C++ for best performance and efficiency
(JavaScript for parts of web interface)
> modular and extensible
> mature, proven codebase:
POCO C++ Libraries, Google V8, Eclipse Paho, SQLite
AngularJS, jQuery, OpenLayers, Ace (text editor),
+ Applied Informatics OSP and Remoting frameworks
> C++-to-JavaScript bridge
> Raspberry Pi, Beaglebone, Edison, RED, MangOH, etc.
> prototype on Linux or OS X host, easily deploy to device
> web interface with JavaScript editor
7. Why JavaScript?
> Popular and widely known*
> Standardized
> Easy to integrate into an existing framework
> Multiple embeddable engines available
> Good performance (for a scripting language)
> I like it ;-)
* but not necessarily universally liked
8. Sensors & Devices Protocols Cloud Services
Temperature, Ambient Light,
Humidity, Air Pressure, etc.
HTTP, HTTPS AirVantage
I/O, LED, Trigger,
Rotary Encoder
MQTT Bluemix
Accelerometer CoAP* Twitter
GNSS/GPS WebEvent Amazon IoT
Barcode Reader, RFID* WebTunnel Twilio (SMS)
XBee (ZigBee, IEEE 802.15.4) XBee API my-devices.net
TI SensorTag Bluetooth LE any with MQTT API
Serial Port Modbus any with HTTP/REST API
* planned
9. Pro Users and Device Manufacturers
> add device specific APIs
> make devices programmable in JavaScript for partners or end users
> device specific app store (sell additional software features)
> additional frameworks (Shell, UPnP, Remoting SOAP and JSON-RPC)
> customizable web user interface
> improved user authentication and authorization
> signed bundles
> pro support
10. Usage Examples
> Building Automation
> Vehicle Telematics/Connected Cars
> Energy Manager
(photovoltaics and battery controller)
> Industrial Internet of Things Platform
13. POCO C++ LIBRARIES
platform abstraction, multithreading, XML and JSON processing, filesystem access,
stream, datagram and multicast sockets, HTTP server and client, crypto, SSL/TLS, etc.
Remoting
serialization, remote methods and events, IPC
Open Service Platform
dynamic module system
service registry
web application server
user authentication/authorization
Platform
JavaScript
V8 JavaScript engine and C++ bindings/bridging
Devices and Sensors
Sensors, Serial Port, GNSS/GPS, Accelerometer, I/O, …
Protocols
MQTT, CoAP, Modbus, Bluetooth LE, XBee, …
Services
WebEvent, DeviceStatus, NetworkEnvironment, …
WebUI
Login, Launcher, Bundles, Playground, etc.
IoT Components
14. POCO C++ Libraries
> Started 2004
> ~300.000 LOC
> 1000+ classes
> on GitHub since 2012
1730+ stars
640+ forks
40-200 clones/day
> ~100 contributors
> Boost License
> http://pocoproject.org
POSIX, WIN32, other (RT)OS API
Foundation
C++ and C Standard LibrariesApplication
Zip
Net
Crypto
Data
SQLite
ODBC
MySQL
NetSSL
Util
Tools, Utilities and
additional Libraries
XML JSON
15. V8
> Google’s JavaScript Engine
> Used by Chrome/Chromium and node.js
> C++ library, (reasonably) easy to integrate and to extend
> Compiles JavaScript to native code (x86, ARM, MIPS)
> Great performance
> BSD License
16. Remoting
> Similar to .NET Remoting or Java RMI, but for C++
> Code generator parses annotated C++ header files and generates code
(serialization/deserialization, method dispatching, helpers)
> Supports different transports (binary TCP, SOAP, JSON-RPC)
> Used for automatic C++-to-JavaScript bridging
> Will also be used to implement sandbox mechanism
17. Open Service Platform (OSP)
> Inspired by OSGi, but for C++ (also JavaScript, Python, etc.)
> Dynamic module system based on bundles
(Zip files with metadata,
shared libs, other files)
> Dependency and
lifecycle management
> Services and service registry
> Web Server
POCO Core Libraries
(Foundation,XML,Util,Net)
Operating
System
API
Std.C/C++
Libraries
Service
Registry
Portable Runtime
Environment
Life
C
ycle
M
anagem
ent
Bundle
M
anagem
ent
Standard
Services
Bundles
install,resolve,start,stop
and uninstall bundles
provide services to other
bundles and find services
provided by other bundles
manage bundle versions
and dependencies
web server,
web- and console-
based management,
user authentication
and authorization,
preferences,etc.
application-specific
functionality and services
18. Combining POCO C++ Libraries and V8
> JavaScript is single-threaded and garbage-collected
> POCO is multithreaded (specifically web server)
> Make C++ object available to JavaScript
easy for static objects, just provide Wrapper
> Allow JavaScript code to create C++ objects
easy if you don’t care about memory/resource leaks
> Register a callback function called by GC when object is deleted
allows you to properly delete underlying c++ object
> However, V8 does not do callbacks when script ends
wrapped C++ objects won’t be deleted, leaks resulting
> Need to track every C++ object a script creates and clean up afterwards :-(
22. Service
<<generatedFrom>>
IService
ServiceProxy
Service
RemoteObject
The interface class has
all @remote methods
from the service class.
Service
Skeleton
<<invokes>>
<<generated>>
<<generated>><<generated>>
<<generated>>
Service
ServerHelper
<<generated>>
Registers
Skeleton, RemoteObject
and EventDispatcher (if
needed) with the Object
Request Broker.
Service
ProxyFactory
<<creates>>
<<generated>>
Service
ClientHelper
<<generated>>
Registers ProxyFactory
with the Object Request
Broker.
<<registers>><<registers>>
<<registers>>
Service
EventSubscriber
<<generated>>
Service
EventDispatcher
<<generated>>
<<registers>>
23. var tempSensor = ...;
tempSensor.on(‘valueChanged', function(ev) {
var temp = ev.data;
// ...
});
if (tempSensor.ready())
{
var temp = tempSensor.value();
// ...
}
30. // history.jss - GET /history.jss?item=temperature&maxItems=10
var db = require('database');
var validItems = ['temperature', 'humidity', 'illuminance'];
var data = [];
db.session.pageSize = form.maxItems ? parseInt(form.maxItems) : 20;
var item = form.item;
if (validItems.indexOf(item) > -1)
{
var recordSet = db.session.execute(
'SELECT timestamp, ' + item + ' FROM datalog ORDER BY timestamp DESC');
31. // history.jss (continued)
for (var row = 0; row < recordSet.rowCount; row++)
{
var time = recordSet.getValue('timestamp');
var value = recordSet.getValue(item);
var date = new LocalDateTime(1970, 1, 1);
date.addSeconds(time);
data[recordSet.rowCount - row - 1] = {
timestamp: date.format('%H:%M:%S'),
value: value
};
recordSet.moveNext();
}
recordSet.close();
}
response.contentType = 'application/json';
response.write(JSON.stringify(data));
response.send();
32. // MQTT to AirVantage
var sensors = require('sensors');
var mqttClientRefs = serviceRegistry.find('io.macchina.mqtt.id == "airvantage"');
if (mqttClientRefs.length > 0)
{
console.log('MQTT Client found');
var mqttClient = mqttClientRefs[0].instance();
setInterval(function() {
var epoch = "" + 1000*DateTime().epoch; // seconds to milliseconds
var payload = {};
payload[epoch] = {
"sensors.temperature": sensors.temperature.value(),
"sensors.humidity": sensors.humidity.value()
"sensors.illuminance": sensors.illuminance.value()
};
mqttClient.publish('JA347400060803/messages/json',
JSON.stringify(payload), 0);
}, 10000);
33. // twilio.js
var net = require('net');
module.exports = {
sendSMS: function(to, message) {
var accountSID = application.config.getString("twilio.accountSID");
var authToken = application.config.getString("twilio.authToken");
var from = application.config.getString("twilio.from");
var twilioHttpRequest = new net.HTTPRequest(
"POST",
"https://api.twilio.com/2010-04-01/Accounts/"
+ accountSID
+ "/SMS/Messages"
);
twilioHttpRequest.authenticate(accountSID, authToken);
twilioHttpRequest.contentType = "application/x-www-form-urlencoded";
twilioHttpRequest.content =
"From=" + encodeURIComponent(from) +
"&To=" + encodeURIComponent(to) +
"&Body=" + encodeURIComponent(message);
twilioHttpRequest.send(function(result) {
console.log("Twilio SMS Response: %O", result);
});
};
34. var sensors = require('sensors');
var twilio = require('twilio');
var enableSMS = true;
sensors.illuminance.on('valueChanged', function(ev) {
logger.notice("valueChanged: " + ev.data);
if (ev.data < 10)
{
logger.warning("Lights out!");
if (enableSMS)
{
twilio.sendSMS("+4367612345678", "Lights out!");
enableSMS = false;
}
}
else if (ev.data > 50)
{
enableSMS = true;
}
});