Open Lighting Architecture and ArtNet integration

I’m wondering whether anyone has any experience in the OLA protocol and could potentially point me in the right direction.

I’d love to be able to run a Raspberry Pi as an OLA ‘server’ and have it send commands over WiFi, have the Spark Core pick up the signal, and control RGB LED lighting through MOSFET’s connected to its PWM outputs.

So far I’ve only been able to find people successfully doing it on Arduino’s using USB, however this would need to be a WiFi (Ethernet) deal…

Any ideas?

Just took a quick look and it seems to use DMX.

There’s a DMX shield coming up but how soon… no idea…

You can search for DMX and see past threads. Haven’t seen a working one so far. Can by done on the :spark: but haven’t seen it yet.

That’s right, in this case I’m most interested about the ability to send DMX commands over Ethernet and have them picked up by the :spark:

DMX Shield sounds amazing, but that would require more hardware to get the device talking to RGB LED’s. Ideally I would love to be able to receive the commands and then trigger values on the MOSFET’s.

Not sure which you have to port but should be ArtNet

See here:

http://playground.arduino.cc/Learning/DMX

What kind of RGB LED? Must it be the DMX protocol?

We can write up something to control the RGB LEDs via a simple web app or Spark.function and get this thing running.

Makes things simpler :slight_smile:

Sure, it can probably be another protocol. My thinking was to use openHAB as the hub for my home automation, connecting to various :spark: devices around the house, and DMX over Ethernet seemed to be the easiest to implement.

Not set in stone yet though.

Fair enough. I’m not having enough motivation to do the porting since I have never used a DMX device or have no DMX device to test as well! :smiley:

I've been doing a lot of research here and decided to run an OLA server and use ArtNet to talk to the Spark devices. I've actually started putting together a script which I hope will achieve what I want.

It doesn't compile yet, but I've posted the code below. Unfortunately I seem to be getting the following errors:

In file included from ../inc/spark_wiring.h:30:0,
from ../inc/application.h:31,
from artnet_receiver.cpp:9:
../../core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning "Defaulting to Release Build" [-Wcpp]
artnet_receiver.cpp: In function 'void loop()':
artnet_receiver.cpp:56:23: error: expected primary-expression before '.' token
artnet_receiver.cpp:69:15: error: expected unqualified-id before '=' token
artnet_receiver.cpp:70:21: error: expected primary-expression before '.' token
artnet_receiver.cpp:71:8: error: expected unqualified-id before '.' token
artnet_receiver.cpp:109:28: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
make: *** [artnet_receiver.o] Error 1

/*
ArtNet-for-Spark-Core
=====================

A script to allow the Spark Core to receive DMX commands from an ArtNet server and trigger lights connected to PWM outputs.

This project is a port of the Arduino based script originally written by Christoph Guillermet.
*/

#define short_get_high_byte(x) ((HIGH_BYTE & x) >> 8)
#define short_get_low_byte(x)  (LOW_BYTE & x)
#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );

// variables set when a packet is received
byte remoteIp[4];        // holds originating IP
unsigned int remotePort; // holds originating port

// channel 
const int number_of_channels = 512; // amount of total channels
const int channel_position = 1; // start reading from this channel

// buffers
#define MaxSize 1024
char packetBuffer[MaxSize]; // store incoming data
byte buffer_dmx[number_of_channels+channel_position]; // store filetered DMX data

// artnet parameters
unsigned int localPort = 6454;      // default artnet port is UDP 6454
const int art_net_header_size=17;
const int max_packet_size=576;
char ArtNetHead[8]="Art-Net";
char OpHbyteReceive=0;
char OpLbyteReceive=0;
short is_artnet_version_1=0;
short is_artnet_version_2=0;
short seq_artnet=0;
short artnet_physical=0;
short incoming_universe=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;
boolean match_artnet=1;
short Opcode=0;
UDP Udp;

void setup() {
  //setup pins as PWM output
  pinMode(4, OUTPUT);  //check with leds + resistance in pwm
  pinMode(5, OUTPUT);  //check with leds + resistance in pwm
  pinMode(6, OUTPUT);  //check with leds + resistance in pwm
  
  //setup udp socket
  Udp.begin(localPort);
}

