The Industrial IoT revolution will happen at the Edge and in the Fog, not in the Cloud.

Get ready with macchina.io, a comprehensive and powerful open source toolkit for IoT edge and fog computing applications that connect to sensors, devices and cloud services.

What is macchina.io?

A toolkit for embedded IoT edge and fog computing applications that connect sensors, devices and cloud services.

macchina.io is an open source software toolkit for quickly building device applications for the Internet of Things running on Linux-based devices like the Raspberry Pi, Beaglebone or MangOH. macchina.io implements a web-enabled, modular and extensible C++ and JavaScript runtime environment and provides easy to use building blocks. These enable applications to talk to various sensors, devices and cloud services, and to process, analyze and filter sensor data locally, at the edge device or within the local network ("fog").

Why macchina.io?

Easy and fun to use. Reliable and Rock-Solid. Efficient, Modular and Extensible. Open Source.

Rapidly build IoT device applications for edge and fog computing in JavaScript and/or C++. Reliable and rock-solid, based on industry proven components like the POCO C++ Libraries and the V8 JavaScript engine. Implemented in C++ for maximum efficiency. Runs on Embedded Linux devices with as little as 32 MB of RAM, as well as desktop Linux and macOS. Develop and test on desktop machine, then easily deploy to embedded device. Open source, under the Apache 2.0 License.

Who is macchina.io for?

macchina.io is for device manufacturers, system integrators and professional makers.

For device manufacturers and system integrators macchina.io PRO delivers a scalable, extensible and secure software framework that supports features such as secure software updates, device APIs and device-specific app stores, backed by professional support and consulting services available from Applied Informatics.
For professional makers, macchina.io delivers a powerful, fun-to-use and free toolkit to play, experiment and quickly build prototypes with.

Read the white paper: Programming IoT Gateways with macchina.io.

Leading companies are using macchina.io building blocks to create automotive telematics platforms, building and home automation devices, edge computing systems, smart sensors and energy management systems.

What will you build? Get started today!

Features

Sensors and Devices API

macchina.io provides rich APIs for accessing various sensors and devices, which can be used from both JavaScript and native C++ code.

Web Application Server

macchina.io is based on a powerful embedded web application server, providing a flexible module system that makes it easy to build dynamically extensible applications providing rich web-based user interfaces.

JavaScript Engine

Build your applications faster. macchina.io includes the V8 JavaScript engine which compiles JavaScript to native ARM or x86 machine code for great performance.

Components and Services

A powerful components and services architecture enables modular, easily extensible applications that can be upgraded and extended with new features in the field.

Communication Protocols

Broad support for modern and legacy communication protocols makes it easy to integrate sensor networks and automation devices.

HTTP(S) and MQTT Clients

macchina.io includes HTTP(S) and MQTT clients for connecting to cloud services and other IoT devices.

Embedded Database

macchina.io uses SQLite as embedded database. Great for logging sensor data and available to both JavaScript and C++ code.

Data Flow Engine

A built-in extensible data flow engine lets you build applications without coding.

Secure Remote Management

macchina.io uses my-devices.net for secure remote management and remote access via Web, SSH and VNC.

The macchina.io Stack

Who is behind macchina.io?

Günter Obiltschnig Günter Obiltschnig Founder & Lead Developer @obiltschnig

macchina.io has been created by Günter Obiltschnig, Founder and CTO of Applied Informatics, and Founder and Lead Developer of the POCO C++ Libraries.

Contact

Günter Obiltschnig
Applied Informatics Software Engineering GmbH
+43 4253 32596
guenter@appinf.com
www.appinf.com

Funding

The development of macchina.io was partly funded by the Internet Foundation Austria’s netidee program (2015/2016 term). See the announcement on the blog.

Examples

Web User Interface

macchina.io comes with a built-in web server providing different web apps for device management, testing and getting started with JavaScript development. These can be modified or replaced with a device-specific interface and apps. In any case, the web server is just another plug-in, so it can even be removed entirely if not needed.

JavaScript

Sensors

