kopia lustrzana https://github.com/Aircoookie/WLED
197 wiersze
7.1 KiB
C++
197 wiersze
7.1 KiB
C++
![]() |
#include "wled.h"
|
||
|
|
||
|
class InternalTemperatureUsermod : public Usermod
|
||
|
{
|
||
|
|
||
|
private:
|
||
![]() |
static constexpr unsigned long minLoopInterval = 1000; // minimum allowable interval (ms)
|
||
![]() |
unsigned long loopInterval = 10000;
|
||
|
unsigned long lastTime = 0;
|
||
|
bool isEnabled = false;
|
||
![]() |
float temperature = 0.0f;
|
||
![]() |
uint8_t previousPlaylist = 0; // Stores the playlist that was active before high-temperature activation
|
||
|
uint8_t previousPreset = 0; // Stores the preset that was active before high-temperature activation
|
||
![]() |
uint8_t presetToActivate = 0; // Preset to activate when temp goes above threshold (0 = disabled)
|
||
![]() |
float activationThreshold = 95.0f; // Temperature threshold to trigger high-temperature actions
|
||
![]() |
float resetMargin = 2.0f; // Margin below the activation threshold (Prevents frequent toggling when close to threshold)
|
||
![]() |
bool isAboveThreshold = false; // Flag to track if the high temperature preset is currently active
|
||
![]() |
|
||
|
static const char _name[];
|
||
|
static const char _enabled[];
|
||
|
static const char _loopInterval[];
|
||
![]() |
static const char _activationThreshold[];
|
||
|
static const char _presetToActivate[];
|
||
![]() |
|
||
![]() |
// any private methods should go here (non-inline method should be defined out of class)
|
||
![]() |
void publishMqtt(const char *state, bool retain = false); // example for publishing MQTT message
|
||
|
|
||
|
public:
|
||
|
void setup()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void loop()
|
||
|
{
|
||
|
// if usermod is disabled or called during strip updating just exit
|
||
|
// NOTE: on very long strips strip.isUpdating() may always return true so update accordingly
|
||
|
if (!isEnabled || strip.isUpdating() || millis() - lastTime <= loopInterval)
|
||
|
return;
|
||
|
|
||
|
lastTime = millis();
|
||
|
|
||
![]() |
// Measure the temperature
|
||
![]() |
#ifdef ESP8266 // ESP8266
|
||
|
// does not seem possible
|
||
|
temperature = -1;
|
||
|
#elif defined(CONFIG_IDF_TARGET_ESP32S2) // ESP32S2
|
||
|
temperature = -1;
|
||
|
#else // ESP32 ESP32S3 and ESP32C3
|
||
|
temperature = roundf(temperatureRead() * 10) / 10;
|
||
|
#endif
|
||
![]() |
if(presetToActivate != 0){
|
||
![]() |
// Check if temperature has exceeded the activation threshold
|
||
![]() |
if (temperature >= activationThreshold) {
|
||
|
// Update the state flag if not already set
|
||
![]() |
if (!isAboveThreshold) {
|
||
![]() |
isAboveThreshold = true;
|
||
|
}
|
||
![]() |
// Check if a 'high temperature' preset is configured and it's not already active
|
||
![]() |
if (currentPreset != presetToActivate) {
|
||
![]() |
// If a playlist is active, store it for reactivation later
|
||
|
if (currentPlaylist > 0) {
|
||
|
previousPlaylist = currentPlaylist;
|
||
|
}
|
||
|
// If a preset is active, store it for reactivation later
|
||
|
else if (currentPreset > 0) {
|
||
|
previousPreset = currentPreset;
|
||
|
// If no playlist or preset is active, save current state for reactivation later
|
||
|
} else {
|
||
|
saveTemporaryPreset();
|
||
|
}
|
||
|
// Activate the 'high temperature' preset
|
||
![]() |
applyPreset(presetToActivate);
|
||
|
}
|
||
|
}
|
||
|
// Check if temperature is back below the threshold
|
||
|
else if (temperature <= (activationThreshold - resetMargin)) {
|
||
|
// Update the state flag if not already set
|
||
|
if (isAboveThreshold){
|
||
|
isAboveThreshold = false;
|
||
|
}
|
||
![]() |
// Check if the 'high temperature' preset is active
|
||
|
if (currentPreset == presetToActivate) {
|
||
|
// Check if a previous playlist was stored
|
||
|
if (previousPlaylist > 0) {
|
||
|
// Reactivate the stored playlist
|
||
|
applyPreset(previousPlaylist);
|
||
|
// Clear the stored playlist
|
||
|
previousPlaylist = 0;
|
||
|
}
|
||
|
// Check if a previous preset was stored
|
||
|
else if (previousPreset > 0) {
|
||
|
// Reactivate the stored preset
|
||
|
applyPreset(previousPreset);
|
||
|
// Clear the stored preset
|
||
|
previousPreset = 0;
|
||
|
// If no previous playlist or preset was stored, revert to the stored state
|
||
|
} else {
|
||
|
applyTemporaryPreset();
|
||
|
}
|
||
![]() |
}
|
||
|
}
|
||
![]() |
}
|
||
![]() |
|
||
![]() |
#ifndef WLED_DISABLE_MQTT
|
||
|
if (WLED_MQTT_CONNECTED)
|
||
|
{
|
||
|
char array[10];
|
||
|
snprintf(array, sizeof(array), "%f", temperature);
|
||
|
publishMqtt(array);
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
void addToJsonInfo(JsonObject &root)
|
||
|
{
|
||
|
if (!isEnabled)
|
||
|
return;
|
||
|
|
||
|
// if "u" object does not exist yet wee need to create it
|
||
|
JsonObject user = root["u"];
|
||
|
if (user.isNull())
|
||
|
user = root.createNestedObject("u");
|
||
|
|
||
|
JsonArray userTempArr = user.createNestedArray(FPSTR(_name));
|
||
|
userTempArr.add(temperature);
|
||
|
userTempArr.add(F(" °C"));
|
||
|
|
||
|
// if "sensor" object does not exist yet wee need to create it
|
||
|
JsonObject sensor = root[F("sensor")];
|
||
|
if (sensor.isNull())
|
||
|
sensor = root.createNestedObject(F("sensor"));
|
||
|
|
||
|
JsonArray sensorTempArr = sensor.createNestedArray(FPSTR(_name));
|
||
|
sensorTempArr.add(temperature);
|
||
|
sensorTempArr.add(F("°C"));
|
||
|
}
|
||
|
|
||
|
void addToConfig(JsonObject &root)
|
||
|
{
|
||
|
JsonObject top = root.createNestedObject(FPSTR(_name));
|
||
|
top[FPSTR(_enabled)] = isEnabled;
|
||
|
top[FPSTR(_loopInterval)] = loopInterval;
|
||
![]() |
top[FPSTR(_activationThreshold)] = activationThreshold;
|
||
|
top[FPSTR(_presetToActivate)] = presetToActivate;
|
||
![]() |
}
|
||
|
|
||
![]() |
// Append useful info to the usermod settings gui
|
||
|
void appendConfigData()
|
||
|
{
|
||
|
// Display 'ms' next to the 'Loop Interval' setting
|
||
![]() |
oappend(F("addInfo('Internal Temperature:Loop Interval', 1, 'ms');"));
|
||
![]() |
// Display '°C' next to the 'Activation Threshold' setting
|
||
![]() |
oappend(F("addInfo('Internal Temperature:Activation Threshold', 1, '°C');"));
|
||
![]() |
// Display '0 = Disabled' next to the 'Preset To Activate' setting
|
||
![]() |
oappend(F("addInfo('Internal Temperature:Preset To Activate', 1, '0 = unused');"));
|
||
![]() |
}
|
||
|
|
||
![]() |
bool readFromConfig(JsonObject &root)
|
||
|
{
|
||
|
JsonObject top = root[FPSTR(_name)];
|
||
|
bool configComplete = !top.isNull();
|
||
|
configComplete &= getJsonValue(top[FPSTR(_enabled)], isEnabled);
|
||
|
configComplete &= getJsonValue(top[FPSTR(_loopInterval)], loopInterval);
|
||
![]() |
loopInterval = max(loopInterval, minLoopInterval); // Makes sure the loop interval isn't too small.
|
||
![]() |
configComplete &= getJsonValue(top[FPSTR(_presetToActivate)], presetToActivate);
|
||
|
configComplete &= getJsonValue(top[FPSTR(_activationThreshold)], activationThreshold);
|
||
![]() |
return configComplete;
|
||
|
}
|
||
|
|
||
|
uint16_t getId()
|
||
|
{
|
||
|
return USERMOD_ID_INTERNAL_TEMPERATURE;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
const char InternalTemperatureUsermod::_name[] PROGMEM = "Internal Temperature";
|
||
|
const char InternalTemperatureUsermod::_enabled[] PROGMEM = "Enabled";
|
||
|
const char InternalTemperatureUsermod::_loopInterval[] PROGMEM = "Loop Interval";
|
||
![]() |
const char InternalTemperatureUsermod::_activationThreshold[] PROGMEM = "Activation Threshold";
|
||
|
const char InternalTemperatureUsermod::_presetToActivate[] PROGMEM = "Preset To Activate";
|
||
![]() |
|
||
|
void InternalTemperatureUsermod::publishMqtt(const char *state, bool retain)
|
||
|
{
|
||
|
#ifndef WLED_DISABLE_MQTT
|
||
|
// Check if MQTT Connected, otherwise it will crash the 8266
|
||
|
if (WLED_MQTT_CONNECTED)
|
||
|
{
|
||
|
char subuf[64];
|
||
|
strcpy(subuf, mqttDeviceTopic);
|
||
|
strcat_P(subuf, PSTR("/mcutemp"));
|
||
|
mqtt->publish(subuf, 0, retain, state);
|
||
|
}
|
||
|
#endif
|
||
![]() |
}
|
||
|
|
||
|
static InternalTemperatureUsermod internal_temperature_v2;
|
||
|
REGISTER_USERMOD(internal_temperature_v2);
|