Migrate to ESPAsyncE131
This commit is contained in:
parent
3aacb7150d
commit
6eae6db46b
@ -31,6 +31,7 @@ lib_deps_external =
|
|||||||
FastLED@3.3.2
|
FastLED@3.3.2
|
||||||
NeoPixelBus@2.5.1
|
NeoPixelBus@2.5.1
|
||||||
ESPAsyncTCP@1.2.0
|
ESPAsyncTCP@1.2.0
|
||||||
|
ESPAsyncUDP@1.1.0
|
||||||
AsyncTCP@1.0.3
|
AsyncTCP@1.0.3
|
||||||
Esp Async WebServer@1.2.0
|
Esp Async WebServer@1.2.0
|
||||||
#ArduinoJson@5.13.5
|
#ArduinoJson@5.13.5
|
||||||
|
@ -58,3 +58,9 @@ Uses Linearicons by Perxis!
|
|||||||
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
Join the Discord [server](https://discord.gg/KuqP7NE) to discuss everything about WLED!
|
||||||
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
|
You can also send me mails to [dev.aircoookie@gmail.com](mailto:dev.aircoookie@gmail.com).
|
||||||
If WLED really brightens up your every day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
If WLED really brightens up your every day, you can [![](https://img.shields.io/badge/send%20me%20a%20small%20gift-paypal-blue.svg?style=flat-square)](https://paypal.me/aircoookie)
|
||||||
|
|
||||||
|
*Disclaimer:*
|
||||||
|
If you are sensitive to photoeleptic seizures it is not recommended that you use this software.
|
||||||
|
In case you still want to try, don't use strobe, lighting or noise modes or high effect speed settings.
|
||||||
|
As per the MIT license, i assume no liability for any damage to you or any other person or equipment.
|
||||||
|
|
||||||
|
@ -388,6 +388,7 @@ class WS2812FX {
|
|||||||
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
|
color_from_palette(uint16_t, bool, bool, uint8_t, uint8_t pbri = 255),
|
||||||
color_blend(uint32_t,uint32_t,uint8_t),
|
color_blend(uint32_t,uint32_t,uint8_t),
|
||||||
gamma32(uint32_t),
|
gamma32(uint32_t),
|
||||||
|
getLastShow(void),
|
||||||
getPixelColor(uint16_t),
|
getPixelColor(uint16_t),
|
||||||
getColor(void);
|
getColor(void);
|
||||||
|
|
||||||
|
@ -76,7 +76,6 @@ void WS2812FX::service() {
|
|||||||
if(doShow) {
|
if(doShow) {
|
||||||
yield();
|
yield();
|
||||||
show();
|
show();
|
||||||
_lastShow = millis();
|
|
||||||
}
|
}
|
||||||
_triggered = false;
|
_triggered = false;
|
||||||
}
|
}
|
||||||
@ -243,6 +242,7 @@ void WS2812FX::show(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bus->Show();
|
bus->Show();
|
||||||
|
_lastShow = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::trigger() {
|
void WS2812FX::trigger() {
|
||||||
@ -438,6 +438,10 @@ WS2812FX::Segment* WS2812FX::getSegments(void) {
|
|||||||
return _segments;
|
return _segments;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t WS2812FX::getLastShow(void) {
|
||||||
|
return _lastShow;
|
||||||
|
}
|
||||||
|
|
||||||
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) {
|
void WS2812FX::setSegment(uint8_t n, uint16_t i1, uint16_t i2) {
|
||||||
if (n >= MAX_NUM_SEGMENTS) return;
|
if (n >= MAX_NUM_SEGMENTS) return;
|
||||||
Segment& seg = _segments[n];
|
Segment& seg = _segments[n];
|
||||||
|
@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* E131.cpp
|
|
||||||
*
|
|
||||||
* Project: E131 - E.131 (sACN) library for Arduino
|
|
||||||
* Copyright (c) 2015 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 "E131.h"
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
/* E1.17 ACN Packet Identifier */
|
|
||||||
const byte E131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
|
|
||||||
|
|
||||||
/* Constructor */
|
|
||||||
E131::E131() {
|
|
||||||
#ifdef NO_DOUBLE_BUFFER
|
|
||||||
memset(pbuff1.raw, 0, sizeof(pbuff1.raw));
|
|
||||||
packet = &pbuff1;
|
|
||||||
pwbuff = packet;
|
|
||||||
#else
|
|
||||||
memset(pbuff1.raw, 0, sizeof(pbuff1.raw));
|
|
||||||
memset(pbuff2.raw, 0, sizeof(pbuff2.raw));
|
|
||||||
packet = &pbuff1;
|
|
||||||
pwbuff = &pbuff2;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
stats.num_packets = 0;
|
|
||||||
stats.packet_errors = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void E131::initUnicast() {
|
|
||||||
udp.begin(E131_DEFAULT_PORT);
|
|
||||||
}
|
|
||||||
|
|
||||||
void E131::initMulticast(uint16_t universe, uint8_t n) {
|
|
||||||
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
|
|
||||||
((universe >> 0) & 0xff));
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
|
||||||
ip4_addr_t ifaddr;
|
|
||||||
ip4_addr_t multicast_addr;
|
|
||||||
|
|
||||||
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
|
||||||
for (uint8_t i = 1; i < n; i++) {
|
|
||||||
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
|
||||||
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
|
||||||
& 0xff)));
|
|
||||||
igmp_joingroup(&ifaddr, &multicast_addr);
|
|
||||||
}
|
|
||||||
udp.beginMulticast(address, E131_DEFAULT_PORT);
|
|
||||||
#else
|
|
||||||
ip_addr_t ifaddr;
|
|
||||||
ip_addr_t multicast_addr;
|
|
||||||
|
|
||||||
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
|
||||||
for (uint8_t i = 1; i < n; i++) {
|
|
||||||
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
|
||||||
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
|
||||||
& 0xff)));
|
|
||||||
igmp_joingroup(&ifaddr, &multicast_addr);
|
|
||||||
}
|
|
||||||
udp.beginMulticast(WiFi.localIP(), address, E131_DEFAULT_PORT);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
void E131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
|
|
||||||
if (type == E131_UNICAST)
|
|
||||||
initUnicast();
|
|
||||||
if (type == E131_MULTICAST)
|
|
||||||
initMulticast(universe, n);
|
|
||||||
}
|
|
@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* E131.h
|
|
||||||
*
|
|
||||||
* Project: E131 - E.131 (sACN) library for Arduino
|
|
||||||
* Copyright (c) 2015 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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef E131_H_
|
|
||||||
#define E131_H_
|
|
||||||
|
|
||||||
#include "Arduino.h"
|
|
||||||
|
|
||||||
/* Network interface detection. WiFi for ESP8266 and Ethernet for AVR */
|
|
||||||
#if defined (ARDUINO_ARCH_ESP8266)
|
|
||||||
# include <ESP8266WiFi.h>
|
|
||||||
# define NO_DOUBLE_BUFFER
|
|
||||||
#elif defined (ARDUINO_ARCH_ESP32)
|
|
||||||
# include <WiFi.h>
|
|
||||||
#endif
|
|
||||||
# include <WiFiUdp.h>
|
|
||||||
# include <lwip/ip_addr.h>
|
|
||||||
# include <lwip/igmp.h>
|
|
||||||
# define _UDP WiFiUDP
|
|
||||||
|
|
||||||
/* Defaults */
|
|
||||||
#define E131_DEFAULT_PORT 5568
|
|
||||||
|
|
||||||
/* E1.31 Packet Offsets */
|
|
||||||
#define E131_ROOT_PREAMBLE_SIZE 0
|
|
||||||
#define E131_ROOT_POSTAMBLE_SIZE 2
|
|
||||||
#define E131_ROOT_ID 4
|
|
||||||
#define E131_ROOT_FLENGTH 16
|
|
||||||
#define E131_ROOT_VECTOR 18
|
|
||||||
#define E131_ROOT_CID 22
|
|
||||||
|
|
||||||
#define E131_FRAME_FLENGTH 38
|
|
||||||
#define E131_FRAME_VECTOR 40
|
|
||||||
#define E131_FRAME_SOURCE 44
|
|
||||||
#define E131_FRAME_PRIORITY 108
|
|
||||||
#define E131_FRAME_RESERVED 109
|
|
||||||
#define E131_FRAME_SEQ 111
|
|
||||||
#define E131_FRAME_OPT 112
|
|
||||||
#define E131_FRAME_UNIVERSE 113
|
|
||||||
|
|
||||||
#define E131_DMP_FLENGTH 115
|
|
||||||
#define E131_DMP_VECTOR 117
|
|
||||||
#define E131_DMP_TYPE 118
|
|
||||||
#define E131_DMP_ADDR_FIRST 119
|
|
||||||
#define E131_DMP_ADDR_INC 121
|
|
||||||
#define E131_DMP_COUNT 123
|
|
||||||
#define E131_DMP_DATA 125
|
|
||||||
|
|
||||||
/* E1.31 Packet Structure */
|
|
||||||
typedef union {
|
|
||||||
struct {
|
|
||||||
/* Root Layer */
|
|
||||||
uint16_t preamble_size;
|
|
||||||
uint16_t postamble_size;
|
|
||||||
uint8_t acn_id[12];
|
|
||||||
uint16_t root_flength;
|
|
||||||
uint32_t root_vector;
|
|
||||||
uint8_t cid[16];
|
|
||||||
|
|
||||||
/* Frame Layer */
|
|
||||||
uint16_t frame_flength;
|
|
||||||
uint32_t frame_vector;
|
|
||||||
uint8_t source_name[64];
|
|
||||||
uint8_t priority;
|
|
||||||
uint16_t reserved;
|
|
||||||
uint8_t sequence_number;
|
|
||||||
uint8_t options;
|
|
||||||
uint16_t universe;
|
|
||||||
|
|
||||||
/* DMP Layer */
|
|
||||||
uint16_t dmp_flength;
|
|
||||||
uint8_t dmp_vector;
|
|
||||||
uint8_t type;
|
|
||||||
uint16_t first_address;
|
|
||||||
uint16_t address_increment;
|
|
||||||
uint16_t property_value_count;
|
|
||||||
uint8_t property_values[513];
|
|
||||||
} __attribute__((packed));
|
|
||||||
|
|
||||||
uint8_t raw[638];
|
|
||||||
} e131_packet_t;
|
|
||||||
|
|
||||||
/* Error Types */
|
|
||||||
typedef enum {
|
|
||||||
ERROR_NONE,
|
|
||||||
ERROR_IGNORE,
|
|
||||||
ERROR_ACN_ID,
|
|
||||||
ERROR_PACKET_SIZE,
|
|
||||||
ERROR_VECTOR_ROOT,
|
|
||||||
ERROR_VECTOR_FRAME,
|
|
||||||
ERROR_VECTOR_DMP
|
|
||||||
} e131_error_t;
|
|
||||||
|
|
||||||
/* E1.31 Listener Types */
|
|
||||||
typedef enum {
|
|
||||||
E131_UNICAST,
|
|
||||||
E131_MULTICAST
|
|
||||||
} e131_listen_t;
|
|
||||||
|
|
||||||
/* Status structure */
|
|
||||||
typedef struct {
|
|
||||||
uint32_t num_packets;
|
|
||||||
uint32_t packet_errors;
|
|
||||||
IPAddress last_clientIP;
|
|
||||||
uint16_t last_clientPort;
|
|
||||||
} e131_stats_t;
|
|
||||||
|
|
||||||
class E131 {
|
|
||||||
private:
|
|
||||||
/* Constants for packet validation */
|
|
||||||
static const uint8_t ACN_ID[];
|
|
||||||
static const uint32_t VECTOR_ROOT = 4;
|
|
||||||
static const uint32_t VECTOR_FRAME = 2;
|
|
||||||
static const uint8_t VECTOR_DMP = 2;
|
|
||||||
|
|
||||||
e131_packet_t pbuff1; /* Packet buffer */
|
|
||||||
#ifndef NO_DOUBLE_BUFFER
|
|
||||||
e131_packet_t pbuff2; /* Double buffer */
|
|
||||||
#endif
|
|
||||||
e131_packet_t *pwbuff; /* Pointer to working packet buffer */
|
|
||||||
_UDP udp; /* UDP handle */
|
|
||||||
|
|
||||||
/* Internal Initializers */
|
|
||||||
void initUnicast();
|
|
||||||
void initMulticast(uint16_t universe, uint8_t n = 1);
|
|
||||||
|
|
||||||
public:
|
|
||||||
uint8_t *data; /* Pointer to DMX channel data */
|
|
||||||
uint16_t universe; /* DMX Universe of last valid packet */
|
|
||||||
e131_packet_t *packet; /* Pointer to last valid packet */
|
|
||||||
e131_stats_t stats; /* Statistics tracker */
|
|
||||||
|
|
||||||
E131();
|
|
||||||
|
|
||||||
/* Generic UDP listener, no physical or IP configuration */
|
|
||||||
void begin(e131_listen_t type, uint16_t universe = 1, uint8_t n = 1);
|
|
||||||
|
|
||||||
/* Main packet parser */
|
|
||||||
inline uint16_t parsePacket() {
|
|
||||||
e131_error_t error;
|
|
||||||
uint16_t retval = 0;
|
|
||||||
|
|
||||||
int size = udp.parsePacket();
|
|
||||||
if (size) {
|
|
||||||
udp.readBytes(pwbuff->raw, size);
|
|
||||||
error = validate();
|
|
||||||
if (!error) {
|
|
||||||
#ifndef NO_DOUBLE_BUFFER
|
|
||||||
e131_packet_t *swap = packet;
|
|
||||||
packet = pwbuff;
|
|
||||||
pwbuff = swap;
|
|
||||||
#endif
|
|
||||||
universe = htons(packet->universe);
|
|
||||||
data = packet->property_values + 1;
|
|
||||||
retval = htons(packet->property_value_count) - 1;
|
|
||||||
stats.num_packets++;
|
|
||||||
stats.last_clientIP = udp.remoteIP();
|
|
||||||
stats.last_clientPort = udp.remotePort();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Packet validater */
|
|
||||||
inline e131_error_t validate() {
|
|
||||||
if (memcmp(pwbuff->acn_id, ACN_ID, sizeof(pwbuff->acn_id)))
|
|
||||||
return ERROR_ACN_ID;
|
|
||||||
if (htonl(pwbuff->root_vector) != VECTOR_ROOT)
|
|
||||||
return ERROR_VECTOR_ROOT;
|
|
||||||
if (htonl(pwbuff->frame_vector) != VECTOR_FRAME)
|
|
||||||
return ERROR_VECTOR_FRAME;
|
|
||||||
if (pwbuff->dmp_vector != VECTOR_DMP)
|
|
||||||
return ERROR_VECTOR_DMP;
|
|
||||||
if (pwbuff->property_values[0] != 0)
|
|
||||||
return ERROR_IGNORE;
|
|
||||||
return ERROR_NONE;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif /* E131_H_ */
|
|
116
wled00/src/dependencies/e131/ESPAsyncE131.cpp
Normal file
116
wled00/src/dependencies/e131/ESPAsyncE131.cpp
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* 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 "ESPAsyncE131.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
// E1.17 ACN Packet Identifier
|
||||||
|
const byte ESPAsyncE131::ACN_ID[12] = { 0x41, 0x53, 0x43, 0x2d, 0x45, 0x31, 0x2e, 0x31, 0x37, 0x00, 0x00, 0x00 };
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
ESPAsyncE131::ESPAsyncE131(e131_packet_callback_function callback) {
|
||||||
|
_callback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Public begin() members
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
bool ESPAsyncE131::begin(e131_listen_t type, uint16_t universe, uint8_t n) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
if (type == E131_UNICAST)
|
||||||
|
success = initUnicast();
|
||||||
|
if (type == E131_MULTICAST)
|
||||||
|
success = initMulticast(universe, n);
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Private init() members
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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, uint8_t n) {
|
||||||
|
bool success = false;
|
||||||
|
|
||||||
|
IPAddress address = IPAddress(239, 255, ((universe >> 8) & 0xff),
|
||||||
|
((universe >> 0) & 0xff));
|
||||||
|
|
||||||
|
if (udp.listenMulticast(address, E131_DEFAULT_PORT)) {
|
||||||
|
ip4_addr_t ifaddr;
|
||||||
|
ip4_addr_t multicast_addr;
|
||||||
|
|
||||||
|
ifaddr.addr = static_cast<uint32_t>(WiFi.localIP());
|
||||||
|
for (uint8_t i = 1; i < n; i++) {
|
||||||
|
multicast_addr.addr = static_cast<uint32_t>(IPAddress(239, 255,
|
||||||
|
(((universe + i) >> 8) & 0xff), (((universe + i) >> 0)
|
||||||
|
& 0xff)));
|
||||||
|
igmp_joingroup(&ifaddr, &multicast_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
udp.onPacket(std::bind(&ESPAsyncE131::parsePacket, this,
|
||||||
|
std::placeholders::_1));
|
||||||
|
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Packet parsing - Private
|
||||||
|
//
|
||||||
|
/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
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;
|
||||||
|
if (htonl(sbuff->root_vector) != ESPAsyncE131::VECTOR_ROOT)
|
||||||
|
error = ERROR_VECTOR_ROOT;
|
||||||
|
if (htonl(sbuff->frame_vector) != ESPAsyncE131::VECTOR_FRAME)
|
||||||
|
error = ERROR_VECTOR_FRAME;
|
||||||
|
if (sbuff->dmp_vector != ESPAsyncE131::VECTOR_DMP)
|
||||||
|
error = ERROR_VECTOR_DMP;
|
||||||
|
if (sbuff->property_values[0] != 0)
|
||||||
|
error = ERROR_IGNORE;
|
||||||
|
|
||||||
|
if (!error) {
|
||||||
|
_callback(sbuff, _packet.remoteIP());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
151
wled00/src/dependencies/e131/ESPAsyncE131.h
Normal file
151
wled00/src/dependencies/e131/ESPAsyncE131.h
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* ESPAsyncE131.h
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef ESPASYNCE131_H_
|
||||||
|
#define ESPASYNCE131_H_
|
||||||
|
|
||||||
|
#ifdef ESP32
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <AsyncUDP.h>
|
||||||
|
#elif defined (ESP8266)
|
||||||
|
#include <ESPAsyncUDP.h>
|
||||||
|
#include <ESP8266WiFi.h>
|
||||||
|
#include <ESP8266WiFiMulti.h>
|
||||||
|
#else
|
||||||
|
#error Platform not supported
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <lwip/ip_addr.h>
|
||||||
|
#include <lwip/igmp.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#if LWIP_VERSION_MAJOR == 1
|
||||||
|
typedef struct ip_addr ip4_addr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Defaults
|
||||||
|
#define E131_DEFAULT_PORT 5568
|
||||||
|
|
||||||
|
// E1.31 Packet Offsets
|
||||||
|
#define E131_ROOT_PREAMBLE_SIZE 0
|
||||||
|
#define E131_ROOT_POSTAMBLE_SIZE 2
|
||||||
|
#define E131_ROOT_ID 4
|
||||||
|
#define E131_ROOT_FLENGTH 16
|
||||||
|
#define E131_ROOT_VECTOR 18
|
||||||
|
#define E131_ROOT_CID 22
|
||||||
|
|
||||||
|
#define E131_FRAME_FLENGTH 38
|
||||||
|
#define E131_FRAME_VECTOR 40
|
||||||
|
#define E131_FRAME_SOURCE 44
|
||||||
|
#define E131_FRAME_PRIORITY 108
|
||||||
|
#define E131_FRAME_RESERVED 109
|
||||||
|
#define E131_FRAME_SEQ 111
|
||||||
|
#define E131_FRAME_OPT 112
|
||||||
|
#define E131_FRAME_UNIVERSE 113
|
||||||
|
|
||||||
|
#define E131_DMP_FLENGTH 115
|
||||||
|
#define E131_DMP_VECTOR 117
|
||||||
|
#define E131_DMP_TYPE 118
|
||||||
|
#define E131_DMP_ADDR_FIRST 119
|
||||||
|
#define E131_DMP_ADDR_INC 121
|
||||||
|
#define E131_DMP_COUNT 123
|
||||||
|
#define E131_DMP_DATA 125
|
||||||
|
|
||||||
|
// E1.31 Packet Structure
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
// Root Layer
|
||||||
|
uint16_t preamble_size;
|
||||||
|
uint16_t postamble_size;
|
||||||
|
uint8_t acn_id[12];
|
||||||
|
uint16_t root_flength;
|
||||||
|
uint32_t root_vector;
|
||||||
|
uint8_t cid[16];
|
||||||
|
|
||||||
|
// Frame Layer
|
||||||
|
uint16_t frame_flength;
|
||||||
|
uint32_t frame_vector;
|
||||||
|
uint8_t source_name[64];
|
||||||
|
uint8_t priority;
|
||||||
|
uint16_t reserved;
|
||||||
|
uint8_t sequence_number;
|
||||||
|
uint8_t options;
|
||||||
|
uint16_t universe;
|
||||||
|
|
||||||
|
// DMP Layer
|
||||||
|
uint16_t dmp_flength;
|
||||||
|
uint8_t dmp_vector;
|
||||||
|
uint8_t type;
|
||||||
|
uint16_t first_address;
|
||||||
|
uint16_t address_increment;
|
||||||
|
uint16_t property_value_count;
|
||||||
|
uint8_t property_values[513];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
uint8_t raw[638];
|
||||||
|
} e131_packet_t;
|
||||||
|
|
||||||
|
// Error Types
|
||||||
|
typedef enum {
|
||||||
|
ERROR_NONE,
|
||||||
|
ERROR_IGNORE,
|
||||||
|
ERROR_ACN_ID,
|
||||||
|
ERROR_PACKET_SIZE,
|
||||||
|
ERROR_VECTOR_ROOT,
|
||||||
|
ERROR_VECTOR_FRAME,
|
||||||
|
ERROR_VECTOR_DMP
|
||||||
|
} e131_error_t;
|
||||||
|
|
||||||
|
// E1.31 Listener Types
|
||||||
|
typedef enum {
|
||||||
|
E131_UNICAST,
|
||||||
|
E131_MULTICAST
|
||||||
|
} e131_listen_t;
|
||||||
|
|
||||||
|
// new packet callback
|
||||||
|
typedef void (*e131_packet_callback_function) (e131_packet_t* p, IPAddress clientIP);
|
||||||
|
|
||||||
|
class ESPAsyncE131 {
|
||||||
|
private:
|
||||||
|
// Constants for packet validation
|
||||||
|
static const uint8_t ACN_ID[];
|
||||||
|
static const uint32_t VECTOR_ROOT = 4;
|
||||||
|
static const uint32_t VECTOR_FRAME = 2;
|
||||||
|
static const uint8_t VECTOR_DMP = 2;
|
||||||
|
|
||||||
|
e131_packet_t *sbuff; // Pointer to scratch packet buffer
|
||||||
|
AsyncUDP udp; // AsyncUDP
|
||||||
|
|
||||||
|
// Internal Initializers
|
||||||
|
bool initUnicast();
|
||||||
|
bool initMulticast(uint16_t universe, uint8_t n = 1);
|
||||||
|
|
||||||
|
// Packet parser callback
|
||||||
|
void parsePacket(AsyncUDPPacket _packet);
|
||||||
|
|
||||||
|
e131_packet_callback_function _callback = nullptr;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ESPAsyncE131(e131_packet_callback_function callback);
|
||||||
|
|
||||||
|
// Generic UDP listener, no physical or IP configuration
|
||||||
|
bool begin(e131_listen_t type, uint16_t universe = 1, uint8_t n = 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ESPASYNCE131_H_
|
@ -68,7 +68,7 @@
|
|||||||
#ifndef WLED_DISABLE_BLYNK
|
#ifndef WLED_DISABLE_BLYNK
|
||||||
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
#include "src/dependencies/blynk/BlynkSimpleEsp.h"
|
||||||
#endif
|
#endif
|
||||||
#include "src/dependencies/e131/E131.h"
|
#include "src/dependencies/e131/ESPAsyncE131.h"
|
||||||
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
|
#include "src/dependencies/async-mqtt-client/AsyncMqttClient.h"
|
||||||
#include "src/dependencies/json/AsyncJson-v6.h"
|
#include "src/dependencies/json/AsyncJson-v6.h"
|
||||||
#include "src/dependencies/json/ArduinoJson-v6.h"
|
#include "src/dependencies/json/ArduinoJson-v6.h"
|
||||||
@ -100,7 +100,7 @@
|
|||||||
|
|
||||||
|
|
||||||
//version code in format yymmddb (b = daily build)
|
//version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 1911161
|
#define VERSION 1911181
|
||||||
char versionString[] = "0.8.7-dev";
|
char versionString[] = "0.8.7-dev";
|
||||||
|
|
||||||
|
|
||||||
@ -197,8 +197,7 @@ bool receiveDirect = true; //receive UDP realtime
|
|||||||
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
|
bool arlsDisableGammaCorrection = true; //activate if gamma correction is handled by the source
|
||||||
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
|
bool arlsForceMaxBri = false; //enable to force max brightness if source has very dark colors that would be black
|
||||||
|
|
||||||
bool e131Enabled = true; //settings for E1.31 (sACN) protocol
|
uint16_t e131Universe = 1; //settings for E1.31 (sACN) protocol
|
||||||
uint16_t e131Universe = 1;
|
|
||||||
bool e131Multicast = false;
|
bool e131Multicast = false;
|
||||||
|
|
||||||
char mqttDeviceTopic[33] = ""; //main MQTT topic (individual per device, default is wled/mac)
|
char mqttDeviceTopic[33] = ""; //main MQTT topic (individual per device, default is wled/mac)
|
||||||
@ -434,10 +433,17 @@ AsyncWebServer server(80);
|
|||||||
AsyncClient* hueClient = NULL;
|
AsyncClient* hueClient = NULL;
|
||||||
AsyncMqttClient* mqtt = NULL;
|
AsyncMqttClient* mqtt = NULL;
|
||||||
|
|
||||||
|
//function prototypes
|
||||||
|
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
|
||||||
|
void handleE131Packet(e131_packet_t*, IPAddress);
|
||||||
|
|
||||||
|
#define E131_MAX_UNIVERSE_COUNT 7
|
||||||
|
|
||||||
//udp interface objects
|
//udp interface objects
|
||||||
WiFiUDP notifierUdp, rgbUdp;
|
WiFiUDP notifierUdp, rgbUdp;
|
||||||
WiFiUDP ntpUdp;
|
WiFiUDP ntpUdp;
|
||||||
E131* e131;
|
ESPAsyncE131 e131(handleE131Packet);
|
||||||
|
bool e131NewData = false;
|
||||||
|
|
||||||
//led fx library object
|
//led fx library object
|
||||||
WS2812FX strip = WS2812FX();
|
WS2812FX strip = WS2812FX();
|
||||||
@ -469,11 +475,6 @@ WS2812FX strip = WS2812FX();
|
|||||||
#include "SPIFFSEditor.h"
|
#include "SPIFFSEditor.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
//function prototypes
|
|
||||||
void serveMessage(AsyncWebServerRequest*,uint16_t,String,String,byte);
|
|
||||||
|
|
||||||
|
|
||||||
//turns all LEDs off and restarts ESP
|
//turns all LEDs off and restarts ESP
|
||||||
void reset()
|
void reset()
|
||||||
{
|
{
|
||||||
|
@ -230,7 +230,7 @@ void initInterfaces() {
|
|||||||
if (ntpEnabled) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
if (ntpEnabled) ntpConnected = ntpUdp.begin(ntpLocalPort);
|
||||||
|
|
||||||
initBlynk(blynkApiKey);
|
initBlynk(blynkApiKey);
|
||||||
initE131();
|
Serial.println(e131.begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe, E131_MAX_UNIVERSE_COUNT));
|
||||||
reconnectHue();
|
reconnectHue();
|
||||||
initMqtt();
|
initMqtt();
|
||||||
interfacesInited = true;
|
interfacesInited = true;
|
||||||
|
@ -86,36 +86,26 @@ void arlsLock(uint32_t timeoutMs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void initE131(){
|
void handleE131Packet(e131_packet_t* p, IPAddress clientIP){
|
||||||
if (WLED_CONNECTED && e131Enabled)
|
|
||||||
{
|
|
||||||
if (e131 == nullptr) e131 = new E131();
|
|
||||||
e131->begin((e131Multicast) ? E131_MULTICAST : E131_UNICAST , e131Universe);
|
|
||||||
} else {
|
|
||||||
e131Enabled = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void handleE131(){
|
|
||||||
//E1.31 protocol support
|
//E1.31 protocol support
|
||||||
if(WLED_CONNECTED && e131Enabled) {
|
uint16_t uni = htons(p->universe);
|
||||||
uint16_t len = e131->parsePacket();
|
if (uni < e131Universe || uni >= e131Universe + E131_MAX_UNIVERSE_COUNT) return;
|
||||||
if (!len || e131->universe < e131Universe || e131->universe > e131Universe +4) return;
|
|
||||||
|
uint16_t len = htons(p->property_value_count) -1;
|
||||||
len /= 3; //one LED is 3 DMX channels
|
len /= 3; //one LED is 3 DMX channels
|
||||||
|
|
||||||
uint16_t multipacketOffset = (e131->universe - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
uint16_t multipacketOffset = (uni - e131Universe)*170; //if more than 170 LEDs (510 channels), client will send in next higher universe
|
||||||
if (ledCount <= multipacketOffset) return;
|
if (ledCount <= multipacketOffset) return;
|
||||||
|
|
||||||
arlsLock(realtimeTimeoutMs);
|
arlsLock(realtimeTimeoutMs);
|
||||||
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
if (len + multipacketOffset > ledCount) len = ledCount - multipacketOffset;
|
||||||
|
|
||||||
for (uint16_t i = 0; i < len; i++) {
|
for (uint16_t i = 0; i < len; i++) {
|
||||||
int j = i * 3;
|
int j = i * 3 +1;
|
||||||
setRealtimePixel(i + multipacketOffset, e131->data[j], e131->data[j+1], e131->data[j+2], 0);
|
setRealtimePixel(i + multipacketOffset, p->property_values[j], p->property_values[j+1], p->property_values[j+2], 0);
|
||||||
}
|
|
||||||
strip.show();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
e131NewData = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -126,7 +116,12 @@ void handleNotifications()
|
|||||||
notify(notificationSentCallMode,true);
|
notify(notificationSentCallMode,true);
|
||||||
}
|
}
|
||||||
|
|
||||||
handleE131();
|
if (e131NewData && millis() - strip.getLastShow() > 15)
|
||||||
|
{
|
||||||
|
e131NewData = false;
|
||||||
|
strip.show();
|
||||||
|
Serial.println("Show");
|
||||||
|
}
|
||||||
|
|
||||||
//unlock strip when realtime UDP times out
|
//unlock strip when realtime UDP times out
|
||||||
if (realtimeActive && millis() > realtimeTimeout)
|
if (realtimeActive && millis() > realtimeTimeout)
|
||||||
|
Loading…
Reference in New Issue
Block a user