void loop() {
  int packetSize = UDP.parsePacket();
  
  //FIXME: test/debug check
  //if(packetSize>art_net_header_size && packetSize<=max_packet_size)//check size to avoid unneeded checks
  if(packetSize) {
    Serial.print("Packet received! (size: ");
    Serial.print(packetSize);
    Serial.print(") \n");
    Serial.print(art_net_header_size);
    Serial.print("\n");
    Serial.print(max_packet_size);
    Serial.print("\n");
    
    IPAddress = UDP.remoteIP();    
    remotePort = UDP.remotePort();
    UDP.read(packetBuffer, MaxSize);
    
    //read header
    match_artnet=1;
    for (int i=0;i<7;i++) {
      //if not corresponding, this is not an artnet packet, so we stop reading
      if(char(packetBuffer[i])!=ArtNetHead[i]) {
        match_artnet=0;break;
      } 
    } 
       
     //if its an artnet header
    if(match_artnet==1) { 
        //artnet protocole revision, not really needed
        //is_artnet_version_1=packetBuffer[10]; 
        //is_artnet_version_2=packetBuffer[11];*/
      
        //sequence of data, to avoid lost packets on routeurs
        //seq_artnet=packetBuffer[12];*/
          
        //physical port of  dmx N°
        //artnet_physical=packetBuffer[13];*/
        
      //operator code enables to know wich type of message Art-Net it is
      Opcode=bytes_to_short(packetBuffer[9],packetBuffer[8]);
       
      //if opcode is DMX type
      if(Opcode==0x5000) {
        is_opcode_is_dmx=1;is_opcode_is_artpoll=0;
      }   
       
      //if opcode is artpoll 
      else if(Opcode==0x2000) {
         is_opcode_is_artpoll=1;is_opcode_is_dmx=0;
         //( we should normally reply to it, giving ip adress of the device)
      } 
       
      //if its DMX data we will read it now
      if(is_opcode_is_dmx=1) {
         //if you need to filter DMX universes, uncomment next line to have the universe rceived
         //incoming_universe= bytes_to_short(packetBuffer[15],packetBuffer[14])
       
          //getting data from a channel position, on a precise amount of channels, this to avoid to much operation if you need only 4 channels for example
          //channel position
          for(int i=channel_position-1;i< number_of_channels;i++) {
            buffer_dmx[i]= byte(packetBuffer[i+17]);
          }
      }
    }//end of sniffing
     
    for(int k=6; k<9; k++) {
       Serial.print(buffer_dmx[k]);
       Serial.print(", ");  
    }
    Serial.println("");

    //stuff to do on PWM or whatever
    analogWrite(4,buffer_dmx[1]);  
    analogWrite(5,buffer_dmx[2]); 
    analogWrite(6,buffer_dmx[3]);      
  }  
}

Any feedback is much appreciated :slight_smile:

Just some UDP. not changed to Udp

There’s only 1 error left to read in the IPAddress = Udp.remoteIP(); It’s a 4 byte return value and it should not be read this way.

I can’t remember how they do it off hand but let me dig :smile:

/*
ArtNet-for-Spark-Core
=====================

A script to allow the Spark Core to receive DMX commands from an ArtNet server and trigger lights connected to PWM outputs.

This project is a port of the Arduino based script originally written by Christoph Guillermet.
*/

#define short_get_high_byte(x) ((HIGH_BYTE & x) >> 8)
#define short_get_low_byte(x)  (LOW_BYTE & x)
#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );

// variables set when a packet is received
byte remoteIp[4];        // holds originating IP
unsigned int remotePort; // holds originating port

// channel 
const int number_of_channels = 512; // amount of total channels
const int channel_position = 1; // start reading from this channel

// buffers
#define MaxSize 1024
char packetBuffer[MaxSize]; // store incoming data
byte buffer_dmx[number_of_channels+channel_position]; // store filetered DMX data

// artnet parameters
unsigned int localPort = 6454;      // default artnet port is UDP 6454
const int art_net_header_size=17;
const int max_packet_size=576;
char ArtNetHead[8]="Art-Net";
char OpHbyteReceive=0;
char OpLbyteReceive=0;
short is_artnet_version_1=0;
short is_artnet_version_2=0;
short seq_artnet=0;
short artnet_physical=0;
short incoming_universe=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;
boolean match_artnet=1;
short Opcode=0;
UDP Udp;

