Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
246 changes: 127 additions & 119 deletions Artnet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,20 +24,28 @@ THE SOFTWARE.

#include <Artnet.h>

Artnet::Artnet() {}
Artnet::Artnet()
{
setArtDmxCallback(nullptr);
setArtPollCallback(nullptr);
setArtSyncCallback(nullptr);
}

void Artnet::begin(byte mac[], byte ip[])
{
#if !defined(ARDUINO_SAMD_ZERO) && !defined(ESP8266) && !defined(ESP32)
Ethernet.begin(mac,ip);
#endif

Udp.begin(ART_NET_PORT);
begin();
}

void Artnet::begin()
{
Udp.begin(ART_NET_PORT);
if (udp.listen(ART_NET_PORT))
{
udp.onPacket(std::bind(&Artnet::parsePacket, this, std::placeholders::_1));
}

}

void Artnet::setBroadcastAuto(IPAddress ip, IPAddress sn)
Expand All @@ -64,118 +72,117 @@ void Artnet::setBroadcast(IPAddress bc)
broadcast = bc;
}

uint16_t Artnet::read()
void Artnet::parsePacket(AsyncUDPPacket _packet)
{
packetSize = Udp.parsePacket();

remoteIP = Udp.remoteIP();
if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
{
Udp.read(artnetPacket, MAX_BUFFER_ARTNET);

// Check that packetID is "Art-Net" else ignore
for (byte i = 0 ; i < 8 ; i++)
{
if (artnetPacket[i] != ART_NET_ID[i])
return 0;
}

opcode = artnetPacket[8] | artnetPacket[9] << 8;

if (opcode == ART_DMX)
{
sequence = artnetPacket[12];
incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START, remoteIP);
return ART_DMX;
}
if (opcode == ART_POLL)
{
//fill the reply struct, and then send it to the network's broadcast address
Serial.print("POLL from ");
Serial.print(remoteIP);
Serial.print(" broadcast addr: ");
Serial.println(broadcast);

#if !defined(ARDUINO_SAMD_ZERO) && !defined(ESP8266) && !defined(ESP32)
IPAddress local_ip = Ethernet.localIP();
#else
IPAddress local_ip = WiFi.localIP();
#endif
node_ip_address[0] = local_ip[0];
node_ip_address[1] = local_ip[1];
node_ip_address[2] = local_ip[2];
node_ip_address[3] = local_ip[3];

sprintf((char *)id, "Art-Net");
memcpy(ArtPollReply.id, id, sizeof(ArtPollReply.id));
memcpy(ArtPollReply.ip, node_ip_address, sizeof(ArtPollReply.ip));

ArtPollReply.opCode = ART_POLL_REPLY;
ArtPollReply.port = ART_NET_PORT;

memset(ArtPollReply.goodinput, 0x08, 4);
memset(ArtPollReply.goodoutput, 0x80, 4);
memset(ArtPollReply.porttypes, 0xc0, 4);

uint8_t shortname [18];
uint8_t longname [64];
sprintf((char *)shortname, "artnet arduino");
sprintf((char *)longname, "Art-Net -> Arduino Bridge");
memcpy(ArtPollReply.shortname, shortname, sizeof(shortname));
memcpy(ArtPollReply.longname, longname, sizeof(longname));

ArtPollReply.etsaman[0] = 0;
ArtPollReply.etsaman[1] = 0;
ArtPollReply.verH = 1;
ArtPollReply.ver = 0;
ArtPollReply.subH = 0;
ArtPollReply.sub = 0;
ArtPollReply.oemH = 0;
ArtPollReply.oem = 0xFF;
ArtPollReply.ubea = 0;
ArtPollReply.status = 0xd2;
ArtPollReply.swvideo = 0;
ArtPollReply.swmacro = 0;
ArtPollReply.swremote = 0;
ArtPollReply.style = 0;

ArtPollReply.numbportsH = 0;
ArtPollReply.numbports = 4;
ArtPollReply.status2 = 0x08;

ArtPollReply.bindip[0] = node_ip_address[0];
ArtPollReply.bindip[1] = node_ip_address[1];
ArtPollReply.bindip[2] = node_ip_address[2];
ArtPollReply.bindip[3] = node_ip_address[3];

uint8_t swin[4] = {0x01,0x02,0x03,0x04};
uint8_t swout[4] = {0x01,0x02,0x03,0x04};
for(uint8_t i = 0; i < 4; i++)
do // once
{
packetSize = _packet.length();
remoteIP = _packet.remoteIP();
uint8_t * artnetPacket = _packet.data();

if (packetSize > MAX_BUFFER_ARTNET || packetSize < 1)
{
// invalid size of PDU
break;
}

// Check that packetID is "Art-Net" else ignore
for (byte i = 0 ; i < 8 ; i++)
{
if (artnetPacket[i] != ART_NET_ID[i])
{
// Serial.println("Artnet: Invalid packetId");
break;
}
}

opcode = artnetPacket[8] | (artnetPacket[9] << 8);

if (opcode == ART_DMX)
{
sequence = artnetPacket[12];
incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

if (nullptr != artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START, remoteIP);
break;
}

if (opcode == ART_POLL)
{
ArtPollReply.swout[i] = swout[i];
ArtPollReply.swin[i] = swin[i];
if (nullptr != artDmxPollCallback) (*artDmxPollCallback)(broadcast);

IPAddress local_ip = _packet.localIP();

node_ip_address[0] = local_ip[0];
node_ip_address[1] = local_ip[1];
node_ip_address[2] = local_ip[2];
node_ip_address[3] = local_ip[3];

struct artnet_reply_s ArtPollReply;

sprintf((char *)id, "Art-Net");
memcpy(ArtPollReply.id, id, sizeof(ArtPollReply.id));
memcpy(ArtPollReply.ip, node_ip_address, sizeof(ArtPollReply.ip));

ArtPollReply.opCode = ART_POLL_REPLY;
ArtPollReply.port = ART_NET_PORT;

memset(ArtPollReply.goodinput, 0x08, 4);
memset(ArtPollReply.goodoutput, 0x80, 4);
memset(ArtPollReply.porttypes, 0xc0, 4);

uint8_t shortname [18];
uint8_t longname [64];
sprintf((char *)shortname, "artnet arduino");
sprintf((char *)longname, "Art-Net -> Arduino Bridge");
memcpy(ArtPollReply.shortname, shortname, sizeof(shortname));
memcpy(ArtPollReply.longname, longname, sizeof(longname));

ArtPollReply.etsaman[0] = 0;
ArtPollReply.etsaman[1] = 0;
ArtPollReply.verH = 1;
ArtPollReply.ver = 0;
ArtPollReply.subH = 0;
ArtPollReply.sub = 0;
ArtPollReply.oemH = 0;
ArtPollReply.oem = 0xFF;
ArtPollReply.ubea = 0;
ArtPollReply.status = 0xd2;
ArtPollReply.swvideo = 0;
ArtPollReply.swmacro = 0;
ArtPollReply.swremote = 0;
ArtPollReply.style = 0;

ArtPollReply.numbportsH = 0;
ArtPollReply.numbports = 4;
ArtPollReply.status2 = 0x08;

ArtPollReply.bindip[0] = node_ip_address[0];
ArtPollReply.bindip[1] = node_ip_address[1];
ArtPollReply.bindip[2] = node_ip_address[2];
ArtPollReply.bindip[3] = node_ip_address[3];

uint8_t swin[4] = {0x01,0x02,0x03,0x04};
uint8_t swout[4] = {0x01,0x02,0x03,0x04};
for(uint8_t i = 0; i < 4; i++)
{
ArtPollReply.swout[i] = swout[i];
ArtPollReply.swin[i] = swin[i];
}
sprintf((char *)ArtPollReply.nodereport, "%i DMX output universes active.", ArtPollReply.numbports);
udp.broadcastTo((uint8_t*)&ArtPollReply, sizeof(ArtPollReply), ART_NET_PORT);

break;
}
sprintf((char *)ArtPollReply.nodereport, "%i DMX output universes active.", ArtPollReply.numbports);
Udp.beginPacket(broadcast, ART_NET_PORT);//send the packet to the broadcast address
Udp.write((uint8_t *)&ArtPollReply, sizeof(ArtPollReply));
Udp.endPacket();

return ART_POLL;
}
if (opcode == ART_SYNC)
{
if (artSyncCallback) (*artSyncCallback)(remoteIP);
return ART_SYNC;
}
}
else
{
return 0;
}
return 0;

if (opcode == ART_SYNC)
{
if (nullptr != artSyncCallback) (*artSyncCallback)(remoteIP);
break;
}

} while(false);
}

