Sending OSC signals over a closed (no internet) network

Hi all,

UPDATE

The problem was with the test network I was using to experiment with at home. The code below works great at my actual project site!

I know this topic has been covered before, particularly in the following threads:

[UDP broadcast only works when connected to the cloud, why?][1]
[How to send UDP broadcasts in MANUAL or SEMI-AUTOMATIC mode][2]
[Local Network Mode?][3]

I’ve tried the tricks offered in them, but I still can’t seem to get UDP packets to send over a closed network with no internet with the following code:

#include "simple-OSC/simple-OSC.h"

UDP udp;

IPAddress outIp(192, 168, 0, 5);//your computer IP
unsigned int outPort = 1234; //computer incoming port

int buttonPin = D2;

SYSTEM_MODE(SEMI_AUTOMATIC);

void setup()
{
    WiFi.hasCredentials();
    WiFi.setCredentials("Chipmunk", "AT2010TA2015", WPA2);
    WiFi.connect();
    
    WiFi.gatewayIP();
    
    
    udp.begin(0);
      while (!WiFi.ready())
      {
        delay(500);
    }
    Particle.process();
  Particle.process(); 
    
    pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
    int buttonState;
    buttonState = digitalRead(buttonPin);
    
    if (buttonState == HIGH) {
    
    //SEND
    OSCMessage outMessage("/Butt1");
    outMessage.addFloat(1);
    outMessage.send(udp,outIp,outPort);
    delay(100);
    }
    
    
    
    else {
    
    OSCMessage outMessage("/Butt1");
    outMessage.addFloat(0);
    outMessage.send(udp,outIp,outPort);
    delay(100);
    }
}

Any help would be greatly appreciated!

I’m not quite sure what’s wrong with your code. However, you should only set the WiFi credentials and static IP address/gateway/DNS once. The setting is extraordinarily sticky - it stays set in safe mode, during user code flash and system firmware upgrades. Setting it on every boot causes flash wear and the potential for corruption if the device is unplugged while it’s being set.

Here’s a minimal working code example of sending UDP with Wi-Fi only manual mode:

#include "Particle.h"

SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(MANUAL);

const unsigned long SEND_PERIOD_MS = 5000;
const size_t UDP_BUFFER_SIZE = 128;

enum WifiState { WIFI_STATE_NOT_CONNECTED, WIFI_STATE_CONNECTING, WIFI_STATE_CONNECTED, WIFI_STATE_RUNNING };

IPAddress serverAddr(192,168,2,4);
const int serverPort = 7123;

WifiState wifiState = WIFI_STATE_NOT_CONNECTED;
unsigned long lastSend = 0;
UDP udp;
byte udpBuffer[UDP_BUFFER_SIZE] = { 0 };
int seq = 0;

void setup() {
	Serial.begin(9600);

	WiFi.on();
}

void loop() {
	switch(wifiState) {
	case WIFI_STATE_NOT_CONNECTED:
		Serial.println("connecting");
		WiFi.connect();
		wifiState = WIFI_STATE_CONNECTING;
		break;

	case WIFI_STATE_CONNECTING:
		if (WiFi.ready()) {
			wifiState = WIFI_STATE_CONNECTED;
		}
		// The WiFi.connect() call never times out, it will keep trying forever so there's
		// no need to call WiFi.connect() again here.
		break;

	case WIFI_STATE_CONNECTED:
		// Do any one-time initialization here like calling udp.begin() or tcpServer.begin()
		Serial.println("connected");
		udp.begin(0);
		wifiState = WIFI_STATE_RUNNING;
		break;

	case WIFI_STATE_RUNNING:
		if (!WiFi.ready()) {
			Serial.println("disconnected during connected state");
			wifiState = WIFI_STATE_CONNECTING;

			// No need to call WiFi.connect() again, it will keep retrying forever
			break;
		}

		// Running with WiFi enabled here
		if (millis() - lastSend >=  SEND_PERIOD_MS) {
			lastSend = millis();

			Serial.printlnf("sending seq=%d", seq);

			snprintf((char *)udpBuffer, UDP_BUFFER_SIZE, "seq %d", seq++);

			udp.sendPacket(udpBuffer, UDP_BUFFER_SIZE, serverAddr, serverPort);
		}
		break;


	}
}

And the test server code in node.js

// Run this like:
// node server.js
var dgram = require("dgram");

var server = dgram.createSocket("udp4");

server.on("error", function (err) {
  console.log("server error:\n" + err.stack);
  server.close();
});

server.on("message", function (msg, rinfo) {
  console.log("server got: " + msg + " from " +
    rinfo.address + ":" + rinfo.port);
});

server.on("listening", function () {
  var address = server.address();
  console.log("server listening " +
      address.address + ":" + address.port);
});

server.bind(7123);

2 Likes

Thanks for the reply rickkas! That said, your code is definitely outside the realm of what I am used to; for setting up a static IP, how do I do that safely just once? Is that being handled by your server code? You’ll have to excuse my ignorance, I’m relatively new to the Particle Ecosystem, and am used to programming arduinos.

You can run the Wi-Fi and static IP initialization code once by flashing the program/sketch with it, then deleting or commenting out the WiFi setup calls; nothing complicated for that part.

Oh, got it, I see what you are saying. That makes sense! Thanks!

Still looking for advice on the rest of the code, but that was very helpful!