Merge branch 'main' into seg-groups
This commit is contained in:
commit
0a5aac724a
@ -21,9 +21,7 @@ click==8.1.3
|
||||
# platformio
|
||||
# uvicorn
|
||||
colorama==0.4.6
|
||||
# via
|
||||
# click
|
||||
# platformio
|
||||
# via platformio
|
||||
h11==0.14.0
|
||||
# via
|
||||
# uvicorn
|
||||
@ -42,7 +40,7 @@ pyelftools==0.29
|
||||
# via platformio
|
||||
pyserial==3.5
|
||||
# via platformio
|
||||
requests==2.28.2
|
||||
requests==2.31.0
|
||||
# via platformio
|
||||
semantic-version==2.10.0
|
||||
# via platformio
|
||||
@ -52,8 +50,6 @@ starlette==0.23.1
|
||||
# via platformio
|
||||
tabulate==0.9.0
|
||||
# via platformio
|
||||
typing-extensions==4.5.0
|
||||
# via starlette
|
||||
urllib3==1.26.15
|
||||
# via requests
|
||||
uvicorn==0.20.0
|
||||
|
@ -1,6 +1,9 @@
|
||||
# Multi Relay
|
||||
|
||||
This usermod-v2 modification allows the connection of multiple relays, each with individual delay and on/off mode.
|
||||
Usermod supports PCF8574 I2C port expander to reduce GPIO use.
|
||||
PCF8574 supports 8 outputs and each output corresponds to a relay in WLED (relay 0 = port 0, etc). I you are using more than 8 relays with multiple PCF8574 make sure their addresses are set conscutively (e.g. 0x20 and 0x21). You can set address of first expander in settings.
|
||||
(**NOTE:** Will require Wire library and global I2C pins defined.)
|
||||
|
||||
## HTTP API
|
||||
All responses are returned in JSON format.
|
||||
@ -81,13 +84,15 @@ void registerUsermods()
|
||||
Usermod can be configured via the Usermods settings page.
|
||||
|
||||
* `enabled` - enable/disable usermod
|
||||
* `use-PCF8574` - use PCF8574 port expander instead of GPIO pins
|
||||
* `first-PCF8574` - I2C address of first expander (WARNING: enter *decimal* value)
|
||||
* `broadcast`- time in seconds between MQTT relay-state broadcasts
|
||||
* `HA-discovery`- enable Home Assistant auto discovery
|
||||
* `pin` - ESP GPIO pin the relay is connected to (can be configured at compile time `-D MULTI_RELAY_PINS=xx,xx,...`)
|
||||
* `delay-s` - delay in seconds after on/off command is received
|
||||
* `active-high` - assign high/low activation of relay (can be used to reverse relay states)
|
||||
* `external` - if enabled, WLED does not control relay, it can only be triggered by an external command (MQTT, HTTP, JSON or button)
|
||||
* `button` - button (from LED Settings) that controls this relay
|
||||
* `broadcast`- time in seconds between MQTT relay-state broadcasts
|
||||
* `HA-discovery`- enable Home Assistant auto discovery
|
||||
|
||||
If there is no MultiRelay section, just save current configuration and re-open Usermods settings page.
|
||||
|
||||
@ -100,3 +105,6 @@ Have fun - @blazoncek
|
||||
2021-11
|
||||
* Added information about dynamic configuration options
|
||||
* Added button support.
|
||||
|
||||
2023-05
|
||||
* Added support for PCF8574 I2C port expander (multiple)
|
File diff suppressed because it is too large
Load Diff
@ -199,12 +199,12 @@ void Segment::setUpLeds() {
|
||||
#else
|
||||
leds = &Segment::_globalLeds[start];
|
||||
#endif
|
||||
else if (!leds) {
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound())
|
||||
leds = (CRGB*)ps_malloc(sizeof(CRGB)*length());
|
||||
else
|
||||
#endif
|
||||
else if (leds == nullptr && length() > 0) { //softhack007 quickfix - avoid malloc(0) which is undefined behaviour (should not happen, but i've seen it)
|
||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
//if (psramFound())
|
||||
// leds = (CRGB*)ps_malloc(sizeof(CRGB)*length()); // softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards
|
||||
//else
|
||||
//#endif
|
||||
leds = (CRGB*)malloc(sizeof(CRGB)*length());
|
||||
}
|
||||
}
|
||||
@ -1069,11 +1069,12 @@ void WS2812FX::finalizeInit(void)
|
||||
}
|
||||
if (useLedsArray) {
|
||||
size_t arrSize = sizeof(CRGB) * getLengthTotal();
|
||||
#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
if (psramFound())
|
||||
Segment::_globalLeds = (CRGB*) ps_malloc(arrSize);
|
||||
else
|
||||
#endif
|
||||
// softhack007 disabled; putting leds into psram leads to horrible slowdown on WROVER boards (see setUpLeds())
|
||||
//#if defined(ARDUINO_ARCH_ESP32) && defined(WLED_USE_PSRAM)
|
||||
//if (psramFound())
|
||||
// Segment::_globalLeds = (CRGB*) ps_malloc(arrSize);
|
||||
//else
|
||||
//#endif
|
||||
Segment::_globalLeds = (CRGB*) malloc(arrSize);
|
||||
memset(Segment::_globalLeds, 0, arrSize);
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ void handleDDPPacket(e131_packet_t* p) {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ddpChannelsPerLed = (p->dataType == DDP_TYPE_RGBW32) ? 4 : 3; // data type 0x1A is RGBW (type 3, 8 bit/channel)
|
||||
uint8_t ddpChannelsPerLed = (p->dataType & 0b00111000 == 0b011) ? 4 : 3; // data type 0x1B (formerly 0x1A) is RGBW (type 3, 8 bit/channel)
|
||||
|
||||
uint32_t start = htonl(p->channelOffset) / ddpChannelsPerLed;
|
||||
start += DMXAddress / ddpChannelsPerLed;
|
||||
|
3956
wled00/html_ui.h
3956
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -53,6 +53,7 @@ void onMqttConnect(bool sessionPresent)
|
||||
|
||||
|
||||
void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties properties, size_t len, size_t index, size_t total) {
|
||||
static char *payloadStr;
|
||||
|
||||
DEBUG_PRINT(F("MQTT msg: "));
|
||||
DEBUG_PRINTLN(topic);
|
||||
@ -62,11 +63,22 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
DEBUG_PRINTLN(F("no payload -> leave"));
|
||||
return;
|
||||
}
|
||||
//make a copy of the payload to 0-terminate it
|
||||
char* payloadStr = new char[len+1];
|
||||
if (payloadStr == nullptr) return; //no mem
|
||||
strncpy(payloadStr, payload, len);
|
||||
payloadStr[len] = '\0';
|
||||
|
||||
if (index == 0) { // start (1st partial packet or the only packet)
|
||||
if (payloadStr) delete[] payloadStr; // fail-safe: release buffer
|
||||
payloadStr = new char[total+1]; // allocate new buffer
|
||||
}
|
||||
if (payloadStr == nullptr) return; // buffer not allocated
|
||||
|
||||
// copy (partial) packet to buffer and 0-terminate it if it is last packet
|
||||
char* buff = payloadStr + index;
|
||||
memcpy(buff, payload, len);
|
||||
if (index + len >= total) { // at end
|
||||
payloadStr[total] = '\0'; // terminate c style string
|
||||
} else {
|
||||
DEBUG_PRINTLN(F("Partial packet received."));
|
||||
return; // process next packet
|
||||
}
|
||||
DEBUG_PRINTLN(payloadStr);
|
||||
|
||||
size_t topicPrefixLen = strlen(mqttDeviceTopic);
|
||||
@ -80,6 +92,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
// Non-Wled Topic used here. Probably a usermod subscribed to this topic.
|
||||
usermods.onMqttMessage(topic, payloadStr);
|
||||
delete[] payloadStr;
|
||||
payloadStr = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -87,16 +100,20 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
//Prefix is stripped from the topic at this point
|
||||
|
||||
if (strcmp_P(topic, PSTR("/col")) == 0) {
|
||||
colorFromDecOrHexString(col, (char*)payloadStr);
|
||||
colorFromDecOrHexString(col, payloadStr);
|
||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||
} else if (strcmp_P(topic, PSTR("/api")) == 0) {
|
||||
if (!requestJSONBufferLock(15)) { delete[] payloadStr; return; }
|
||||
if (payload[0] == '{') { //JSON API
|
||||
if (!requestJSONBufferLock(15)) {
|
||||
delete[] payloadStr;
|
||||
payloadStr = nullptr;
|
||||
return;
|
||||
}
|
||||
if (payloadStr[0] == '{') { //JSON API
|
||||
deserializeJson(doc, payloadStr);
|
||||
deserializeState(doc.as<JsonObject>());
|
||||
} else { //HTTP API
|
||||
String apireq = "win"; apireq += '&'; // reduce flash string usage
|
||||
apireq += (char*)payloadStr;
|
||||
apireq += payloadStr;
|
||||
handleSet(nullptr, apireq);
|
||||
}
|
||||
releaseJSONBufferLock();
|
||||
@ -108,6 +125,7 @@ void onMqttMessage(char* topic, char* payload, AsyncMqttClientMessageProperties
|
||||
parseMQTTBriPayload(payloadStr);
|
||||
}
|
||||
delete[] payloadStr;
|
||||
payloadStr = nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
@ -53,8 +53,8 @@ typedef struct ip_addr ip4_addr_t;
|
||||
#define DDP_PUSH_FLAG 0x01
|
||||
#define DDP_TIMECODE_FLAG 0x10
|
||||
|
||||
#define DDP_TYPE_RGB24 0x0A
|
||||
#define DDP_TYPE_RGBW32 0x1A
|
||||
#define DDP_TYPE_RGB24 0x0B // 00 001 011 (RGB , 8 bits per channel, 3 channels)
|
||||
#define DDP_TYPE_RGBW32 0x1B // 00 011 011 (RGBW, 8 bits per channel, 4 channels)
|
||||
|
||||
#define ARTNET_OPCODE_OPDMX 0x5000
|
||||
#define ARTNET_OPCODE_OPPOLL 0x2000
|
||||
|
@ -10,7 +10,7 @@
|
||||
*/
|
||||
/*
|
||||
* @title Espalexa library
|
||||
* @version 2.7.0
|
||||
* @version 2.7.1
|
||||
* @author Christian Schwinne
|
||||
* @license MIT
|
||||
* @contributors d-999
|
||||
@ -50,7 +50,7 @@
|
||||
#include "../network/Network.h"
|
||||
|
||||
#ifdef ESPALEXA_DEBUG
|
||||
#pragma message "Espalexa 2.7.0 debug mode"
|
||||
#pragma message "Espalexa 2.7.1 debug mode"
|
||||
#define EA_DEBUG(x) Serial.print (x)
|
||||
#define EA_DEBUGLN(x) Serial.println (x)
|
||||
#else
|
||||
@ -142,7 +142,7 @@ private:
|
||||
}
|
||||
|
||||
//device JSON string: color+temperature device emulates LCT015, dimmable device LWB010, (TODO: on/off Plug 01, color temperature device LWT010, color device LST001)
|
||||
void deviceJsonString(EspalexaDevice* dev, char* buf)
|
||||
void deviceJsonString(EspalexaDevice* dev, char* buf, size_t maxBuf) // softhack007 "size" parameter added, to avoid buffer overrun
|
||||
{
|
||||
char buf_lightid[27];
|
||||
encodeLightId(dev->getId() + 1, buf_lightid);
|
||||
@ -153,19 +153,19 @@ private:
|
||||
//TODO: %f is not working for some reason on ESP8266 in v0.11.0 (was fine in 0.10.2). Need to investigate
|
||||
//sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%f,%f]")
|
||||
// ,dev->getHue(), dev->getSat(), dev->getX(), dev->getY());
|
||||
sprintf_P(buf_col,PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%s,%s]"),dev->getHue(), dev->getSat(),
|
||||
snprintf_P(buf_col, sizeof(buf_col), PSTR(",\"hue\":%u,\"sat\":%u,\"effect\":\"none\",\"xy\":[%s,%s]"),dev->getHue(), dev->getSat(),
|
||||
((String)dev->getX()).c_str(), ((String)dev->getY()).c_str());
|
||||
|
||||
char buf_ct[16] = "";
|
||||
//white spectrum support
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1 && dev->getType() != EspalexaDeviceType::color)
|
||||
sprintf(buf_ct, ",\"ct\":%u", dev->getCt());
|
||||
snprintf(buf_ct, sizeof(buf_ct), ",\"ct\":%u", dev->getCt());
|
||||
|
||||
char buf_cm[20] = "";
|
||||
if (static_cast<uint8_t>(dev->getType()) > 1)
|
||||
sprintf(buf_cm,PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
|
||||
snprintf(buf_cm, sizeof(buf_cm), PSTR("\",\"colormode\":\"%s"), modeString(dev->getColorMode()));
|
||||
|
||||
sprintf_P(buf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
||||
snprintf_P(buf, maxBuf, PSTR("{\"state\":{\"on\":%s,\"bri\":%u%s%s,\"alert\":\"none%s\",\"mode\":\"homeautomation\",\"reachable\":true},"
|
||||
"\"type\":\"%s\",\"name\":\"%s\",\"modelid\":\"%s\",\"manufacturername\":\"Philips\",\"productname\":\"E%u"
|
||||
"\",\"uniqueid\":\"%s\",\"swversion\":\"espalexa-2.7.0\"}")
|
||||
|
||||
@ -219,10 +219,10 @@ private:
|
||||
EA_DEBUGLN("# Responding to description.xml ... #\n");
|
||||
IPAddress localIP = Network.localIP();
|
||||
char s[16];
|
||||
sprintf(s, "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
snprintf(s, sizeof(s), "%d.%d.%d.%d", localIP[0], localIP[1], localIP[2], localIP[3]);
|
||||
char buf[1024];
|
||||
|
||||
sprintf_P(buf,PSTR("<?xml version=\"1.0\" ?>"
|
||||
snprintf_P(buf, sizeof(buf), PSTR("<?xml version=\"1.0\" ?>"
|
||||
"<root xmlns=\"urn:schemas-upnp-org:device-1-0\">"
|
||||
"<specVersion><major>1</major><minor>0</minor></specVersion>"
|
||||
"<URLBase>http://%s:80/</URLBase>"
|
||||
@ -297,7 +297,7 @@ private:
|
||||
|
||||
char buf[1024];
|
||||
|
||||
sprintf_P(buf,PSTR("HTTP/1.1 200 OK\r\n"
|
||||
snprintf_P(buf, sizeof(buf), PSTR("HTTP/1.1 200 OK\r\n"
|
||||
"EXT:\r\n"
|
||||
"CACHE-CONTROL: max-age=100\r\n" // SSDP_INTERVAL
|
||||
"LOCATION: http://%s:80/description.xml\r\n"
|
||||
@ -493,7 +493,7 @@ public:
|
||||
unsigned idx = decodeLightKey(devId);
|
||||
EA_DEBUGLN(idx);
|
||||
char buf[50];
|
||||
sprintf_P(buf,PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId);
|
||||
snprintf_P(buf,sizeof(buf),PSTR("[{\"success\":{\"/lights/%u/state/\": true}}]"),devId);
|
||||
server->send(200, "application/json", buf);
|
||||
if (idx >= currentDeviceCount) return true; //return if invalid ID
|
||||
EspalexaDevice* dev = devices[idx];
|
||||
@ -571,7 +571,7 @@ public:
|
||||
jsonTemp += ':';
|
||||
|
||||
char buf[512];
|
||||
deviceJsonString(devices[i], buf);
|
||||
deviceJsonString(devices[i], buf, sizeof(buf)-1);
|
||||
jsonTemp += buf;
|
||||
if (i < currentDeviceCount-1) jsonTemp += ',';
|
||||
}
|
||||
@ -588,7 +588,7 @@ public:
|
||||
return true;
|
||||
}
|
||||
char buf[512];
|
||||
deviceJsonString(devices[idx], buf);
|
||||
deviceJsonString(devices[idx], buf, sizeof(buf)-1);
|
||||
server->send(200, "application/json", buf);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,15 @@
|
||||
|
||||
#include "EspalexaDevice.h"
|
||||
|
||||
// debug macros
|
||||
#ifdef ESPALEXA_DEBUG
|
||||
#define EA_DEBUG(x) Serial.print (x)
|
||||
#define EA_DEBUGLN(x) Serial.println (x)
|
||||
#else
|
||||
#define EA_DEBUG(x)
|
||||
#define EA_DEBUGLN(x)
|
||||
#endif
|
||||
|
||||
EspalexaDevice::EspalexaDevice(){}
|
||||
|
||||
EspalexaDevice::EspalexaDevice(String deviceName, BrightnessCallbackFunction gnCallback, uint8_t initialValue) { //constructor for dimmable device
|
||||
@ -124,18 +133,21 @@ uint32_t EspalexaDevice::getRGB()
|
||||
{
|
||||
//TODO tweak a bit to match hue lamp characteristics
|
||||
//based on https://gist.github.com/paulkaplan/5184275
|
||||
float temp = 10000/ _ct; //kelvins = 1,000,000/mired (and that /100)
|
||||
float temp = (_ct != 0) ? (10000/ _ct) : 2; //kelvins = 1,000,000/mired (and that /100) softhack007: avoid division by zero - using "2" as substitute
|
||||
float r, g, b;
|
||||
|
||||
#ifdef ESPALEXA_DEBUG
|
||||
if (_ct == 0) {EA_DEBUGLN(F("EspalexaDevice::getRGB() Warning: ct = 0!"));}
|
||||
#endif
|
||||
if (temp <= 66) {
|
||||
r = 255;
|
||||
g = temp;
|
||||
g = 99.470802 * log(g) - 161.119568;
|
||||
g = 99.470802 * logf(g) - 161.119568;
|
||||
if (temp <= 19) {
|
||||
b = 0;
|
||||
} else {
|
||||
b = temp-10;
|
||||
b = 138.517731 * log(b) - 305.044793;
|
||||
b = 138.517731 * logf(b) - 305.044793;
|
||||
}
|
||||
} else {
|
||||
r = temp - 60;
|
||||
@ -192,9 +204,9 @@ uint32_t EspalexaDevice::getRGB()
|
||||
b = 1.0f;
|
||||
}
|
||||
// Apply gamma correction
|
||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * pow(r, (1.0f / 2.4f)) - 0.055f;
|
||||
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * pow(g, (1.0f / 2.4f)) - 0.055f;
|
||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * pow(b, (1.0f / 2.4f)) - 0.055f;
|
||||
r = r <= 0.0031308f ? 12.92f * r : (1.0f + 0.055f) * powf(r, (1.0f / 2.4f)) - 0.055f;
|
||||
g = g <= 0.0031308f ? 12.92f * g : (1.0f + 0.055f) * powf(g, (1.0f / 2.4f)) - 0.055f;
|
||||
b = b <= 0.0031308f ? 12.92f * b : (1.0f + 0.055f) * powf(b, (1.0f / 2.4f)) - 0.055f;
|
||||
|
||||
if (r > b && r > g) {
|
||||
// red is biggest
|
||||
@ -328,8 +340,10 @@ void EspalexaDevice::setColor(uint8_t r, uint8_t g, uint8_t b)
|
||||
float X = r * 0.664511f + g * 0.154324f + b * 0.162028f;
|
||||
float Y = r * 0.283881f + g * 0.668433f + b * 0.047685f;
|
||||
float Z = r * 0.000088f + g * 0.072310f + b * 0.986039f;
|
||||
_x = X / (X + Y + Z);
|
||||
_y = Y / (X + Y + Z);
|
||||
if ((r+g+b) > 0) { // softhack007: avoid division by zero
|
||||
_x = X / (X + Y + Z);
|
||||
_y = Y / (X + Y + Z);
|
||||
} else { _x = _y = 0.5f;} // softhack007: use default values in case of "black"
|
||||
_rgb = ((r << 16) | (g << 8) | b);
|
||||
_mode = EspalexaColorMode::xy;
|
||||
}
|
||||
|
@ -151,6 +151,10 @@ struct PSRAM_Allocator {
|
||||
if (psramFound()) return ps_malloc(size); // use PSRAM if it exists
|
||||
else return malloc(size); // fallback
|
||||
}
|
||||
void* reallocate(void* ptr, size_t new_size) {
|
||||
if (psramFound()) return ps_realloc(ptr, new_size); // use PSRAM if it exists
|
||||
else return realloc(ptr, new_size); // fallback
|
||||
}
|
||||
void deallocate(void* pointer) {
|
||||
free(pointer);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user