void Artnet::printPacketHeader()
Expand All @@ -192,11 +199,12 @@ void Artnet::printPacketHeader()
Serial.println(sequence);
}

void Artnet::printPacketContent()
void Artnet::printPacketContent(uint8_t * artnetPacket)
{
for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
Serial.print(artnetPacket[i], DEC);
Serial.print(" ");
}
Serial.println('\n');
for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++)
{
Serial.print(artnetPacket[i], DEC);
Serial.print(" ");
}
Serial.println('\n');
}
34 changes: 15 additions & 19 deletions Artnet.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ THE SOFTWARE.
#include <WiFi101.h>
#include <WiFiUdp.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <ESPAsyncUDP.h>
#elif defined(ESP32)
#include <WiFi.h>
#include <WiFiUdp.h>
#include <AsyncUDP.h>
#elif defined(ARDUINO_TEENSY41)
#include <NativeEthernet.h>
#include <NativeEthernetUdp.h>
Expand Down Expand Up @@ -105,15 +103,8 @@ class Artnet
void setBroadcastAuto(IPAddress ip, IPAddress sn);
void setBroadcast(byte bc[]);
void setBroadcast(IPAddress bc);
uint16_t read();
void printPacketHeader();
void printPacketContent();

// Return a pointer to the start of the DMX data
inline uint8_t* getDmxFrame(void)
{
return artnetPacket + ART_DMX_START;
}
void printPacketContent(uint8_t * ArtnetPacket);

