God damn CRLF conversion. (I want to keep it clean)

This commit is contained in:
Blaz Kristan 2021-07-23 21:48:38 +02:00
parent 067a88b3e7
commit b3b3e3ea20

View File

@ -1,406 +1,406 @@
#pragma once #pragma once
#include "wled.h" #include "wled.h"
#ifndef PIR_SENSOR_PIN #ifndef PIR_SENSOR_PIN
// compatible with QuinLED-Dig-Uno // compatible with QuinLED-Dig-Uno
#ifdef ARDUINO_ARCH_ESP32 #ifdef ARDUINO_ARCH_ESP32
#define PIR_SENSOR_PIN 23 // Q4 #define PIR_SENSOR_PIN 23 // Q4
#else //ESP8266 boards #else //ESP8266 boards
#define PIR_SENSOR_PIN 13 // Q4 (D7 on D1 mini) #define PIR_SENSOR_PIN 13 // Q4 (D7 on D1 mini)
#endif #endif
#endif #endif
/* /*
* This usermod handles PIR sensor states. * This usermod handles PIR sensor states.
* The strip will be switched on and the off timer will be resetted when the sensor goes HIGH. * The strip will be switched on and the off timer will be resetted when the sensor goes HIGH.
* When the sensor state goes LOW, the off timer is started and when it expires, the strip is switched off. * When the sensor state goes LOW, the off timer is started and when it expires, the strip is switched off.
* *
* *
* Usermods allow you to add own functionality to WLED more easily * Usermods allow you to add own functionality to WLED more easily
* See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality * See: https://github.com/Aircoookie/WLED/wiki/Add-own-functionality
* *
* v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example. * v2 usermods are class inheritance based and can (but don't have to) implement more functions, each of them is shown in this example.
* Multiple v2 usermods can be added to one compilation easily. * Multiple v2 usermods can be added to one compilation easily.
* *
* Creating a usermod: * Creating a usermod:
* This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template. * This file serves as an example. If you want to create a usermod, it is recommended to use usermod_v2_empty.h from the usermods folder as a template.
* Please remember to rename the class and file to a descriptive name. * Please remember to rename the class and file to a descriptive name.
* You may also use multiple .h and .cpp files. * You may also use multiple .h and .cpp files.
* *
* Using a usermod: * Using a usermod:
* 1. Copy the usermod into the sketch folder (same folder as wled00.ino) * 1. Copy the usermod into the sketch folder (same folder as wled00.ino)
* 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: public:
/** /**
* constructor * constructor
*/ */
PIRsensorSwitch() {} PIRsensorSwitch() {}
/** /**
* desctructor * desctructor
*/ */
~PIRsensorSwitch() {} ~PIRsensorSwitch() {}
/** /**
* Enable/Disable the PIR sensor * Enable/Disable the PIR sensor
*/ */
void EnablePIRsensor(bool en) { enabled = en; } void EnablePIRsensor(bool en) { enabled = en; }
/** /**
* Get PIR sensor enabled/disabled state * Get PIR sensor enabled/disabled state
*/ */
bool PIRsensorEnabled() { return enabled; } bool PIRsensorEnabled() { return enabled; }
private: private:
// PIR sensor pin // PIR sensor pin
int8_t PIRsensorPin = PIR_SENSOR_PIN; int8_t PIRsensorPin = PIR_SENSOR_PIN;
// notification mode for colorUpdated() // notification mode for colorUpdated()
const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE const byte NotifyUpdateMode = CALL_MODE_NO_NOTIFY; // CALL_MODE_DIRECT_CHANGE
// delay before switch off after the sensor state goes LOW // delay before switch off after the sensor state goes LOW
uint32_t m_switchOffDelay = 600000; // 10min uint32_t m_switchOffDelay = 600000; // 10min
// off timer start time // off timer start time
uint32_t m_offTimerStart = 0; uint32_t m_offTimerStart = 0;
// current PIR sensor pin state // current PIR sensor pin state
byte sensorPinState = LOW; byte sensorPinState = LOW;
// PIR sensor enabled // PIR sensor enabled
bool enabled = true; bool enabled = true;
// status of initialisation // status of initialisation
bool initDone = false; bool initDone = false;
// on and off presets // on and off presets
uint8_t m_onPreset = 0; uint8_t m_onPreset = 0;
uint8_t m_offPreset = 0; uint8_t m_offPreset = 0;
// flag to indicate that PIR sensor should activate WLED during nighttime only // flag to indicate that PIR sensor should activate WLED during nighttime only
bool m_nightTimeOnly = false; bool m_nightTimeOnly = false;
// flag to send MQTT message only (assuming it is enabled) // flag to send MQTT message only (assuming it is enabled)
bool m_mqttOnly = false; bool m_mqttOnly = false;
// flag to enable triggering only if WLED is initially off (LEDs are not on, preventing running effect being overwritten by PIR) // flag to enable triggering only if WLED is initially off (LEDs are not on, preventing running effect being overwritten by PIR)
bool m_offOnly = false; bool m_offOnly = false;
bool PIRtriggered = false; bool PIRtriggered = false;
unsigned long lastLoop = 0; unsigned long lastLoop = 0;
// strings to reduce flash memory usage (used more than twice) // strings to reduce flash memory usage (used more than twice)
static const char _name[]; static const char _name[];
static const char _switchOffDelay[]; static const char _switchOffDelay[];
static const char _enabled[]; static const char _enabled[];
static const char _onPreset[]; static const char _onPreset[];
static const char _offPreset[]; static const char _offPreset[];
static const char _nightTime[]; static const char _nightTime[];
static const char _mqttOnly[]; static const char _mqttOnly[];
static const char _offOnly[]; static const char _offOnly[];
/** /**
* check if it is daytime * check if it is daytime
* if sunrise/sunset is not defined (no NTP or lat/lon) default to nighttime * if sunrise/sunset is not defined (no NTP or lat/lon) default to nighttime
*/ */
bool isDayTime() { bool isDayTime() {
bool isDayTime = false; bool isDayTime = false;
updateLocalTime(); updateLocalTime();
uint8_t hr = hour(localTime); uint8_t hr = hour(localTime);
uint8_t mi = minute(localTime); uint8_t mi = minute(localTime);
if (sunrise && sunset) { if (sunrise && sunset) {
if (hour(sunrise)<hr && hour(sunset)>hr) { if (hour(sunrise)<hr && hour(sunset)>hr) {
isDayTime = true; isDayTime = true;
} else { } else {
if (hour(sunrise)==hr && minute(sunrise)<mi) { if (hour(sunrise)==hr && minute(sunrise)<mi) {
isDayTime = true; isDayTime = true;
} }
if (hour(sunset)==hr && minute(sunset)>mi) { if (hour(sunset)==hr && minute(sunset)>mi) {
isDayTime = true; isDayTime = true;
} }
} }
} }
return isDayTime; return isDayTime;
} }
/** /**
* switch strip on/off * switch strip on/off
*/ */
void switchStrip(bool switchOn) void switchStrip(bool switchOn)
{ {
PIRtriggered = switchOn; PIRtriggered = switchOn;
if (switchOn && m_onPreset) { if (switchOn && m_onPreset) {
applyPreset(m_onPreset); applyPreset(m_onPreset);
} else if (!switchOn && m_offPreset) { } else if (!switchOn && m_offPreset) {
applyPreset(m_offPreset); applyPreset(m_offPreset);
} else if (switchOn && bri == 0) { } else 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);
} }
} }
void publishMqtt(const char* state) void publishMqtt(const char* state)
{ {
//Check if MQTT Connected, otherwise it will crash the 8266 //Check if MQTT Connected, otherwise it will crash the 8266
if (WLED_MQTT_CONNECTED){ if (WLED_MQTT_CONNECTED){
char subuf[64]; char subuf[64];
strcpy(subuf, mqttDeviceTopic); strcpy(subuf, mqttDeviceTopic);
strcat_P(subuf, PSTR("/motion")); strcat_P(subuf, PSTR("/motion"));
mqtt->publish(subuf, 0, false, state); mqtt->publish(subuf, 0, false, state);
} }
} }
/** /**
* 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()
{ {
bool pinState = digitalRead(PIRsensorPin); bool pinState = digitalRead(PIRsensorPin);
if (pinState != sensorPinState) { if (pinState != sensorPinState) {
sensorPinState = pinState; // change previous state sensorPinState = pinState; // change previous state
if (sensorPinState == HIGH) { if (sensorPinState == HIGH) {
m_offTimerStart = 0; m_offTimerStart = 0;
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true); if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(true);
publishMqtt("on"); publishMqtt("on");
} else /*if (bri != 0)*/ { } else /*if (bri != 0)*/ {
// start switch off timer // start switch off timer
m_offTimerStart = millis(); m_offTimerStart = millis();
} }
return true; return true;
} }
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_offTimerStart > 0 && millis() - m_offTimerStart > m_switchOffDelay)
{ {
if (enabled == true) if (enabled == true)
{ {
if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(false); if (!m_mqttOnly && (!m_nightTimeOnly || (m_nightTimeOnly && !isDayTime()))) switchStrip(false);
publishMqtt("off"); publishMqtt("off");
} }
m_offTimerStart = 0; m_offTimerStart = 0;
return true; return true;
} }
return false; return 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()
{ {
if (enabled) { if (enabled) {
// pin retrieved from cfg.json (readFromConfig()) prior to running setup() // pin retrieved from cfg.json (readFromConfig()) prior to running setup()
if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin,false)) { if (PIRsensorPin >= 0 && pinManager.allocatePin(PIRsensorPin,false)) {
// PIR Sensor mode INPUT_PULLUP // PIR Sensor mode INPUT_PULLUP
pinMode(PIRsensorPin, INPUT_PULLUP); pinMode(PIRsensorPin, INPUT_PULLUP);
sensorPinState = digitalRead(PIRsensorPin); sensorPinState = digitalRead(PIRsensorPin);
} else { } else {
if (PIRsensorPin >= 0) DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed.")); if (PIRsensorPin >= 0) DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed."));
PIRsensorPin = -1; // allocation failed PIRsensorPin = -1; // allocation failed
enabled = false; enabled = false;
} }
} }
initDone = true; initDone = true;
} }
/** /**
* 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()
{ {
// only check sensors 4x/s // only check sensors 4x/s
if (!enabled || millis() - lastLoop < 250 || strip.isUpdating() || (m_offOnly && bri && !PIRtriggered)) return; if (!enabled || millis() - lastLoop < 250 || strip.isUpdating() || (m_offOnly && bri && !PIRtriggered)) return;
lastLoop = millis(); lastLoop = millis();
if (!updatePIRsensorState()) { if (!updatePIRsensorState()) {
handleOffTimer(); handleOffTimer();
} }
} }
/** /**
* 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
*/ */
void addToJsonInfo(JsonObject &root) void addToJsonInfo(JsonObject &root)
{ {
JsonObject user = root["u"]; JsonObject user = root["u"];
if (user.isNull()) user = root.createNestedObject("u"); if (user.isNull()) user = root.createNestedObject("u");
if (enabled) if (enabled)
{ {
// off timer // off timer
String uiDomString = F("PIR <i class=\"icons\">&#xe325;</i>"); String uiDomString = F("PIR <i class=\"icons\">&#xe325;</i>");
JsonArray infoArr = user.createNestedArray(uiDomString); // timer value JsonArray infoArr = user.createNestedArray(uiDomString); // timer value
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 += F("h "); uiDomString += F("h ");
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 += F("min "); uiDomString += F("min ");
} }
uiDomString += (offSeconds); uiDomString += (offSeconds);
infoArr.add(uiDomString + F("s")); infoArr.add(uiDomString + F("s"));
} else { } else {
infoArr.add(sensorPinState ? F("sensor on") : F("inactive")); infoArr.add(sensorPinState ? F("sensor on") : F("inactive"));
} }
} else { } else {
String uiDomString = F("PIR sensor"); String uiDomString = F("PIR sensor");
JsonArray infoArr = user.createNestedArray(uiDomString); JsonArray infoArr = user.createNestedArray(uiDomString);
infoArr.add(F("disabled")); infoArr.add(F("disabled"));
} }
} }
/** /**
* 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)
{ {
} }
*/ */
/** /**
* 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)
{ {
} }
*/ */
/** /**
* provide the changeable values * provide the changeable values
*/ */
void addToConfig(JsonObject &root) void addToConfig(JsonObject &root)
{ {
JsonObject top = root.createNestedObject(FPSTR(_name)); JsonObject top = root.createNestedObject(FPSTR(_name));
top[FPSTR(_enabled)] = enabled; top[FPSTR(_enabled)] = enabled;
top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000; top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000;
top["pin"] = PIRsensorPin; top["pin"] = PIRsensorPin;
top[FPSTR(_onPreset)] = m_onPreset; top[FPSTR(_onPreset)] = m_onPreset;
top[FPSTR(_offPreset)] = m_offPreset; top[FPSTR(_offPreset)] = m_offPreset;
top[FPSTR(_nightTime)] = m_nightTimeOnly; top[FPSTR(_nightTime)] = m_nightTimeOnly;
top[FPSTR(_mqttOnly)] = m_mqttOnly; top[FPSTR(_mqttOnly)] = m_mqttOnly;
top[FPSTR(_offOnly)] = m_offOnly; top[FPSTR(_offOnly)] = m_offOnly;
DEBUG_PRINTLN(F("PIR config saved.")); DEBUG_PRINTLN(F("PIR config saved."));
} }
/** /**
* restore the changeable values * restore the changeable values
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json * readFromConfig() is called before setup() to populate properties from values stored in cfg.json
* *
* The function should return true if configuration was successfully loaded or false if there was no configuration. * The function should return true if configuration was successfully loaded or false if there was no configuration.
*/ */
bool readFromConfig(JsonObject &root) bool readFromConfig(JsonObject &root)
{ {
bool oldEnabled = enabled; bool oldEnabled = enabled;
int8_t oldPin = PIRsensorPin; int8_t oldPin = PIRsensorPin;
JsonObject top = root[FPSTR(_name)]; JsonObject top = root[FPSTR(_name)];
if (top.isNull()) { if (top.isNull()) {
DEBUG_PRINT(FPSTR(_name)); DEBUG_PRINT(FPSTR(_name));
DEBUG_PRINTLN(F(": No config found. (Using defaults.)")); DEBUG_PRINTLN(F(": No config found. (Using defaults.)"));
return false; return false;
} }
PIRsensorPin = top["pin"] | PIRsensorPin; PIRsensorPin = top["pin"] | PIRsensorPin;
enabled = top[FPSTR(_enabled)] | enabled; enabled = top[FPSTR(_enabled)] | enabled;
m_switchOffDelay = (top[FPSTR(_switchOffDelay)] | m_switchOffDelay/1000) * 1000; m_switchOffDelay = (top[FPSTR(_switchOffDelay)] | m_switchOffDelay/1000) * 1000;
m_onPreset = top[FPSTR(_onPreset)] | m_onPreset; m_onPreset = top[FPSTR(_onPreset)] | m_onPreset;
m_onPreset = max(0,min(250,(int)m_onPreset)); m_onPreset = max(0,min(250,(int)m_onPreset));
m_offPreset = top[FPSTR(_offPreset)] | m_offPreset; m_offPreset = top[FPSTR(_offPreset)] | m_offPreset;
m_offPreset = max(0,min(250,(int)m_offPreset)); m_offPreset = max(0,min(250,(int)m_offPreset));
m_nightTimeOnly = top[FPSTR(_nightTime)] | m_nightTimeOnly; m_nightTimeOnly = top[FPSTR(_nightTime)] | m_nightTimeOnly;
m_mqttOnly = top[FPSTR(_mqttOnly)] | m_mqttOnly; m_mqttOnly = top[FPSTR(_mqttOnly)] | m_mqttOnly;
m_offOnly = top[FPSTR(_offOnly)] | m_offOnly; m_offOnly = top[FPSTR(_offOnly)] | m_offOnly;
DEBUG_PRINT(FPSTR(_name)); DEBUG_PRINT(FPSTR(_name));
if (!initDone) { if (!initDone) {
// reading config prior to setup() // reading config prior to setup()
DEBUG_PRINTLN(F(" config loaded.")); DEBUG_PRINTLN(F(" config loaded."));
} else { } else {
if (oldPin != PIRsensorPin || oldEnabled != enabled) { if (oldPin != PIRsensorPin || oldEnabled != enabled) {
// check if pin is OK // check if pin is OK
if (oldPin != PIRsensorPin && oldPin >= 0) { if (oldPin != PIRsensorPin && oldPin >= 0) {
// if we are changing pin in settings page // if we are changing pin in settings page
// deallocate old pin // deallocate old pin
pinManager.deallocatePin(oldPin); pinManager.deallocatePin(oldPin);
if (pinManager.allocatePin(PIRsensorPin,false)) { if (pinManager.allocatePin(PIRsensorPin,false)) {
pinMode(PIRsensorPin, INPUT_PULLUP); pinMode(PIRsensorPin, INPUT_PULLUP);
} else { } else {
// allocation failed // allocation failed
PIRsensorPin = -1; PIRsensorPin = -1;
enabled = false; enabled = false;
} }
} }
if (enabled) { if (enabled) {
sensorPinState = digitalRead(PIRsensorPin); sensorPinState = digitalRead(PIRsensorPin);
} }
} }
DEBUG_PRINTLN(F(" config (re)loaded.")); DEBUG_PRINTLN(F(" config (re)loaded."));
} }
// use "return !top["newestParameter"].isNull();" when updating Usermod with new features // use "return !top["newestParameter"].isNull();" when updating Usermod with new features
return !top[FPSTR(_offOnly)].isNull(); return !top[FPSTR(_offOnly)].isNull();
} }
/** /**
* 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.
*/ */
uint16_t getId() uint16_t getId()
{ {
return USERMOD_ID_PIRSWITCH; return USERMOD_ID_PIRSWITCH;
} }
}; };
// strings to reduce flash memory usage (used more than twice) // strings to reduce flash memory usage (used more than twice)
const char PIRsensorSwitch::_name[] PROGMEM = "PIRsensorSwitch"; const char PIRsensorSwitch::_name[] PROGMEM = "PIRsensorSwitch";
const char PIRsensorSwitch::_enabled[] PROGMEM = "PIRenabled"; const char PIRsensorSwitch::_enabled[] PROGMEM = "PIRenabled";
const char PIRsensorSwitch::_switchOffDelay[] PROGMEM = "PIRoffSec"; const char PIRsensorSwitch::_switchOffDelay[] PROGMEM = "PIRoffSec";
const char PIRsensorSwitch::_onPreset[] PROGMEM = "on-preset"; const char PIRsensorSwitch::_onPreset[] PROGMEM = "on-preset";
const char PIRsensorSwitch::_offPreset[] PROGMEM = "off-preset"; const char PIRsensorSwitch::_offPreset[] PROGMEM = "off-preset";
const char PIRsensorSwitch::_nightTime[] PROGMEM = "nighttime-only"; const char PIRsensorSwitch::_nightTime[] PROGMEM = "nighttime-only";
const char PIRsensorSwitch::_mqttOnly[] PROGMEM = "mqtt-only"; const char PIRsensorSwitch::_mqttOnly[] PROGMEM = "mqtt-only";
const char PIRsensorSwitch::_offOnly[] PROGMEM = "off-only"; const char PIRsensorSwitch::_offOnly[] PROGMEM = "off-only";