Permalink
f737d98 Nov 14, 2017
288 lines (225 sloc) 9.87 KB
title description services author manager ms.service ms.workload ms.tgt_pltfrm ms.devlang ms.topic ms.date ms.author
Create an Azure IoT Edge Module with Node.js | Microsoft Docs
This tutorial showcases how to write a BLE data converter module using the latest Azure IoT Edge NPM packages and Yeoman generator.
iot-hub
sushi
timlt
iot-hub
na
na
js
article
06/28/2017
sushi

Create an Azure IoT Edge Module with Node.js

This tutorial showcases how to create a module for Azure IoT Edge in JS.

In this tutorial, we walk through environment setup and how to write a BLE data converter module using the latest Azure IoT Edge NPM packages.

Prerequisites

In this section, you set up your environment for IoT Edge module development. It applies to both 64-bit Windows and 64-bit Linux (Ubuntu 14+) operating systems.

The following software is required:

Architecture

The Azure IoT Edge platform heavily adopts the Von Neumann architecture. Which means that the entire Azure IoT Edge architecture is a system that processes input and produces output; and that each individual module is also a tiny input-output subsystem. In this tutorial, we introduce the following two modules:

  1. A module that receives a simulated BLE signal and converts it into a formatted JSON message.
  2. A module that prints the received JSON message.

The following image displays the typical end to end dataflow for this project:

Dataflow between three modules

Set up the environment

Below we show you how to quickly set up environment to start to write your first BLE converter module with JS.

Create module project

  1. Open a command-line window, run yo az-iot-gw-module.
  2. Follow the steps on the screen to finish the initialization of your module project.

Project structure

A JS module project consists of the following components:

modules - The customized JS module source files. Replace the default sensor.js and printer.js with your own module files.

app.js - The entry file to start the Edge instance.

gw.config.json - The configuration file to customize the modules to be loaded by Edge.

package.json - The metadata information for module project.

README.md - The basic documentation for module project.

Package file

This package.json declares all the metadata information needed by a module project that includes the name, version, entry, scripts, runtime, and development dependencies.

Following code snippet shows how to configure for BLE converter sample project.

{
  "name": "converter",
  "version": "1.0.0",
  "description": "BLE data converter sample for Azure IoT Edge.",
  "repository": {
    "type": "git",
    "url": "https://github.com/Azure-Samples/iot-edge-samples"
  },
  "main": "app.js",
  "scripts": {
    "start": "node app.js"
  },
  "author": "Microsoft Corporation",
  "license": "MIT",
  "dependencies": {
  },
  "devDependencies": {
    "azure-iot-gateway": "~1.1.3"
  }
}

Entry file

The app.js defines the way to initialize the edge instance. Here we don't need to make any change.

(function() {
  'use strict';

  const Gateway = require('azure-iot-gateway');
  let config_path = './gw.config.json';

  // node app.js
  if (process.argv.length < 2) {
    throw 'Calling pattern should be node app.js.';
  }

  const gw = new Gateway(config_path);
  gw.run();
})();

Interface of module

You can treat an Azure IoT Edge module as a data processor whose job is to: receive input, process it, and produce output.

The input might be data from hardware (like a motion detector), a message from other modules, or anything else (like a random number generated periodically by a timer).

The output is similar to the input, it could trigger hardware behavior (like the blinking LED), a message to other modules, or anything else (like printing to the console).

Modules communicate with each other using message object. The content of a message is a byte array that is capable of representing any kind of data you like. Properties are also available in the message and are simply a string-to-string mapping. You may think of properties as the headers in an HTTPS request, or the metadata of a file.

In order to develop an Azure IoT Edge module in JS, you need to create a new module object that implements the required methods receive(). At this point, you may also choose to implement the optional create() or start(), or destroy() methods as well. The following code snippet shows you the scaffolding of JS module object.

'use strict';

module.exports = {
  broker: null,
  configuration: null,

  create: function (broker, configuration) {
    // Default implementation.
    this.broker = broker;
    this.configuration = configuration;

    return true;
  },

  start: function () {
    // Produce
  },

  receive: function (message) {
    // Consume
  },

  destroy: function () {
  }
};

Converter module

Input Processor Output Source File
Temperature data message Parse and construct a new JSON message Structure JSON message converter.js

This module is a typical Azure IoT Edge module. It accepts temperature messages from other modules (a hardware module, or in this case our simulated BLE module); and then normalizes the temperature message in to a structured JSON message (including appending the message ID, setting the property of whether we need to trigger the temperature alert, and so on).

receive: function (message) {
  // Initialize the messageCount in global object at first time.
  if (!global.messageCount) {
    global.messageCount = 0;
  }

  // Read the content and properties objects from message.
  let rawContent = JSON.parse(Buffer.from(message.content).toString('utf8'));
  let rawProperties = message.properties;

  // Generate new properties object.
  let newProperties = {
    source: rawProperties.source,
    macAddress: rawProperties.macAddress,
    temperatureAlert: rawContent.temperature > 30 ? 'true' : 'false'
  };

  // Generate new content object.
  let newContent = {
    deviceId: 'Intel NUC Gateway',
    messageId: ++global.messageCount,
    temperature: rawContent.temperature
  };

  // Publish the new message to broker.
  this.broker.publish(
    {
      properties: newProperties,
      content: new Uint8Array(Buffer.from(JSON.stringify(newContent), 'utf8'))
    }
  );
},

Printer module

Input Processor Output Source File
Any message from other modules N/A Log the message to console printer.js

This module is simple, self-explanatory, which outputs the received messages(property, content) to the terminal window.

receive: function (message) {
  let properties = JSON.stringify(message.properties);
  let content = Buffer.from(message.content).toString('utf8');

  console.log(`printer.receive.properties - ${properties}`);
  console.log(`printer.receive.content - ${content}\n`);
}

Configuration

The final step before running the modules is to configure the Azure IoT Edge and to establish the connections between modules.

First we need to declare our node loader (since Azure IoT Edge supports loaders of different languages) which could be referenced by its name in the sections afterward.

"loaders": [
  {
    "type": "node",
    "name": "node"
  }
]

Once we have declared our loaders, we also need to declare our modules as well. Similar to declaring the loaders, they can also be referenced by their name attribute. When declaring a module, we need to specify the loader it should use (which should be the one we defined before) and the entry-point (should be the normalized class name of our module) for each module. The simulated_device module is a native module that is included in the Azure IoT Edge core runtime package. Include args in the JSON file even if it is null.

"modules": [
  {
    "name": "simulated_device",
    "loader": {
      "name": "native",
      "entrypoint": {
        "module.path": "simulated_device"
      }
    },
    "args": {
      "macAddress": "01:02:03:03:02:01",
      "messagePeriod": 500
    }
  },
  {
    "name": "converter",
    "loader": {
      "name": "node",
      "entrypoint": {
        "main.path": "modules/converter.js"
      }
    },
    "args": null
  },
  {
    "name": "printer",
    "loader": {
      "name": "node",
      "entrypoint": {
        "main.path": "modules/printer.js"
      }
    },
    "args": null
  }
]

At the end of the configuration, we establish the connections. Each connection is expressed by source and sink. They should both reference a pre-defined module. The output message of source module is forwarded to the input of sink module.

"links": [
  {
    "source": "simulated_device",
    "sink": "converter"
  },
  {
    "source": "converter",
    "sink": "printer"
  }
]

Running the modules

  1. npm install
  2. npm start

If you want to terminate the application, press <Enter> key.

[!IMPORTANT] It is not recommended to use Ctrl + C to terminate the IoT Edge application. As this way may cause the process to terminate abnormally.