void setup() {
  //setup pins as PWM output
  pinMode(4, OUTPUT);  //check with leds + resistance in pwm
  pinMode(5, OUTPUT);  //check with leds + resistance in pwm
  pinMode(6, OUTPUT);  //check with leds + resistance in pwm

  //setup udp socket
  Udp.begin(localPort);
}

void loop() {
  int packetSize = Udp.parsePacket();

  //FIXME: test/debug check
  //if(packetSize>art_net_header_size && packetSize<=max_packet_size)//check size to avoid unneeded checks
  if(packetSize) {
    Serial.print("Packet received! (size: ");
    Serial.print(packetSize);
    Serial.print(") \n");
    Serial.print(art_net_header_size);
    Serial.print("\n");
    Serial.print(max_packet_size);
    Serial.print("\n");

     IPAddress remoteIp = Udp.remoteIP();    
    remotePort = Udp.remotePort();
    Udp.read(packetBuffer, MaxSize);

    //read header
    match_artnet=1;
    for (int i=0;i<7;i++) {
      //if not corresponding, this is not an artnet packet, so we stop reading
      if(char(packetBuffer[i])!=ArtNetHead[i]) {
        match_artnet=0;break;
      } 
    } 

     //if its an artnet header
    if(match_artnet==1) { 
        //artnet protocole revision, not really needed
        //is_artnet_version_1=packetBuffer[10]; 
        //is_artnet_version_2=packetBuffer[11];*/

        //sequence of data, to avoid lost packets on routeurs
        //seq_artnet=packetBuffer[12];*/

        //physical port of  dmx N°
        //artnet_physical=packetBuffer[13];*/

      //operator code enables to know wich type of message Art-Net it is
      Opcode=bytes_to_short(packetBuffer[9],packetBuffer[8]);

      //if opcode is DMX type
      if(Opcode==0x5000) {
        is_opcode_is_dmx=1;is_opcode_is_artpoll=0;
      }   

      //if opcode is artpoll 
      else if(Opcode==0x2000) {
         is_opcode_is_artpoll=1;is_opcode_is_dmx=0;
         //( we should normally reply to it, giving ip adress of the device)
      } 

      //if its DMX data we will read it now
      if(is_opcode_is_dmx ==1) {
         //if you need to filter DMX universes, uncomment next line to have the universe rceived
         //incoming_universe= bytes_to_short(packetBuffer[15],packetBuffer[14])

          //getting data from a channel position, on a precise amount of channels, this to avoid to much operation if you need only 4 channels for example
          //channel position
          for(int i=channel_position-1;i< number_of_channels;i++) {
            buffer_dmx[i]= byte(packetBuffer[i+17]);
          }
      }
    }//end of sniffing

    for(int k=6; k<9; k++) {
       Serial.print(buffer_dmx[k]);
       Serial.print(", ");  
    }
    Serial.println("");

    //stuff to do on PWM or whatever
    analogWrite(4,buffer_dmx[1]);  
    analogWrite(5,buffer_dmx[2]); 
    analogWrite(6,buffer_dmx[3]);      
  }  
}

@Jeff, It’s all done and you can try the code above.

Basically, just some simple typo and missing out the VAR name. Good job!

IPAddress is a class (think of it like a type in this case) and it returned by remoteIP() so you could write:

IPAddress rIP = Udp.remoteIP();  // rIP is the variable
2 Likes

@kennethlimcp & @bko – you guys are legends!

The code compiles! I will give it a go interfacing with the OLA server as soon as my :spark: arrives :smile: In the meantime I’ll try and clean it up a little. I’ve also posted the code to GitHub at https://github.com/iJaffa/ArtNet-for-Spark-Core


One thing I wanted to ask as well: I’ve noticed that in the Arduino world scripts define the below code. I’m assuming that this is not necessary in the Spark world because of the built in networking functionality. Am I correct in assuming this, or will I need to define this in my script as well?

//MAC and IP of the ethernet shield
byte mac[] = {144, 162, 218, 00, 16, 96};
byte ip[] = {192, 168, 1, 177};
1 Like

You definitely can comment those out :smile:

FYI, if you want to get more Network information from the :spark: core,

see http://docs.spark.io/#/firmware/connection-management-network

That reminds me of Network.ping() that @bko worked on which has been merged and available on the WebIDE but yet to be documented.

Will work on the docs tomorrow morning :yellow_heart:

Hi @Jeff