Sensors and other devices are presented as services that can be searched for based on various properties. In the following sample, we look for an ambient light (luminance) and a temperature sensor. The code that looks for sensors is implemented as a module and can be imported using the familiar require() function.


var sensors = {};

var ambientLightRefs = serviceRegistry.find('io.macchina.physicalQuantity == "luminance"');
if (ambientLightRefs.length > 0)
{
    sensors.ambientLight = ambientLightRefs[0].instance();
    logger.information('Ambient Light: ' + sensors.ambientLight.getPropertyString('name'));
}

var temperatureRefs = serviceRegistry.find('io.macchina.physicalQuantity == "temperature"');
if (temperatureRefs.length > 0)
{
    sensors.temperature = temperatureRefs[0].instance();
    logger.information('Temperature: ' + sensors.temperature.getPropertyString('name'));
}

module.exports = sensors;
						

Database

Once we have a sensor object, we can get a callback whenever the measured value changes. In the following example, we write the current sensor value into a SQLite database, together with a timestamp.


var data = require('data');
var sensors = require("sensors.js");

var dbPath = application.config.getString('datalogger.database');
var dbSession = new data.DBSession('SQLite', dbPath);

sensors.temperature.on('valueChanged', 
    function (event) 
    {
        dbSession.execute('INSERT INTO datalog VALUES (?, ?)',
            Date(),
            event.data);
    });
						

Serial Port

Many devices provide a serial (UART) interface and support a simple text-based protocol. It's easy to process data received from such devices.


var serial = null;
var serialRef = serviceRegistry.findByName('io.macchina.serialport#0');
if (serialRef)
{
    serial = serialRef.instance();
    logger.notice("SerialDevice found: " + serial.getPropertyString("device"));
}

serial.setFeature("events", true);
serial.setPropertyString("delimiters", "\n");
serial.setPropertyDouble("timeout", 0.1);
serial.on("lineReceived", 
    function(line) 
    { 
        logger.notice("Received: " + line.data); 
    });
						

Cloud Services

The following example shows how to send data to a cloud service providing a REST interface. We periodically obtain temperature and ambient light measurements and send them to the AirVantage M2M Cloud service.


var net = require('net');
var sensors = require('sensors.js');

var username = application.config.getString("airvantage.username");
var password = application.config.getString("airvantage.password");

setInterval(
    function()
    {
        var httpRequest = new net.HTTPRequest('POST', 'https://na.airvantage.net/device/messages');
        var epoch = 1000*DateTime().epoch; // seconds to milliseconds
        httpRequest.timeout = 10.0;
        httpRequest.authenticate(username, password);
        httpRequest.content = JSON.stringify(
            [
                {
                    "sensor.temperature": 
                        [
                            {
                                "timestamp": epoch,
                                "value": sensors.temperature.value()
                            }
                        ],
                    "sensor.ambientLight":
                        [ 
                            {
                                "timestamp": epoch,
                                "value": sensors.ambientLight.value()
                            }
                        ]
                }
            ]
        );
        var httpResponse = httpRequest.send();
        if (httpResponse.status != 200)
        {
            logger.error("Failed sending data to AirVantage: " + httpResponse.reason);
        }
    },
    30000);
						

The above sample blocks in send() until the HTTP request has been completed. HTTP requests can also be sent asynchronously. In this case, a callback function will be called when the request has completed.


        // ...
        httpRequest.send(
            function (result)
            {
                if (result.error)
                {
                    logger.error(result.error);
                }
                else if (result.response.status != 200)
                {
                    logger.error("HTTP request failed: " + result.response.reason);
                }
            });
        // ...
						

Servlets

The following example shows how to implement a servlet in JavaScript that reads sensor data from the SQLite database and formats it as JSON.


var data = require('data');

var dbPath = application.config.getString('logger.database');
var dbSession = new data.DBSession('SQLite', dbPath);
dbSession.pageSize = 20;

var recordSet = dbSession.execute('SELECT timestamp, temperature FROM datalog ORDER BY timestamp DESC');
response.contentType = 'application/json';
response.write(recordSet.toJSON());
response.send();