PIR sensor usermod pin reservation.
Time settings UI tweaks.
This commit is contained in:
parent
cb38976162
commit
f91384596c
@ -2,6 +2,15 @@
|
||||
|
||||
#include "wled.h"
|
||||
|
||||
#ifndef PIR_SENSOR_PIN
|
||||
// compatible with QuinLED-Dig-Uno
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
#define PIR_SENSOR_PIN 23 // Q4
|
||||
#else //ESP8266 boards
|
||||
#define PIR_SENSOR_PIN 13 // Q4 (D7 on D1 mini)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This usermod handles PIR sensor states.
|
||||
* The strip will be switched on and the off timer will be resetted when the sensor goes HIGH.
|
||||
@ -24,6 +33,9 @@
|
||||
* 2. Register the usermod by adding #include "usermod_filename.h" in the top and registerUsermod(new MyUsermodClass()) in the bottom of usermods_list.cpp
|
||||
*/
|
||||
|
||||
// MQTT topic for sensor values
|
||||
const char MQTT_TOPIC[] = "/motion";
|
||||
|
||||
class PIRsensorSwitch : public Usermod
|
||||
{
|
||||
public:
|
||||
@ -60,7 +72,7 @@ public:
|
||||
|
||||
private:
|
||||
// PIR sensor pin
|
||||
const uint8_t PIRsensorPin = 13; // D7 on D1 mini
|
||||
int8_t PIRsensorPin = PIR_SENSOR_PIN;
|
||||
// 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
|
||||
@ -107,6 +119,17 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
void publishMqtt(const char* state)
|
||||
{
|
||||
//Check if MQTT Connected, otherwise it will crash the 8266
|
||||
if (mqtt != nullptr){
|
||||
char subuf[64];
|
||||
strcpy(subuf, mqttDeviceTopic);
|
||||
strcat(subuf, MQTT_TOPIC);
|
||||
mqtt->publish(subuf, 0, true, state);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and update PIR sensor state.
|
||||
* Initilize/reset switch off timer
|
||||
@ -121,6 +144,7 @@ private:
|
||||
{
|
||||
m_offTimerStart = 0;
|
||||
switchStrip(true);
|
||||
publishMqtt("on");
|
||||
}
|
||||
else if (bri != 0)
|
||||
{
|
||||
@ -143,6 +167,7 @@ private:
|
||||
if (m_PIRenabled == true)
|
||||
{
|
||||
switchStrip(false);
|
||||
publishMqtt("off");
|
||||
}
|
||||
m_offTimerStart = 0;
|
||||
return true;
|
||||
@ -159,12 +184,19 @@ public:
|
||||
*/
|
||||
void setup()
|
||||
{
|
||||
// PIR Sensor mode INPUT_PULLUP
|
||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||
if (m_PIRenabled)
|
||||
{
|
||||
// assign interrupt function and set CHANGE mode
|
||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||
// pin retrieved from cfg.json (readFromConfig()) prior to running setup()
|
||||
if (!pinManager.allocatePin(PIRsensorPin,false)) {
|
||||
PIRsensorPin = -1; // allocation failed
|
||||
m_PIRenabled = false;
|
||||
DEBUG_PRINTLN(F("PIRSensorSwitch pin allocation failed."));
|
||||
} else {
|
||||
// PIR Sensor mode INPUT_PULLUP
|
||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||
if (m_PIRenabled)
|
||||
{
|
||||
// assign interrupt function and set CHANGE mode
|
||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -273,8 +305,8 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
||||
*/
|
||||
void addToJsonState(JsonObject &root)
|
||||
{
|
||||
root["PIRenabled"] = m_PIRenabled;
|
||||
root["PIRoffSec"] = (m_switchOffDelay / 1000);
|
||||
root[F("PIRenabled")] = m_PIRenabled;
|
||||
root[F("PIRoffSec")] = (m_switchOffDelay / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -285,15 +317,37 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
||||
*/
|
||||
void readFromJsonState(JsonObject &root)
|
||||
{
|
||||
if (root["PIRoffSec"] != nullptr)
|
||||
if (root[F("PIRoffSec")] != nullptr)
|
||||
{
|
||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root["PIRoffSec"].as<unsigned long>())));
|
||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root[F("PIRoffSec")].as<unsigned long>())));
|
||||
m_updateConfig = true;
|
||||
}
|
||||
|
||||
if (root["PIRenabled"] != nullptr)
|
||||
if (root[F("pin")] != nullptr)
|
||||
{
|
||||
if (root["PIRenabled"] && !m_PIRenabled)
|
||||
int8_t pin = (int)root[F("pin")];
|
||||
// check if pin is OK
|
||||
if (pin != PIRsensorPin && pin>=0 && pinManager.allocatePin(pin,false)) {
|
||||
// deallocate old pin
|
||||
pinManager.deallocatePin(PIRsensorPin);
|
||||
// PIR Sensor mode INPUT_PULLUP
|
||||
pinMode(pin, INPUT_PULLUP);
|
||||
if (m_PIRenabled)
|
||||
{
|
||||
// remove old ISR
|
||||
detachInterrupt(PIRsensorPin);
|
||||
// assign interrupt function and set CHANGE mode
|
||||
attachInterrupt(digitalPinToInterrupt(pin), ISR_PIRstateChange, CHANGE);
|
||||
newPIRsensorState(true, true);
|
||||
}
|
||||
PIRsensorPin = pin;
|
||||
m_updateConfig = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (root[F("PIRenabled")] != nullptr)
|
||||
{
|
||||
if (root[F("PIRenabled")] && !m_PIRenabled)
|
||||
{
|
||||
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||
newPIRsensorState(true, true);
|
||||
@ -302,7 +356,7 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
||||
{
|
||||
detachInterrupt(PIRsensorPin);
|
||||
}
|
||||
m_PIRenabled = root["PIRenabled"];
|
||||
m_PIRenabled = root[F("PIRenabled")];
|
||||
m_updateConfig = true;
|
||||
}
|
||||
}
|
||||
@ -312,19 +366,24 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
||||
*/
|
||||
void addToConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root.createNestedObject("PIRsensorSwitch");
|
||||
top["PIRenabled"] = m_PIRenabled;
|
||||
top["PIRoffSec"] = m_switchOffDelay;
|
||||
JsonObject top = root.createNestedObject(F("PIRsensorSwitch"));
|
||||
top[F("PIRenabled")] = m_PIRenabled;
|
||||
top[F("PIRoffSec")] = m_switchOffDelay;
|
||||
top[F("pin")] = PIRsensorPin;
|
||||
}
|
||||
|
||||
/**
|
||||
* restore the changeable values
|
||||
* readFromConfig() is called before setup() to populate properties from values stored in cfg.json
|
||||
*/
|
||||
void readFromConfig(JsonObject &root)
|
||||
{
|
||||
JsonObject top = root["PIRsensorSwitch"];
|
||||
m_PIRenabled = (top["PIRenabled"] != nullptr ? top["PIRenabled"] : true);
|
||||
m_switchOffDelay = top["PIRoffSec"] | m_switchOffDelay;
|
||||
JsonObject top = root[F("PIRsensorSwitch")];
|
||||
if (!top.isNull() && top[F("pin")] != nullptr) {
|
||||
PIRsensorPin = (int)top[F("pin")];
|
||||
}
|
||||
m_PIRenabled = (top[F("PIRenabled")] != nullptr ? top[F("PIRenabled")] : true);
|
||||
m_switchOffDelay = top[F("PIRoffSec")] | m_switchOffDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -46,12 +46,12 @@
|
||||
var ih="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";
|
||||
for (i=0;i<8;i++)
|
||||
{
|
||||
ih+="<tr><td><input name=\"W"+i+"\" id=\"W"+i+"\" type=\"number\" style=\"display:none\"><input id=\"W"+i+"0\" type=\"checkbox\"></td><td><input name=\"H"+i+"\" type=\"number\" min=\"0\" max=\"24\"></td><td><input name=\"N"+i+"\" type=\"number\" min=\"0\" max=\"59\"></td><td><input name=\"T"+i+"\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
ih+="<tr><td><input name=\"W"+i+"\" id=\"W"+i+"\" type=\"number\" style=\"display:none\"><input id=\"W"+i+"0\" type=\"checkbox\"></td><td><input name=\"H"+i+"\" class=\"small\" type=\"number\" min=\"0\" max=\"24\"></td><td><input name=\"N"+i+"\" class=\"small\" type=\"number\" min=\"0\" max=\"59\"></td><td><input name=\"T"+i+"\" class=\"small\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W"+i+j+"\" type=\"checkbox\"></td>";
|
||||
}
|
||||
ih+="<tr><td><input name=\"W8\" id=\"W8\" type=\"number\" style=\"display:none\"><input id=\"W80\" type=\"checkbox\"></td><td>Sunrise<input name=\"H8\" value=\"255\" type=\"hidden\"></td><td><input name=\"N8\" type=\"number\" min=\"-59\" max=\"59\"></td><td><input name=\"T8\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
ih+="<tr><td><input name=\"W8\" id=\"W8\" type=\"number\" style=\"display:none\"><input id=\"W80\" type=\"checkbox\"></td><td>Sunrise<input name=\"H8\" class=\"small\" value=\"255\" type=\"hidden\"></td><td><input name=\"N8\" class=\"small\" type=\"number\" min=\"-59\" max=\"59\"></td><td><input name=\"T8\" class=\"small\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W8"+j+"\" type=\"checkbox\"></td>";
|
||||
ih+="<tr><td><input name=\"W9\" id=\"W9\" type=\"number\" style=\"display:none\"><input id=\"W90\" type=\"checkbox\"></td><td>Sunset<input name=\"H9\" value=\"255\" type=\"hidden\"></td><td><input name=\"N9\" type=\"number\" min=\"-59\" max=\"59\"><td><input name=\"T9\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
ih+="<tr><td><input name=\"W9\" id=\"W9\" type=\"number\" style=\"display:none\"><input id=\"W90\" type=\"checkbox\"></td><td>Sunset<input name=\"H9\" class=\"small\" value=\"255\" type=\"hidden\"></td><td><input name=\"N9\" class=\"small\" type=\"number\" min=\"-59\" max=\"59\"><td><input name=\"T9\" class=\"small\" type=\"number\" min=\"0\" max=\"250\"></td>";
|
||||
for (j=1;j<8;j++) ih+="<td><input id=\"W9"+j+"\" type=\"checkbox\"></td>";
|
||||
gId("TMT").innerHTML=ih;
|
||||
}
|
||||
@ -142,8 +142,8 @@
|
||||
</div>
|
||||
Countdown Mode: <input type="checkbox" name="CE"><br>
|
||||
Countdown Goal:<br>
|
||||
Year: 20 <input name="CY" type="number" min="0" max="99" required> Month: <input name="CI" type="number" min="1" max="12" required> Day: <input name="CD" type="number" min="1" max="31" required><br>
|
||||
Hour: <input name="CH" type="number" min="0" max="23" required> Minute: <input name="CM" type="number" min="0" max="59" required> Second: <input name="CS" type="number" min="0" max="59" required><br>
|
||||
Year: 20 <input name="CY" class="small" type="number" min="0" max="99" required> Month: <input name="CI" class="small" type="number" min="1" max="12" required> Day: <input name="CD" class="small" type="number" min="1" max="31" required><br>
|
||||
Hour: <input name="CH" class="small" type="number" min="0" max="23" required> Minute: <input name="CM" class="small" type="number" min="0" max="59" required> Second: <input name="CS" class="small" type="number" min="0" max="59" required><br>
|
||||
<h3>Macro presets</h3>
|
||||
<b>Macros have moved!</b><br>
|
||||
<i>Presets now also can be used as macros to save both JSON and HTTP API commands.<br>
|
||||
|
@ -43,6 +43,12 @@ input[type="number"] {
|
||||
font-size: medium;
|
||||
margin: 2px;
|
||||
}
|
||||
input[type="number"].big {
|
||||
width: 80px;
|
||||
}
|
||||
input[type="number"].small {
|
||||
width: 40px;
|
||||
}
|
||||
select {
|
||||
margin: 2px;
|
||||
font-size: medium;
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
// Autogenerated from wled00/data/style.css, do not edit!!
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;border-radius:24px;display:inline-block;font-size:20px;margin:12px 8px 8px;padding:8px 12px;min-width:48px}.toprow{top:0;position:sticky;background-color:#222;z-index:1}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em;font-size:medium;margin:2px}select{margin:2px;font-size:medium}input[type=checkbox]{-ms-transform:scale(2);-moz-transform:scale(2);-webkit-transform:scale(2);-o-transform:scale(2);transform:scale(2)}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}td{padding:2px}.d5{width:4.5em!important}</style>)=====";
|
||||
const char PAGE_settingsCss[] PROGMEM = R"=====(<style>body{font-family:Verdana,sans-serif;text-align:center;background:#222;color:#fff;line-height:200%;margin:0}hr{border-color:#666}button{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.3ch solid #333;border-radius:24px;display:inline-block;font-size:20px;margin:12px 8px 8px;padding:8px 12px;min-width:48px}.toprow{top:0;position:sticky;background-color:#222;z-index:1}.helpB{text-align:left;position:absolute;width:60px}input{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}input[type=number]{width:4em;font-size:medium;margin:2px}input[type=number].big{width:80px}input[type=number].small{width:40px}select{margin:2px;font-size:medium}input[type=checkbox]{-ms-transform:scale(2);-moz-transform:scale(2);-webkit-transform:scale(2);-o-transform:scale(2);transform:scale(2)}select{background:#333;color:#fff;font-family:Verdana,sans-serif;border:.5ch solid #333}td{padding:2px}.d5{width:4.5em!important}</style>)=====";
|
||||
|
||||
|
||||
// Autogenerated from wled00/data/settings.htm, do not edit!!
|
||||
@ -297,7 +297,7 @@ type="submit">Save</button></form></body></html>)=====";
|
||||
// Autogenerated from wled00/data/settings_time.htm, do not edit!!
|
||||
const char PAGE_settings_time[] PROGMEM = R"=====(<!DOCTYPE html><html lang="en"><head><meta name="viewport" content="width=500">
|
||||
<meta charset="utf-8"><title>Time Settings</title><script>
|
||||
var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings")}function B(){window.open("/settings","_self")}function S(){BTa(),GetV(),Cs(),FC()}function gId(t){return d.getElementById(t)}function Cs(){gId("cac").style.display="none",gId("coc").style.display="block",gId("ccc").style.display="none",gId("ca").selected&&(gId("cac").style.display="block"),gId("cc").selected&&(gId("coc").style.display="none",gId("ccc").style.display="block"),gId("cn").selected&&(gId("coc").style.display="none")}function BTa(){var t="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for(i=0;i<8;i++)for(t+='<tr><td><input name="W'+i+'" id="W'+i+'" type="number" style="display:none"><input id="W'+i+'0" type="checkbox"></td><td><input name="H'+i+'" type="number" min="0" max="24"></td><td><input name="N'+i+'" type="number" min="0" max="59"></td><td><input name="T'+i+'" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W'+i+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W8" id="W8" type="number" style="display:none"><input id="W80" type="checkbox"></td><td>Sunrise<input name="H8" value="255" type="hidden"></td><td><input name="N8" type="number" min="-59" max="59"></td><td><input name="T8" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W8'+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W9" id="W9" type="number" style="display:none"><input id="W90" type="checkbox"></td><td>Sunset<input name="H9" value="255" type="hidden"></td><td><input name="N9" type="number" min="-59" max="59"><td><input name="T9" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W9'+j+'" type="checkbox"></td>';gId("TMT").innerHTML=t}function FC(){for(j=0;j<8;j++)for(i=0;i<10;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1}function Wd(){for(a=[0,0,0,0,0,0,0,0,0,0],i=0;i<10;i++){for(m=1,j=0;j<8;j++)a[i]+=gId("W"+i+j).checked*m,m*=2;gId("W"+i).value=a[i]}}function GetV() {
|
||||
var d=document;function H(){window.open("https://github.com/Aircoookie/WLED/wiki/Settings#time-settings")}function B(){window.open("/settings","_self")}function S(){BTa(),GetV(),Cs(),FC()}function gId(t){return d.getElementById(t)}function Cs(){gId("cac").style.display="none",gId("coc").style.display="block",gId("ccc").style.display="none",gId("ca").selected&&(gId("cac").style.display="block"),gId("cc").selected&&(gId("coc").style.display="none",gId("ccc").style.display="block"),gId("cn").selected&&(gId("coc").style.display="none")}function BTa(){var t="<tr><th>Active</th><th>Hour</th><th>Minute</th><th>Preset</th><th>M</th><th>T</th><th>W</th><th>T</th><th>F</th><th>S</th><th>S</th></tr>";for(i=0;i<8;i++)for(t+='<tr><td><input name="W'+i+'" id="W'+i+'" type="number" style="display:none"><input id="W'+i+'0" type="checkbox"></td><td><input name="H'+i+'" class="small" type="number" min="0" max="24"></td><td><input name="N'+i+'" class="small" type="number" min="0" max="59"></td><td><input name="T'+i+'" class="small" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W'+i+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W8" id="W8" type="number" style="display:none"><input id="W80" type="checkbox"></td><td>Sunrise<input name="H8" class="small" value="255" type="hidden"></td><td><input name="N8" class="small" type="number" min="-59" max="59"></td><td><input name="T8" class="small" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W8'+j+'" type="checkbox"></td>';for(t+='<tr><td><input name="W9" id="W9" type="number" style="display:none"><input id="W90" type="checkbox"></td><td>Sunset<input name="H9" class="small" value="255" type="hidden"></td><td><input name="N9" class="small" type="number" min="-59" max="59"><td><input name="T9" class="small" type="number" min="0" max="250"></td>',j=1;j<8;j++)t+='<td><input id="W9'+j+'" type="checkbox"></td>';gId("TMT").innerHTML=t}function FC(){for(j=0;j<8;j++)for(i=0;i<10;i++)gId("W"+i+j).checked=gId("W"+i).value>>j&1}function Wd(){for(a=[0,0,0,0,0,0,0,0,0,0],i=0;i<10;i++){for(m=1,j=0;j<8;j++)a[i]+=gId("W"+i+j).checked*m,m*=2;gId("W"+i).value=a[i]}}function GetV() {
|
||||
%CSS%%SCSS%</head><body onload="S()"><form
|
||||
id="form_s" name="Sf" method="post" onsubmit="Wd()"><div class="toprow"><div
|
||||
class="helpB"><button type="button" onclick="H()">?</button></div><button
|
||||
@ -330,13 +330,14 @@ name="O2" type="number" min="0" max="255" required><br><div id="cac">12h LED:
|
||||
type="checkbox" name="OS"><br></div><div id="ccc">Cronixie Display: <input
|
||||
name="CX" maxlength="6"><br>Cronixie Backlight: <input type="checkbox"
|
||||
name="CB"><br></div>Countdown Mode: <input type="checkbox" name="CE"><br>
|
||||
Countdown Goal:<br>Year: 20 <input name="CY" type="number" min="0" max="99"
|
||||
required> Month: <input name="CI" type="number" min="1" max="12" required> Day:
|
||||
<input name="CD" type="number" min="1" max="31" required><br>Hour: <input
|
||||
name="CH" type="number" min="0" max="23" required> Minute: <input name="CM"
|
||||
type="number" min="0" max="59" required> Second: <input name="CS" type="number"
|
||||
min="0" max="59" required><br><h3>Macro presets</h3><b>Macros have moved!</b>
|
||||
<br><i>
|
||||
Countdown Goal:<br>Year: 20 <input name="CY" class="small" type="number"
|
||||
min="0" max="99" required> Month: <input name="CI" class="small" type="number"
|
||||
min="1" max="12" required> Day: <input name="CD" class="small" type="number"
|
||||
min="1" max="31" required><br>Hour: <input name="CH" class="small"
|
||||
type="number" min="0" max="23" required> Minute: <input name="CM" class="small"
|
||||
type="number" min="0" max="59" required> Second: <input name="CS" class="small"
|
||||
type="number" min="0" max="59" required><br><h3>Macro presets</h3><b>
|
||||
Macros have moved!</b><br><i>
|
||||
Presets now also can be used as macros to save both JSON and HTTP API commands.
|
||||
<br>Just enter the preset id below!</i> <i>
|
||||
Use 0 for the default action instead of a preset</i><br>Alexa On/Off Preset:
|
||||
|
Loading…
Reference in New Issue
Block a user