OSC subscriber / publisher for Arduino

ArduinoOSC

OSC subscriber / publisher for Arduino

NOTE : BREAKING API CHANGES (v0.3.x or later)

  • almost all apis has have changed and got much simpler
  • dropped support for OscSerial (recommend to use MsgPacketizer for much smaller packet size)

Feature

  • simple usage
    • flexible callback registration with lambda
    • directly binding osc packet to values
    • osc packet sending in one-line
    • publishing osc packet in one-line
  • support basic OSC types based on oscpkt
    • TF (bool: true, false)
    • i (int32_t)
    • h (int64_t)
    • f (float)
    • d (double)
    • s (string)
    • b (bundle)
  • support pattern-matching (wildcards)
  • does NOT support timestamp values.

Usage

Include ArduinoOSC

Please include #include "ArduinoOSC.h first.

If you use the board which has both WiFi and Ethernet, you can't use #include <ArduinoOSC.h>. Please replace it with #include <ArduinoOSCWiFi.h> or #include <ArduinoOSCEther.h> depending on the interface you want to use.

// For the boards which can use ether WiFi or Ethernet
#include <ArduinoOSC.h>
// OR use WiFi on the board which can use both WiFi and Ethernet
#include <ArduinoOSCWiFi.h>
// OR use Ethenet on the board which can use both WiFi and Ethernet
#include <ArduinoOSCEther.h>

Following examples use OscWiFi. To use with Ethernet, please change OscWiFi to OscEther.

One-Line Subscriber / Publisher

#include <ArduinoOSCWiFi.h>
// #include <ArduinoOSC.h> // you can use this if your borad supports only WiFi or Ethernet

int i; float f; String s;

void setup() {
    // WiFi stuff
    WiFi.begin(ssid, pwd);
    WiFi.config(ip, gateway, subnet);

    // subscribe osc packet and directly bind to variable
    OscWiFi.subscribe(bind_port, "/bind/values", i, f, s);

    // publish osc packet in 30 times/sec (default)
    OscWiFi.publish(host, publish_port, "/publish/value", i, f, s);
    // function can also be published
    OscWiFi.publish(host, publish_port, "/publish/func", &millis, &micros)
        ->setFrameRate(1); // and publish it once per second
}

void loop() {
    OscWiFi.update(); // should be called to subscribe + publish osc
}

Bind OSC to Lambda Arguments and One-Line Send

void setup() {
    // WiFi stuff
    // ...

    OscWiFi.subscribe(bind_port, "/lambda/bind/args",
        [&](int& i, float& f, String& s) {
            Serial.print("/lambda/bind/args ");
            Serial.print(i); Serial.print(" ");
            Serial.print(f); Serial.print(" ");
            Serial.print(s); Serial.println();

            // One-Line Send Back
            OscWiFi.send(host, send_port, "/reply", i, f, s);
        }
    );
}

void loop() {
    OscWiFi.update(); // should be called
}

Other Way to Subscribe

// OscMessage as lambda argument
OscWiFi.subscribe(recv_port, "/lambda/msg",
    [](const OscMessage& m) {
        Serial.print(m.remoteIP()); Serial.print(" ");
        Serial.print(m.remotePort()); Serial.print(" ");
        Serial.print(m.size()); Serial.print(" ");
        Serial.print(m.address()); Serial.print(" ");
        Serial.print(m.arg<int>(0)); Serial.print(" ");
        Serial.print(m.arg<float>(1)); Serial.print(" ");
        Serial.print(m.arg<String>(2)); Serial.println();
    }
);

// wildcard address pattern matching
OscWiFi.subscribe(recv_port, "/wildcard/*/test",
    [](const OscMessage& m) {
        Serial.print(m.remoteIP()); Serial.print(" ");
        Serial.print(m.remotePort()); Serial.print(" ");
        Serial.print(m.size()); Serial.print(" ");
        Serial.print(m.address()); Serial.print(" ");
        Serial.print(m.arg<int>(0)); Serial.println();
    }
);

