Chapter 5 - EasyNet

I have been developing EasyNet to let me create a smart interactive system which I can keep on evolving indefinitely to suit my future needs.
There is no need to know IP addresses, no network configuration to bother with, and no rigid framework structure to adhere to.
The same basic network script is used on all nodes, making interactive networking simple for my own needs, and for anyone else who wants to use it.
Each EasyNet node is given a unique name of choice (or one will be created automatically) allowing nodes to address each other by their unique names.
Nodes communicate by broadcasting simple UDP text messages which consists of the target name plus whatever info or message is being sent.
The user decides what info is sent, by deciding what specific key words (instructions) the different nodes should respond to, and how they should respond.
Optional data may also be included if wished.

Target_name  Instruction  [ optional data strings ]

As well as responding to their unique name (and also their IP address if needed), nodes can also be assigned and respond to multiple 'group' names, and "ALL", 
I don't claim perfection, and undoubtedly it could be optimised and improved, but it works well for my purposes.
It is not intended to be super-fast or highly efficient, it is intended to be super-easy to use, and highly flexible and expandable.

I've already published some projects which allow EasyNet nodes to interact with each other to create automation and control systems.
 Smart Switch and Smart Socket can send and receive switch and sensor triggers to control Mains relays.
 Sensor alerts and system announcements can be spoken from one or more Voice Announcer TTS nodes by sending appropriate text msgs to be spoken.
 An Alerts Monitor node can collate sensor alerts from various remote nodes to visually display sensor channels on a central neo-pixel monitor.
 IR receiver nodes can read InfraRed remote control signals from different locations and distribute IR signals to one or more remote IR emitter locations.
 IR signals can either be emitted to control IR equipment, or be decodedby the esp node to control any of its local functionality, such as operate relays etc.

Thus existing EasyNet projects already allow triggered sensor alerts to control other devices, and/or send IR signals to control equipment, and/or send TTS messages to speak relevant announcements, and/or display visual sensor channel status, all at various selected locations... and it is easy to add more functionality.

For example: to suit my own needs I have created a weird "Sentry" to act as my central system controller.
  It reads external digital sensors using analog inputs to provide adjustable 0 to 5v logic level thresholds (for improved trigger reliability down long lengths of thin wires
  Announces Alerts via distributed audio Text to Speech  (can be used to announce some types of events at some locations and other types of events at others in different voices)
  Transmits Alerts to any nodes who may be interested (sending msgs to EasyNet 'groupnames' makes it possible for multiple listening devices to each respond
  Permits other EasyNet nodes to request and receive system status information, allowing multiple remote 'System Console' devices to monitor and control at the same time
  Uses Wemos D1 Mini footprint to allow the same script to work with either an esp8266 or esp32 device plugged into the wemos socket (by using software flags)
  When using an esp32, includes RJ45 cable ethernet capability for bridging EasyNet traffic between different wifi networks, plus adds SD card for file logging
  Provides visual central system clock, plus optional scheduled speaking clock (muted outside of socially acceptable hours), automatic announcement volume adjustments

EasyNet allows any of the local "Sentry" features to be made readily available as remote network functionality for any other EasyNet nodes to use..
So any remote nodes could write entries to the Sentry central Log file, or send the Sentry messages for announcement, or sync to its RTC date and time, etc.
Shared functionality is accessed simply by sending a message to the required target name with an appropriate instruction for it to recognise and respond to.

Conversely, any messages NOT intended for a node can either just be ignored, OR automatically relayed elsewhere if it has been configured to be a bridging node.
So messages not intended for nodes on a local wifi network could be automatically bridged via cable ethernet to the nodes on a remote wifi network and vice versa.
Or a serial cable bridge could relay messages to another Annex serial bridge... or even to a totally different serial platform such as arduino or ras pi etc - .

The Sentry was planned as a dual standard device which I might perhaps initially publish as an esp8266 project, while continuing development of a pin-compatible plug-in esp32 version to take advantage of the additional Annex32 features such as cable ethernet and SD card, while using exactly the same script, simply changing software flags depending on what hardware was being used. That all went as planned, and It's been working reliably through power cuts and lightning storms for months without problems or false triggers.
But priorities change - and it is probably too weird to be worth publishing as a project anyway - so I've mentioned it here just to illustrate how EasyNet has let me cater to my own needs .

An optional "Watchdog" monitor (Sonoff S20) was later added to supply power to the Sentry device. If the watchdog is present and enabled, it periodically sends a request for acknowledgement to the specified 'Sentry' watch client. If the watched client fails to respond within the specified 'timeout' period the watchdog records the failure in its log then disables subsequent client monitoring (to prevent endlessly transmitting to a failed client) before cycling power to the client off and back on again to try to reboot it.

The "Watchdog" node recognises a local "WATCH" EasyNet instruction, thereby allowing the watchdog facility to be remotely turned on or off.

   Watchdog_target_name   Watch  ( 1 / 0 )  [ watch_period ]  [ watch-client_name ]   
          where 1 or 0 turns the watchdog monitoring feature on or off, and optional [watch_period] and [watch_client_name] allow those parameters to be changed if required.

If cycling power to the unresponsive Sentry causes it to successfully reboot, it sends "WATCHDOG  WATCH  1" at startup which causes the Watchdog (if present) to re-enable monitoring of the watch client (Sentry) again.
If there is no Watchdog monitor present then that bootup message will just fall on deaf ears of course, but if a Watchdog is available its log will contain a record of all the Sentry failures, even though the Sentry may have been successfully restarted every time it failed.


Behind the Scenes
By default, UDP broadcasts do not include any error-correction or hand-shaking facilities - they are just 'fire and forget' - which may be ok for a few nodes on an isolated wifi subnet, but cannot be depended upon in a busy shared network with lots of noisy traffic.

So EasyNet offers optional hand-shaking capability to make udp communications more robust if needed.
Messages are usually sent as a response to some sort of trigger event, so the response will have been hard-coded by the user into the appropriate subroutine code.
Therefore it is up to the user to decide whether the message is important enough to require ACKnowledgement, or can just be 'fire and forget'.
This is achieved by using an appropriate user-sub...
  SEND msg$ is just a fire and forget udp broadcast
  SENDQ msg$ adds the msg$ into a RETRY Queue for periodic resending until either it is ACKnowledged or a pre-defined Time2Live expires.

SENDQ adds  ID=(unixdate+unixtime+Time2Live)  to the end of the message, which the sending node uses to time out unACKed msgs from the queue.
The target responds to any received messages containing 'ID=' by echoing back an ACKnowledgement of the received msg to the sender (is all done automatically).

The user can set the default value of Time2Live (in seconds) for whatever duration the sender should keep re-trying to send the messages.
Bear in mind that if a node becomes unreachable then no sent messages will be acknowledged by it, so the senders SENTQ will just keep on growing bigger until the un-acked messages eventually expire and are deleted from the queue... something to consider when changing Time2Live.
The periodic retry timer only tries to resend the first (next) unexpired message still in the FIFO retry queue, then adds it back on to the end of the retry queue... so any remaining un-acknowledged msgs are being continuously cycled from back of the queue to the front from where they are periodically tried to be resent.
If a node is kept busy doing other tasks, increase it's periodic timer1 frequency to something it can more comfortably manage (eg: 5 seconds).
Messages could be prioritised for importance by attaching different Time2Live durations for different message urgencies if needed.
Robin Baker,
Jun 5, 2018, 11:50 AM