Merge branch 'segment-api' into audioreactive-prototype
This commit is contained in:
commit
a6f31a577a
6
package-lock.json
generated
6
package-lock.json
generated
@ -2067,9 +2067,9 @@
|
|||||||
"integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw=="
|
"integrity": "sha512-a6sumDlzyHVJWb8+YofY4TW112G6p2FCPEAFk+59gIYHv3XHRhm9ltVQ9kli4hNWeQBwSpe8cRN25x0ROunMOw=="
|
||||||
},
|
},
|
||||||
"terser": {
|
"terser": {
|
||||||
"version": "4.8.0",
|
"version": "4.8.1",
|
||||||
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.0.tgz",
|
"resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz",
|
||||||
"integrity": "sha512-EAPipTNeWsb/3wLPeup1tVPaXfIaU68xMnVdPafIL1TV05OhASArYyIfFvnvJCNrR2NIOvDVNNTFRa+Re2MWyw==",
|
"integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"commander": "^2.20.0",
|
"commander": "^2.20.0",
|
||||||
"source-map": "~0.6.1",
|
"source-map": "~0.6.1",
|
||||||
|
@ -263,120 +263,60 @@ writeChunks(
|
|||||||
name: "PAGE_settings",
|
name: "PAGE_settings",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=0\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_wifi.htm",
|
file: "settings_wifi.htm",
|
||||||
name: "PAGE_settings_wifi",
|
name: "PAGE_settings_wifi",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=1\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_leds.htm",
|
file: "settings_leds.htm",
|
||||||
name: "PAGE_settings_leds",
|
name: "PAGE_settings_leds",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=2\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_dmx.htm",
|
file: "settings_dmx.htm",
|
||||||
name: "PAGE_settings_dmx",
|
name: "PAGE_settings_dmx",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=7\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_ui.htm",
|
file: "settings_ui.htm",
|
||||||
name: "PAGE_settings_ui",
|
name: "PAGE_settings_ui",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=3\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_sync.htm",
|
file: "settings_sync.htm",
|
||||||
name: "PAGE_settings_sync",
|
name: "PAGE_settings_sync",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=4\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_time.htm",
|
file: "settings_time.htm",
|
||||||
name: "PAGE_settings_time",
|
name: "PAGE_settings_time",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=5\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_sec.htm",
|
file: "settings_sec.htm",
|
||||||
name: "PAGE_settings_sec",
|
name: "PAGE_settings_sec",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=6\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_um.htm",
|
file: "settings_um.htm",
|
||||||
name: "PAGE_settings_um",
|
name: "PAGE_settings_um",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=8\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_2D.htm",
|
file: "settings_2D.htm",
|
||||||
name: "PAGE_settings_2D",
|
name: "PAGE_settings_2D",
|
||||||
method: "gzip",
|
method: "gzip",
|
||||||
filter: "html-minify",
|
filter: "html-minify",
|
||||||
mangle: (str) =>
|
|
||||||
str
|
|
||||||
.replace(
|
|
||||||
/function GetV().*\<\/script\>/gms,
|
|
||||||
"</script><script src=\"/settings/s.js?p=10\"></script>"
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
file: "settings_pin.htm",
|
file: "settings_pin.htm",
|
||||||
|
@ -103,25 +103,24 @@ class Animated_Staircase : public Usermod {
|
|||||||
|
|
||||||
void updateSegments() {
|
void updateSegments() {
|
||||||
mainSegmentId = strip.getMainSegmentId();
|
mainSegmentId = strip.getMainSegmentId();
|
||||||
WS2812FX::Segment* segments = strip.getSegments();
|
for (int i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
Segment &seg = strip.getSegment(i);
|
||||||
if (!segments->isActive()) {
|
if (!seg.isActive()) {
|
||||||
maxSegmentId = i - 1;
|
maxSegmentId = i - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i >= onIndex && i < offIndex) {
|
if (i >= onIndex && i < offIndex) {
|
||||||
segments->setOption(SEG_OPTION_ON, 1, i);
|
seg.setOption(SEG_OPTION_ON, true);
|
||||||
|
|
||||||
// We may need to copy mode and colors from segment 0 to make sure
|
// We may need to copy mode and colors from segment 0 to make sure
|
||||||
// changes are propagated even when the config is changed during a wipe
|
// changes are propagated even when the config is changed during a wipe
|
||||||
// segments->mode = mainsegment.mode;
|
// segments->mode = mainsegment.mode;
|
||||||
// segments->colors[0] = mainsegment.colors[0];
|
// segments->colors[0] = mainsegment.colors[0];
|
||||||
} else {
|
} else {
|
||||||
segments->setOption(SEG_OPTION_ON, 0, i);
|
seg.setOption(SEG_OPTION_ON, false);
|
||||||
}
|
}
|
||||||
// Always mark segments as "transitional", we are animating the staircase
|
// Always mark segments as "transitional", we are animating the staircase
|
||||||
segments->setOption(SEG_OPTION_TRANSITIONAL, 1, i);
|
seg.setOption(SEG_OPTION_TRANSITIONAL, true);
|
||||||
}
|
}
|
||||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
}
|
}
|
||||||
@ -290,13 +289,13 @@ class Animated_Staircase : public Usermod {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Restore segment options
|
// Restore segment options
|
||||||
WS2812FX::Segment* segments = strip.getSegments();
|
for (int i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
for (int i = 0; i < MAX_NUM_SEGMENTS; i++, segments++) {
|
Segment &seg = strip.getSegment(i);
|
||||||
if (!segments->isActive()) {
|
if (!seg.isActive()) {
|
||||||
maxSegmentId = i - 1;
|
maxSegmentId = i - 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
segments->setOption(SEG_OPTION_ON, 1, i);
|
seg.setOption(SEG_OPTION_ON, true);
|
||||||
}
|
}
|
||||||
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
colorUpdated(CALL_MODE_DIRECT_CHANGE);
|
||||||
DEBUG_PRINTLN(F("Animated Staircase disabled."));
|
DEBUG_PRINTLN(F("Animated Staircase disabled."));
|
||||||
|
@ -1,40 +1,90 @@
|
|||||||
Hello! I have written a v2 usermod for the BME280/BMP280 sensor based on the [existing v1 usermod](https://github.com/Aircoookie/WLED/blob/master/usermods/Wemos_D1_mini%2BWemos32_mini_shield/usermod_bme280.cpp). It is not just a refactor, there are many changes which I made to fit my use case, and I hope they will fit the use cases of others as well! Most notably, this usermod is *just* for the BME280 and does not control a display like in the v1 usermod designed for the WeMos shield.
|
# Usermod BME280
|
||||||
|
This Usermod is designed to read a `BME280` or `BMP280` sensor and output the following:
|
||||||
|
- Temperature
|
||||||
|
- Humidity (`BME280` only)
|
||||||
|
- Pressure
|
||||||
|
- Heat Index (`BME280` only)
|
||||||
|
- Dew Point (`BME280` only)
|
||||||
|
|
||||||
- Requires libraries `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280)) and `Wire`. Please add these under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
|
Configuration is all completed via the Usermod menu. There are no settings to set in code! The following settings can be configured in the Usermod Menu:
|
||||||
- Data is published over MQTT so make sure you've enabled the MQTT sync interface.
|
- Temperature Decimals (number of decimal places to output)
|
||||||
|
- Humidity Decimals
|
||||||
|
- Pressure Decimals
|
||||||
|
- Temperature Interval (how many seconds between reads of temperature and humidity)
|
||||||
|
- Pressure Interval
|
||||||
|
- Publish Always (turn off to only publish changes, on to publish whether or not value changed)
|
||||||
|
- Use Celsius (turn off to use Farenheit)
|
||||||
|
- Home Assistant Discovery (turn on to sent MQTT Discovery entries for Home Assistant)
|
||||||
|
- SCL/SDA GPIO Pins
|
||||||
|
|
||||||
|
Dependencies
|
||||||
|
- Libraries
|
||||||
|
- `BME280@~3.0.0` (by [finitespace](https://github.com/finitespace/BME280))
|
||||||
|
- `Wire`
|
||||||
|
- These must be added under `lib_deps` in your `platform.ini` (or `platform_override.ini`).
|
||||||
|
- Data is published over MQTT - make sure you've enabled the MQTT sync interface.
|
||||||
- This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else listening on the serial TX pin of your board will get confused by log messages!
|
- This usermod also writes to serial (GPIO1 on ESP8266). Please make sure nothing else listening on the serial TX pin of your board will get confused by log messages!
|
||||||
|
|
||||||
To enable, compile with `USERMOD_BME280` defined (i.e. `platformio_override.ini`)
|
In addition to outputting via MQTT, you can read the values from the Info Screen on the dashboard page of the device's web interface.
|
||||||
|
|
||||||
|
Methods also exist to read the read/calculated values from other WLED modules through code.
|
||||||
|
- `getTemperatureC()`
|
||||||
|
- `getTemperatureF()`
|
||||||
|
- `getHumidity()`
|
||||||
|
- `getPressure()`
|
||||||
|
- `getDewPointC()`
|
||||||
|
- `getDewPointF()`
|
||||||
|
- `getHeatIndexC()`
|
||||||
|
- `getHeatIndexF()`
|
||||||
|
|
||||||
|
# Complilation
|
||||||
|
|
||||||
|
To enable, compile with `USERMOD_BME280` defined (e.g. in `platformio_override.ini`)
|
||||||
```ini
|
```ini
|
||||||
|
[env:usermod_bme280_d1_mini]
|
||||||
|
extends = env:d1_mini
|
||||||
build_flags =
|
build_flags =
|
||||||
${common.build_flags_esp8266}
|
${common.build_flags_esp8266}
|
||||||
-D USERMOD_BME280
|
-D USERMOD_BME280
|
||||||
```
|
lib_deps =
|
||||||
or define `USERMOD_BME280` in `my_config.h`
|
${esp8266.lib_deps}
|
||||||
```c++
|
BME280@~3.0.0
|
||||||
#define USERMOD_BME280
|
Wire
|
||||||
```
|
```
|
||||||
|
|
||||||
Changes include:
|
|
||||||
- Adjustable measure intervals
|
|
||||||
- Temperature and pressure have separate intervals due to pressure not frequently changing at any constant altitude
|
|
||||||
- Adjustment of number of decimal places in published sensor values
|
|
||||||
- Separate adjustment for temperature, humidity and pressure values
|
|
||||||
- Values are rounded to the specified number of decimal places
|
|
||||||
- Pressure measured in units of hPa instead of Pa
|
|
||||||
- Calculation of heat index (apparent temperature) and dew point
|
|
||||||
- These, along with humidity measurements, are disabled if the sensor is a BMP280
|
|
||||||
- 16x oversampling of sensor during measurement
|
|
||||||
- Values are only published if they are different from the previous value
|
|
||||||
- Values are published on startup (continually until the MQTT broker acknowledges a successful publication)
|
|
||||||
|
|
||||||
Adjustments are made through preprocessor definitions at the start of the class definition.
|
# MQTT
|
||||||
|
MQTT topics are as follows (`<deviceTopic>` is set in MQTT section of Sync Setup menu):
|
||||||
MQTT topics are as follows:
|
|
||||||
Measurement type | MQTT topic
|
Measurement type | MQTT topic
|
||||||
--- | ---
|
--- | ---
|
||||||
Temperature | `<deviceTopic>/temperature`
|
Temperature | `<deviceTopic>/temperature`
|
||||||
Humidity | `<deviceTopic>/humidity`
|
Humidity | `<deviceTopic>/humidity`
|
||||||
Pressure | `<deviceTopic>/pressure`
|
Pressure | `<deviceTopic>/pressure`
|
||||||
Heat index | `<deviceTopic>/heat_index`
|
Heat index | `<deviceTopic>/heat_index`
|
||||||
Dew point | `<deviceTopic>/dew_point`
|
Dew point | `<deviceTopic>/dew_point`
|
||||||
|
|
||||||
|
If you are using Home Assistant, and `Home Assistant Discovery` is turned on, Home Assistant should automatically detect a new device, provided you have the MQTT integration installed. The device is seperate from the main WLED device and will contain sensors for Pressure, Humidity, Temperature, Dew Point and Heat Index.
|
||||||
|
|
||||||
|
# Revision History
|
||||||
|
Jul 2022
|
||||||
|
- Added Home Assistant Discovery
|
||||||
|
- Added API interface to output data
|
||||||
|
- Removed compile-time variables
|
||||||
|
- Added usermod menu interface
|
||||||
|
- Added value outputs to info screen
|
||||||
|
- Updated `readme.md`
|
||||||
|
- Registered usermod
|
||||||
|
- Implemented PinManager for usermod
|
||||||
|
- Implemented reallocation of pins without reboot
|
||||||
|
|
||||||
|
Apr 2021
|
||||||
|
- Added `Publish Always` option
|
||||||
|
|
||||||
|
Dec 2020
|
||||||
|
- Ported to V2 Usermod format
|
||||||
|
- Customisable `measure intervals`
|
||||||
|
- Customisable number of `decimal places` in published sensor values
|
||||||
|
- Pressure measured in units of hPa instead of Pa
|
||||||
|
- Calculation of heat index (apparent temperature) and dew point
|
||||||
|
- `16x oversampling` of sensor during measurement
|
||||||
|
- Values only published if they are different from the previous value
|
@ -1,3 +1,6 @@
|
|||||||
|
// force the compiler to show a warning to confirm that this file is included
|
||||||
|
#warning **** Included USERMOD_BME280 version 2.0 ****
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
@ -9,43 +12,30 @@
|
|||||||
class UsermodBME280 : public Usermod
|
class UsermodBME280 : public Usermod
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// User-defined configuration
|
|
||||||
#define Celsius // Show temperature mesaurement in Celcius. Comment out for Fahrenheit
|
// NOTE: Do not implement any compile-time variables, anything the user needs to configure
|
||||||
#define TemperatureDecimals 1 // Number of decimal places in published temperaure values
|
// should be configurable from the Usermod menu using the methods below
|
||||||
#define HumidityDecimals 2 // Number of decimal places in published humidity values
|
// key settings set via usermod menu
|
||||||
#define PressureDecimals 2 // Number of decimal places in published pressure values
|
unsigned long TemperatureDecimals = 0; // Number of decimal places in published temperaure values
|
||||||
#define TemperatureInterval 5 // Interval to measure temperature (and humidity, dew point if available) in seconds
|
unsigned long HumidityDecimals = 0; // Number of decimal places in published humidity values
|
||||||
#define PressureInterval 300 // Interval to measure pressure in seconds
|
unsigned long PressureDecimals = 0; // Number of decimal places in published pressure values
|
||||||
#define PublishAlways 0 // Publish values even when they have not changed
|
unsigned long TemperatureInterval = 5; // Interval to measure temperature (and humidity, dew point if available) in seconds
|
||||||
|
unsigned long PressureInterval = 300; // Interval to measure pressure in seconds
|
||||||
|
bool PublishAlways = false; // Publish values even when they have not changed
|
||||||
|
bool UseCelsius = true; // Use Celsius for Reporting
|
||||||
|
bool HomeAssistantDiscovery = false; // Publish Home Assistant Device Information
|
||||||
|
|
||||||
// Sanity checks
|
// set the default pins based on the architecture, these get overridden by Usermod menu settings
|
||||||
#if !defined(TemperatureDecimals) || TemperatureDecimals < 0
|
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
||||||
#define TemperatureDecimals 0
|
#define HW_PIN_SCL 22
|
||||||
#endif
|
#define HW_PIN_SDA 21
|
||||||
#if !defined(HumidityDecimals) || HumidityDecimals < 0
|
#else // ESP8266 boards
|
||||||
#define HumidityDecimals 0
|
#define HW_PIN_SCL 5
|
||||||
#endif
|
#define HW_PIN_SDA 4
|
||||||
#if !defined(PressureDecimals) || PressureDecimals < 0
|
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
||||||
#define PressureDecimals 0
|
#endif
|
||||||
#endif
|
int8_t ioPin[2] = {HW_PIN_SCL, HW_PIN_SDA}; // I2C pins: SCL, SDA...defaults to Arch hardware pins but overridden at setup()
|
||||||
#if !defined(TemperatureInterval) || TemperatureInterval < 0
|
bool initDone = false;
|
||||||
#define TemperatureInterval 1
|
|
||||||
#endif
|
|
||||||
#if !defined(PressureInterval) || PressureInterval < 0
|
|
||||||
#define PressureInterval TemperatureInterval
|
|
||||||
#endif
|
|
||||||
#if !defined(PublishAlways)
|
|
||||||
#define PublishAlways 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32 // ESP32 boards
|
|
||||||
uint8_t SCL_PIN = 22;
|
|
||||||
uint8_t SDA_PIN = 21;
|
|
||||||
#else // ESP8266 boards
|
|
||||||
uint8_t SCL_PIN = 5;
|
|
||||||
uint8_t SDA_PIN = 4;
|
|
||||||
//uint8_t RST_PIN = 16; // Uncoment for Heltec WiFi-Kit-8
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// BME280 sensor settings
|
// BME280 sensor settings
|
||||||
BME280I2C::Settings settings{
|
BME280I2C::Settings settings{
|
||||||
@ -75,6 +65,7 @@ private:
|
|||||||
float sensorHeatIndex;
|
float sensorHeatIndex;
|
||||||
float sensorDewPoint;
|
float sensorDewPoint;
|
||||||
float sensorPressure;
|
float sensorPressure;
|
||||||
|
String tempScale;
|
||||||
// Track previous sensor values
|
// Track previous sensor values
|
||||||
float lastTemperature;
|
float lastTemperature;
|
||||||
float lastHumidity;
|
float lastHumidity;
|
||||||
@ -82,43 +73,122 @@ private:
|
|||||||
float lastDewPoint;
|
float lastDewPoint;
|
||||||
float lastPressure;
|
float lastPressure;
|
||||||
|
|
||||||
|
// MQTT topic strings for publishing Home Assistant discovery topics
|
||||||
|
bool mqttInitialized = false;
|
||||||
|
String mqttTemperatureTopic = "";
|
||||||
|
String mqttHumidityTopic = "";
|
||||||
|
String mqttPressureTopic = "";
|
||||||
|
String mqttHeatIndexTopic = "";
|
||||||
|
String mqttDewPointTopic = "";
|
||||||
|
|
||||||
// Store packet IDs of MQTT publications
|
// Store packet IDs of MQTT publications
|
||||||
uint16_t mqttTemperaturePub = 0;
|
uint16_t mqttTemperaturePub = 0;
|
||||||
uint16_t mqttPressurePub = 0;
|
uint16_t mqttPressurePub = 0;
|
||||||
|
|
||||||
|
// Read the BME280/BMP280 Sensor (which one runs depends on whether Celsius or Farenheit being set in Usermod Menu)
|
||||||
void UpdateBME280Data(int SensorType)
|
void UpdateBME280Data(int SensorType)
|
||||||
{
|
{
|
||||||
float _temperature, _humidity, _pressure;
|
float _temperature, _humidity, _pressure;
|
||||||
#ifdef Celsius
|
|
||||||
|
if (UseCelsius) {
|
||||||
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
BME280::TempUnit tempUnit(BME280::TempUnit_Celsius);
|
||||||
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius);
|
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Celsius);
|
||||||
#else
|
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
|
||||||
|
|
||||||
|
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
|
||||||
|
|
||||||
|
sensorTemperature = _temperature;
|
||||||
|
sensorHumidity = _humidity;
|
||||||
|
sensorPressure = _pressure;
|
||||||
|
tempScale = "°C";
|
||||||
|
if (sensorType == 1)
|
||||||
|
{
|
||||||
|
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
|
||||||
|
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
BME280::TempUnit tempUnit(BME280::TempUnit_Fahrenheit);
|
||||||
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Fahrenheit);
|
EnvironmentCalculations::TempUnit envTempUnit(EnvironmentCalculations::TempUnit_Fahrenheit);
|
||||||
#endif
|
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
|
||||||
BME280::PresUnit presUnit(BME280::PresUnit_hPa);
|
|
||||||
|
|
||||||
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
|
bme.read(_pressure, _temperature, _humidity, tempUnit, presUnit);
|
||||||
|
|
||||||
sensorTemperature = _temperature;
|
sensorTemperature = _temperature;
|
||||||
sensorHumidity = _humidity;
|
sensorHumidity = _humidity;
|
||||||
sensorPressure = _pressure;
|
sensorPressure = _pressure;
|
||||||
if (sensorType == 1)
|
tempScale = "°F";
|
||||||
{
|
if (sensorType == 1)
|
||||||
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
|
{
|
||||||
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
|
sensorHeatIndex = EnvironmentCalculations::HeatIndex(_temperature, _humidity, envTempUnit);
|
||||||
|
sensorDewPoint = EnvironmentCalculations::DewPoint(_temperature, _humidity, envTempUnit);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Procedure to define all MQTT discovery Topics
|
||||||
|
void _mqttInitialize()
|
||||||
|
{
|
||||||
|
mqttTemperatureTopic = String(mqttDeviceTopic) + F("/temperature");
|
||||||
|
mqttPressureTopic = String(mqttDeviceTopic) + F("/pressure");
|
||||||
|
mqttHumidityTopic = String(mqttDeviceTopic) + F("/humidity");
|
||||||
|
mqttHeatIndexTopic = String(mqttDeviceTopic) + F("/heat_index");
|
||||||
|
mqttDewPointTopic = String(mqttDeviceTopic) + F("/dew_point");
|
||||||
|
|
||||||
|
if (HomeAssistantDiscovery) {
|
||||||
|
_createMqttSensor(F("Temperature"), mqttTemperatureTopic, F("temperature"), tempScale);
|
||||||
|
_createMqttSensor(F("Pressure"), mqttPressureTopic, F("pressure"), F("hPa"));
|
||||||
|
_createMqttSensor(F("Humidity"), mqttHumidityTopic, F("humidity"), F("%"));
|
||||||
|
_createMqttSensor(F("HeatIndex"), mqttHeatIndexTopic, F("temperature"), tempScale);
|
||||||
|
_createMqttSensor(F("DewPoint"), mqttDewPointTopic, F("temperature"), tempScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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/sensor/")) + mqttClientID + F("/") + name + F("/config");
|
||||||
|
|
||||||
|
StaticJsonDocument<600> doc;
|
||||||
|
|
||||||
|
doc[F("name")] = String(serverDescription) + " " + name;
|
||||||
|
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;
|
||||||
|
|
||||||
|
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:
|
public:
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Wire.begin(SDA_PIN, SCL_PIN);
|
bool HW_Pins_Used = (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA); // note whether architecture-based hardware SCL/SDA pins used
|
||||||
|
PinOwner po = PinOwner::UM_BME280; // defaults to being pinowner for SCL/SDA pins
|
||||||
|
PinManagerPinType pins[2] = { { ioPin[0], true }, { ioPin[1], true } }; // allocate pins
|
||||||
|
if (HW_Pins_Used) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||||
|
if (!pinManager.allocateMultiplePins(pins, 2, po)) { sensorType=0; return; }
|
||||||
|
|
||||||
|
Wire.begin(ioPin[1], ioPin[0]);
|
||||||
|
|
||||||
if (!bme.begin())
|
if (!bme.begin())
|
||||||
{
|
{
|
||||||
sensorType = 0;
|
sensorType = 0;
|
||||||
Serial.println("Could not find BME280I2C sensor!");
|
DEBUG_PRINTLN(F("Could not find BME280I2C sensor!"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -126,24 +196,25 @@ public:
|
|||||||
{
|
{
|
||||||
case BME280::ChipModel_BME280:
|
case BME280::ChipModel_BME280:
|
||||||
sensorType = 1;
|
sensorType = 1;
|
||||||
Serial.println("Found BME280 sensor! Success.");
|
DEBUG_PRINTLN(F("Found BME280 sensor! Success."));
|
||||||
break;
|
break;
|
||||||
case BME280::ChipModel_BMP280:
|
case BME280::ChipModel_BMP280:
|
||||||
sensorType = 2;
|
sensorType = 2;
|
||||||
Serial.println("Found BMP280 sensor! No Humidity available.");
|
DEBUG_PRINTLN(F("Found BMP280 sensor! No Humidity available."));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
sensorType = 0;
|
sensorType = 0;
|
||||||
Serial.println("Found UNKNOWN sensor! Error!");
|
DEBUG_PRINTLN(F("Found UNKNOWN sensor! Error!"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initDone=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
// BME280 sensor MQTT publishing
|
// BME280 sensor MQTT publishing
|
||||||
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
|
// Check if sensor present and MQTT Connected, otherwise it will crash the MCU
|
||||||
if (sensorType != 0 && mqtt != nullptr)
|
if (sensorType != 0 && WLED_MQTT_CONNECTED)
|
||||||
{
|
{
|
||||||
// Timer to fetch new temperature, humidity and pressure data at intervals
|
// Timer to fetch new temperature, humidity and pressure data at intervals
|
||||||
timer = millis();
|
timer = millis();
|
||||||
@ -154,9 +225,15 @@ public:
|
|||||||
|
|
||||||
UpdateBME280Data(sensorType);
|
UpdateBME280Data(sensorType);
|
||||||
|
|
||||||
float temperature = roundf(sensorTemperature * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
|
float temperature = roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
float humidity, heatIndex, dewPoint;
|
float humidity, heatIndex, dewPoint;
|
||||||
|
|
||||||
|
if (WLED_MQTT_CONNECTED && !mqttInitialized)
|
||||||
|
{
|
||||||
|
_mqttInitialize();
|
||||||
|
mqttInitialized = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If temperature has changed since last measure, create string populated with device topic
|
// If temperature has changed since last measure, create string populated with device topic
|
||||||
// from the UI and values read from sensor, then publish to broker
|
// from the UI and values read from sensor, then publish to broker
|
||||||
if (temperature != lastTemperature || PublishAlways)
|
if (temperature != lastTemperature || PublishAlways)
|
||||||
@ -169,25 +246,25 @@ public:
|
|||||||
|
|
||||||
if (sensorType == 1) // Only if sensor is a BME280
|
if (sensorType == 1) // Only if sensor is a BME280
|
||||||
{
|
{
|
||||||
humidity = roundf(sensorHumidity * pow(10, HumidityDecimals)) / pow(10, HumidityDecimals);
|
humidity = roundf(sensorHumidity * powf(10, HumidityDecimals)) / powf(10, HumidityDecimals);
|
||||||
heatIndex = roundf(sensorHeatIndex * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
|
heatIndex = roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
dewPoint = roundf(sensorDewPoint * pow(10, TemperatureDecimals)) / pow(10, TemperatureDecimals);
|
dewPoint = roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
|
||||||
if (humidity != lastHumidity || PublishAlways)
|
if (humidity != lastHumidity || PublishAlways)
|
||||||
{
|
{
|
||||||
String topic = String(mqttDeviceTopic) + "/humidity";
|
String topic = String(mqttDeviceTopic) + F("/humidity");
|
||||||
mqtt->publish(topic.c_str(), 0, false, String(humidity, HumidityDecimals).c_str());
|
mqtt->publish(topic.c_str(), 0, false, String(humidity, HumidityDecimals).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (heatIndex != lastHeatIndex || PublishAlways)
|
if (heatIndex != lastHeatIndex || PublishAlways)
|
||||||
{
|
{
|
||||||
String topic = String(mqttDeviceTopic) + "/heat_index";
|
String topic = String(mqttDeviceTopic) + F("/heat_index");
|
||||||
mqtt->publish(topic.c_str(), 0, false, String(heatIndex, TemperatureDecimals).c_str());
|
mqtt->publish(topic.c_str(), 0, false, String(heatIndex, TemperatureDecimals).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dewPoint != lastDewPoint || PublishAlways)
|
if (dewPoint != lastDewPoint || PublishAlways)
|
||||||
{
|
{
|
||||||
String topic = String(mqttDeviceTopic) + "/dew_point";
|
String topic = String(mqttDeviceTopic) + F("/dew_point");
|
||||||
mqtt->publish(topic.c_str(), 0, false, String(dewPoint, TemperatureDecimals).c_str());
|
mqtt->publish(topic.c_str(), 0, false, String(dewPoint, TemperatureDecimals).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -201,11 +278,11 @@ public:
|
|||||||
{
|
{
|
||||||
lastPressureMeasure = timer;
|
lastPressureMeasure = timer;
|
||||||
|
|
||||||
float pressure = roundf(sensorPressure * pow(10, PressureDecimals)) / pow(10, PressureDecimals);
|
float pressure = roundf(sensorPressure * powf(10, PressureDecimals)) / powf(10, PressureDecimals);
|
||||||
|
|
||||||
if (pressure != lastPressure || PublishAlways)
|
if (pressure != lastPressure || PublishAlways)
|
||||||
{
|
{
|
||||||
String topic = String(mqttDeviceTopic) + "/pressure";
|
String topic = String(mqttDeviceTopic) + F("/pressure");
|
||||||
mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(pressure, PressureDecimals).c_str());
|
mqttPressurePub = mqtt->publish(topic.c_str(), 0, true, String(pressure, PressureDecimals).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -213,4 +290,173 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* API calls te enable data exchange between WLED modules
|
||||||
|
*/
|
||||||
|
inline float getTemperatureC() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
inline float getTemperatureF() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return ((float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getHumidity() {
|
||||||
|
return (float)roundf(sensorHumidity * powf(10, HumidityDecimals));
|
||||||
|
}
|
||||||
|
inline float getPressure() {
|
||||||
|
return (float)roundf(sensorPressure * powf(10, PressureDecimals));
|
||||||
|
}
|
||||||
|
inline float getDewPointC() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getDewPointF() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return ((float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inline float getHeatIndexC() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) * 1.8f + 32;
|
||||||
|
}
|
||||||
|
}inline float getHeatIndexF() {
|
||||||
|
if (UseCelsius) {
|
||||||
|
return ((float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals) -32) * 0.56f;
|
||||||
|
} else {
|
||||||
|
return (float)roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish Sensor Information to Info Page
|
||||||
|
void addToJsonInfo(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject user = root[F("u")];
|
||||||
|
if (user.isNull()) user = root.createNestedObject(F("u"));
|
||||||
|
|
||||||
|
if (sensorType==0) //No Sensor
|
||||||
|
{
|
||||||
|
// if we sensor not detected, let the user know
|
||||||
|
JsonArray temperature_json = user.createNestedArray(F("BME/BMP280 Sensor"));
|
||||||
|
temperature_json.add(F("Not Found"));
|
||||||
|
}
|
||||||
|
else if (sensorType==2) //BMP280
|
||||||
|
{
|
||||||
|
|
||||||
|
JsonArray temperature_json = user.createNestedArray(F("Temperature"));
|
||||||
|
JsonArray pressure_json = user.createNestedArray(F("Pressure"));
|
||||||
|
temperature_json.add(roundf(sensorTemperature * powf(10, TemperatureDecimals)));
|
||||||
|
temperature_json.add(tempScale);
|
||||||
|
pressure_json.add(roundf(sensorPressure * powf(10, PressureDecimals)));
|
||||||
|
pressure_json.add(F("hPa"));
|
||||||
|
}
|
||||||
|
else if (sensorType==1) //BME280
|
||||||
|
{
|
||||||
|
JsonArray temperature_json = user.createNestedArray(F("Temperature"));
|
||||||
|
JsonArray humidity_json = user.createNestedArray(F("Humidity"));
|
||||||
|
JsonArray pressure_json = user.createNestedArray(F("Pressure"));
|
||||||
|
JsonArray heatindex_json = user.createNestedArray(F("Heat Index"));
|
||||||
|
JsonArray dewpoint_json = user.createNestedArray(F("Dew Point"));
|
||||||
|
temperature_json.add(roundf(sensorTemperature * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals));
|
||||||
|
temperature_json.add(tempScale);
|
||||||
|
humidity_json.add(roundf(sensorHumidity * powf(10, HumidityDecimals)));
|
||||||
|
humidity_json.add(F("%"));
|
||||||
|
pressure_json.add(roundf(sensorPressure * powf(10, PressureDecimals)));
|
||||||
|
pressure_json.add(F("hPa"));
|
||||||
|
heatindex_json.add(roundf(sensorHeatIndex * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals));
|
||||||
|
heatindex_json.add(tempScale);
|
||||||
|
dewpoint_json.add(roundf(sensorDewPoint * powf(10, TemperatureDecimals)) / powf(10, TemperatureDecimals));
|
||||||
|
dewpoint_json.add(tempScale);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Usermod Config Settings
|
||||||
|
void addToConfig(JsonObject& root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject(F("BME280/BMP280"));
|
||||||
|
top[F("TemperatureDecimals")] = TemperatureDecimals;
|
||||||
|
top[F("HumidityDecimals")] = HumidityDecimals;
|
||||||
|
top[F("PressureDecimals")] = PressureDecimals;
|
||||||
|
top[F("TemperatureInterval")] = TemperatureInterval;
|
||||||
|
top[F("PressureInterval")] = PressureInterval;
|
||||||
|
top[F("PublishAlways")] = PublishAlways;
|
||||||
|
top[F("UseCelsius")] = UseCelsius;
|
||||||
|
top[F("HomeAssistantDiscovery")] = HomeAssistantDiscovery;
|
||||||
|
JsonArray io_pin = top.createNestedArray(F("pin"));
|
||||||
|
for (byte i=0; i<2; i++) io_pin.add(ioPin[i]);
|
||||||
|
top[F("help4Pins")] = F("SCL,SDA"); // help for Settings page
|
||||||
|
DEBUG_PRINTLN(F("BME280 config saved."));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read Usermod Config Settings
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
int8_t newPin[2]; for (byte i=0; i<2; i++) newPin[i] = ioPin[i]; // prepare to note changed pins
|
||||||
|
|
||||||
|
JsonObject top = root[F("BME280/BMP280")];
|
||||||
|
if (top.isNull()) {
|
||||||
|
DEBUG_PRINT(F("BME280/BMP280"));
|
||||||
|
DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
bool configComplete = !top.isNull();
|
||||||
|
|
||||||
|
// A 3-argument getJsonValue() assigns the 3rd argument as a default value if the Json value is missing
|
||||||
|
configComplete &= getJsonValue(top[F("TemperatureDecimals")], TemperatureDecimals, 1);
|
||||||
|
configComplete &= getJsonValue(top[F("HumidityDecimals")], HumidityDecimals, 0);
|
||||||
|
configComplete &= getJsonValue(top[F("PressureDecimals")], PressureDecimals, 0);
|
||||||
|
configComplete &= getJsonValue(top[F("TemperatureInterval")], TemperatureInterval, 30);
|
||||||
|
configComplete &= getJsonValue(top[F("PressureInterval")], PressureInterval, 30);
|
||||||
|
configComplete &= getJsonValue(top[F("PublishAlways")], PublishAlways, false);
|
||||||
|
configComplete &= getJsonValue(top[F("UseCelsius")], UseCelsius, true);
|
||||||
|
configComplete &= getJsonValue(top[F("HomeAssistantDiscovery")], HomeAssistantDiscovery, false);
|
||||||
|
for (byte i=0; i<2; i++) configComplete &= getJsonValue(top[F("pin")][i], newPin[i], ioPin[i]);
|
||||||
|
|
||||||
|
DEBUG_PRINT(FPSTR(F("BME280/BMP280")));
|
||||||
|
if (!initDone) {
|
||||||
|
// first run: reading from cfg.json
|
||||||
|
for (byte i=0; i<2; i++) ioPin[i] = newPin[i];
|
||||||
|
DEBUG_PRINTLN(F(" config loaded."));
|
||||||
|
} else {
|
||||||
|
DEBUG_PRINTLN(F(" config (re)loaded."));
|
||||||
|
// changing parameters from settings page
|
||||||
|
bool pinsChanged = false;
|
||||||
|
for (byte i=0; i<2; i++) if (ioPin[i] != newPin[i]) { pinsChanged = true; break; } // check if any pins changed
|
||||||
|
if (pinsChanged) { //if pins changed, deallocate old pins and allocate new ones
|
||||||
|
PinOwner po = PinOwner::UM_BME280;
|
||||||
|
if (ioPin[0]==HW_PIN_SCL && ioPin[1]==HW_PIN_SDA) po = PinOwner::HW_I2C; // allow multiple allocations of HW I2C bus pins
|
||||||
|
pinManager.deallocateMultiplePins((const uint8_t *)ioPin, 2, po); // deallocate pins
|
||||||
|
for (byte i=0; i<2; i++) ioPin[i] = newPin[i];
|
||||||
|
setup();
|
||||||
|
}
|
||||||
|
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features
|
||||||
|
return !top[F("pin")].isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
return configComplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t getId() {
|
||||||
|
return USERMOD_ID_BME280;
|
||||||
|
}
|
||||||
};
|
};
|
@ -355,7 +355,7 @@ public:
|
|||||||
// Color in grayscale bitmaps if Segment 1 exists
|
// Color in grayscale bitmaps if Segment 1 exists
|
||||||
// TODO If secondary and tertiary are black, color all in primary,
|
// TODO If secondary and tertiary are black, color all in primary,
|
||||||
// else color first three from Seg 1 color slots and last three from Seg 2 color slots
|
// else color first three from Seg 1 color slots and last three from Seg 2 color slots
|
||||||
WS2812FX::Segment& seg1 = strip.getSegment(tubeSegment);
|
Segment& seg1 = strip.getSegment(tubeSegment);
|
||||||
if (seg1.isActive()) {
|
if (seg1.isActive()) {
|
||||||
digitColor = strip.getPixelColor(seg1.start + digit);
|
digitColor = strip.getPixelColor(seg1.start + digit);
|
||||||
dimming = seg1.opacity;
|
dimming = seg1.opacity;
|
||||||
|
@ -63,7 +63,7 @@ class ElekstubeIPSUsermod : public Usermod {
|
|||||||
if (!toki.isTick()) return;
|
if (!toki.isTick()) return;
|
||||||
updateLocalTime();
|
updateLocalTime();
|
||||||
|
|
||||||
WS2812FX::Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
Segment& seg1 = strip.getSegment(tfts.tubeSegment);
|
||||||
if (seg1.isActive()) {
|
if (seg1.isActive()) {
|
||||||
bool update = false;
|
bool update = false;
|
||||||
if (seg1.opacity != lastBri) update = true;
|
if (seg1.opacity != lastBri) update = true;
|
||||||
|
@ -132,7 +132,7 @@ static ArduinoFFT<float> FFT = ArduinoFFT<float>( vReal, vImag, samplesFFT, SAMP
|
|||||||
static arduinoFFT FFT = arduinoFFT(vReal, vImag, samplesFFT, SAMPLE_RATE);
|
static arduinoFFT FFT = arduinoFFT(vReal, vImag, samplesFFT, SAMPLE_RATE);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static TaskHandle_t FFT_Task;
|
static TaskHandle_t FFT_Task = nullptr;
|
||||||
|
|
||||||
float fftAddAvg(int from, int to) {
|
float fftAddAvg(int from, int to) {
|
||||||
float result = 0.0f;
|
float result = 0.0f;
|
||||||
@ -1150,24 +1150,26 @@ class AudioReactive : public Usermod {
|
|||||||
uiDomString += F("</button>");
|
uiDomString += F("</button>");
|
||||||
infoArr.add(uiDomString);
|
infoArr.add(uiDomString);
|
||||||
|
|
||||||
infoArr = user.createNestedArray(F("Input level"));
|
if (enabled) {
|
||||||
uiDomString = F("<div class=\"slider\"><div class=\"sliderwrap il\"><input class=\"noslide\" onchange=\"requestJson({");
|
infoArr = user.createNestedArray(F("Input level"));
|
||||||
uiDomString += FPSTR(_name);
|
uiDomString = F("<div class=\"slider\"><div class=\"sliderwrap il\"><input class=\"noslide\" onchange=\"requestJson({");
|
||||||
uiDomString += F(":{");
|
uiDomString += FPSTR(_name);
|
||||||
uiDomString += FPSTR(_inputLvl);
|
uiDomString += F(":{");
|
||||||
uiDomString += F(":parseInt(this.value)}});\" oninput=\"updateTrail(this);\" max=255 min=0 type=\"range\" value=");
|
uiDomString += FPSTR(_inputLvl);
|
||||||
uiDomString += inputLevel;
|
uiDomString += F(":parseInt(this.value)}});\" oninput=\"updateTrail(this);\" max=255 min=0 type=\"range\" value=");
|
||||||
uiDomString += F(" /><div class=\"sliderdisplay\"></div></div></div>"); //<output class=\"sliderbubble\"></output>
|
uiDomString += inputLevel;
|
||||||
infoArr.add(uiDomString);
|
uiDomString += F(" /><div class=\"sliderdisplay\"></div></div></div>"); //<output class=\"sliderbubble\"></output>
|
||||||
|
infoArr.add(uiDomString);
|
||||||
|
|
||||||
#ifdef WLED_DEBUG
|
#ifdef WLED_DEBUG
|
||||||
infoArr = user.createNestedArray(F("Sampling time"));
|
infoArr = user.createNestedArray(F("Sampling time"));
|
||||||
infoArr.add(sampleTime);
|
infoArr.add(sampleTime);
|
||||||
infoArr.add("ms");
|
infoArr.add("ms");
|
||||||
infoArr = user.createNestedArray(F("FFT time"));
|
infoArr = user.createNestedArray(F("FFT time"));
|
||||||
infoArr.add(fftTime-sampleTime);
|
infoArr.add(fftTime-sampleTime);
|
||||||
infoArr.add("ms");
|
infoArr.add("ms");
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1175,12 +1177,15 @@ class AudioReactive : public Usermod {
|
|||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
||||||
* Values in the state object may be modified by connected clients
|
* Values in the state object may be modified by connected clients
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
void addToJsonState(JsonObject& root)
|
void addToJsonState(JsonObject& root)
|
||||||
{
|
{
|
||||||
//root["user0"] = userVar0;
|
if (!initDone) return; // prevent crash on boot applyPreset()
|
||||||
|
JsonObject usermod = root[FPSTR(_name)];
|
||||||
|
if (usermod.isNull()) {
|
||||||
|
usermod = root.createNestedObject(FPSTR(_name));
|
||||||
|
}
|
||||||
|
usermod["on"] = enabled;
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1264,8 +1269,7 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
JsonObject sync = top.createNestedObject("sync");
|
JsonObject sync = top.createNestedObject("sync");
|
||||||
sync[F("port")] = audioSyncPort;
|
sync[F("port")] = audioSyncPort;
|
||||||
sync[F("send")] = (bool) (audioSyncEnabled & 0x01);
|
sync[F("mode")] = audioSyncEnabled;
|
||||||
sync[F("receive")] = (bool) (audioSyncEnabled & 0x02);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1305,13 +1309,8 @@ class AudioReactive : public Usermod {
|
|||||||
configComplete &= getJsonValue(top["cfg"][F("gain")], sampleGain);
|
configComplete &= getJsonValue(top["cfg"][F("gain")], sampleGain);
|
||||||
configComplete &= getJsonValue(top["cfg"][F("AGC")], soundAgc);
|
configComplete &= getJsonValue(top["cfg"][F("AGC")], soundAgc);
|
||||||
|
|
||||||
configComplete &= getJsonValue(top["sync"][F("port")], audioSyncPort);
|
configComplete &= getJsonValue(top["sync"][F("port")], audioSyncPort);
|
||||||
|
configComplete &= getJsonValue(top["sync"][F("mode")], audioSyncEnabled);
|
||||||
bool send = audioSyncEnabled & 0x01;
|
|
||||||
bool receive = audioSyncEnabled & 0x02;
|
|
||||||
configComplete &= getJsonValue(top["sync"][F("send")], send);
|
|
||||||
configComplete &= getJsonValue(top["sync"][F("receive")], receive);
|
|
||||||
audioSyncEnabled = send | (receive << 1);
|
|
||||||
|
|
||||||
return configComplete;
|
return configComplete;
|
||||||
}
|
}
|
||||||
@ -1331,6 +1330,10 @@ class AudioReactive : public Usermod {
|
|||||||
oappend(SET_F("addOption(dd,'Normal',1);"));
|
oappend(SET_F("addOption(dd,'Normal',1);"));
|
||||||
oappend(SET_F("addOption(dd,'Vivid',2);"));
|
oappend(SET_F("addOption(dd,'Vivid',2);"));
|
||||||
oappend(SET_F("addOption(dd,'Lazy',3);"));
|
oappend(SET_F("addOption(dd,'Lazy',3);"));
|
||||||
|
oappend(SET_F("dd=addDropdown('AudioReactive','sync:mode');"));
|
||||||
|
oappend(SET_F("addOption(dd,'Off',0);"));
|
||||||
|
oappend(SET_F("addOption(dd,'Send',1);"));
|
||||||
|
oappend(SET_F("addOption(dd,'Receive',2);"));
|
||||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'<i>requires reboot!</i>');")); // 0 is field type, 1 is actual field
|
oappend(SET_F("addInfo('AudioReactive:digitalmic:type',1,'<i>requires reboot!</i>');")); // 0 is field type, 1 is actual field
|
||||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'I2S SD');"));
|
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',0,'I2S SD');"));
|
||||||
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'I2S WS');"));
|
oappend(SET_F("addInfo('AudioReactive:digitalmic:pin[]',1,'I2S WS');"));
|
||||||
|
@ -96,7 +96,7 @@ class StairwayWipeUsermod : public Usermod {
|
|||||||
resetTimebase(); //make sure wipe starts from beginning
|
resetTimebase(); //make sure wipe starts from beginning
|
||||||
|
|
||||||
//set wipe direction
|
//set wipe direction
|
||||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
Segment& seg = strip.getSegment(0);
|
||||||
bool doReverse = (userVar0 == 2);
|
bool doReverse = (userVar0 == 2);
|
||||||
seg.setOption(1, doReverse);
|
seg.setOption(1, doReverse);
|
||||||
|
|
||||||
|
@ -89,7 +89,7 @@ void startWipe()
|
|||||||
resetTimebase(); //make sure wipe starts from beginning
|
resetTimebase(); //make sure wipe starts from beginning
|
||||||
|
|
||||||
//set wipe direction
|
//set wipe direction
|
||||||
WS2812FX::Segment& seg = strip.getSegment(0);
|
Segment& seg = strip.getSegment(0);
|
||||||
bool doReverse = (userVar0 == 2);
|
bool doReverse = (userVar0 == 2);
|
||||||
seg.setOption(1, doReverse);
|
seg.setOption(1, doReverse);
|
||||||
|
|
||||||
|
@ -251,6 +251,7 @@ private:
|
|||||||
* Sort either the modes or the palettes using quicksort.
|
* Sort either the modes or the palettes using quicksort.
|
||||||
*/
|
*/
|
||||||
void re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip) {
|
void re_sortModes(const char **modeNames, byte *indexes, int count, int numSkip) {
|
||||||
|
if (!modeNames) return;
|
||||||
listBeingSorted = modeNames;
|
listBeingSorted = modeNames;
|
||||||
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
|
qsort(indexes + numSkip, count - numSkip, sizeof(byte), re_qstringCmp);
|
||||||
listBeingSorted = nullptr;
|
listBeingSorted = nullptr;
|
||||||
@ -527,13 +528,13 @@ public:
|
|||||||
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
effectCurrent = modes_alpha_indexes[effectCurrentIndex];
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
strip.setMode(i, effectCurrent);
|
strip.setMode(i, effectCurrent);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
//Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
strip.setMode(strip.getMainSegmentId(), effectCurrent);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -555,13 +556,13 @@ public:
|
|||||||
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
|
effectSpeed = max(min((increase ? effectSpeed+fadeAmount : effectSpeed-fadeAmount), 255), 0);
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -583,13 +584,13 @@ public:
|
|||||||
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
|
effectIntensity = max(min((increase ? effectIntensity+fadeAmount : effectIntensity-fadeAmount), 255), 0);
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -612,22 +613,23 @@ public:
|
|||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
uint8_t id = strip.getFirstSelectedSegId();
|
uint8_t id = strip.getFirstSelectedSegId();
|
||||||
|
Segment& sid = strip.getSegment(id);
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 3: val = strip.getSegment(id).custom3 = max(min((increase ? strip.getSegment(id).custom3+fadeAmount : strip.getSegment(id).custom3-fadeAmount), 255), 0); break;
|
case 3: val = sid.custom3 = max(min((increase ? sid.custom3+fadeAmount : sid.custom3-fadeAmount), 255), 0); break;
|
||||||
case 2: val = strip.getSegment(id).custom2 = max(min((increase ? strip.getSegment(id).custom2+fadeAmount : strip.getSegment(id).custom2-fadeAmount), 255), 0); break;
|
case 2: val = sid.custom2 = max(min((increase ? sid.custom2+fadeAmount : sid.custom2-fadeAmount), 255), 0); break;
|
||||||
default: val = strip.getSegment(id).custom1 = max(min((increase ? strip.getSegment(id).custom1+fadeAmount : strip.getSegment(id).custom1-fadeAmount), 255), 0); break;
|
default: val = sid.custom1 = max(min((increase ? sid.custom1+fadeAmount : sid.custom1-fadeAmount), 255), 0); break;
|
||||||
}
|
}
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || i == id) continue;
|
if (!seg.isActive() || i == id) continue;
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 3: strip.getSegment(i).custom3 = strip.getSegment(id).custom3; break;
|
case 3: seg.custom3 = sid.custom3; break;
|
||||||
case 2: strip.getSegment(i).custom2 = strip.getSegment(id).custom2; break;
|
case 2: seg.custom2 = sid.custom2; break;
|
||||||
default: strip.getSegment(i).custom1 = strip.getSegment(id).custom1; break;
|
default: seg.custom1 = sid.custom1; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getMainSegment();
|
||||||
switch (par) {
|
switch (par) {
|
||||||
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
|
case 3: val = seg.custom3 = max(min((increase ? seg.custom3+fadeAmount : seg.custom3-fadeAmount), 255), 0); break;
|
||||||
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
|
case 2: val = seg.custom2 = max(min((increase ? seg.custom2+fadeAmount : seg.custom2-fadeAmount), 255), 0); break;
|
||||||
@ -656,13 +658,13 @@ public:
|
|||||||
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
effectPalette = palettes_alpha_indexes[effectPaletteIndex];
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.palette = effectPalette;
|
seg.palette = effectPalette;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.palette = effectPalette;
|
seg.palette = effectPalette;
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -685,13 +687,13 @@ public:
|
|||||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -714,13 +716,13 @@ public:
|
|||||||
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
|
currentSat1 = max(min((increase ? currentSat1+fadeAmount : currentSat1-fadeAmount), 255), 0);
|
||||||
colorHStoRGB(currentHue1*256, currentSat1, col);
|
colorHStoRGB(currentHue1*256, currentSat1, col);
|
||||||
if (applyToAll) {
|
if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
seg.colors[0] = RGBW32(col[0], col[1], col[2], col[3]);
|
||||||
}
|
}
|
||||||
lampUdated();
|
lampUdated();
|
||||||
@ -774,13 +776,13 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
currentCCT = max(min((increase ? currentCCT+fadeAmount : currentCCT-fadeAmount), 255), 0);
|
||||||
// if (applyToAll) {
|
// if (applyToAll) {
|
||||||
for (byte i=0; i<strip.getMaxSegments(); i++) {
|
for (byte i=0; i<strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive()) continue;
|
if (!seg.isActive()) continue;
|
||||||
seg.setCCT(currentCCT, i);
|
seg.setCCT(currentCCT);
|
||||||
}
|
}
|
||||||
// } else {
|
// } else {
|
||||||
// WS2812FX::Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
// Segment& seg = strip.getSegment(strip.getMainSegmentId());
|
||||||
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
// seg.setCCT(currentCCT, strip.getMainSegmentId());
|
||||||
// }
|
// }
|
||||||
lampUdated();
|
lampUdated();
|
||||||
|
@ -27,14 +27,14 @@ saveMacro(1, "&FX=0&R=255&G=255&B=255", false);
|
|||||||
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
//strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||||
|
|
||||||
//select first two segments (background color + FX settable)
|
//select first two segments (background color + FX settable)
|
||||||
WS2812FX::Segment &seg = strip.getSegment(0);
|
Segment &seg = strip.getSegment(0);
|
||||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((0 & 0xFF) << 8) | ((0 & 0xFF)));
|
||||||
strip.getSegment(0).setOption(0, false);
|
strip.getSegment(0).setOption(0, false);
|
||||||
strip.getSegment(0).setOption(2, false);
|
strip.getSegment(0).setOption(2, false);
|
||||||
//other segments are text
|
//other segments are text
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment &seg = strip.getSegment(i);
|
Segment &seg = strip.getSegment(i);
|
||||||
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
seg.colors[0] = ((0 << 24) | ((0 & 0xFF) << 16) | ((190 & 0xFF) << 8) | ((180 & 0xFF)));
|
||||||
strip.getSegment(i).setOption(0, true);
|
strip.getSegment(i).setOption(0, true);
|
||||||
strip.setBrightness(128);
|
strip.setBrightness(128);
|
||||||
@ -50,7 +50,7 @@ void selectWordSegments(bool state)
|
|||||||
{
|
{
|
||||||
for (int i = 1; i < 10; i++)
|
for (int i = 1; i < 10; i++)
|
||||||
{
|
{
|
||||||
//WS2812FX::Segment &seg = strip.getSegment(i);
|
//Segment &seg = strip.getSegment(i);
|
||||||
strip.getSegment(i).setOption(0, state);
|
strip.getSegment(i).setOption(0, state);
|
||||||
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
// strip.getSegment(1).setOption(SEG_OPTION_SELECTED, true);
|
||||||
//seg.mode = 12;
|
//seg.mode = 12;
|
||||||
|
3121
wled00/FX.cpp
3121
wled00/FX.cpp
File diff suppressed because it is too large
Load Diff
1315
wled00/FX.h
1315
wled00/FX.h
File diff suppressed because it is too large
Load Diff
@ -35,6 +35,7 @@
|
|||||||
// but ledmap takes care of that. ledmap is constructed upon initialization
|
// but ledmap takes care of that. ledmap is constructed upon initialization
|
||||||
// so matrix should disable regular ledmap processing
|
// so matrix should disable regular ledmap processing
|
||||||
void WS2812FX::setUpMatrix() {
|
void WS2812FX::setUpMatrix() {
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
// erase old ledmap, just in case.
|
// erase old ledmap, just in case.
|
||||||
if (customMappingTable != nullptr) delete[] customMappingTable;
|
if (customMappingTable != nullptr) delete[] customMappingTable;
|
||||||
customMappingTable = nullptr;
|
customMappingTable = nullptr;
|
||||||
@ -46,7 +47,7 @@ void WS2812FX::setUpMatrix() {
|
|||||||
|
|
||||||
// safety check
|
// safety check
|
||||||
if (matrixWidth * matrixHeight > MAX_LEDS) {
|
if (matrixWidth * matrixHeight > MAX_LEDS) {
|
||||||
matrixWidth = getLengthTotal();
|
matrixWidth = _length;
|
||||||
matrixHeight = 1;
|
matrixHeight = 1;
|
||||||
isMatrix = false;
|
isMatrix = false;
|
||||||
return;
|
return;
|
||||||
@ -94,107 +95,113 @@ void WS2812FX::setUpMatrix() {
|
|||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
// memory allocation error
|
// memory allocation error
|
||||||
matrixWidth = getLengthTotal();
|
matrixWidth = _length;
|
||||||
matrixHeight = 1;
|
matrixHeight = 1;
|
||||||
isMatrix = false;
|
isMatrix = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// not a matrix set up
|
// not a matrix set up
|
||||||
matrixWidth = getLengthTotal();
|
matrixWidth = _length;
|
||||||
matrixHeight = 1;
|
matrixHeight = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// absolute matrix version of setPixelColor()
|
||||||
|
void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, uint32_t col)
|
||||||
|
{
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (!isMatrix) return; // not a matrix set-up
|
||||||
|
uint16_t index = y * matrixWidth + x;
|
||||||
|
if (index >= _length) return;
|
||||||
|
if (index < customMappingSize) index = customMappingTable[index];
|
||||||
|
busses.setPixelColor(index, col);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// returns RGBW values of pixel
|
||||||
|
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
uint16_t index = (y * matrixWidth + x);
|
||||||
|
if (index >= _length) return 0;
|
||||||
|
if (index < customMappingSize) index = customMappingTable[index];
|
||||||
|
return busses.getPixelColor(index);
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
// Segment:: routines
|
||||||
|
///////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
// XY(x,y) - gets pixel index within current segment (often used to reference leds[] array element)
|
||||||
uint16_t IRAM_ATTR WS2812FX::XY(uint16_t x, uint16_t y) {
|
uint16_t IRAM_ATTR Segment::XY(uint16_t x, uint16_t y) {
|
||||||
uint16_t width = SEGMENT.virtualWidth(); // segment width in logical pixels
|
#ifndef WLED_DISABLE_2D
|
||||||
uint16_t height = SEGMENT.virtualHeight(); // segment height in logical pixels
|
uint16_t width = virtualWidth(); // segment width in logical pixels
|
||||||
/*
|
uint16_t height = virtualHeight(); // segment height in logical pixels
|
||||||
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) {
|
|
||||||
uint16_t t;
|
|
||||||
// swap X & Y if segment transposed
|
|
||||||
t = x; x = y; y = t;
|
|
||||||
// swap width & height if segment transposed
|
|
||||||
t = width; width = height; height = t;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
return (x%width) + (y%height) * width;
|
return (x%width) + (y%height) * width;
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// get2DPixelIndex(x,y,seg) - returns an index of segment pixel in a matrix layout
|
void IRAM_ATTR Segment::setPixelColorXY(int x, int y, uint32_t col)
|
||||||
// index still needs to undergo ledmap processing to represent actual physical pixel
|
|
||||||
// matrix is always organized by matrixHeight number of matrixWidth pixels from top to bottom, left to right
|
|
||||||
// so: pixel at get2DPixelIndex(5,6) in a 2D segment with [start=10, stop=19, startY=20, stopY=29 : 10x10 pixels]
|
|
||||||
// corresponds to pixel with logical index of 847 (0 based) if a 2D segment belongs to a 32x32 matrix.
|
|
||||||
// math: (matrixWidth * (startY + y)) + start + x => (32 * (20+6)) + 10 + 5 = 847
|
|
||||||
uint16_t IRAM_ATTR WS2812FX::get2DPixelIndex(uint16_t x, uint16_t y, uint8_t seg) {
|
|
||||||
if (seg == 255) seg = _segment_index;
|
|
||||||
x %= _segments[seg].width(); // just in case constrain x (wrap around)
|
|
||||||
y %= _segments[seg].height(); // just in case constrain y (wrap around)
|
|
||||||
return ((_segments[seg].startY + y) * matrixWidth) + _segments[seg].start + x;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR WS2812FX::setPixelColorXY(int x, int y, byte r, byte g, byte b, byte w)
|
|
||||||
{
|
{
|
||||||
if (!isMatrix) return; // not a matrix set-up
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (!strip.isMatrix) return; // not a matrix set-up
|
||||||
|
|
||||||
if (_bri_t < 255) {
|
uint8_t _bri_t = strip._bri_t;
|
||||||
r = scale8(r, _bri_t);
|
//uint8_t _bri_t = currentBri(getOption(SEG_OPTION_ON) ? opacity : 0);
|
||||||
g = scale8(g, _bri_t);
|
if (_bri_t < 255) {
|
||||||
b = scale8(b, _bri_t);
|
byte r = scale8(R(col), _bri_t);
|
||||||
w = scale8(w, _bri_t);
|
byte g = scale8(G(col), _bri_t);
|
||||||
|
byte b = scale8(B(col), _bri_t);
|
||||||
|
byte w = scale8(W(col), _bri_t);
|
||||||
|
col = RGBW32(r, g, b, w);
|
||||||
}
|
}
|
||||||
uint32_t col = RGBW32(r, g, b, w);
|
|
||||||
|
|
||||||
if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) x = SEGMENT.virtualWidth() - x - 1;
|
if (getOption(SEG_OPTION_REVERSED) ) x = virtualWidth() - x - 1;
|
||||||
if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) y = SEGMENT.virtualHeight() - y - 1;
|
if (getOption(SEG_OPTION_REVERSED_Y)) y = virtualHeight() - y - 1;
|
||||||
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
if (getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
|
|
||||||
x *= SEGMENT.groupLength(); // expand to physical pixels
|
x *= groupLength(); // expand to physical pixels
|
||||||
y *= SEGMENT.groupLength(); // expand to physical pixels
|
y *= groupLength(); // expand to physical pixels
|
||||||
if (x >= SEGMENT.width() || y >= SEGMENT.height()) return; // if pixel would fall out of segment just exit
|
if (x >= width() || y >= height()) return; // if pixel would fall out of segment just exit
|
||||||
|
|
||||||
for (uint8_t j = 0; j < SEGMENT.grouping; j++) { // groupping vertically
|
for (int j = 0; j < grouping; j++) { // groupping vertically
|
||||||
for (uint8_t g = 0; g < SEGMENT.grouping; g++) { // groupping horizontally
|
for (int g = 0; g < grouping; g++) { // groupping horizontally
|
||||||
uint16_t index, xX = (x+g), yY = (y+j);
|
uint16_t xX = (x+g), yY = (y+j);
|
||||||
if (xX >= SEGMENT.width() || yY >= SEGMENT.height()) continue; // we have reached one dimension's end
|
if (xX >= width() || yY >= height()) continue; // we have reached one dimension's end
|
||||||
|
|
||||||
//if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) xX = SEGMENT.width() - xX - 1;
|
strip.setPixelColorXY(start + xX, startY + yY, col);
|
||||||
//if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) yY = SEGMENT.height() - yY - 1;
|
|
||||||
|
|
||||||
index = get2DPixelIndex(xX, yY);
|
if (getOption(SEG_OPTION_MIRROR)) { //set the corresponding horizontally mirrored pixel
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
if (getOption(SEG_OPTION_TRANSPOSED)) strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||||
busses.setPixelColor(index, col);
|
else strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||||
|
|
||||||
if (SEGMENT.getOption(SEG_OPTION_MIRROR)) { //set the corresponding horizontally mirrored pixel
|
|
||||||
//index = get2DPixelIndex(SEGMENT.width() - xX - 1, yY);
|
|
||||||
index = SEGMENT.getOption(SEG_OPTION_TRANSPOSED) ? get2DPixelIndex(xX, SEGMENT.height() - yY - 1) : get2DPixelIndex(SEGMENT.width() - xX - 1, yY);
|
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
busses.setPixelColor(index, col);
|
|
||||||
}
|
}
|
||||||
if (SEGMENT.getOption(SEG_OPTION_MIRROR_Y)) { //set the corresponding vertically mirrored pixel
|
if (getOption(SEG_OPTION_MIRROR_Y)) { //set the corresponding vertically mirrored pixel
|
||||||
//index = get2DPixelIndex(xX, SEGMENT.height() - yY - 1);
|
if (getOption(SEG_OPTION_TRANSPOSED)) strip.setPixelColorXY(start + width() - xX - 1, startY + yY, col);
|
||||||
index = SEGMENT.getOption(SEG_OPTION_TRANSPOSED) ? get2DPixelIndex(SEGMENT.width() - xX - 1, yY) : get2DPixelIndex(xX, SEGMENT.height() - yY - 1);
|
else strip.setPixelColorXY(start + xX, startY + height() - yY - 1, col);
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
busses.setPixelColor(index, col);
|
|
||||||
}
|
}
|
||||||
if (SEGMENT.getOption(SEG_OPTION_MIRROR_Y) && SEGMENT.getOption(SEG_OPTION_MIRROR)) { //set the corresponding vertically AND horizontally mirrored pixel
|
if (getOption(SEG_OPTION_MIRROR_Y) && getOption(SEG_OPTION_MIRROR)) { //set the corresponding vertically AND horizontally mirrored pixel
|
||||||
index = get2DPixelIndex(SEGMENT.width() - xX - 1, SEGMENT.height() - yY - 1);
|
strip.setPixelColorXY(width() - xX - 1, height() - yY - 1, col);
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
busses.setPixelColor(index, col);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// anti-aliased version of setPixelColorXY()
|
// anti-aliased version of setPixelColorXY()
|
||||||
void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(float x, float y, byte r, byte g, byte b, byte w, bool aa)
|
void Segment::setPixelColorXY(float x, float y, uint32_t col, bool aa)
|
||||||
{
|
{
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
|
if (!strip.isMatrix) return; // not a matrix set-up
|
||||||
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
if (x<0.0f || x>1.0f || y<0.0f || y>1.0f) return; // not normalized
|
||||||
|
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t rows = virtualHeight();
|
||||||
|
|
||||||
float fX = x * (cols-1);
|
float fX = x * (cols-1);
|
||||||
float fY = y * (rows-1);
|
float fY = y * (rows-1);
|
||||||
@ -213,80 +220,59 @@ void /*IRAM_ATTR*/ WS2812FX::setPixelColorXY(float x, float y, byte r, byte g, b
|
|||||||
uint32_t cXRYB = getPixelColorXY(xR, yB);
|
uint32_t cXRYB = getPixelColorXY(xR, yB);
|
||||||
|
|
||||||
if (xL!=xR && yT!=yB) {
|
if (xL!=xR && yT!=yB) {
|
||||||
// blend TL pixel
|
setPixelColorXY(xL, yT, color_blend(col, cXLYT, uint8_t(sqrtf(dL*dT)*255.0f))); // blend TL pixel
|
||||||
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, uint8_t(sqrtf(dL*dT)*255.0f));
|
setPixelColorXY(xR, yT, color_blend(col, cXRYT, uint8_t(sqrtf(dR*dT)*255.0f))); // blend TR pixel
|
||||||
setPixelColorXY(xL, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
setPixelColorXY(xL, yB, color_blend(col, cXLYB, uint8_t(sqrtf(dL*dB)*255.0f))); // blend BL pixel
|
||||||
// blend TR pixel
|
setPixelColorXY(xR, yB, color_blend(col, cXRYB, uint8_t(sqrtf(dR*dB)*255.0f))); // blend BR pixel
|
||||||
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, uint8_t(sqrtf(dR*dT)*255.0f));
|
|
||||||
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
|
|
||||||
// blend BL pixel
|
|
||||||
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, uint8_t(sqrtf(dL*dB)*255.0f));
|
|
||||||
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
|
|
||||||
// blend BR pixel
|
|
||||||
cXRYB = color_blend(RGBW32(r,g,b,w), cXRYB, uint8_t(sqrtf(dR*dB)*255.0f));
|
|
||||||
setPixelColorXY(xR, yB, R(cXRYB), G(cXRYB), B(cXRYB), W(cXRYB));
|
|
||||||
} else if (xR!=xL && yT==yB) {
|
} else if (xR!=xL && yT==yB) {
|
||||||
// blend L pixel
|
setPixelColorXY(xR, yT, color_blend(col, cXLYT, uint8_t(dL*255.0f))); // blend L pixel
|
||||||
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, uint8_t(dL*255.0f));
|
setPixelColorXY(xR, yT, color_blend(col, cXRYT, uint8_t(dR*255.0f))); // blend R pixel
|
||||||
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
|
||||||
// blend R pixel
|
|
||||||
cXRYT = color_blend(RGBW32(r,g,b,w), cXRYT, uint8_t(dR*255.0f));
|
|
||||||
setPixelColorXY(xR, yT, R(cXRYT), G(cXRYT), B(cXRYT), W(cXRYT));
|
|
||||||
} else if (xR==xL && yT!=yB) {
|
} else if (xR==xL && yT!=yB) {
|
||||||
// blend T pixel
|
setPixelColorXY(xR, yT, color_blend(col, cXLYT, uint8_t(dT*255.0f))); // blend T pixel
|
||||||
cXLYT = color_blend(RGBW32(r,g,b,w), cXLYT, uint8_t(dT*255.0f));
|
setPixelColorXY(xL, yB, color_blend(col, cXLYB, uint8_t(dB*255.0f))); // blend B pixel
|
||||||
setPixelColorXY(xR, yT, R(cXLYT), G(cXLYT), B(cXLYT), W(cXLYT));
|
|
||||||
// blend B pixel
|
|
||||||
cXLYB = color_blend(RGBW32(r,g,b,w), cXLYB, uint8_t(dB*255.0f));
|
|
||||||
setPixelColorXY(xL, yB, R(cXLYB), G(cXLYB), B(cXLYB), W(cXLYB));
|
|
||||||
} else {
|
} else {
|
||||||
// exact match (x & y land on a pixel)
|
setPixelColorXY(xL, yT, col); // exact match (x & y land on a pixel)
|
||||||
setPixelColorXY(xL, yT, r, g, b, w);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), r, g, b, w);
|
setPixelColorXY(uint16_t(roundf(fX)), uint16_t(roundf(fY)), col);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns RGBW values of pixel
|
// returns RGBW values of pixel
|
||||||
uint32_t WS2812FX::getPixelColorXY(uint16_t x, uint16_t y) {
|
uint32_t Segment::getPixelColorXY(uint16_t x, uint16_t y) {
|
||||||
uint16_t index;
|
#ifndef WLED_DISABLE_2D
|
||||||
if (SEGLEN) {
|
if (getOption(SEG_OPTION_REVERSED) ) x = virtualWidth() - x - 1;
|
||||||
if (SEGMENT.getOption(SEG_OPTION_REVERSED) ) x = SEGMENT.virtualWidth() - x - 1;
|
if (getOption(SEG_OPTION_REVERSED_Y)) y = virtualHeight() - y - 1;
|
||||||
if (SEGMENT.getOption(SEG_OPTION_REVERSED_Y)) y = SEGMENT.virtualHeight() - y - 1;
|
if (getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
||||||
if (SEGMENT.getOption(SEG_OPTION_TRANSPOSED)) { uint16_t t = x; x = y; y = t; } // swap X & Y if segment transposed
|
x *= groupLength(); // expand to physical pixels
|
||||||
|
y *= groupLength(); // expand to physical pixels
|
||||||
x *= SEGMENT.groupLength(); // expand to physical pixels
|
if (x >= width() || y >= height()) return 0;
|
||||||
y *= SEGMENT.groupLength(); // expand to physical pixels
|
return strip.getPixelColorXY(start + x, startY + y);
|
||||||
if (x >= SEGMENT.width() || y >= SEGMENT.height()) return 0;
|
#else
|
||||||
|
return 0;
|
||||||
index = get2DPixelIndex(x, y);
|
#endif
|
||||||
} else {
|
|
||||||
index = y * matrixWidth + x;
|
|
||||||
}
|
|
||||||
if (index < customMappingSize) index = customMappingTable[index];
|
|
||||||
|
|
||||||
return busses.getPixelColor(index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Blends the specified color with the existing pixel color.
|
||||||
* Blends the specified color with the existing pixel color.
|
void Segment::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) {
|
||||||
*/
|
#ifndef WLED_DISABLE_2D
|
||||||
void WS2812FX::blendPixelColorXY(uint16_t x, uint16_t y, uint32_t color, uint8_t blend) {
|
|
||||||
setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend));
|
setPixelColorXY(x, y, color_blend(getPixelColorXY(x,y), color, blend));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Adds the specified color with the existing pixel color perserving color balance.
|
||||||
* Adds the specified color with the existing pixel color perserving color balance.
|
void Segment::addPixelColorXY(uint16_t x, uint16_t y, uint32_t color) {
|
||||||
*/
|
#ifndef WLED_DISABLE_2D
|
||||||
void WS2812FX::addPixelColorXY(uint16_t x, uint16_t y, uint32_t color) {
|
|
||||||
setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color));
|
setPixelColorXY(x, y, color_add(getPixelColorXY(x,y), color));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurRow: perform a blur on a row of a rectangular matrix
|
// blurRow: perform a blur on a row of a rectangular matrix
|
||||||
void WS2812FX::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) {
|
void Segment::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (row >= rows) return;
|
if (row >= rows) return;
|
||||||
// blur one row
|
// blur one row
|
||||||
@ -294,13 +280,13 @@ void WS2812FX::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) {
|
|||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t x = 0; x < cols; x++) {
|
for (uint16_t x = 0; x < cols; x++) {
|
||||||
CRGB cur = leds ? leds[XY(x,row)] : col_to_crgb(getPixelColorXY(x, row));
|
CRGB cur = leds ? leds[XY(x,row)] : CRGB(getPixelColorXY(x, row));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (x) {
|
if (x) {
|
||||||
CRGB prev = (leds ? leds[XY(x-1,row)] : col_to_crgb(getPixelColorXY(x-1, row))) + part;
|
CRGB prev = (leds ? leds[XY(x-1,row)] : CRGB(getPixelColorXY(x-1, row))) + part;
|
||||||
if (leds) leds[XY(x-1,row)] = prev;
|
if (leds) leds[XY(x-1,row)] = prev;
|
||||||
else setPixelColorXY(x-1, row, prev);
|
else setPixelColorXY(x-1, row, prev);
|
||||||
}
|
}
|
||||||
@ -308,12 +294,14 @@ void WS2812FX::blurRow(uint16_t row, fract8 blur_amount, CRGB* leds) {
|
|||||||
else setPixelColorXY(x, row, cur);
|
else setPixelColorXY(x, row, cur);
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// blurCol: perform a blur on a column of a rectangular matrix
|
// blurCol: perform a blur on a column of a rectangular matrix
|
||||||
void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
void Segment::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (col >= cols) return;
|
if (col >= cols) return;
|
||||||
// blur one column
|
// blur one column
|
||||||
@ -321,13 +309,13 @@ void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
|||||||
uint8_t seep = blur_amount >> 1;
|
uint8_t seep = blur_amount >> 1;
|
||||||
CRGB carryover = CRGB::Black;
|
CRGB carryover = CRGB::Black;
|
||||||
for (uint16_t i = 0; i < rows; i++) {
|
for (uint16_t i = 0; i < rows; i++) {
|
||||||
CRGB cur = leds ? leds[XY(col,i)] : col_to_crgb(getPixelColorXY(col, i));
|
CRGB cur = leds ? leds[XY(col,i)] : CRGB(getPixelColorXY(col, i));
|
||||||
CRGB part = cur;
|
CRGB part = cur;
|
||||||
part.nscale8(seep);
|
part.nscale8(seep);
|
||||||
cur.nscale8(keep);
|
cur.nscale8(keep);
|
||||||
cur += carryover;
|
cur += carryover;
|
||||||
if (i) {
|
if (i) {
|
||||||
CRGB prev = (leds ? leds[XY(col,i-1)] : col_to_crgb(getPixelColorXY(col, i-1))) + part;
|
CRGB prev = (leds ? leds[XY(col,i-1)] : CRGB(getPixelColorXY(col, i-1))) + part;
|
||||||
if (leds) leds[XY(col,i-1)] = prev;
|
if (leds) leds[XY(col,i-1)] = prev;
|
||||||
else setPixelColorXY(col, i-1, prev);
|
else setPixelColorXY(col, i-1, prev);
|
||||||
}
|
}
|
||||||
@ -335,6 +323,7 @@ void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
|||||||
else setPixelColorXY(col, i, cur);
|
else setPixelColorXY(col, i, cur);
|
||||||
carryover = part;
|
carryover = part;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// blur1d: one-dimensional blur filter. Spreads light to 2 line neighbors.
|
// blur1d: one-dimensional blur filter. Spreads light to 2 line neighbors.
|
||||||
@ -351,17 +340,20 @@ void WS2812FX::blurCol(uint16_t col, fract8 blur_amount, CRGB* leds) {
|
|||||||
// eventually all the way to black; this is by design so that
|
// eventually all the way to black; this is by design so that
|
||||||
// it can be used to (slowly) clear the LEDs to black.
|
// it can be used to (slowly) clear the LEDs to black.
|
||||||
|
|
||||||
void WS2812FX::blur1d(CRGB* leds, fract8 blur_amount) {
|
void Segment::blur1d(CRGB* leds, fract8 blur_amount) {
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
#ifndef WLED_DISABLE_2D
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for (uint16_t y = 0; y < rows; y++) blurRow(y, blur_amount, leds);
|
for (uint16_t y = 0; y < rows; y++) blurRow(y, blur_amount, leds);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
// 1D Box blur (with added weight - blur_amount: [0=no blur, 255=max blur])
|
||||||
void WS2812FX::blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds) {
|
void Segment::blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
const uint16_t dim1 = vertical ? rows : cols;
|
const uint16_t rows = virtualHeight();
|
||||||
const uint16_t dim2 = vertical ? cols : rows;
|
const uint16_t dim1 = vertical ? rows : cols;
|
||||||
|
const uint16_t dim2 = vertical ? cols : rows;
|
||||||
if (i >= dim2) return;
|
if (i >= dim2) return;
|
||||||
const float seep = blur_amount/255.f;
|
const float seep = blur_amount/255.f;
|
||||||
const float keep = 3.f - 2.f*seep;
|
const float keep = 3.f - 2.f*seep;
|
||||||
@ -374,9 +366,9 @@ void WS2812FX::blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds)
|
|||||||
uint16_t yp = vertical ? y-1 : y;
|
uint16_t yp = vertical ? y-1 : y;
|
||||||
uint16_t xn = vertical ? x : x+1;
|
uint16_t xn = vertical ? x : x+1;
|
||||||
uint16_t yn = vertical ? y+1 : y;
|
uint16_t yn = vertical ? y+1 : y;
|
||||||
CRGB curr = leds ? leds[XY(x,y)] : col_to_crgb(getPixelColorXY(x,y));
|
CRGB curr = leds ? leds[XY(x,y)] : CRGB(getPixelColorXY(x,y));
|
||||||
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : (leds ? leds[XY(xp,yp)] : col_to_crgb(getPixelColorXY(xp,yp)));
|
CRGB prev = (xp<0 || yp<0) ? CRGB::Black : (leds ? leds[XY(xp,yp)] : CRGB(getPixelColorXY(xp,yp)));
|
||||||
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : (leds ? leds[XY(xn,yn)] : col_to_crgb(getPixelColorXY(xn,yn)));
|
CRGB next = ((vertical && yn>=dim1) || (!vertical && xn>=dim1)) ? CRGB::Black : (leds ? leds[XY(xn,yn)] : CRGB(getPixelColorXY(xn,yn)));
|
||||||
uint16_t r, g, b;
|
uint16_t r, g, b;
|
||||||
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
r = (curr.r*keep + (prev.r + next.r)*seep) / 3;
|
||||||
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
g = (curr.g*keep + (prev.g + next.g)*seep) / 3;
|
||||||
@ -389,63 +381,65 @@ void WS2812FX::blur1d(uint16_t i, bool vertical, fract8 blur_amount, CRGB* leds)
|
|||||||
if (leds) leds[XY(x,y)] = tmp[j];
|
if (leds) leds[XY(x,y)] = tmp[j];
|
||||||
else setPixelColorXY(x, y, tmp[j]);
|
else setPixelColorXY(x, y, tmp[j]);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::blur2d(CRGB* leds, fract8 blur_amount) {
|
void Segment::blur2d(CRGB* leds, fract8 blur_amount) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for (uint16_t i = 0; i < rows; i++) blurRow(i, blur_amount, leds); // blur all rows
|
for (uint16_t i = 0; i < rows; i++) blurRow(i, blur_amount, leds); // blur all rows
|
||||||
for (uint16_t k = 0; k < cols; k++) blurCol(k, blur_amount, leds); // blur all columns
|
for (uint16_t k = 0; k < cols; k++) blurCol(k, blur_amount, leds); // blur all columns
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::moveX(CRGB *leds, int8_t delta) {
|
void Segment::moveX(CRGB *leds, int8_t delta) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
if (!delta) return;
|
if (!delta) return;
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
for (uint8_t y = 0; y < rows; y++) for (uint8_t x = 0; x < cols-1; x++) {
|
for (uint8_t y = 0; y < rows; y++) for (uint8_t x = 0; x < cols-1; x++) {
|
||||||
|
if (x + delta >= cols) break;
|
||||||
if (leds) leds[XY(x, y)] = leds[XY((x + delta)%cols, y)];
|
if (leds) leds[XY(x, y)] = leds[XY((x + delta)%cols, y)];
|
||||||
else setPixelColorXY(x, y, getPixelColorXY((x + delta)%cols, y));
|
else setPixelColorXY(x, y, getPixelColorXY((x + delta)%cols, y));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t y = 0; y < rows; y++) for (int16_t x = cols-1; x >= 0; x--) {
|
for (uint8_t y = 0; y < rows; y++) for (int16_t x = cols-1; x >= 0; x--) {
|
||||||
if (x + delta < 0) {
|
if (x + delta < 0) break;
|
||||||
if (leds) leds[XY(x, y)] = leds[XY(cols + delta, y)];
|
if (leds) leds[XY(x, y)] = leds[XY(x + delta, y)];
|
||||||
else setPixelColorXY(x, y, getPixelColorXY(cols + delta, y));
|
else setPixelColorXY(x, y, getPixelColorXY(x + delta, y));
|
||||||
} else {
|
|
||||||
if (leds) leds[XY(x, y)] = leds[XY(x + delta, y)];
|
|
||||||
else setPixelColorXY(x, y, getPixelColorXY(x + delta, y));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::moveY(CRGB *leds, int8_t delta) {
|
void Segment::moveY(CRGB *leds, int8_t delta) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
if (!delta) return;
|
if (!delta) return;
|
||||||
if (delta > 0) {
|
if (delta > 0) {
|
||||||
for (uint8_t x = 0; x < cols; x++) for (uint8_t y = 0; y < rows-1; y++) {
|
for (uint8_t x = 0; x < cols; x++) for (uint8_t y = 0; y < rows-1; y++) {
|
||||||
if (leds) leds[XY(x, y)] = leds[XY(x, (y + delta)%rows)];
|
if (y + delta >= rows) break;
|
||||||
else setPixelColorXY(x, y, getPixelColorXY(x, (y + delta)%rows));
|
if (leds) leds[XY(x, y)] = leds[XY(x, (y + delta))];
|
||||||
|
else setPixelColorXY(x, y, getPixelColorXY(x, (y + delta)));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (uint8_t x = 0; x < cols; x++) for (int16_t y = rows-1; y >= 0; y--) {
|
for (uint8_t x = 0; x < cols; x++) for (int16_t y = rows-1; y >= 0; y--) {
|
||||||
if (y + delta < 0) {
|
if (y + delta < 0) break;
|
||||||
if (leds) leds[XY(x, y)] = leds[XY(x, rows + delta)];
|
if (leds) leds[XY(x, y)] = leds[XY(x, y + delta)];
|
||||||
else setPixelColorXY(x, y, getPixelColorXY(x, rows + delta));
|
else setPixelColorXY(x, y, getPixelColorXY(x, y + delta));
|
||||||
} else {
|
|
||||||
if (leds) leds[XY(x, y)] = leds[XY(x, y + delta)];
|
|
||||||
else setPixelColorXY(x, y, getPixelColorXY(x, y + delta));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// move() - move all pixels in desired direction delta number of pixels
|
// move() - move all pixels in desired direction delta number of pixels
|
||||||
// @param dir direction: 0=left, 1=left-up, 2=up, 3=right-up, 4=right, 5=right-down, 6=down, 7=left-down
|
// @param dir direction: 0=left, 1=left-up, 2=up, 3=right-up, 4=right, 5=right-down, 6=down, 7=left-down
|
||||||
// @param delta number of pixels to move
|
// @param delta number of pixels to move
|
||||||
void WS2812FX::move(uint8_t dir, uint8_t delta, CRGB *leds) {
|
void Segment::move(uint8_t dir, uint8_t delta, CRGB *leds) {
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
if (delta==0) return;
|
if (delta==0) return;
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 0: moveX(leds, delta); break;
|
case 0: moveX(leds, delta); break;
|
||||||
@ -457,21 +451,25 @@ void WS2812FX::move(uint8_t dir, uint8_t delta, CRGB *leds) {
|
|||||||
case 6: moveY(leds,-delta); break;
|
case 6: moveY(leds,-delta); break;
|
||||||
case 7: moveX(leds, delta); moveY(leds,-delta); break;
|
case 7: moveX(leds, delta); moveY(leds,-delta); break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::fill_solid(CRGB* leds, CRGB color) {
|
void Segment::fill_solid(CRGB* leds, CRGB color) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
if (leds) leds[XY(x,y)] = color;
|
if (leds) leds[XY(x,y)] = color;
|
||||||
else setPixelColorXY(x, y, color);
|
else setPixelColorXY(x, y, color);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
// by stepko, taken from https://editor.soulmatelights.com/gallery/573-blobs
|
||||||
void WS2812FX::fill_circle(CRGB* leds, uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
void Segment::fill_circle(CRGB* leds, uint16_t cx, uint16_t cy, uint8_t radius, CRGB col) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for (int16_t y = -radius; y <= radius; y++) {
|
for (int16_t y = -radius; y <= radius; y++) {
|
||||||
for (int16_t x = -radius; x <= radius; x++) {
|
for (int16_t x = -radius; x <= radius; x++) {
|
||||||
if (x * x + y * y <= radius * radius &&
|
if (x * x + y * y <= radius * radius &&
|
||||||
@ -480,31 +478,39 @@ void WS2812FX::fill_circle(CRGB* leds, uint16_t cx, uint16_t cy, uint8_t radius,
|
|||||||
leds[XY(cx + x, cy + y)] += col;
|
leds[XY(cx + x, cy + y)] += col;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::fadeToBlackBy(CRGB* leds, uint8_t fadeBy) {
|
void Segment::fadeToBlackBy(CRGB* leds, uint8_t fadeBy) {
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
nscale8(leds, 255 - fadeBy);
|
nscale8(leds, 255 - fadeBy);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::nscale8(CRGB* leds, uint8_t scale) {
|
void Segment::nscale8(CRGB* leds, uint8_t scale) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
for(uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) {
|
||||||
if (leds) leds[XY(x,y)].nscale8(scale);
|
if (leds) leds[XY(x,y)].nscale8(scale);
|
||||||
else setPixelColorXY(x, y, col_to_crgb(getPixelColorXY(x, y)).nscale8(scale));
|
else setPixelColorXY(x, y, CRGB(getPixelColorXY(x, y)).nscale8(scale));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void WS2812FX::setPixels(CRGB* leds) {
|
void Segment::setPixels(CRGB* leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) setPixelColorXY(x, y, leds[XY(x,y)]);
|
for (uint16_t y = 0; y < rows; y++) for (uint16_t x = 0; x < cols; x++) setPixelColorXY(x, y, leds[XY(x,y)]);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//line function
|
//line function
|
||||||
void WS2812FX::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, CRGB *leds) {
|
void Segment::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB c, CRGB *leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
if (x0 >= cols || x1 >= cols || y0 >= rows || y1 >= rows) return;
|
||||||
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
const int16_t dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
|
||||||
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
const int16_t dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
|
||||||
@ -517,8 +523,10 @@ void WS2812FX::drawLine(uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, CRGB
|
|||||||
if (e2 >-dx) { err -= dy; x0 += sx; }
|
if (e2 >-dx) { err -= dy; x0 += sx; }
|
||||||
if (e2 < dy) { err += dx; y0 += sy; }
|
if (e2 < dy) { err += dx; y0 += sy; }
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
// font curtesy of https://github.com/idispatch/raster-fonts
|
// font curtesy of https://github.com/idispatch/raster-fonts
|
||||||
static const unsigned char console_font_6x8[] PROGMEM = {
|
static const unsigned char console_font_6x8[] PROGMEM = {
|
||||||
|
|
||||||
@ -4527,10 +4535,10 @@ static const unsigned char console_font_5x8[] PROGMEM = {
|
|||||||
0x00, /* 00000 */
|
0x00, /* 00000 */
|
||||||
0x00, /* 00000 */
|
0x00, /* 00000 */
|
||||||
0x90, /* 10010 */
|
0x90, /* 10010 */
|
||||||
0x90, /* 10010 */
|
|
||||||
0xF0, /* 11110 */
|
0xF0, /* 11110 */
|
||||||
0x90, /* 10010 */
|
0x90, /* 10010 */
|
||||||
0x90, /* 10010 */
|
0x90, /* 10010 */
|
||||||
|
0x90, /* 10010 */
|
||||||
0x00, /* 00000 */
|
0x00, /* 00000 */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -6669,19 +6677,21 @@ static const unsigned char console_font_5x8[] PROGMEM = {
|
|||||||
0x00, /* 00000 */
|
0x00, /* 00000 */
|
||||||
0x00, /* 00000 */
|
0x00, /* 00000 */
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
// draws a raster font character on canvas
|
// draws a raster font character on canvas
|
||||||
// only supports 5x8 and 6x8 fonts ATM
|
// only supports 5x8 and 6x8 fonts ATM
|
||||||
void WS2812FX::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color, CRGB *leds) {
|
void Segment::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w, uint8_t h, CRGB color, CRGB *leds) {
|
||||||
const uint16_t cols = SEGMENT.virtualWidth();
|
#ifndef WLED_DISABLE_2D
|
||||||
const uint16_t rows = SEGMENT.virtualHeight();
|
const uint16_t cols = virtualWidth();
|
||||||
|
const uint16_t rows = virtualHeight();
|
||||||
|
|
||||||
if (w<5 || w>6 || h!=8) return;
|
if (w<5 || w>6 || h!=8) return;
|
||||||
for (uint8_t i = 0; i<h; i++) { // character height
|
for (uint8_t i = 0; i<h; i++) { // character height
|
||||||
int16_t y0 = y + i;
|
int16_t y0 = y + i;
|
||||||
if (y0 < 0) continue; // drawing off-screen
|
if (y0 < 0) continue; // drawing off-screen
|
||||||
if (y0 >= rows) break; // drawing off-screen
|
if (y0 >= rows) break; // drawing off-screen
|
||||||
uint8_t bits;
|
uint8_t bits = 0;
|
||||||
switch (w) {
|
switch (w) {
|
||||||
case 5: bits = pgm_read_byte_near(&console_font_5x8[(chr * 8) + i]); break;
|
case 5: bits = pgm_read_byte_near(&console_font_5x8[(chr * 8) + i]); break;
|
||||||
case 6: bits = pgm_read_byte_near(&console_font_6x8[(chr * 8) + i]); break;
|
case 6: bits = pgm_read_byte_near(&console_font_6x8[(chr * 8) + i]); break;
|
||||||
@ -6694,10 +6704,12 @@ void WS2812FX::drawCharacter(unsigned char chr, int16_t x, int16_t y, uint8_t w,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))
|
#define WU_WEIGHT(a,b) ((uint8_t) (((a)*(b)+(a)+(b))>>8))
|
||||||
void WS2812FX::wu_pixel(CRGB *leds, uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
void Segment::wu_pixel(CRGB *leds, uint32_t x, uint32_t y, CRGB c) { //awesome wu_pixel procedure by reddit u/sutaburosu
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
// extract the fractional parts and derive their inverses
|
// extract the fractional parts and derive their inverses
|
||||||
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
uint8_t xx = x & 0xff, yy = y & 0xff, ix = 255 - xx, iy = 255 - yy;
|
||||||
// calculate the intensities for each affected pixel
|
// calculate the intensities for each affected pixel
|
||||||
@ -6710,5 +6722,6 @@ void WS2812FX::wu_pixel(CRGB *leds, uint32_t x, uint32_t y, CRGB c) { //awe
|
|||||||
leds[xy].g = qadd8(leds[xy].g, c.g * wu[i] >> 8);
|
leds[xy].g = qadd8(leds[xy].g, c.g * wu[i] >> 8);
|
||||||
leds[xy].b = qadd8(leds[xy].b, c.b * wu[i] >> 8);
|
leds[xy].b = qadd8(leds[xy].b, c.b * wu[i] >> 8);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#undef WU_WEIGHT
|
#undef WU_WEIGHT
|
||||||
|
1656
wled00/FX_fcn.cpp
1656
wled00/FX_fcn.cpp
File diff suppressed because it is too large
Load Diff
@ -195,11 +195,11 @@ void handleAnalog(uint8_t b)
|
|||||||
colorHStoRGB(aRead*256,255,col);
|
colorHStoRGB(aRead*256,255,col);
|
||||||
} else {
|
} else {
|
||||||
// otherwise use "double press" for segment selection
|
// otherwise use "double press" for segment selection
|
||||||
WS2812FX::Segment& seg = strip.getSegment(macroDoublePress[b]);
|
Segment& seg = strip.getSegment(macroDoublePress[b]);
|
||||||
if (aRead == 0) {
|
if (aRead == 0) {
|
||||||
seg.setOption(SEG_OPTION_ON, 0); // off
|
seg.setOption(SEG_OPTION_ON, 0); // off
|
||||||
} else {
|
} else {
|
||||||
seg.setOpacity(aRead, macroDoublePress[b]);
|
seg.setOpacity(aRead);
|
||||||
seg.setOption(SEG_OPTION_ON, 1);
|
seg.setOption(SEG_OPTION_ON, 1);
|
||||||
}
|
}
|
||||||
// this will notify clients of update (websockets,mqtt,etc)
|
// this will notify clients of update (websockets,mqtt,etc)
|
||||||
|
@ -91,6 +91,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
Bus::setCCTBlend(strip.cctBlending);
|
Bus::setCCTBlend(strip.cctBlending);
|
||||||
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
strip.setTargetFps(hw_led["fps"]); //NOP if 0, default 42 FPS
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
// 2D Matrix Settings
|
// 2D Matrix Settings
|
||||||
JsonObject matrix = hw_led[F("matrix")];
|
JsonObject matrix = hw_led[F("matrix")];
|
||||||
if (!matrix.isNull()) {
|
if (!matrix.isNull()) {
|
||||||
@ -125,6 +126,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
|
|
||||||
strip.setUpMatrix();
|
strip.setUpMatrix();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
JsonArray ins = hw_led["ins"];
|
JsonArray ins = hw_led["ins"];
|
||||||
|
|
||||||
@ -132,6 +134,7 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
uint8_t s = 0; // bus iterator
|
uint8_t s = 0; // bus iterator
|
||||||
if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback
|
if (fromFS) busses.removeAll(); // can't safely manipulate busses directly in network callback
|
||||||
uint32_t mem = 0;
|
uint32_t mem = 0;
|
||||||
|
bool busesChanged = false;
|
||||||
for (JsonObject elm : ins) {
|
for (JsonObject elm : ins) {
|
||||||
if (s >= WLED_MAX_BUSSES) break;
|
if (s >= WLED_MAX_BUSSES) break;
|
||||||
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
uint8_t pins[5] = {255, 255, 255, 255, 255};
|
||||||
@ -161,10 +164,11 @@ bool deserializeConfig(JsonObject doc, bool fromFS) {
|
|||||||
} else {
|
} else {
|
||||||
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
||||||
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode);
|
busConfigs[s] = new BusConfig(ledType, pins, start, length, colorOrder, reversed, skipFirst, AWmode);
|
||||||
doInitBusses = true;
|
busesChanged = true;
|
||||||
}
|
}
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
|
doInitBusses = busesChanged;
|
||||||
// finalization done in beginStrip()
|
// finalization done in beginStrip()
|
||||||
}
|
}
|
||||||
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
|
if (hw_led["rev"]) busses.getBus(0)->reversed = true; //set 0.11 global reversed setting for first bus
|
||||||
@ -618,6 +622,7 @@ void serializeConfig() {
|
|||||||
hw_led["fps"] = strip.getTargetFps();
|
hw_led["fps"] = strip.getTargetFps();
|
||||||
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
hw_led[F("rgbwm")] = Bus::getAutoWhiteMode(); // global override
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
// 2D Matrix Settings
|
// 2D Matrix Settings
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
JsonObject matrix = hw_led.createNestedObject(F("matrix"));
|
||||||
@ -639,6 +644,7 @@ void serializeConfig() {
|
|||||||
pnl["s"] = strip.panel[i].serpentine;
|
pnl["s"] = strip.panel[i].serpentine;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
JsonArray hw_led_ins = hw_led.createNestedArray("ins");
|
||||||
|
|
||||||
|
@ -1,12 +1,57 @@
|
|||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Color conversion methods
|
* Color conversion & utility methods
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color blend function
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR color_blend(uint32_t color1, uint32_t color2, uint16_t blend, bool b16) {
|
||||||
|
if(blend == 0) return color1;
|
||||||
|
uint16_t blendmax = b16 ? 0xFFFF : 0xFF;
|
||||||
|
if(blend == blendmax) return color2;
|
||||||
|
uint8_t shift = b16 ? 16 : 8;
|
||||||
|
|
||||||
|
uint32_t w1 = W(color1);
|
||||||
|
uint32_t r1 = R(color1);
|
||||||
|
uint32_t g1 = G(color1);
|
||||||
|
uint32_t b1 = B(color1);
|
||||||
|
|
||||||
|
uint32_t w2 = W(color2);
|
||||||
|
uint32_t r2 = R(color2);
|
||||||
|
uint32_t g2 = G(color2);
|
||||||
|
uint32_t b2 = B(color2);
|
||||||
|
|
||||||
|
uint32_t w3 = ((w2 * blend) + (w1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t r3 = ((r2 * blend) + (r1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t g3 = ((g2 * blend) + (g1 * (blendmax - blend))) >> shift;
|
||||||
|
uint32_t b3 = ((b2 * blend) + (b1 * (blendmax - blend))) >> shift;
|
||||||
|
|
||||||
|
return RGBW32(r3, g3, b3, w3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* color add function that preserves ratio
|
||||||
|
* idea: https://github.com/Aircoookie/WLED/pull/2465 by https://github.com/Proto-molecule
|
||||||
|
*/
|
||||||
|
uint32_t color_add(uint32_t c1, uint32_t c2)
|
||||||
|
{
|
||||||
|
uint32_t r = R(c1) + R(c2);
|
||||||
|
uint32_t g = G(c1) + G(c2);
|
||||||
|
uint32_t b = B(c1) + B(c2);
|
||||||
|
uint32_t w = W(c1) + W(c2);
|
||||||
|
uint16_t max = r;
|
||||||
|
if (g > max) max = g;
|
||||||
|
if (b > max) max = b;
|
||||||
|
if (w > max) max = w;
|
||||||
|
if (max < 256) return RGBW32(r, g, b, w);
|
||||||
|
else return RGBW32(r * 255 / max, g * 255 / max, b * 255 / max, w * 255 / max);
|
||||||
|
}
|
||||||
|
|
||||||
void setRandomColor(byte* rgb)
|
void setRandomColor(byte* rgb)
|
||||||
{
|
{
|
||||||
lastRandomIndex = strip.get_random_wheel_index(lastRandomIndex);
|
lastRandomIndex = strip.getMainSegment().get_random_wheel_index(lastRandomIndex);
|
||||||
colorHStoRGB(lastRandomIndex*256,255,rgb);
|
colorHStoRGB(lastRandomIndex*256,255,rgb);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,6 +5,8 @@
|
|||||||
* Readability defines and their associated numerical values + compile-time constants
|
* Readability defines and their associated numerical values + compile-time constants
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define GRADIENT_PALETTE_COUNT 58
|
||||||
|
|
||||||
//Defaults
|
//Defaults
|
||||||
#define DEFAULT_CLIENT_SSID "Your_Network"
|
#define DEFAULT_CLIENT_SSID "Your_Network"
|
||||||
#define DEFAULT_AP_PASS "wled1234"
|
#define DEFAULT_AP_PASS "wled1234"
|
||||||
@ -76,7 +78,8 @@
|
|||||||
#define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h"
|
#define USERMOD_ID_WORDCLOCK 27 //Usermod "usermod_v2_word_clock.h"
|
||||||
#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h"
|
#define USERMOD_ID_MY9291 28 //Usermod "usermod_MY9291.h"
|
||||||
#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h"
|
#define USERMOD_ID_SI7021_MQTT_HA 29 //Usermod "usermod_si7021_mqtt_ha.h"
|
||||||
#define USERMOD_ID_AUDIOREACTIVE 30 //Usermod "audioreactive.h"
|
#define USERMOD_ID_BME280 30 //Usermod "usermod_bme280.h
|
||||||
|
#define USERMOD_ID_AUDIOREACTIVE 31 //Usermod "audioreactive.h"
|
||||||
|
|
||||||
//Access point behavior
|
//Access point behavior
|
||||||
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
#define AP_BEHAVIOR_BOOT_NO_CONN 0 //Open AP when no connection after boot
|
||||||
@ -223,6 +226,7 @@
|
|||||||
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
|
#define SEG_OPTION_MIRROR 3 //Indicates that the effect will be mirrored within the segment
|
||||||
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
|
#define SEG_OPTION_NONUNITY 4 //Indicates that the effect does not use FRAMETIME or needs getPixelColor
|
||||||
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
#define SEG_OPTION_FREEZE 5 //Segment contents will not be refreshed
|
||||||
|
#define SEG_OPTION_RESET 6 //Segment runtime requires reset
|
||||||
#define SEG_OPTION_TRANSITIONAL 7
|
#define SEG_OPTION_TRANSITIONAL 7
|
||||||
#define SEG_OPTION_REVERSED_Y 8
|
#define SEG_OPTION_REVERSED_Y 8
|
||||||
#define SEG_OPTION_MIRROR_Y 9
|
#define SEG_OPTION_MIRROR_Y 9
|
||||||
@ -358,4 +362,46 @@
|
|||||||
|
|
||||||
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
|
#define INTERFACE_UPDATE_COOLDOWN 2000 //time in ms to wait between websockets, alexa, and MQTT updates
|
||||||
|
|
||||||
|
#if defined(ESP8266) && defined(HW_PIN_SCL)
|
||||||
|
#undef HW_PIN_SCL
|
||||||
|
#endif
|
||||||
|
#if defined(ESP8266) && defined(HW_PIN_SDA)
|
||||||
|
#undef HW_PIN_SDA
|
||||||
|
#endif
|
||||||
|
#ifndef HW_PIN_SCL
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define HW_PIN_SCL 5
|
||||||
|
#else
|
||||||
|
#define HW_PIN_SCL 22
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef HW_PIN_SDA
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define HW_PIN_SDA 4
|
||||||
|
#else
|
||||||
|
#define HW_PIN_SDA 21
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP8266) && defined(HW_PIN_CLOCKSPI)
|
||||||
|
#undef HW_PIN_CLOCKSPI
|
||||||
|
#endif
|
||||||
|
#if defined(ESP8266) && defined(HW_PIN_DATASPI)
|
||||||
|
#undef HW_PIN_DATASPI
|
||||||
|
#endif
|
||||||
|
#ifndef HW_PIN_CLOCKSPI
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define HW_PIN_CLOCKSPI 14
|
||||||
|
#else
|
||||||
|
#define HW_PIN_CLOCKSPI 18
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
#ifndef HW_PIN_DATASPI
|
||||||
|
#ifdef ESP8266
|
||||||
|
#define HW_PIN_DATASPI 13
|
||||||
|
#else
|
||||||
|
#define HW_PIN_DATASPI 23
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -193,7 +193,7 @@ button {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 8px;
|
top: 8px;
|
||||||
left: 12px;
|
left: 12px;
|
||||||
pointer-events: none;
|
/*pointer-events: none;*/
|
||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
}
|
}
|
||||||
@ -368,7 +368,7 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#sliders {
|
#sliders {
|
||||||
width: 310px;
|
width: 300px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
position: sticky;
|
position: sticky;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
@ -380,18 +380,34 @@ button {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.slider {
|
.slider {
|
||||||
background: var(--c-2);
|
background-color: var(--c-2);
|
||||||
max-width: 310px;
|
max-width: 300px;
|
||||||
min-width: 280px;
|
min-width: 280px;
|
||||||
margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */
|
margin: 0 auto; /* add 5px; if you want some vertical space but looks ugly */
|
||||||
border-radius: 15px;
|
border-radius: 24px;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter {
|
||||||
|
background-color: var(--c-4);
|
||||||
|
box-shadow: 0px 0px 6px 6px var(--c-1);
|
||||||
|
border-radius: 26px;
|
||||||
|
height: 26px;
|
||||||
|
margin: 0 auto 4px; /* 8px if you want space */
|
||||||
|
padding: 8px 2px;
|
||||||
|
position: relative;
|
||||||
|
/*width: 260px;*/
|
||||||
|
/*transition: opacity 1s;*/
|
||||||
|
/*opacity: 1;*/
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Tooltip text */
|
/* Tooltip text */
|
||||||
.slider .tooltiptext {
|
.slider .tooltiptext {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
background-color: var(--c-5);
|
background-color: var(--c-5);
|
||||||
|
/*border: 2px solid var(--c-2);*/
|
||||||
|
box-shadow: 4px 4px 10px 4px var(--c-1);
|
||||||
color: var(--c-f);
|
color: var(--c-f);
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
@ -447,6 +463,10 @@ button {
|
|||||||
.hide {
|
.hide {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
.fade {
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.first {
|
.first {
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
@ -827,19 +847,22 @@ input[type=range]::-moz-range-thumb {
|
|||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
padding: 4px;
|
padding: 4px 8px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: 19px;
|
font-size: 19px;
|
||||||
background-color: var(--c-3);
|
background-color: var(--c-3);
|
||||||
color: var(--c-d);
|
color: var(--c-d);
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border: 1px solid var(--c-2);
|
border: 0 solid var(--c-2);
|
||||||
border-radius: 5px;
|
border-radius: 20px;
|
||||||
transition-duration: 0.5s;
|
transition-duration: 0.5s;
|
||||||
-webkit-backface-visibility: hidden;
|
-webkit-backface-visibility: hidden;
|
||||||
-webkit-transform:translate3d(0,0,0);
|
-webkit-transform:translate3d(0,0,0);
|
||||||
|
-webkit-appearance: none;
|
||||||
|
-moz-appearance: none;
|
||||||
backface-visibility: hidden;
|
backface-visibility: hidden;
|
||||||
transform:translate3d(0,0,0);
|
transform:translate3d(0,0,0);
|
||||||
|
text-overflow: ellipsis;
|
||||||
}
|
}
|
||||||
#tt {
|
#tt {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -847,16 +870,26 @@ select {
|
|||||||
.cl {
|
.cl {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
}
|
}
|
||||||
.sel-p {
|
select.sel-p, select.sel-pl, select.sel-ple {
|
||||||
margin: 5px 0 10px;
|
margin: 5px 0;
|
||||||
width: 5em;
|
|
||||||
}
|
|
||||||
.sel-pl {
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
background-position: 141px 16px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
.sel-ple {
|
div.sel-p {
|
||||||
width: 100%;
|
position: relative;
|
||||||
|
}
|
||||||
|
div.sel-p:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
right: 10px;
|
||||||
|
top: 22px;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
border-left: 8px solid transparent;
|
||||||
|
border-right: 8px solid transparent;
|
||||||
|
border-top: 8px solid var(--c-f);
|
||||||
|
}
|
||||||
|
select.sel-ple {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
option {
|
option {
|
||||||
@ -1173,6 +1206,25 @@ TD .checkmark, TD .radiomark {
|
|||||||
left: 9px;
|
left: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter .fchkl {
|
||||||
|
display: inline-block;
|
||||||
|
min-width: 0.7em;
|
||||||
|
padding: 4px 4px 4px 32px;
|
||||||
|
text-align: left;
|
||||||
|
line-height: 24px;
|
||||||
|
vertical-align: middle;
|
||||||
|
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||||
|
filter: grayscale(100%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.lbl-s {
|
||||||
|
display: inline-block;
|
||||||
|
/* margin: 10px 4px 0 0; */
|
||||||
|
font-size: 13px;
|
||||||
|
width: 48%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
/* list wrapper */
|
/* list wrapper */
|
||||||
.list {
|
.list {
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -1226,6 +1278,7 @@ TD .checkmark, TD .radiomark {
|
|||||||
.lstI.sticky,
|
.lstI.sticky,
|
||||||
.lstI.selected {
|
.lstI.selected {
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
box-shadow: 0px 0px 10px 4px var(--c-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#pcont .selected:not([class*="expanded"]) {
|
#pcont .selected:not([class*="expanded"]) {
|
||||||
@ -1258,6 +1311,9 @@ TD .checkmark, TD .radiomark {
|
|||||||
/* list item name (for sorting) */
|
/* list item name (for sorting) */
|
||||||
.lstIname {
|
.lstIname {
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||||
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* list item palette preview */
|
/* list item palette preview */
|
||||||
@ -1287,6 +1343,8 @@ TD .checkmark, TD .radiomark {
|
|||||||
border-radius: 21px;
|
border-radius: 21px;
|
||||||
background: var(--c-2);
|
background: var(--c-2);
|
||||||
border: 1px solid var(--c-3);
|
border: 1px solid var(--c-3);
|
||||||
|
-webkit-filter: grayscale(100%); /* Safari 6.0 - 9.0 */
|
||||||
|
filter: grayscale(100%);
|
||||||
}
|
}
|
||||||
|
|
||||||
.fnd input[type="text"]:focus {
|
.fnd input[type="text"]:focus {
|
||||||
|
@ -202,7 +202,7 @@
|
|||||||
<div class="staytop fnd" id="fxFind">
|
<div class="staytop fnd" id="fxFind">
|
||||||
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist')" />
|
<input type="text" placeholder="Search" oninput="search(this,'fxlist')" onfocus="search(this,'fxlist')" />
|
||||||
<i class="icons clear-icon" onclick="clean(this);"></i>
|
<i class="icons clear-icon" onclick="clean(this);"></i>
|
||||||
<i class="icons search-icon"></i>
|
<i class="icons search-icon" onclick="gId('filters').classList.toggle('hide');" style="cursor:pointer;"></i>
|
||||||
</div>
|
</div>
|
||||||
<div id="fxlist" class="list">
|
<div id="fxlist" class="list">
|
||||||
<div class="lstI">
|
<div class="lstI">
|
||||||
@ -217,6 +217,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="sliders">
|
<div id="sliders">
|
||||||
|
<div id="filters" class="filter">
|
||||||
|
<label id="filterPal" class="check fchkl">🎨
|
||||||
|
<input type="checkbox" data-flt="🎨" onchange="filterFx(this)">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filter1D" class="check fchkl">1D
|
||||||
|
<input type="checkbox" data-flt="*" onchange="filterFx(this)">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filter2D" class="check fchkl">2D<!-- ⊞ -->
|
||||||
|
<input type="checkbox" data-flt="2D" onchange="filterFx(this)">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filterVol" class="check fchkl">♪
|
||||||
|
<input type="checkbox" data-flt="♪" onchange="filterFx(this)">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
<label id="filterFreq" class="check fchkl">♫
|
||||||
|
<input type="checkbox" data-flt="♫" onchange="filterFx(this)">
|
||||||
|
<span class="checkmark"></span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
<div id="slider0" class="slider">
|
<div id="slider0" class="slider">
|
||||||
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglFreeze()"></i>
|
<i class="icons slider-icon" style="cursor: pointer;" onclick="tglFreeze()"></i>
|
||||||
<div class="sliderwrap il">
|
<div class="sliderwrap il">
|
||||||
|
@ -5,10 +5,10 @@ var isOn = false, nlA = false, isLv = false, isInfo = false, isNodes = false, sy
|
|||||||
var hasWhite = false, hasRGB = false, hasCCT = false;
|
var hasWhite = false, hasRGB = false, hasCCT = false;
|
||||||
var nlDur = 60, nlTar = 0;
|
var nlDur = 60, nlTar = 0;
|
||||||
var nlMode = false;
|
var nlMode = false;
|
||||||
var selectedFx = 0, prevFx = -1;
|
var selectedFx = 0;
|
||||||
var selectedPal = 0;
|
var selectedPal = 0;
|
||||||
var csel = 0; // selected color slot (0-2)
|
var csel = 0; // selected color slot (0-2)
|
||||||
var currentPreset = -1, prevPS = -1;
|
var currentPreset = -1;
|
||||||
var lastUpdate = 0;
|
var lastUpdate = 0;
|
||||||
var segCount = 0, ledCount = 0, lowestUnused = 0, maxSeg = 0, lSeg = 0;
|
var segCount = 0, ledCount = 0, lowestUnused = 0, maxSeg = 0, lSeg = 0;
|
||||||
var pcMode = false, pcModeA = false, lastw = 0, wW;
|
var pcMode = false, pcModeA = false, lastw = 0, wW;
|
||||||
@ -25,7 +25,7 @@ var ws, cpick, ranges;
|
|||||||
var cfg = {
|
var cfg = {
|
||||||
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
theme:{base:"dark", bg:{url:""}, alpha:{bg:0.6,tab:0.8}, color:{bg:""}},
|
||||||
comp :{colors:{picker: true, rgb: false, quick: true, hex: false},
|
comp :{colors:{picker: true, rgb: false, quick: true, hex: false},
|
||||||
labels:true, pcmbot:false, pid:true, seglen:false, segpwr:false, css:true, hdays:false}
|
labels:true, pcmbot:false, pid:true, seglen:false, segpwr:false, segexp:false, css:true, hdays:false}
|
||||||
};
|
};
|
||||||
var hol = [
|
var hol = [
|
||||||
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
[0,11,24,4,"https://aircoookie.github.io/xmas.png"], // christmas
|
||||||
@ -167,12 +167,12 @@ function loadBg(iUrl)
|
|||||||
img.src = iUrl;
|
img.src = iUrl;
|
||||||
if (iUrl == "" || iUrl==="https://picsum.photos/1920/1080") {
|
if (iUrl == "" || iUrl==="https://picsum.photos/1920/1080") {
|
||||||
var today = new Date();
|
var today = new Date();
|
||||||
for (var i=0; i<hol.length; i++) {
|
for (var h of (hol||[])) {
|
||||||
var yr = hol[i][0]==0 ? today.getFullYear() : hol[i][0];
|
var yr = h[0]==0 ? today.getFullYear() : h[0];
|
||||||
var hs = new Date(yr,hol[i][1],hol[i][2]);
|
var hs = new Date(yr,h[1],h[2]);
|
||||||
var he = new Date(hs);
|
var he = new Date(hs);
|
||||||
he.setDate(he.getDate() + hol[i][3]);
|
he.setDate(he.getDate() + h[3]);
|
||||||
if (today>=hs && today<=he) img.src = hol[i][4];
|
if (today>=hs && today<=he) img.src = h[4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.addEventListener('load', (e) => {
|
img.addEventListener('load', (e) => {
|
||||||
@ -605,7 +605,7 @@ function parseInfo(i) {
|
|||||||
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
mh = i.leds.matrix ? i.leds.matrix.h : 0;
|
||||||
isM = mw>0 && mh>0;
|
isM = mw>0 && mh>0;
|
||||||
if (!isM) hideModes("2D ");
|
if (!isM) hideModes("2D ");
|
||||||
if (!i.u || !i.u.AudioReactive) { /*hideModes("♪ ");*/ hideModes("♫ "); } // hide /*audio*/ frequency reactive effects
|
//if (!i.u || !i.u.AudioReactive) { /*hideModes(" ♪");*/ hideModes(" ♫"); } // hide /*audio*/ frequency reactive effects
|
||||||
}
|
}
|
||||||
|
|
||||||
//https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
//https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
||||||
@ -621,6 +621,19 @@ function parseInfo(i) {
|
|||||||
//}
|
//}
|
||||||
//setInnerHTML(obj, html);
|
//setInnerHTML(obj, html);
|
||||||
|
|
||||||
|
//https://stackoverflow.com/questions/2592092/executing-script-elements-inserted-with-innerhtml
|
||||||
|
//var setInnerHTML = function(elm, html) {
|
||||||
|
// elm.innerHTML = html;
|
||||||
|
// Array.from(elm.querySelectorAll("script")).forEach( oldScript => {
|
||||||
|
// const newScript = document.createElement("script");
|
||||||
|
// Array.from(oldScript.attributes)
|
||||||
|
// .forEach( attr => newScript.setAttribute(attr.name, attr.value) );
|
||||||
|
// newScript.appendChild(document.createTextNode(oldScript.innerHTML));
|
||||||
|
// oldScript.parentNode.replaceChild(newScript, oldScript);
|
||||||
|
// });
|
||||||
|
//}
|
||||||
|
//setInnerHTML(obj, html);
|
||||||
|
|
||||||
function populateInfo(i)
|
function populateInfo(i)
|
||||||
{
|
{
|
||||||
var cn="";
|
var cn="";
|
||||||
@ -671,17 +684,15 @@ function populateSegments(s)
|
|||||||
let li = lastinfo;
|
let li = lastinfo;
|
||||||
segCount = 0; lowestUnused = 0; lSeg = 0;
|
segCount = 0; lowestUnused = 0; lSeg = 0;
|
||||||
|
|
||||||
for (var y = 0; y < (s.seg||[]).length; y++)
|
for (var inst of (s.seg||[])) {
|
||||||
{
|
|
||||||
segCount++;
|
segCount++;
|
||||||
|
|
||||||
var inst = s.seg[y];
|
|
||||||
let i = parseInt(inst.id);
|
let i = parseInt(inst.id);
|
||||||
if (i == lowestUnused) lowestUnused = i+1;
|
if (i == lowestUnused) lowestUnused = i+1;
|
||||||
if (i > lSeg) lSeg = i;
|
if (i > lSeg) lSeg = i;
|
||||||
|
|
||||||
let sg = gId(`seg${i}`);
|
let sg = gId(`seg${i}`);
|
||||||
let exp = sg ? sg.classList.contains("expanded") : false;
|
let exp = sg ? (sg.classList.contains("expanded") || (i===0 && cfg.comp.segexp)) : false;
|
||||||
|
|
||||||
let segp = `<div id="segp${i}" class="sbs">
|
let segp = `<div id="segp${i}" class="sbs">
|
||||||
<i class="icons e-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})"></i>
|
<i class="icons e-icon pwr ${inst.on ? "act":""}" id="seg${i}pwr" onclick="setSegPwr(${i})"></i>
|
||||||
@ -690,17 +701,33 @@ function populateSegments(s)
|
|||||||
<div class="sliderdisplay"></div>
|
<div class="sliderdisplay"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark schk"></span></label>`;
|
let rvXck = `<label class="check revchkl">Reverse ${isM?'':'direction'}<input type="checkbox" id="seg${i}rev" onchange="setRev(${i})" ${inst.rev?"checked":""}><span class="checkmark"></span></label>`;
|
||||||
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark schk"></span></label>`;
|
let miXck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mi" onchange="setMi(${i})" ${inst.mi?"checked":""}><span class="checkmark"></span></label>`;
|
||||||
let rvYck = "", miYck ="";
|
let rvYck = "", miYck ="";
|
||||||
if (isM) {
|
if (isM) {
|
||||||
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark schk"></span></label>`;
|
rvYck = `<label class="check revchkl">Reverse<input type="checkbox" id="seg${i}rY" onchange="setRevY(${i})" ${inst.rY?"checked":""}><span class="checkmark"></span></label>`;
|
||||||
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark schk"></span></label>`;
|
miYck = `<label class="check revchkl">Mirror<input type="checkbox" id="seg${i}mY" onchange="setMiY(${i})" ${inst.mY?"checked":""}><span class="checkmark"></span></label>`;
|
||||||
}
|
}
|
||||||
|
let map2D = `<div id="seg${i}map2D" data-map="map2D" class="lbl-s hide">Expand 1D FX<br>
|
||||||
|
<div class="sel-p"><select class="sel-p" id="seg${i}mp12" onchange="setMp12(${i})">
|
||||||
|
<option value="0" ${inst.mp12==0?' selected':''}>None</option>
|
||||||
|
<option value="1" ${inst.mp12==1?' selected':''}>Bar</option>
|
||||||
|
<option value="2" ${inst.mp12==2?' selected':''}>Arc</option>
|
||||||
|
<option value="3" ${inst.mp12==3?' selected':''}>Corner</option>
|
||||||
|
</select></div>
|
||||||
|
</div>`;
|
||||||
|
let sndSim = `<div data-snd="ssim" class="lbl-s hide">Sound sim<br>
|
||||||
|
<div class="sel-p"><select class="sel-p" id="seg${i}ssim" onchange="setSSim(${i})">
|
||||||
|
<option value="0" ${inst.ssim==0?' selected':''}>BeatSin</option>
|
||||||
|
<option value="1" ${inst.ssim==1?' selected':''}>WeWillRockYou</option>
|
||||||
|
<option value="2" ${inst.ssim==2?' selected':''}>U10_3</option>
|
||||||
|
<option value="3" ${inst.ssim==3?' selected':''}>U14_3</option>
|
||||||
|
</select></div>
|
||||||
|
</div>`;
|
||||||
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}">
|
cn += `<div class="seg lstI ${i==s.mainseg ? 'selected' : ''} ${exp ? "expanded":""}" id="seg${i}">
|
||||||
<label class="check schkl">
|
<label class="check schkl">
|
||||||
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
<input type="checkbox" id="seg${i}sel" onchange="selSeg(${i})" ${inst.sel ? "checked":""}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>
|
<i class="icons e-icon frz" id="seg${i}frz" onclick="event.preventDefault();tglFreeze(${i});">&#x${inst.frz ? (li.live && li.liveseg==i?'e410':'e0e8') : 'e325'};</i>
|
||||||
<div class="segname" onclick="selSegEx(${i})">
|
<div class="segname" onclick="selSegEx(${i})">
|
||||||
@ -741,10 +768,12 @@ function populateSegments(s)
|
|||||||
</table>
|
</table>
|
||||||
<div class="h bp" id="seg${i}len"></div>
|
<div class="h bp" id="seg${i}len"></div>
|
||||||
${!isM?rvXck:''}
|
${!isM?rvXck:''}
|
||||||
|
${map2D}
|
||||||
|
${s.AudioReactive && s.AudioReactive.on ? "" : sndSim}
|
||||||
<label class="check revchkl">
|
<label class="check revchkl">
|
||||||
${isM?'Transpose':'Mirror effect'}
|
${isM?'Transpose':'Mirror effect'}
|
||||||
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
|
<input type="checkbox" id="seg${i}${isM?'tp':'mi'}" onchange="${(isM?'setTp(':'setMi(')+i})" ${isM?(inst.tp?"checked":""):(inst.mi?"checked":"")}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<div class="del">
|
<div class="del">
|
||||||
<button class="btn btn-xs" id="segr${i}" title="Repeat until end" onclick="rptSeg(${i})"><i class="icons btn-icon"></i></button>
|
<button class="btn btn-xs" id="segr${i}" title="Repeat until end" onclick="rptSeg(${i})"><i class="icons btn-icon"></i></button>
|
||||||
@ -779,27 +808,34 @@ function populateEffects()
|
|||||||
var effects = eJson;
|
var effects = eJson;
|
||||||
var html = "";
|
var html = "";
|
||||||
|
|
||||||
effects.shift(); // remove solid
|
effects.shift(); // temporary remove solid
|
||||||
for (let i = 0; i < effects.length; i++) effects[i] = {id: effects[i][0], name:effects[i][1]};
|
for (let i = 0; i < effects.length; i++) {
|
||||||
|
effects[i] = {
|
||||||
|
id: effects[i][0],
|
||||||
|
name:effects[i][1]
|
||||||
|
};
|
||||||
|
}
|
||||||
effects.sort((a,b) => (a.name).localeCompare(b.name));
|
effects.sort((a,b) => (a.name).localeCompare(b.name));
|
||||||
|
|
||||||
effects.unshift({
|
effects.unshift({
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"name": "Solid"
|
"name": "Solid"
|
||||||
});
|
});
|
||||||
|
|
||||||
for (let i = 0; i < effects.length; i++) {
|
for (let ef of effects) {
|
||||||
// WLEDSR: add slider and color control to setX (used by requestjson)
|
// WLEDSR: add slider and color control to setX (used by requestjson)
|
||||||
if (effects[i].name.indexOf("Reserved") < 0) {
|
let id = ef.id;
|
||||||
let id = effects[i].id;
|
let nm = ef.name;
|
||||||
html += generateListItemHtml(
|
let fd = "";
|
||||||
'fx',
|
if (ef.name.indexOf("Reserved") < 0) {
|
||||||
id,
|
if (Array.isArray(fxdata) && fxdata.length>id) {
|
||||||
effects[i].name,
|
fd = fxdata[id].substr(1);
|
||||||
'setX',
|
var eP = (fd == '')?[]:fd.split(";");
|
||||||
'',
|
var p = (eP.length<3 || eP[2]==='')?[]:eP[2].split(",");
|
||||||
!(Array.isArray(fxdata) && fxdata.length>id) ? '' : fxdata[id].substr(1)
|
var m = (eP.length<4 || eP[3]==='')?[]:eP[3].split(",");
|
||||||
);
|
if (isM && m.length>0) for (let r of m) { if (r.substring(0,4)=="mp12") nm += " *"; } // 1D effects with defined mapping
|
||||||
|
if (p.length>0 && p[0].substring(0,1) === "!") nm += " 🎨";
|
||||||
|
}
|
||||||
|
html += generateListItemHtml('fx',id,nm,'setX','',fd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -809,7 +845,7 @@ function populateEffects()
|
|||||||
function populatePalettes()
|
function populatePalettes()
|
||||||
{
|
{
|
||||||
var palettes = lJson;
|
var palettes = lJson;
|
||||||
palettes.shift(); // remove default
|
palettes.shift(); // temporary remove default
|
||||||
for (let i = 0; i < palettes.length; i++) {
|
for (let i = 0; i < palettes.length; i++) {
|
||||||
palettes[i] = {
|
palettes[i] = {
|
||||||
"id": palettes[i][0],
|
"id": palettes[i][0],
|
||||||
@ -817,20 +853,19 @@ function populatePalettes()
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
palettes.sort((a,b) => (a.name).localeCompare(b.name));
|
palettes.sort((a,b) => (a.name).localeCompare(b.name));
|
||||||
|
|
||||||
palettes.unshift({
|
palettes.unshift({
|
||||||
"id": 0,
|
"id": 0,
|
||||||
"name": "Default"
|
"name": "Default"
|
||||||
});
|
});
|
||||||
|
|
||||||
var html = "";
|
var html = "";
|
||||||
for (let i = 0; i < palettes.length; i++) {
|
for (let pa of palettes) {
|
||||||
html += generateListItemHtml(
|
html += generateListItemHtml(
|
||||||
'palette',
|
'palette',
|
||||||
palettes[i].id,
|
pa.id,
|
||||||
palettes[i].name,
|
pa.name,
|
||||||
'setPalette',
|
'setPalette',
|
||||||
`<div class="lstIprev" style="${genPalPrevCss(palettes[i].id)}"></div>`
|
`<div class="lstIprev" style="${genPalPrevCss(pa.id)}"></div>`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -895,12 +930,12 @@ function genPalPrevCss(id)
|
|||||||
return `background: linear-gradient(to right,${gradient.join()});`;
|
return `background: linear-gradient(to right,${gradient.join()});`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', extraPar = '')
|
function generateListItemHtml(listName, id, name, clickAction, extraHtml = '', effectPar = '')
|
||||||
{
|
{
|
||||||
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" data-opt="${extraPar}" onClick="${clickAction}(${id})">
|
return `<div class="lstI${id==0?' sticky':''}" data-id="${id}" data-opt="${effectPar}" onClick="${clickAction}(${id})">
|
||||||
<label class="radio schkl" onclick="event.preventDefault()">
|
<label class="radio schkl" onclick="event.preventDefault()">
|
||||||
<input type="radio" value="${id}" name="${listName}">
|
<input type="radio" value="${id}" name="${listName}">
|
||||||
<span class="radiomark schk"></span>
|
<span class="radiomark"></span>
|
||||||
<div class="lstIcontent">
|
<div class="lstIcontent">
|
||||||
<span class="lstIname">
|
<span class="lstIname">
|
||||||
${name}
|
${name}
|
||||||
@ -933,8 +968,7 @@ function populateNodes(i,n)
|
|||||||
var nnodes = 0;
|
var nnodes = 0;
|
||||||
if (n.nodes) {
|
if (n.nodes) {
|
||||||
n.nodes.sort((a,b) => (a.name).localeCompare(b.name));
|
n.nodes.sort((a,b) => (a.name).localeCompare(b.name));
|
||||||
for (var x=0;x<n.nodes.length;x++) {
|
for (var o of n.nodes) {
|
||||||
var o = n.nodes[x];
|
|
||||||
if (o.name) {
|
if (o.name) {
|
||||||
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');">${bname(o)}</button>`;
|
var url = `<button class="btn" title="${o.ip}" onclick="location.assign('http://${o.ip}');">${bname(o)}</button>`;
|
||||||
urows += inforow(url,`${btype(o.type)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
urows += inforow(url,`${btype(o.type)}<br><i>${o.vid==0?"N/A":o.vid}</i>`);
|
||||||
@ -979,7 +1013,7 @@ function updateTrail(e)
|
|||||||
var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
|
var max = e.hasAttribute('max') ? e.attributes.max.value : 255;
|
||||||
var perc = Math.round(e.value * 100 / max);
|
var perc = Math.round(e.value * 100 / max);
|
||||||
if (perc < 50) perc += 2;
|
if (perc < 50) perc += 2;
|
||||||
var val = `linear-gradient(90deg, var(--bg) ${perc}%, var(--c-4) ${perc}%)`;
|
var val = `linear-gradient(90deg, var(--bg) ${perc}%, var(--c-6) ${perc}%)`;
|
||||||
sd.style.backgroundImage = val;
|
sd.style.backgroundImage = val;
|
||||||
}
|
}
|
||||||
var b = e.parentNode.parentNode.getElementsByTagName('output')[0];
|
var b = e.parentNode.parentNode.getElementsByTagName('output')[0];
|
||||||
@ -1004,6 +1038,7 @@ function updateLen(s)
|
|||||||
start = parseInt(gId(`seg${s}sY`).value);
|
start = parseInt(gId(`seg${s}sY`).value);
|
||||||
stop = parseInt(gId(`seg${s}eY`).value);
|
stop = parseInt(gId(`seg${s}eY`).value);
|
||||||
len *= (stop-(cfg.comp.seglen?0:start));
|
len *= (stop-(cfg.comp.seglen?0:start));
|
||||||
|
if (stop-start>1) gId(`seg${s}map2D`).classList.remove("hide"); else gId(`seg${s}map2D`).classList.add("hide");
|
||||||
}
|
}
|
||||||
var out = "(delete)";
|
var out = "(delete)";
|
||||||
if (len > 1) {
|
if (len > 1) {
|
||||||
@ -1109,15 +1144,21 @@ function updateSelectedFx()
|
|||||||
if (selEffectInput) selEffectInput.checked = true;
|
if (selEffectInput) selEffectInput.checked = true;
|
||||||
|
|
||||||
var selElement = parent.querySelector('.selected');
|
var selElement = parent.querySelector('.selected');
|
||||||
if (selElement) selElement.classList.remove('selected');
|
if (selElement) {
|
||||||
|
selElement.classList.remove('selected');
|
||||||
|
selElement.style.bottom = null; // remove element style added in slider handling
|
||||||
|
}
|
||||||
|
|
||||||
var selectedEffect = parent.querySelector(`.lstI[data-id="${selectedFx}"]`);
|
var selectedEffect = parent.querySelector(`.lstI[data-id="${selectedFx}"]`);
|
||||||
if (selectedEffect) {
|
if (selectedEffect) {
|
||||||
selectedEffect.classList.add('selected');
|
selectedEffect.classList.add('selected');
|
||||||
var fx = (selectedFx != prevFx) && currentPreset==-1; // effect changed & preset==none
|
setEffectParameters(selectedFx);
|
||||||
var ps = (prevPS != currentPreset) && currentPreset==-1; // preset changed & preset==none
|
|
||||||
// WLEDSR: extract the Slider and color control string from the HTML element and set it.
|
var selectedName = selectedEffect.querySelector(".lstIname").innerText;
|
||||||
setSliderAndColorControl(selectedFx, (fx || ps));
|
var segs = gId("segcont").querySelectorAll(`div[data-map="map2D"]`);
|
||||||
|
for (const seg of segs) if (selectedName.indexOf("2D ")<0) seg.classList.remove("hide"); else seg.classList.add("hide");
|
||||||
|
var segs = gId("segcont").querySelectorAll(`div[data-snd="ssim"]`);
|
||||||
|
for (const seg of segs) if (selectedName.indexOf(" ♪")<0 && selectedName.indexOf(" ♫")<0) seg.classList.add("hide"); else seg.classList.remove("hide"); // also "♫ "?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1180,6 +1221,7 @@ function makeWS() {
|
|||||||
function readState(s,command=false)
|
function readState(s,command=false)
|
||||||
{
|
{
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
|
if (s.success) return true; // no data to process
|
||||||
|
|
||||||
isOn = s.on;
|
isOn = s.on;
|
||||||
gId('sliderBri').value = s.bri;
|
gId('sliderBri').value = s.bri;
|
||||||
@ -1188,7 +1230,6 @@ function readState(s,command=false)
|
|||||||
nlTar = s.nl.tbri;
|
nlTar = s.nl.tbri;
|
||||||
nlFade = s.nl.fade;
|
nlFade = s.nl.fade;
|
||||||
syncSend = s.udpn.send;
|
syncSend = s.udpn.send;
|
||||||
prevPS = currentPreset;
|
|
||||||
if (s.pl<0) currentPreset = s.ps;
|
if (s.pl<0) currentPreset = s.ps;
|
||||||
else currentPreset = s.pl;
|
else currentPreset = s.pl;
|
||||||
|
|
||||||
@ -1224,7 +1265,7 @@ function readState(s,command=false)
|
|||||||
if (!i) {
|
if (!i) {
|
||||||
showToast('No Segments!', true);
|
showToast('No Segments!', true);
|
||||||
updateUI();
|
updateUI();
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cd = gId('csl').children;
|
var cd = gId('csl').children;
|
||||||
@ -1266,11 +1307,11 @@ function readState(s,command=false)
|
|||||||
showToast('Error ' + s.error + ": " + errstr, true);
|
showToast('Error ' + s.error + ": " + errstr, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
prevFx = selectedFx;
|
|
||||||
selectedPal = i.pal;
|
selectedPal = i.pal;
|
||||||
selectedFx = i.fx;
|
selectedFx = i.fx;
|
||||||
redrawPalPrev(); // if any color changed (random palette did at least)
|
redrawPalPrev(); // if any color changed (random palette did at least)
|
||||||
updateUI();
|
updateUI();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// WLEDSR: control HTML elements for Slider and Color Control
|
// WLEDSR: control HTML elements for Slider and Color Control
|
||||||
@ -1294,16 +1335,15 @@ function readState(s,command=false)
|
|||||||
// Note: Effects can override default pattern behaviour
|
// Note: Effects can override default pattern behaviour
|
||||||
// - FadeToBlack can override the background setting
|
// - FadeToBlack can override the background setting
|
||||||
// - Defining SEGCOL(<i>) can override a specific palette using these values (e.g. Color Gradient)
|
// - Defining SEGCOL(<i>) can override a specific palette using these values (e.g. Color Gradient)
|
||||||
function setSliderAndColorControl(idx, applyDef=false)
|
function setEffectParameters(idx)
|
||||||
{
|
{
|
||||||
if (!(Array.isArray(fxdata) && fxdata.length>idx)) return;
|
if (!(Array.isArray(fxdata) && fxdata.length>idx)) return;
|
||||||
var controlDefined = (fxdata[idx].substr(0,1) == "@");
|
var controlDefined = (fxdata[idx].substr(0,1) == "@");
|
||||||
var extra = fxdata[idx].substr(1);
|
var effectPar = fxdata[idx].substr(1);
|
||||||
var extras = (extra == '')?[]:extra.split(";");
|
var effectPars = (effectPar == '')?[]:effectPar.split(";");
|
||||||
var slOnOff = (extras.length==0 || extras[0]=='')?[]:extras[0].split(",");
|
var slOnOff = (effectPars.length==0 || effectPars[0]=='')?[]:effectPars[0].split(",");
|
||||||
var coOnOff = (extras.length<2 || extras[1]=='')?[]:extras[1].split(",");
|
var coOnOff = (effectPars.length<2 || effectPars[1]=='')?[]:effectPars[1].split(",");
|
||||||
var paOnOff = (extras.length<3 || extras[2]=='')?[]:extras[2].split(",");
|
var paOnOff = (effectPars.length<3 || effectPars[2]=='')?[]:effectPars[2].split(",");
|
||||||
var obj = {"seg":{}};
|
|
||||||
|
|
||||||
// set html slider items on/off
|
// set html slider items on/off
|
||||||
var nSliders = Math.min(5,Math.floor(gId("sliders").children.length)); // div for each slider
|
var nSliders = Math.min(5,Math.floor(gId("sliders").children.length)); // div for each slider
|
||||||
@ -1316,10 +1356,6 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
if (slOnOff.length>i && slOnOff[i].indexOf("=")>0) {
|
if (slOnOff.length>i && slOnOff[i].indexOf("=")>0) {
|
||||||
// embeded default values
|
// embeded default values
|
||||||
var dPos = slOnOff[i].indexOf("=");
|
var dPos = slOnOff[i].indexOf("=");
|
||||||
var v = Math.max(0,Math.min(255,parseInt(slOnOff[i].substr(dPos+1))));
|
|
||||||
if (i==0) { if (applyDef) gId("sliderSpeed").value = v; obj.seg.sx = v; }
|
|
||||||
else if (i==1) { if (applyDef) gId("sliderIntensity").value = v; obj.seg.ix = v; }
|
|
||||||
else { if (applyDef) gId("sliderC"+(i-1)).value = v; obj.seg["c"+(i-1)+"x"] = v}
|
|
||||||
slOnOff[i] = slOnOff[i].substring(0,dPos);
|
slOnOff[i] = slOnOff[i].substring(0,dPos);
|
||||||
}
|
}
|
||||||
if (slOnOff.length>i && slOnOff[i]!="!") label.innerHTML = slOnOff[i];
|
if (slOnOff.length>i && slOnOff[i]!="!") label.innerHTML = slOnOff[i];
|
||||||
@ -1327,18 +1363,15 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
else if (i==1) label.innerHTML = "Effect intensity";
|
else if (i==1) label.innerHTML = "Effect intensity";
|
||||||
else label.innerHTML = "Custom" + (i-1);
|
else label.innerHTML = "Custom" + (i-1);
|
||||||
sldCnt++;
|
sldCnt++;
|
||||||
//if (sldCnt++===0) slider.classList.add("top");
|
|
||||||
slider.classList.remove("hide");
|
slider.classList.remove("hide");
|
||||||
//slider.setAttribute('title',label.innerHTML);
|
|
||||||
} else {
|
} else {
|
||||||
slider.classList.add("hide");
|
slider.classList.add("hide");
|
||||||
//slider.classList.remove("top");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set the bottom position of selected effect (sticky) as the top of sliders div
|
// set the bottom position of selected effect (sticky) as the top of sliders div
|
||||||
let top = parseInt(getComputedStyle(gId("sliders")).height);
|
let top = parseInt(getComputedStyle(gId("sliders")).height);
|
||||||
/*if (sldCnt===1)*/ top += 28; // size of tooltip
|
//top += 5; // size of tooltip
|
||||||
let sel = d.querySelector('#fxlist .selected');
|
let sel = d.querySelector('#fxlist .selected');
|
||||||
if (sel) sel.style.bottom = top + "px"; // we will need to remove this when unselected (in setX())
|
if (sel) sel.style.bottom = top + "px"; // we will need to remove this when unselected (in setX())
|
||||||
|
|
||||||
@ -1346,7 +1379,7 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
var cslLabel = '';
|
var cslLabel = '';
|
||||||
var sep = '';
|
var sep = '';
|
||||||
var hide = true;
|
var hide = true;
|
||||||
var cslCnt = 0;
|
var cslCnt = 0, oCsel = csel;
|
||||||
for (let i=0; i<gId("csl").children.length; i++) {
|
for (let i=0; i<gId("csl").children.length; i++) {
|
||||||
var btn = gId("csl" + i);
|
var btn = gId("csl" + i);
|
||||||
// if no controlDefined or coOnOff has a value
|
// if no controlDefined or coOnOff has a value
|
||||||
@ -1364,13 +1397,13 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
else if (i==1) btn.innerHTML = "Bg";
|
else if (i==1) btn.innerHTML = "Bg";
|
||||||
else btn.innerHTML = "Cs";
|
else btn.innerHTML = "Cs";
|
||||||
hide = false;
|
hide = false;
|
||||||
if (!cslCnt) selectSlot(i); // select 1st displayed slot
|
if (!cslCnt || oCsel==i) selectSlot(i); // select 1st displayed slot or old one
|
||||||
cslCnt++;
|
cslCnt++;
|
||||||
} else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3
|
} else if (!controlDefined /*|| paOnOff.length>0*/) { // if no controls then all buttons should be shown for color 1..3
|
||||||
btn.style.display = "inline";
|
btn.style.display = "inline";
|
||||||
btn.innerHTML = `${i+1}`;
|
btn.innerHTML = `${i+1}`;
|
||||||
hide = false;
|
hide = false;
|
||||||
if (!cslCnt) selectSlot(i); // select 1st displayed slot
|
if (!cslCnt || oCsel==i) selectSlot(i); // select 1st displayed slot or old one
|
||||||
cslCnt++;
|
cslCnt++;
|
||||||
} else {
|
} else {
|
||||||
btn.style.display = "none";
|
btn.style.display = "none";
|
||||||
@ -1388,11 +1421,6 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
// embeded default values
|
// embeded default values
|
||||||
var dPos = paOnOff[0].indexOf("=");
|
var dPos = paOnOff[0].indexOf("=");
|
||||||
var v = Math.max(0,Math.min(255,parseInt(paOnOff[0].substr(dPos+1))));
|
var v = Math.max(0,Math.min(255,parseInt(paOnOff[0].substr(dPos+1))));
|
||||||
var p = d.querySelector(`#pallist input[name="palette"][value="${v}"]`);
|
|
||||||
if (applyDef && p) {
|
|
||||||
p.checked = true;
|
|
||||||
obj.seg.pal = v;
|
|
||||||
}
|
|
||||||
paOnOff[0] = paOnOff[0].substring(0,dPos);
|
paOnOff[0] = paOnOff[0].substring(0,dPos);
|
||||||
}
|
}
|
||||||
if (paOnOff.length>0 && paOnOff[0] != "!") pall.innerHTML = paOnOff[0];
|
if (paOnOff.length>0 && paOnOff[0] != "!") pall.innerHTML = paOnOff[0];
|
||||||
@ -1401,14 +1429,11 @@ function setSliderAndColorControl(idx, applyDef=false)
|
|||||||
// disable palett list
|
// disable palett list
|
||||||
pall.innerHTML = '<i class="icons sel-icon" onclick="tglHex()"></i> Color palette not used';
|
pall.innerHTML = '<i class="icons sel-icon" onclick="tglHex()"></i> Color palette not used';
|
||||||
palw.style.display = "none";
|
palw.style.display = "none";
|
||||||
// if numeric set as selected palette
|
|
||||||
if (paOnOff.length>0 && paOnOff[0]!="" && !isNaN(paOnOff[0]) && parseInt(paOnOff[0])!=selectedPal) obj.seg.pal = parseInt(paOnOff[0]);
|
|
||||||
}
|
}
|
||||||
// not all color selectors shown, hide palettes created from color selectors
|
// not all color selectors shown, hide palettes created from color selectors
|
||||||
for (let e of (gId('pallist').querySelectorAll('.lstI')||[])) {
|
for (let e of (gId('pallist').querySelectorAll('.lstI')||[])) {
|
||||||
if (cslCnt < 3 && e.querySelector('.lstIname').innerText.indexOf("* C")>=0) e.classList.add('hide'); else e.classList.remove('hide');
|
if (cslCnt < 3 && e.querySelector('.lstIname').innerText.indexOf("* C")>=0) e.classList.add('hide'); else e.classList.remove('hide');
|
||||||
}
|
}
|
||||||
if (!isEmpty(obj.seg) && applyDef) requestJson(obj); // update default values (may need throttling on ESP8266)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var jsonTimeout;
|
var jsonTimeout;
|
||||||
@ -1588,7 +1613,7 @@ function resetUtil()
|
|||||||
{
|
{
|
||||||
// gId('segutil').innerHTML = '<button class="btn btn-s" onclick="makeSeg()"><i class="icons btn-icon"></i>segment</button>';
|
// gId('segutil').innerHTML = '<button class="btn btn-s" onclick="makeSeg()"><i class="icons btn-icon"></i>segment</button>';
|
||||||
gId('segutil').innerHTML = '<div class="seg btn btn-s" style="border-radius:24px;padding:0;">'
|
gId('segutil').innerHTML = '<div class="seg btn btn-s" style="border-radius:24px;padding:0;">'
|
||||||
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark schk"></span></label>'
|
+ '<label class="check schkl"><input type="checkbox" id="selall" onchange="selSegAll(this)"><span class="checkmark"></span></label>'
|
||||||
+ '<div class="segname" onclick="makeSeg()"><i class="icons btn-icon"></i>segment</div></div>';
|
+ '<div class="segname" onclick="makeSeg()"><i class="icons btn-icon"></i>segment</div></div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1601,14 +1626,14 @@ var plJson = {"0":{
|
|||||||
"end": 0
|
"end": 0
|
||||||
}};
|
}};
|
||||||
|
|
||||||
function makePlSel(incPl=false) {
|
function makePlSel(el, incPl=false) {
|
||||||
var plSelContent = "";
|
var plSelContent = "";
|
||||||
delete pJson["0"]; // remove filler preset
|
delete pJson["0"]; // remove filler preset
|
||||||
var arr = Object.entries(pJson);
|
var arr = Object.entries(pJson);
|
||||||
for (var i = 0; i < arr.length; i++) {
|
for (var a of arr) {
|
||||||
var n = arr[i][1].n ? arr[i][1].n : "Preset " + arr[i][0];
|
var n = a[1].n ? a[1].n : "Preset " + a[0];
|
||||||
if (!incPl && arr[i][1].playlist && arr[i][1].playlist.ps) continue; // remove playlists, sub-playlists not yet supported
|
if (!incPl && a[1].playlist && a[1].playlist.ps) continue; // remove playlists, sub-playlists not yet supported
|
||||||
plSelContent += `<option value="${arr[i][0]}">${n}</option>`
|
plSelContent += `<option value="${a[0]}" ${a[0]==el?"selected":""}>${n}</option>`
|
||||||
}
|
}
|
||||||
return plSelContent;
|
return plSelContent;
|
||||||
}
|
}
|
||||||
@ -1685,20 +1710,20 @@ function makeP(i,pl) {
|
|||||||
content =
|
content =
|
||||||
`<div id="ple${i}" style="margin-top:10px;"></div><label class="check revchkl">Shuffle
|
`<div id="ple${i}" style="margin-top:10px;"></div><label class="check revchkl">Shuffle
|
||||||
<input type="checkbox" id="pl${i}rtgl" onchange="plR(${i})" ${plJson[i].r||rep<0?"checked":""}>
|
<input type="checkbox" id="pl${i}rtgl" onchange="plR(${i})" ${plJson[i].r||rep<0?"checked":""}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label class="check revchkl">Repeat indefinitely
|
<label class="check revchkl">Repeat indefinitely
|
||||||
<input type="checkbox" id="pl${i}rptgl" onchange="plR(${i})" ${rep>0?"":"checked"}>
|
<input type="checkbox" id="pl${i}rptgl" onchange="plR(${i})" ${rep>0?"":"checked"}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<div id="pl${i}o1" style="display:${rep>0?"block":"none"}">
|
<div id="pl${i}o1" style="display:${rep>0?"block":"none"}">
|
||||||
<div class="c">Repeat <input class="noslide" type="number" id="pl${i}rp" oninput="plR(${i})" max=127 min=0 value=${rep>0?rep:1}> times</div>
|
<div class="c">Repeat <input class="noslide" type="number" id="pl${i}rp" oninput="plR(${i})" max=127 min=0 value=${rep>0?rep:1}> times</div>
|
||||||
<div class="sel">End preset:<br>
|
<div class="sel">End preset:<br>
|
||||||
<select class="sel sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
|
<div class="sel-p"><select class="sel-ple" id="pl${i}selEnd" onchange="plR(${i})" data-val=${plJson[i].end?plJson[i].end:0}>
|
||||||
<option value="0">None</option>
|
<option value="0">None</option>
|
||||||
<option value="255">Restore preset</option>
|
<option value="255">Restore preset</option>
|
||||||
${makePlSel(true)}
|
${makePlSel(plJson[i].end?plJson[i].end:0, true)}
|
||||||
</select></div>
|
</select></div></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="c"><button class="btn btn-p" onclick="testPl(${i}, this)"><i class='icons btn-icon'></i>Test</button></div>`;
|
<div class="c"><button class="btn btn-p" onclick="testPl(${i}, this)"><i class='icons btn-icon'></i>Test</button></div>`;
|
||||||
} else {
|
} else {
|
||||||
@ -1708,24 +1733,24 @@ ${makePlSel(true)}
|
|||||||
Include brightness
|
Include brightness
|
||||||
</span>
|
</span>
|
||||||
<input type="checkbox" id="p${i}ibtgl" checked>
|
<input type="checkbox" id="p${i}ibtgl" checked>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label class="check revchkl">
|
<label class="check revchkl">
|
||||||
<span class="lstIname">
|
<span class="lstIname">
|
||||||
Save segment bounds
|
Save segment bounds
|
||||||
</span>
|
</span>
|
||||||
<input type="checkbox" id="p${i}sbtgl" checked>
|
<input type="checkbox" id="p${i}sbtgl" checked>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
<label class="check revchkl">
|
<label class="check revchkl">
|
||||||
<span class="lstIname">
|
<span class="lstIname">
|
||||||
Checked segments only
|
Checked segments only
|
||||||
</span>
|
</span>
|
||||||
<input type="checkbox" id="p${i}sbchk">
|
<input type="checkbox" id="p${i}sbchk">
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>`;
|
</label>`;
|
||||||
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>0) {
|
if (Array.isArray(lastinfo.maps) && lastinfo.maps.length>0) {
|
||||||
content += `<div class="sel">Ledmap: <select class="sel sel-p" id="p${i}lmp"><option value="">None</option>`;
|
content += `<div class="sel">Ledmap: <select class="sel-p" id="p${i}lmp"><option value="">None</option>`;
|
||||||
for (const k of (lastinfo.maps||[])) content += `<option value="${k}"${(i>0 && pJson[i].ledmap==k)?" selected":""}>${k}</option>`;
|
for (const k of (lastinfo.maps||[])) content += `<option value="${k}"${(i>0 && pJson[i].ledmap==k)?" selected":""}>${k}</option>`;
|
||||||
content += "</select></div>";
|
content += "</select></div>";
|
||||||
}
|
}
|
||||||
@ -1740,7 +1765,7 @@ ${makePlSel(true)}
|
|||||||
${pl?"Show playlist editor":(i>0)?"Overwrite with state":"Use current state"}
|
${pl?"Show playlist editor":(i>0)?"Overwrite with state":"Use current state"}
|
||||||
</span>
|
</span>
|
||||||
<input type="checkbox" id="p${i}cstgl" onchange="tglCs(${i})" ${(i==0||pl)?"checked":""}>
|
<input type="checkbox" id="p${i}cstgl" onchange="tglCs(${i})" ${(i==0||pl)?"checked":""}>
|
||||||
<span class="checkmark schk"></span>
|
<span class="checkmark"></span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="po2" id="p${i}o2">
|
<div class="po2" id="p${i}o2">
|
||||||
@ -1778,9 +1803,9 @@ function makePlEntry(p,i) {
|
|||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="80%" colspan=2>
|
<td width="80%" colspan=2>
|
||||||
<select class="sel sel-pl" onchange="plePs(${p},${i},this)" data-val="${plJson[p].ps[i]}" data-index="${i}">
|
<div class="sel-p"><select class="sel-pl" onchange="plePs(${p},${i},this)" data-val="${plJson[p].ps[i]}" data-index="${i}">
|
||||||
${makePlSel()}
|
${makePlSel(plJson[p].ps[i])}
|
||||||
</select>
|
</select></div>
|
||||||
</td>
|
</td>
|
||||||
<td class="c"><button class="btn btn-pl-add" onclick="addPl(${p},${i})"><i class="icons btn-icon"></i></button></td>
|
<td class="c"><button class="btn btn-pl-add" onclick="addPl(${p},${i})"><i class="icons btn-icon"></i></button></td>
|
||||||
</tr>
|
</tr>
|
||||||
@ -1952,6 +1977,20 @@ function setMiY(s)
|
|||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setMp12(s)
|
||||||
|
{
|
||||||
|
var value = gId(`seg${s}mp12`).selectedIndex;
|
||||||
|
var obj = {"seg": {"id": s, "mp12": value}};
|
||||||
|
requestJson(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setSSim(s)
|
||||||
|
{
|
||||||
|
var value = gId(`seg${s}ssim`).selectedIndex;
|
||||||
|
var obj = {"seg": {"id": s, "ssim": value}};
|
||||||
|
requestJson(obj);
|
||||||
|
}
|
||||||
|
|
||||||
function setTp(s)
|
function setTp(s)
|
||||||
{
|
{
|
||||||
var tp = gId(`seg${s}tp`).checked;
|
var tp = gId(`seg${s}tp`).checked;
|
||||||
@ -1990,6 +2029,8 @@ function setX(ind = null)
|
|||||||
} else {
|
} else {
|
||||||
d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true;
|
d.querySelector(`#fxlist input[name="fx"][value="${ind}"]`).checked = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
// this code also in updateSelectedFx
|
||||||
var selElement = d.querySelector('#fxlist .selected');
|
var selElement = d.querySelector('#fxlist .selected');
|
||||||
if (selElement) {
|
if (selElement) {
|
||||||
selElement.classList.remove('selected');
|
selElement.classList.remove('selected');
|
||||||
@ -1997,7 +2038,7 @@ function setX(ind = null)
|
|||||||
}
|
}
|
||||||
|
|
||||||
d.querySelector(`#fxlist .lstI[data-id="${ind}"]`).classList.add('selected');
|
d.querySelector(`#fxlist .lstI[data-id="${ind}"]`).classList.add('selected');
|
||||||
|
*/
|
||||||
var obj = {"seg": {"fx": parseInt(ind)}};
|
var obj = {"seg": {"fx": parseInt(ind)}};
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
@ -2009,11 +2050,13 @@ function setPalette(paletteId = null)
|
|||||||
} else {
|
} else {
|
||||||
d.querySelector(`#pallist input[name="palette"][value="${paletteId}"]`).checked = true;
|
d.querySelector(`#pallist input[name="palette"][value="${paletteId}"]`).checked = true;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
var selElement = d.querySelector('#pallist .selected');
|
var selElement = d.querySelector('#pallist .selected');
|
||||||
if (selElement) {
|
if (selElement) {
|
||||||
selElement.classList.remove('selected')
|
selElement.classList.remove('selected')
|
||||||
}
|
}
|
||||||
d.querySelector(`#pallist .lstI[data-id="${paletteId}"]`).classList.add('selected');
|
d.querySelector(`#pallist .lstI[data-id="${paletteId}"]`).classList.add('selected');
|
||||||
|
*/
|
||||||
var obj = {"seg": {"pal": paletteId}};
|
var obj = {"seg": {"pal": paletteId}};
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
@ -2127,6 +2170,7 @@ function saveP(i,pl)
|
|||||||
}
|
}
|
||||||
populatePresets();
|
populatePresets();
|
||||||
resetPUtil();
|
resetPUtil();
|
||||||
|
setTimeout(()=>{pmtLast=0; loadPresets();}, 500); // force reloading of presets
|
||||||
}
|
}
|
||||||
|
|
||||||
function testPl(i,bt) {
|
function testPl(i,bt) {
|
||||||
@ -2362,6 +2406,11 @@ function rSegs()
|
|||||||
bt.style.color = "var(--c-f)";
|
bt.style.color = "var(--c-f)";
|
||||||
bt.innerHTML = "Reset segments";
|
bt.innerHTML = "Reset segments";
|
||||||
var obj = {"seg":[{"start":0,"stop":ledCount,"sel":true}]};
|
var obj = {"seg":[{"start":0,"stop":ledCount,"sel":true}]};
|
||||||
|
if (isM) {
|
||||||
|
obj.seg[0].stop = mw;
|
||||||
|
obj.seg[0].startX = 0;
|
||||||
|
obj.seg[0].stopY = mh;
|
||||||
|
}
|
||||||
for (let i=1; i<=lSeg; i++) obj.seg.push({"stop":0});
|
for (let i=1; i<=lSeg; i++) obj.seg.push({"stop":0});
|
||||||
requestJson(obj);
|
requestJson(obj);
|
||||||
}
|
}
|
||||||
@ -2422,6 +2471,10 @@ function hideModes(txt)
|
|||||||
for (let e of (gId('fxlist').querySelectorAll('.lstI')||[])) {
|
for (let e of (gId('fxlist').querySelectorAll('.lstI')||[])) {
|
||||||
if (e.querySelector('.lstIname').innerText.indexOf(txt) >= 0) e.classList.add("hide"); //else e.classList.remove("hide");
|
if (e.querySelector('.lstIname').innerText.indexOf(txt) >= 0) e.classList.add("hide"); //else e.classList.remove("hide");
|
||||||
}
|
}
|
||||||
|
if (txt==="2D ") {
|
||||||
|
gId("filter1D").classList.add("hide");
|
||||||
|
gId("filter2D").classList.add("hide");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function search(f,l=null)
|
function search(f,l=null)
|
||||||
@ -2444,6 +2497,19 @@ function clean(c)
|
|||||||
i.value='';
|
i.value='';
|
||||||
i.focus();
|
i.focus();
|
||||||
i.dispatchEvent(new Event('input'));
|
i.dispatchEvent(new Event('input'));
|
||||||
|
if (i.parentElement.id=='fxFind') {
|
||||||
|
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{e.checked=false;});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function filterFx(o)
|
||||||
|
{
|
||||||
|
if (!o) return;
|
||||||
|
let i = gId('fxFind').children[0];
|
||||||
|
i.value=!o.checked?'':o.dataset.flt;
|
||||||
|
i.focus();
|
||||||
|
i.dispatchEvent(new Event('input'));
|
||||||
|
gId("filters").querySelectorAll("input[type=checkbox]").forEach((e)=>{if(e!==o)e.checked=false;});
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure "dur" and "transition" are arrays with at least the length of "ps"
|
// make sure "dur" and "transition" are arrays with at least the length of "ps"
|
||||||
|
@ -6,9 +6,38 @@
|
|||||||
<title>WLED Settings</title>
|
<title>WLED Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d=document;
|
var d=document;
|
||||||
|
var loc = false, locip;
|
||||||
function gId(n){return d.getElementById(n);}
|
function gId(n){return d.getElementById(n);}
|
||||||
function S(){GetV();}
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
function GetV(){}
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function S(){
|
||||||
|
if (window.location.protocol == "file:") {
|
||||||
|
loc = true;
|
||||||
|
locip = localStorage.getItem('locIp');
|
||||||
|
if (!locip) {
|
||||||
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=0';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
|
@ -41,8 +41,6 @@
|
|||||||
}
|
}
|
||||||
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=10';
|
||||||
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
//if (loc) loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
|
||||||
//else { GetV(); UI(); }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxPanels=64;
|
var maxPanels=64;
|
||||||
@ -104,9 +102,6 @@ Serpentine: <input type="checkbox" name="P${i}S"></div>`;
|
|||||||
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
|
gId("pnl_add").style.display = (i<maxPanels) ? "inline":"none";
|
||||||
gId("pnl_rem").style.display = (i>1) ? "inline":"none";
|
gId("pnl_rem").style.display = (i>1) ? "inline":"none";
|
||||||
}
|
}
|
||||||
|
|
||||||
//values injected by server while sending HTML
|
|
||||||
//fun-ction GetV() {}
|
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
|
@ -6,35 +6,65 @@
|
|||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>DMX Settings</title>
|
<title>DMX Settings</title>
|
||||||
<script>
|
<script>
|
||||||
function GCH(num) {
|
var d=document;
|
||||||
d=document;
|
var loc = false, locip;
|
||||||
d.getElementById('dmxchannels').innerHTML += "";
|
function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}
|
||||||
for (i=0;i<num;i++) {
|
function B(){window.history.back();}
|
||||||
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
function GCH(num) {
|
||||||
}
|
d.getElementById('dmxchannels').innerHTML += "";
|
||||||
}
|
for (i=0;i<num;i++) {
|
||||||
function mMap(){
|
d.getElementById('dmxchannels').innerHTML += "<span id=CH" + (i+1) + "s >Channel " + (i+1) + ": <select name=CH" + (i+1) + " id=\"CH" + (i+1) + "\"><option value=0>Set to 0</option><option value=1>Red</option><option value=2>Green</option><option value=3>Blue</option><option value=4>White</option><option value=5>Shutter (Brightness)</option><option value=6>Set to 255</option></select></span><br />\n";
|
||||||
d=document;
|
|
||||||
numCh=document.Sf.CN.value;
|
|
||||||
numGap=document.Sf.CG.value;
|
|
||||||
if (parseInt(numCh)>parseInt(numGap)) {
|
|
||||||
d.getElementById("gapwarning").style.display="block";
|
|
||||||
} else {
|
|
||||||
d.getElementById("gapwarning").style.display="none";
|
|
||||||
}
|
|
||||||
for (i=0;i<15;i++) {
|
|
||||||
if (i>=numCh) {
|
|
||||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
|
||||||
d.getElementById("CH"+(i+1)).disabled = true;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
|
||||||
d.getElementById("CH"+(i+1)).disabled = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
function mMap(){
|
||||||
function S(){GCH(15);GetV();mMap();}function H(){window.open("https://github.com/Aircoookie/WLED/wiki/DMX");}function B(){window.history.back();}
|
numCh=document.Sf.CN.value;
|
||||||
function GetV(){}
|
numGap=document.Sf.CG.value;
|
||||||
|
if (parseInt(numCh)>parseInt(numGap)) {
|
||||||
|
d.getElementById("gapwarning").style.display="block";
|
||||||
|
} else {
|
||||||
|
d.getElementById("gapwarning").style.display="none";
|
||||||
|
}
|
||||||
|
for (i=0;i<15;i++) {
|
||||||
|
if (i>=numCh) {
|
||||||
|
d.getElementById("CH"+(i+1) + "s").style.opacity = "0.5";
|
||||||
|
d.getElementById("CH"+(i+1)).disabled = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
d.getElementById("CH"+(i+1) + "s").style.opacity = "1";
|
||||||
|
d.getElementById("CH"+(i+1)).disabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GCH(15);GetV();mMap();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function S(){
|
||||||
|
if (window.location.protocol == "file:") {
|
||||||
|
loc = true;
|
||||||
|
locip = localStorage.getItem('locIp');
|
||||||
|
if (!locip) {
|
||||||
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=7';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
|
@ -8,10 +8,29 @@
|
|||||||
<script>
|
<script>
|
||||||
var d=document,laprev=55,maxB=1,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
var d=document,laprev=55,maxB=1,maxM=4000,maxPB=4096,maxL=1333,maxLbquot=0; //maximum bytes for LED allocation: 4kB for 8266, 32kB for 32
|
||||||
var customStarts=false,startsDirty=[],maxCOOverrides=5;
|
var customStarts=false,startsDirty=[],maxCOOverrides=5;
|
||||||
|
var loc = false, locip;
|
||||||
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
|
function H(){window.open("https://kno.wled.ge/features/settings/#led-settings");}
|
||||||
function B(){window.open("/settings","_self");}
|
function B(){window.open("/settings","_self");}
|
||||||
function gId(n){return d.getElementById(n);}
|
function gId(n){return d.getElementById(n);}
|
||||||
function off(n){d.getElementsByName(n)[0].value = -1;}
|
function off(n){d.getElementsByName(n)[0].value = -1;}
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();checkSi();setABL();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
var timeout;
|
var timeout;
|
||||||
function showToast(text, error = false)
|
function showToast(text, error = false)
|
||||||
{
|
{
|
||||||
@ -506,12 +525,17 @@ Length: <input type="number" name="XC${i}" id="xc${i}" class="l" min="1" max="65
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function S(){GetV();checkSi();setABL();}
|
function S(){
|
||||||
function GetV()
|
if (window.location.protocol == "file:") {
|
||||||
{
|
loc = true;
|
||||||
//values injected by server while sending HTML
|
locip = localStorage.getItem('locIp');
|
||||||
//d.um_p=[6,7,8,9,10,11,1];bLimits(3,4096,4000,1664);d.Sf.MS.checked=1;addLEDs(1);d.Sf.L00.value=2;d.Sf.LC0.value=30;d.Sf.LT0.value=22;d.Sf.CO0.value=0;d.Sf.LS0.value=15;d.Sf.CV0.checked=1;d.Sf.SL0.checked=0;addLEDs(1);d.Sf.L01.value=10;d.Sf.L11.value=10;d.Sf.L21.value=1;d.Sf.L31.value=10;d.Sf.LC1.value=60;d.Sf.LT1.value=80;d.Sf.CO1.value=1;d.Sf.LS1.value=0;d.Sf.CV1.checked=0;d.Sf.SL1.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=56;d.Sf.AW.value=3;d.Sf.BO.checked=1;d.Sf.BP.value=80;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=0;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=0;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=12;d.Sf.RM.checked=1;addBtn(0,0,0);addBtn(1,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=0;
|
if (!locip) {
|
||||||
//d.um_p=[6,7,8,9,10,11,14,15,13,1,21,19,22,25,26,27,5,23,18,17];bLimits(10,2048,64000,8192);d.Sf.MS.checked=1;d.Sf.CCT.checked=0;addLEDs(1);d.Sf.L00.value=192;d.Sf.L10.value=168;d.Sf.L20.value=0;d.Sf.L30.value=61;d.Sf.LC0.value=421;d.Sf.LT0.value=80;d.Sf.CO0.value=1;d.Sf.LS0.value=0;d.Sf.CV0.checked=0;d.Sf.SL0.checked=0;d.Sf.RF0.checked=0;d.Sf.MA.value=850;d.Sf.LA.value=0;d.Sf.CA.value=127;d.Sf.AW.value=3;d.Sf.BO.checked=0;d.Sf.BP.value=0;d.Sf.GB.checked=0;d.Sf.GC.checked=1;d.Sf.TF.checked=1;d.Sf.TD.value=700;d.Sf.PF.checked=1;d.Sf.BF.value=100;d.Sf.TB.value=0;d.Sf.TL.value=60;d.Sf.TW.value=1;d.Sf.PB.selectedIndex=0;d.Sf.RL.value=-1;d.Sf.RM.checked=1;addBtn(0,-1,0);addBtn(1,-1,0);addBtn(2,-1,0);addBtn(3,-1,0);d.Sf.TT.value=32;d.Sf.IR.value=-1;d.Sf.IT.value=8;
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=2';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
|
@ -7,11 +7,30 @@
|
|||||||
<title>Misc Settings</title>
|
<title>Misc Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
|
var loc = false, locip;
|
||||||
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
|
function H() { window.open("https://kno.wled.ge/features/settings/#security-settings"); }
|
||||||
function B() { window.open("/settings","_self"); }
|
function B() { window.open("/settings","_self"); }
|
||||||
function U() { window.open("/update","_self"); }
|
function U() { window.open("/update","_self"); }
|
||||||
function gId(s) { return d.getElementById(s); }
|
function gId(s) { return d.getElementById(s); }
|
||||||
function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); }
|
function isObj(o) { return (o && typeof o === 'object' && !Array.isArray(o)); }
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
var timeout;
|
var timeout;
|
||||||
function showToast(text, error = false)
|
function showToast(text, error = false)
|
||||||
{
|
{
|
||||||
@ -40,16 +59,24 @@
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function GetV()
|
function S() {
|
||||||
{
|
if (window.location.protocol == "file:") {
|
||||||
//values injected by server while sending HTML
|
loc = true;
|
||||||
|
locip = localStorage.getItem('locIp');
|
||||||
|
if (!locip) {
|
||||||
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=6';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>
|
<style>
|
||||||
@import url("style.css");
|
@import url("style.css");
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body onload="GetV()">
|
<body onload="S()">
|
||||||
<form id="form_s" name="Sf" method="post">
|
<form id="form_s" name="Sf" method="post">
|
||||||
<div class="toprow">
|
<div class="toprow">
|
||||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||||
|
@ -5,42 +5,71 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<title>Sync Settings</title>
|
<title>Sync Settings</title>
|
||||||
<script>var d=document;
|
<script>var d=document;
|
||||||
function gId(s)
|
var loc = false, locip;
|
||||||
{
|
function gId(s)
|
||||||
return d.getElementById(s);
|
|
||||||
}
|
|
||||||
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
|
||||||
function B(){window.open("/settings","_self");}
|
|
||||||
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
|
||||||
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
|
||||||
function FC()
|
|
||||||
{
|
|
||||||
for(j=0;j<8;j++)
|
|
||||||
{
|
{
|
||||||
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
return d.getElementById(s);
|
||||||
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
|
||||||
}
|
}
|
||||||
}
|
function H(){window.open("https://kno.wled.ge/interfaces/udp-notifier/");}
|
||||||
function GC()
|
function B(){window.open("/settings","_self");}
|
||||||
{
|
function adj(){if (d.Sf.DI.value == 6454) {if (d.Sf.DA.value == 1) d.Sf.DA.value = 0; if (d.Sf.EU.value == 1) d.Sf.EU.value = 0;}
|
||||||
var a=0, b=0;
|
else if (d.Sf.DI.value == 5568) {if (d.Sf.DA.value == 0) d.Sf.DA.value = 1; if (d.Sf.EU.value == 0) d.Sf.EU.value = 1;} }
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();SetVal();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function FC()
|
||||||
|
{
|
||||||
|
for(j=0;j<8;j++)
|
||||||
|
{
|
||||||
|
gId("G"+(j+1)).checked=gId("GS").value>>j&1;
|
||||||
|
gId("R"+(j+1)).checked=gId("GR").value>>j&1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function GC()
|
||||||
|
{
|
||||||
|
var a=0, b=0;
|
||||||
|
|
||||||
var m=1;
|
var m=1;
|
||||||
for(j=0;j<8;j++)
|
for(j=0;j<8;j++)
|
||||||
{
|
{
|
||||||
a+=gId("G"+(j+1)).checked*m;
|
a+=gId("G"+(j+1)).checked*m;
|
||||||
b+=gId("R"+(j+1)).checked*m;
|
b+=gId("R"+(j+1)).checked*m;
|
||||||
m*=2;
|
m*=2;
|
||||||
|
}
|
||||||
|
gId("GS").value=a;
|
||||||
|
gId("GR").value=b;
|
||||||
}
|
}
|
||||||
gId("GS").value=a;
|
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
||||||
gId("GR").value=b;
|
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
||||||
}
|
function S(){
|
||||||
function SP(){var p = d.Sf.DI.value; gId("xp").style.display = (p > 0)?"none":"block"; if (p > 0) d.Sf.EP.value = p;}
|
if (window.location.protocol == "file:") {
|
||||||
function SetVal(){switch(parseInt(d.Sf.EP.value)){case 5568: d.Sf.DI.value = 5568; break; case 6454: d.Sf.DI.value = 6454; break; case 4048: d.Sf.DI.value = 4048; break; }; SP();FC();}
|
loc = true;
|
||||||
function S(){GetV();SetVal();}
|
locip = localStorage.getItem('locIp');
|
||||||
function GetV(){var d=document;}
|
if (!locip) {
|
||||||
</script>
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=4';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
|
}
|
||||||
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
<body onload="S()">
|
<body onload="S()">
|
||||||
|
@ -7,26 +7,42 @@
|
|||||||
<title>Time Settings</title>
|
<title>Time Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d=document;
|
var d=document;
|
||||||
|
var loc = false, locip;
|
||||||
var el=false;
|
var el=false;
|
||||||
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
var ms=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
|
||||||
function H()
|
function H() { window.open("https://kno.wled.ge/features/settings/#time-settings"); }
|
||||||
{
|
function B() { window.open("/settings","_self"); }
|
||||||
window.open("https://kno.wled.ge/features/settings/#time-settings");
|
function gId(s) { return d.getElementById(s); }
|
||||||
|
function gN(s) { return d.getElementsByName(s)[0]; }
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
BTa();GetV();updLoc();Cs();FC();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function B()
|
function S() {
|
||||||
{
|
if (window.location.protocol == "file:") {
|
||||||
window.open("/settings","_self");
|
loc = true;
|
||||||
}
|
locip = localStorage.getItem('locIp');
|
||||||
function S()
|
if (!locip) {
|
||||||
{
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
BTa();GetV();updLoc();Cs();FC();
|
localStorage.setItem('locIp', locip);
|
||||||
}
|
}
|
||||||
function gId(s)
|
}
|
||||||
{
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=5';
|
||||||
return d.getElementById(s);
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
}
|
|
||||||
function gN(s) {
|
|
||||||
return d.getElementsByName(s)[0];
|
|
||||||
}
|
}
|
||||||
function expand(o,i)
|
function expand(o,i)
|
||||||
{
|
{
|
||||||
@ -34,10 +50,7 @@
|
|||||||
t.style.display = t.style.display!=="none" ? "none" : "";
|
t.style.display = t.style.display!=="none" ? "none" : "";
|
||||||
o.innerHTML = t.style.display==="none" ? "📅" : "✕";
|
o.innerHTML = t.style.display==="none" ? "📅" : "✕";
|
||||||
}
|
}
|
||||||
function Cs()
|
function Cs() { gId("cac").style.display=(gN("OL").checked)?"block":"none"; }
|
||||||
{
|
|
||||||
gId("cac").style.display=(gN("OL").checked)?"block":"none";
|
|
||||||
}
|
|
||||||
function BTa()
|
function BTa()
|
||||||
{
|
{
|
||||||
var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>";
|
var ih="<thead><tr><th>En.</th><th>Hour</th><th>Minute</th><th>Preset</th><th></th></tr></thead>";
|
||||||
@ -132,10 +145,6 @@
|
|||||||
if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N";
|
if (parseFloat(d.Sf.LT.value)<0) { d.Sf.LTR.value = "S"; d.Sf.LT.value = -1*parseFloat(d.Sf.LT.value); } else d.Sf.LTR.value = "N";
|
||||||
if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E";
|
if (parseFloat(d.Sf.LN.value)<0) { d.Sf.LNR.value = "W"; d.Sf.LN.value = -1*parseFloat(d.Sf.LN.value); } else d.Sf.LNR.value = "E";
|
||||||
}
|
}
|
||||||
function GetV()
|
|
||||||
{
|
|
||||||
//values injected by server while sending HTML
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
<title>UI Settings</title>
|
<title>UI Settings</title>
|
||||||
<script>
|
<script>
|
||||||
var d = document;
|
var d = document;
|
||||||
|
var loc = false, locip;
|
||||||
var initial_ds, initial_st, initial_su;
|
var initial_ds, initial_st, initial_su;
|
||||||
var sett = null;
|
var sett = null;
|
||||||
var l = {
|
var l = {
|
||||||
@ -23,6 +24,7 @@
|
|||||||
"pid": "Show preset IDs",
|
"pid": "Show preset IDs",
|
||||||
"seglen": "Set segment length instead of stop LED",
|
"seglen": "Set segment length instead of stop LED",
|
||||||
"segpwr": "Hide segment power & brightness",
|
"segpwr": "Hide segment power & brightness",
|
||||||
|
"segexp" : "Always expand first segment",
|
||||||
"css": "Enable custom CSS",
|
"css": "Enable custom CSS",
|
||||||
"hdays": "Enable custom Holidays list"
|
"hdays": "Enable custom Holidays list"
|
||||||
},
|
},
|
||||||
@ -40,10 +42,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
function gId(s)
|
function gId(s) { return d.getElementById(s); }
|
||||||
{
|
|
||||||
return d.getElementById(s);
|
|
||||||
}
|
|
||||||
function isObject(item) {
|
function isObject(item) {
|
||||||
return (item && typeof item === 'object' && !Array.isArray(item));
|
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||||
}
|
}
|
||||||
@ -163,22 +162,43 @@
|
|||||||
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
|
if (d.Sf.DS.value != initial_ds || d.Sf.ST.checked != initial_st || d.Sf.SU.checked != initial_su) d.Sf.submit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
|
function loadJS(FILE_URL, async = true) {
|
||||||
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();
|
||||||
|
initial_ds = d.Sf.DS.value;
|
||||||
|
initial_st = d.Sf.ST.checked;
|
||||||
|
initial_su = d.Sf.SU.checked;
|
||||||
|
GetLS();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
function S()
|
function S()
|
||||||
{
|
{
|
||||||
GetV();
|
if (window.location.protocol == "file:") {
|
||||||
initial_ds = d.Sf.DS.value;
|
loc = true;
|
||||||
initial_st = d.Sf.ST.checked;
|
locip = localStorage.getItem('locIp');
|
||||||
initial_su = d.Sf.SU.checked;
|
if (!locip) {
|
||||||
GetLS();
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
}
|
localStorage.setItem('locIp', locip);
|
||||||
function H()
|
}
|
||||||
{
|
}
|
||||||
window.open("https://kno.wled.ge/features/settings/#user-interface-settings");
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=3';
|
||||||
}
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
function B()
|
|
||||||
{
|
|
||||||
window.open("/settings","_self");
|
|
||||||
}
|
}
|
||||||
|
function H() { window.open("https://kno.wled.ge/features/settings/#user-interface-settings"); }
|
||||||
|
function B() { window.open("/settings","_self"); }
|
||||||
function UI()
|
function UI()
|
||||||
{
|
{
|
||||||
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
gId('idonthateyou').style.display = (gId('dm').checked) ? 'inline':'none';
|
||||||
@ -213,7 +233,6 @@
|
|||||||
fO.value = '';
|
fO.value = '';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
function GetV(){var d=document;}
|
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
@ -241,6 +260,7 @@
|
|||||||
<span class="l"></span>: <input type="checkbox" id="comp_pid" class="agi cb"><br>
|
<span class="l"></span>: <input type="checkbox" id="comp_pid" class="agi cb"><br>
|
||||||
<span class="l"></span>: <input type="checkbox" id="comp_seglen" class="agi cb"><br>
|
<span class="l"></span>: <input type="checkbox" id="comp_seglen" class="agi cb"><br>
|
||||||
<span class="l"></span>: <input type="checkbox" id="comp_segpwr" class="agi cb"><br>
|
<span class="l"></span>: <input type="checkbox" id="comp_segpwr" class="agi cb"><br>
|
||||||
|
<span class="l"></span>: <input type="checkbox" id="comp_segexp" class="agi cb"><br>
|
||||||
I hate dark mode: <input type="checkbox" id="dm" onchange="UI()"><br>
|
I hate dark mode: <input type="checkbox" id="dm" onchange="UI()"><br>
|
||||||
<span id="idonthateyou" style="display:none"><i>Why would you? </i>🥺<br></span>
|
<span id="idonthateyou" style="display:none"><i>Why would you? </i>🥺<br></span>
|
||||||
<span class="l"></span>: <input type="number" min=0.0 max=1.0 step=0.01 id="theme_alpha_tab" class="agi"><br>
|
<span class="l"></span>: <input type="number" min=0.0 max=1.0 step=0.01 id="theme_alpha_tab" class="agi"><br>
|
||||||
|
@ -81,6 +81,7 @@
|
|||||||
}
|
}
|
||||||
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
function addField(k,f,o,a=false) { //key, field, (sub)object, isArray
|
||||||
if (isO(o)) {
|
if (isO(o)) {
|
||||||
|
urows += '<hr style="width:260px">';
|
||||||
for (const [s,v] of Object.entries(o)) {
|
for (const [s,v] of Object.entries(o)) {
|
||||||
// possibility to nest objects (only 1 level)
|
// possibility to nest objects (only 1 level)
|
||||||
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
if (f!=='unknown' && !k.includes(":")) addField(k+":"+f,s,v);
|
||||||
@ -191,7 +192,6 @@
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
if (d.Sf.checkValidity()) d.Sf.submit(); //https://stackoverflow.com/q/37323914
|
||||||
}
|
}
|
||||||
//fun-ction GetV() {} // replaced during 'npm run build'
|
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
|
@ -6,16 +6,44 @@
|
|||||||
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
<meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" name="viewport"/>
|
||||||
<title>WiFi Settings</title>
|
<title>WiFi Settings</title>
|
||||||
<script>
|
<script>
|
||||||
|
var d=document;
|
||||||
|
var loc = false, locip;
|
||||||
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
|
function H(){window.open("https://kno.wled.ge/features/settings/#wifi-settings");}
|
||||||
function B(){window.open("/settings","_self");}
|
function B(){window.open("/settings","_self");}
|
||||||
function GetV()
|
// https://www.educative.io/edpresso/how-to-dynamically-load-a-js-file-in-javascript
|
||||||
{
|
function loadJS(FILE_URL, async = true) {
|
||||||
//values injected by server while sending HTML
|
let scE = d.createElement("script");
|
||||||
|
scE.setAttribute("src", FILE_URL);
|
||||||
|
scE.setAttribute("type", "text/javascript");
|
||||||
|
scE.setAttribute("async", async);
|
||||||
|
d.body.appendChild(scE);
|
||||||
|
// success event
|
||||||
|
scE.addEventListener("load", () => {
|
||||||
|
//console.log("File loaded");
|
||||||
|
GetV();
|
||||||
|
});
|
||||||
|
// error event
|
||||||
|
scE.addEventListener("error", (ev) => {
|
||||||
|
console.log("Error on loading file", ev);
|
||||||
|
alert("Loading of configuration script failed.\nIncomplete page data!");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function S() {
|
||||||
|
if (window.location.protocol == "file:") {
|
||||||
|
loc = true;
|
||||||
|
locip = localStorage.getItem('locIp');
|
||||||
|
if (!locip) {
|
||||||
|
locip = prompt("File Mode. Please enter WLED IP!");
|
||||||
|
localStorage.setItem('locIp', locip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var url = (loc?`http://${locip}`:'') + '/settings/s.js?p=1';
|
||||||
|
loadJS(url, false); // If we set async false, file is loaded and executed, then next statement is processed
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style>@import url("style.css");</style>
|
<style>@import url("style.css");</style>
|
||||||
</head>
|
</head>
|
||||||
<body onload="GetV()">
|
<body onload="S()">
|
||||||
<form id="form_s" name="Sf" method="post">
|
<form id="form_s" name="Sf" method="post">
|
||||||
<div class="toprow">
|
<div class="toprow">
|
||||||
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
<div class="helpB"><button type="button" onclick="H()">?</button></div>
|
||||||
|
@ -58,6 +58,9 @@ bool getJsonValue(const JsonVariant& element, DestType& destination, const Defau
|
|||||||
|
|
||||||
|
|
||||||
//colors.cpp
|
//colors.cpp
|
||||||
|
uint32_t color_blend(uint32_t,uint32_t,uint16_t,bool b16=false);
|
||||||
|
uint32_t color_add(uint32_t,uint32_t);
|
||||||
|
|
||||||
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
inline uint32_t colorFromRgbw(byte* rgbw) { return uint32_t((byte(rgbw[3]) << 24) | (byte(rgbw[0]) << 16) | (byte(rgbw[1]) << 8) | (byte(rgbw[2]))); }
|
||||||
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
void colorHStoRGB(uint16_t hue, byte sat, byte* rgb); //hue, sat to rgb
|
||||||
void colorKtoRGB(uint16_t kelvin, byte* rgb);
|
void colorKtoRGB(uint16_t kelvin, byte* rgb);
|
||||||
@ -129,7 +132,7 @@ void handleIR();
|
|||||||
|
|
||||||
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
void deserializeSegment(JsonObject elem, byte it, byte presetId = 0);
|
||||||
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
bool deserializeState(JsonObject root, byte callMode = CALL_MODE_DIRECT_CHANGE, byte presetId = 0);
|
||||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset = false, bool segmentBounds = true);
|
||||||
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
void serializeState(JsonObject root, bool forPreset = false, bool includeBri = true, bool segmentBounds = true);
|
||||||
void serializeInfo(JsonObject root);
|
void serializeInfo(JsonObject root);
|
||||||
void serializeModeNames(JsonArray arr, const char *qstring);
|
void serializeModeNames(JsonArray arr, const char *qstring);
|
||||||
@ -296,7 +299,7 @@ class UsermodManager {
|
|||||||
void onUpdateBegin(bool);
|
void onUpdateBegin(bool);
|
||||||
bool add(Usermod* um);
|
bool add(Usermod* um);
|
||||||
Usermod* lookup(uint16_t mod_id);
|
Usermod* lookup(uint16_t mod_id);
|
||||||
byte getModCount();
|
byte getModCount() {return numMods;};
|
||||||
};
|
};
|
||||||
|
|
||||||
//usermods_list.cpp
|
//usermods_list.cpp
|
||||||
@ -321,8 +324,10 @@ bool isAsterisksOnly(const char* str, byte maxLen);
|
|||||||
bool requestJSONBufferLock(uint8_t module=255);
|
bool requestJSONBufferLock(uint8_t module=255);
|
||||||
void releaseJSONBufferLock();
|
void releaseJSONBufferLock();
|
||||||
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLen);
|
||||||
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen);
|
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var = nullptr);
|
||||||
|
int16_t extractModeDefaults(uint8_t mode, const char *segVar);
|
||||||
uint16_t crc16(const unsigned char* data_p, size_t length);
|
uint16_t crc16(const unsigned char* data_p, size_t length);
|
||||||
|
um_data_t* simulateSound(uint8_t simulationId);
|
||||||
|
|
||||||
//wled_eeprom.cpp
|
//wled_eeprom.cpp
|
||||||
void applyMacro(byte index);
|
void applyMacro(byte index);
|
||||||
|
File diff suppressed because it is too large
Load Diff
3597
wled00/html_ui.h
3597
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -89,8 +89,8 @@ byte relativeChange(byte property, int8_t amount, byte lowerBoundary, byte highe
|
|||||||
void changeEffect(uint8_t fx)
|
void changeEffect(uint8_t fx)
|
||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
strip.setMode(i, fx);
|
strip.setMode(i, fx);
|
||||||
}
|
}
|
||||||
@ -105,8 +105,8 @@ void changeEffect(uint8_t fx)
|
|||||||
void changePalette(uint8_t pal)
|
void changePalette(uint8_t pal)
|
||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.palette = pal;
|
seg.palette = pal;
|
||||||
}
|
}
|
||||||
@ -124,8 +124,8 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
int16_t new_val = (int16_t) effectSpeed + amount;
|
int16_t new_val = (int16_t) effectSpeed + amount;
|
||||||
effectSpeed = (byte)constrain(new_val,0,255);
|
effectSpeed = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.speed = effectSpeed;
|
seg.speed = effectSpeed;
|
||||||
}
|
}
|
||||||
@ -135,7 +135,7 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
setValuesFromMainSeg();
|
setValuesFromMainSeg();
|
||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the hue of the primary color
|
} else { // if Effect == "solid Color", change the hue of the primary color
|
||||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
fastled_col.red = R(sseg.colors[0]);
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
fastled_col.green = G(sseg.colors[0]);
|
||||||
@ -147,8 +147,8 @@ void changeEffectSpeed(int8_t amount)
|
|||||||
prim_hsv.h = (byte)new_val;
|
prim_hsv.h = (byte)new_val;
|
||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||||
}
|
}
|
||||||
@ -171,8 +171,8 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
int16_t new_val = (int16_t) effectIntensity + amount;
|
int16_t new_val = (int16_t) effectIntensity + amount;
|
||||||
effectIntensity = (byte)constrain(new_val,0,255);
|
effectIntensity = (byte)constrain(new_val,0,255);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.intensity = effectIntensity;
|
seg.intensity = effectIntensity;
|
||||||
}
|
}
|
||||||
@ -182,7 +182,7 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
setValuesFromMainSeg();
|
setValuesFromMainSeg();
|
||||||
}
|
}
|
||||||
} else { // if Effect == "solid Color", change the saturation of the primary color
|
} else { // if Effect == "solid Color", change the saturation of the primary color
|
||||||
WS2812FX::Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& sseg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
CRGB fastled_col;
|
CRGB fastled_col;
|
||||||
fastled_col.red = R(sseg.colors[0]);
|
fastled_col.red = R(sseg.colors[0]);
|
||||||
fastled_col.green = G(sseg.colors[0]);
|
fastled_col.green = G(sseg.colors[0]);
|
||||||
@ -192,8 +192,8 @@ void changeEffectIntensity(int8_t amount)
|
|||||||
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
|
prim_hsv.s = (byte)constrain(new_val,0,255); // constrain to 0-255
|
||||||
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
hsv2rgb_rainbow(prim_hsv, fastled_col);
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
seg.colors[0] = RGBW32(fastled_col.red, fastled_col.green, fastled_col.blue, W(sseg.colors[0]));
|
||||||
}
|
}
|
||||||
@ -214,8 +214,8 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
{
|
{
|
||||||
if (irApplyToAllSelected) {
|
if (irApplyToAllSelected) {
|
||||||
// main segment may not be selected!
|
// main segment may not be selected!
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
byte capabilities = seg.getLightCapabilities();
|
byte capabilities = seg.getLightCapabilities();
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
@ -226,14 +226,14 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
||||||
if (hasW) mask |= 0xFF000000; // white
|
if (hasW) mask |= 0xFF000000; // white
|
||||||
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
||||||
seg.setColor(0, c | 0xFFFFFF, i); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
seg.setColor(0, c | 0xFFFFFF); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||||
} else if (c & mask) seg.setColor(0, c & mask, i); // only apply if not black
|
} else if (c & mask) seg.setColor(0, c & mask); // only apply if not black
|
||||||
if (isCCT && cct >= 0) seg.setCCT(cct, i);
|
if (isCCT && cct >= 0) seg.setCCT(cct);
|
||||||
}
|
}
|
||||||
setValuesFromFirstSelectedSeg();
|
setValuesFromFirstSelectedSeg();
|
||||||
} else {
|
} else {
|
||||||
byte i = strip.getMainSegmentId();
|
byte i = strip.getMainSegmentId();
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
byte capabilities = seg.getLightCapabilities();
|
byte capabilities = seg.getLightCapabilities();
|
||||||
uint32_t mask = 0;
|
uint32_t mask = 0;
|
||||||
bool isRGB = GET_BIT(capabilities, 0); // is segment RGB capable
|
bool isRGB = GET_BIT(capabilities, 0); // is segment RGB capable
|
||||||
@ -243,9 +243,9 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
if (isRGB) mask |= 0x00FFFFFF; // RGB
|
||||||
if (hasW) mask |= 0xFF000000; // white
|
if (hasW) mask |= 0xFF000000; // white
|
||||||
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
if (hasW && !wSlider && (c & 0xFF000000)) { // segment has white channel & white channel is auto calculated & white specified
|
||||||
seg.setColor(0, c | 0xFFFFFF, i); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
seg.setColor(0, c | 0xFFFFFF); // for accurate/brighter mode we fake white (since button may not set white color to 0xFFFFFF)
|
||||||
} else if (c & mask) seg.setColor(0, c & mask, i); // only apply if not black
|
} else if (c & mask) seg.setColor(0, c & mask); // only apply if not black
|
||||||
if (isCCT && cct >= 0) seg.setCCT(cct, i);
|
if (isCCT && cct >= 0) seg.setCCT(cct);
|
||||||
setValuesFromMainSeg();
|
setValuesFromMainSeg();
|
||||||
}
|
}
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
@ -253,7 +253,7 @@ void changeColor(uint32_t c, int16_t cct=-1)
|
|||||||
|
|
||||||
void changeWhite(int8_t amount, int16_t cct=-1)
|
void changeWhite(int8_t amount, int16_t cct=-1)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
byte r = R(seg.colors[0]);
|
||||||
byte g = G(seg.colors[0]);
|
byte g = G(seg.colors[0]);
|
||||||
byte b = B(seg.colors[0]);
|
byte b = B(seg.colors[0]);
|
||||||
@ -424,7 +424,7 @@ void decodeIR24CT(uint32_t code)
|
|||||||
|
|
||||||
void decodeIR40(uint32_t code)
|
void decodeIR40(uint32_t code)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
Segment& seg = irApplyToAllSelected ? strip.getFirstSelectedSeg() : strip.getMainSegment();
|
||||||
byte r = R(seg.colors[0]);
|
byte r = R(seg.colors[0]);
|
||||||
byte g = G(seg.colors[0]);
|
byte g = G(seg.colors[0]);
|
||||||
byte b = B(seg.colors[0]);
|
byte b = B(seg.colors[0]);
|
||||||
@ -712,7 +712,7 @@ void initIR()
|
|||||||
|
|
||||||
void handleIR()
|
void handleIR()
|
||||||
{
|
{
|
||||||
if (irEnabled > 0 && millis() - irCheckedTime > 120)
|
if (irEnabled > 0 && millis() - irCheckedTime > 120 && !strip.isUpdating())
|
||||||
{
|
{
|
||||||
irCheckedTime = millis();
|
irCheckedTime = millis();
|
||||||
if (irEnabled > 0)
|
if (irEnabled > 0)
|
||||||
|
174
wled00/json.cpp
174
wled00/json.cpp
@ -11,11 +11,19 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
byte id = elem["id"] | it;
|
byte id = elem["id"] | it;
|
||||||
if (id >= strip.getMaxSegments()) return;
|
if (id >= strip.getMaxSegments()) return;
|
||||||
|
|
||||||
WS2812FX::Segment& seg = strip.getSegment(id);
|
int stop = elem["stop"] | -1;
|
||||||
WS2812FX::Segment prev = seg; //make a backup so we can tell if something changed
|
|
||||||
|
// if using vectors use this code to append segment
|
||||||
|
if (id >= strip.getSegmentsNum()) {
|
||||||
|
if (stop <= 0) return; // ignore empty/inactive segments
|
||||||
|
strip.appendSegment(Segment(0, strip.getLengthTotal()));
|
||||||
|
id = strip.getSegmentsNum()-1; // segments are added at the end of list
|
||||||
|
}
|
||||||
|
|
||||||
|
Segment& seg = strip.getSegment(id);
|
||||||
|
Segment prev = seg; //make a backup so we can tell if something changed
|
||||||
|
|
||||||
uint16_t start = elem["start"] | seg.start;
|
uint16_t start = elem["start"] | seg.start;
|
||||||
int stop = elem["stop"] | -1;
|
|
||||||
if (stop < 0) {
|
if (stop < 0) {
|
||||||
uint16_t len = elem["len"];
|
uint16_t len = elem["len"];
|
||||||
stop = (len > 0) ? start + len : seg.stop;
|
stop = (len > 0) ? start + len : seg.stop;
|
||||||
@ -31,7 +39,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
elem.remove("rpt"); // remove for recursive call
|
elem.remove("rpt"); // remove for recursive call
|
||||||
elem.remove("n"); // remove for recursive call
|
elem.remove("n"); // remove for recursive call
|
||||||
uint16_t len = stop - start;
|
uint16_t len = stop - start;
|
||||||
for (byte i=id+1; i<strip.getMaxSegments(); i++) {
|
for (size_t i=id+1; i<strip.getMaxSegments(); i++) {
|
||||||
start = start + len;
|
start = start + len;
|
||||||
if (start >= strip.getLengthTotal()) break;
|
if (start >= strip.getLengthTotal()) break;
|
||||||
//TODO: add support for 2D
|
//TODO: add support for 2D
|
||||||
@ -70,9 +78,14 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
|
|
||||||
uint16_t grp = elem["grp"] | seg.grouping;
|
uint16_t grp = elem["grp"] | seg.grouping;
|
||||||
uint16_t spc = elem[F("spc")] | seg.spacing;
|
uint16_t spc = elem[F("spc")] | seg.spacing;
|
||||||
uint16_t of = seg.offset;
|
uint16_t of = seg.offset;
|
||||||
|
uint8_t soundSim = elem[F("ssim")] | seg.soundSim;
|
||||||
|
uint8_t map1D2D = elem[F("mp12")] | seg.map1D2D;
|
||||||
|
|
||||||
if (spc>0 && spc!=seg.spacing) strip.fill(BLACK, id); // clear spacing gaps
|
if ((spc>0 && spc!=seg.spacing) || seg.map1D2D!=map1D2D) seg.fill(BLACK); // clear spacing gaps
|
||||||
|
|
||||||
|
seg.map1D2D = map1D2D & 0x03;
|
||||||
|
seg.soundSim = soundSim & 0x07;
|
||||||
|
|
||||||
uint16_t len = 1;
|
uint16_t len = 1;
|
||||||
if (stop > start) len = stop - start;
|
if (stop > start) len = stop - start;
|
||||||
@ -88,23 +101,23 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
|
|
||||||
byte segbri = seg.opacity;
|
byte segbri = seg.opacity;
|
||||||
if (getVal(elem["bri"], &segbri)) {
|
if (getVal(elem["bri"], &segbri)) {
|
||||||
if (segbri > 0) seg.setOpacity(segbri, id);
|
if (segbri > 0) seg.setOpacity(segbri);
|
||||||
seg.setOption(SEG_OPTION_ON, segbri, id);
|
seg.setOption(SEG_OPTION_ON, segbri);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
|
bool on = elem["on"] | seg.getOption(SEG_OPTION_ON);
|
||||||
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
|
if (elem["on"].is<const char*>() && elem["on"].as<const char*>()[0] == 't') on = !on;
|
||||||
seg.setOption(SEG_OPTION_ON, on, id);
|
seg.setOption(SEG_OPTION_ON, on);
|
||||||
bool frz = elem["frz"] | seg.getOption(SEG_OPTION_FREEZE);
|
bool frz = elem["frz"] | seg.getOption(SEG_OPTION_FREEZE);
|
||||||
if (elem["frz"].is<const char*>() && elem["frz"].as<const char*>()[0] == 't') frz = !seg.getOption(SEG_OPTION_FREEZE);
|
if (elem["frz"].is<const char*>() && elem["frz"].as<const char*>()[0] == 't') frz = !seg.getOption(SEG_OPTION_FREEZE);
|
||||||
seg.setOption(SEG_OPTION_FREEZE, frz, id);
|
seg.setOption(SEG_OPTION_FREEZE, frz);
|
||||||
|
|
||||||
seg.setCCT(elem["cct"] | seg.cct, id);
|
seg.setCCT(elem["cct"] | seg.cct);
|
||||||
|
|
||||||
JsonArray colarr = elem["col"];
|
JsonArray colarr = elem["col"];
|
||||||
if (!colarr.isNull())
|
if (!colarr.isNull())
|
||||||
{
|
{
|
||||||
for (uint8_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
int rgbw[] = {0,0,0,0};
|
int rgbw[] = {0,0,0,0};
|
||||||
bool colValid = false;
|
bool colValid = false;
|
||||||
@ -115,13 +128,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
if (hexCol == nullptr) { //Kelvin color temperature (or invalid), e.g 2400
|
||||||
int kelvin = colarr[i] | -1;
|
int kelvin = colarr[i] | -1;
|
||||||
if (kelvin < 0) continue;
|
if (kelvin < 0) continue;
|
||||||
if (kelvin == 0) seg.setColor(i, 0, id);
|
if (kelvin == 0) seg.setColor(i, 0);
|
||||||
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
if (kelvin > 0) colorKtoRGB(kelvin, brgbw);
|
||||||
colValid = true;
|
colValid = true;
|
||||||
} else { //HEX string, e.g. "FFAA00"
|
} else { //HEX string, e.g. "FFAA00"
|
||||||
colValid = colorFromHexString(brgbw, hexCol);
|
colValid = colorFromHexString(brgbw, hexCol);
|
||||||
}
|
}
|
||||||
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||||
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
} else { //Array of ints (RGB or RGBW color), e.g. [255,160,0]
|
||||||
byte sz = colX.size();
|
byte sz = colX.size();
|
||||||
if (sz == 0) continue; //do nothing on empty array
|
if (sz == 0) continue; //do nothing on empty array
|
||||||
@ -132,7 +145,7 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
|
|
||||||
if (!colValid) continue;
|
if (!colValid) continue;
|
||||||
|
|
||||||
seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]), id);
|
seg.setColor(i, RGBW32(rgbw[0],rgbw[1],rgbw[2],rgbw[3]));
|
||||||
if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh
|
if (seg.mode == FX_MODE_STATIC) strip.trigger(); //instant refresh
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,31 +162,74 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
seg.setOption(SEG_OPTION_SELECTED, elem[F("sel")] | seg.getOption(SEG_OPTION_SELECTED));
|
seg.setOption(SEG_OPTION_SELECTED, elem["sel"] | seg.getOption(SEG_OPTION_SELECTED));
|
||||||
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
seg.setOption(SEG_OPTION_REVERSED, elem["rev"] | seg.getOption(SEG_OPTION_REVERSED));
|
||||||
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
seg.setOption(SEG_OPTION_MIRROR , elem[F("mi")] | seg.getOption(SEG_OPTION_MIRROR ));
|
||||||
// 2D options
|
#ifndef WLED_DISABLE_2D
|
||||||
seg.setOption(SEG_OPTION_REVERSED_Y, elem[F("rY")] | seg.getOption(SEG_OPTION_REVERSED_Y));
|
seg.setOption(SEG_OPTION_REVERSED_Y, elem[F("rY")] | seg.getOption(SEG_OPTION_REVERSED_Y));
|
||||||
seg.setOption(SEG_OPTION_MIRROR_Y , elem[F("mY")] | seg.getOption(SEG_OPTION_MIRROR_Y ));
|
seg.setOption(SEG_OPTION_MIRROR_Y , elem[F("mY")] | seg.getOption(SEG_OPTION_MIRROR_Y ));
|
||||||
seg.setOption(SEG_OPTION_TRANSPOSED, elem[F("tp")] | seg.getOption(SEG_OPTION_TRANSPOSED));
|
seg.setOption(SEG_OPTION_TRANSPOSED, elem[F("tp")] | seg.getOption(SEG_OPTION_TRANSPOSED));
|
||||||
|
#endif
|
||||||
|
|
||||||
byte fx = seg.mode;
|
byte fx = seg.mode;
|
||||||
if (getVal(elem["fx"], &fx, 1, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 1-255 exact value)
|
if (getVal(elem["fx"], &fx, 0, strip.getModeCount())) { //load effect ('r' random, '~' inc/dec, 0-255 exact value)
|
||||||
if (!presetId && currentPlaylist>=0) unloadPlaylist();
|
if (!presetId && currentPlaylist>=0) unloadPlaylist();
|
||||||
strip.setMode(id, fx);
|
if (fx != seg.mode) {
|
||||||
|
//seg.startTransition(strip.getTransition()); // set effect transitions
|
||||||
|
seg.markForReset();
|
||||||
|
seg.mode = fx;
|
||||||
|
// load default values from effect string if effect is selected without
|
||||||
|
// any other effect parameter (i.e. effect clicked in UI)
|
||||||
|
if ( elem[F("sx")].isNull()
|
||||||
|
&& elem[F("ix")].isNull()
|
||||||
|
&& elem["pal"].isNull()
|
||||||
|
&& elem[F("c1")].isNull()
|
||||||
|
&& elem[F("c2")].isNull()
|
||||||
|
&& elem[F("c3")].isNull() )
|
||||||
|
{
|
||||||
|
// compatibility mode begin
|
||||||
|
char buf[5]; // dummy buffer
|
||||||
|
for (int i=0; i<5; i++) {
|
||||||
|
uint8_t *var;
|
||||||
|
switch (i) {
|
||||||
|
case 0: var = &seg.speed; break;
|
||||||
|
case 1: var = &seg.intensity; break;
|
||||||
|
case 2: var = &seg.custom1; break;
|
||||||
|
case 3: var = &seg.custom2; break;
|
||||||
|
case 4: var = &seg.custom3; break;
|
||||||
|
}
|
||||||
|
extractModeSlider(fx, i, buf, 4, var);
|
||||||
|
}
|
||||||
|
extractModeSlider(fx, 255, buf, 4, &seg.palette);
|
||||||
|
//end compatibility mode
|
||||||
|
int16_t sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("sx")); if (sOpt >= 0) seg.speed = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("ix")); if (sOpt >= 0) seg.intensity = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("c1")); if (sOpt >= 0) seg.custom1 = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("c2")); if (sOpt >= 0) seg.custom2 = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("c3")); if (sOpt >= 0) seg.custom3 = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, "pal"); if (sOpt >= 0 && sOpt < strip.getPaletteCount()) seg.palette = sOpt;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("mp12")); if (sOpt >= 0) seg.map1D2D = sOpt & 0x03;
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("ssim")); if (sOpt >= 0) seg.soundSim = sOpt & 0x07;
|
||||||
|
sOpt = extractModeDefaults(fx, "rev"); if (sOpt >= 0) seg.reverse = (bool)sOpt; // setOption(SEG_OPTION_REVERSED, (bool)sOpt); // NOTE: setting this option is a risky business
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("mi")); if (sOpt >= 0) seg.mirror = (bool)sOpt; // setOption(SEG_OPTION_MIRROR, (bool)sOpt); // NOTE: setting this option is a risky business
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("rY")); if (sOpt >= 0) seg.reverse_y = (bool)sOpt; // setOption(SEG_OPTION_REVERSED_Y, (bool)sOpt); // NOTE: setting this option is a risky business
|
||||||
|
sOpt = extractModeDefaults(fx, SET_F("mY")); if (sOpt >= 0) seg.mirror_y = (bool)sOpt; // setOption(SEG_OPTION_MIRROR_Y, (bool)sOpt); // NOTE: setting this option is a risky business
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//getVal also supports inc/decrementing and random
|
//getVal also supports inc/decrementing and random
|
||||||
getVal(elem[F("sx")], &seg.speed);
|
getVal(elem[F("sx")], &seg.speed);
|
||||||
getVal(elem[F("ix")], &seg.intensity);
|
getVal(elem[F("ix")], &seg.intensity);
|
||||||
getVal(elem["pal"], &seg.palette, 1, strip.getPaletteCount());
|
getVal(elem["pal"], &seg.palette, 1, strip.getPaletteCount());
|
||||||
getVal(elem[F("c1")], &seg.custom1);
|
getVal(elem[F("c1")], &seg.custom1);
|
||||||
getVal(elem[F("c2")], &seg.custom2);
|
getVal(elem[F("c2")], &seg.custom2);
|
||||||
getVal(elem[F("c3")], &seg.custom3);
|
getVal(elem[F("c3")], &seg.custom3);
|
||||||
|
|
||||||
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
JsonArray iarr = elem[F("i")]; //set individual LEDs
|
||||||
if (!iarr.isNull()) {
|
if (!iarr.isNull()) {
|
||||||
uint8_t oldSegId = strip.setPixelSegment(id);
|
//uint8_t oldSegId = strip.setPixelSegment(id);
|
||||||
|
|
||||||
// set brightness immediately and disable transition
|
// set brightness immediately and disable transition
|
||||||
transitionDelayTemp = 0;
|
transitionDelayTemp = 0;
|
||||||
@ -183,13 +239,13 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
// freeze and init to black
|
// freeze and init to black
|
||||||
if (!seg.getOption(SEG_OPTION_FREEZE)) {
|
if (!seg.getOption(SEG_OPTION_FREEZE)) {
|
||||||
seg.setOption(SEG_OPTION_FREEZE, true);
|
seg.setOption(SEG_OPTION_FREEZE, true);
|
||||||
strip.fill(0);
|
seg.fill(BLACK);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t start = 0, stop = 0;
|
uint16_t start = 0, stop = 0;
|
||||||
byte set = 0; //0 nothing set, 1 start set, 2 range set
|
byte set = 0; //0 nothing set, 1 start set, 2 range set
|
||||||
|
|
||||||
for (uint16_t i = 0; i < iarr.size(); i++) {
|
for (size_t i = 0; i < iarr.size(); i++) {
|
||||||
if(iarr[i].is<JsonInteger>()) {
|
if(iarr[i].is<JsonInteger>()) {
|
||||||
if (!set) {
|
if (!set) {
|
||||||
start = iarr[i];
|
start = iarr[i];
|
||||||
@ -208,29 +264,28 @@ void deserializeSegment(JsonObject elem, byte it, byte presetId)
|
|||||||
byte brgbw[] = {0,0,0,0};
|
byte brgbw[] = {0,0,0,0};
|
||||||
const char* hexCol = iarr[i];
|
const char* hexCol = iarr[i];
|
||||||
if (colorFromHexString(brgbw, hexCol)) {
|
if (colorFromHexString(brgbw, hexCol)) {
|
||||||
for (uint8_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
for (size_t c = 0; c < 4; c++) rgbw[c] = brgbw[c];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (set < 2) stop = start + 1;
|
if (set < 2) stop = start + 1;
|
||||||
for (uint16_t i = start; i < stop; i++) {
|
for (int i = start; i < stop; i++) {
|
||||||
if (strip.gammaCorrectCol) {
|
if (strip.gammaCorrectCol) {
|
||||||
strip.setPixelColor(i, strip.gamma8(rgbw[0]), strip.gamma8(rgbw[1]), strip.gamma8(rgbw[2]), strip.gamma8(rgbw[3]));
|
seg.setPixelColor(i, strip.gamma8(rgbw[0]), strip.gamma8(rgbw[1]), strip.gamma8(rgbw[2]), strip.gamma8(rgbw[3]));
|
||||||
} else {
|
} else {
|
||||||
strip.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
seg.setPixelColor(i, rgbw[0], rgbw[1], rgbw[2], rgbw[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!set) start++;
|
if (!set) start++;
|
||||||
set = 0;
|
set = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strip.setPixelSegment(oldSegId);
|
//strip.setPixelSegment(oldSegId);
|
||||||
strip.trigger();
|
strip.trigger();
|
||||||
}
|
}
|
||||||
// send UDP if not in preset and something changed that is not just selection
|
// send UDP if not in preset and something changed that is not just selection
|
||||||
// send UDP if something changed that is not just selection or segment power/opacity
|
// send UDP if something changed that is not just selection or segment power/opacity
|
||||||
if ((seg.differs(prev) & 0x7E) && seg.getOption(SEG_OPTION_ON)==prev.getOption(SEG_OPTION_ON)) stateChanged = true;
|
if ((seg.differs(prev) & 0x7E) && seg.getOption(SEG_OPTION_ON)==prev.getOption(SEG_OPTION_ON)) stateChanged = true;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// deserializes WLED state (fileDoc points to doc object if called from web server)
|
// deserializes WLED state (fileDoc points to doc object if called from web server)
|
||||||
@ -248,11 +303,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
if (root["on"].is<const char*>() && root["on"].as<const char*>()[0] == 't') toggleOnOff();
|
||||||
|
|
||||||
if (bri && !onBefore) { // unfreeze all segments when turning on
|
if (bri && !onBefore) { // unfreeze all segments when turning on
|
||||||
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
for (size_t s=0; s < strip.getSegmentsNum(); s++) {
|
||||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false, s);
|
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, false);
|
||||||
}
|
}
|
||||||
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
|
if (realtimeMode && !realtimeOverride && useMainSegmentOnly) { // keep live segment frozen if live
|
||||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -304,7 +359,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
realtimeOverride = root[F("lor")] | realtimeOverride;
|
realtimeOverride = root[F("lor")] | realtimeOverride;
|
||||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||||
if (realtimeMode && useMainSegmentOnly) {
|
if (realtimeMode && useMainSegmentOnly) {
|
||||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root.containsKey("live")) {
|
if (root.containsKey("live")) {
|
||||||
@ -326,13 +381,11 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
//apply all selected segments
|
//apply all selected segments
|
||||||
//bool didSet = false;
|
//bool didSet = false;
|
||||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
for (size_t s = 0; s < strip.getSegmentsNum(); s++) {
|
||||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
Segment &sg = strip.getSegment(s);
|
||||||
if (sg.isActive()) {
|
if (sg.isSelected()) {
|
||||||
if (sg.isSelected()) {
|
deserializeSegment(segVar, s, presetId);
|
||||||
deserializeSegment(segVar, s, presetId);
|
//didSet = true;
|
||||||
//didSet = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//TODO: not sure if it is good idea to change first active but unselected segment
|
//TODO: not sure if it is good idea to change first active but unselected segment
|
||||||
@ -342,8 +395,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
JsonArray segs = segVar.as<JsonArray>();
|
JsonArray segs = segVar.as<JsonArray>();
|
||||||
for (JsonObject elem : segs)
|
for (JsonObject elem : segs) {
|
||||||
{
|
|
||||||
deserializeSegment(elem, it, presetId);
|
deserializeSegment(elem, it, presetId);
|
||||||
it++;
|
it++;
|
||||||
}
|
}
|
||||||
@ -396,7 +448,7 @@ bool deserializeState(JsonObject root, byte callMode, byte presetId)
|
|||||||
return stateResponse;
|
return stateResponse;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
void serializeSegment(JsonObject& root, Segment& seg, byte id, bool forPreset, bool segmentBounds)
|
||||||
{
|
{
|
||||||
root["id"] = id;
|
root["id"] = id;
|
||||||
if (segmentBounds) {
|
if (segmentBounds) {
|
||||||
@ -423,7 +475,7 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
|||||||
// this will reduce RAM footprint from ~300 bytes to 84 bytes per segment
|
// this will reduce RAM footprint from ~300 bytes to 84 bytes per segment
|
||||||
char colstr[70]; colstr[0] = '['; colstr[1] = '\0'; //max len 68 (5 chan, all 255)
|
char colstr[70]; colstr[0] = '['; colstr[1] = '\0'; //max len 68 (5 chan, all 255)
|
||||||
const char *format = strip.hasWhiteChannel() ? PSTR("[%u,%u,%u,%u]") : PSTR("[%u,%u,%u]");
|
const char *format = strip.hasWhiteChannel() ? PSTR("[%u,%u,%u,%u]") : PSTR("[%u,%u,%u]");
|
||||||
for (uint8_t i = 0; i < 3; i++)
|
for (size_t i = 0; i < 3; i++)
|
||||||
{
|
{
|
||||||
byte segcol[4]; byte* c = segcol;
|
byte segcol[4]; byte* c = segcol;
|
||||||
segcol[0] = R(seg.colors[i]);
|
segcol[0] = R(seg.colors[i]);
|
||||||
@ -452,6 +504,8 @@ void serializeSegment(JsonObject& root, WS2812FX::Segment& seg, byte id, bool fo
|
|||||||
root[F("mY")] = seg.getOption(SEG_OPTION_MIRROR_Y);
|
root[F("mY")] = seg.getOption(SEG_OPTION_MIRROR_Y);
|
||||||
root[F("tp")] = seg.getOption(SEG_OPTION_TRANSPOSED);
|
root[F("tp")] = seg.getOption(SEG_OPTION_TRANSPOSED);
|
||||||
}
|
}
|
||||||
|
root[F("ssim")] = seg.soundSim;
|
||||||
|
root[F("mp12")] = seg.map1D2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segmentBounds)
|
void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segmentBounds)
|
||||||
@ -493,9 +547,17 @@ void serializeState(JsonObject root, bool forPreset, bool includeBri, bool segme
|
|||||||
|
|
||||||
bool selectedSegmentsOnly = root[F("sc")] | false;
|
bool selectedSegmentsOnly = root[F("sc")] | false;
|
||||||
JsonArray seg = root.createNestedArray("seg");
|
JsonArray seg = root.createNestedArray("seg");
|
||||||
for (byte s = 0; s < strip.getMaxSegments(); s++) {
|
for (size_t s = 0; s < strip.getMaxSegments(); s++) {
|
||||||
WS2812FX::Segment &sg = strip.getSegment(s);
|
if (s >= strip.getSegmentsNum()) {
|
||||||
if (selectedSegmentsOnly && !sg.isSelected()) continue;
|
if (forPreset && segmentBounds) { //disable segments not part of preset
|
||||||
|
JsonObject seg0 = seg.createNestedObject();
|
||||||
|
seg0["stop"] = 0;
|
||||||
|
continue;
|
||||||
|
} else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Segment &sg = strip.getSegment(s);
|
||||||
|
if (!forPreset && selectedSegmentsOnly && !sg.isSelected()) continue;
|
||||||
if (sg.isActive()) {
|
if (sg.isActive()) {
|
||||||
JsonObject seg0 = seg.createNestedObject();
|
JsonObject seg0 = seg.createNestedObject();
|
||||||
serializeSegment(seg0, sg, s, forPreset, segmentBounds);
|
serializeSegment(seg0, sg, s, forPreset, segmentBounds);
|
||||||
@ -518,18 +580,22 @@ void serializeInfo(JsonObject root)
|
|||||||
leds["fps"] = strip.getFps();
|
leds["fps"] = strip.getFps();
|
||||||
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
leds[F("maxpwr")] = (strip.currentMilliamps)? strip.ablMilliampsMax : 0;
|
||||||
leds[F("maxseg")] = strip.getMaxSegments();
|
leds[F("maxseg")] = strip.getMaxSegments();
|
||||||
|
//leds[F("actseg")] = strip.getActiveSegmentsNum();
|
||||||
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
//leds[F("seglock")] = false; //might be used in the future to prevent modifications to segment config
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
JsonObject matrix = leds.createNestedObject("matrix");
|
JsonObject matrix = leds.createNestedObject("matrix");
|
||||||
matrix["w"] = strip.matrixWidth;
|
matrix["w"] = strip.matrixWidth;
|
||||||
matrix["h"] = strip.matrixHeight;
|
matrix["h"] = strip.matrixHeight;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
uint8_t totalLC = 0;
|
uint8_t totalLC = 0;
|
||||||
JsonArray lcarr = leds.createNestedArray(F("seglc"));
|
JsonArray lcarr = leds.createNestedArray(F("seglc"));
|
||||||
uint8_t nSegs = strip.getLastActiveSegmentId();
|
size_t nSegs = strip.getSegmentsNum();
|
||||||
for (byte s = 0; s <= nSegs; s++) {
|
for (size_t s = 0; s < nSegs; s++) {
|
||||||
|
if (!strip.getSegment(s).isActive()) continue;
|
||||||
uint8_t lc = strip.getSegment(s).getLightCapabilities();
|
uint8_t lc = strip.getSegment(s).getLightCapabilities();
|
||||||
totalLC |= lc;
|
totalLC |= lc;
|
||||||
lcarr.add(lc);
|
lcarr.add(lc);
|
||||||
@ -577,7 +643,7 @@ void serializeInfo(JsonObject root)
|
|||||||
root[F("palcount")] = strip.getPaletteCount();
|
root[F("palcount")] = strip.getPaletteCount();
|
||||||
|
|
||||||
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
JsonArray ledmaps = root.createNestedArray(F("maps"));
|
||||||
for (uint8_t i=0; i<10; i++) {
|
for (size_t i=0; i<10; i++) {
|
||||||
char fileName[16];
|
char fileName[16];
|
||||||
strcpy_P(fileName, PSTR("/ledmap"));
|
strcpy_P(fileName, PSTR("/ledmap"));
|
||||||
if (i) sprintf(fileName +7, "%d", i);
|
if (i) sprintf(fileName +7, "%d", i);
|
||||||
@ -956,7 +1022,7 @@ bool serveLiveLeds(AsyncWebServerRequest* request, uint32_t wsClient)
|
|||||||
obuf = buffer;
|
obuf = buffer;
|
||||||
olen = 9;
|
olen = 9;
|
||||||
|
|
||||||
for (uint16_t i= 0; i < used; i += n)
|
for (size_t i= 0; i < used; i += n)
|
||||||
{
|
{
|
||||||
uint32_t c = strip.getPixelColor(i);
|
uint32_t c = strip.getPixelColor(i);
|
||||||
uint8_t r = qadd8(W(c), R(c)); //add white channel to RGB channels as a simple RGBW -> RGB map
|
uint8_t r = qadd8(W(c), R(c)); //add white channel to RGB channels as a simple RGBW -> RGB map
|
||||||
|
@ -8,7 +8,7 @@ void setValuesFromMainSeg() { setValuesFromSegment(strip.getMainSegment
|
|||||||
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
void setValuesFromFirstSelectedSeg() { setValuesFromSegment(strip.getFirstSelectedSegId()); }
|
||||||
void setValuesFromSegment(uint8_t s)
|
void setValuesFromSegment(uint8_t s)
|
||||||
{
|
{
|
||||||
WS2812FX::Segment& seg = strip.getSegment(s);
|
Segment& seg = strip.getSegment(s);
|
||||||
col[0] = R(seg.colors[0]);
|
col[0] = R(seg.colors[0]);
|
||||||
col[1] = G(seg.colors[0]);
|
col[1] = G(seg.colors[0]);
|
||||||
col[2] = B(seg.colors[0]);
|
col[2] = B(seg.colors[0]);
|
||||||
@ -30,9 +30,9 @@ void applyValuesToSelectedSegs()
|
|||||||
{
|
{
|
||||||
// copy of first selected segment to tell if value was updated
|
// copy of first selected segment to tell if value was updated
|
||||||
uint8_t firstSel = strip.getFirstSelectedSegId();
|
uint8_t firstSel = strip.getFirstSelectedSegId();
|
||||||
WS2812FX::Segment selsegPrev = strip.getSegment(firstSel);
|
Segment selsegPrev = strip.getSegment(firstSel);
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
if (i != firstSel && (!seg.isActive() || !seg.isSelected())) continue;
|
||||||
|
|
||||||
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
if (effectSpeed != selsegPrev.speed) {seg.speed = effectSpeed; stateChanged = true;}
|
||||||
@ -41,8 +41,8 @@ void applyValuesToSelectedSegs()
|
|||||||
if (effectCurrent != selsegPrev.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
|
if (effectCurrent != selsegPrev.mode) {strip.setMode(i, effectCurrent); stateChanged = true;}
|
||||||
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
uint32_t col0 = RGBW32( col[0], col[1], col[2], col[3]);
|
||||||
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
uint32_t col1 = RGBW32(colSec[0], colSec[1], colSec[2], colSec[3]);
|
||||||
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0, i); stateChanged = true;}
|
if (col0 != selsegPrev.colors[0]) {seg.setColor(0, col0); stateChanged = true;}
|
||||||
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1, i); stateChanged = true;}
|
if (col1 != selsegPrev.colors[1]) {seg.setColor(1, col1); stateChanged = true;}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ void parseLxJson(int lxValue, byte segId, bool secondary)
|
|||||||
} else {
|
} else {
|
||||||
DEBUG_PRINT(F("LX: segment "));
|
DEBUG_PRINT(F("LX: segment "));
|
||||||
DEBUG_PRINTLN(segId);
|
DEBUG_PRINTLN(segId);
|
||||||
strip.getSegment(segId).setColor(secondary, RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]), segId);
|
strip.getSegment(segId).setColor(secondary, RGBW32(rgbw[0], rgbw[1], rgbw[2], rgbw[3]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,6 @@
|
|||||||
#ifndef PalettesWLED_h
|
#ifndef PalettesWLED_h
|
||||||
#define PalettesWLED_h
|
#define PalettesWLED_h
|
||||||
|
|
||||||
#define GRADIENT_PALETTE_COUNT 58
|
|
||||||
|
|
||||||
const byte ib_jul01_gp[] PROGMEM = {
|
const byte ib_jul01_gp[] PROGMEM = {
|
||||||
0, 194, 1, 1,
|
0, 194, 1, 1,
|
||||||
94, 1, 29, 18,
|
94, 1, 29, 18,
|
||||||
|
@ -56,7 +56,8 @@ enum struct PinOwner : uint8_t {
|
|||||||
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
|
// #define USERMOD_ID_SN_PHOTORESISTOR // 0x11 // Usermod "usermod_sn_photoresistor.h" -- Uses hard-coded pin (PHOTORESISTOR_PIN == A0), but could be easily updated to use pinManager
|
||||||
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
UM_RGBRotaryEncoder = USERMOD_RGB_ROTARY_ENCODER, // 0x16 // Usermod "rgb-rotary-encoder.h"
|
||||||
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA, // 0x17 // Usermod "quinled-an-penta.h"
|
UM_QuinLEDAnPenta = USERMOD_ID_QUINLED_AN_PENTA, // 0x17 // Usermod "quinled-an-penta.h"
|
||||||
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE // 0x1E // Usermod: "audio_reactive.h"
|
UM_BME280 = USERMOD_ID_BME280, // 0x18 // Usermod "usermod_bme280.h -- Uses "standard" HW_I2C pins
|
||||||
|
UM_Audioreactive = USERMOD_ID_AUDIOREACTIVE // 0x1E // Usermod "audio_reactive.h"
|
||||||
};
|
};
|
||||||
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
static_assert(0u == static_cast<uint8_t>(PinOwner::None), "PinOwner::None must be zero, so default array initialization works as expected");
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ void handlePresets(bool force)
|
|||||||
presetToApply = 0; //clear request for preset
|
presetToApply = 0; //clear request for preset
|
||||||
callModeToApply = 0;
|
callModeToApply = 0;
|
||||||
|
|
||||||
DEBUG_PRINTLN(F("Applying preset: "));
|
DEBUG_PRINT(F("Applying preset: "));
|
||||||
DEBUG_PRINTLN(tmpPreset);
|
DEBUG_PRINTLN(tmpPreset);
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
@ -86,6 +86,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
Bus::setAutoWhiteMode(request->arg(F("AW")).toInt());
|
Bus::setAutoWhiteMode(request->arg(F("AW")).toInt());
|
||||||
strip.setTargetFps(request->arg(F("FR")).toInt());
|
strip.setTargetFps(request->arg(F("FR")).toInt());
|
||||||
|
|
||||||
|
bool busesChanged = false;
|
||||||
for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) {
|
for (uint8_t s = 0; s < WLED_MAX_BUSSES; s++) {
|
||||||
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
char lp[4] = "L0"; lp[2] = 48+s; lp[3] = 0; //ascii 0-9 //strip data pin
|
||||||
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
|
char lc[4] = "LC"; lc[2] = 48+s; lc[3] = 0; //strip length
|
||||||
@ -98,7 +99,9 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
|
char aw[4] = "AW"; aw[2] = 48+s; aw[3] = 0; //auto white mode
|
||||||
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //channel swap
|
char wo[4] = "WO"; wo[2] = 48+s; wo[3] = 0; //channel swap
|
||||||
if (!request->hasArg(lp)) {
|
if (!request->hasArg(lp)) {
|
||||||
DEBUG_PRINTLN(F("No data.")); break;
|
DEBUG_PRINT(F("No data for "));
|
||||||
|
DEBUG_PRINTLN(s);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
for (uint8_t i = 0; i < 5; i++) {
|
for (uint8_t i = 0; i < 5; i++) {
|
||||||
lp[1] = 48+i;
|
lp[1] = 48+i;
|
||||||
@ -118,10 +121,12 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
awmode = request->arg(aw).toInt();
|
awmode = request->arg(aw).toInt();
|
||||||
channelSwap = (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) ? request->arg(wo).toInt() : 0;
|
channelSwap = (type == TYPE_SK6812_RGBW || type == TYPE_TM1814) ? request->arg(wo).toInt() : 0;
|
||||||
// actual finalization is done in WLED::loop() (removing old busses and adding new)
|
// actual finalization is done in WLED::loop() (removing old busses and adding new)
|
||||||
|
// this may happen even before this loop is finished so we do "doInitBusses" after the loop
|
||||||
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
if (busConfigs[s] != nullptr) delete busConfigs[s];
|
||||||
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode);
|
busConfigs[s] = new BusConfig(type, pins, start, length, colorOrder | (channelSwap<<4), request->hasArg(cv), skip, awmode);
|
||||||
doInitBusses = true;
|
busesChanged = true;
|
||||||
}
|
}
|
||||||
|
//doInitBusses = busesChanged; // we will do that below to ensure all input data is processed
|
||||||
|
|
||||||
ColorOrderMap com = {};
|
ColorOrderMap com = {};
|
||||||
for (uint8_t s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) {
|
for (uint8_t s = 0; s < WLED_MAX_COLOR_ORDER_MAPPINGS; s++) {
|
||||||
@ -197,6 +202,8 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
if (t >= 0 && t < 4) strip.paletteBlend = t;
|
if (t >= 0 && t < 4) strip.paletteBlend = t;
|
||||||
t = request->arg(F("BF")).toInt();
|
t = request->arg(F("BF")).toInt();
|
||||||
if (t > 0) briMultiplier = t;
|
if (t > 0) briMultiplier = t;
|
||||||
|
|
||||||
|
doInitBusses = busesChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
//UI
|
//UI
|
||||||
@ -547,6 +554,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
releaseJSONBufferLock();
|
releaseJSONBufferLock();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
//2D panels
|
//2D panels
|
||||||
if (subPage == 10)
|
if (subPage == 10)
|
||||||
{
|
{
|
||||||
@ -570,6 +578,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
}
|
}
|
||||||
strip.setUpMatrix(); // will check limits
|
strip.setUpMatrix(); // will check limits
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
lastEditTime = millis();
|
lastEditTime = millis();
|
||||||
if (subPage != 2 && !doReboot) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
if (subPage != 2 && !doReboot) serializeConfig(); //do not save if factory reset or LED settings (which are saved after LED re-init)
|
||||||
@ -599,17 +608,17 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
pos = req.indexOf(F("SS="));
|
pos = req.indexOf(F("SS="));
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
byte t = getNumVal(&req, pos);
|
byte t = getNumVal(&req, pos);
|
||||||
if (t < strip.getMaxSegments()) {
|
if (t < strip.getSegmentsNum()) {
|
||||||
selectedSeg = t;
|
selectedSeg = t;
|
||||||
singleSegment = true;
|
singleSegment = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
WS2812FX::Segment& selseg = strip.getSegment(selectedSeg);
|
Segment& selseg = strip.getSegment(selectedSeg);
|
||||||
pos = req.indexOf(F("SV=")); //segment selected
|
pos = req.indexOf(F("SV=")); //segment selected
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
byte t = getNumVal(&req, pos);
|
byte t = getNumVal(&req, pos);
|
||||||
if (t == 2) for (uint8_t i = 0; i < strip.getMaxSegments(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
|
if (t == 2) for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) strip.getSegment(i).setOption(SEG_OPTION_SELECTED, 0); // unselect other segments
|
||||||
selseg.setOption(SEG_OPTION_SELECTED, t);
|
selseg.setOption(SEG_OPTION_SELECTED, t);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -657,9 +666,9 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
pos = req.indexOf(F("SB=")); //Segment brightness/opacity
|
pos = req.indexOf(F("SB=")); //Segment brightness/opacity
|
||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
byte segbri = getNumVal(&req, pos);
|
byte segbri = getNumVal(&req, pos);
|
||||||
selseg.setOption(SEG_OPTION_ON, segbri, selectedSeg);
|
selseg.setOption(SEG_OPTION_ON, segbri);
|
||||||
if (segbri) {
|
if (segbri) {
|
||||||
selseg.setOpacity(segbri, selectedSeg);
|
selseg.setOpacity(segbri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -762,7 +771,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
if (pos > 0) {
|
if (pos > 0) {
|
||||||
colorFromDecOrHexString(tmpCol, (char*)req.substring(pos + 3).c_str());
|
colorFromDecOrHexString(tmpCol, (char*)req.substring(pos + 3).c_str());
|
||||||
uint32_t col2 = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
|
uint32_t col2 = RGBW32(tmpCol[0], tmpCol[1], tmpCol[2], tmpCol[3]);
|
||||||
selseg.setColor(2, col2, selectedSeg); // defined above (SS= or main)
|
selseg.setColor(2, col2); // defined above (SS= or main)
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
if (!singleSegment) strip.setColor(2, col2); // will set color to all active & selected segments
|
if (!singleSegment) strip.setColor(2, col2); // will set color to all active & selected segments
|
||||||
}
|
}
|
||||||
@ -791,14 +800,14 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
if (col0Changed) {
|
if (col0Changed) {
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
uint32_t colIn0 = RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]);
|
uint32_t colIn0 = RGBW32(colIn[0], colIn[1], colIn[2], colIn[3]);
|
||||||
selseg.setColor(0, colIn0, selectedSeg);
|
selseg.setColor(0, colIn0);
|
||||||
if (!singleSegment) strip.setColor(0, colIn0); // will set color to all active & selected segments
|
if (!singleSegment) strip.setColor(0, colIn0); // will set color to all active & selected segments
|
||||||
}
|
}
|
||||||
|
|
||||||
if (col1Changed) {
|
if (col1Changed) {
|
||||||
stateChanged = true;
|
stateChanged = true;
|
||||||
uint32_t colIn1 = RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]);
|
uint32_t colIn1 = RGBW32(colInSec[0], colInSec[1], colInSec[2], colInSec[3]);
|
||||||
selseg.setColor(1, colIn1, selectedSeg);
|
selseg.setColor(1, colIn1);
|
||||||
if (!singleSegment) strip.setColor(1, colIn1); // will set color to all active & selected segments
|
if (!singleSegment) strip.setColor(1, colIn1); // will set color to all active & selected segments
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -815,8 +824,8 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
|
stateChanged |= (fxModeChanged || speedChanged || intensityChanged || paletteChanged);
|
||||||
|
|
||||||
// apply to main and all selected segments to prevent #1618.
|
// apply to main and all selected segments to prevent #1618.
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (uint8_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
if (i != selectedSeg && (singleSegment || !seg.isActive() || !seg.isSelected())) continue; // skip non main segments if not applying to all
|
||||||
if (fxModeChanged) strip.setMode(i, effectIn);
|
if (fxModeChanged) strip.setMode(i, effectIn);
|
||||||
if (speedChanged) seg.speed = speedIn;
|
if (speedChanged) seg.speed = speedIn;
|
||||||
@ -918,7 +927,7 @@ bool handleSet(AsyncWebServerRequest *request, const String& req, bool apply)
|
|||||||
realtimeOverride = getNumVal(&req, pos);
|
realtimeOverride = getNumVal(&req, pos);
|
||||||
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
if (realtimeOverride > 2) realtimeOverride = REALTIME_OVERRIDE_ALWAYS;
|
||||||
if (realtimeMode && useMainSegmentOnly) {
|
if (realtimeMode && useMainSegmentOnly) {
|
||||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride, strip.getMainSegmentId());
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, !realtimeOverride);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ void notify(byte callMode, bool followUp)
|
|||||||
default: return;
|
default: return;
|
||||||
}
|
}
|
||||||
byte udpOut[WLEDPACKETSIZE];
|
byte udpOut[WLEDPACKETSIZE];
|
||||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
Segment& mainseg = strip.getMainSegment();
|
||||||
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
|
udpOut[0] = 0; //0: wled notifier protocol 1: WARLS protocol
|
||||||
udpOut[1] = callMode;
|
udpOut[1] = callMode;
|
||||||
udpOut[2] = bri;
|
udpOut[2] = bri;
|
||||||
@ -89,12 +89,14 @@ void notify(byte callMode, bool followUp)
|
|||||||
udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant
|
udpOut[37] = strip.hasCCTBus() ? 0 : 255; //check this is 0 for the next value to be significant
|
||||||
udpOut[38] = mainseg.cct;
|
udpOut[38] = mainseg.cct;
|
||||||
|
|
||||||
udpOut[39] = strip.getMaxSegments();
|
udpOut[39] = strip.getActiveSegmentsNum();
|
||||||
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
|
udpOut[40] = UDP_SEG_SIZE; //size of each loop iteration (one segment)
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
size_t s = 0, nsegs = strip.getSegmentsNum();
|
||||||
WS2812FX::Segment &selseg = strip.getSegment(i);
|
for (size_t i = 0; i < nsegs; i++) {
|
||||||
uint16_t ofs = 41 + i*UDP_SEG_SIZE; //start of segment offset byte
|
Segment &selseg = strip.getSegment(i);
|
||||||
udpOut[0 +ofs] = i;
|
if (!selseg.isActive()) continue;
|
||||||
|
uint16_t ofs = 41 + s*UDP_SEG_SIZE; //start of segment offset byte
|
||||||
|
udpOut[0 +ofs] = s;
|
||||||
udpOut[1 +ofs] = selseg.start >> 8;
|
udpOut[1 +ofs] = selseg.start >> 8;
|
||||||
udpOut[2 +ofs] = selseg.start & 0xFF;
|
udpOut[2 +ofs] = selseg.start & 0xFF;
|
||||||
udpOut[3 +ofs] = selseg.stop >> 8;
|
udpOut[3 +ofs] = selseg.stop >> 8;
|
||||||
@ -122,6 +124,7 @@ void notify(byte callMode, bool followUp)
|
|||||||
udpOut[25+ofs] = B(selseg.colors[2]);
|
udpOut[25+ofs] = B(selseg.colors[2]);
|
||||||
udpOut[26+ofs] = W(selseg.colors[2]);
|
udpOut[26+ofs] = W(selseg.colors[2]);
|
||||||
udpOut[27+ofs] = selseg.cct;
|
udpOut[27+ofs] = selseg.cct;
|
||||||
|
++s;
|
||||||
}
|
}
|
||||||
|
|
||||||
//uint16_t offs = SEG_OFFSET;
|
//uint16_t offs = SEG_OFFSET;
|
||||||
@ -143,20 +146,20 @@ void realtimeLock(uint32_t timeoutMs, byte md)
|
|||||||
if (!realtimeMode && !realtimeOverride) {
|
if (!realtimeMode && !realtimeOverride) {
|
||||||
uint16_t stop, start;
|
uint16_t stop, start;
|
||||||
if (useMainSegmentOnly) {
|
if (useMainSegmentOnly) {
|
||||||
WS2812FX::Segment& mainseg = strip.getMainSegment();
|
Segment& mainseg = strip.getMainSegment();
|
||||||
start = mainseg.start;
|
start = mainseg.start;
|
||||||
stop = mainseg.stop;
|
stop = mainseg.stop;
|
||||||
mainseg.setOption(SEG_OPTION_FREEZE, true, strip.getMainSegmentId());
|
mainseg.setOption(SEG_OPTION_FREEZE, true);
|
||||||
} else {
|
} else {
|
||||||
start = 0;
|
start = 0;
|
||||||
stop = strip.getLengthTotal();
|
stop = strip.getLengthTotal();
|
||||||
}
|
}
|
||||||
// clear strip/segment
|
// clear strip/segment
|
||||||
for (uint16_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
|
for (size_t i = start; i < stop; i++) strip.setPixelColor(i,0,0,0,0);
|
||||||
// if WLED was off and using main segment only, freeze non-main segments so they stay off
|
// if WLED was off and using main segment only, freeze non-main segments so they stay off
|
||||||
if (useMainSegmentOnly && bri == 0) {
|
if (useMainSegmentOnly && bri == 0) {
|
||||||
for (uint8_t s=0; s < strip.getMaxSegments(); s++) {
|
for (size_t s=0; s < strip.getSegmentsNum(); s++) {
|
||||||
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true, s);
|
strip.getSegment(s).setOption(SEG_OPTION_FREEZE, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -183,7 +186,7 @@ void exitRealtime() {
|
|||||||
realtimeMode = REALTIME_MODE_INACTIVE; // inform UI immediately
|
realtimeMode = REALTIME_MODE_INACTIVE; // inform UI immediately
|
||||||
realtimeIP[0] = 0;
|
realtimeIP[0] = 0;
|
||||||
if (useMainSegmentOnly) { // unfreeze live segment again
|
if (useMainSegmentOnly) { // unfreeze live segment again
|
||||||
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, false, strip.getMainSegmentId());
|
strip.getMainSegment().setOption(SEG_OPTION_FREEZE, false);
|
||||||
}
|
}
|
||||||
updateInterfaces(CALL_MODE_WS_SEND);
|
updateInterfaces(CALL_MODE_WS_SEND);
|
||||||
}
|
}
|
||||||
@ -221,7 +224,7 @@ void handleNotifications()
|
|||||||
if (!udpConnected) return;
|
if (!udpConnected) return;
|
||||||
|
|
||||||
bool isSupp = false;
|
bool isSupp = false;
|
||||||
uint16_t packetSize = notifierUdp.parsePacket();
|
size_t packetSize = notifierUdp.parsePacket();
|
||||||
if (!packetSize && udp2Connected) {
|
if (!packetSize && udp2Connected) {
|
||||||
packetSize = notifier2Udp.parsePacket();
|
packetSize = notifier2Udp.parsePacket();
|
||||||
isSupp = true;
|
isSupp = true;
|
||||||
@ -241,7 +244,7 @@ void handleNotifications()
|
|||||||
if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
|
if (realtimeOverride && !(realtimeMode && useMainSegmentOnly)) return;
|
||||||
uint16_t id = 0;
|
uint16_t id = 0;
|
||||||
uint16_t totalLen = strip.getLengthTotal();
|
uint16_t totalLen = strip.getLengthTotal();
|
||||||
for (uint16_t i = 0; i < packetSize -2; i += 3)
|
for (size_t i = 0; i < packetSize -2; i += 3)
|
||||||
{
|
{
|
||||||
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
|
setRealtimePixel(id, lbuf[i], lbuf[i+1], lbuf[i+2], 0);
|
||||||
id++; if (id >= totalLen) break;
|
id++; if (id >= totalLen) break;
|
||||||
@ -275,7 +278,7 @@ void handleNotifications()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (it != Nodes.end()) {
|
if (it != Nodes.end()) {
|
||||||
for (byte x = 0; x < 4; x++) {
|
for (size_t x = 0; x < 4; x++) {
|
||||||
it->second.ip[x] = udpIn[x + 2];
|
it->second.ip[x] = udpIn[x + 2];
|
||||||
}
|
}
|
||||||
it->second.age = 0; // reset 'age counter'
|
it->second.age = 0; // reset 'age counter'
|
||||||
@ -287,7 +290,7 @@ void handleNotifications()
|
|||||||
it->second.nodeType = udpIn[38];
|
it->second.nodeType = udpIn[38];
|
||||||
uint32_t build = 0;
|
uint32_t build = 0;
|
||||||
if (len >= 44)
|
if (len >= 44)
|
||||||
for (byte i=0; i<sizeof(uint32_t); i++)
|
for (size_t i=0; i<sizeof(uint32_t); i++)
|
||||||
build |= udpIn[40+i]<<(8*i);
|
build |= udpIn[40+i]<<(8*i);
|
||||||
it->second.build = build;
|
it->second.build = build;
|
||||||
}
|
}
|
||||||
@ -339,11 +342,11 @@ void handleNotifications()
|
|||||||
if (applyEffects && currentPlaylist >= 0) unloadPlaylist();
|
if (applyEffects && currentPlaylist >= 0) unloadPlaylist();
|
||||||
if (version > 10 && (receiveSegmentOptions || receiveSegmentBounds)) {
|
if (version > 10 && (receiveSegmentOptions || receiveSegmentBounds)) {
|
||||||
uint8_t numSrcSegs = udpIn[39];
|
uint8_t numSrcSegs = udpIn[39];
|
||||||
for (uint8_t i = 0; i < numSrcSegs; i++) {
|
for (size_t i = 0; i < numSrcSegs; i++) {
|
||||||
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
|
uint16_t ofs = 41 + i*udpIn[40]; //start of segment offset byte
|
||||||
uint8_t id = udpIn[0 +ofs];
|
uint8_t id = udpIn[0 +ofs];
|
||||||
if (id > strip.getMaxSegments()) break;
|
if (id > strip.getSegmentsNum()) break;
|
||||||
WS2812FX::Segment& selseg = strip.getSegment(id);
|
Segment& selseg = strip.getSegment(id);
|
||||||
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
|
uint16_t start = (udpIn[1+ofs] << 8 | udpIn[2+ofs]);
|
||||||
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
|
uint16_t stop = (udpIn[3+ofs] << 8 | udpIn[4+ofs]);
|
||||||
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
|
uint16_t offset = (udpIn[7+ofs] << 8 | udpIn[8+ofs]);
|
||||||
@ -351,8 +354,8 @@ void handleNotifications()
|
|||||||
strip.setSegment(id, start, stop, selseg.grouping, selseg.spacing, offset);
|
strip.setSegment(id, start, stop, selseg.grouping, selseg.spacing, offset);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (uint8_t j = 0; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01, id); //only take into account mirrored, selected, on, reversed
|
for (size_t j = 0; j<4; j++) selseg.setOption(j, (udpIn[9 +ofs] >> j) & 0x01); //only take into account mirrored, selected, on, reversed
|
||||||
selseg.setOpacity(udpIn[10+ofs], id);
|
selseg.setOpacity(udpIn[10+ofs]);
|
||||||
if (applyEffects) {
|
if (applyEffects) {
|
||||||
strip.setMode(id, udpIn[11+ofs]);
|
strip.setMode(id, udpIn[11+ofs]);
|
||||||
selseg.speed = udpIn[12+ofs];
|
selseg.speed = udpIn[12+ofs];
|
||||||
@ -360,10 +363,10 @@ void handleNotifications()
|
|||||||
selseg.palette = udpIn[14+ofs];
|
selseg.palette = udpIn[14+ofs];
|
||||||
}
|
}
|
||||||
if (receiveNotificationColor || !someSel) {
|
if (receiveNotificationColor || !someSel) {
|
||||||
selseg.setColor(0, RGBW32(udpIn[15+ofs],udpIn[16+ofs],udpIn[17+ofs],udpIn[18+ofs]), id);
|
selseg.setColor(0, RGBW32(udpIn[15+ofs],udpIn[16+ofs],udpIn[17+ofs],udpIn[18+ofs]));
|
||||||
selseg.setColor(1, RGBW32(udpIn[19+ofs],udpIn[20+ofs],udpIn[21+ofs],udpIn[22+ofs]), id);
|
selseg.setColor(1, RGBW32(udpIn[19+ofs],udpIn[20+ofs],udpIn[21+ofs],udpIn[22+ofs]));
|
||||||
selseg.setColor(2, RGBW32(udpIn[23+ofs],udpIn[24+ofs],udpIn[25+ofs],udpIn[26+ofs]), id);
|
selseg.setColor(2, RGBW32(udpIn[23+ofs],udpIn[24+ofs],udpIn[25+ofs],udpIn[26+ofs]));
|
||||||
selseg.setCCT(udpIn[27+ofs], id);
|
selseg.setCCT(udpIn[27+ofs]);
|
||||||
}
|
}
|
||||||
//setSegment() also properly resets segments
|
//setSegment() also properly resets segments
|
||||||
if (receiveSegmentBounds) {
|
if (receiveSegmentBounds) {
|
||||||
@ -377,8 +380,8 @@ void handleNotifications()
|
|||||||
|
|
||||||
// simple effect sync, applies to all selected segments
|
// simple effect sync, applies to all selected segments
|
||||||
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
if (applyEffects && (version < 11 || !receiveSegmentOptions)) {
|
||||||
for (uint8_t i = 0; i < strip.getMaxSegments(); i++) {
|
for (size_t i = 0; i < strip.getSegmentsNum(); i++) {
|
||||||
WS2812FX::Segment& seg = strip.getSegment(i);
|
Segment& seg = strip.getSegment(i);
|
||||||
if (!seg.isActive() || !seg.isSelected()) continue;
|
if (!seg.isActive() || !seg.isSelected()) continue;
|
||||||
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
|
if (udpIn[8] < strip.getModeCount()) strip.setMode(i, udpIn[8]);
|
||||||
seg.speed = udpIn[9];
|
seg.speed = udpIn[9];
|
||||||
@ -458,7 +461,7 @@ void handleNotifications()
|
|||||||
|
|
||||||
uint16_t id = (tpmPayloadFrameSize/3)*(packetNum-1); //start LED
|
uint16_t id = (tpmPayloadFrameSize/3)*(packetNum-1); //start LED
|
||||||
uint16_t totalLen = strip.getLengthTotal();
|
uint16_t totalLen = strip.getLengthTotal();
|
||||||
for (uint16_t i = 6; i < tpmPayloadFrameSize + 4; i += 3)
|
for (size_t i = 6; i < tpmPayloadFrameSize + 4U; i += 3)
|
||||||
{
|
{
|
||||||
if (id < totalLen)
|
if (id < totalLen)
|
||||||
{
|
{
|
||||||
@ -494,14 +497,14 @@ void handleNotifications()
|
|||||||
uint16_t totalLen = strip.getLengthTotal();
|
uint16_t totalLen = strip.getLengthTotal();
|
||||||
if (udpIn[0] == 1) //warls
|
if (udpIn[0] == 1) //warls
|
||||||
{
|
{
|
||||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
for (size_t i = 2; i < packetSize -3; i += 4)
|
||||||
{
|
{
|
||||||
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
setRealtimePixel(udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3], 0);
|
||||||
}
|
}
|
||||||
} else if (udpIn[0] == 2) //drgb
|
} else if (udpIn[0] == 2) //drgb
|
||||||
{
|
{
|
||||||
uint16_t id = 0;
|
uint16_t id = 0;
|
||||||
for (uint16_t i = 2; i < packetSize -2; i += 3)
|
for (size_t i = 2; i < packetSize -2; i += 3)
|
||||||
{
|
{
|
||||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||||
|
|
||||||
@ -510,7 +513,7 @@ void handleNotifications()
|
|||||||
} else if (udpIn[0] == 3) //drgbw
|
} else if (udpIn[0] == 3) //drgbw
|
||||||
{
|
{
|
||||||
uint16_t id = 0;
|
uint16_t id = 0;
|
||||||
for (uint16_t i = 2; i < packetSize -3; i += 4)
|
for (size_t i = 2; i < packetSize -3; i += 4)
|
||||||
{
|
{
|
||||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||||
|
|
||||||
@ -519,7 +522,7 @@ void handleNotifications()
|
|||||||
} else if (udpIn[0] == 4) //dnrgb
|
} else if (udpIn[0] == 4) //dnrgb
|
||||||
{
|
{
|
||||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||||
for (uint16_t i = 4; i < packetSize -2; i += 3)
|
for (size_t i = 4; i < packetSize -2; i += 3)
|
||||||
{
|
{
|
||||||
if (id >= totalLen) break;
|
if (id >= totalLen) break;
|
||||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], 0);
|
||||||
@ -528,7 +531,7 @@ void handleNotifications()
|
|||||||
} else if (udpIn[0] == 5) //dnrgbw
|
} else if (udpIn[0] == 5) //dnrgbw
|
||||||
{
|
{
|
||||||
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
uint16_t id = ((udpIn[3] << 0) & 0xFF) + ((udpIn[2] << 8) & 0xFF00);
|
||||||
for (uint16_t i = 4; i < packetSize -2; i += 4)
|
for (size_t i = 4; i < packetSize -2; i += 4)
|
||||||
{
|
{
|
||||||
if (id >= totalLen) break;
|
if (id >= totalLen) break;
|
||||||
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
setRealtimePixel(id, udpIn[i], udpIn[i+1], udpIn[i+2], udpIn[i+3]);
|
||||||
@ -618,7 +621,7 @@ void sendSysInfoUDP()
|
|||||||
data[0] = 255;
|
data[0] = 255;
|
||||||
data[1] = 1;
|
data[1] = 1;
|
||||||
|
|
||||||
for (byte x = 0; x < 4; x++) {
|
for (size_t x = 0; x < 4; x++) {
|
||||||
data[x + 2] = ip[x];
|
data[x + 2] = ip[x];
|
||||||
}
|
}
|
||||||
memcpy((byte *)data + 6, serverDescription, 32);
|
memcpy((byte *)data + 6, serverDescription, 32);
|
||||||
@ -632,7 +635,7 @@ void sendSysInfoUDP()
|
|||||||
data[39] = ip[3]; // unit ID == last IP number
|
data[39] = ip[3]; // unit ID == last IP number
|
||||||
|
|
||||||
uint32_t build = VERSION;
|
uint32_t build = VERSION;
|
||||||
for (byte i=0; i<sizeof(uint32_t); i++)
|
for (size_t i=0; i<sizeof(uint32_t); i++)
|
||||||
data[40+i] = (build>>(8*i)) & 0xFF;
|
data[40+i] = (build>>(8*i)) & 0xFF;
|
||||||
|
|
||||||
IPAddress broadcastIP(255, 255, 255, 255);
|
IPAddress broadcastIP(255, 255, 255, 255);
|
||||||
@ -684,15 +687,15 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
|||||||
case 0: // DDP
|
case 0: // DDP
|
||||||
{
|
{
|
||||||
// calculate the number of UDP packets we need to send
|
// calculate the number of UDP packets we need to send
|
||||||
uint16_t channelCount = length * 3; // 1 channel for every R,G,B value
|
size_t channelCount = length * 3; // 1 channel for every R,G,B value
|
||||||
uint16_t packetCount = ((channelCount-1) / DDP_CHANNELS_PER_PACKET) +1;
|
size_t packetCount = ((channelCount-1) / DDP_CHANNELS_PER_PACKET) +1;
|
||||||
|
|
||||||
// there are 3 channels per RGB pixel
|
// there are 3 channels per RGB pixel
|
||||||
uint32_t channel = 0; // TODO: allow specifying the start channel
|
uint32_t channel = 0; // TODO: allow specifying the start channel
|
||||||
// the current position in the buffer
|
// the current position in the buffer
|
||||||
uint16_t bufferOffset = 0;
|
size_t bufferOffset = 0;
|
||||||
|
|
||||||
for (uint16_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
|
for (size_t currentPacket = 0; currentPacket < packetCount; currentPacket++) {
|
||||||
if (sequenceNumber > 15) sequenceNumber = 0;
|
if (sequenceNumber > 15) sequenceNumber = 0;
|
||||||
|
|
||||||
if (!ddpUdp.beginPacket(client, DDP_DEFAULT_PORT)) { // port defined in ESPAsyncE131.h
|
if (!ddpUdp.beginPacket(client, DDP_DEFAULT_PORT)) { // port defined in ESPAsyncE131.h
|
||||||
@ -701,10 +704,10 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
|||||||
}
|
}
|
||||||
|
|
||||||
// the amount of data is AFTER the header in the current packet
|
// the amount of data is AFTER the header in the current packet
|
||||||
uint16_t packetSize = DDP_CHANNELS_PER_PACKET;
|
size_t packetSize = DDP_CHANNELS_PER_PACKET;
|
||||||
|
|
||||||
uint8_t flags = DDP_FLAGS1_VER1;
|
uint8_t flags = DDP_FLAGS1_VER1;
|
||||||
if (currentPacket == (packetCount - 1)) {
|
if (currentPacket == (packetCount - 1U)) {
|
||||||
// last packet, set the push flag
|
// last packet, set the push flag
|
||||||
// TODO: determine if we want to send an empty push packet to each destination after sending the pixel data
|
// TODO: determine if we want to send an empty push packet to each destination after sending the pixel data
|
||||||
flags = DDP_FLAGS1_VER1 | DDP_FLAGS1_PUSH;
|
flags = DDP_FLAGS1_VER1 | DDP_FLAGS1_PUSH;
|
||||||
@ -729,7 +732,7 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, uint8
|
|||||||
|
|
||||||
// write the colors, the write write(const uint8_t *buffer, size_t size)
|
// write the colors, the write write(const uint8_t *buffer, size_t size)
|
||||||
// function is just a loop internally too
|
// function is just a loop internally too
|
||||||
for (uint16_t i = 0; i < packetSize; i += 3) {
|
for (size_t i = 0; i < packetSize; i += 3) {
|
||||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
|
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // R
|
||||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // G
|
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // G
|
||||||
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // B
|
ddpUdp.write(scale8(buffer[bufferOffset++], bri)); // B
|
||||||
|
@ -59,5 +59,3 @@ bool UsermodManager::add(Usermod* um)
|
|||||||
ums[numMods++] = um;
|
ums[numMods++] = um;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte UsermodManager::getModCount() {return numMods;}
|
|
250
wled00/util.cpp
250
wled00/util.cpp
@ -238,14 +238,13 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
char lineBuffer[256];
|
char lineBuffer[256];
|
||||||
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
//strcpy_P(lineBuffer, (const char*)pgm_read_dword(&(WS2812FX::_modeData[mode])));
|
||||||
strcpy_P(lineBuffer, strip.getModeData(mode));
|
strcpy_P(lineBuffer, strip.getModeData(mode));
|
||||||
if (strlen(lineBuffer) > 0) {
|
size_t len = strlen(lineBuffer);
|
||||||
size_t j = 0;
|
size_t j = 0;
|
||||||
for (; j < maxLen; j++) {
|
for (; j < maxLen && j < len; j++) {
|
||||||
if (lineBuffer[j] == '\0' || lineBuffer[j] == '@') break;
|
if (lineBuffer[j] == '\0' || lineBuffer[j] == '@') break;
|
||||||
dest[j] = lineBuffer[j];
|
dest[j] = lineBuffer[j];
|
||||||
}
|
|
||||||
dest[j] = 0; // terminate string
|
|
||||||
}
|
}
|
||||||
|
dest[j] = 0; // terminate string
|
||||||
return strlen(dest);
|
return strlen(dest);
|
||||||
} else return 0;
|
} else return 0;
|
||||||
}
|
}
|
||||||
@ -282,7 +281,7 @@ uint8_t extractModeName(uint8_t mode, const char *src, char *dest, uint8_t maxLe
|
|||||||
|
|
||||||
|
|
||||||
// extracts effect slider data (1st group after @)
|
// extracts effect slider data (1st group after @)
|
||||||
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen)
|
uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxLen, uint8_t *var)
|
||||||
{
|
{
|
||||||
dest[0] = '\0'; // start by clearing buffer
|
dest[0] = '\0'; // start by clearing buffer
|
||||||
|
|
||||||
@ -292,30 +291,50 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
|||||||
int16_t start = lineBuffer.indexOf('@');
|
int16_t start = lineBuffer.indexOf('@');
|
||||||
int16_t stop = lineBuffer.indexOf(';', start);
|
int16_t stop = lineBuffer.indexOf(';', start);
|
||||||
if (start>0 && stop>0) {
|
if (start>0 && stop>0) {
|
||||||
String names = lineBuffer.substring(start+1, stop);
|
String names = lineBuffer.substring(start, stop); // include @
|
||||||
int16_t nameBegin = 0, nameEnd;
|
int16_t nameBegin = 1, nameEnd, nameDefault;
|
||||||
for (size_t i=0; i<=slider; i++) {
|
if (slider < 10) {
|
||||||
const char *tmpstr;
|
for (size_t i=0; i<=slider; i++) {
|
||||||
dest[0] = '\0'; //clear dest buffer
|
const char *tmpstr;
|
||||||
if (i > 0 && nameBegin == 0) break; // there are no more names
|
dest[0] = '\0'; //clear dest buffer
|
||||||
nameEnd = names.indexOf(',', nameBegin);
|
if (nameBegin == 0) break; // there are no more names
|
||||||
if (names.charAt(nameBegin) == '!') {
|
nameEnd = names.indexOf(',', nameBegin);
|
||||||
switch (i) {
|
if (i == slider) {
|
||||||
case 0: tmpstr = PSTR("FX Speed"); break;
|
nameDefault = names.indexOf('=', nameBegin); // find default value
|
||||||
case 1: tmpstr = PSTR("FX Intensity"); break;
|
if (nameDefault > 0 && var && ((nameEnd>0 && nameDefault<nameEnd) || nameEnd<0)) {
|
||||||
case 2: tmpstr = PSTR("FX Custom 1"); break;
|
*var = (uint8_t)atoi(names.substring(nameDefault+1).c_str());
|
||||||
case 3: tmpstr = PSTR("FX Custom 2"); break;
|
}
|
||||||
case 4: tmpstr = PSTR("FX Custom 3"); break;
|
if (names.charAt(nameBegin) == '!') {
|
||||||
default: tmpstr = PSTR("FX Custom"); break;
|
switch (slider) {
|
||||||
|
case 0: tmpstr = PSTR("FX Speed"); break;
|
||||||
|
case 1: tmpstr = PSTR("FX Intensity"); break;
|
||||||
|
case 2: tmpstr = PSTR("FX Custom 1"); break;
|
||||||
|
case 3: tmpstr = PSTR("FX Custom 2"); break;
|
||||||
|
case 4: tmpstr = PSTR("FX Custom 3"); break;
|
||||||
|
default: tmpstr = PSTR("FX Custom"); break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name?
|
||||||
|
else tmpstr = names.substring(nameBegin, nameEnd).c_str();
|
||||||
|
}
|
||||||
|
strlcpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous)
|
||||||
|
}
|
||||||
|
nameBegin = nameEnd+1; // next name (if "," is not found it will be 0)
|
||||||
|
} // next slider
|
||||||
|
} else if (slider == 255) {
|
||||||
|
// palette
|
||||||
|
strlcpy(dest, "pal", maxLen);
|
||||||
|
names = lineBuffer.substring(stop+1); // stop has index of color slot names
|
||||||
|
nameBegin = names.indexOf(';'); // look for palette
|
||||||
|
if (nameBegin >= 0) {
|
||||||
|
nameEnd = names.indexOf(';', nameBegin+1);
|
||||||
|
if (!isdigit(names[nameBegin+1])) nameBegin = names.indexOf('=', nameBegin+1); // look for default value
|
||||||
|
if (nameEnd >= 0 && nameBegin > nameEnd) nameBegin = -1;
|
||||||
|
if (nameBegin >= 0 && var) {
|
||||||
|
*var = (uint8_t)atoi(names.substring(nameBegin+1).c_str());
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (nameEnd<0) tmpstr = names.substring(nameBegin).c_str(); // did not find ",", last name?
|
|
||||||
else tmpstr = names.substring(nameBegin, nameEnd).c_str();
|
|
||||||
}
|
}
|
||||||
strncpy(dest, tmpstr, maxLen); // copy the name into buffer (replacing previous)
|
}
|
||||||
nameBegin = nameEnd+1; // next name (if "," is not found it will be 0)
|
|
||||||
} // next slider
|
|
||||||
|
|
||||||
// we have slider name (including default value) in the dest buffer
|
// we have slider name (including default value) in the dest buffer
|
||||||
for (size_t i=0; i<strlen(dest); i++) if (dest[i]=='=') { dest[i]='\0'; break; } // truncate default value
|
for (size_t i=0; i<strlen(dest); i++) if (dest[i]=='=') { dest[i]='\0'; break; } // truncate default value
|
||||||
|
|
||||||
@ -325,6 +344,7 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
|||||||
case 0: strncpy_P(dest, PSTR("FX Speed"), maxLen); break;
|
case 0: strncpy_P(dest, PSTR("FX Speed"), maxLen); break;
|
||||||
case 1: strncpy_P(dest, PSTR("FX Intensity"), maxLen); break;
|
case 1: strncpy_P(dest, PSTR("FX Intensity"), maxLen); break;
|
||||||
}
|
}
|
||||||
|
dest[maxLen] = '\0'; // strncpy does not necessarily null terminate string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return strlen(dest);
|
return strlen(dest);
|
||||||
@ -333,6 +353,23 @@ uint8_t extractModeSlider(uint8_t mode, uint8_t slider, char *dest, uint8_t maxL
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int16_t extractModeDefaults(uint8_t mode, const char *segVar)
|
||||||
|
{
|
||||||
|
if (mode < strip.getModeCount()) {
|
||||||
|
String lineBuffer = strip.getModeData(mode);
|
||||||
|
if (lineBuffer.length() > 0) {
|
||||||
|
int16_t start = lineBuffer.lastIndexOf(';');
|
||||||
|
if (start<0) return -1;
|
||||||
|
|
||||||
|
int16_t stop = lineBuffer.indexOf(segVar, start+1);
|
||||||
|
if (stop<0) return -1;
|
||||||
|
return atoi(lineBuffer.substring(stop+strlen(segVar)+1).c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint16_t crc16(const unsigned char* data_p, size_t length) {
|
uint16_t crc16(const unsigned char* data_p, size_t length) {
|
||||||
uint8_t x;
|
uint8_t x;
|
||||||
uint16_t crc = 0xFFFF;
|
uint16_t crc = 0xFFFF;
|
||||||
@ -343,4 +380,155 @@ uint16_t crc16(const unsigned char* data_p, size_t length) {
|
|||||||
crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x <<5)) ^ ((uint16_t)x);
|
crc = (crc << 8) ^ ((uint16_t)(x << 12)) ^ ((uint16_t)(x <<5)) ^ ((uint16_t)x);
|
||||||
}
|
}
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Begin simulateSound (to enable audio enhanced effects to display something)
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Currently 4 types defined, to be fine tuned and new types added
|
||||||
|
typedef enum UM_SoundSimulations {
|
||||||
|
UMS_BeatSin = 0,
|
||||||
|
UMS_WeWillRockYou,
|
||||||
|
UMS_10_3,
|
||||||
|
UMS_14_3
|
||||||
|
} um_soundSimulations_t;
|
||||||
|
|
||||||
|
// this is still work in progress
|
||||||
|
um_data_t* simulateSound(uint8_t simulationId)
|
||||||
|
{
|
||||||
|
static float sampleAvg;
|
||||||
|
static uint8_t soundAgc;
|
||||||
|
static float sampleAgc;
|
||||||
|
static int16_t sampleRaw;
|
||||||
|
static int16_t rawSampleAgc;
|
||||||
|
static uint8_t samplePeak;
|
||||||
|
static float FFT_MajorPeak;
|
||||||
|
static float FFT_Magnitude;
|
||||||
|
static uint8_t maxVol;
|
||||||
|
static uint8_t binNum;
|
||||||
|
static float multAgc;
|
||||||
|
|
||||||
|
float sampleGain;
|
||||||
|
uint8_t soundSquelch;
|
||||||
|
uint8_t inputLevel;
|
||||||
|
|
||||||
|
//arrays
|
||||||
|
uint8_t *fftResult;
|
||||||
|
uint8_t *myVals;
|
||||||
|
float *fftBin;
|
||||||
|
|
||||||
|
static um_data_t* um_data = nullptr;
|
||||||
|
|
||||||
|
if (!um_data) {
|
||||||
|
//claim storage for arrays
|
||||||
|
fftResult = (uint8_t *)malloc(sizeof(uint8_t) * 16);
|
||||||
|
myVals = (uint8_t *)malloc(sizeof(uint8_t) * 32);
|
||||||
|
fftBin = (float *)malloc(sizeof(float) * 256); // not used (for debugging purposes)
|
||||||
|
|
||||||
|
// initialize um_data pointer structure
|
||||||
|
// NOTE!!!
|
||||||
|
// This may change as AudioReactive usermod may change
|
||||||
|
um_data = new um_data_t;
|
||||||
|
um_data->u_size = 18;
|
||||||
|
um_data->u_type = new um_types_t[um_data->u_size];
|
||||||
|
um_data->u_data = new void*[um_data->u_size];
|
||||||
|
um_data->u_data[ 0] = &sampleAvg;
|
||||||
|
um_data->u_data[ 1] = &soundAgc;
|
||||||
|
um_data->u_data[ 2] = &sampleAgc;
|
||||||
|
um_data->u_data[ 3] = &sampleRaw;
|
||||||
|
um_data->u_data[ 4] = &rawSampleAgc;
|
||||||
|
um_data->u_data[ 5] = &samplePeak;
|
||||||
|
um_data->u_data[ 6] = &FFT_MajorPeak;
|
||||||
|
um_data->u_data[ 7] = &FFT_Magnitude;
|
||||||
|
um_data->u_data[ 8] = fftResult;
|
||||||
|
um_data->u_data[ 9] = &maxVol;
|
||||||
|
um_data->u_data[10] = &binNum;
|
||||||
|
um_data->u_data[11] = &multAgc;
|
||||||
|
um_data->u_data[14] = myVals; //*used (only once, Pixels)
|
||||||
|
um_data->u_data[13] = &sampleGain;
|
||||||
|
um_data->u_data[15] = &soundSquelch;
|
||||||
|
um_data->u_data[16] = fftBin; //only used in binmap
|
||||||
|
um_data->u_data[17] = &inputLevel;
|
||||||
|
} else {
|
||||||
|
// get arrays from um_data
|
||||||
|
fftResult = (uint8_t*)um_data->u_data[8];
|
||||||
|
myVals = (uint8_t*)um_data->u_data[14];
|
||||||
|
fftBin = (float*)um_data->u_data[16];
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ms = millis();
|
||||||
|
|
||||||
|
switch (simulationId) {
|
||||||
|
default:
|
||||||
|
case UMS_BeatSin:
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = beatsin8(120 / (i+1), 0, 255);
|
||||||
|
// fftResult[i] = (beatsin8(120, 0, 255) + (256/16 * i)) % 256;
|
||||||
|
sampleAvg = fftResult[8];
|
||||||
|
break;
|
||||||
|
case UMS_WeWillRockYou:
|
||||||
|
if (ms%2000 < 200) {
|
||||||
|
sampleAvg = random8(255);
|
||||||
|
for (int i = 0; i<5; i++)
|
||||||
|
fftResult[i] = random8(255);
|
||||||
|
}
|
||||||
|
else if (ms%2000 < 400) {
|
||||||
|
sampleAvg = 0;
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = 0;
|
||||||
|
}
|
||||||
|
else if (ms%2000 < 600) {
|
||||||
|
sampleAvg = random8(255);
|
||||||
|
for (int i = 5; i<11; i++)
|
||||||
|
fftResult[i] = random8(255);
|
||||||
|
}
|
||||||
|
else if (ms%2000 < 800) {
|
||||||
|
sampleAvg = 0;
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = 0;
|
||||||
|
}
|
||||||
|
else if (ms%2000 < 1000) {
|
||||||
|
sampleAvg = random8(255);
|
||||||
|
for (int i = 11; i<16; i++)
|
||||||
|
fftResult[i] = random8(255);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sampleAvg = 0;
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case UMS_10_3:
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = inoise8(beatsin8(90 / (i+1), 0, 200)*15 + (ms>>10), ms>>3);
|
||||||
|
sampleAvg = fftResult[8];
|
||||||
|
break;
|
||||||
|
case UMS_14_3:
|
||||||
|
for (int i = 0; i<16; i++)
|
||||||
|
fftResult[i] = inoise8(beatsin8(120 / (i+1), 10, 30)*10 + (ms>>14), ms>>3);
|
||||||
|
sampleAvg = fftResult[8];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
//derive other vars from sampleAvg
|
||||||
|
|
||||||
|
//sampleAvg = mapf(sampleAvg, 0, 255, 0, 255); // help me out here
|
||||||
|
soundAgc = 0; //only avg in simulations
|
||||||
|
sampleAgc = sampleAvg;
|
||||||
|
sampleRaw = sampleAvg;
|
||||||
|
sampleRaw = map(sampleRaw, 50, 190, 0, 224);
|
||||||
|
rawSampleAgc = sampleAvg;
|
||||||
|
samplePeak = random8() > 250;
|
||||||
|
FFT_MajorPeak = sampleAvg;
|
||||||
|
FFT_Magnitude = sampleAvg;
|
||||||
|
multAgc = sampleAvg;
|
||||||
|
myVals[millis()%32] = sampleAvg; // filling values semi randomly (why?)
|
||||||
|
sampleGain = 40;
|
||||||
|
soundSquelch = 10;
|
||||||
|
maxVol = 10; // this gets feedback fro UI
|
||||||
|
binNum = 8; // this gets feedback fro UI
|
||||||
|
inputLevel = 128; // this gets feedback fro UI
|
||||||
|
|
||||||
|
return um_data;
|
||||||
|
}
|
||||||
|
@ -118,6 +118,7 @@ void WLED::loop()
|
|||||||
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
|
if (stripMillis > maxStripMillis) maxStripMillis = stripMillis;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
#ifdef ESP8266
|
#ifdef ESP8266
|
||||||
MDNS.update();
|
MDNS.update();
|
||||||
@ -692,6 +693,7 @@ void WLED::handleConnection()
|
|||||||
DEBUG_PRINT(F("Heap too low! "));
|
DEBUG_PRINT(F("Heap too low! "));
|
||||||
DEBUG_PRINTLN(heap);
|
DEBUG_PRINTLN(heap);
|
||||||
forceReconnect = true;
|
forceReconnect = true;
|
||||||
|
strip.purgeSegments(); // remove inactive segments from memory
|
||||||
}
|
}
|
||||||
lastHeap = heap;
|
lastHeap = heap;
|
||||||
heapTime = now;
|
heapTime = now;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2206281
|
#define VERSION 2207271
|
||||||
|
|
||||||
//uncomment this if you have a "my_config.h" file you'd like to use
|
//uncomment this if you have a "my_config.h" file you'd like to use
|
||||||
//#define WLED_USE_MY_CONFIG
|
//#define WLED_USE_MY_CONFIG
|
||||||
@ -152,19 +152,19 @@ using PSRAMDynamicJsonDocument = BasicJsonDocument<PSRAM_Allocator>;
|
|||||||
#define PSRAMDynamicJsonDocument DynamicJsonDocument
|
#define PSRAMDynamicJsonDocument DynamicJsonDocument
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "const.h"
|
||||||
#include "fcn_declare.h"
|
#include "fcn_declare.h"
|
||||||
#include "html_ui.h"
|
#include "html_ui.h"
|
||||||
#ifdef WLED_ENABLE_SIMPLE_UI
|
#ifdef WLED_ENABLE_SIMPLE_UI
|
||||||
#include "html_simple.h"
|
#include "html_simple.h"
|
||||||
#endif
|
#endif
|
||||||
#include "html_settings.h"
|
#include "html_settings.h"
|
||||||
#include "html_other.h"
|
#include "html_other.h"
|
||||||
#include "FX.h"
|
|
||||||
#include "ir_codes.h"
|
#include "ir_codes.h"
|
||||||
#include "const.h"
|
|
||||||
#include "NodeStruct.h"
|
#include "NodeStruct.h"
|
||||||
#include "pin_manager.h"
|
#include "pin_manager.h"
|
||||||
#include "bus_manager.h"
|
#include "bus_manager.h"
|
||||||
|
#include "FX.h"
|
||||||
|
|
||||||
#ifndef CLIENT_SSID
|
#ifndef CLIENT_SSID
|
||||||
#define CLIENT_SSID DEFAULT_CLIENT_SSID
|
#define CLIENT_SSID DEFAULT_CLIENT_SSID
|
||||||
|
@ -418,7 +418,7 @@ void deEEP() {
|
|||||||
segObj[F("ix")] = EEPROM.read(i+16);
|
segObj[F("ix")] = EEPROM.read(i+16);
|
||||||
segObj["pal"] = EEPROM.read(i+17);
|
segObj["pal"] = EEPROM.read(i+17);
|
||||||
} else {
|
} else {
|
||||||
WS2812FX::Segment* seg = strip.getSegments();
|
Segment* seg = strip.getSegments();
|
||||||
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
memcpy(seg, EEPROM.getDataPtr() +i+2, 240);
|
||||||
if (ver == 2) { //versions before 2004230 did not have opacity
|
if (ver == 2) { //versions before 2004230 did not have opacity
|
||||||
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
for (byte j = 0; j < strip.getMaxSegments(); j++)
|
||||||
|
@ -297,8 +297,8 @@ void initServer()
|
|||||||
DEBUG_PRINTLN(F("Update Success"));
|
DEBUG_PRINTLN(F("Update Success"));
|
||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("Update Failed"));
|
DEBUG_PRINTLN(F("Update Failed"));
|
||||||
WLED::instance().enableWatchdog();
|
|
||||||
usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
usermods.onUpdateBegin(false); // notify usermods that update has failed (some may require task init)
|
||||||
|
WLED::instance().enableWatchdog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -58,6 +58,10 @@ void wsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventTyp
|
|||||||
if (verboseResponse) {
|
if (verboseResponse) {
|
||||||
sendDataWs(client);
|
sendDataWs(client);
|
||||||
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||||
|
} else {
|
||||||
|
// we have to send something back otherwise WS connection closes
|
||||||
|
client->text(F("{\"success\":true}"));
|
||||||
|
lastInterfaceUpdate = millis() - (INTERFACE_UPDATE_COOLDOWN -500);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -96,8 +100,6 @@ void sendDataWs(AsyncWebSocketClient * client)
|
|||||||
if (!ws.count()) return;
|
if (!ws.count()) return;
|
||||||
AsyncWebSocketMessageBuffer * buffer;
|
AsyncWebSocketMessageBuffer * buffer;
|
||||||
|
|
||||||
while (strip.isUpdating()) yield();
|
|
||||||
|
|
||||||
if (!requestJSONBufferLock(12)) return;
|
if (!requestJSONBufferLock(12)) return;
|
||||||
|
|
||||||
JsonObject state = doc.createNestedObject("state");
|
JsonObject state = doc.createNestedObject("state");
|
||||||
|
@ -308,9 +308,15 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
|
|
||||||
// set limits
|
// set limits
|
||||||
oappend(SET_F("bLimits("));
|
oappend(SET_F("bLimits("));
|
||||||
|
#ifdef ESP32
|
||||||
|
// requested by @softhack007 https://github.com/blazoncek/WLED/issues/33
|
||||||
|
if (usermods.lookup(USERMOD_ID_AUDIOREACTIVE))
|
||||||
|
oappend(itoa(WLED_MAX_BUSSES-2,nS,10)); // prevent use of I2S buses if audio installed
|
||||||
|
else
|
||||||
|
#endif
|
||||||
oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
|
oappend(itoa(WLED_MAX_BUSSES,nS,10)); oappend(",");
|
||||||
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
|
oappend(itoa(MAX_LEDS_PER_BUS,nS,10)); oappend(",");
|
||||||
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
|
oappend(itoa(MAX_LED_MEMORY,nS,10)); oappend(",");
|
||||||
oappend(itoa(MAX_LEDS,nS,10));
|
oappend(itoa(MAX_LEDS,nS,10));
|
||||||
oappend(SET_F(");"));
|
oappend(SET_F(");"));
|
||||||
|
|
||||||
@ -636,6 +642,7 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
if (subPage == 10) // 2D matrices
|
if (subPage == 10) // 2D matrices
|
||||||
{
|
{
|
||||||
sappend('v',SET_F("SOMP"),strip.isMatrix);
|
sappend('v',SET_F("SOMP"),strip.isMatrix);
|
||||||
|
#ifndef WLED_DISABLE_2D
|
||||||
oappend(SET_F("resetPanels();"));
|
oappend(SET_F("resetPanels();"));
|
||||||
if (strip.isMatrix) {
|
if (strip.isMatrix) {
|
||||||
sappend('v',SET_F("PH"),strip.panelH);
|
sappend('v',SET_F("PH"),strip.panelH);
|
||||||
@ -660,5 +667,8 @@ void getSettingsJS(byte subPage, char* dest)
|
|||||||
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
|
pO[l] = 'S'; sappend('c',pO,strip.panel[i].serpentine);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
oappend(SET_F("gId(\"somp\").remove(1);")); // remove 2D option from dropdown
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user