Normally you would not need these, but if your code really needs to use these for something you want to do, you can read both the MAC and the IP address. You never need to set them.

The IP address can be useful to know if you are debugging, so I often print it out at setup time on my LCD display.

I thought as much :slight_smile:

I’ve never been great at programming, and this is my first real go at the Arduino/Spark language, so thanks for your assistance.

I will update this thread once I have my :spark: in hand and have been able to do some real world testing of the code.

I’m hoping that I can just connect my LED strip via the MOSFET design in my other post and have it work :slight_smile:

OK, so I finally received my Spark Core today, and have managed to successfully send my code to it (although I had some real trouble trying to get it to connect to WiFi, the iOS app just did not work).

Problem is my :spark: goes into SOS mode followed by 8 blinks, so looks like it’s running out of memory.

Any reasons it’s doing this? This is the code I’m using: (also on GitHub)

/*
ArtNet-for-Spark-Core
=====================

A script to allow the Spark Core to listen for ArtNet DMX commands from an OLA server over Wi-Fi and output PWM values 
to selected pins. My hooking an RGB LED strip to three outputs it should be possible to control the strip RGB colour.

This project is a port of the Arduino based script originally written by Christoph Guillermet.

Thank you to the Spark Community for support in porting the code.
*/

#define short_get_high_byte(x) ((HIGH_BYTE & x) >> 8)
#define short_get_low_byte(x)  (LOW_BYTE & x)
#define bytes_to_short(h,l) ( ((h << 8) & 0xff00) | (l & 0x00FF) );

// variables set when a packet is received
byte remoteIp[4];			// holds originating IP
unsigned int remotePort;	// holds originating port

// channel 
const int number_of_channels = 512;	// amount of total channels
const int channel_position = 1;		// start reading from this channel

// buffers
#define MaxSize 1024
char packetBuffer[MaxSize];								// store incoming data
byte buffer_dmx[number_of_channels+channel_position];	// store filetered DMX data

// artnet parameters
unsigned int localPort = 6454;		// default artnet port is UDP 6454
const int art_net_header_size=17;
const int max_packet_size=576;
char ArtNetHead[8]="ArtNet";
char OpHbyteReceive=0;
char OpLbyteReceive=0;
short is_artnet_version_1=0;
short is_artnet_version_2=0;
short seq_artnet=0;
short artnet_physical=0;
short incoming_universe=0;
boolean is_opcode_is_dmx=0;
boolean is_opcode_is_artpoll=0;
boolean match_artnet=1;
short Opcode=0;
UDP Udp;

void setup() {
	//setup pins as PWM output
	pinMode(4, OUTPUT);	//check with leds + resistance in pwm
	pinMode(5, OUTPUT);	//check with leds + resistance in pwm
	pinMode(6, OUTPUT);	//check with leds + resistance in pwm
	
	//setup udp socket
	Udp.begin(localPort);
}

void loop() {
	int packetSize = Udp.parsePacket();
	
	//FIXME: test/debug check
	//if(packetSize>art_net_header_size && packetSize<=max_packet_size)//check size to avoid unneeded checks
	
	if(packetSize) {
		Serial.print("Packet received! (size: ");
		Serial.print(packetSize);
		Serial.print(") \n");
		Serial.print(art_net_header_size);
		Serial.print("\n");
		Serial.print(max_packet_size);
		Serial.print("\n");
		
		IPAddress remoteIp = Udp.remoteIP();
		remotePort = Udp.remotePort();
		Udp.read(packetBuffer, MaxSize);
		
		//read header
		match_artnet=1;
		for (int i=0;i<7;i++) {
			//if not corresponding, this is not an artnet packet, so we stop reading
			if(char(packetBuffer[i])!=ArtNetHead[i]) {
				match_artnet=0;break;
			}
		}
		
		//if it's an artnet header
		if(match_artnet==1) {
			//artnet protocol revision, not really needed
			//is_artnet_version_1=packetBuffer[10]; 
			//is_artnet_version_2=packetBuffer[11];
			
			//sequence of data, to avoid lost packets on routers
			//seq_artnet=packetBuffer[12];
			
			//physical port of  dmx N°
			//artnet_physical=packetBuffer[13];
			
			//operator code to know wich type of ArtNet message is received
			Opcode=bytes_to_short(packetBuffer[9],packetBuffer[8]);
			
			//if opcode is DMX type
			if(Opcode==0x5000) {
				is_opcode_is_dmx=1;is_opcode_is_artpoll=0;
			}
			
			//if opcode is artpoll
			else if(Opcode==0x2000) {
				is_opcode_is_artpoll=1;
				is_opcode_is_dmx=0;
				//we should normally reply to it, giving ip adress of the device)
			}
			
			//if its DMX data we will read it now
			if(is_opcode_is_dmx=1) {
				//if you need to filter DMX universes, uncomment next line to have the universe received
				//incoming_universe= bytes_to_short(packetBuffer[15],packetBuffer[14])
				
				//getting data from a channel position on a precise amount of channels
				//do this to avoid to much operation if for example you only need a few channels
				//channel position
				for (int i=channel_position-1;i< number_of_channels;i++) {
					buffer_dmx[i]= byte(packetBuffer[i+17]);
				}
			}
		}
		//end of sniffing
		
		for (int k=6; k<9; k++) {
			Serial.print(buffer_dmx[k]);
			Serial.print(", ");
		}
		
		Serial.println("");
		
		//stuff to do on PWM or whatever
		analogWrite(4,buffer_dmx[1]);
		analogWrite(5,buffer_dmx[2]);
		analogWrite(6,buffer_dmx[3]);
	}
}

