OSC: UDP <-> SLIP gateway.
Posted: Sat Aug 15, 2015 1:41 am
Hello ESP8266 community.
I recently had need to forward OSC messages from TouchOSC http://hexler.net/software/touchosc to an Arduino (Teensy 3.1) based project. The ideal solution was of course to have esp8266 acting as a gateway to one of the available UARTs.
I found the CNMAT OSC library https://github.com/CNMAT/OSC but this didn't work correctly out of the box. After looking through this forum I found ameisso's port of the library https://github.com/ameisso/OSCLib-for-ESP8266 with which I was able to successfully receive and respond to messages from TouchOSC.
For some reason it does not include the SLIPEncodedSerial part of the CNMAT library. If you simply take SLIPEncodedSerial.cpp and SLIPEncodedSerial.h from CNMAT and put it into the ameisso library folder, serial OSC messages work as well.
After some initial issues with losing bytes while reading SLIP messages I was able to get the thing working. So far this implementation has proved to be pretty reliable (*EDIT* see note below about message flooding). I'm now enjoying building up control surfaces in TouchOSC for use on the Teensy3.1.
Some issues I am aware of:
*EDIT* 2/9/2015: now rate limited to approx. 100 messages/second, excess messages are simply discarded. This seems more stable now. Ideally I would only discard duplicate messages, but this works well enough for my current needs.
Regards, mogs
I recently had need to forward OSC messages from TouchOSC http://hexler.net/software/touchosc to an Arduino (Teensy 3.1) based project. The ideal solution was of course to have esp8266 acting as a gateway to one of the available UARTs.
I found the CNMAT OSC library https://github.com/CNMAT/OSC but this didn't work correctly out of the box. After looking through this forum I found ameisso's port of the library https://github.com/ameisso/OSCLib-for-ESP8266 with which I was able to successfully receive and respond to messages from TouchOSC.
For some reason it does not include the SLIPEncodedSerial part of the CNMAT library. If you simply take SLIPEncodedSerial.cpp and SLIPEncodedSerial.h from CNMAT and put it into the ameisso library folder, serial OSC messages work as well.
After some initial issues with losing bytes while reading SLIP messages I was able to get the thing working. So far this implementation has proved to be pretty reliable (*EDIT* see note below about message flooding). I'm now enjoying building up control surfaces in TouchOSC for use on the Teensy3.1.
Some issues I am aware of:
- Serial->UDP messages are being truncated to approximately 500 bytes, this could cause issues with long messages/bundles.
OSCBundles are not implemented, at this time I have not experimented with bundles at all.
*EDIT* esp8266 module will crash if messages come in too quickly.
*EDIT* 2/9/2015: now rate limited to approx. 100 messages/second, excess messages are simply discarded. This seems more stable now. Ideally I would only discard duplicate messages, but this works well enough for my current needs.
Code: Select all
// This program converts UDP OSC messages into SLIP Serial OSC messages on the ESP8266 wifi board
// At the moment there is no OSC bundle support, not sure I need it at the moment
#include <ESP8266WiFi.h>
#include <WiFiUDP.h>
#include <OSCMessage.h>
#include <SLIPEncodedSerial.h>
int status = WL_IDLE_STATUS;
const char* ssid = "wifissid"; // your network name (SSID)
const char* pass = "wifipassword"; // your network password
int localPort = 8000;
int destPort = 9000;
IPAddress outIp(192, 168, 2, 39); //default IP, will change with received udp
WiFiUDP Udp;
SLIPEncodedSerial SLIPSerial(Serial);
void setup()
{
SLIPSerial.begin(115200);
WiFi.begin(ssid, pass);
int tries=0;
while (WiFi.status() != WL_CONNECTED) {
delay(500);
tries++;
if (tries > 30){
break;
}
}
Udp.begin(localPort);
}
void loop(){ // read=udp->serial, write=serial->udp
int rd,wr;
OSCMessage rMsg, wMsg;
//static unsigned int bp = 0;
static bool packet = 0;
static unsigned long tr = 0, tw = 0;
if((rd = Udp.parsePacket())>0){
if(tr - micros() > 10000) {
outIp = Udp.remoteIP();
while (rd--)
rMsg.fill(Udp.read());
if(!rMsg.hasError()) {
SLIPSerial.beginPacket();
rMsg.send(SLIPSerial);
SLIPSerial.endPacket();
}
rMsg.empty();
} else {
while (rd--)
Udp.read();
}
tr = micros();
}
while(!SLIPSerial.endofPacket()) {
if(wr = SLIPSerial.available()>0){
tw = micros();
if(!packet)
packet = 1;
while(wr--) { //this needs a byte limit
wMsg.fill(SLIPSerial.read());
//if(++bp >= 512) break; //packets seem to get truncated about here anyway
}
}
if((micros() - tw) > 10000) break; //Timeout for no eoP()
//if(bp >= 512) break; //break again
}
if(packet) {
if(!wMsg.hasError()) {
Udp.beginPacket(outIp, destPort);
wMsg.send(Udp);
Udp.endPacket();
packet = 0;
}
}
}
Regards, mogs