// no arguments
OscWiFi.subscribe(recv_port, "/need/reply", []() {
    OscWiFi.send(host, send_port, "/reply", i, f, s);
});

// pre-defined callback
OscWiFi.subscribe(recv_port, "/callback", onOscReceived);

Supported Platform

This library currently supports following platforms and interfaces. Please feel free to send PR or request for more board support!

WiFi

  • ESP32
  • ESP8266
  • Arduino Uno WiFi Rev2
  • Arduino MKR VIDOR 4000
  • Arduino MKR WiFi 1010
  • Arduino MKR WiFi 1000
  • Arduino Nano 33 IoT

Ethernet

  • Almost all platforms which has Ethernet library

Limitation and Options for NO-STL Boards

STL is used to handle packet data by default, but for following boards/architectures, ArxContainer is used to store the packet data because STL can not be used for such boards. The storage size of such boards for packets, queue of packets, max packet binary size, callbacks are limited.

  • AVR
  • megaAVR

Usage Recommendation for Arduino Uno (and other boards with tiny memory size)

For the boards which has tiny memory size (e.g. Arduino Uno), I reccomend not to use publisher and subscriber. Though you can use them on such boards, such rich functions requires more memory. The reccomended way is to use send and parse manually. The example is shown in examples/arduino/OscEtherUno, so please consider to use it.

#include <ArduinoOSCEther.h>
// #include <ArduinoOSC.h> // you can use this because Uno supports only Ethernet

// required to use manual packet parsing
OscEtherServer server(recv_port);
OscEtherClient client;
// OscEtherClient client(local_port);  // set the local port of client manually (default: 9)


void setup() {
    Ethernet.begin(mac, ip);
}

void loop() {
    // manual sending instead of publishers
    static uint32_t prev_func_ms = millis();
    if (millis() > prev_func_ms + 500) {
        client.send(host, publish_port, "/publish/func", millis(), micros());
        prev_func_ms = millis();
    }

    // manual parsing instead of subscribers
    if (server.parse()) {
        const OscMessage* msg = server.message();

        if (msg->address() == "/need/reply") {
            Serial.println("/need/reply");
            int i = millis();
            float f = (float)micros() / 1000.f;
            String s = F("hello");
            client.send(host, send_port, "/reply", i, f, s);
        }
    }
}

Memory Management (only for NO-STL Boards)

As mentioned above, for such boards like Arduino Uno, the storage sizes are limited. And of course you can manage them by defining following macros. But these default values are optimized for such boards, please be careful not to excess your boards storage/memory.

#define ARDUINOOSC_MAX_MSG_ARGUMENT_SIZE 8
#define ARDUINOOSC_MAX_MSG_BYTE_SIZE 128
#define ARDUINOOSC_MAX_MSG_QUEUE_SIZE 1
#define ARDUINOOSC_MAX_PUBLISH_DESTINATION 4
#define ARDUINOOSC_MAX_SUBSCRIBE_ADDRESS_PER_PORT 4
#define ARDUINOOSC_MAX_SUBSCRIBE_PORTS 2

Enable Bundle for NO-STL Boards

OSC bundle option is disabled for such boards. If you want to use that, please use this macro and handle packets manually. ArduinoOSC does not use bundle by default.

#define ARDUINOOSC_ENABLE_BUNDLE
#define ARDUINOOSC_MAX_MSG_BUNDLE_SIZE 128

Enable Debug Logger

You can see the debug log when you insert following line before include ArduinoOSC.

#define ARDUINOOSC_DEBUGLOG_ENABLE
#include <ArduinoOSC.h>

Embedded Libraries

Special Thanks

License

MIT

