8. Arduino NodeWire library

The Arduino NodeWire Library version 1.0 enables you to create IoT nodes using any Arduino compatible board and it has two main parts:

  1. The Node, which specifies the input and output ports
  2. the Link, which specifies the medium that the node uses to communicate with the outside world.

A node encapsulates the behavior of a connected device. The input and output ports is how you talk to a node. You write values to the input ports and read values from the output port. Your code must have functions that will provide a value for when each of the output ports are read and functions that will consume the value provided when any of the input ports are written to.

Node<int> node; // store input port values as int
node.inputs = "led"; // list of input portnames separated by space
node.outputs = "button"; // list of output portnames separated by space

node.on_read("button",
   []() -> nString {
      return digitalRead(BUTTON);
   }
);

node.on("led",
  [](nString val, nString sender) {
       digitalWrite(LED_BUILTIN,(int)val);
   }
);

This is the core functionality of a node. But a node cannot work in isolation. It has to be able to talk to the outside world. It is the link class that provides this connectivity. And there are many types of links: SerialLink, esp8266link, ethernetlink, gprslink, nrflink etc, depending on how you want your node to be connected.

You create the link object and associate it with the node during setup:

Node<int> node;
SerialLink link;

Serial.begin(38400);
link.begin(&Serial);

node.setLink(link);

And here is the complete code:

#include <nnode.h>
#include <nseriallink.h>

#define LED LED_BUILTIN

Node<int> node;
SerialLink link;

void setup() {
  Serial.begin(38400);
  link.begin(&Serial);

  node.inputs = "led";
  node.init("node01");
  node.setLink(&link);

  node.on("led",
     [](nString val, nString sender) {
        digitalWrite(LED,(int)val);
     }
  );

  pinMode(LED, OUTPUT);
}

void loop() {
  node.run();
}

The serial link enables you to interact with a node using PlainTalk over the Serial monitor. The node can also connect to the cloud through a gateway that has a Serial interface such as an ESP8266-based one or a python node running on Raspberry-pi or a PC.

Compile and upload the above sketch to your Arduino board. Launch the serial monitor and note the annunciation. Type the following in the serial monitor to stop the annunciation:

node01 ack cp

Make sure you select to send ‘Newline’ on the drop down at the bottom of the serial monitor window. Also make sure the selected baud rate is 38400.

_images/sm.png

To determine the amount of memory (ram) available:

node01 get memory cp

8.1. How to talk to ports

On the serial monitor, try the following commands.

node01 set led 1 cp

This will switch on the LED on the Arduino board. To switch it off:

node01 set led 0 cp

To get the current status:

node01 get led cp

You can enumerate the available ports by,

node01 get ports cp

8.2. How to define ports that takes non integer value

The values you read and write to a port does not have to be a numerical value. It can be any kind of value: an integer, a float, a string, and array or an object. All these are values that can be represented by nString.

Here is an example that remakes the led example but this time, the port takes one of three possible values: on, off or blink.

#include <nnode.h>
#include <nseriallink.h>

#define LED LED_BUILTIN

Node<nString> node;
SerialLink link;

bool ledon = false;

void setup() {
  Serial.begin(38400);
  link.begin(&Serial);

  node.inputs = "led:List|on,off,blink";
  node.init_with_props("blinky");
  node.setLink(&link);

  node.on("led",
     [](nString val, nString sender) {
         node.stopTimer(0);
         if(val=="on")
             digitalWrite(LED,1);
         else if(val=="off")
             digitalWrite(LED,0);
         else if(val=="blink")
             node.startTimer(0);
     }
  );


  node.on_timer(500,
     []() {
          if(ledon) digitalWrite(LED, 1); else digitalWrite(LED, 0);
             ledon = !ledon;
     }
  );

  pinMode(LED, OUTPUT);
}

void loop() {
  node.run();
}

To switch on the led we send:

blinky set led on cp

To switch it off:

blinky set led off cp

and when we send:

blinky set led blink cp

it blinks continously in one second intervals, 500ms on and 500ms off.

The timer function is used to schedule periodic events. You can define up to three timers: 0, 1 and 3, numbered in order of creation.

8.3. Multiple port example

#include <nnode.h>
#include <nseriallink.h>

#define MAINS 1
#define IGNITION LED_BUILTIN
#define BUZZER 3

Node<int> node;
SerialLink link;

void setup() {
  Serial.begin(38400);
  link.begin(&Serial);

  node.outputs = "mains gen";
  node.inputs = "ignition buzzer relay";

  node.init("sco");
  node.setLink(&link);

  node.on("ignition",
    [](nString val, nString sender) {
       digitalWrite(IGNITION,(int)val);
     }
  );

  node.on("buzzer",
    [](nString val, nString sender) {
       digitalWrite(BUZZER,(int)val);
     }
  );

  node.on_timer(1000,
    []() {
       Serial.println("tick");
     }
  );

  node.on_timer(500,
    []() {
       Serial.println("tock");
     }
  );

  node.on_read("mains",
    []() -> nString {
        return digitalRead(MAINS);
     }
  );

  pinMode(IGNITION, OUTPUT);
  node.startTimer(0);
  node.startTimer(1);
}

void loop() {
  node.run();
}

8.4. Other Topics

nString EEPROM Files Data Files