Merge branch 'master' of https://github.com/Aircoookie/WLED
This commit is contained in:
commit
aefd81228e
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,116 +31,138 @@
|
|||||||
* 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 class members. You can declare variables and functions only accessible to your usermod here
|
private:
|
||||||
unsigned long m_lastTime = 0;
|
//Private class members. You can declare variables and functions only accessible to your usermod here
|
||||||
|
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
|
||||||
|
* Use it to initialize network interfaces
|
||||||
|
*/
|
||||||
|
void connected()
|
||||||
|
{
|
||||||
|
//Serial.println("Connected to WiFi!");
|
||||||
|
|
||||||
/*
|
++m_connectedWiFi;
|
||||||
* connected() is called every time the WiFi is (re)connected
|
|
||||||
* Use it to initialize network interfaces
|
|
||||||
*/
|
|
||||||
void connected() {
|
|
||||||
//Serial.println("Connected to WiFi!");
|
|
||||||
|
|
||||||
++m_connectedWiFi;
|
// initialize ping_options structure
|
||||||
|
memset(&m_pingOpt, 0, sizeof(struct ping_option));
|
||||||
// initialize ping_options structure
|
m_pingOpt.count = 1;
|
||||||
memset(&m_pingOpt, 0, sizeof(struct ping_option));
|
m_pingOpt.ip = WiFi.localIP();
|
||||||
m_pingOpt.count = 1;
|
}
|
||||||
m_pingOpt.ip = WiFi.localIP();
|
|
||||||
|
|
||||||
}
|
/**
|
||||||
|
* loop
|
||||||
|
*/
|
||||||
/*
|
void loop()
|
||||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
{
|
||||||
*
|
if (m_connectedWiFi > 0 && millis() - m_lastTime > m_pingDelayMs)
|
||||||
* 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() {
|
|
||||||
if (m_connectedWiFi > 0 && millis()-m_lastTime > PingDelayMs)
|
|
||||||
{
|
|
||||||
ping_start(&m_pingOpt);
|
|
||||||
m_lastTime = millis();
|
|
||||||
++m_pingCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
* Below it is shown how this could be used for e.g. a light sensor
|
|
||||||
*/
|
|
||||||
void addToJsonInfo(JsonObject& root)
|
|
||||||
{
|
{
|
||||||
//this code adds "u":{"⚡ Ping fix pings": m_pingCount} to the info object
|
ping_start(&m_pingOpt);
|
||||||
JsonObject user = root["u"];
|
m_lastTime = millis();
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
++m_pingCount;
|
||||||
|
|
||||||
JsonArray infoArr = user.createNestedArray("⚡ Ping fix pings"); //name
|
|
||||||
infoArr.add(m_pingCount); //value
|
|
||||||
|
|
||||||
//this code adds "u":{"⚡ Reconnects": m_connectedWiFi - 1} to the info object
|
|
||||||
infoArr = user.createNestedArray("⚡ Reconnects"); //name
|
|
||||||
infoArr.add(m_connectedWiFi - 1); //value
|
|
||||||
}
|
}
|
||||||
|
if (m_updateConfig)
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
void addToJsonState(JsonObject& root)
|
|
||||||
{
|
{
|
||||||
//root["user0"] = userVar0;
|
serializeConfig();
|
||||||
|
m_updateConfig = false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
* Below it is shown how this could be used for e.g. a light sensor
|
||||||
|
*/
|
||||||
|
void addToJsonInfo(JsonObject &root)
|
||||||
|
{
|
||||||
|
//this code adds "u":{"⚡ Ping fix pings": m_pingCount} to the info object
|
||||||
|
JsonObject user = root["u"];
|
||||||
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject("u");
|
||||||
|
|
||||||
/*
|
String uiDomString = "⚡ Ping fix pings<span style=\"display:block;padding-left:25px;\">\
|
||||||
* readFromJsonState() can be used to receive data clients send to the /json/state part of the JSON API (state object).
|
Delay <input type=\"number\" min=\"5\" max=\"300\" value=\"";
|
||||||
* Values in the state object may be modified by connected clients
|
uiDomString += (unsigned long)(m_pingDelayMs / 1000);
|
||||||
*/
|
uiDomString += "\" onchange=\"requestJson({PingDelay:parseInt(this.value)});\">sec</span>";
|
||||||
void readFromJsonState(JsonObject& root)
|
|
||||||
|
JsonArray infoArr = user.createNestedArray(uiDomString); //name
|
||||||
|
infoArr.add(m_pingCount); //value
|
||||||
|
|
||||||
|
//this code adds "u":{"⚡ Reconnects": m_connectedWiFi - 1} to the info object
|
||||||
|
infoArr = user.createNestedArray("⚡ Reconnects"); //name
|
||||||
|
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).
|
||||||
|
* Values in the state object may be modified by connected clients
|
||||||
|
*/
|
||||||
|
void addToJsonState(JsonObject &root)
|
||||||
|
{
|
||||||
|
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).
|
||||||
|
* Values in the state object may be modified by connected clients
|
||||||
|
*/
|
||||||
|
void readFromJsonState(JsonObject &root)
|
||||||
|
{
|
||||||
|
if (root["PingDelay"] != nullptr)
|
||||||
{
|
{
|
||||||
//userVar0 = root["user0"] | userVar0; //if "user0" key exists in JSON, update, else keep old value
|
m_pingDelayMs = (1000 * max(1UL, min(300UL, root["PingDelay"].as<unsigned long>())));
|
||||||
//if (root["bri"] == 255) Serial.println(F("Don't burn down your garage!"));
|
m_updateConfig = true;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
uint16_t getId()
|
|
||||||
{
|
|
||||||
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!
|
* 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!).
|
||||||
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||||
|
*/
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_FIXNETSERVICES;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
#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,19 +11,21 @@ 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
|
||||||
|
|
||||||
The usermod supports the following state changes:
|
The usermod supports the following state changes:
|
||||||
|
|
||||||
| JSON key | Value range | Description |
|
| JSON key | Value range | Description |
|
||||||
|------------|-------------|---------------------------------|
|
|------------|-------------|---------------------------------|
|
||||||
| 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.
|
||||||
@ -55,7 +57,7 @@ Example **usermods_list.cpp**:
|
|||||||
//#include "usermod_v2_example.h"
|
//#include "usermod_v2_example.h"
|
||||||
//#include "usermod_temperature.h"
|
//#include "usermod_temperature.h"
|
||||||
//#include "usermod_v2_empty.h"
|
//#include "usermod_v2_empty.h"
|
||||||
#include "usermod_PIR_sensor_switch.h"
|
#include "usermod_PIR_sensor_switch.h"
|
||||||
|
|
||||||
void registerUsermods()
|
void registerUsermods()
|
||||||
{
|
{
|
||||||
@ -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;`
|
|
||||||
|
2. Use `#include "usermod_PIR_sensor_switch.h"` at the top of the `usermod.h` where you need it.
|
||||||
- To the on button:
|
|
||||||
`m_PIRenabled = false;`
|
**Example usermod.h :**
|
||||||
|
```cpp
|
||||||
5. Edit line 40, on `usermod_PIR_sensor_switch.h` in the `wled00` directory:
|
#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,228 +24,343 @@
|
|||||||
* 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
|
||||||
private:
|
{
|
||||||
// PIR sensor pin
|
public:
|
||||||
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
/**
|
||||||
// notification mode for colorUpdated()
|
* constructor
|
||||||
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
*/
|
||||||
// delay before switch off after the sensor state goes LOW
|
PIRsensorSwitch()
|
||||||
uint32_t m_switchOffDelay = 600000;
|
{
|
||||||
// off timer start time
|
// set static instance pointer
|
||||||
uint32_t m_offTimerStart = 0;
|
PIRsensorSwitchInstance(this);
|
||||||
// current PIR sensor pin state
|
}
|
||||||
byte m_PIRsensorPinState = LOW;
|
/**
|
||||||
// PIR sensor enabled - ISR attached
|
* desctructor
|
||||||
bool m_PIRenabled = true;
|
*/
|
||||||
|
~PIRsensorSwitch()
|
||||||
|
{
|
||||||
|
PIRsensorSwitchInstance(nullptr, true);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* return or change if new PIR sensor state is available
|
* return the instance pointer of the class
|
||||||
*/
|
*/
|
||||||
static volatile bool newPIRsensorState(bool changeState = false, bool newState = false) {
|
static PIRsensorSwitch *GetInstance() { return PIRsensorSwitchInstance(); }
|
||||||
static volatile bool s_PIRsensorState = false;
|
|
||||||
if (changeState) {
|
/**
|
||||||
s_PIRsensorState = newState;
|
* Enable/Disable the PIR sensor
|
||||||
|
*/
|
||||||
|
void EnablePIRsensor(bool enable) { m_PIRenabled = enable; }
|
||||||
|
/**
|
||||||
|
* Get PIR sensor enabled/disabled state
|
||||||
|
*/
|
||||||
|
bool PIRsensorEnabled() { return m_PIRenabled; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
// PIR sensor pin
|
||||||
|
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
||||||
|
// notification mode for colorUpdated()
|
||||||
|
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
||||||
|
// delay before switch off after the sensor state goes LOW
|
||||||
|
uint32_t m_switchOffDelay = 600000;
|
||||||
|
// off timer start time
|
||||||
|
uint32_t m_offTimerStart = 0;
|
||||||
|
// current PIR sensor pin state
|
||||||
|
byte m_PIRsensorPinState = LOW;
|
||||||
|
// PIR sensor enabled - ISR attached
|
||||||
|
bool m_PIRenabled = true;
|
||||||
|
// state if serializeConfig() should be called
|
||||||
|
bool m_updateConfig = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return or change if new PIR sensor state is available
|
||||||
|
*/
|
||||||
|
static volatile bool newPIRsensorState(bool changeState = false, bool newState = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* PIR sensor state has changed
|
||||||
|
*/
|
||||||
|
static void IRAM_ATTR ISR_PIRstateChange();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set/get instance pointer
|
||||||
|
*/
|
||||||
|
static PIRsensorSwitch *PIRsensorSwitchInstance(PIRsensorSwitch *pInstance = nullptr, bool bRemoveInstance = false);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* switch strip on/off
|
||||||
|
*/
|
||||||
|
void switchStrip(bool switchOn)
|
||||||
|
{
|
||||||
|
if (switchOn && bri == 0)
|
||||||
|
{
|
||||||
|
bri = briLast;
|
||||||
|
colorUpdated(NotifyUpdateMode);
|
||||||
|
}
|
||||||
|
else if (!switchOn && bri != 0)
|
||||||
|
{
|
||||||
|
briLast = bri;
|
||||||
|
bri = 0;
|
||||||
|
colorUpdated(NotifyUpdateMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read and update PIR sensor state.
|
||||||
|
* Initilize/reset switch off timer
|
||||||
|
*/
|
||||||
|
bool updatePIRsensorState()
|
||||||
|
{
|
||||||
|
if (newPIRsensorState())
|
||||||
|
{
|
||||||
|
m_PIRsensorPinState = digitalRead(PIRsensorPin);
|
||||||
|
|
||||||
|
if (m_PIRsensorPinState == HIGH)
|
||||||
|
{
|
||||||
|
m_offTimerStart = 0;
|
||||||
|
switchStrip(true);
|
||||||
}
|
}
|
||||||
return s_PIRsensorState;
|
else if (bri != 0)
|
||||||
}
|
{
|
||||||
|
// start switch off timer
|
||||||
/*
|
m_offTimerStart = millis();
|
||||||
* PIR sensor state has changed
|
|
||||||
*/
|
|
||||||
static void IRAM_ATTR ISR_PIRstateChange() {
|
|
||||||
newPIRsensorState(true, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* switch strip on/off
|
|
||||||
*/
|
|
||||||
void switchStrip(bool switchOn) {
|
|
||||||
if (switchOn && bri == 0) {
|
|
||||||
bri = briLast;
|
|
||||||
colorUpdated(NotifyUpdateMode);
|
|
||||||
}
|
|
||||||
else if (!switchOn && bri != 0) {
|
|
||||||
briLast = bri;
|
|
||||||
bri = 0;
|
|
||||||
colorUpdated(NotifyUpdateMode);
|
|
||||||
}
|
}
|
||||||
|
newPIRsensorState(true, false);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* Read and update PIR sensor state.
|
* switch off the strip if the delay has elapsed
|
||||||
* Initilize/reset switch off timer
|
*/
|
||||||
*/
|
bool handleOffTimer()
|
||||||
bool updatePIRsensorState() {
|
{
|
||||||
if (newPIRsensorState()) {
|
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay)
|
||||||
m_PIRsensorPinState = digitalRead(PIRsensorPin);
|
{
|
||||||
|
if (m_PIRenabled == true)
|
||||||
if (m_PIRsensorPinState == HIGH) {
|
{
|
||||||
m_offTimerStart = 0;
|
switchStrip(false);
|
||||||
switchStrip(true);
|
|
||||||
}
|
|
||||||
else if (bri != 0) {
|
|
||||||
// start switch off timer
|
|
||||||
m_offTimerStart = millis();
|
|
||||||
}
|
|
||||||
newPIRsensorState(true, false);
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
m_offTimerStart = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
public:
|
||||||
* switch off the strip if the delay has elapsed
|
//Functions called by WLED
|
||||||
*/
|
|
||||||
bool handleOffTimer() {
|
|
||||||
if (m_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay) {
|
|
||||||
if (m_PIRenabled == true){
|
|
||||||
switchStrip(false);
|
|
||||||
}
|
|
||||||
m_offTimerStart = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
/**
|
||||||
//Functions called by WLED
|
* setup() is called once at boot. WiFi is not yet connected at this point.
|
||||||
|
* You can use it to initialize variables, sensors or similar.
|
||||||
/*
|
*/
|
||||||
* setup() is called once at boot. WiFi is not yet connected at this point.
|
void setup()
|
||||||
* You can use it to initialize variables, sensors or similar.
|
{
|
||||||
*/
|
// PIR Sensor mode INPUT_PULLUP
|
||||||
void setup() {
|
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||||
// PIR Sensor mode INPUT_PULLUP
|
if (m_PIRenabled)
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
{
|
||||||
// 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
|
||||||
|
* Use it to initialize network interfaces
|
||||||
|
*/
|
||||||
|
void connected()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/**
|
||||||
* connected() is called every time the WiFi is (re)connected
|
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
||||||
* Use it to initialize network interfaces
|
*/
|
||||||
*/
|
void loop()
|
||||||
void connected() {
|
{
|
||||||
|
if (!updatePIRsensorState())
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* loop() is called continuously. Here you can check for events, read sensors, etc.
|
|
||||||
*/
|
|
||||||
void loop() {
|
|
||||||
if (!updatePIRsensorState()) {
|
|
||||||
handleOffTimer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
*/
|
|
||||||
void addToJsonInfo(JsonObject& root)
|
|
||||||
{
|
{
|
||||||
//this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
|
handleOffTimer();
|
||||||
// the value contains a button to toggle the sensor enabled/disabled
|
if (m_updateConfig)
|
||||||
JsonObject user = root["u"];
|
{
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
serializeConfig();
|
||||||
|
m_updateConfig = false;
|
||||||
JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
|
|
||||||
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
|
||||||
String sensorStateInfo;
|
|
||||||
|
|
||||||
// PIR sensor state
|
|
||||||
if (m_PIRenabled) {
|
|
||||||
uiDomString += "false";
|
|
||||||
sensorStateInfo = (m_PIRsensorPinState != LOW ? "active" : "inactive"); //value
|
|
||||||
} else {
|
|
||||||
uiDomString += "true";
|
|
||||||
sensorStateInfo = "Disabled !";
|
|
||||||
}
|
|
||||||
uiDomString += "});return false;\">";
|
|
||||||
uiDomString += sensorStateInfo;
|
|
||||||
uiDomString += "</button>";
|
|
||||||
infoArr.add(uiDomString); //value
|
|
||||||
|
|
||||||
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
|
||||||
infoArr = user.createNestedArray("⏲ switch off timer"); //name
|
|
||||||
|
|
||||||
// off timer
|
|
||||||
if (m_offTimerStart > 0) {
|
|
||||||
uiDomString = "";
|
|
||||||
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
|
||||||
if (offSeconds >= 3600) {
|
|
||||||
uiDomString += (offSeconds / 3600);
|
|
||||||
uiDomString += " hours ";
|
|
||||||
offSeconds %= 3600;
|
|
||||||
}
|
|
||||||
if (offSeconds >= 60) {
|
|
||||||
uiDomString += (offSeconds / 60);
|
|
||||||
offSeconds %= 60;
|
|
||||||
} else if (uiDomString.length() > 0){
|
|
||||||
uiDomString += 0;
|
|
||||||
}
|
|
||||||
if (uiDomString.length() > 0){
|
|
||||||
uiDomString += " min ";
|
|
||||||
}
|
|
||||||
uiDomString += (offSeconds);
|
|
||||||
infoArr.add(uiDomString + " sec");
|
|
||||||
} else {
|
|
||||||
infoArr.add("inactive");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
*/
|
||||||
|
void addToJsonInfo(JsonObject &root)
|
||||||
|
{
|
||||||
|
//this code adds "u":{"⏲ PIR sensor state":uiDomString} to the info object
|
||||||
|
// the value contains a button to toggle the sensor enabled/disabled
|
||||||
|
JsonObject user = root["u"];
|
||||||
|
if (user.isNull())
|
||||||
|
user = root.createNestedObject("u");
|
||||||
|
|
||||||
/*
|
JsonArray infoArr = user.createNestedArray("⏲ PIR sensor state"); //name
|
||||||
* addToJsonState() can be used to add custom entries to the /json/state part of the JSON API (state object).
|
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
||||||
* Values in the state object may be modified by connected clients
|
String sensorStateInfo;
|
||||||
* Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
|
|
||||||
* Add "PIRoffSec" to json state. This can be used to adjust <m_switchOffDelay> milliseconds .
|
// PIR sensor state
|
||||||
*/
|
if (m_PIRenabled)
|
||||||
void addToJsonState(JsonObject& root)
|
|
||||||
{
|
{
|
||||||
root["PIRenabled"] = m_PIRenabled;
|
uiDomString += "false";
|
||||||
root["PIRoffSec"] = (m_switchOffDelay / 1000);
|
sensorStateInfo = (m_PIRsensorPinState != LOW ? "active" : "inactive"); //value
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
* Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
|
|
||||||
* Read "PIRoffSec" from json state and adjust <m_switchOffDelay> milliseconds .
|
|
||||||
*/
|
|
||||||
void readFromJsonState(JsonObject& root)
|
|
||||||
{
|
{
|
||||||
if (root["PIRoffSec"] != nullptr) {
|
uiDomString += "true";
|
||||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
sensorStateInfo = "Disabled !";
|
||||||
}
|
|
||||||
|
|
||||||
if (root["PIRenabled"] != nullptr) {
|
|
||||||
if (root["PIRenabled"] && !m_PIRenabled) {
|
|
||||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
|
||||||
newPIRsensorState(true, true);
|
|
||||||
}
|
|
||||||
else if(m_PIRenabled) {
|
|
||||||
detachInterrupt(PIRsensorPin);
|
|
||||||
}
|
|
||||||
m_PIRenabled = root["PIRenabled"];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
uiDomString += "});return false;\">";
|
||||||
|
uiDomString += sensorStateInfo;
|
||||||
/*
|
uiDomString += "</button>";
|
||||||
* getId() allows you to optionally give your V2 usermod an unique ID (please define it in const.h!).
|
infoArr.add(uiDomString); //value
|
||||||
* This could be used in the future for the system to determine whether your usermod is installed.
|
|
||||||
*/
|
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
||||||
uint16_t getId()
|
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
|
||||||
|
if (m_offTimerStart > 0)
|
||||||
{
|
{
|
||||||
return USERMOD_ID_PIRSWITCH;
|
uiDomString = "";
|
||||||
|
unsigned int offSeconds = (m_switchOffDelay - (millis() - m_offTimerStart)) / 1000;
|
||||||
|
if (offSeconds >= 3600)
|
||||||
|
{
|
||||||
|
uiDomString += (offSeconds / 3600);
|
||||||
|
uiDomString += " hours ";
|
||||||
|
offSeconds %= 3600;
|
||||||
|
}
|
||||||
|
if (offSeconds >= 60)
|
||||||
|
{
|
||||||
|
uiDomString += (offSeconds / 60);
|
||||||
|
offSeconds %= 60;
|
||||||
|
}
|
||||||
|
else if (uiDomString.length() > 0)
|
||||||
|
{
|
||||||
|
uiDomString += 0;
|
||||||
|
}
|
||||||
|
if (uiDomString.length() > 0)
|
||||||
|
{
|
||||||
|
uiDomString += " min ";
|
||||||
|
}
|
||||||
|
uiDomString += (offSeconds);
|
||||||
|
infoArr.add(uiDomString + " sec");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
infoArr.add("inactive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* Add "PIRenabled" to json state. This can be used to disable/enable the sensor.
|
||||||
|
* Add "PIRoffSec" to json state. This can be used to adjust <m_switchOffDelay> milliseconds.
|
||||||
|
*/
|
||||||
|
void addToJsonState(JsonObject &root)
|
||||||
|
{
|
||||||
|
root["PIRenabled"] = m_PIRenabled;
|
||||||
|
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).
|
||||||
|
* Values in the state object may be modified by connected clients
|
||||||
|
* Read "PIRenabled" from json state and switch enable/disable the PIR sensor.
|
||||||
|
* Read "PIRoffSec" from json state and adjust <m_switchOffDelay> milliseconds.
|
||||||
|
*/
|
||||||
|
void readFromJsonState(JsonObject &root)
|
||||||
|
{
|
||||||
|
if (root["PIRoffSec"] != nullptr)
|
||||||
|
{
|
||||||
|
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
||||||
|
m_updateConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//More methods can be added in the future, this example will then be extended.
|
if (root["PIRenabled"] != nullptr)
|
||||||
//Your usermod will remain compatible as it does not need to implement all methods from the Usermod base class!
|
{
|
||||||
|
if (root["PIRenabled"] && !m_PIRenabled)
|
||||||
|
{
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||||
|
newPIRsensorState(true, true);
|
||||||
|
}
|
||||||
|
else if (m_PIRenabled)
|
||||||
|
{
|
||||||
|
detachInterrupt(PIRsensorPin);
|
||||||
|
}
|
||||||
|
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!).
|
||||||
|
* This could be used in the future for the system to determine whether your usermod is installed.
|
||||||
|
*/
|
||||||
|
uint16_t getId()
|
||||||
|
{
|
||||||
|
return USERMOD_ID_PIRSWITCH;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//////////////////////////////////////////////////////
|
||||||
|
// 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,8 +223,11 @@ 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)
|
||||||
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
//one PU is the power it takes to have 1 channel 1 step brighter per brightness step
|
||||||
@ -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;
|
||||||
|
@ -221,7 +221,7 @@ void deserializeConfig() {
|
|||||||
getStringFromJson(mqttClientID, if_mqtt[F("cid")], 41);
|
getStringFromJson(mqttClientID, if_mqtt[F("cid")], 41);
|
||||||
|
|
||||||
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], 33); // "wled/test"
|
getStringFromJson(mqttDeviceTopic, if_mqtt[F("topics")][F("device")], 33); // "wled/test"
|
||||||
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], 33); // ""
|
getStringFromJson(mqttGroupTopic, if_mqtt[F("topics")][F("group")], 33); // ""
|
||||||
|
|
||||||
JsonObject if_hue = interfaces[F("hue")];
|
JsonObject if_hue = interfaces[F("hue")];
|
||||||
CJSON(huePollingEnabled, if_hue[F("en")]);
|
CJSON(huePollingEnabled, if_hue[F("en")]);
|
||||||
@ -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")];
|
||||||
@ -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");
|
||||||
|
Loading…
Reference in New Issue
Block a user