fyrwatch / fyrnode

An Arduino firmware library for the ESP8266 to design, configure and deploy nodes on the FyrMesh Platform.
MIT License
1 stars 0 forks source link
arduino esp8266 forest-fire fyrwatch mesh-networks painlessmesh wireless-sensor-networks

FyrNode

FyrNode Banner

A firmware library to design, configure and deploy nodes on the FyrMesh Platform.

Version: 0.2.0
Platform: Arduino ESP8266
Language: Arduino C/C++ License: MIT

Contributors

This repository contains the following:

FyrNode Library

An Arduino library that contains firmware code for sensor nodes and control nodes that run on the FyrMesh Platfrom. Contains abstraction tools to support a modular sensor hardware configurations, callbacks to support the painlessMesh library, loop runtimes to check button statuses and a custom message delivery protocol.
It is intended to be compatible with the ESP8266 NodeMCU boards.

The library is based on the painlessMesh library that implements a mesh network of nodes based on the ESP8266 and ESP32 platforms. This library combines this functionality along with its custom JSON-based command messaging protocol and modular hardware configuration support to abstract the FyrMesh platforms requirements into a simple collection classes that achieve all the required functionality behind the scenes.

Library Dependencies

Mesh Messaging Protocols

This library operates with 2 mesh messaging protocols, IMC & ICC. Both of these systems do not use a request-response system. Instead, they employ an Remote Procedure Call based system by sending 'commands' and handling incoming 'messages'. Unique handlers are built for each type of message or command.

InterMesh Communication (IMC)

A distibuted communication protocol where all nodes on the mesh can communicate using messages. Each message follows a simple structure as illustrated below.

message: {
  "type": "message",
  "origin": <uint_32>,
  "reach": {
    "type": <str>,
    "destination": <uint_32> (optional)
  },
  "data": {
    "type": <str>,
    <data/metadata>
  }
}

The origin is the nodeID of the node that sent the message and the data field is a dicitionary with a key type set to the type of message along with set of additional data/metadata. The reach field is set with reach parameters. The type may be either unicast or broadcast. The reach destination field is ignored for broadcast messages and is a recipient nodeID for unicast messages.

Some of the current types of messages include the following, each of which have their own characteristic set of metadata embedded in the data field.

The meshcommand messages are always generated by the control node and follow the following structure.

meshcommand: {
  "type": "message",
  "origin": <uint_32>,
  "reach": {
    "type": <str>,
    "destination": <uint_32> (optional)
  },
  "data": {
    "type": "meshcommand",
    "command": <str>,
    <data/metadata>
  }
}

The only real difference is the required command field within the data field. This string determines the command string and the sensor node calls the appropriate command handler to handle it.

When other recognized types of messages are recieved by the mesh, the appropriate message handler and if an unrecognized message type is recieved, it is ignored and logged to the Serial.

InterControl Communication (ICC)

An asymmetric protocol that allows the control node and the controller to send 'controlcommands' and 'meshlogs' to each other. This 'meshlog' format is also used by sensor nodes to log data to their Serial.

meshlog: {
  "type": "meshlog",
  "nodeID": <uint_32>,
  "nodetime": <uint64_t>,
  "logdata": {
    "type": <str>,
    "message": <str>,
    <data/metadata>
  }
}

The nodeID is the nodeID of the node that is generating the log and the nodetime is the internal clock time of the node when the log is generated. The logdata field is a dictionary with the a type and message key for the log type and log message and is often filled with other data/metadata for context.

Some of the current types of meshlogs include the following,

'*' These meshlog types are only generated by the control node and handled by the controller using the FyrMesh orchestration runtimes.
'^' These meshlog types are only generated by sensor nodes and only used for logging.

Apart from meshlogs, the library currently supports the command interface for the controller to send commands to the control node. The reverse is not possible yet, as of v0.2.0. These control commands are structured as follows.

controlcommand: {
  "type": "controlcommand",
  "command": <str>
  <data/metadata>
}

The command field determines the command to be executed and is often passed with some additional metadata to help handle the command. Some of the current types of control commands are:

FyrNode API

The library contains two classes FyrNode and FyrNodeControl. They behave as the sensor nodes and the control node for the FyrMesh platform respectively. The hardware configuration of the node is specified using a collection of global values made available to the library using the extern keyword.

