Package: reticul8
reticul8Remotely articulated MCU endpoints for Pythonreticul8 allows you to use Python to remotely control a compatible microcontroller
such as an Arduino or ESP32.On the Python side, it uses Python 3.5+ and asyncioOn the microcontroller side it usesPJONandPJON-cythonto communicate with
the micro controller - anything uC that can run PJON should be compatible.It also usesprotocol buffersto encapsulate the RPC messages.For example, you could use the following setup to wirelessly control an
ESP32 using ESPNOW"HUB" (Running Python) <--Serial/UART--> NODE 1 (ESP32)
                                          ^--ESPNOW --> NODE 2 (ESP32)
                                          ^--ESPNOW --> NODE n (ESP32)Rationalereticul8 is designed to meet the following requirements :-The system should be able to run "complex application logic" and be "internet connected"Nodes in the system should be able to connect to the hub using a variety of mediums (wired and wireless)Nodes should be able to run on common MCU hardware (Arduino and ESP32 targeted initially)Nodes should be fast and reliable, but don't need to be "smart" - application logic can live elsewhereCommunication between nodes and controller should be fast and reliable (ie not over the internet!)Notice that one key requirement is theabsence of internet connectivity. What happens to your home
automation system when the internet goes down?reticul8 is designed for a home automation system where the nodes are not (necessarily) directly connected
to the internet. This also has the benefit of making communication between the controller/hub and the nodes much
faster than something like pub/sub (<70ms rtt for a two node setup with ESPNOW and ThroughSerial).Building on PJON as the communication medium between the nodes allows for plenty of options.reticul8 is designed to be part of a home automation system - specifically it allows nodes (eg an ESP32 or Arduino) to
operate as dumb remote endpoints controlled by a smart controller (eg Python running on RaspberryPi).Competing projects include :-Mongoose OS - An open source Operating System for the Internet of ThingsMicroPython - Python for microcontrollersZerynth - The Middleware for IoT using Python on MicrocontrollersBut when I looked at the features I required, none of these seemed like a good fit. MicroPython and Zerynth seemed to
be too "resource heavy" to run a simple dumb endpoint. Mongoose OS was a pretty close fit but it still assumes your
nodes are on the internet.Arduino-like API:The nodes (endpoints) are controlled using Remote Procedure Calls (RPC) defined withprotocolbuf.An Arduino-like API is provided :-importasyncioimportuvloopfromreticul8importrpc,pjon_strategiesfromreticul8.arduinoimport*classNode(rpc.Node):asyncdefnotify_startup(self):print("Received startup message from{}".format(self.device_id))withself:# schedule the inbuilt LED to blink 10 timeswithSchedule(count=10,after_ms=100,every_ms=500):awaitdigitalWrite(22,LOW)withSchedule(count=10,after_ms=600,every_ms=500):awaitdigitalWrite(22,HIGH)awaitasyncio.sleep(10)#manually blink the LEDawaitpinMode(22,OUTPUT)foriinrange(5):awaitdigitalWrite(22,HIGH)awaitsleep(.1)awaitdigitalWrite(22,LOW)awaitsleep(.1)#read the value of the pinawaitpinMode(19,INPUT_PULLUP)value=awaitdigitalRead(19)print("HIGH"ifvalue==HIGHelse"LOW")#ping the remote nodeforiinrange(10):awaitping()#an ESP32 feature - built in PWMawaitPWM_config(22)whileTrue:awaitPWM_fade(pin=22,duty=0,fade_ms=500)awaitsleep(1)awaitPWM_fade(pin=22,duty=8192,fade_ms=500)awaitsleep(1)classPJON(pjon_strategies.SerialAsyncio):defnotify_connection_made(self):print("ESP32 connected")defnotify_connection_lost(self):asyncio.get_event_loop().stop()asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())loop=asyncio.get_event_loop()transport=PJON(device_id=10,url="/dev/ttyUSB0",baudrate=115200)Node(remote_device_id=11,transport=PJON)loop.run_forever()loop.close()Supported RPCsGPIOpinMode()digitalRead()digitalWrite()INPUT -> Watch pin for changes with callback on change, debounceI2Ci2c_readi2c_writeESP32 specific features:PWM (ledc)OTA Updatereticul8 helpersschedule commands to run repeatedlyrun multiple commandsPlanned featuresAnalog outputAnalog inputTouch sensor (ESP32)Pulse counter (ESP32)Building an ESP-IDF component nodeCreate a new ESP-IDF project,
andadd the Arduino component.Add reticul8 as a component :-cdcomponents
gitclonehttps://github.com/xlfe/reticul8Yourmain.cppjust needs to setup your PJON buses, and pass these to the reticul8 class. Call setup and loop as per
the arduino functions.// Define Wifi config for ESPNOW#include"esp_wifi_types.h"staticwifi_country_twifi_country={cc:"AU",schan:1,nchan:14,max_tx_power:80,// Level 10policy:WIFI_COUNTRY_POLICY_MANUAL};#include"Arduino.h"# PJON defines#define PJON_INCLUDE_ANY#define PJON_INCLUDE_TSA#define PJON_INCLUDE_EN#define TSA_RESPONSE_TIME_OUT 100000#include<reticul8.h>PJON<Any>*bus=NULL;RETICUL8*r8=NULL;voidloop(){r8->loop();}voidsetup(){Serial.begin(115200);Serial.flush();//EPSNOWStrategyLink<ESPNOW>*link_esp=newStrategyLink<ESPNOW>;PJON<Any>*bus_esp=newPJON<Any>();bus_esp->set_asynchronous_acknowledge(false);bus_esp->set_synchronous_acknowledge(true);bus_esp->set_packet_id(true);bus_esp->set_crc_32(true);bus_esp->strategy.set_link(link_esp);//Uncomment the line below to make a single bus device (eg leaf)// otherwise the device is initialised as a bridge between esp-now and serial// r8 = new RETICUL8(bus_esp, 10); /*//SerialStrategyLink<ThroughSerialAsync>*link_tsa=newStrategyLink<ThroughSerialAsync>;link_tsa->strategy.set_serial(&Serial);bus=newPJON<Any>(11);bus->strategy.set_link(link_tsa);bus->set_asynchronous_acknowledge(false);bus->set_synchronous_acknowledge(false);bus->set_packet_id(false);bus->set_crc_32(false);PJON<Any>*secondary[1]={bus_esp};r8=newRETICUL8(bus,10,secondary,1);//*/r8->begin();}Finally, make sure yourcomponent.mk(in same directory as main.cpp) includes the following :-COMPONENT_DEPENDS+=reticul8#Used for build timestampCPPFLAGS+=-D"__COMPILE_TIME__=`date'+%s'`"