Try lowering MaxSize.

Hey @kennethlimcp – thanks, should have updated the thread/post.

I’ve lowered maxsize, and the code runs, however for some reason it’s having trouble parsing the ArtNet data, and no matter what DMX data is being transmitted, the Spark will always read it as 0, 0, 0.

I’m trying to figure out if this is to do with the apparent issues with the UDP framework for Spark at the moment, maybe there is a better way of parsing the data. I’ve put together the following code to try and find out what the Spark is seeing from the OLA server:

unsigned int localPort = 6454;      // local port to listen on

UDP Udp;

const int UDP_TX_PACKET_MAX_SIZE=24;
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet

void setup() {
  Udp.begin(localPort);
  Serial.begin(9600);
}

void loop() {
  int packetSize = Udp.parsePacket();
  if(packetSize > 12)  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i =0; i < 4; i++) {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer,UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);
}
}

However, the only output I see in the console is:

Received packet of size 191
From 10.0.1.30, port 6454
Contents:
- ArtNet server
Received packet of size 167
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 143
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 119
From 10.0.1.30, port 6454
Contents:
A
Received packet of size 95
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 71
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 47
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 23
From 10.0.1.30, port 6454
Contents:
 
Received packet of size 14
From 10.0.1.30, port 6454
Contents:
Art-Net

The raw packets being broadcast on the network look like this:

I need to have the Spark pick out the packets coming in on port 6454 which have the blue highlighting and purple box in common (header of “Art-Net” and the Opcode “0x5000”) and pull out the red green and blue boxed values, convert to decimals, and apply this decimal to a PWM output.

@bko suggested I use client.read() instead, however I’m not sure how this works and how to use it to parse raw packet data…

1 Like

I put some starter code back in that other thread–hope it helps.

1 Like

Thanks @bko - I will give it a go tomorrow. Very helpful indeed!

1 Like

I’ve worked on it somewhat today, and this is how far I have gotten:

unsigned int localPort = 6454;

const int MaxSize=32;
char databyte[MaxSize];

UDP Udp;

void setup() {
  Udp.begin(localPort);
  Serial.begin(9600);
}

void loop() {

const char prefix[] = { 'A','r','t','-','N','e','t', 0x0, 0x0, 0x50};
#define NSKIP 8

byte x;  // three values to update
byte y;
byte z;

int prefixIdx = 0;
int skipCount = 0;
int readCount = 0;

//States
bool searching = true;
bool inPrefix = false;
bool skipping = false;
bool reading3 = false;

//...
int nbytes = Udp.parsePacket();

while (nbytes>16 && nbytes <=32) {
  Udp.read(databyte,1);
  nbytes--;
  
  if (searching) {
    if (databyte == prefix[prefixIdx]) {
      prefixIdx++;
      searching = false;
      inPrefix = true;
    }
  }
  
  else if (inPrefix) {
    if (databyte == prefix[prefixIdx]) {
      prefixIdx++;
      if (prefixIdx == sizeof(prefix)) { //done
        inPrefix = false;
        skipping = true;
	    skipCount = 0;
        prefixIdx = 0; // for next time
      } 
    } else { // stopped matching part way, see we start a new one
      prefixIdx = 0;
      if (databyte == prefix[prefixIdx]) {
        prefixIdx++;
      } else {
	inPrefix = false;
	searching = true;
      }
    }
  }
  
  else if (skipping) {
    if (skipCount++ == NSKIP) {
      reading3 = true;
      skipCount = 0;
      readCount = 0;
    }
  }
  
  else if (reading3) {
    switch (readCount) {
    case 0:
      x = databyte;
      break;
    case 1:
      y = databyte;
      break;
    case 2:
      z = databyte;
      reading3 = false;
      searching = true;
      break;
    default:
      reading3 = false;
      searching = true;
    }
    readCount++;
  }
  
  Serial.println("Data received:");
  Serial.println(x);
  Serial.println(y);
  Serial.println(z);
  
}
}

