.. include:: _controller_substitutions.repl

.. _C013_page:

|C013_typename|
==================================================

|C013_shortinfo|

Controller details
------------------

Type: |C013_type|

Name: |C013_name|

Status: |C013_status|

GitHub: |C013_github|_

Maintainer: |C013_maintainer|

Change log
----------

.. versionchanged:: 2.0
  ...

  |improved|
  Implementation of secure communication and check for valid data.

.. versionadded:: 1.0
  ...

  |added|
  Initial release version.

Description
-----------

ESPEasy is able to communicate between nodes itself.
It is an IANA registered service: `espeasy-p2p <https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=8266#ESPeasy>`_

* Service Name:  espeasy-p2p
* Port Number: 8266
* Transport Protocol:  UDP
* Description: ESPeasy peer-2-peer communication
* Registration date: 2018-11-28

This protocol is targeted specific for use by ESPeasy to let ESPeasy nodes
communicate with each other to create a big swarm of nodes working together
without the need for a hosted service like MQTT, which needs a central broker.

It is currently used for:

* Discovery of nodes
* Sharing sensor data among nodes

Later updates may add:

* Distribution of settings
* Sending commands

Sending & Known Nodes
---------------------

ESPEasy keeps track of all nodes advertising themselves via Sysinfo messages.

This knowledge is kept in a ``NodeStruct`` for at least 10 minutes.
If a node is not sending a Sysinfo message in this period, it will be removed from the list.

Data Format Versions
--------------------

During the IANA port assignment assessment, a number of issues were pointed out by their experts.

* Versioning
* Security
* Data validation
* Traffic limiting and congestion handling

There are now 2 versions available:

* Version "0" - No security, no data validation.
* Version "1" - Introduced in ESPeasy build <???>

Data Format Version 0
---------------------

Sending and receiving is causing issues when the swarm of nodes increases.

* All nodes with this service enabled will advertise their presence every 30 seconds via broadcast
* Nodes can not subscribe to receiving sensor data updates
* Non broadcast messages are sent to each individual known node, regardless if the receiving node will use the data
* Sensor Data messages are sent to each individual known node
* Sensor Info updates are sent to each individual known node when a plugin coupled to this plugin is saved.

Of each known node the following data is kept:

.. code-block:: C++

  struct NodeStruct
  {
    String nodeName;
    byte ip[4];
    uint16_t build;
    byte age;
    byte nodeType;
  };

The key to index this ``NodeStruct`` is the nodes unit number.

ASCII Data
~~~~~~~~~~

Command Message
***************

First byte is not 0xFF.

The entire message processed as a command like this:

.. code-block:: C++

  packetBuffer[len] = 0;
  String request = &packetBuffer[0];
  struct EventStruct TempEvent;
  parseCommandString(&TempEvent, request);
  TempEvent.Source = VALUE_SOURCE_SYSTEM;
  if (!PluginCall(PLUGIN_WRITE, &TempEvent, request)) {
    ExecuteCommand(VALUE_SOURCE_SYSTEM, &packetBuffer[0]);
  }

As can be seen, no checks for size, and it is just expected to be a valid ESPeasy command.
Also no check to see if the command is supported by the receiving end and no feedback to the sender.

Binary Data
~~~~~~~~~~~

Binary data is marked with the first byte 0xFF.

On the receiving end, it is packed in an event in the ``Data`` field and processed like this:

.. code-block:: C++

  struct EventStruct TempEvent;
  TempEvent.Data = reinterpret_cast<byte*>(&packetBuffer[0]);
  TempEvent.Par1 = remoteIP[3];
  TempEvent.Par2 = len;
  PluginCall(PLUGIN_UDP_IN, &TempEvent, dummyString);
  CPluginCall(CPLUGIN_UDP_IN, &TempEvent);

N.B. only the controller C013 implements code for handling UDP data.

Message types supported, determined by the 2nd byte:

* 1: Sysinfo message
* 2: Sensor info pull request (not implemented)
* 3: Sensor info
* 4: Sensor data pull request (not implemented)
* 5: Sensor data

Sysinfo Message
***************

There are 2 types of Sysinfo messages, a standard and an extended message.
The extended message starts with the same information as the standard one.

Standard Sysinfo message (13 bytes):

* 2 bytes marker (255 , 1)
* 6 byte MAC address
* 4 byte IP address
* 1 byte unit number

Extended Sysinfo message (13 + 28 = 41 bytes):

* 2 bytes ESPeasy data version number (LSB, MSB)
* 25 bytes node name
* 1 byte node type

The node type is defined as:

*  1 = "ESP Easy"
* 17 = "ESP Easy Mega"
* 33 = "ESP Easy 32"
* 65 = "Arduino Easy"
* 81 = "Nano Easy"

Sensor Info message
*******************

Sensor Info messages are just a description of a shared sensor.
It contains some information to setup a new sensor on the receiving end.

These messages are just a serialized byte stream of ``struct C013_SensorInfoStruct`` .

.. code-block:: C++

  struct C013_SensorInfoStruct
  {
    byte header = 255;
    byte ID = 3;
    byte sourcelUnit;
    byte destUnit;
    byte sourceTaskIndex;
    byte destTaskIndex;
    byte deviceNumber;
    char taskName[26];
    char ValueNames[VARS_PER_TASK][26];
  };


Sensor Data message
*******************


These messages are just a serialized byte stream of ``struct C013_SensorDataStruct`` .

.. code-block:: C++

  struct C013_SensorDataStruct
  {
    byte header = 255;
    byte ID = 5;
    byte sourcelUnit;
    byte destUnit;
    byte sourceTaskIndex;
    byte destTaskIndex;
    float Values[VARS_PER_TASK];
  };


Data Format Version 1
---------------------

This version remains compatible with version 0 for backwards compatibility.
It is using the "next" unused marker.

All messages will have a standard packet data format:

* 2 bytes Marker (255 , 6)
* 2 bytes Version   => also determines data offset (header length)
* 2 bytes Message type
* 2 bytes Size of data block in "N" blocks of 16 bytes
* 2 bytes Key/group selector
* 2 bytes Sequence number
* (16 x N) bytes Data block AES encrypted data (including 2 bytes checksum)
* 2 bytes Packet checksum

This allows to:

* Distinguish data format versions
* Filter on message type before allocating large buffers
* Use multiple (pre-shared) encryption keys to have several levels of security or just several groups.
* Validate correct transmission of packet (last 2 checksum bytes) before decrypting data.
* Allow for larger messages to be sent in sequences. (e.g. firmware upgrades?)
* Validate sender and content of data block, since it contains a checksum too, which is part of the encrypted data block.

Since AES has a block size of 16 bytes (128 bit), the size of the data block is defined as a block of 16 bytes.
This allows up-to 1 MB of messages. (2^16 * 2^4 = 2^20)
An UDP datagram sent over IPv4 cannot exceed 65,507 bytes (65,535 − 8 byte UDP header − 20 byte IP header).
In IPv6 jumbograms it is possible to have UDP packets of size greater than 65,535 bytes.