inline uint16_t getOpcode(void)
{
Expand Down Expand Up @@ -145,6 +136,11 @@ class Artnet
artDmxCallback = fptr;
}

inline void setArtPollCallback(void (*fptr)(IPAddress broadcastIP))
{
artDmxPollCallback = fptr;
}

inline void setArtSyncCallback(void (*fptr)(IPAddress remoteIP))
{
artSyncCallback = fptr;
Expand All @@ -153,15 +149,10 @@ class Artnet
private:
uint8_t node_ip_address[4];
uint8_t id[8];
#if defined(ARDUINO_SAMD_ZERO) || defined(ESP8266) || defined(ESP32)
WiFiUDP Udp;
#else
EthernetUDP Udp;
#endif
struct artnet_reply_s ArtPollReply;
AsyncUDP udp; // AsyncUDP



uint8_t artnetPacket[MAX_BUFFER_ARTNET];
uint16_t packetSize;
IPAddress broadcast;
uint16_t opcode;
Expand All @@ -170,7 +161,12 @@ class Artnet
uint16_t dmxDataLength;
IPAddress remoteIP;
void (*artDmxCallback)(uint16_t universe, uint16_t length, uint8_t sequence, uint8_t* data, IPAddress remoteIP);
void (*artDmxPollCallback)(IPAddress broadcastIP);
void (*artSyncCallback)(IPAddress remoteIP);

// Packet parser callback
void parsePacket(AsyncUDPPacket _packet);

};

#endif