esp mesh network with osc

With the painlessMesh library it turned out easy to set up a decentralised mesh network for a few ESP8266 modules. The example below show how I set it up and how to send and receive OpenSoundControl (OSC) messages. The code should also work on an ESP32 but I did not try that yet.

1. Install the painlessMesh and the OSC libraries for Arduino.

2. Program a few nodes (ESP8266) so that they all run this code...

//req. libraries: OSC, painlessMesh

#include <Arduino.h>
#include <painlessMesh.h>
#include <WiFiUdp.h>
#include <OSCMessage.h>
#include <OSCData.h>

#define MESH_NAME "networkname" //EDIT mesh name
#define MESH_PASS "networkpass" //EDIT password
#define MAX_CONN 4  //EDIT esp32 can have more than esp8266

#define INPORT 19998  //osc in port
#define OUTPORT 57120 //osc out port (sc)

IPAddress outIP;
WiFiUDP Udp;
painlessMesh  mesh;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  mesh.init(MESH_NAME, MESH_PASS, 5555, WIFI_AP_STA, 1, 0, MAX_CONN);
  Udp.begin(INPORT);
}

void pingFunc(OSCMessage &inMsg) {
  digitalWrite(LED_BUILTIN, 1 - digitalRead(LED_BUILTIN));  //toggle led
  OSCMessage outmsg("/pong");
  outmsg.add(mesh.getNodeId()); //uint32
  IPAddress ip;
  ip= mesh.getStationIP(); //0.0.0.0 if current base station
  outmsg.add(ip[0]);
  outmsg.add(ip[1]);
  outmsg.add(ip[2]);
  outmsg.add(ip[3]);
  ip= mesh.getAPIP();
  outmsg.add(ip[0]);
  outmsg.add(ip[1]);
  outmsg.add(ip[2]);
  outmsg.add(ip[3]);
  Udp.beginPacket(outIP, OUTPORT);
  outmsg.send(Udp);
  Udp.endPacket();
}

void loop() {
  mesh.update();

  int packetSize= Udp.parsePacket();
  if (packetSize) {
    OSCMessage inMsg;
    while (packetSize--) {
      inMsg.fill(Udp.read());
    }
    if (!inMsg.hasError()) {
      outIP= Udp.remoteIP();
      inMsg.dispatch("/ping", pingFunc);
    }
  }
}

3. After that power up the nodes and a new WiFi network should show up.

4. Connect a laptop to the new mesh network and take note of the IP number assigned.

5. Run the test code below on the laptop. It will broadcast a \ping OSC message and listen for \pong replies.

The test code is for SuperCollider but any program that can send OSC should work.

(
OSCFunc({|msg| msg.postln}, \pong);
NetAddr.broadcastFlag= true;
NetAddr("10.214.190.255", 19998).sendMsg(\ping);  //EDIT laptop ip number but leave 255 as the last number
)

The painlessMesh library will for sure come in handy when I need a network without a WiFi router, or for when trying to cover a larger area.
A major drawback though seem to be that the maximum number of nodes that can be used is really low. Apparently an ESP8266 can only handle 5 (TCP/IP) connections at the same time and an ESP32 about three times that. And that is not very many.