Merge branch 'master' into esp32_multistrip
This commit is contained in:
commit
b7543c8a45
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,6 +1,22 @@
|
|||||||
## WLED changelog
|
## WLED changelog
|
||||||
|
|
||||||
### WLED version 0.11.0
|
### Development versions after 0.11.0 release
|
||||||
|
|
||||||
|
#### Build 2012101
|
||||||
|
|
||||||
|
- Fixed preset cycle default duration rounded down to nearest 10sec interval (#1458)
|
||||||
|
- Enabled E1.31/DDP/Art-Net in AP mode
|
||||||
|
|
||||||
|
#### Build 2012100
|
||||||
|
|
||||||
|
- Fixed multi-segment preset cycle
|
||||||
|
- Fixed EEPROM (pre-0.11 settings) not cleared on factory reset
|
||||||
|
- Fixed an issue with intermittent crashes on FX change (PR #1465)
|
||||||
|
- Added function to know if strip is updating (PR #1466)
|
||||||
|
- Fixed using colorwheel sliding the UI (PR #1459)
|
||||||
|
- Fixed analog clock settings not saving (PR #1448)
|
||||||
|
- Added Temperature palette (PR #1430)
|
||||||
|
- Added Candy cane FX (PR #1445)
|
||||||
|
|
||||||
#### Build 2012020
|
#### Build 2012020
|
||||||
|
|
||||||
@ -11,6 +27,8 @@
|
|||||||
|
|
||||||
- Fixed compilation for analog (PWM) LEDs
|
- Fixed compilation for analog (PWM) LEDs
|
||||||
|
|
||||||
|
### WLED version 0.11.0
|
||||||
|
|
||||||
#### Build 2011290
|
#### Build 2011290
|
||||||
|
|
||||||
- Release of WLED 0.11.0 "Mirai"
|
- Release of WLED 0.11.0 "Mirai"
|
||||||
|
5
images/Readme.md
Normal file
5
images/Readme.md
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
### Additional Logos
|
||||||
|
|
||||||
|
Additional awesome logos for WLED can be found here [Aircoookie/Akemi](https://github.com/Aircoookie/Akemi).
|
||||||
|
|
||||||
|
<img src="https://github.com/Aircoookie/Akemi/blob/master/akemi/001_cheerful.png">
|
@ -1,17 +1,32 @@
|
|||||||
# Fix unreachable net services V2
|
# Fix unreachable net services V2
|
||||||
|
|
||||||
|
**Attention: This usermod compiles only for ESP8266**
|
||||||
|
|
||||||
This usermod-v2 modification performs a ping request to the local IP address every 60 seconds. By this procedure the net services of WLED remains accessible in some problematic WLAN environments.
|
This usermod-v2 modification performs a ping request to the local IP address every 60 seconds. By this procedure the net services of WLED remains accessible in some problematic WLAN environments.
|
||||||
|
|
||||||
The modification works with static or DHCP IP address configuration.
|
The modification works with static or DHCP IP address configuration.
|
||||||
|
|
||||||
**Webinterface**: The number of pings and reconnects is displayed on the info page in the web interface.
|
|
||||||
|
|
||||||
_Story:_
|
_Story:_
|
||||||
|
|
||||||
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
||||||
|
|
||||||
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
||||||
|
|
||||||
|
## Webinterface
|
||||||
|
|
||||||
|
The number of pings and reconnects is displayed on the info page in the web interface.
|
||||||
|
The ping delay can be changed. Changes persist after a reboot.
|
||||||
|
|
||||||
|
## JSON API
|
||||||
|
|
||||||
|
The usermod supports the following state changes:
|
||||||
|
|
||||||
|
| JSON key | Value range | Description |
|
||||||
|
|-------------|------------------|---------------------------------|
|
||||||
|
| PingDelayMs | 5000 to 18000000 | Deactivdate/activate the sensor |
|
||||||
|
|
||||||
|
Changes also persist after a reboot.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
1. Copy the file `usermod_Fix_unreachable_netservices.h` to the `wled00` directory.
|
1. Copy the file `usermod_Fix_unreachable_netservices.h` to the `wled00` directory.
|
||||||
|
@ -1,6 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
#if defined(ESP32)
|
||||||
|
#warning "Usermod FixUnreachableNetServices works only with ESP8266 builds"
|
||||||
|
class FixUnreachableNetServices : public Usermod
|
||||||
|
{
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ESP8266)
|
||||||
#include <ping.h>
|
#include <ping.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -23,34 +31,37 @@
|
|||||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class FixUnreachableNetServices : public Usermod {
|
class FixUnreachableNetServices : public Usermod
|
||||||
|
{
|
||||||
private:
|
private:
|
||||||
//Private class members. You can declare variables and functions only accessible to your usermod here
|
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||||
unsigned long m_lastTime = 0;
|
unsigned long m_lastTime = 0;
|
||||||
|
|
||||||
// desclare required variables
|
// declare required variables
|
||||||
const unsigned int PingDelayMs = 60000;
|
unsigned long m_pingDelayMs = 60000;
|
||||||
unsigned long m_connectedWiFi = 0;
|
unsigned long m_connectedWiFi = 0;
|
||||||
ping_option m_pingOpt;
|
ping_option m_pingOpt;
|
||||||
unsigned int m_pingCount = 0;
|
unsigned int m_pingCount = 0;
|
||||||
|
bool m_updateConfig = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//Functions called by WLED
|
//Functions called by WLED
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||||
* You can use it to initialize variables, sensors or similar.
|
* You can use it to initialize variables, sensors or similar.
|
||||||
*/
|
*/
|
||||||
void setup() {
|
void setup()
|
||||||
|
{
|
||||||
//Serial.println("Hello from my usermod!");
|
//Serial.println("Hello from my usermod!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* connected() is called every time the WiFi is (re)connected
|
* connected() is called every time the WiFi is (re)connected
|
||||||
* Use it to initialize network interfaces
|
* Use it to initialize network interfaces
|
||||||
*/
|
*/
|
||||||
void connected() {
|
void connected()
|
||||||
|
{
|
||||||
//Serial.println("Connected to WiFi!");
|
//Serial.println("Connected to WiFi!");
|
||||||
|
|
||||||
++m_connectedWiFi;
|
++m_connectedWiFi;
|
||||||
@ -59,31 +70,27 @@ class FixUnreachableNetServices : public Usermod {
|
|||||||
memset(&m_pingOpt, 0, sizeof(struct ping_option));
|
memset(&m_pingOpt, 0, sizeof(struct ping_option));
|
||||||
m_pingOpt.count = 1;
|
m_pingOpt.count = 1;
|
||||||
m_pingOpt.ip = WiFi.localIP();
|
m_pingOpt.ip = WiFi.localIP();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
* loop
|
||||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
|
||||||
*
|
|
||||||
* Tips:
|
|
||||||
* 1. You can use "if (WLED_CONNECTED)" to check for a successful network connection.
|
|
||||||
* Additionally, "if (WLED_MQTT_CONNECTED)" is available to check for a connection to an MQTT broker.
|
|
||||||
*
|
|
||||||
* 2. Try to avoid using the delay() function. NEVER use delays longer than 10 milliseconds.
|
|
||||||
* Instead, use a timer check as shown here.
|
|
||||||
*/
|
*/
|
||||||
void loop() {
|
void loop()
|
||||||
if (m_connectedWiFi > 0 && millis()-m_lastTime > PingDelayMs)
|
{
|
||||||
|
if (m_connectedWiFi > 0 && millis() - m_lastTime > m_pingDelayMs)
|
||||||
{
|
{
|
||||||
ping_start(&m_pingOpt);
|
ping_start(&m_pingOpt);
|
||||||
m_lastTime = millis();
|
m_lastTime = millis();
|
||||||
++m_pingCount;
|
++m_pingCount;
|
||||||
}
|
}
|
||||||
|
if (m_updateConfig)
|
||||||
|
{
|
||||||
|
serializeConfig();
|
||||||
|
m_updateConfig = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||||
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
* Creating an "u" object allows you to add custom key/value pairs to the Info section of the WLED web UI.
|
||||||
* Below it is shown how this could be used for e.g. a light sensor
|
* Below it is shown how this could be used for e.g. a light sensor
|
||||||
@ -92,9 +99,15 @@ class FixUnreachableNetServices : public Usermod {
|
|||||||
{
|
{
|
||||||
//this code adds "u":{"⚡ Ping fix pings": m_pingCount} to the info object
|
//this code adds "u":{"⚡ Ping fix pings": m_pingCount} to the info object
|
||||||
JsonObject user = root["u"];
|
JsonObject user = root["u"];
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject("u");
|
||||||
|
|
||||||
JsonArray infoArr = user.createNestedArray("⚡ Ping fix pings"); //name
|
String uiDomString = "⚡ Ping fix pings<span style=\"display:block;padding-left:25px;\">\
|
||||||
|
Delay <input type=\"number\" min=\"5\" max=\"300\" value=\"";
|
||||||
|
uiDomString += (unsigned long)(m_pingDelayMs / 1000);
|
||||||
|
uiDomString += "\" onchange=\"requestJson({PingDelay:parseInt(this.value)});\">sec</span>";
|
||||||
|
|
||||||
|
JsonArray infoArr = user.createNestedArray(uiDomString); //name
|
||||||
infoArr.add(m_pingCount); //value
|
infoArr.add(m_pingCount); //value
|
||||||
|
|
||||||
//this code adds "u":{"⚡ Reconnects": m_connectedWiFi - 1} to the info object
|
//this code adds "u":{"⚡ Reconnects": m_connectedWiFi - 1} to the info object
|
||||||
@ -102,29 +115,48 @@ class FixUnreachableNetServices : public Usermod {
|
|||||||
infoArr.add(m_connectedWiFi - 1); //value
|
infoArr.add(m_connectedWiFi - 1); //value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* 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;
|
root["PingDelay"] = (m_pingDelayMs/1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
* readFromJsonState() can be used to receive data clients send 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 readFromJsonState(JsonObject &root)
|
void readFromJsonState(JsonObject &root)
|
||||||
{
|
{
|
||||||
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
if (root["PingDelay"] != nullptr)
|
||||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
{
|
||||||
|
m_pingDelayMs = (1000 * max(1UL, min(300UL, root["PingDelay"].as<unsigned long>())));
|
||||||
|
m_updateConfig = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* provide the changeable values
|
||||||
|
*/
|
||||||
|
void addToConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject("FixUnreachableNetServices");
|
||||||
|
top["PingDelayMs"] = m_pingDelayMs;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* restore the changeable values
|
||||||
|
*/
|
||||||
|
void readFromConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject top = root["FixUnreachableNetServices"];
|
||||||
|
m_pingDelayMs = top["PingDelayMs"] | m_pingDelayMs;
|
||||||
|
m_pingDelayMs = max(5000UL, min(18000000UL, m_pingDelayMs));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||||
*/
|
*/
|
||||||
@ -132,7 +164,5 @@ class FixUnreachableNetServices : public Usermod {
|
|||||||
{
|
{
|
||||||
return USERMOD_ID_FIXNETSERVICES;
|
return USERMOD_ID_FIXNETSERVICES;
|
||||||
}
|
}
|
||||||
|
|
||||||
//More methods can be added in the future, this example will then be extended.
|
|
||||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
# Fix unreachable Webserver
|
|
||||||
|
|
||||||
This modification performs a ping request to the local IP address every 60 seconds. By this procedure the web server remains accessible in some problematic WLAN environments.
|
|
||||||
|
|
||||||
The modification works with static or DHCP IP address configuration
|
|
||||||
|
|
||||||
_Story:_
|
|
||||||
|
|
||||||
Unfortunately, with all ESP projects where a web server or other network services are running, I have the problem that after some time the web server is no longer accessible. Now I found out that the connection is at least reestablished when a ping request is executed by the device.
|
|
||||||
|
|
||||||
With this modification, in the worst case, the network functions are not available for 60 seconds until the next ping request.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
|
|
||||||
Copy and replace the file `usermod.cpp` in wled00 directory.
|
|
||||||
|
|
||||||
|
|
@ -1,43 +0,0 @@
|
|||||||
#include "wled.h"
|
|
||||||
/*
|
|
||||||
* This file allows you to add own functionality to WLED more easily
|
|
||||||
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
|
|
||||||
* EEPROM bytes 2750+ are reserved for your custom use case. (if you extend #define EEPSIZE in const.h)
|
|
||||||
* bytes 2400+ are currently ununsed, but might be used for future wled features
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <ping.h>
|
|
||||||
|
|
||||||
const int PingDelayMs = 60000;
|
|
||||||
long lastCheckTime = 0;
|
|
||||||
bool connectedWiFi = false;
|
|
||||||
ping_option pingOpt;
|
|
||||||
|
|
||||||
//Use userVar0 and userVar1 (API calls &U0=,&U1=, uint16_t)
|
|
||||||
|
|
||||||
//gets called once at boot. Do all initialization that doesn't depend on network here
|
|
||||||
void userSetup()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//gets called every time WiFi is (re-)connected. Initialize own network interfaces here
|
|
||||||
void userConnected()
|
|
||||||
{
|
|
||||||
connectedWiFi = true;
|
|
||||||
// initialize ping_options structure
|
|
||||||
memset(&pingOpt, 0, sizeof(struct ping_option));
|
|
||||||
pingOpt.count = 1;
|
|
||||||
pingOpt.ip = WiFi.localIP();
|
|
||||||
}
|
|
||||||
|
|
||||||
//loop. You can use "if (WLED_CONNECTED)" to check for successful connection
|
|
||||||
void userLoop()
|
|
||||||
{
|
|
||||||
if (connectedWiFi && millis()-lastCheckTime > PingDelayMs)
|
|
||||||
{
|
|
||||||
ping_start(&pingOpt);
|
|
||||||
lastCheckTime = millis();
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,8 +11,8 @@ The LED strip is switched [using a relay](https://github.com/Aircoookie/WLED/wik
|
|||||||
|
|
||||||
The info page in the web interface shows the items below
|
The info page in the web interface shows the items below
|
||||||
|
|
||||||
- the state of the sensor. By clicking on the state the sensor can be deactivated/activated.
|
- the state of the sensor. By clicking on the state the sensor can be deactivated/activated. Changes persist after a reboot.
|
||||||
**I recommend to deactivate the sensor before installing an OTA update**.
|
**I recommend to deactivate the sensor before an OTA update and activate it again afterwards**.
|
||||||
- the remaining time of the off timer.
|
- the remaining time of the off timer.
|
||||||
|
|
||||||
## JSON API
|
## JSON API
|
||||||
@ -24,6 +24,8 @@ The usermod supports the following state changes:
|
|||||||
| PIRenabled | bool | Deactivdate/activate the sensor |
|
| PIRenabled | bool | Deactivdate/activate the sensor |
|
||||||
| PIRoffSec | 60 to 43200 | Off timer seconds |
|
| PIRoffSec | 60 to 43200 | Off timer seconds |
|
||||||
|
|
||||||
|
Changes also persist after a reboot.
|
||||||
|
|
||||||
## Sensor connection
|
## Sensor connection
|
||||||
|
|
||||||
My setup uses an HC-SR501 sensor, a HC-SR505 should also work.
|
My setup uses an HC-SR501 sensor, a HC-SR505 should also work.
|
||||||
@ -72,26 +74,36 @@ void registerUsermods()
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usermod installation (advanced mode)
|
## API to enable/disable the PIR sensor from outside. For example from another usermod.
|
||||||
|
|
||||||
In this mode IR sensor will disable PIR when light ON by remote controller and enable PIR when light OFF.
|
The class provides the static method `PIRsensorSwitch* PIRsensorSwitch::GetInstance()` to get a pointer to the usermod object.
|
||||||
|
|
||||||
1. Copy the file `usermod_PIR_sensor_switch.h` to the `wled00` directory.
|
To query or change the PIR sensor state the methods `bool PIRsensorEnabled()` and `void EnablePIRsensor(bool enable)` are available.
|
||||||
2. Register the usermod by adding `#include "usermod_PIR_sensor_switch.h"` in the top and `registerUsermod(new PIRsensorSwitch());` in the bottom of `usermods_list.cpp`.
|
|
||||||
3. Add to the line 237, on `wled.h` in the `wled00` directory:
|
|
||||||
|
|
||||||
`WLED_GLOBAL bool m_PIRenabled _INIT(true); // enable PIR sensor`
|
### There are two options to get access to the usermod instance:
|
||||||
|
|
||||||
4. On `ir.cpp` in the `wled00` directory, add to the IR controller's mapping (beyond line 200):
|
1. Include `usermod_PIR_sensor_switch.h` **before** you include the other usermod in `usermods_list.cpp'
|
||||||
|
|
||||||
- To the off button:
|
or
|
||||||
`m_PIRenabled = true;`
|
|
||||||
|
|
||||||
- To the on button:
|
2. Use `#include "usermod_PIR_sensor_switch.h"` at the top of the `usermod.h` where you need it.
|
||||||
`m_PIRenabled = false;`
|
|
||||||
|
|
||||||
5. Edit line 40, on `usermod_PIR_sensor_switch.h` in the `wled00` directory:
|
**Example usermod.h :**
|
||||||
|
```cpp
|
||||||
|
#include "wled.h"
|
||||||
|
|
||||||
`\\bool m_PIRenabled = true;`
|
#include "usermod_PIR_sensor_switch.h"
|
||||||
|
|
||||||
|
class MyUsermod : public Usermod {
|
||||||
|
//...
|
||||||
|
|
||||||
|
void togglePIRSensor() {
|
||||||
|
if (PIRsensorSwitch::GetInstance() != nullptr) {
|
||||||
|
PIRsensorSwitch::GetInstance()->EnablePIRsensor(!PIRsensorSwitch::GetInstance()->PIRsensorEnabled());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//...
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
Have fun - @gegu
|
Have fun - @gegu
|
||||||
|
@ -24,7 +24,40 @@
|
|||||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PIRsensorSwitch : public Usermod {
|
class PIRsensorSwitch : public Usermod
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
*/
|
||||||
|
PIRsensorSwitch()
|
||||||
|
{
|
||||||
|
// set static instance pointer
|
||||||
|
PIRsensorSwitchInstance(this);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* desctructor
|
||||||
|
*/
|
||||||
|
~PIRsensorSwitch()
|
||||||
|
{
|
||||||
|
PIRsensorSwitchInstance(nullptr, true);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return the instance pointer of the class
|
||||||
|
*/
|
||||||
|
static PIRsensorSwitch *GetInstance() { return PIRsensorSwitchInstance(); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable/Disable the PIR sensor
|
||||||
|
*/
|
||||||
|
void EnablePIRsensor(bool enable) { m_PIRenabled = enable; }
|
||||||
|
/**
|
||||||
|
* Get PIR sensor enabled/disabled state
|
||||||
|
*/
|
||||||
|
bool PIRsensorEnabled() { return m_PIRenabled; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// PIR sensor pin
|
// PIR sensor pin
|
||||||
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
||||||
@ -38,53 +71,59 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
byte m_PIRsensorPinState = LOW;
|
byte m_PIRsensorPinState = LOW;
|
||||||
// PIR sensor enabled - ISR attached
|
// PIR sensor enabled - ISR attached
|
||||||
bool m_PIRenabled = true;
|
bool m_PIRenabled = true;
|
||||||
|
// state if serializeConfig() should be called
|
||||||
|
bool m_updateConfig = false;
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* return or change if new PIR sensor state is available
|
* return or change if new PIR sensor state is available
|
||||||
*/
|
*/
|
||||||
static volatile bool newPIRsensorState(bool changeState = false, bool newState = false) {
|
static volatile bool newPIRsensorState(bool changeState = false, bool newState = false);
|
||||||
static volatile bool s_PIRsensorState = false;
|
|
||||||
if (changeState) {
|
|
||||||
s_PIRsensorState = newState;
|
|
||||||
}
|
|
||||||
return s_PIRsensorState;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* PIR sensor state has changed
|
* PIR sensor state has changed
|
||||||
*/
|
*/
|
||||||
static void IRAM_ATTR ISR_PIRstateChange() {
|
static void IRAM_ATTR ISR_PIRstateChange();
|
||||||
newPIRsensorState(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* Set/get instance pointer
|
||||||
|
*/
|
||||||
|
static PIRsensorSwitch *PIRsensorSwitchInstance(PIRsensorSwitch *pInstance = nullptr, bool bRemoveInstance = false);
|
||||||
|
|
||||||
|
/**
|
||||||
* switch strip on/off
|
* switch strip on/off
|
||||||
*/
|
*/
|
||||||
void switchStrip(bool switchOn) {
|
void switchStrip(bool switchOn)
|
||||||
if (switchOn && bri == 0) {
|
{
|
||||||
|
if (switchOn && bri == 0)
|
||||||
|
{
|
||||||
bri = briLast;
|
bri = briLast;
|
||||||
colorUpdated(NotifyUpdateMode);
|
colorUpdated(NotifyUpdateMode);
|
||||||
}
|
}
|
||||||
else if (!switchOn && bri != 0) {
|
else if (!switchOn && bri != 0)
|
||||||
|
{
|
||||||
briLast = bri;
|
briLast = bri;
|
||||||
bri = 0;
|
bri = 0;
|
||||||
colorUpdated(NotifyUpdateMode);
|
colorUpdated(NotifyUpdateMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Read and update PIR sensor state.
|
* Read and update PIR sensor state.
|
||||||
* Initilize/reset switch off timer
|
* Initilize/reset switch off timer
|
||||||
*/
|
*/
|
||||||
bool updatePIRsensorState() {
|
bool updatePIRsensorState()
|
||||||
if (newPIRsensorState()) {
|
{
|
||||||
|
if (newPIRsensorState())
|
||||||
|
{
|
||||||
m_PIRsensorPinState = digitalRead(PIRsensorPin);
|
m_PIRsensorPinState = digitalRead(PIRsensorPin);
|
||||||
|
|
||||||
if (m_PIRsensorPinState == HIGH) {
|
if (m_PIRsensorPinState == HIGH)
|
||||||
|
{
|
||||||
m_offTimerStart = 0;
|
m_offTimerStart = 0;
|
||||||
switchStrip(true);
|
switchStrip(true);
|
||||||
}
|
}
|
||||||
else if (bri != 0) {
|
else if (bri != 0)
|
||||||
|
{
|
||||||
// start switch off timer
|
// start switch off timer
|
||||||
m_offTimerStart = millis();
|
m_offTimerStart = millis();
|
||||||
}
|
}
|
||||||
@ -94,12 +133,15 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* switch off the strip if the delay has elapsed
|
* switch off the strip if the delay has elapsed
|
||||||
*/
|
*/
|
||||||
bool handleOffTimer() {
|
bool handleOffTimer()
|
||||||
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay) {
|
{
|
||||||
if (m_PIRenabled == true){
|
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay)
|
||||||
|
{
|
||||||
|
if (m_PIRenabled == true)
|
||||||
|
{
|
||||||
switchStrip(false);
|
switchStrip(false);
|
||||||
}
|
}
|
||||||
m_offTimerStart = 0;
|
m_offTimerStart = 0;
|
||||||
@ -111,37 +153,46 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
public:
|
public:
|
||||||
//Functions called by WLED
|
//Functions called by WLED
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||||
* You can use it to initialize variables, sensors or similar.
|
* You can use it to initialize variables, sensors or similar.
|
||||||
*/
|
*/
|
||||||
void setup() {
|
void setup()
|
||||||
|
{
|
||||||
// PIR Sensor mode INPUT_PULLUP
|
// PIR Sensor mode INPUT_PULLUP
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||||
|
if (m_PIRenabled)
|
||||||
|
{
|
||||||
// assign interrupt function and set CHANGE mode
|
// assign interrupt function and set CHANGE mode
|
||||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* connected() is called every time the WiFi is (re)connected
|
* connected() is called every time the WiFi is (re)connected
|
||||||
* Use it to initialize network interfaces
|
* Use it to initialize network interfaces
|
||||||
*/
|
*/
|
||||||
void connected() {
|
void connected()
|
||||||
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||||
*/
|
*/
|
||||||
void loop() {
|
void loop()
|
||||||
if (!updatePIRsensorState()) {
|
{
|
||||||
|
if (!updatePIRsensorState())
|
||||||
|
{
|
||||||
handleOffTimer();
|
handleOffTimer();
|
||||||
|
if (m_updateConfig)
|
||||||
|
{
|
||||||
|
serializeConfig();
|
||||||
|
m_updateConfig = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
* addToJsonInfo() can be used to add custom entries to the /json/info part of the JSON API.
|
||||||
*
|
*
|
||||||
* Add PIR sensor state and switch off timer duration to jsoninfo
|
* Add PIR sensor state and switch off timer duration to jsoninfo
|
||||||
@ -151,17 +202,21 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
//this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
|
//this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
|
||||||
// the value contains a button to toggle the sensor enabled/disabled
|
// the value contains a button to toggle the sensor enabled/disabled
|
||||||
JsonObject user = root["u"];
|
JsonObject user = root["u"];
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject("u");
|
||||||
|
|
||||||
JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
|
JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
|
||||||
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
||||||
String sensorStateInfo;
|
String sensorStateInfo;
|
||||||
|
|
||||||
// PIR sensor state
|
// PIR sensor state
|
||||||
if (m_PIRenabled) {
|
if (m_PIRenabled)
|
||||||
|
{
|
||||||
uiDomString += "false";
|
uiDomString += "false";
|
||||||
sensorStateInfo = (m_PIRsensorPinState != LOW ? "active" : "inactive"); //value
|
sensorStateInfo = (m_PIRsensorPinState != LOW ? "active" : "inactive"); //value
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
uiDomString += "true";
|
uiDomString += "true";
|
||||||
sensorStateInfo = "Disabled !";
|
sensorStateInfo = "Disabled !";
|
||||||
}
|
}
|
||||||
@ -171,35 +226,46 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
infoArr.add(uiDomString); //value
|
infoArr.add(uiDomString); //value
|
||||||
|
|
||||||
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
||||||
infoArr = user.createNestedArray("⏲ switch off timer"); //name
|
uiDomString = "⏲ switch off timer<span style=\"display:block;padding-left:25px;\">\
|
||||||
|
after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
||||||
|
uiDomString += (m_switchOffDelay / 60000);
|
||||||
|
uiDomString += "\" onchange=\"requestJson({PIRoffSec:parseInt(this.value)*60});\">min</span>";
|
||||||
|
infoArr = user.createNestedArray(uiDomString); //name
|
||||||
|
|
||||||
// off timer
|
// off timer
|
||||||
if (m_offTimerStart > 0) {
|
if (m_offTimerStart > 0)
|
||||||
|
{
|
||||||
uiDomString = "";
|
uiDomString = "";
|
||||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
||||||
if (offSeconds >= 3600) {
|
if (offSeconds >= 3600)
|
||||||
|
{
|
||||||
uiDomString += (offSeconds / 3600);
|
uiDomString += (offSeconds / 3600);
|
||||||
uiDomString += " hours ";
|
uiDomString += " hours ";
|
||||||
offSeconds %= 3600;
|
offSeconds %= 3600;
|
||||||
}
|
}
|
||||||
if (offSeconds >= 60) {
|
if (offSeconds >= 60)
|
||||||
|
{
|
||||||
uiDomString += (offSeconds / 60);
|
uiDomString += (offSeconds / 60);
|
||||||
offSeconds %= 60;
|
offSeconds %= 60;
|
||||||
} else if (uiDomString.length() > 0){
|
}
|
||||||
|
else if (uiDomString.length() > 0)
|
||||||
|
{
|
||||||
uiDomString += 0;
|
uiDomString += 0;
|
||||||
}
|
}
|
||||||
if (uiDomString.length() > 0){
|
if (uiDomString.length() > 0)
|
||||||
|
{
|
||||||
uiDomString += " min ";
|
uiDomString += " min ";
|
||||||
}
|
}
|
||||||
uiDomString += (offSeconds);
|
uiDomString += (offSeconds);
|
||||||
infoArr.add(uiDomString + " sec");
|
infoArr.add(uiDomString + " sec");
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
infoArr.add("inactive");
|
infoArr.add("inactive");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* 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
|
||||||
* Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
|
* Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
|
||||||
@ -211,8 +277,7 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
root["PIRoffSec"] = (m_switchOffDelay / 1000);
|
root["PIRoffSec"] = (m_switchOffDelay / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
/*
|
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
* readFromJsonState() can be used to receive data clients send 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
|
||||||
* Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
|
* Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
|
||||||
@ -220,24 +285,49 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
*/
|
*/
|
||||||
void readFromJsonState(JsonObject &root)
|
void readFromJsonState(JsonObject &root)
|
||||||
{
|
{
|
||||||
if (root["PIRoffSec"] != nullptr) {
|
if (root["PIRoffSec"] != nullptr)
|
||||||
|
{
|
||||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
||||||
|
m_updateConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (root["PIRenabled"] != nullptr) {
|
if (root["PIRenabled"] != nullptr)
|
||||||
if (root["PIRenabled"] && !m_PIRenabled) {
|
{
|
||||||
|
if (root["PIRenabled"] && !m_PIRenabled)
|
||||||
|
{
|
||||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||||
newPIRsensorState(true, true);
|
newPIRsensorState(true, true);
|
||||||
}
|
}
|
||||||
else if(m_PIRenabled) {
|
else if (m_PIRenabled)
|
||||||
|
{
|
||||||
detachInterrupt(PIRsensorPin);
|
detachInterrupt(PIRsensorPin);
|
||||||
}
|
}
|
||||||
m_PIRenabled = root["PIRenabled"];
|
m_PIRenabled = root["PIRenabled"];
|
||||||
|
m_updateConfig = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* provide the changeable values
|
||||||
|
*/
|
||||||
|
void addToConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject top = root.createNestedObject("PIRsensorSwitch");
|
||||||
|
top["PIRenabled"] = m_PIRenabled;
|
||||||
|
top["PIRoffSec"] = m_switchOffDelay;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
|
* restore the changeable values
|
||||||
|
*/
|
||||||
|
void readFromConfig(JsonObject &root)
|
||||||
|
{
|
||||||
|
JsonObject top = root["PIRsensorSwitch"];
|
||||||
|
m_PIRenabled = (top["PIRenabled"] != nullptr ? top["PIRenabled"] : true);
|
||||||
|
m_switchOffDelay = top["PIRoffSec"] | m_switchOffDelay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||||
*/
|
*/
|
||||||
@ -245,7 +335,32 @@ class PIRsensorSwitch : public Usermod {
|
|||||||
{
|
{
|
||||||
return USERMOD_ID_PIRSWITCH;
|
return USERMOD_ID_PIRSWITCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
//More methods can be added in the future, this example will then be extended.
|
|
||||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// PIRsensorSwitch static method implementations
|
||||||
|
|
||||||
|
volatile bool PIRsensorSwitch::newPIRsensorState(bool changeState, bool newState)
|
||||||
|
{
|
||||||
|
static volatile bool s_PIRsensorState = false;
|
||||||
|
if (changeState)
|
||||||
|
{
|
||||||
|
s_PIRsensorState = newState;
|
||||||
|
}
|
||||||
|
return s_PIRsensorState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR PIRsensorSwitch::ISR_PIRstateChange()
|
||||||
|
{
|
||||||
|
newPIRsensorState(true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
PIRsensorSwitch *PIRsensorSwitch::PIRsensorSwitchInstance(PIRsensorSwitch *pInstance, bool bRemoveInstance)
|
||||||
|
{
|
||||||
|
static PIRsensorSwitch *s_pPIRsensorSwitch = nullptr;
|
||||||
|
if (pInstance != nullptr || bRemoveInstance)
|
||||||
|
{
|
||||||
|
s_pPIRsensorSwitch = pInstance;
|
||||||
|
}
|
||||||
|
return s_pPIRsensorSwitch;
|
||||||
|
}
|
||||||
|
28
wled00/FX.h
28
wled00/FX.h
@ -317,9 +317,31 @@ class WS2812FX {
|
|||||||
WS2812FX::_usedSegmentData -= _dataLen;
|
WS2812FX::_usedSegmentData -= _dataLen;
|
||||||
_dataLen = 0;
|
_dataLen = 0;
|
||||||
}
|
}
|
||||||
void reset(){next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0; deallocateData();}
|
|
||||||
|
/**
|
||||||
|
* If reset of this segment was request, clears runtime
|
||||||
|
* settings of this segment.
|
||||||
|
* Must not be called while an effect mode function is running
|
||||||
|
* because it could access the data buffer and this method
|
||||||
|
* may free that data buffer.
|
||||||
|
*/
|
||||||
|
void resetIfRequired() {
|
||||||
|
if (_requiresReset) {
|
||||||
|
next_time = 0; step = 0; call = 0; aux0 = 0; aux1 = 0;
|
||||||
|
deallocateData();
|
||||||
|
_requiresReset = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Flags that before the next effect is calculated,
|
||||||
|
* the internal segment state should be reset.
|
||||||
|
* Call resetIfRequired before calling the next effect function.
|
||||||
|
*/
|
||||||
|
void reset() { _requiresReset = true; }
|
||||||
private:
|
private:
|
||||||
uint16_t _dataLen = 0;
|
uint16_t _dataLen = 0;
|
||||||
|
bool _requiresReset = false;
|
||||||
} segment_runtime;
|
} segment_runtime;
|
||||||
|
|
||||||
WS2812FX() {
|
WS2812FX() {
|
||||||
@ -480,7 +502,9 @@ class WS2812FX {
|
|||||||
gammaCorrectCol = true,
|
gammaCorrectCol = true,
|
||||||
applyToAllSelected = true,
|
applyToAllSelected = true,
|
||||||
segmentsAreIdentical(Segment* a, Segment* b),
|
segmentsAreIdentical(Segment* a, Segment* b),
|
||||||
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p);
|
setEffectConfig(uint8_t m, uint8_t s, uint8_t i, uint8_t p),
|
||||||
|
// return true if the strip is being sent pixel updates
|
||||||
|
isUpdating(void);
|
||||||
|
|
||||||
uint8_t
|
uint8_t
|
||||||
mainSegment = 0,
|
mainSegment = 0,
|
||||||
|
@ -76,6 +76,11 @@ void WS2812FX::service() {
|
|||||||
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
for(uint8_t i=0; i < MAX_NUM_SEGMENTS; i++)
|
||||||
{
|
{
|
||||||
_segment_index = i;
|
_segment_index = i;
|
||||||
|
|
||||||
|
// reset the segment runtime data if needed, called before isActive to ensure deleted
|
||||||
|
// segment's buffers are cleared
|
||||||
|
SEGENV.resetIfRequired();
|
||||||
|
|
||||||
if (SEGMENT.isActive())
|
if (SEGMENT.isActive())
|
||||||
{
|
{
|
||||||
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
if(nowUp > SEGENV.next_time || _triggered || (doShow && SEGMENT.mode == 0)) //last is temporary
|
||||||
@ -218,7 +223,10 @@ void WS2812FX::setPixelColor(uint16_t i, byte r, byte g, byte b, byte w)
|
|||||||
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
//you can set it to 0 if the ESP is powered by USB and the LEDs by external
|
||||||
|
|
||||||
void WS2812FX::show(void) {
|
void WS2812FX::show(void) {
|
||||||
if (_callback) _callback();
|
|
||||||
|
// avoid race condition, caputre _callback value
|
||||||
|
show_callback callback = _callback;
|
||||||
|
if (callback) callback();
|
||||||
|
|
||||||
//power limit calculation
|
//power limit calculation
|
||||||
//each LED can draw up 195075 "power units" (approx. 53mA)
|
//each LED can draw up 195075 "power units" (approx. 53mA)
|
||||||
@ -291,10 +299,24 @@ void WS2812FX::show(void) {
|
|||||||
bus->SetBrightness(_brightness);
|
bus->SetBrightness(_brightness);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// some buses send asynchronously and this method will return before
|
||||||
|
// all of the data has been sent.
|
||||||
|
// See https://github.com/Makuna/NeoPixelBus/wiki/ESP32-NeoMethods#neoesp32rmt-methods
|
||||||
bus->Show();
|
bus->Show();
|
||||||
_lastShow = millis();
|
_lastShow = millis();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a true value if any of the strips are still being updated.
|
||||||
|
* On some hardware (ESP32), strip updates are done asynchronously.
|
||||||
|
*/
|
||||||
|
bool WS2812FX::isUpdating() {
|
||||||
|
return !bus->CanShow();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Forces the next frame to be computed on all active segments.
|
||||||
|
*/
|
||||||
void WS2812FX::trigger() {
|
void WS2812FX::trigger() {
|
||||||
_triggered = true;
|
_triggered = true;
|
||||||
}
|
}
|
||||||
|
@ -296,7 +296,6 @@ public:
|
|||||||
|
|
||||||
void Show()
|
void Show()
|
||||||
{
|
{
|
||||||
byte b;
|
|
||||||
switch (_type)
|
switch (_type)
|
||||||
{
|
{
|
||||||
case NeoPixelType_Grb: _pGrb->Show(); break;
|
case NeoPixelType_Grb: _pGrb->Show(); break;
|
||||||
@ -304,6 +303,22 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This will return true if enough time has passed since the last time Show() was called.
|
||||||
|
* This also means that calling Show() will not cause any undue waiting. If the method for
|
||||||
|
* the defined bus is hardware that sends asynchronously, then call CanShow() will let
|
||||||
|
* you know if it has finished sending the data from the last Show().
|
||||||
|
*/
|
||||||
|
bool CanShow()
|
||||||
|
{
|
||||||
|
switch (_type)
|
||||||
|
{
|
||||||
|
case NeoPixelType_Grb: return _pGrb->CanShow();
|
||||||
|
case NeoPixelType_Grbw: return _pGrbw->CanShow();
|
||||||
|
default: return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetPixelColor(uint16_t indexPixel, RgbwColor c)
|
void SetPixelColor(uint16_t indexPixel, RgbwColor c)
|
||||||
{
|
{
|
||||||
RgbwColor col;
|
RgbwColor col;
|
||||||
|
@ -162,7 +162,7 @@ void deserializeConfig() {
|
|||||||
CJSON(presetCycleMax, def_cy[F("range")][1]);
|
CJSON(presetCycleMax, def_cy[F("range")][1]);
|
||||||
|
|
||||||
tdd = def_cy[F("dur")] | -1;
|
tdd = def_cy[F("dur")] | -1;
|
||||||
if (tdd >= 0) presetCycleTime = tdd * 100;
|
if (tdd > 0) presetCycleTime = tdd;
|
||||||
|
|
||||||
JsonObject interfaces = doc["if"];
|
JsonObject interfaces = doc["if"];
|
||||||
|
|
||||||
@ -251,7 +251,11 @@ void deserializeConfig() {
|
|||||||
CJSON(countdownMode, ol[F("cntdwn")]);
|
CJSON(countdownMode, ol[F("cntdwn")]);
|
||||||
overlayCurrent = overlayDefault;
|
overlayCurrent = overlayDefault;
|
||||||
|
|
||||||
JsonArray ol_cntdwn = ol[F("cntdwn")]; //[20,12,31,23,59,59]
|
CJSON(overlayMin, ol[F("min")]);
|
||||||
|
CJSON(overlayMax, ol[F("max")]);
|
||||||
|
CJSON(analogClock12pixel, ol[F("o12pix")]);
|
||||||
|
CJSON(analogClock5MinuteMarks, ol[F("o5m")]);
|
||||||
|
CJSON(analogClockSecondsTrail, ol[F("osec")]);
|
||||||
|
|
||||||
//timed macro rules
|
//timed macro rules
|
||||||
JsonObject tm = doc[F("timers")];
|
JsonObject tm = doc[F("timers")];
|
||||||
@ -478,7 +482,7 @@ void serializeConfig() {
|
|||||||
JsonArray def_cy_range = def_cy.createNestedArray("range");
|
JsonArray def_cy_range = def_cy.createNestedArray("range");
|
||||||
def_cy_range.add(presetCycleMin);
|
def_cy_range.add(presetCycleMin);
|
||||||
def_cy_range.add(presetCycleMax);
|
def_cy_range.add(presetCycleMax);
|
||||||
def_cy[F("dur")] = presetCycleTime / 100;
|
def_cy[F("dur")] = presetCycleTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject interfaces = doc.createNestedObject("if");
|
JsonObject interfaces = doc.createNestedObject("if");
|
||||||
@ -562,6 +566,12 @@ void serializeConfig() {
|
|||||||
ol[F("clock")] = overlayDefault;
|
ol[F("clock")] = overlayDefault;
|
||||||
ol[F("cntdwn")] = countdownMode;
|
ol[F("cntdwn")] = countdownMode;
|
||||||
|
|
||||||
|
ol[F("min")] = overlayMin;
|
||||||
|
ol[F("max")] = overlayMax;
|
||||||
|
ol[F("o12pix")] = analogClock12pixel;
|
||||||
|
ol[F("o5m")] = analogClock5MinuteMarks;
|
||||||
|
ol[F("osec")] = analogClockSecondsTrail;
|
||||||
|
|
||||||
JsonObject timers = doc.createNestedObject("timers");
|
JsonObject timers = doc.createNestedObject("timers");
|
||||||
|
|
||||||
JsonObject cntdwn = timers.createNestedObject("cntdwn");
|
JsonObject cntdwn = timers.createNestedObject("cntdwn");
|
||||||
|
@ -2443,10 +2443,23 @@ let iSlide = 0, x0 = null, scrollS = 0, locked = false, w;
|
|||||||
|
|
||||||
function unify(e) { return e.changedTouches ? e.changedTouches[0] : e }
|
function unify(e) { return e.changedTouches ? e.changedTouches[0] : e }
|
||||||
|
|
||||||
|
function hasIroClass(classList) {
|
||||||
|
for (var i = 0; i < classList.length; i++) {
|
||||||
|
var element = classList[i];
|
||||||
|
if (element.startsWith('Iro')) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function lock(e) {
|
function lock(e) {
|
||||||
if (pcMode) return;
|
if (pcMode) return;
|
||||||
var l = e.target.classList;
|
var l = e.target.classList;
|
||||||
if (l.contains('noslide') || l.contains('iro__wheel__saturation') || l.contains('iro__slider__value') || l.contains('iro__slider')) return;
|
var pl = e.target.parentElement.classList;
|
||||||
|
|
||||||
|
if (l.contains('noslide') || hasIroClass(l) || hasIroClass(pl)) return;
|
||||||
|
|
||||||
x0 = unify(e).clientX;
|
x0 = unify(e).clientX;
|
||||||
scrollS = d.getElementsByClassName("tabcontent")[iSlide].scrollTop;
|
scrollS = d.getElementsByClassName("tabcontent")[iSlide].scrollTop;
|
||||||
|
|
||||||
|
@ -235,6 +235,7 @@ void userLoop();
|
|||||||
void applyMacro(byte index);
|
void applyMacro(byte index);
|
||||||
void deEEP();
|
void deEEP();
|
||||||
void deEEPSettings();
|
void deEEPSettings();
|
||||||
|
void clearEEPROM();
|
||||||
|
|
||||||
//wled_serial.cpp
|
//wled_serial.cpp
|
||||||
void handleSerial();
|
void handleSerial();
|
||||||
|
2839
wled00/html_ui.h
2839
wled00/html_ui.h
File diff suppressed because it is too large
Load Diff
@ -107,7 +107,7 @@ void colorUpdated(int callMode)
|
|||||||
notify(callMode);
|
notify(callMode);
|
||||||
|
|
||||||
//set flag to update blynk and mqtt
|
//set flag to update blynk and mqtt
|
||||||
if (callMode != NOTIFIER_CALL_MODE_PRESET_CYCLE) interfaceUpdateCallMode = callMode;
|
interfaceUpdateCallMode = callMode;
|
||||||
} else {
|
} else {
|
||||||
if (nightlightActive && !nightlightActiveOld &&
|
if (nightlightActive && !nightlightActiveOld &&
|
||||||
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
|
callMode != NOTIFIER_CALL_MODE_NOTIFICATION &&
|
||||||
@ -303,10 +303,10 @@ void handleNightlight()
|
|||||||
if (bri == 0 || nightlightActive) return;
|
if (bri == 0 || nightlightActive) return;
|
||||||
|
|
||||||
if (presetCycCurr < presetCycleMin || presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
|
if (presetCycCurr < presetCycleMin || presetCycCurr > presetCycleMax) presetCycCurr = presetCycleMin;
|
||||||
applyPreset(presetCycCurr);
|
applyPreset(presetCycCurr); //this handles colorUpdated() for us
|
||||||
presetCycCurr++;
|
presetCycCurr++;
|
||||||
if (presetCycCurr > 250) presetCycCurr = 1;
|
if (presetCycCurr > 250) presetCycCurr = 1;
|
||||||
colorUpdated(NOTIFIER_CALL_MODE_PRESET_CYCLE);
|
interfaceUpdateCallMode = 0; //disable updates to MQTT and Blynk
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,6 +266,7 @@ void handleSettingsSet(AsyncWebServerRequest *request, byte subPage)
|
|||||||
if (request->hasArg(F("RS"))) //complete factory reset
|
if (request->hasArg(F("RS"))) //complete factory reset
|
||||||
{
|
{
|
||||||
WLED_FS.format();
|
WLED_FS.format();
|
||||||
|
clearEEPROM();
|
||||||
serveMessage(request, 200, F("All Settings erased."), F("Connect to WLED-AP to setup again"),255);
|
serveMessage(request, 200, F("All Settings erased."), F("Connect to WLED-AP to setup again"),255);
|
||||||
doReboot = true;
|
doReboot = true;
|
||||||
}
|
}
|
||||||
|
@ -377,6 +377,7 @@ void WLED::initAP(bool resetAP)
|
|||||||
if (udpPort2 > 0 && udpPort2 != ntpLocalPort && udpPort2 != udpPort && udpPort2 != udpRgbPort) {
|
if (udpPort2 > 0 && udpPort2 != ntpLocalPort && udpPort2 != udpPort && udpPort2 != udpRgbPort) {
|
||||||
udp2Connected = notifier2Udp.begin(udpPort2);
|
udp2Connected = notifier2Udp.begin(udpPort2);
|
||||||
}
|
}
|
||||||
|
e131.begin(false, e131Port, e131Universe, E131_MAX_UNIVERSE_COUNT);
|
||||||
|
|
||||||
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
|
||||||
dnsServer.start(53, "*", WiFi.softAPIP());
|
dnsServer.start(53, "*", WiFi.softAPIP());
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2012020
|
#define VERSION 2012101
|
||||||
|
|
||||||
//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
|
||||||
|
@ -36,6 +36,20 @@
|
|||||||
//21-> 0.10.1p
|
//21-> 0.10.1p
|
||||||
//22-> 2009260
|
//22-> 2009260
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Erase all (pre 0.11) configuration data on factory reset
|
||||||
|
*/
|
||||||
|
void clearEEPROM()
|
||||||
|
{
|
||||||
|
EEPROM.begin(EEPSIZE);
|
||||||
|
for (int i = 0; i < EEPSIZE; i++)
|
||||||
|
{
|
||||||
|
EEPROM.write(i, 0);
|
||||||
|
}
|
||||||
|
EEPROM.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
|
void readStringFromEEPROM(uint16_t pos, char* str, uint16_t len)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < len; ++i)
|
for (int i = 0; i < len; ++i)
|
||||||
|
Loading…
Reference in New Issue
Block a user