Skip to content

An Arduino firmware library for the ESP8266 to design, configure and deploy nodes on the FyrMesh Platform.

License

Notifications You must be signed in to change notification settings

fyrwatch/fyrnode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

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

  • Manish Meganathan
  • Mariyam A. Ghani

This repository contains the following:

  • An Arduino Library for the ESP8266
    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.

  • A Configuration Value Generation Tool
    An interactive python script to generate the configuration variables for any custom FyrNode configuration.

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.

  • meshcommand
  • handshake
  • handshakeACK
  • sensordata
  • configdata
  • connectionupdate

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,

  • meshsync
  • nodesync
  • handshake-rxack
  • sensordata
  • configdata
  • controlconfigdata
  • controlnodelist
  • messagerx

'*' 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:

  • connection-on
  • connection-off
  • readsensors-mesh
  • readsensors-node
  • readconfig-mesh
  • readconfig-node
  • readconfig-control
  • readnodelist-control

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.

  • begin()
    This method is used in the void setup() function of the Arduino Sketch. It initialises all the sensors, buttons, interfaces and initiates the mesh.
  • update() This method is used in the void loop() function of the Arduino Sketch. It runs the mesh.update() runtime in the backend along with checking for connection states, new messages and button states.

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.

  • begin()
    This method is used in the void setup() function of the Arduino Sketch. It initialises all the buttons, interfaces and initiates the mesh.
  • update() This method is used in the void loop() function of the Arduino Sketch. It runs the mesh.update() runtime in the backend along with checking for connection states, new messages and button states.

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:

  • MESH_SSID
    This String value determines the SSID name of the mesh AP configuration.
  • MESH_PSWD
    This String value determines the password of the mesh AP configuration.
  • MESH_PORT
    This uint16_t value determines the port on which the node has to listen to for mesh messages.
  • DHTTYP
    This int value determines the sensor ID attached to the DHT interface. Refer to the Sensor Value Codes section for sensor values.
  • DHTPIN
    This int value determines the pin on which the DHT sensor is attached. Refer to NodeMCU Pin Numbering section for pin values.
  • GASTYP
    This int value determines the sensor ID attached to the GAS interface. Refer to the Sensor Value Codes section for sensor values.
  • GASPIN
  • This int value determines the pin on which the GAS sensor is attached. Refer to NodeMCU Pin Numbering section for pin values.
  • FLMTYP
    This int value determines the sensor ID attached to the FLM interface. Refer to the Sensor Value Codes section for sensor values.
  • FLMPIN
    This int value determines the pin on which the FLM sensor is attached. Refer to NodeMCU Pin Numbering section for pin values.
  • PINGER
    This bool value determines whether a button is attached to the PINGER interface. Pressing this button broadcasts a pingresponse command to the mesh.
  • PINGERPIN
    This int value determines the pin on which the PINGER button is attached. Refer to NodeMCU Pin Numbering section for pin values.
  • SERIALBAUD
    This uint32_t value determines the baud rate of the Serial interface.
  • CONNECTLEDPIN
    This int value determines the pin on which the connection indicator LED is attached. Defaults to the built-in LED at pin D0 (16).

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.