However I am getting the following compile errors:

> In file included from ../inc/spark_wiring.h:30:0,
> from ../inc/application.h:31,
> from /udp_parse.cpp:2:
> ../../core-common-lib/SPARK_Firmware_Driver/inc/config.h:12:2: warning: #warning "Defaulting to Release Build" [-Wcpp]
> /udp_parse.cpp:5:1: error: expected unqualified-id before 'else'
> /udp_parse.cpp:6:1: error: expected unqualified-id before 'else'
> /udp_parse.cpp:7:1: error: expected unqualified-id before 'else'
> /udp_parse.cpp: In function 'void loop()':
> /udp_parse.cpp:40:37: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
> /udp_parse.cpp:48:37: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
> /udp_parse.cpp:58:39: error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
> /udp_parse.cpp:78:11: error: invalid conversion from 'char*' to 'byte {aka unsigned char}' [-fpermissive]
> /udp_parse.cpp:81:11: error: invalid conversion from 'char*' to 'byte {aka unsigned char}' [-fpermissive]
> /udp_parse.cpp:84:11: error: invalid conversion from 'char*' to 'byte {aka unsigned char}' [-fpermissive]
> make: *** [/udp_parse.o] Error 1

I’ve tried byte conversion using byte(databyte) however have not had much luck. :frowning:

1 Like

Hi @Jeff

Sorry–forgot how databyte was declared. We really only need one byte now, but I left your array and just lowered the size.

unsigned int localPort = 6454;

const int MaxSize=2;
char databyte[MaxSize];

UDP Udp;

void setup() {
  Udp.begin(localPort);
  Serial.begin(9600);
}

void loop() {

const char prefix[] = { 'A','r','t','-','N','e','t', 0x0, 0x0, 0x50};
#define NSKIP 8

byte x;  // three values to update
byte y;
byte z;

int prefixIdx = 0;
int skipCount = 0;
int readCount = 0;

//States
bool searching = true;
bool inPrefix = false;
bool skipping = false;
bool reading3 = false;

//...
int nbytes = Udp.parsePacket();

while (nbytes>16 && nbytes <=32) {
  Udp.read(databyte,1);
  nbytes--;

  if (searching) {
    if (databyte[0] == prefix[prefixIdx]) {
      prefixIdx++;
      searching = false;
      inPrefix = true;
    }
  }

  else if (inPrefix) {
    if (databyte[0] == prefix[prefixIdx]) {
      prefixIdx++;
      if (prefixIdx == sizeof(prefix)) { //done
        inPrefix = false;
        skipping = true;
	    skipCount = 0;
        prefixIdx = 0; // for next time
      } 
    } else { // stopped matching part way, see we start a new one
      prefixIdx = 0;
      if (databyte[0] == prefix[prefixIdx]) {
        prefixIdx++;
      } else {
	inPrefix = false;
	searching = true;
      }
    }
  }

  else if (skipping) {
    if (skipCount++ == NSKIP) {
      reading3 = true;
      skipCount = 0;
      readCount = 0;
    }
  }

  else if (reading3) {
    switch (readCount) {
    case 0:
      x = databyte[0];
      break;
    case 1:
      y = databyte[0];
      break;
    case 2:
      z = databyte[0];
      reading3 = false;
      searching = true;
      break;
    default:
      reading3 = false;
      searching = true;
    }
    readCount++;
  }

  Serial.println("Data received:");
  Serial.println(x);
  Serial.println(y);
  Serial.println(z);

}
}
1 Like