Owner
Hideaki Tai
Hardware Engineer
Hideaki Tai
Comments
  • Receive an Udp Osc message as reply to a previus Osc message

    Receive an Udp Osc message as reply to a previus Osc message

    Hi, I would like to interact with my digital mixer using Osc messages. I'm able to send message, but I cannot read any reply form the server.

    My scenario is the following: I send an OSC message to mixer (192.168.1.33 port 10024) and Mixer reply to my Arduino IP (192.168.1.199) but the mixer use the Remote UDP Port that Arduino use for send the message.

    WhatsApp Image 2021-03-18 at 14 57 05

    I sniff some udp packet and seems that OscEther.send use a local port (random probably, port 9 in my test) that is not releated to OscEtherServer [server.begin(serverPort)]. Can you give me some advices?

    #include <ArduinoOSC.h>
    
    
    byte myMac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
    byte myIp[]  = { 192, 168, 1, 199 };
    
    int serverPort  = 8888; //this is not right in my scenario
    
    
    const char* mixerIp = "192.168.1.33";
    const int mixerPort = 10024;
    
    
    // required to use manual packet parsing
    OscEtherServer server;
    
    void setup()
    {
        Serial.begin(115200);
        Ethernet.begin(myMac, myIp);
        server.begin(serverPort); // <--- I should listen reply on the same port that I use to send UDP request...
    }
    
    
    void loop()
    {
        // manual sending instead of publishers
        static uint32_t prev_func_ms = millis();
        if (millis() > prev_func_ms + 2500)
        {
            prev_func_ms = millis();
            OscEther.send(mixerIp, mixerPort, "/info");
        }
    
     
        // manual parsing instead of subscribers
        if (server.parse())
        { 
          // I did not receive nothing on "serverPort" because is not releated with Oscether.send() Udp Local Port...
            Serial.println("server.parse()");
            const OscMessage* msg = server.message();
        }
    }
    
  • Sometimes `subscribe` is unstable in ESP32

    Sometimes `subscribe` is unstable in ESP32

    こんにちは。最高に使いやすいライブラリの公開、ありがとうございます。

    タイトルにもあります通り、Subscribeの応答速度がpublishの有無とインターバルによって変化してしまうような挙動をしております。こちらは使用上仕方のないことなのでしょうか?

    具体的には、ESP32にて以下のようなコードを実行しているのですが、ESP32がOSCメッセージを受信した際に即時に応答せず、パケットが1秒程度溜まってから排出されるような挙動をしてしまっています。なおOSCメッセージはMaxから100msecごと/foo Xの形で送っており、Xは100msecごとに0.01ずつインクリメントされるようになっています。 コード

    void setup() {
      delay(1000);
      WiFi.begin(ssid, pwd);
      WiFi.config(ip, gateway, subnet);
    
      while(WiFi.status() != WL_CONNECTED) { Serial.print("."); delay(500); }
      Serial.begin(115200);
    
      OscWiFi.subscribe(port_a, "/foo",
            [&](const float& f)  {
                Serial.print("/foo ");
                Serial.println(f);
            }
        );
    
      OscWiFi.publish("224.0.0.1", port_b, "/active", 1.0) -> setIntervalMsec(1000.0f);
    }
    
    void loop() {
        OscWiFi.update(); 
    }
    

    スクリーンショット 2020-06-13 10 15 19

    OscWiFi.publishの行をコメントアウトしてみたところ、以下のようになり、連続的な受信がままならない状況になりました。

    スクリーンショット 2020-06-13 10 23 11

    publishとsubscribeに何らかの因果を感じたので、今度はpublishをアンコメントし、intervalを1 msecにしてみたところ、subscribeの応答速度が大変早まりました。

    可能であればintervalを1000msのまま、subscribeはなるべく高速に使用したいのですが、そのようなことは可能なのでしょうか?お忙しいところお手数をおかけしますがご教授いただけると幸いです。 よろしくおねがいします。

  • Core Panic

    Core Panic

    Whenever I send osc to my ESP32 using Arduino OSC it crashes. I get the following error.

    lambda : 192.168.0.169 61084 1 /lambda 3 Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled. Core 1 register dump: PC : 0x4014298c PS : 0x00060830 A0 : 0x800d1eda A1 : 0x3ffb1ee0
    A2 : 0x00000003 A3 : 0x00000001 A4 : 0x3ffbbaa8 A5 : 0x00000001
    A6 : 0x3ffba72b A7 : 0x3ffafedb A8 : 0x00000004 A9 : 0x00000000
    A10 : 0x00000000 A11 : 0x3f4000ba A12 : 0x0000000a A13 : 0x3ffafedb
    A14 : 0x00ff0000 A15 : 0xff000000 SAR : 0x00000010 EXCCAUSE: 0x0000001c
    EXCVADDR: 0x00000003 LBEG : 0x4014298c LEND : 0x4014299a LCOUNT : 0x00000003

    Backtrace: 0x4014298c:0x3ffb1ee0 0x400d1ed7:0x3ffb1f10 0x400d3381:0x3ffb1f40 0x400d33b6:0x3ffb1f90 0x400d4b11:0x3ffb1fb0 0x4008e6f1:0x3ffb1fd0

  • Enabled wifi support for some arduino boards #9

    Enabled wifi support for some arduino boards #9

    I enabled wifi support for some arduino boards (Arduino UNO WiFi Rev.2, MKR WiFi 1010 ...) as described in #9 .

    Not totally sure if they also could handle bundles, so I let it deactivated.

  • ESP32 AP mode

    ESP32 AP mode

    Hi,

    Static mode work perfectly but I don't have any success to use ArduinoOSC with AP mode wifi. there's a way to use ArduinoSOC with AP mode with a ESP32 ?

    Bets & thx for your great library ;)

    Chris

  • Compilation error when including ArduinoOSC.h in a C++ header

    Compilation error when including ArduinoOSC.h in a C++ header

    This isn't my post but it summarizes the issue well:

    https://www.gitmemory.com/issue/hideakitai/ArduinoOSC/5/529086213

    I tried using a forward declaration in my header ("class OscMessage") but then realized it's not allowed with "OscMessage &m" using the "address of" operator.

    Thanks for the lib!

  • Unable to parse or post any OSC message on WiFi

    Unable to parse or post any OSC message on WiFi

    I'm using an Arduino MKR Wifi 1010 module, and the example with the WiFi.h library. I'm able to connect to the network, set an ip address, and make publish messages (although they are only 2 messages per second, not the 30hz mentioned). However when I send OSC back to the Arduino IP, on any of the reports, it doesn't print out any data to the serial monitor.

    I'm wondering how to parse and post custom messages to 3rd party applications like TouchDesigner.

  • Event-driven approach to receiving OSC data rather than polling?

    Event-driven approach to receiving OSC data rather than polling?

    This is more of a feature request. Would it be possible to implement a more event-driven approach to receiving OSC data rather than polling parse()? I'm implementing freertos tasks which trigger FastLED, so avoiding creation of a periodic polling task would waste less cpu time.

    Here's a similar discussion: https://github.com/espressif/arduino-esp32/issues/1995

    p.s. no pressure on this one, just a feature request. I'll let you know how it goes with polling.

  • Buffer gets overwritten while decoding

    Buffer gets overwritten while decoding

    Is it possible that a buffer can get overwritten while still parsed?

    Sending following messages (quite fast behind each other). The number indicates the length in bytes:

    /iad/led/color iii 36
    /iad/imu/rpy i 24
    

    On the arduino, when falling into this error-check (regarding too few arguments), I print out the current buffer (storage.end() - storage.begin()), first the byte value and then the corresponding charachter:

    Size: 36
    47|/ 105|i 97|a 100|d 47|/ 105|i 109|m 117|u 47|/ 114|r 112|p 121|y 0|� 0|� 0|� 0|� 44|, 105|i 0|� 0|� 0|� 0|� 1| 101|e 0|� 0|� 0|� 49|1 0|� 0|� 0|� 0|� 0|� 0|� 0|� -1|⸮
    

    Well, that looks like the 36 byte buffer of the /iad/led/color packet, but filled with the values of the /iad/imu/rpy packet.

    I am super confused now...either I am not reading the right data for debug or there is some concurrent work going on. Sending the same package behind each other of course makes no difference, because we are overwriting the same buffer.

    After one of these messages, the stream.parsePacket() returns always 65524.

    Here an example sketch, which let me recreate this problem:

    #include <SPI.h>
    #include <WiFiNINA.h>
    #include <WiFiUdp.h>
    #include <utility/wifi_drv.h>
    
    #include <ArduinoOSC.h>
    
    #include "secrets.h"
    
    #define OscWiFi ArduinoOSC::Manager<WiFiUDP>::getInstance()
    
    #define IN_PORT 8000
    
    int keyIndex = 0;
    int status = WL_IDLE_STATUS;
    
    void setup() {
      Serial.begin(9600);
    
      // connect wifi
      while (status != WL_CONNECTED) {
        Serial.print("Connecting to SSID: ");
        Serial.println(ssid);
        status = WiFi.begin(ssid, keyIndex, pass);
      }
    
      // setup inputs
      OscWiFi.subscribe(IN_PORT, "/test/rgb", [&](int& r, int& g, int& b) {
        // do nothing
      });
    
      OscWiFi.subscribe(IN_PORT, "/test/w", [&](int& w) {
        // do nothing
      });
    
    
      Serial.println("everything setup to test!");
    }
    
    void loop() {
      OscWiFi.update();
    }
    

    Just send (with any OSC client) /test/rgb and /test/w alternately in a high framerate.

  • Compilation error when including ArduinoOSC.h in several headers

    Compilation error when including ArduinoOSC.h in several headers

    I have a class that can handle OscMessage so I need to include ArduinoOSC.h in the header of this class. This leads to compilation error (multiple definition of Packetizer::crc8 and ArduinoOSC::match). To solve this problem, I created two files (ArduinoOSC.cpp next to ArduinoOSC.h and Packetizer.cpp next to Packetizer.h), included their respective headers and moved the code from the problematic functions in the corresponding cpp. It now compiles and works well even though I don't fully understand why. Here are the concerned files. ArduinoOSC_modif.zip

    Thanks for this great and useful work by the way.

  • Is it possible to have a non-fixed IP ?

    Is it possible to have a non-fixed IP ?

    Thanks fro making this library. It works great.

    Is there an option to get an IP assigned via DHCP? Or do I always need to hard code one?

    Thanks for any advice.

  • run ArduinoOSCEther with OLIMEX ESP32 POE

    run ArduinoOSCEther with OLIMEX ESP32 POE

    Hi, I try to use OLIMEX ESP32 POE with ArduinoOSCEther. With this device ETH_LAN8720 example works through ETH.h provide by library Espressif ESP32 but it doesn't work with Ehternet.h used with ArduinoOSCEther.

    There's a way to run ArduinoOSC through Ethernet with kind of this board ?

    best ;)

