Flash optimizations & class texts.
This commit is contained in:
parent
8608c45309
commit
6ba1795ded
@ -33,9 +33,6 @@
|
|||||||
* 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
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// MQTT topic for sensor values
|
|
||||||
const char MQTT_TOPIC[] = "/motion";
|
|
||||||
|
|
||||||
class PIRsensorSwitch : public Usermod
|
class PIRsensorSwitch : public Usermod
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -76,15 +73,22 @@ private:
|
|||||||
// notification mode for colorUpdated()
|
// notification mode for colorUpdated()
|
||||||
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_CALL_MODE_DIRECT_CHANGE
|
const byte NotifyUpdateMode = NOTIFIER_CALL_MODE_NO_NOTIFY; // NOTIFIER_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;
|
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 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
|
// status of initialisation
|
||||||
bool m_updateConfig = false;
|
bool initDone = false;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _switchOffDelay[];
|
||||||
|
static const char _enabled[];
|
||||||
|
static const char _active[];
|
||||||
|
static const char _inactive[];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* return or change if new PIR sensor state is available
|
* return or change if new PIR sensor state is available
|
||||||
@ -125,7 +129,7 @@ private:
|
|||||||
if (mqtt != nullptr){
|
if (mqtt != nullptr){
|
||||||
char subuf[64];
|
char subuf[64];
|
||||||
strcpy(subuf, mqttDeviceTopic);
|
strcpy(subuf, mqttDeviceTopic);
|
||||||
strcat(subuf, MQTT_TOPIC);
|
strcat_P(subuf, PSTR("/motion"));
|
||||||
mqtt->publish(subuf, 0, true, state);
|
mqtt->publish(subuf, 0, true, state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,12 +196,12 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
// PIR Sensor mode INPUT_PULLUP
|
// PIR Sensor mode INPUT_PULLUP
|
||||||
pinMode(PIRsensorPin, INPUT_PULLUP);
|
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||||
if (m_PIRenabled)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -213,14 +217,8 @@ public:
|
|||||||
*/
|
*/
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
if (!updatePIRsensorState())
|
if (!updatePIRsensorState()) {
|
||||||
{
|
|
||||||
handleOffTimer();
|
handleOffTimer();
|
||||||
if (m_updateConfig)
|
|
||||||
{
|
|
||||||
serializeConfig();
|
|
||||||
m_updateConfig = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,33 +235,32 @@ public:
|
|||||||
if (user.isNull())
|
if (user.isNull())
|
||||||
user = root.createNestedObject("u");
|
user = root.createNestedObject("u");
|
||||||
|
|
||||||
JsonArray infoArr = user.createNestedArray("<i class=\"icons\"></i> PIR sensor state"); //name
|
JsonArray infoArr = user.createNestedArray(F("<i class=\"icons\"></i> PIR sensor state")); //name
|
||||||
String uiDomString = "<button class=\"btn infobtn\" onclick=\"requestJson({PIRenabled:";
|
String uiDomString = F("<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 ? FPSTR(_active) : FPSTR(_inactive)); //value
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uiDomString += "true";
|
uiDomString += "true";
|
||||||
sensorStateInfo = "Disabled!";
|
sensorStateInfo = F("Disabled!");
|
||||||
}
|
}
|
||||||
uiDomString += "});return false;\">";
|
uiDomString += F("});return false;\">");
|
||||||
uiDomString += sensorStateInfo;
|
uiDomString += sensorStateInfo;
|
||||||
uiDomString += "</button>";
|
uiDomString += F("</button>");
|
||||||
infoArr.add(uiDomString); //value
|
infoArr.add(uiDomString); //value
|
||||||
|
|
||||||
if (m_PIRenabled)
|
if (m_PIRenabled)
|
||||||
{
|
{
|
||||||
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
//this code adds "u":{"⏲ switch off timer":uiDomString} to the info object
|
||||||
uiDomString = "<i class=\"icons\"></i> switch off timer<span style=\"display:block;padding-left:25px;\">\
|
uiDomString = F("<i class=\"icons\"></i> switch off timer<span style=\"display:block;padding-left:25px;\">after <input type=\"number\" min=\"1\" max=\"720\" value=\"");
|
||||||
after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|
||||||
uiDomString += (m_switchOffDelay / 60000);
|
uiDomString += (m_switchOffDelay / 60000);
|
||||||
uiDomString += "\" onchange=\"requestJson({PIRoffSec:parseInt(this.value)*60});\">min</span>";
|
uiDomString += F("\" onchange=\"requestJson({PIRoffSec:parseInt(this.value)*60});\">min</span>");
|
||||||
infoArr = user.createNestedArray(uiDomString); //name
|
infoArr = user.createNestedArray(uiDomString); //name
|
||||||
|
|
||||||
// off timer
|
// off timer
|
||||||
@ -274,7 +271,7 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
if (offSeconds >= 3600)
|
if (offSeconds >= 3600)
|
||||||
{
|
{
|
||||||
uiDomString += (offSeconds / 3600);
|
uiDomString += (offSeconds / 3600);
|
||||||
uiDomString += " hours ";
|
uiDomString += F("h ");
|
||||||
offSeconds %= 3600;
|
offSeconds %= 3600;
|
||||||
}
|
}
|
||||||
if (offSeconds >= 60)
|
if (offSeconds >= 60)
|
||||||
@ -288,14 +285,14 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
}
|
}
|
||||||
if (uiDomString.length() > 0)
|
if (uiDomString.length() > 0)
|
||||||
{
|
{
|
||||||
uiDomString += " min ";
|
uiDomString += F("min ");
|
||||||
}
|
}
|
||||||
uiDomString += (offSeconds);
|
uiDomString += (offSeconds);
|
||||||
infoArr.add(uiDomString + " sec");
|
infoArr.add(uiDomString + F("s"));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
infoArr.add("inactive");
|
infoArr.add(FPSTR(_inactive));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -308,8 +305,8 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
*/
|
*/
|
||||||
void addToJsonState(JsonObject &root)
|
void addToJsonState(JsonObject &root)
|
||||||
{
|
{
|
||||||
root[F("PIRenabled")] = m_PIRenabled;
|
root[FPSTR(_enabled)] = m_PIRenabled;
|
||||||
root[F("PIRoffSec")] = (m_switchOffDelay / 1000);
|
root[FPSTR(_switchOffDelay)] = (m_switchOffDelay / 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -320,14 +317,11 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
*/
|
*/
|
||||||
void readFromJsonState(JsonObject &root)
|
void readFromJsonState(JsonObject &root)
|
||||||
{
|
{
|
||||||
if (root[F("PIRoffSec")] != nullptr)
|
if (root[FPSTR(_switchOffDelay)] != nullptr) {
|
||||||
{
|
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root[FPSTR(_switchOffDelay)].as<unsigned long>())));
|
||||||
m_switchOffDelay = (1000 * max(60UL, min(43200UL, root[F("PIRoffSec")].as<unsigned long>())));
|
|
||||||
m_updateConfig = true;
|
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
if (root["pin"] != nullptr)
|
if (root["pin"] != nullptr) {
|
||||||
{
|
|
||||||
int8_t pin = (int)root["pin"];
|
int8_t pin = (int)root["pin"];
|
||||||
// check if pin is OK
|
// check if pin is OK
|
||||||
if (pin != PIRsensorPin && pin>=0 && pinManager.allocatePin(pin,false)) {
|
if (pin != PIRsensorPin && pin>=0 && pinManager.allocatePin(pin,false)) {
|
||||||
@ -344,23 +338,17 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
newPIRsensorState(true, true);
|
newPIRsensorState(true, true);
|
||||||
}
|
}
|
||||||
PIRsensorPin = pin;
|
PIRsensorPin = pin;
|
||||||
m_updateConfig = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (root[F("PIRenabled")] != nullptr)
|
if (root[FPSTR(_enabled)] != nullptr) {
|
||||||
{
|
if (root[FPSTR(_enabled)] && !m_PIRenabled && PIRsensorPin >= 0) {
|
||||||
if (root[F("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 && PIRsensorPin >= 0) {
|
||||||
else if (m_PIRenabled)
|
|
||||||
{
|
|
||||||
detachInterrupt(PIRsensorPin);
|
detachInterrupt(PIRsensorPin);
|
||||||
}
|
}
|
||||||
m_PIRenabled = root[F("PIRenabled")];
|
m_PIRenabled = root[FPSTR(_enabled)];
|
||||||
m_updateConfig = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -369,10 +357,11 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
*/
|
*/
|
||||||
void addToConfig(JsonObject &root)
|
void addToConfig(JsonObject &root)
|
||||||
{
|
{
|
||||||
JsonObject top = root.createNestedObject(F("PIRsensorSwitch"));
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||||
top[F("PIRenabled")] = m_PIRenabled;
|
top[FPSTR(_enabled)] = m_PIRenabled;
|
||||||
top[F("PIRoffSec")] = m_switchOffDelay;
|
top[FPSTR(_switchOffDelay)] = m_switchOffDelay / 1000;
|
||||||
top["pin"] = PIRsensorPin;
|
top["pin"] = PIRsensorPin;
|
||||||
|
DEBUG_PRINTLN(F("PIR config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -381,12 +370,59 @@ after <input type=\"number\" min=\"1\" max=\"720\" value=\"";
|
|||||||
*/
|
*/
|
||||||
void readFromConfig(JsonObject &root)
|
void readFromConfig(JsonObject &root)
|
||||||
{
|
{
|
||||||
JsonObject top = root[F("PIRsensorSwitch")];
|
bool oldEnabled = m_PIRenabled;
|
||||||
if (!top.isNull() && top["pin"] != nullptr) {
|
int8_t oldPin = PIRsensorPin;
|
||||||
PIRsensorPin = (int)top["pin"];
|
|
||||||
|
JsonObject top = root[FPSTR(_name)];
|
||||||
|
if (top.isNull()) return;
|
||||||
|
|
||||||
|
if (top["pin"] != nullptr) {
|
||||||
|
PIRsensorPin = min(39,max(-1,top["pin"].as<int>())); // check bounds
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top[FPSTR(_enabled)] != nullptr) {
|
||||||
|
if (top[FPSTR(_enabled)].is<bool>()) {
|
||||||
|
m_PIRenabled = top[FPSTR(_enabled)].as<bool>(); // reading from cfg.json
|
||||||
|
} else {
|
||||||
|
// change from settings page
|
||||||
|
String str = top[FPSTR(_enabled)]; // checkbox -> off or on
|
||||||
|
m_PIRenabled = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (top[FPSTR(_switchOffDelay)] != nullptr) {
|
||||||
|
m_switchOffDelay = (top[FPSTR(_switchOffDelay)].as<int>() * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!initDone) {
|
||||||
|
// reading config prior to setup()
|
||||||
|
DEBUG_PRINTLN(F("PIR config loaded."));
|
||||||
|
} else {
|
||||||
|
if (oldPin != PIRsensorPin || oldEnabled != m_PIRenabled) {
|
||||||
|
if (oldEnabled) {
|
||||||
|
// remove old ISR if disabling usermod
|
||||||
|
detachInterrupt(oldPin);
|
||||||
|
}
|
||||||
|
// check if pin is OK
|
||||||
|
if (oldPin != PIRsensorPin && oldPin >= 0) {
|
||||||
|
// if we are changing pin in settings page
|
||||||
|
// deallocate old pin
|
||||||
|
pinManager.deallocatePin(oldPin);
|
||||||
|
if (pinManager.allocatePin(PIRsensorPin,false)) {
|
||||||
|
pinMode(PIRsensorPin, INPUT_PULLUP);
|
||||||
|
} else {
|
||||||
|
// allocation failed
|
||||||
|
PIRsensorPin = -1;
|
||||||
|
m_PIRenabled = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (m_PIRenabled) {
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIRsensorPin), ISR_PIRstateChange, CHANGE);
|
||||||
|
newPIRsensorState(true, true);
|
||||||
|
}
|
||||||
|
DEBUG_PRINTLN(F("PIR config (re)loaded."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_PIRenabled = (top[F("PIRenabled")] != nullptr ? top[F("PIRenabled")] : true);
|
|
||||||
m_switchOffDelay = top[F("PIRoffSec")] | m_switchOffDelay;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -425,4 +461,11 @@ PIRsensorSwitch *PIRsensorSwitch::PIRsensorSwitchInstance(PIRsensorSwitch *pInst
|
|||||||
s_pPIRsensorSwitch = pInstance;
|
s_pPIRsensorSwitch = pInstance;
|
||||||
}
|
}
|
||||||
return s_pPIRsensorSwitch;
|
return s_pPIRsensorSwitch;
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
const char PIRsensorSwitch::_name[] PROGMEM = "PIRsensorSwitch";
|
||||||
|
const char PIRsensorSwitch::_switchOffDelay[] PROGMEM = "PIRoffSec";
|
||||||
|
const char PIRsensorSwitch::_enabled[] PROGMEM = "PIRenabled";
|
||||||
|
const char PIRsensorSwitch::_active[] PROGMEM = "active";
|
||||||
|
const char PIRsensorSwitch::_inactive[] PROGMEM = "inactive";
|
||||||
|
@ -23,9 +23,6 @@
|
|||||||
#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000
|
#define USERMOD_DALLASTEMPERATURE_FIRST_MEASUREMENT_AT 20000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// strings
|
|
||||||
const char _um_Temperature[] PROGMEM = "Temperature";
|
|
||||||
|
|
||||||
class UsermodTemperature : public Usermod {
|
class UsermodTemperature : public Usermod {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -54,6 +51,11 @@ class UsermodTemperature : public Usermod {
|
|||||||
// temperature if flashed to a board without a sensor attached
|
// temperature if flashed to a board without a sensor attached
|
||||||
bool disabled = false;
|
bool disabled = false;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _enabled[];
|
||||||
|
static const char _readInterval[];
|
||||||
|
|
||||||
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
//Dallas sensor quick reading. Credit to - Author: Peter Scargill, August 17th, 2013
|
||||||
int16_t readDallas() {
|
int16_t readDallas() {
|
||||||
byte i;
|
byte i;
|
||||||
@ -180,7 +182,7 @@ class UsermodTemperature : public Usermod {
|
|||||||
JsonObject user = root["u"];
|
JsonObject user = root["u"];
|
||||||
if (user.isNull()) user = root.createNestedObject("u");
|
if (user.isNull()) user = root.createNestedObject("u");
|
||||||
|
|
||||||
JsonArray temp = user.createNestedArray(FPSTR(_um_Temperature));
|
JsonArray temp = user.createNestedArray(FPSTR(_name));
|
||||||
//temp.add(F("Loaded."));
|
//temp.add(F("Loaded."));
|
||||||
|
|
||||||
if (!getTemperatureComplete) {
|
if (!getTemperatureComplete) {
|
||||||
@ -215,20 +217,20 @@ class UsermodTemperature : public Usermod {
|
|||||||
* Values in the state object may be modified by connected clients
|
* Values in the state object may be modified by connected clients
|
||||||
* Read "<usermodname>_<usermodparam>" from json state and and change settings (i.e. GPIO pin) used.
|
* Read "<usermodname>_<usermodparam>" from json state and and change settings (i.e. GPIO pin) used.
|
||||||
*/
|
*/
|
||||||
void readFromJsonState(JsonObject &root) {
|
//void readFromJsonState(JsonObject &root) {
|
||||||
if (!initDone) return; // prevent crash on boot applyPreset()
|
// if (!initDone) return; // prevent crash on boot applyPreset()
|
||||||
}
|
//}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
* addToConfig() (called from set.cpp) stores persistent properties to cfg.json
|
||||||
*/
|
*/
|
||||||
void addToConfig(JsonObject &root) {
|
void addToConfig(JsonObject &root) {
|
||||||
// we add JSON object: {"Temperature": {"pin": 0, "degC": true}}
|
// we add JSON object: {"Temperature": {"pin": 0, "degC": true}}
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_um_Temperature)); // usermodname
|
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||||
top[F("enabled")] = !disabled;
|
top[FPSTR(_enabled)] = !disabled;
|
||||||
top["pin"] = temperaturePin; // usermodparam
|
top["pin"] = temperaturePin; // usermodparam
|
||||||
top["degC"] = degC; // usermodparam
|
top["degC"] = degC; // usermodparam
|
||||||
top[F("read-interval-s")] = readingInterval / 1000;
|
top[FPSTR(_readInterval)] = readingInterval / 1000;
|
||||||
DEBUG_PRINTLN(F("Temperature config saved."));
|
DEBUG_PRINTLN(F("Temperature config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -237,27 +239,31 @@ class UsermodTemperature : public Usermod {
|
|||||||
*/
|
*/
|
||||||
void readFromConfig(JsonObject &root) {
|
void readFromConfig(JsonObject &root) {
|
||||||
// we look for JSON object: {"Temperature": {"pin": 0, "degC": true}}
|
// we look for JSON object: {"Temperature": {"pin": 0, "degC": true}}
|
||||||
JsonObject top = root[FPSTR(_um_Temperature)];
|
JsonObject top = root[FPSTR(_name)];
|
||||||
int8_t newTemperaturePin = temperaturePin;
|
int8_t newTemperaturePin = temperaturePin;
|
||||||
|
|
||||||
if (!top.isNull() && top["pin"] != nullptr) {
|
if (!top.isNull() && top["pin"] != nullptr) {
|
||||||
if (top[F("enabled")].is<bool>()) {
|
if (top[FPSTR(_enabled)].is<bool>()) {
|
||||||
disabled = !top[F("enabled")].as<bool>();
|
disabled = !top[FPSTR(_enabled)].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
String str = top[F("enabled")]; // checkbox -> off or on
|
String str = top[FPSTR(_enabled)]; // checkbox -> off or on
|
||||||
disabled = (bool)(str=="off"); // off is guaranteed to be present
|
disabled = (bool)(str=="off"); // off is guaranteed to be present
|
||||||
}
|
}
|
||||||
newTemperaturePin = min(39,max(-1,top["pin"].as<int>()));
|
newTemperaturePin = min(39,max(-1,top["pin"].as<int>()));
|
||||||
if (top["degC"].is<bool>()) {
|
if (top["degC"].is<bool>()) {
|
||||||
|
// reading from cfg.json
|
||||||
degC = top["degC"].as<bool>();
|
degC = top["degC"].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
|
// new configuration from set.cpp
|
||||||
String str = top["degC"]; // checkbox -> off or on
|
String str = top["degC"]; // checkbox -> off or on
|
||||||
degC = (bool)(str!="off"); // off is guaranteed to be present
|
degC = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
}
|
}
|
||||||
readingInterval = min(120,max(10,top[F("read-interval-s")].as<int>())) * 1000;
|
readingInterval = min(120,max(10,top[FPSTR(_readInterval)].as<int>())) * 1000; // convert to ms
|
||||||
DEBUG_PRINTLN(F("Temperature config loaded."));
|
DEBUG_PRINTLN(F("Temperature config (re)loaded."));
|
||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("No config found. (Using defaults.)"));
|
DEBUG_PRINTLN(F("No config found. (Using defaults.)"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!initDone) {
|
if (!initDone) {
|
||||||
// first run: reading from cfg.json
|
// first run: reading from cfg.json
|
||||||
temperaturePin = newTemperaturePin;
|
temperaturePin = newTemperaturePin;
|
||||||
@ -279,3 +285,8 @@ class UsermodTemperature : public Usermod {
|
|||||||
return USERMOD_ID_TEMPERATURE;
|
return USERMOD_ID_TEMPERATURE;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
const char UsermodTemperature::_name[] PROGMEM = "Temperature";
|
||||||
|
const char UsermodTemperature::_enabled[] PROGMEM = "enabled";
|
||||||
|
const char UsermodTemperature::_readInterval[] PROGMEM = "read-interval-s";
|
@ -1,226 +1,231 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "wled.h"
|
#include "wled.h"
|
||||||
|
|
||||||
// v2 Usermod to automatically save settings
|
// v2 Usermod to automatically save settings
|
||||||
// to configurable preset after a change to any of
|
// to configurable preset after a change to any of
|
||||||
//
|
//
|
||||||
// * brightness
|
// * brightness
|
||||||
// * effect speed
|
// * effect speed
|
||||||
// * effect intensity
|
// * effect intensity
|
||||||
// * mode (effect)
|
// * mode (effect)
|
||||||
// * palette
|
// * palette
|
||||||
//
|
//
|
||||||
// but it will wait for configurable number of seconds, a "settle"
|
// but it will wait for configurable number of seconds, a "settle"
|
||||||
// period in case there are other changes (any change will
|
// period in case there are other changes (any change will
|
||||||
// extend the "settle" window).
|
// extend the "settle" window).
|
||||||
//
|
//
|
||||||
// It can be configured to load auto saved preset at startup,
|
// It can be configured to load auto saved preset at startup,
|
||||||
// during the first `loop()`.
|
// during the first `loop()`.
|
||||||
//
|
//
|
||||||
// AutoSaveUsermod is standalone, but if FourLineDisplayUsermod
|
// AutoSaveUsermod is standalone, but if FourLineDisplayUsermod
|
||||||
// is installed, it will notify the user of the saved changes.
|
// is installed, it will notify the user of the saved changes.
|
||||||
|
|
||||||
// format: "~ MM-DD HH:MM:SS ~"
|
// format: "~ MM-DD HH:MM:SS ~"
|
||||||
#define PRESET_NAME_BUFFER_SIZE 25
|
#define PRESET_NAME_BUFFER_SIZE 25
|
||||||
|
|
||||||
// strings
|
class AutoSaveUsermod : public Usermod {
|
||||||
const char _um_AutoSave[] PROGMEM = "Autosave";
|
|
||||||
const char _autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec";
|
private:
|
||||||
const char _autoSavePreset[] PROGMEM = "autoSavePreset";
|
|
||||||
const char _autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot";
|
bool firstLoop = true;
|
||||||
|
bool initDone = false;
|
||||||
class AutoSaveUsermod : public Usermod {
|
|
||||||
|
// configurable parameters
|
||||||
private:
|
unsigned long autoSaveAfterSec = 15; // 15s by default
|
||||||
|
uint8_t autoSavePreset = 250; // last possible preset
|
||||||
bool firstLoop = true;
|
bool applyAutoSaveOnBoot = false; // do we load auto-saved preset on boot?
|
||||||
bool initDone = false;
|
|
||||||
|
// If we've detected the need to auto save, this will be non zero.
|
||||||
// configurable parameters
|
unsigned long autoSaveAfter = 0;
|
||||||
unsigned long autoSaveAfterSec = 15; // 15s by default
|
|
||||||
uint8_t autoSavePreset = 250; // last possible preset
|
uint8_t knownBrightness = 0;
|
||||||
bool applyAutoSaveOnBoot = false; // do we load auto-saved preset on boot?
|
uint8_t knownEffectSpeed = 0;
|
||||||
|
uint8_t knownEffectIntensity = 0;
|
||||||
// If we've detected the need to auto save, this will be non zero.
|
uint8_t knownMode = 0;
|
||||||
unsigned long autoSaveAfter = 0;
|
uint8_t knownPalette = 0;
|
||||||
|
|
||||||
uint8_t knownBrightness = 0;
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
uint8_t knownEffectSpeed = 0;
|
FourLineDisplayUsermod* display;
|
||||||
uint8_t knownEffectIntensity = 0;
|
#endif
|
||||||
uint8_t knownMode = 0;
|
|
||||||
uint8_t knownPalette = 0;
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
static const char _autoSaveAfterSec[];
|
||||||
FourLineDisplayUsermod* display;
|
static const char _autoSavePreset[];
|
||||||
#endif
|
static const char _autoSaveApplyOnBoot[];
|
||||||
|
|
||||||
void inline saveSettings() {
|
void inline saveSettings() {
|
||||||
char presetNameBuffer[PRESET_NAME_BUFFER_SIZE];
|
char presetNameBuffer[PRESET_NAME_BUFFER_SIZE];
|
||||||
updateLocalTime();
|
updateLocalTime();
|
||||||
sprintf_P(presetNameBuffer,
|
sprintf_P(presetNameBuffer,
|
||||||
PSTR("~ %02d-%02d %02d:%02d:%02d ~"),
|
PSTR("~ %02d-%02d %02d:%02d:%02d ~"),
|
||||||
month(localTime), day(localTime),
|
month(localTime), day(localTime),
|
||||||
hour(localTime), minute(localTime), second(localTime));
|
hour(localTime), minute(localTime), second(localTime));
|
||||||
savePreset(autoSavePreset, true, presetNameBuffer);
|
savePreset(autoSavePreset, true, presetNameBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void inline displayOverlay() {
|
void inline displayOverlay() {
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
if (display != nullptr) {
|
if (display != nullptr) {
|
||||||
display->wakeDisplay();
|
display->wakeDisplay();
|
||||||
display->overlay("Settings", "Auto Saved", 1500);
|
display->overlay("Settings", "Auto Saved", 1500);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// gets called once at boot. Do all initialization that doesn't depend on
|
// gets called once at boot. Do all initialization that doesn't depend on
|
||||||
// network here
|
// network here
|
||||||
void setup() {
|
void setup() {
|
||||||
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
#ifdef USERMOD_FOUR_LINE_DISPLAY
|
||||||
// This Usermod has enhanced funcionality if
|
// This Usermod has enhanced funcionality if
|
||||||
// FourLineDisplayUsermod is available.
|
// FourLineDisplayUsermod is available.
|
||||||
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
display = (FourLineDisplayUsermod*) usermods.lookup(USERMOD_ID_FOUR_LINE_DISP);
|
||||||
#endif
|
#endif
|
||||||
initDone = true;
|
initDone = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// gets called every time WiFi is (re-)connected. Initialize own network
|
// gets called every time WiFi is (re-)connected. Initialize own network
|
||||||
// interfaces here
|
// interfaces here
|
||||||
void connected() {}
|
void connected() {}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Da loop.
|
* Da loop.
|
||||||
*/
|
*/
|
||||||
void loop() {
|
void loop() {
|
||||||
if (!autoSaveAfterSec) return; // setting 0 as autosave seconds disables autosave
|
if (!autoSaveAfterSec) return; // setting 0 as autosave seconds disables autosave
|
||||||
|
|
||||||
unsigned long now = millis();
|
unsigned long now = millis();
|
||||||
uint8_t currentMode = strip.getMode();
|
uint8_t currentMode = strip.getMode();
|
||||||
uint8_t currentPalette = strip.getSegment(0).palette;
|
uint8_t currentPalette = strip.getSegment(0).palette;
|
||||||
if (firstLoop) {
|
if (firstLoop) {
|
||||||
firstLoop = false;
|
firstLoop = false;
|
||||||
if (applyAutoSaveOnBoot) applyPreset(autoSavePreset);
|
if (applyAutoSaveOnBoot) applyPreset(autoSavePreset);
|
||||||
knownBrightness = bri;
|
knownBrightness = bri;
|
||||||
knownEffectSpeed = effectSpeed;
|
knownEffectSpeed = effectSpeed;
|
||||||
knownEffectIntensity = effectIntensity;
|
knownEffectIntensity = effectIntensity;
|
||||||
knownMode = currentMode;
|
knownMode = currentMode;
|
||||||
knownPalette = currentPalette;
|
knownPalette = currentPalette;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long wouldAutoSaveAfter = now + autoSaveAfterSec*1000;
|
unsigned long wouldAutoSaveAfter = now + autoSaveAfterSec*1000;
|
||||||
if (knownBrightness != bri) {
|
if (knownBrightness != bri) {
|
||||||
knownBrightness = bri;
|
knownBrightness = bri;
|
||||||
autoSaveAfter = wouldAutoSaveAfter;
|
autoSaveAfter = wouldAutoSaveAfter;
|
||||||
} else if (knownEffectSpeed != effectSpeed) {
|
} else if (knownEffectSpeed != effectSpeed) {
|
||||||
knownEffectSpeed = effectSpeed;
|
knownEffectSpeed = effectSpeed;
|
||||||
autoSaveAfter = wouldAutoSaveAfter;
|
autoSaveAfter = wouldAutoSaveAfter;
|
||||||
} else if (knownEffectIntensity != effectIntensity) {
|
} else if (knownEffectIntensity != effectIntensity) {
|
||||||
knownEffectIntensity = effectIntensity;
|
knownEffectIntensity = effectIntensity;
|
||||||
autoSaveAfter = wouldAutoSaveAfter;
|
autoSaveAfter = wouldAutoSaveAfter;
|
||||||
} else if (knownMode != currentMode) {
|
} else if (knownMode != currentMode) {
|
||||||
knownMode = currentMode;
|
knownMode = currentMode;
|
||||||
autoSaveAfter = wouldAutoSaveAfter;
|
autoSaveAfter = wouldAutoSaveAfter;
|
||||||
} else if (knownPalette != currentPalette) {
|
} else if (knownPalette != currentPalette) {
|
||||||
knownPalette = currentPalette;
|
knownPalette = currentPalette;
|
||||||
autoSaveAfter = wouldAutoSaveAfter;
|
autoSaveAfter = wouldAutoSaveAfter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (autoSaveAfter && now > autoSaveAfter) {
|
if (autoSaveAfter && now > autoSaveAfter) {
|
||||||
autoSaveAfter = 0;
|
autoSaveAfter = 0;
|
||||||
// Time to auto save. You may have some flickry?
|
// Time to auto save. You may have some flickry?
|
||||||
saveSettings();
|
saveSettings();
|
||||||
displayOverlay();
|
displayOverlay();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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
|
||||||
*/
|
*/
|
||||||
//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");
|
||||||
//JsonArray data = user.createNestedArray(F("Autosave"));
|
//JsonArray data = user.createNestedArray(F("Autosave"));
|
||||||
//data.add(F("Loaded."));
|
//data.add(F("Loaded."));
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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) {
|
||||||
// if (!initDone) return; // prevent crash on boot applyPreset()
|
// if (!initDone) return; // prevent crash on boot applyPreset()
|
||||||
//}
|
//}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
* addToConfig() can be used to add custom persistent settings to the cfg.json file in the "um" (usermod) object.
|
||||||
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
* It will be called by WLED when settings are actually saved (for example, LED settings are saved)
|
||||||
* If you want to force saving the current state, use serializeConfig() in your loop().
|
* If you want to force saving the current state, use serializeConfig() in your loop().
|
||||||
*
|
*
|
||||||
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
* CAUTION: serializeConfig() will initiate a filesystem write operation.
|
||||||
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
* It might cause the LEDs to stutter and will cause flash wear if called too often.
|
||||||
* Use it sparingly and always in the loop, never in network callbacks!
|
* Use it sparingly and always in the loop, never in network callbacks!
|
||||||
*
|
*
|
||||||
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
* addToConfig() will also not yet add your setting to one of the settings pages automatically.
|
||||||
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
* To make that work you still have to add the setting to the HTML, xml.cpp and set.cpp manually.
|
||||||
*
|
*
|
||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||||
*/
|
*/
|
||||||
void addToConfig(JsonObject& root) {
|
void addToConfig(JsonObject& root) {
|
||||||
// we add JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}}
|
// we add JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}}
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_um_AutoSave)); // usermodname
|
JsonObject top = root.createNestedObject(FPSTR(_name)); // usermodname
|
||||||
top[FPSTR(_autoSaveAfterSec)] = autoSaveAfterSec; // usermodparam
|
top[FPSTR(_autoSaveAfterSec)] = autoSaveAfterSec; // usermodparam
|
||||||
top[FPSTR(_autoSavePreset)] = autoSavePreset; // usermodparam
|
top[FPSTR(_autoSavePreset)] = autoSavePreset; // usermodparam
|
||||||
top[FPSTR(_autoSaveApplyOnBoot)] = applyAutoSaveOnBoot;
|
top[FPSTR(_autoSaveApplyOnBoot)] = applyAutoSaveOnBoot;
|
||||||
DEBUG_PRINTLN(F("Autosave config saved."));
|
DEBUG_PRINTLN(F("Autosave config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
* readFromConfig() can be used to read back the custom settings you added with addToConfig().
|
||||||
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
* This is called by WLED when settings are loaded (currently this only happens once immediately after boot)
|
||||||
*
|
*
|
||||||
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
* readFromConfig() is called BEFORE setup(). This means you can use your persistent values in setup() (e.g. pin assignments, buffer sizes),
|
||||||
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
* but also that if you want to write persistent values to a dynamic buffer, you'd need to allocate it here instead of in setup.
|
||||||
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
* If you don't know what that is, don't fret. It most likely doesn't affect your use case :)
|
||||||
*/
|
*/
|
||||||
void readFromConfig(JsonObject& root) {
|
void readFromConfig(JsonObject& root) {
|
||||||
// we look for JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}}
|
// we look for JSON object: {"Autosave": {"autoSaveAfterSec": 10, "autoSavePreset": 99}}
|
||||||
JsonObject top = root[FPSTR(_um_AutoSave)];
|
JsonObject top = root[FPSTR(_name)];
|
||||||
if (!top.isNull() && top[FPSTR(_autoSaveAfterSec)] != nullptr) {
|
if (!top.isNull() && top[FPSTR(_autoSaveAfterSec)] != nullptr) {
|
||||||
autoSaveAfterSec = top[FPSTR(_autoSaveAfterSec)].as<int>();
|
autoSaveAfterSec = top[FPSTR(_autoSaveAfterSec)].as<int>();
|
||||||
autoSavePreset = top[FPSTR(_autoSavePreset)].as<int>();
|
autoSavePreset = top[FPSTR(_autoSavePreset)].as<int>();
|
||||||
if (top[FPSTR(_autoSaveApplyOnBoot)].is<bool>()) {
|
if (top[FPSTR(_autoSaveApplyOnBoot)].is<bool>()) {
|
||||||
// reading from cfg.json
|
// reading from cfg.json
|
||||||
applyAutoSaveOnBoot = top[FPSTR(_autoSaveApplyOnBoot)].as<bool>();
|
applyAutoSaveOnBoot = top[FPSTR(_autoSaveApplyOnBoot)].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
// reading from POST message
|
// reading from POST message
|
||||||
String str = top[FPSTR(_autoSaveApplyOnBoot)]; // checkbox -> off or on
|
String str = top[FPSTR(_autoSaveApplyOnBoot)]; // checkbox -> off or on
|
||||||
applyAutoSaveOnBoot = (bool)(str!="off"); // off is guaranteed to be present
|
applyAutoSaveOnBoot = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
}
|
}
|
||||||
DEBUG_PRINTLN(F("Autosave config (re)loaded."));
|
DEBUG_PRINTLN(F("Autosave config (re)loaded."));
|
||||||
} else {
|
} else {
|
||||||
DEBUG_PRINTLN(F("No config found. (Using defaults.)"));
|
DEBUG_PRINTLN(F("No config found. (Using defaults.)"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 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_AUTO_SAVE;
|
return USERMOD_ID_AUTO_SAVE;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
};
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
const char AutoSaveUsermod::_name[] PROGMEM = "Autosave";
|
||||||
|
const char AutoSaveUsermod::_autoSaveAfterSec[] PROGMEM = "autoSaveAfterSec";
|
||||||
|
const char AutoSaveUsermod::_autoSavePreset[] PROGMEM = "autoSavePreset";
|
||||||
|
const char AutoSaveUsermod::_autoSaveApplyOnBoot[] PROGMEM = "autoSaveApplyOnBoot";
|
||||||
|
@ -67,15 +67,6 @@ typedef enum {
|
|||||||
SH1106 // U8X8_SH1106_128X64_WINSTAR_HW_I2C
|
SH1106 // U8X8_SH1106_128X64_WINSTAR_HW_I2C
|
||||||
} DisplayType;
|
} DisplayType;
|
||||||
|
|
||||||
// strings
|
|
||||||
const char _um_4LineDisplay[] PROGMEM = "4LineDisplay";
|
|
||||||
const char _4LD_contrast[] PROGMEM = "contrast";
|
|
||||||
const char _4LD_refreshRate[] PROGMEM = "refreshRate";
|
|
||||||
const char _4LD_screenTimeOut[] PROGMEM = "screenTimeOut";
|
|
||||||
const char _4LD_flip[] PROGMEM = "flip";
|
|
||||||
const char _4LD_sleepMode[] PROGMEM = "sleepMode";
|
|
||||||
const char _4LD_clockMode[] PROGMEM = "clockMode";
|
|
||||||
|
|
||||||
class FourLineDisplayUsermod : public Usermod {
|
class FourLineDisplayUsermod : public Usermod {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -118,6 +109,15 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
|
// Set to 2 or 3 to mark lines 2 or 3. Other values ignored.
|
||||||
byte markLineNum = 0;
|
byte markLineNum = 0;
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
static const char _name[];
|
||||||
|
static const char _contrast[];
|
||||||
|
static const char _refreshRate[];
|
||||||
|
static const char _screenTimeOut[];
|
||||||
|
static const char _flip[];
|
||||||
|
static const char _sleepMode[];
|
||||||
|
static const char _clockMode[];
|
||||||
|
|
||||||
// If display does not work or looks corrupted check the
|
// If display does not work or looks corrupted check the
|
||||||
// constructor reference:
|
// constructor reference:
|
||||||
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
// https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
|
||||||
@ -647,17 +647,17 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
* I highly recommend checking out the basics of ArduinoJson serialization and deserialization in order to use custom settings!
|
||||||
*/
|
*/
|
||||||
void addToConfig(JsonObject& root) {
|
void addToConfig(JsonObject& root) {
|
||||||
JsonObject top = root.createNestedObject(FPSTR(_um_4LineDisplay));
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||||||
JsonArray i2c_pin = top.createNestedArray("pin");
|
JsonArray i2c_pin = top.createNestedArray("pin");
|
||||||
i2c_pin.add(sclPin);
|
i2c_pin.add(sclPin);
|
||||||
i2c_pin.add(sdaPin);
|
i2c_pin.add(sdaPin);
|
||||||
top["type"] = type;
|
top["type"] = type;
|
||||||
top[FPSTR(_4LD_flip)] = (bool) flip;
|
top[FPSTR(_flip)] = (bool) flip;
|
||||||
top[FPSTR(_4LD_contrast)] = contrast;
|
top[FPSTR(_contrast)] = contrast;
|
||||||
top[FPSTR(_4LD_refreshRate)] = refreshRate/1000;
|
top[FPSTR(_refreshRate)] = refreshRate/1000;
|
||||||
top[FPSTR(_4LD_screenTimeOut)] = screenTimeout/1000;
|
top[FPSTR(_screenTimeOut)] = screenTimeout/1000;
|
||||||
top[FPSTR(_4LD_sleepMode)] = (bool) sleepMode;
|
top[FPSTR(_sleepMode)] = (bool) sleepMode;
|
||||||
top[FPSTR(_4LD_clockMode)] = (bool) clockMode;
|
top[FPSTR(_clockMode)] = (bool) clockMode;
|
||||||
DEBUG_PRINTLN(F("4 Line Display config saved."));
|
DEBUG_PRINTLN(F("4 Line Display config saved."));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -675,33 +675,33 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
int8_t newScl = sclPin;
|
int8_t newScl = sclPin;
|
||||||
int8_t newSda = sdaPin;
|
int8_t newSda = sdaPin;
|
||||||
|
|
||||||
JsonObject top = root[FPSTR(_um_4LineDisplay)];
|
JsonObject top = root[FPSTR(_name)];
|
||||||
if (!top.isNull() && top["pin"] != nullptr) {
|
if (!top.isNull() && top["pin"] != nullptr) {
|
||||||
newScl = top["pin"][0];
|
newScl = top["pin"][0];
|
||||||
newSda = top["pin"][1];
|
newSda = top["pin"][1];
|
||||||
newType = top["type"];
|
newType = top["type"];
|
||||||
lineHeight = type==SH1106 ? 2 : 1;
|
lineHeight = type==SH1106 ? 2 : 1;
|
||||||
if (top[FPSTR(_4LD_flip)].is<bool>()) {
|
if (top[FPSTR(_flip)].is<bool>()) {
|
||||||
flip = top[FPSTR(_4LD_flip)].as<bool>();
|
flip = top[FPSTR(_flip)].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
String str = top[FPSTR(_4LD_flip)]; // checkbox -> off or on
|
String str = top[FPSTR(_flip)]; // checkbox -> off or on
|
||||||
flip = (bool)(str!="off"); // off is guaranteed to be present
|
flip = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
needRedraw |= true;
|
needRedraw |= true;
|
||||||
}
|
}
|
||||||
contrast = top[FPSTR(_4LD_contrast)].as<int>();
|
contrast = top[FPSTR(_contrast)].as<int>();
|
||||||
refreshRate = top[FPSTR(_4LD_refreshRate)].as<int>() * 1000;
|
refreshRate = top[FPSTR(_refreshRate)].as<int>() * 1000;
|
||||||
screenTimeout = top[FPSTR(_4LD_screenTimeOut)].as<int>() * 1000;
|
screenTimeout = top[FPSTR(_screenTimeOut)].as<int>() * 1000;
|
||||||
if (top[FPSTR(_4LD_sleepMode)].is<bool>()) {
|
if (top[FPSTR(_sleepMode)].is<bool>()) {
|
||||||
sleepMode = top[FPSTR(_4LD_sleepMode)].as<bool>();
|
sleepMode = top[FPSTR(_sleepMode)].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
String str = top[FPSTR(_4LD_sleepMode)]; // checkbox -> off or on
|
String str = top[FPSTR(_sleepMode)]; // checkbox -> off or on
|
||||||
sleepMode = (bool)(str!="off"); // off is guaranteed to be present
|
sleepMode = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
needRedraw |= true;
|
needRedraw |= true;
|
||||||
}
|
}
|
||||||
if (top[FPSTR(_4LD_clockMode)].is<bool>()) {
|
if (top[FPSTR(_clockMode)].is<bool>()) {
|
||||||
clockMode = top[FPSTR(_4LD_clockMode)].as<bool>();
|
clockMode = top[FPSTR(_clockMode)].as<bool>();
|
||||||
} else {
|
} else {
|
||||||
String str = top[FPSTR(_4LD_clockMode)]; // checkbox -> off or on
|
String str = top[FPSTR(_clockMode)]; // checkbox -> off or on
|
||||||
clockMode = (bool)(str!="off"); // off is guaranteed to be present
|
clockMode = (bool)(str!="off"); // off is guaranteed to be present
|
||||||
needRedraw |= true;
|
needRedraw |= true;
|
||||||
}
|
}
|
||||||
@ -746,4 +746,13 @@ class FourLineDisplayUsermod : public Usermod {
|
|||||||
uint16_t getId() {
|
uint16_t getId() {
|
||||||
return USERMOD_ID_FOUR_LINE_DISP;
|
return USERMOD_ID_FOUR_LINE_DISP;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// strings to reduce flash memory usage (used more than twice)
|
||||||
|
const char FourLineDisplayUsermod::_name[] PROGMEM = "4LineDisplay";
|
||||||
|
const char FourLineDisplayUsermod::_contrast[] PROGMEM = "contrast";
|
||||||
|
const char FourLineDisplayUsermod::_refreshRate[] PROGMEM = "refreshRate";
|
||||||
|
const char FourLineDisplayUsermod::_screenTimeOut[] PROGMEM = "screenTimeOut";
|
||||||
|
const char FourLineDisplayUsermod::_flip[] PROGMEM = "flip";
|
||||||
|
const char FourLineDisplayUsermod::_sleepMode[] PROGMEM = "sleepMode";
|
||||||
|
const char FourLineDisplayUsermod::_clockMode[] PROGMEM = "clockMode";
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// version code in format yymmddb (b = daily build)
|
// version code in format yymmddb (b = daily build)
|
||||||
#define VERSION 2104210
|
#define VERSION 2104221
|
||||||
|
|
||||||
//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
|
||||||
|
Loading…
Reference in New Issue
Block a user