WiFlasher/wiflash_esp32/sacn.cpp

133 lines
3.9 KiB
C++

/*
ESPAsyncE131.cpp
Project: ESPAsyncE131 - Asynchronous E.131 (sACN) library for Arduino ESP8266 and ESP32
Copyright (c) 2019 Shelby Merrick
http://www.forkineye.com
This program is provided free for you to use in any way that you wish,
subject to the laws and regulations where you are using it. Due diligence
is strongly suggested before using this code. Please give credit where due.
The Author makes no warranty of any kind, express or implied, with regard
to this program or the documentation contained in this document. The
Author shall not be liable in any event for incidental or consequential
damages in connection with, or arising out of, the furnishing, performance
or use of these programs.
*/
#include <Arduino.h>
#include <WiFi.h>
#include "sacn.h"
// E1.17 ACN Packet Identifier
const uint8_t ESPAsyncE131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
ESPAsyncE131::ESPAsyncE131(uint8_t buffers) {
stats.num_packets = 0;
stats.packet_errors = 0;
_handler = NULL;
}
bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe) {
bool success = false;
if (type == E131_UNICAST)
success = initUnicast();
if (type == E131_MULTICAST)
success = initMulticast(universe);
return success;
}
bool ESPAsyncE131::initUnicast() {
bool success = false;
if (udp.listen(E131_DEFAULT_PORT)) {
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
std::placeholders::_1));
success = true;
}
return success;
}
bool ESPAsyncE131::initMulticast(uint16_t universe) {
bool success = false;
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
((universe >> 0) & 0xff));
if (udp.listenMulticast(address, E131_DEFAULT_PORT)) {
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
std::placeholders::_1));
success = true;
}
return success;
}
void ESPAsyncE131::parsePacket(AsyncUDPPacket _packet) {
e131_error_t error = ERROR_NONE;
sbuff = reinterpret_cast<e131_packet_t *>(_packet.data());
if (memcmp(sbuff->acn_id, ESPAsyncE131::ACN_ID, sizeof(sbuff->acn_id)))
error = ERROR_ACN_ID;
else if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
error = ERROR_VECTOR_ROOT;
else if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
error = ERROR_VECTOR_FRAME;
else if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
error = ERROR_VECTOR_DMP;
else if (sbuff->property_values[0] != 0)
error = ERROR_IGNORE;
if (error == ERROR_NONE) {
stats.num_packets++;
stats.last_clientIP = _packet.remoteIP();
stats.last_clientPort = _packet.remotePort();
stats.last_seen = millis();
if (_handler) {
_handler(sbuff);
}
} else if (error == ERROR_IGNORE) {
// Do nothing
} else {
if (Serial)
dumpError(sbuff, error);
stats.packet_errors++;
}
}
void ESPAsyncE131::dumpError(e131_packet_t *packet, e131_error_t error) {
switch (error) {
case ERROR_ACN_ID:
Serial.print(F("INVALID PACKET ID: "));
for (uint i = 0; i < sizeof(ACN_ID); i++)
Serial.print(packet->acn_id[i], HEX);
Serial.println("");
break;
case ERROR_PACKET_SIZE:
Serial.println(F("INVALID PACKET SIZE: "));
break;
case ERROR_VECTOR_ROOT:
Serial.print(F("INVALID ROOT VECTOR: 0x"));
Serial.println(htonl(packet->root_vector), HEX);
break;
case ERROR_VECTOR_FRAME:
Serial.print(F("INVALID FRAME VECTOR: 0x"));
Serial.println(htonl(packet->frame_vector), HEX);
break;
case ERROR_VECTOR_DMP:
Serial.print(F("INVALID DMP VECTOR: 0x"));
Serial.println(packet->dmp_vector, HEX);
case ERROR_NONE:
break;
case ERROR_IGNORE:
break;
}
}
void ESPAsyncE131::onPacket(E131PacketHandlerFunction callback)
{
_handler = callback;
}