Arduino Arduino library for the CloudStorage server project. The library provides easy access to server-stored values and operations.

Arduino-CloudStorage Arduino/ESP8266 library that allows you to easly store and retreive data from a remote (cloud) storage in a key/value fashion. Cl

Jan 30, 2022
Arduino library for making an IHC in or output module using an Arduino

Introduction This is an Arduino library for making an IHC in or output module using an Arduino. (IHC controller is a home automation controller made b

Mar 26, 2020
ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT Cloud

ArduinoIoTCloud What? The ArduinoIoTCloud library is the central element of the firmware enabling certain Arduino boards to connect to the Arduino IoT

Dec 16, 2022
Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames.
Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames.

107-Arduino-MCP2515 Arduino library for controlling the MCP2515 in order to receive/transmit CAN frames. This library is prepared to interface easily

Nov 16, 2022
Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.
Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages.

107-Arduino-NMEA-Parser Arduino library for interfacing with any GPS, GLONASS, Galileo or GNSS module and interpreting its NMEA messages. This library

Jan 1, 2023
Arduino library for providing a convenient C++ interface for accessing UAVCAN.
Arduino library for providing a convenient C++ interface for accessing UAVCAN.

107-Arduino-UAVCAN Arduino library for providing a convenient C++ interface for accessing UAVCAN (v1.0-beta) utilizing libcanard. This library works f

Jan 2, 2023
A RESTful environment for Arduino

aREST Overview A simple library that implements a REST API for Arduino & the ESP8266 WiFi chip. It is designed to be universal and currently supports

Dec 29, 2022
Arduino web server library.

aWOT Arduino web server library. Documentation 1. Getting started Hello World Basic routing Application generator Serving static files 2. Guide Routin

Jan 4, 2023
Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485
Arduino, esp32 and esp8266 library for ABB (ex PowerOne) Aurora Inverter, implement a full methods to retrieve data from the Inverter via RS-485

ABB Aurora protocol You can refer the complete documentation on my site ABB Aurora PV inverter library for Arduino, esp8266 and esp32 I create this li

Nov 22, 2022
MCP2515 CAN Controller Driver for Arduino

MCP2515 CAN Controller Library for Arduino Compatibility with the ACAN library This library is fully compatible with the Teensy 3.x ACAN library https

Dec 13, 2022
Arduino library for the MCP2515 CAN Controller

MCP2515 CAN Controller Library for Arduino Compatibility with the ACAN library This library is fully compatible with the Teensy 3.x ACAN library https

Dec 18, 2022
Arduino CAN driver for MCP2517FD CAN Controller (in CAN 2.0B mode)

MCP2517FD CAN Controller Library for Arduino (in CAN 2.0B mode) Compatibility with the other ACAN libraries This library is fully compatible with the

Dec 22, 2022
Distribution of Arduino driver for MCP2517FD CAN controller (CANFD mode)

MCP2517FD and MCP2518FD CAN Controller Library for Arduino (in CAN FD mode) Compatibility with the other ACAN libraries This library is fully compatib

Dec 21, 2022
CAN / CANFD Arduino Library for Teensy 4.0

CAN Library for Teensy 4.0 / 4.1 It handles Controller Area Network (CAN) for CAN1, CAN2 and CAN3, and Controller Area Network with Flexible Data (CAN

Dec 9, 2022
Unified interface for selecting hardware or software SPI implementations on Arduino platforms

AceSPI Unified interface for selecting hardware or software SPI implementations on Arduino platforms. The code was initially part of the AceSegment li

Oct 22, 2021
Unified interface for selecting different implementations for communicating with a TM1637 LED controller chip on Arduino platforms

AceTMI Unified interface for communicating with a TM1637 LED controller chip on Arduino platforms. The code was initially part of the AceSegment libra

Feb 2, 2022
Unified interface for selecting different I2C implementations on Arduino platforms

AceWire Wrapper classes that provide a simple, unified interface for different I2C implementations on Arduino platforms. The code was initially part o

Dec 14, 2022
Analog Devices Analog Digital Converter AD7173 Arduino library

AD7173-Arduino Analog Devices AD7173 analog digital converter Arduino library Mostly tested setup for this library: 1007 data rate external crystal co

Nov 20, 2022
Arduino library for nRF51822-based Adafruit Bluefruit LE modules

This library is for all nRF51 based Adafruit Bluefruit LE modules that use SPI or UART. Current nRF51 based Bluefruit LE products include: Bluefruit L

Nov 6, 2022