This library while designed to be hackable and modular, is intended to be used as is on the nodes themselves. The only level of customization on the nodes is expected to be with the configuration value set to support different types of hardware configurations. New functionality must be implemented directly into the library and not on the sketch file of the node.

Handlers

The modularity of the library is achieved using a set of special runtimes called handlers. There are few types of handlers, such as message handlers and command handlers that are responsible for handling incoming messages and commands. These are IMC commands

FyrNode

The FyrNode object is initialised as mentioned below. The hardware configuration is not specfied at the time of intialisation of this object, but is rather accessed from the collection of global variables. See more in the Hardware Configuration Section.

FyrNode sensornode;

The FyrNode object has the following member methods.

FyrNodeControl

The FyrNodeControl object is initialised as mentioned below. The hardware configuration is not specfied at the time of intialisation of this object, but is rather accessed from the collection of global variables. See more in the Hardware Configuration Section.

FyrNodeControl controlnode;

The FyrNode object has the following member methods.

Configuration Values

The FyrNode library supports a modular approach to node design i.e. every node can be built and configured differently and the mesh can still function as a whole. This is achieved by embedding some values as global constants in the Arduino Sketch, which is then accessed by the library using the extern keyword that tells the linker to fetch the symbol from another part of the program.

The configuration values can either be manually filled in or the config-generator.py script can be used to interactively generate the values and their supporting comments. (This script is unavailable as of v0.2.0)

The configuration symbols are as follows:

Sensor Value Codes

0 = No Attachment
2 = MQ2 (GAS)
11 = DHT11 (DHT)
16 = SEN16 (FLM) 22 = DHT22 (DHT)
all other values are currently unassigned.

NodeMCU Pin Numbering

D0 = 16    D1 = 5    D2 = 4    D3 = 0
D4 = 2    D5 = 14    D6 = 12    D7 = 13
D8 = 15    D9 = 3    D10 = 1    A0 = 17
refer to this link for more information about NodeMCU pins

Example Sketches

An example program that uses the FyrNodeControl class to define a control node.

#include "fyrnode.h"

String MESH_SSID = "whateverYouLike";
String MESH_PSWD = "somethingSneaky";
uint16_t MESH_PORT = 5555;

int DHTTYP = 0;         // DHT attached to None
int DHTPIN = 99;        // DHT attached at None

int GASTYP = 0;         // GAS attached to None
int GASPIN = 99;        // GAS attached at None

int FLMTYP = 0;         // FLM attached to None
int FLMPIN = 99;        // FLM attached at None

bool PINGER = true;     //PINGER attached = true
int PINGERPIN = 5;      //PINGER attached at Pin D1 (GPIO5)

int CONNECTLEDPIN = 16;         // CONNECTLEDPIN attached at Pin D0 (LED_BUILTIN)
uint32_t SERIALBAUD = 115200;    // SERIALBAUD rate is 38400 bps

FyrNodeControl controlnode;

void setup() 
{
    controlnode.begin();
}

void loop() 
{
    controlnode.update();
}

An example program that uses the FyrNode class to define a sensor node that has DHT11 sensor attached at pin D1.

#include "fyrnode.h"

String MESH_SSID = "whateverYouLike";
String MESH_PSWD = "somethingSneaky";
uint16_t MESH_PORT = 5555;

int DHTTYP = 11;        // DHT attached to DHT11 Sensor
int DHTPIN = 5;         // DHT attached at Pin D1 (GPIO5)

int GASTYP = 0;         // GAS attached to None
int GASPIN = 99;        // GAS attached at None

int FLMTYP = 0;         // FLM attached to None
int FLMPIN = 99;        // FLM attached at None

bool PINGER = false;    //PINGER attached = false
int PINGERPIN = 99;     //PINGER attached at None

int CONNECTLEDPIN = 16;         // CONNECTLEDPIN attached at Pin D0 (LED_BUILTIN)
uint32_t SERIALBAUD = 115200;   // SERIALBAUD rate is 38400 bps

FyrNode meshnode;

void setup() 
{
    meshnode.begin();
}

void loop() 
{
    meshnode.update();
}

More examples are available in the library's examples directory.