Merge branch '0_15' into blending-styles

This commit is contained in:
Blaz Kristan 2024-06-30 10:45:54 +02:00
commit 593970ed6d
26 changed files with 512 additions and 97 deletions

View File

@ -1,8 +1,47 @@
## WLED changelog
#### Build 2406290
- WLED 0.15.0-b4 release
- LED settings bus management update (WARNING only allow available outputs)
- Add ETH support for LILYGO-POE-Pro (#4030 by @rorosaurus)
- Update usermod_sn_photoresistor (#4017 by @xkvmoto)
- Several internal fixes and optimisations
- move LED_BUILTIN handling to BusManager class
- reduce max panels (web server limitation)
- edit WiFi TX power (ESP32)
- keep current ledmap ID in UI
- limit outputs in UI based on length
- wifi.ap addition to JSON Info (JSON API)
- relay pin init bugfix
- file editor button in UI
- ESP8266: update was restarting device on some occasions
- a bit of throttling in UI (for ESP8266)
#### Build 2406120
- Update NeoPixelBus to v2.8.0
- Increased LED outputs one ESP32 using parallel I2S (up to 17)
- use single/mono I2S + 4x RMT for 5 outputs or less
- use parallel x8 I2S + 8x RMT for >5 outputs (limit of 300 LEDs per output)
- Fixed code of Smartnest and updated documentation (#4001 by @DevilPro1)
- ESP32-S3 WiFi fix (#4010 by @cstruck)
- TetrisAI usermod fix (#3897 by @muebau)
- ESP-NOW usermod hook
- Update wled.h regarding OTA Password (#3993 by @gsieben)
- Usermod BME68X Sensor Implementation (#3994 by @gsieben)
- Add a usermod for AHT10, AHT15 and AHT20 temperature/humidity sensors (#3977 by @LordMike)
- Update Battery usermod documentation (#3968 by @adamsthws)
- Add INA226 usermod for reading current and power over i2c (#3986 by @LordMike)
- Bugfixes: #3991
- Several internal fixes and optimisations (WARNING: some effects may be broken that rely on overflow/narrow width)
- replace uint8_t and uint16_t with unsigned
- replace in8_t and int16_t with int
- reduces code by 1kB
#### Build 2405180
- WLED 0.14.4 release
- Fix for #3978
- Official 0.15.0-b3 release
- Merge 0.14.3 fixes
- Merge 0.14.3 fixes into 0_15
- Added Pinwheel Expand 1D->2D effect mapping mode (#3961 by @Brandon502)
- Add changeable i2c address to BME280 usermod (#3966 by @LordMike)
- Effect: Firenoise - add palette selection

View File

@ -28,7 +28,7 @@ You are all set if you have enabled `Editor: Detect Indentation` in VS Code.
#### Blocks
Whether the opening bracket of e.g. an `if` block is in the same line as the condition or in a separate line is up to your discretion. If there is only one statement, leaving out block braches is acceptable.
Whether the opening bracket of e.g. an `if` block is in the same line as the condition or in a separate line is up to your discretion. If there is only one statement, leaving out block brackets is acceptable.
Good:
```cpp
@ -49,7 +49,7 @@ if (a == b) doStuff(a);
```
There should always be a space between a keyword and its condition and between the condition and brace.
Within the condition, no space should be between the paranthesis and variables.
Within the condition, no space should be between the parenthesis and variables.
Spaces between variables and operators are up to the authors discretion.
There should be no space between function names and their argument parenthesis.

4
package-lock.json generated
View File

@ -1,12 +1,12 @@
{
"name": "wled",
"version": "0.15.0-b3",
"version": "0.15.0-b4",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "wled",
"version": "0.15.0-b3",
"version": "0.15.0-b4",
"license": "ISC",
"dependencies": {
"clean-css": "^5.3.3",

View File

@ -1,6 +1,6 @@
{
"name": "wled",
"version": "0.15.0-b3",
"version": "0.15.0-b4",
"description": "Tools for WLED project",
"main": "tools/cdata.js",
"directories": {

View File

@ -10,7 +10,7 @@ default_envs = WLED_tasmota_1M # define as many as you need
#----------
# SAMPLE
#----------
[env:WLED_tasmota_1M]
[env:WLED_generic8266_1M]
extends = env:esp01_1m_full # when you want to extend the existing environment (define only updated options)
; board = esp01_1m # uncomment when ou need different board
; platform = ${common.platform_wled_default} # uncomment and change when you want particular platform
@ -26,9 +26,9 @@ lib_deps = ${esp8266.lib_deps}
; adafruit/Adafruit BME280 Library@^2.2.2
; Wire
; robtillaart/SHT85@~0.3.3
; gmag11/QuickESPNow ;@ 0.6.2
; ;gmag11/QuickESPNow @ ~0.7.0 # will also load QuickDebug
; https://github.com/blazoncek/QuickESPNow.git#optional-debug ;; exludes debug library
; https://github.com/kosme/arduinoFFT#develop @ 2.0.1 ;; used for USERMOD_AUDIOREACTIVE
; ${esp32.AR_lib_deps} ;; used for USERMOD_AUDIOREACTIVE
build_unflags = ${common.build_unflags}
build_flags = ${common.build_flags} ${esp8266.build_flags}
;
@ -51,6 +51,11 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
; -D WLED_DISABLE_ESPNOW
; -D WLED_DISABLE_BROWNOUT_DET
;
; enable optional built-in features
; -D WLED_ENABLE_PIXART
; -D WLED_ENABLE_USERMOD_PAGE # if created
; -D WLED_ENABLE_DMX
;
; PIN defines - uncomment and change, if needed:
; -D LEDPIN=2
; or use this for multiple outputs
@ -64,6 +69,8 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
;
; Limit max buses
; -D WLED_MAX_BUSSES=2
; -D WLED_MAX_ANALOG_CHANNELS=3 # only 3 PWM HW pins available
; -D WLED_MAX_DIGITAL_CHANNELS=2 # only 2 HW accelerated pins available
;
; Configure default WiFi
; -D CLIENT_SSID='"MyNetwork"'
@ -128,12 +135,12 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
;
; Use PIR sensor usermod and configure it to use GPIO4 and timer of 60s
; -D USERMOD_PIRSWITCH
; -D PIR_SENSOR_PIN=4
; -D PIR_SENSOR_PIN=4 # use -1 to disable usermod
; -D PIR_SENSOR_OFF_SEC=60
; -D PIR_SENSOR_MAX_SENSORS=2 # max allowable sensors (uses OR logic for triggering)
;
; Use Audioreactive usermod and configure I2S microphone
; -D USERMOD_AUDIOREACTIVE
; -D UM_AUDIOREACTIVE_USE_NEW_FFT
; -D AUDIOPIN=-1
; -D DMTYPE=1 # 0-analog/disabled, 1-I2S generic, 2-ES7243, 3-SPH0645, 4-I2S+mclk, 5-I2S PDM
; -D I2S_SDPIN=36
@ -155,18 +162,22 @@ build_flags = ${common.build_flags} ${esp8266.build_flags}
; -D DEFAULT_LED_COUNT=30
; or this for multiple outputs
; -D PIXEL_COUNTS=30,30
;
; set milliampere limit when using ESP pin to power leds
;
; set the default LED type
; -D DEFAULT_LED_TYPE=22 # see const.h (TYPE_xxxx)
;
; set milliampere limit when using ESP power pin (or inadequate PSU) to power LEDs
; -D ABL_MILLIAMPS_DEFAULT=850
; -D LED_MILLIAMPS_DEFAULT=55
;
; enable IR by setting remote type
; -D IRTYPE=0 ;0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote
; -D IRTYPE=0 # 0 Remote disabled | 1 24-key RGB | 2 24-key with CT | 3 40-key blue | 4 40-key RGB | 5 21-key RGB | 6 6-key black | 7 9-key red | 8 JSON remote
;
; set default color order of your led strip
; -D DEFAULT_LED_COLOR_ORDER=COL_ORDER_GRB
;
; use PSRAM on classic ESP32 rev.1 (rev.3 or above has no issues)
; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue
; -DBOARD_HAS_PSRAM -mfix-esp32-psram-cache-issue # needed only for classic ESP32 rev.1
;
; configure I2C and SPI interface (for various hardware)
; -D I2CSDAPIN=33 # initialise interface

View File

@ -42,7 +42,7 @@ pyelftools==0.29
# via platformio
pyserial==3.5
# via platformio
requests==2.31.0
requests==2.32.0
# via platformio
semantic-version==2.10.0
# via platformio
@ -54,7 +54,7 @@ tabulate==0.9.0
# via platformio
typing-extensions==4.11.0
# via starlette
urllib3==1.26.18
urllib3==1.26.19
# via requests
uvicorn==0.20.0
# via platformio

View File

@ -0,0 +1,36 @@
# BH1750 usermod
> This usermod requires a second UART and was only tested on the ESP32
This usermod will read from a LD2410 movement/presence sensor.
The movement and presence state are displayed in both the Info section of the web UI, as well as published to the `/movement` and `/stationary` MQTT topics respectively.
## Dependencies
- Libraries
- `ncmreynolds/ld2410@^0.1.3`
- This must be added under `lib_deps` in your `platformio.ini` (or `platformio_override.ini`).
- Data is published over MQTT - make sure you've enabled the MQTT sync interface.
## Compilation
To enable, compile with `USERMOD_LD2410` defined (e.g. in `platformio_override.ini`)
```ini
[env:usermod_USERMOD_LD2410_esp32dev]
extends = env:esp32dev
build_flags =
${common.build_flags_esp32}
-D USERMOD_LD2410
lib_deps =
${esp32.lib_deps}
ncmreynolds/ld2410@^0.1.3
```
### Configuration Options
The Usermod screen allows you to:
- enable/disable the usermod
- Configure the RX/TX pins
## Change log
- 2024-06 Created by @wesleygas (https://github.com/wesleygas/)

View File

@ -0,0 +1,237 @@
#warning **** Included USERMOD_LD2410 ****
#ifndef WLED_ENABLE_MQTT
#error "This user mod requires MQTT to be enabled."
#endif
#pragma once
#include "wled.h"
#include <ld2410.h>
class LD2410Usermod : public Usermod {
private:
bool enabled = true;
bool initDone = false;
bool sensorFound = false;
unsigned long lastTime = 0;
unsigned long last_mqtt_sent = 0;
int8_t default_uart_rx = 19;
int8_t default_uart_tx = 18;
String mqttMovementTopic = F("");
String mqttStationaryTopic = F("");
bool mqttInitialized = false;
bool HomeAssistantDiscovery = true; // Publish Home Assistant Discovery messages
ld2410 radar;
bool stationary_detected = false;
bool last_stationary_state = false;
bool movement_detected = false;
bool last_movement_state = false;
// These config variables have defaults set inside readFromConfig()
int8_t uart_rx_pin;
int8_t uart_tx_pin;
// string that are used multiple time (this will save some flash memory)
static const char _name[];
static const char _enabled[];
void publishMqtt(const char* topic, const char* state, bool retain); // example for publishing MQTT message
void _mqttInitialize()
{
mqttMovementTopic = String(mqttDeviceTopic) + F("/ld2410/movement");
mqttStationaryTopic = String(mqttDeviceTopic) + F("/ld2410/stationary");
if (HomeAssistantDiscovery){
_createMqttSensor(F("Movement"), mqttMovementTopic, F("motion"), F(""));
_createMqttSensor(F("Stationary"), mqttStationaryTopic, F("occupancy"), F(""));
}
}
// Create an MQTT Sensor for Home Assistant Discovery purposes, this includes a pointer to the topic that is published to in the Loop.
void _createMqttSensor(const String &name, const String &topic, const String &deviceClass, const String &unitOfMeasurement)
{
String t = String(F("homeassistant/binary_sensor/")) + mqttClientID + F("/") + name + F("/config");
StaticJsonDocument<600> doc;
doc[F("name")] = String(serverDescription) + F(" Module");
doc[F("state_topic")] = topic;
doc[F("unique_id")] = String(mqttClientID) + name;
if (unitOfMeasurement != "")
doc[F("unit_of_measurement")] = unitOfMeasurement;
if (deviceClass != "")
doc[F("device_class")] = deviceClass;
doc[F("expire_after")] = 1800;
doc[F("payload_off")] = "OFF";
doc[F("payload_on")] = "ON";
JsonObject device = doc.createNestedObject(F("device")); // attach the sensor to the same device
device[F("name")] = serverDescription;
device[F("identifiers")] = "wled-sensor-" + String(mqttClientID);
device[F("manufacturer")] = F("WLED");
device[F("model")] = F("FOSS");
device[F("sw_version")] = versionString;
String temp;
serializeJson(doc, temp);
DEBUG_PRINTLN(t);
DEBUG_PRINTLN(temp);
mqtt->publish(t.c_str(), 0, true, temp.c_str());
}
public:
inline bool isEnabled() { return enabled; }
void setup() {
Serial1.begin(256000, SERIAL_8N1, uart_rx_pin, uart_tx_pin);
Serial.print(F("\nLD2410 radar sensor initialising: "));
if(radar.begin(Serial1)){
Serial.println(F("OK"));
} else {
Serial.println(F("not connected"));
}
initDone = true;
}
void loop() {
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
if (!enabled || strip.isUpdating()) return;
radar.read();
unsigned long curr_time = millis();
if(curr_time - lastTime > 1000) //Try to Report every 1000ms
{
lastTime = curr_time;
sensorFound = radar.isConnected();
if(!sensorFound) return;
stationary_detected = radar.presenceDetected();
if(stationary_detected != last_stationary_state){
if (WLED_MQTT_CONNECTED){
publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false);
last_stationary_state = stationary_detected;
}
}
movement_detected = radar.movingTargetDetected();
if(movement_detected != last_movement_state){
if (WLED_MQTT_CONNECTED){
publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false);
last_movement_state = movement_detected;
}
}
// If there hasn't been any activity, send current state to confirm sensor is alive
if(curr_time - last_mqtt_sent > 1000*60*5 && WLED_MQTT_CONNECTED){
publishMqtt("/ld2410/stationary", stationary_detected ? "ON":"OFF", false);
publishMqtt("/ld2410/movement", movement_detected ? "ON":"OFF", false);
}
}
}
void addToJsonInfo(JsonObject& root)
{
// if "u" object does not exist yet wee need to create it
JsonObject user = root[F("u")];
if (user.isNull()) user = root.createNestedObject(F("u"));
JsonArray ld2410_sta_json = user.createNestedArray(F("LD2410 Stationary"));
JsonArray ld2410_mov_json = user.createNestedArray(F("LD2410 Movement"));
if (!enabled){
ld2410_sta_json.add(F("disabled"));
ld2410_mov_json.add(F("disabled"));
} else if(!sensorFound){
ld2410_sta_json.add(F("LD2410"));
ld2410_sta_json.add(" Not Found");
} else {
ld2410_sta_json.add("Sta ");
ld2410_sta_json.add(stationary_detected ? "ON":"OFF");
ld2410_mov_json.add("Mov ");
ld2410_mov_json.add(movement_detected ? "ON":"OFF");
}
}
void addToConfig(JsonObject& root)
{
JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled;
//save these vars persistently whenever settings are saved
top["uart_rx_pin"] = default_uart_rx;
top["uart_tx_pin"] = default_uart_tx;
}
bool readFromConfig(JsonObject& root)
{
// default settings values could be set here (or below using the 3-argument getJsonValue()) instead of in the class definition or constructor
// setting them inside readFromConfig() is slightly more robust, handling the rare but plausible use case of single value being missing after boot (e.g. if the cfg.json was manually edited and a value was removed)
JsonObject top = root[FPSTR(_name)];
bool configComplete = !top.isNull();
if (!configComplete)
{
DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINT(F("LD2410"));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false;
}
configComplete &= getJsonValue(top["uart_rx_pin"], uart_rx_pin, default_uart_rx);
configComplete &= getJsonValue(top["uart_tx_pin"], uart_tx_pin, default_uart_tx);
return configComplete;
}
#ifndef WLED_DISABLE_MQTT
/**
* onMqttConnect() is called when MQTT connection is established
*/
void onMqttConnect(bool sessionPresent) {
// do any MQTT related initialisation here
if(!radar.isConnected()) return;
publishMqtt("/ld2410/status", "I am alive!", false);
if (!mqttInitialized)
{
_mqttInitialize();
mqttInitialized = true;
}
}
#endif
uint16_t getId()
{
return USERMOD_ID_LD2410;
}
};
// add more strings here to reduce flash memory usage
const char LD2410Usermod::_name[] PROGMEM = "LD2410Usermod";
const char LD2410Usermod::_enabled[] PROGMEM = "enabled";
// implementation of non-inline member methods
void LD2410Usermod::publishMqtt(const char* topic, const char* state, bool retain)
{
#ifndef WLED_DISABLE_MQTT
//Check if MQTT Connected, otherwise it will crash
if (WLED_MQTT_CONNECTED) {
last_mqtt_sent = millis();
char subuf[64];
strcpy(subuf, mqttDeviceTopic);
strcat(subuf, topic);
mqtt->publish(subuf, 0, retain, state);
}
#endif
}

View File

@ -58,7 +58,11 @@ private:
bool sensorPinState[PIR_SENSOR_MAX_SENSORS] = {LOW}; // current PIR sensor pin state
// configurable parameters
#if PIR_SENSOR_PIN < 0
bool enabled = false; // PIR sensor disabled
#else
bool enabled = true; // PIR sensor enabled
#endif
int8_t PIRsensorPin[PIR_SENSOR_MAX_SENSORS] = {PIR_SENSOR_PIN}; // PIR sensor pin
uint32_t m_switchOffDelay = PIR_SENSOR_OFF_SEC*1000; // delay before switch off after the sensor state goes LOW (10min)
uint8_t m_onPreset = 0; // on preset

View File

@ -3,7 +3,9 @@
#include "wled.h"
//Pin defaults for QuinLed Dig-Uno (A0)
#ifndef PHOTORESISTOR_PIN
#define PHOTORESISTOR_PIN A0
#endif
// the frequency to check photoresistor, 10 seconds
#ifndef USERMOD_SN_PHOTORESISTOR_MEASUREMENT_INTERVAL
@ -207,4 +209,4 @@ const char Usermod_SN_Photoresistor::_readInterval[] PROGMEM = "read-interval-s"
const char Usermod_SN_Photoresistor::_referenceVoltage[] PROGMEM = "supplied-voltage";
const char Usermod_SN_Photoresistor::_resistorValue[] PROGMEM = "resistor-value";
const char Usermod_SN_Photoresistor::_adcPrecision[] PROGMEM = "adc-precision";
const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset";
const char Usermod_SN_Photoresistor::_offset[] PROGMEM = "offset";

View File

@ -122,9 +122,9 @@ class AutoSaveUsermod : public Usermod {
* Da loop.
*/
void loop() {
if (!autoSaveAfterSec || !enabled || strip.isUpdating() || currentPreset>0) return; // setting 0 as autosave seconds disables autosave
static unsigned long lastRun = 0;
unsigned long now = millis();
if (!autoSaveAfterSec || !enabled || currentPreset>0 || (strip.isUpdating() && now - lastRun < 240)) return; // setting 0 as autosave seconds disables autosave
uint8_t currentMode = strip.getMainSegment().mode;
uint8_t currentPalette = strip.getMainSegment().palette;

View File

@ -4875,7 +4875,7 @@ uint16_t mode_2DBlackHole(void) { // By: Stepko https://editor.soulma
// central white dot
SEGMENT.setPixelColorXY(cols/2, rows/2, WHITE);
// blur everything a bit
SEGMENT.blur(16);
SEGMENT.blur(cols*rows > 100 ? 16 : 0);
return FRAMETIME;
} // mode_2DBlackHole()
@ -5671,8 +5671,7 @@ uint16_t mode_2Dsquaredswirl(void) { // By: Mark Kriegsman. https://g
const uint8_t kBorderWidth = 2;
SEGMENT.fadeToBlackBy(24);
uint8_t blurAmount = SEGMENT.custom3>>1; // reduced resolution slider
SEGMENT.blur(blurAmount);
SEGMENT.blur(SEGMENT.custom3>>1);
// Use two out-of-sync sine waves
int i = beatsin8(19, kBorderWidth, cols-kBorderWidth);
@ -6461,7 +6460,7 @@ uint16_t mode_2DWaverly(void) {
SEGMENT.addPixelColorXY((cols - 1) - i, (rows - 1) - j, ColorFromPalette(SEGPALETTE, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND));
}
}
SEGMENT.blur(16);
SEGMENT.blur(cols*rows > 100 ? 16 : 0);
return FRAMETIME;
} // mode_2DWaverly()

View File

@ -1292,7 +1292,7 @@ void WS2812FX::finalizeInit(void) {
unsigned start = prevLen;
unsigned count = defCounts[(i < defNumCounts) ? i : defNumCounts -1];
prevLen += count;
BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY);
BusConfig defCfg = BusConfig(DEFAULT_LED_TYPE, defPin, start, count, DEFAULT_LED_COLOR_ORDER, false, 0, RGBW_MODE_MANUAL_ONLY, 0, useGlobalLedBuffer);
if (BusManager::add(defCfg) == -1) break;
}
}

View File

@ -37,7 +37,7 @@ struct BusConfig {
uint8_t milliAmpsPerLed;
uint16_t milliAmpsMax;
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, bool dblBfr=false, uint8_t maPerLed=55, uint16_t maMax=ABL_MILLIAMPS_DEFAULT)
BusConfig(uint8_t busType, uint8_t* ppins, uint16_t pstart, uint16_t len = 1, uint8_t pcolorOrder = COL_ORDER_GRB, bool rev = false, uint8_t skip = 0, byte aw=RGBW_MODE_MANUAL_ONLY, uint16_t clock_kHz=0U, bool dblBfr=false, uint8_t maPerLed=LED_MILLIAMPS_DEFAULT, uint16_t maMax=ABL_MILLIAMPS_DEFAULT)
: count(len)
, start(pstart)
, colorOrder(pcolorOrder)
@ -129,7 +129,7 @@ class Bus {
virtual uint32_t getPixelColor(uint16_t pix) { return 0; }
virtual void setBrightness(uint8_t b) { _bri = b; };
virtual uint8_t getPins(uint8_t* pinArray) { return 0; }
virtual uint16_t getLength() { return _len; }
virtual uint16_t getLength() { return isOk() ? _len : 0; }
virtual void setColorOrder(uint8_t co) {}
virtual uint8_t getColorOrder() { return COL_ORDER_RGB; }
virtual uint8_t skippedLeds() { return 0; }

View File

@ -208,13 +208,13 @@ CRGBPalette16 generateRandomPalette(void) //generate fully random palette
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb) //hue, sat to rgb
{
float h = ((float)hue)/65535.0f;
float h = ((float)hue)/10922.5f; // hue*6/65535
float s = ((float)sat)/255.0f;
int i = floorf(h*6);
float f = h * 6.0f - i;
int i = int(h);
float f = h - i;
int p = int(255.0f * (1.0f-s));
int q = int(255.0f * (1.0f-f*s));
int t = int(255.0f * (1.0f-(1.0f-f)*s));
int q = int(255.0f * (1.0f-s*f));
int t = int(255.0f * (1.0f-s*(1.0f-f)));
p = constrain(p, 0, 255);
q = constrain(q, 0, 255);
t = constrain(t, 0, 255);

View File

@ -46,36 +46,58 @@
#ifndef WLED_MAX_BUSSES
#ifdef ESP8266
#define WLED_MAX_BUSSES 3
#define WLED_MAX_DIGITAL_CHANNELS 3
#define WLED_MAX_ANALOG_CHANNELS 5
#define WLED_MAX_BUSSES 4 // will allow 3 digital & 1 analog RGB
#define WLED_MIN_VIRTUAL_BUSSES 2
#else
#if defined(CONFIG_IDF_TARGET_ESP32C3) // 2 RMT, 6 LEDC, only has 1 I2S but NPB does not support it ATM
#define WLED_MAX_BUSSES 3 // will allow 2 digital & 1 analog (or the other way around)
#define WLED_MAX_BUSSES 4 // will allow 2 digital & 2 analog RGB
#define WLED_MAX_DIGITAL_CHANNELS 2
#define WLED_MAX_ANALOG_CHANNELS 6
#define WLED_MIN_VIRTUAL_BUSSES 3
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // 4 RMT, 8 LEDC, only has 1 I2S bus, supported in NPB
// the 5th bus (I2S) will prevent Audioreactive usermod from functioning (it is last used though)
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog
#define WLED_MAX_BUSSES 7 // will allow 5 digital & 2 analog RGB
#define WLED_MAX_DIGITAL_CHANNELS 5
#define WLED_MAX_ANALOG_CHANNELS 8
#define WLED_MIN_VIRTUAL_BUSSES 3
#elif defined(CONFIG_IDF_TARGET_ESP32S3) // 4 RMT, 8 LEDC, has 2 I2S but NPB does not support them ATM
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog
#define WLED_MAX_BUSSES 6 // will allow 4 digital & 2 analog RGB
#define WLED_MAX_DIGITAL_CHANNELS 4
#define WLED_MAX_ANALOG_CHANNELS 8
#define WLED_MIN_VIRTUAL_BUSSES 4
#else
// the last digital bus (I2S0) will prevent Audioreactive usermod from functioning
#define WLED_MAX_BUSSES 17
#define WLED_MIN_VIRTUAL_BUSSES 0
#define WLED_MAX_BUSSES 20 // will allow 17 digital & 3 analog RGB
#define WLED_MAX_DIGITAL_CHANNELS 17
#define WLED_MAX_ANALOG_CHANNELS 10
#define WLED_MIN_VIRTUAL_BUSSES 4
#endif
#endif
#else
#ifdef ESP8266
#if WLED_MAX_BUSES > 5
#if WLED_MAX_BUSSES > 5
#error Maximum number of buses is 5.
#endif
#ifndef WLED_MAX_ANALOG_CHANNELS
#error You must also define WLED_MAX_ANALOG_CHANNELS.
#endif
#ifndef WLED_MAX_DIGITAL_CHANNELS
#error You must also define WLED_MAX_DIGITAL_CHANNELS.
#endif
#define WLED_MIN_VIRTUAL_BUSSES (5-WLED_MAX_BUSSES)
#else
#if WLED_MAX_BUSES > 17
#error Maximum number of buses is 17.
#if WLED_MAX_BUSSES > 20
#error Maximum number of buses is 20.
#endif
#define WLED_MIN_VIRTUAL_BUSSES (17-WLED_MAX_BUSSES)
#ifndef WLED_MAX_ANALOG_CHANNELS
#error You must also define WLED_MAX_ANALOG_CHANNELS.
#endif
#ifndef WLED_MAX_DIGITAL_CHANNELS
#error You must also define WLED_MAX_DIGITAL_CHANNELS.
#endif
#define WLED_MIN_VIRTUAL_BUSSES (20-WLED_MAX_BUSSES)
#endif
#endif
@ -177,6 +199,7 @@
#define USERMOD_ID_BME68X 49 //Usermod "usermod_bme68x.h
#define USERMOD_ID_INA226 50 //Usermod "usermod_ina226.h"
#define USERMOD_ID_AHT10 51 //Usermod "usermod_aht10.h"
#define USERMOD_ID_LD2410 52 //Usermod "usermod_ld2410.h"
//Access point behavior
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
@ -328,7 +351,7 @@
#define BTN_TYPE_TOUCH_SWITCH 9
//Ethernet board types
#define WLED_NUM_ETH_TYPES 12
#define WLED_NUM_ETH_TYPES 13
#define WLED_ETH_NONE 0
#define WLED_ETH_WT32_ETH01 1
@ -342,6 +365,7 @@
#define WLED_ETH_ABCWLEDV43ETH 9
#define WLED_ETH_SERG74 10
#define WLED_ETH_ESP32_POE_WROVER 11
#define WLED_ETH_LILYGO_T_POE_PRO 12
//Hue error codes
#define HUE_ERROR_INACTIVE 0
@ -478,6 +502,16 @@
#endif
#endif
#ifndef LED_MILLIAMPS_DEFAULT
#define LED_MILLIAMPS_DEFAULT 55 // common WS2812B
#else
#if LED_MILLIAMPS_DEFAULT < 1 || LED_MILLIAMPS_DEFAULT > 100
#warning "Unusual LED mA current, overriding with default value."
#undef LED_MILLIAMPS_DEFAULT
#define LED_MILLIAMPS_DEFAULT 55
#endif
#endif
// PWM settings
#ifndef WLED_PWM_FREQ
#ifdef ESP8266

View File

@ -923,6 +923,7 @@ select.sel-p, select.sel-pl, select.sel-ple {
margin: 5px 0;
width: 100%;
height: 40px;
padding: 0 20px 0 8px;
}
div.sel-p {
position: relative;

View File

@ -588,7 +588,7 @@ function loadFXData(callback = null)
fxdata = [];
if (!retry) {
retry = true;
setTimeout(loadFXData, 500); // retry
setTimeout(()=>{loadFXData(loadFX);}, 500); // retry
}
showToast(e, true);
})
@ -1713,9 +1713,7 @@ function requestJson(command=null)
fetch(getURL('/json/si'), {
method: type,
headers: {
"Content-type": "application/json; charset=UTF-8"
},
headers: {"Content-Type": "application/json; charset=UTF-8"},
body: req
})
.then(res => {
@ -2698,7 +2696,9 @@ function setBalance(b)
function rmtTgl(ip,i) {
event.preventDefault();
event.stopPropagation();
fetch(`http://${ip}/win&T=2`, {method: 'get'})
fetch(`http://${ip}/win&T=2`, {
method: 'get'
})
.then((r)=>{
return r.text();
})
@ -2790,21 +2790,23 @@ function loadPalettesData(callback = null)
function getPalettesData(page, callback)
{
fetch(getURL(`/json/palx?page=${page}`), {
method: 'get',
headers: {
"Content-type": "application/json; charset=UTF-8"
}
method: 'get'
})
.then(res => {
if (!res.ok) showErrorToast();
return res.json();
})
.then(json => {
retry = false;
palettesData = Object.assign({}, palettesData, json.p);
if (page < json.m) setTimeout(()=>{ getPalettesData(page + 1, callback); }, 50);
if (page < json.m) setTimeout(()=>{ getPalettesData(page + 1, callback); }, 75);
else callback();
})
.catch((error)=>{
if (!retry) {
retry = true;
setTimeout(()=>{getPalettesData(page,callback);}, 500); // retry
}
showToast(error, true);
});
}
@ -2841,7 +2843,8 @@ function search(field, listId = null) {
if (gId("filters").querySelectorAll("input[type=checkbox]:checked").length) return;
// filter list items but leave (Default & Solid) always visible
gId(listId).querySelectorAll('.lstI').forEach((listItem,i)=>{
const listItems = gId("fxlist").querySelectorAll('.lstI');
listItems.forEach((listItem,i)=>{
if (listId!=='pcont' && i===0) return;
const listItemName = listItem.querySelector('.lstIname').innerText.toUpperCase();
const searchIndex = listItemName.indexOf(field.value.toUpperCase());
@ -3064,7 +3067,7 @@ function size()
function togglePcMode(fromB = false)
{
let ap = (fromB && !lastinfo) || (lastinfo && lastinfo.wifi && lastinfo.witi.ap);
let ap = (fromB && !lastinfo) || (lastinfo && lastinfo.wifi && lastinfo.wifi.ap);
if (fromB) {
pcModeA = !pcModeA;
localStorage.setItem('pcm', pcModeA);

View File

@ -5,7 +5,7 @@
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport">
<title>LED Settings</title>
<script>
var d=document,laprev=55,maxB=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxCO=10,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
var d=document,laprev=55,maxB=1,maxD=1,maxA=1,maxV=0,maxM=4000,maxPB=4096,maxL=1333,maxCO=10,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
var oMaxB=1;
d.um_p = [];
d.rsvd = [];
@ -58,14 +58,16 @@
x.style.animation = 'none';
timeout = setTimeout(function(){ x.className = x.className.replace("show", ""); }, 2900);
}
function bLimits(b,v,p,m,l,o) {
function bLimits(b,v,p,m,l,o=5,d=2,a=6) {
// maxB - max buses (can be changed if using ESP32 parallel I2S)
// maxD - max digital channels (can be changed if using ESP32 parallel I2S)
// maxA - max analog channels
// maxV - min virtual buses
// maxPB - max LEDs per bus
// maxM - max LED memory
// maxL - max LEDs
// maxCO - max Color Order mappings
oMaxB = maxB = b; maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
oMaxB = maxB = b; maxD = d, maxA = a, maxV = v; maxM = m; maxPB = p; maxL = l; maxCO = o;
}
function pinsOK() {
var ok = true;
@ -124,7 +126,10 @@
if (!pinsOK()) {e.stopPropagation();return false;} // Prevent form submission and contact with server
if (bquot > 100) {var msg = "Too many LEDs for me to handle!"; if (maxM < 10000) msg += "\n\rConsider using an ESP32."; alert(msg);}
if (!d.Sf.ABL.checked || d.Sf.PPL.checked) d.Sf.MA.value = 0; // submit 0 as ABL (PPL will handle it)
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
if (d.Sf.checkValidity()) {
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{s.disabled=false;}); // just in case
d.Sf.submit(); //https://stackoverflow.com/q/37323914
}
}
function enABL()
{
@ -221,7 +226,9 @@
maxB = oMaxB; // TODO make sure we start with all possible buses
// enable/disable LED fields
d.Sf.querySelectorAll("#mLC select[name^=LT]").forEach((s)=>{
let LTs = d.Sf.querySelectorAll("#mLC select[name^=LT]");
LTs.forEach((s,i)=>{
if (i < LTs.length-1) s.disabled = true; // prevent changing type (as we can't update options)
// is the field a LED type?
var n = s.name.substring(2);
var t = parseInt(s.value);
@ -283,7 +290,7 @@
// do we have a led count field
if (nm=="LC") {
let c = parseInt(LC.value,10); //get LED count
if (c > 300 && i < 8) maxB = min(oMaxB,10); //TODO: hard limit for buses when using ESP32 parallel I2S
if (c > 300 && i < 8) maxB = oMaxB - max(maxD-7,0); //TODO: hard limit for buses when using ESP32 parallel I2S
if (!customStarts || !startsDirty[n]) gId("ls"+n).value=sLC; //update start value
gId("ls"+n).disabled = !customStarts; //enable/disable field editing
if (c) {
@ -374,53 +381,62 @@
v = parseInt(d.getElementsByName("LS"+s)[0].value) + parseInt(d.getElementsByName("LC"+s)[0].value);
var t = parseInt(d.getElementsByName("LT"+s)[0].value);
if (isPWM(t)) v = 1; //PWM busses
if (isNaN(v)) return 0;
return v;
return isNaN(v) ? 0 : v;
}
function addLEDs(n,init=true)
{
var o = d.getElementsByClassName("iST");
var i = o.length;
let disable = (sel,opt) => { sel.querySelectorAll(opt).forEach((o)=>{o.disabled=true;}); }
var f = gId("mLC");
let digitalB = 0, analogB = 0, twopinB = 0, virtB = 0;
f.querySelectorAll("select[name^=LT]").forEach((s)=>{
let t = s.value;
if (isDig(t) && !isD2P(t)) digitalB++;
if (isD2P(t)) twopinB++;
if (isPWM(t)) analogB += t-40; // type defines PWM pins
if (isVir(t)) virtB++;
});
if ((n==1 && i>=maxB+maxV) || (n==-1 && i==0)) return;
var s = String.fromCharCode((i<10?48:55)+i);
var f = gId("mLC");
if (n==1) {
// npm run build has trouble minimizing spaces inside string
var cn = `<div class="iST">
<hr class="sml">
${i+1}:
<select name="LT${s}" onchange="UI(true)">${i>=maxB ? '' :
'<option value="22" selected>WS281x</option>\
<option value="30">SK6812/WS2814 RGBW</option>\
<option value="31">TM1814</option>\
<option value="24">400kHz</option>\
<option value="25">TM1829</option>\
<option value="26">UCS8903</option>\
<option value="27">APA106/PL9823</option>\
<option value="33">TM1914</option>\
<option value="28">FW1906 GRBCW</option>\
<option value="29">UCS8904 RGBW</option>\
<option value="32">WS2805 RGBCW</option>\
<option value="50">WS2801</option>\
<option value="51">APA102</option>\
<option value="52">LPD8806</option>\
<option value="54">LPD6803</option>\
<option value="53">P9813</option>\
<option value="19">WS2811 White</option>\
<select name="LT${s}" onchange="UI(true)">${i>=maxB && false ? '' :
'<option value="22" data-type="D">WS281x</option>\
<option value="30" data-type="D">SK6812/WS2814 RGBW</option>\
<option value="31" data-type="D">TM1814</option>\
<option value="24" data-type="D">400kHz</option>\
<option value="25" data-type="D">TM1829</option>\
<option value="26" data-type="D">UCS8903</option>\
<option value="27" data-type="D">APA106/PL9823</option>\
<option value="33" data-type="D">TM1914</option>\
<option value="28" data-type="D">FW1906 GRBCW</option>\
<option value="29" data-type="D">UCS8904 RGBW</option>\
<option value="32" data-type="D">WS2805 RGBCW</option>\
<option value="50" data-type="2P">WS2801</option>\
<option value="51" data-type="2P">APA102</option>\
<option value="52" data-type="2P">LPD8806</option>\
<option value="54" data-type="2P">LPD6803</option>\
<option value="53" data-type="2P">P9813</option>\
<option value="19" data-type="D">WS2811 White</option>\
<option value="40">On/Off</option>\
<option value="41">PWM White</option>\
<option value="42">PWM CCT</option>\
<option value="43">PWM RGB</option>\
<option value="44">PWM RGBW</option>\
<option value="45">PWM RGB+CCT</option>\
<!--option value="46">PWM RGB+DCCT</option-->'}
<option value="80">DDP RGB (network)</option>
<!--option value="81">E1.31 RGB (network)</option-->
<option value="82">Art-Net RGB (network)</option>
<option value="88">DDP RGBW (network)</option>
<option value="89">Art-Net RGBW (network)</option>
<option value="41" data-type="A">PWM White</option>\
<option value="42" data-type="AA">PWM CCT</option>\
<option value="43" data-type="AAA">PWM RGB</option>\
<option value="44" data-type="AAAA">PWM RGBW</option>\
<option value="45" data-type="AAAAA">PWM RGB+CCT</option>\
<!--option value="46" data-type="AAAAAA">PWM RGB+DCCT</option-->'}
<option value="80" data-type="V">DDP RGB (network)</option>
<!--option value="81" data-type="V">E1.31 RGB (network)</option-->
<option value="82" data-type="V">Art-Net RGB (network)</option>
<option value="88" data-type="V">DDP RGBW (network)</option>
<option value="89" data-type="V">Art-Net RGBW (network)</option>
</select><br>
<div id="abl${s}">
mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
@ -460,6 +476,11 @@ mA/LED: <select name="LAsel${s}" onchange="enLA(this,'${s}');UI();">
<div id="dig${s}a" style="display:inline"><br>Auto-calculate white channel from RGB:<br><select name="AW${s}"><option value=0>None</option><option value=1>Brighter</option><option value=2>Accurate</option><option value=3>Dual</option><option value=4>Max</option></select>&nbsp;</div>
</div>`;
f.insertAdjacentHTML("beforeend", cn);
let sel = d.getElementsByName("LT"+s)[0]
if (i >= maxB || digitalB >= maxD) disable(sel,'option[data-type="D"]');
if (i >= maxB || twopinB >= 1) disable(sel,'option[data-type="2P"]');
disable(sel,`option[data-type^="${'A'.repeat(maxA-analogB+1)}"]`);
sel.selectedIndex = sel.querySelector('option:not(:disabled)').index;
}
if (n==-1) {
o[--i].remove();--i;
@ -822,6 +843,7 @@ Swap: <select id="xw${s}" name="XW${s}">
<div id="btns"></div>
Disable internal pull-up/down: <input type="checkbox" name="IP"><br>
Touch threshold: <input type="number" class="s" min="0" max="100" name="TT" required><br>
<hr class="sml">
IR GPIO: <input type="number" min="-1" max="48" name="IR" onchange="UI()" class="xs"><select name="IT" onchange="UI()">
<option value=0>Remote disabled</option>
<option value=1>24-key RGB</option>
@ -836,6 +858,7 @@ Swap: <select id="xw${s}" name="XW${s}">
Apply IR change to main segment only: <input type="checkbox" name="MSO"><br>
<div id="json" style="display:none;">JSON file: <input type="file" name="data" accept=".json"><button type="button" class="sml" onclick="uploadFile('/ir.json')">Upload</button><br></div>
<a href="https://kno.wled.ge/interfaces/infrared/" target="_blank">IR info</a><br>
<hr class="sml">
Relay GPIO: <input type="number" min="-1" max="48" name="RL" onchange="UI()" class="xs"><span style="cursor: pointer;" onclick="off('RL')">&nbsp;&#x2715;</span><br>
Invert <input type="checkbox" name="RM"> Open drain <input type="checkbox" name="RO"><br>
<hr class="sml">

View File

@ -263,6 +263,7 @@ Static subnet mask:<br>
<option value="11">ESP32-POE-WROVER</option>
<option value="6">ESP32Deux/RGB2Go Tetra</option>
<option value="7">KIT-VE</option>
<option value="12">LILYGO T-POE Pro</option>
<option value="8">QuinLED-Dig-Octa & T-ETH-POE</option>
<option value="4">QuinLED-ESP32</option>
<option value="10">Serg74-ETH32</option>

View File

@ -210,7 +210,7 @@ void sendImprovInfoResponse() {
//Use serverDescription if it has been changed from the default "WLED", else mDNS name
bool useMdnsName = (strcmp(serverDescription, "WLED") == 0 && strlen(cmDNS) > 0);
char vString[20];
sprintf_P(vString, PSTR("0.15.0-b3/%i"), VERSION);
sprintf_P(vString, PSTR("0.15.0-b4/%i"), VERSION);
const char *str[4] = {"WLED", vString, bString, useMdnsName ? cmDNS : serverDescription};
sendImprovRPCResult(ImprovRPCType::Request_Info, 4, str);

View File

@ -133,6 +133,17 @@ const ethernet_settings ethernetBoards[] = {
18, // eth_mdio,
ETH_PHY_LAN8720, // eth_type,
ETH_CLOCK_GPIO0_OUT // eth_clk_mode
},
// LILYGO T-POE Pro
// https://github.com/Xinyuan-LilyGO/LilyGO-T-ETH-Series/blob/master/schematic/T-POE-PRO.pdf
{
0, // eth_address,
5, // eth_power,
23, // eth_mdc,
18, // eth_mdio,
ETH_PHY_LAN8720, // eth_type,
ETH_CLOCK_GPIO0_OUT // eth_clk_mode
}
};
#endif

View File

@ -243,10 +243,14 @@ bool PinManagerClass::isPinOk(byte gpio, bool output) const
#if defined(CONFIG_IDF_TARGET_ESP32C3)
// strapping pins: 2, 8, & 9
if (gpio > 11 && gpio < 18) return false; // 11-17 SPI FLASH
#if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1
if (gpio > 17 && gpio < 20) return false; // 18-19 USB-JTAG
#endif
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
// 00 to 18 are for general use. Be careful about straping pins GPIO0 and GPIO3 - these may be pulled-up or pulled-down on your board.
#if ARDUINO_USB_CDC_ON_BOOT == 1 || ARDUINO_USB_DFU_ON_BOOT == 1
if (gpio > 18 && gpio < 21) return false; // 19 + 20 = USB-JTAG. Not recommended for other uses.
#endif
if (gpio > 21 && gpio < 33) return false; // 22 to 32: not connected + SPI FLASH
if (gpio > 32 && gpio < 38) return !psramFound(); // 33 to 37: not available if using _octal_ SPI Flash or _octal_ PSRAM
// 38 to 48 are for general use. Be careful about straping pins GPIO45 and GPIO46 - these may be pull-up or pulled-down on your board.

View File

@ -230,6 +230,10 @@
#include "../usermods/INA226_v2/usermod_ina226.h"
#endif
#ifdef USERMOD_LD2410
#include "../usermods/LD2410_v2/usermod_ld2410.h"
#endif
void registerUsermods()
{
/*
@ -446,4 +450,8 @@ void registerUsermods()
#ifdef USERMOD_INA226
usermods.add(new UsermodINA226());
#endif
#ifdef USERMOD_LD2410
usermods.add(new LD2410Usermod());
#endif
}

View File

@ -3,12 +3,12 @@
/*
Main sketch, global variable declarations
@title WLED project sketch
@version 0.15.0-b3
@version 0.15.0-b4
@author Christian Schwinne
*/
// version code in format yymmddb (b = daily build)
#define VERSION 2406190
#define VERSION 2406290
//uncomment this if you have a "my_config.h" file you'd like to use
//#define WLED_USE_MY_CONFIG

View File

@ -356,7 +356,9 @@ void getSettingsJS(byte subPage, char* dest)
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
oappend(itoa(MAX_LEDS,nS,10)); oappend(",");
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10));
oappend(itoa(WLED_MAX_COLOR_ORDER_MAPPINGS,nS,10)); oappend(",");
oappend(itoa(WLED_MAX_DIGITAL_CHANNELS,nS,10)); oappend(",");
oappend(itoa(WLED_MAX_ANALOG_CHANNELS,nS,10));
oappend(SET_F(");"));
sappend('c',SET_F("MS"),autoSegments);