#ifdef FIRMWARE_VARIANT_THERMOSTAT void thermostat_setup() { pinMode(PIN_THERMOSTAT_OUTPUT, OUTPUT); digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE); } void thermostat_updateCurrSetTemp() { // set target temp for heating mode if (thermostat_heatingMode > 0) { // heating on if (thermostat_preset == 0) { // normal/day preset thermostat_currSetTemp = thermostat_setTemp; thermostat_currActualSetTemp = thermostat_setTemp - confTherm.setTempDecreaseVal; } else if (thermostat_preset == 1) { // night/reduction preset thermostat_currSetTemp = thermostat_setTempLow; thermostat_currActualSetTemp = thermostat_setTempLow - confTherm.setTempDecreaseVal; } else if (thermostat_preset == 2) { // night/reduction 2 preset thermostat_currSetTemp = thermostat_setTempLow2; thermostat_currActualSetTemp = thermostat_setTempLow2 - confTherm.setTempDecreaseVal; } } else { // if heatingMode == 0 thermostat_currSetTemp = DEFAULT_SETTEMP_HEATOFF; thermostat_currActualSetTemp = thermostat_currSetTemp; } } void thermostat_mainFunction() { thermostat_updateCurrSetTemp(); //char tmp_topic_out[50]; if (thermostat_heatingMode > 0 && thermostat_turnHeatingOn) { thermostat_heatingOnTime = (millis() - thermostat_heatingLastOnMillis) / 1000; //char buf[101]; //sprintf(buf, "heating on for %lus", heatingOnTime); //sendLog(buf, LOGLEVEL_INFO); } else if (thermostat_heatingMode > 0 && !thermostat_turnHeatingOn) { if(thermostat_heatingLastOnMillis > 0) { // prevent locking the heating after a reboot thermostat_heatingOffTime = (millis() - thermostat_heatingLastOffMillis) / 1000; } //char buf[101]; //sprintf(buf, "heating off for %lus", heatingOffTime); //sendLog(buf, LOGLEVEL_INFO); } //char tmp_topic_out[50]; //sprintf(tmp_topic_out, "%s/%s", mqtt_topic_out, "heating"); if ( sensor_DHT_lastUpdate != 0 && (millis() - sensor_DHT_lastUpdate) <= sensors_maxMeasurementAge ) { // thermostat - only active if measured temperature is < 2 min old #ifdef DEBUG_VERBOSE Serial.print("thermostat, lastTempUpdate="); Serial.print(sensor_DHT_lastUpdate); Serial.print(", lastTempUpdate_delta="); long _lastTempUpdateDelta = millis() - sensor_DHT_lastUpdate; Serial.println(_lastTempUpdateDelta); #endif // thermostat with hysteresis if ( thermostat_turnHeatingOn && sensor_DHT_currTemp >= thermostat_currActualSetTemp ) { thermostat_turnHeatingOn = false; thermostat_heatingLastOffMillis = millis(); thermostat_heatingLockTime = confTherm.heatingMinOffTime; digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE); display_update(); sprintf_P(logBuf, "TSTAT: %s OFF, on for %lus", PGMStr_switchHeating, thermostat_heatingOnTime); sendLog(logBuf, LOGLEVEL_INFO); //Serial.println("heating off"); //mqttclient.publish(tmp_topic_out, "off"); thermostat_publishCurrentValues(); } else if ( !thermostat_turnHeatingOn && thermostat_heatingMode > 0 && thermostat_heatingLockTime == 0 && thermostat_heatingPause == 0 && ( sensor_DHT_currTemp < (thermostat_currActualSetTemp - confTherm.hysteresis) ) ) { //if ( heatingOffTime > confThermAdv.heatingMinOffTime || heatingLastOnMillis == 0) { thermostat_turnHeatingOn = true; //heatingLockTimeActive = false; //heatingLockTime = 0; thermostat_heatingLastOnMillis = millis(); digitalWrite(PIN_THERMOSTAT_OUTPUT, THERMOSTAT_OUTPUT_ONSTATE); display_update(); snprintf(logBuf, LOG_BUFFER_SIZE, "TSTAT: switch heating ON, off for %lus", thermostat_heatingOffTime); sendLog(logBuf, LOGLEVEL_INFO); //Serial.println("heating on"); //mqttclient.publish(tmp_topic_out, "on"); thermostat_publishCurrentValues(); //} //else { // // heating should run BUT lock time is active // heatingLockTimeActive = true; // heatingLockTime = confThermAdv.heatingMinOffTime - heatingOffTime; // display_update(); //} } else if (thermostat_heatingPause > 0) { thermostat_turnHeatingOn = false; thermostat_heatingLastOffMillis = millis(); digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE); display_update(); } } else { // turn off as no temp reading is available if (thermostat_turnHeatingOn) { digitalWrite(PIN_THERMOSTAT_OUTPUT, !THERMOSTAT_OUTPUT_ONSTATE); thermostat_turnHeatingOn = false; thermostat_heatingLastOffMillis = millis(); } if ( sensor_DHT_lastUpdate != 0 ) sendLog(F("TSTAT: heating OFF, temp reading not yet available"), LOGLEVEL_INFO); else if ( (millis() - sensor_DHT_lastUpdate) > sensors_maxMeasurementAge ) sendLog(F("TSTAT: heating OFF, last temp reading too old"), LOGLEVEL_WARN); //mqttclient.publish(tmp_topic_out, "off"); thermostat_publishCurrentValues(); } } void thermostat_toggleOnOff() { if (thermostat_heatingMode > 0) { thermostat_heatingMode = 0; thermostat_heatingPause = 0; thermostat_heatingLockTime = 0; thermostat_lastValueChange = millis(); thermostat_heatingModeAlreadySaved = false; } else { thermostat_heatingMode = 1; thermostat_heatingPause = 0; thermostat_heatingLockTime = 0; thermostat_lastValueChange = millis(); thermostat_heatingModeAlreadySaved = false; } thermostat_updateCurrentHeatingModeName(); display_update(); } void thermostat_togglePreset() { //sendLog(F("switch preset to ")); if (thermostat_pendingPreset < 0 || thermostat_pendingPreset > 2) thermostat_pendingPreset = thermostat_preset; // if (pendingPresetToggle && preset == 0 && pendingPreset == 0) pendingPreset = 1; // else if (pendingPresetToggle && preset == 1 && pendingPreset == 1) pendingPreset = 0; // else if (pendingPreset == 1 && pendingPresetToggle) pendingPreset = 2; // else if (pendingPreset == 2 && !pendingPresetToggle) pendingPreset = 0; // else if (pendingPreset == 2 && pendingPresetToggle) pendingPreset = 1; // pendingPreset 0 => Normal // pendingPreset 1 => Reduction 1 // pendingPreset 2 => Reduction 2 if(thermostat_preset == 0) { // Normal > Reduction 1 > Reduction 2 if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 1; else if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 2; else if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 0; } else if(thermostat_preset == 1) { // Reduction 1 > Normal > Reduction 2 if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 0; else if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 2; else if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 1; } else if(thermostat_preset == 2) { // Reduction 2 > Normal > Reduction 1 if (thermostat_pendingPreset == 2) thermostat_pendingPreset = 0; else if (thermostat_pendingPreset == 0) thermostat_pendingPreset = 1; else if (thermostat_pendingPreset == 1) thermostat_pendingPreset = 2; } // if (preset == 0 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 0 && pendingPreset == 1) pendingPreset = 2; // else if (preset == 1 && pendingPreset == 0) pendingPreset = 2; // else if (preset == 1 && pendingPreset == 1) pendingPreset = 0; // else if (preset == 1 && pendingPreset == 2) pendingPreset = 1; // else if (preset == 1 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 2 && pendingPreset == 0) pendingPreset = 1; // else if (preset == 2 && pendingPreset == 1) pendingPreset = 0; // else if (preset == 2 && pendingPreset == 2) pendingPreset = 0; thermostat_lastValueChange = millis(); thermostat_presetAlreadySaved = false; thermostat_updatePendingPresetName(); //display_update(); //pendingPresetToggle = true; display_showRow2OverlayMessage(thermostat_pendingPresetName); //Serial.print(pendingPreset); //Serial.print(" - \""); //Serial.print(currentPresetName); //Serial.println("\""); } void thermostat_updateCurrentHeatingModeName() { if (thermostat_heatingMode == 0) strlcpy(thermostat_currentModeName, confTherm.modeName0, 14); else if (thermostat_heatingMode == 1) strlcpy(thermostat_currentModeName, confTherm.modeName1, 14); } void thermostat_updateCurrentPresetName() { if (thermostat_preset == 0) strlcpy(thermostat_currentPresetName, confTherm.psetName0, 14); else if (thermostat_preset == 1) strlcpy(thermostat_currentPresetName, confTherm.psetName1, 14); else if (thermostat_preset == 2) strlcpy(thermostat_currentPresetName, confTherm.psetName2, 14); } void thermostat_updatePendingPresetName() { if (thermostat_pendingPreset == 0) strlcpy(thermostat_pendingPresetName, confTherm.psetName0, 14); else if (thermostat_pendingPreset == 1) strlcpy(thermostat_pendingPresetName, confTherm.psetName1, 14); else if (thermostat_pendingPreset == 2) strlcpy(thermostat_pendingPresetName, confTherm.psetName2, 14); } void thermostat_setTempStepUp() { if (thermostat_heatingMode == 1) { sendLog(F("TSTAT: setTemp +0.5")); if ( thermostat_setTemp <= (confTherm.setTempMax - 0.5)) { thermostat_setTemp += 0.5; thermostat_lastValueChange = millis(); thermostat_setTempAlreadySaved = false; } thermostat_mainFunction(); display_update(); } } void thermostat_setTempStepDown() { if (thermostat_heatingMode == 1) { sendLog(F("TSTAT: setTemp -0.5")); if ( thermostat_setTemp >= (confTherm.setTempMin + 0.5)) { thermostat_setTemp -= 0.5; thermostat_lastValueChange = millis(); thermostat_setTempAlreadySaved = false; } thermostat_mainFunction(); display_update(); } } void thermostat_setTempTo(float _setTo) { bool _changed = false; if(_setTo != thermostat_setTemp) { if (_setTo >= confTherm.setTempMin && _setTo <= confTherm.setTempMax) { _changed = true; } else if (_setTo > confTherm.setTempMax) { _setTo = confTherm.setTempMax; _changed = true; } else if (_setTo < confTherm.setTempMin) { _setTo = confTherm.setTempMin; _changed = true; } if (_changed) { thermostat_setTemp = _setTo; thermostat_lastValueChange = millis(); thermostat_setTempAlreadySaved = false; thermostat_mainFunction(); display_update(); thermostat_publishCurrentValues(); sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTemp, PGMStr_changedTo, thermostat_setTemp); sendLog(logBuf); } } } void thermostat_setTempLowStepUp() { sendLog(F("TSTAT: setTempLow +0.5")); if ( thermostat_setTempLow <= (thermostat_setTempLowMax - 0.5)) { thermostat_setTempLow += 0.5; thermostat_lastValueChange = millis(); thermostat_setTempLowAlreadySaved = false; } display_update(); } void thermostat_setTempLowStepDown() { sendLog(F("TSTAT: setTempLow -0.5")); if ( thermostat_setTempLow >= (thermostat_setTempLowMin + 0.5)) { thermostat_setTempLow -= 0.5; thermostat_lastValueChange = millis(); thermostat_setTempLowAlreadySaved = false; } display_update(); } void thermostat_setTempLowTo(float _setTo) { bool _changed = false; if(_setTo != thermostat_setTempLow) { if (_setTo >= thermostat_setTempLowMin && _setTo <= thermostat_setTempLowMax) { _changed = true; } else if (_setTo > thermostat_setTempLowMax) { _setTo = thermostat_setTempLowMax; _changed = true; } else if (_setTo < thermostat_setTempLowMin) { _setTo = thermostat_setTempLowMin; _changed = true; } if (_changed) { thermostat_setTempLow = _setTo; thermostat_lastValueChange = millis(); thermostat_setTempLowAlreadySaved = false; display_update(); thermostat_publishCurrentValues(); sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow, PGMStr_changedTo, thermostat_setTempLow); sendLog(logBuf); } } } void thermostat_setTempLow2StepUp() { sendLog(F("TSTAT: setTempLow2 +0.5")); if ( thermostat_setTempLow2 <= (thermostat_setTempLowMax - 0.5)) { thermostat_setTempLow2 += 0.5; thermostat_lastValueChange = millis(); thermostat_setTempLow2AlreadySaved = false; } display_update(); } void thermostat_setTempLow2StepDown() { sendLog(F("TSTAT: setTempLow2 -0.5")); if ( thermostat_setTempLow2 >= (thermostat_setTempLowMin + 0.5)) { thermostat_setTempLow2 -= 0.5; thermostat_lastValueChange = millis(); thermostat_setTempLow2AlreadySaved = false; } display_update(); } void thermostat_setTempLow2To(float _setTo) { bool _changed = false; if(_setTo != thermostat_setTempLow2) { if (_setTo >= thermostat_setTempLowMin && _setTo <= thermostat_setTempLowMax) { _changed = true; } else if (_setTo > thermostat_setTempLowMax) { _setTo = thermostat_setTempLowMax; _changed = true; } else if (_setTo < thermostat_setTempLowMin) { _setTo = thermostat_setTempLowMin; _changed = true; } if (_changed) { thermostat_setTempLow2 = _setTo; thermostat_lastValueChange = millis(); thermostat_setTempLow2AlreadySaved = false; display_update(); thermostat_publishCurrentValues(); sprintf_P(logBuf, "%s: %s %s %2.1f", PGMStr_thermostat, PGMStr_setTempLow2, PGMStr_changedTo, thermostat_setTempLow2); sendLog(logBuf); } } } void thermostat_setHeatingmodeTo(unsigned char _setTo) { if(_setTo != thermostat_heatingMode) { thermostat_heatingMode = _setTo; thermostat_heatingPause = 0; thermostat_heatingLockTime = 0; thermostat_updateCurrSetTemp(); thermostat_lastValueChange = millis(); thermostat_heatingModeAlreadySaved = false; thermostat_updateCurrentHeatingModeName(); thermostat_mainFunction(); display_update(); thermostat_publishCurrentValues(); sprintf_P(logBuf, "%s: %s %s %u", PGMStr_thermostat, PGMStr_heatingMode, PGMStr_changedTo, thermostat_heatingMode); sendLog(logBuf); } } void thermostat_setHeatingPause(uint8_t _setTo) { bool _changed = false; if(_setTo == 0) { thermostat_heatingPause = 0; _changed = true; sprintf_P(logBuf, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_disabled); } else if (_setTo == 1 && thermostat_heatingPause == 0) { thermostat_heatingPause = confTherm.pauseTout; _changed = true; sprintf_P(logBuf, "%s: %s %s", PGMStr_thermostat, PGMStr_heatingPause, PGMStr_enabled); } if(_changed) { thermostat_lastValueChange = millis(); thermostat_mainFunction(); display_update(); thermostat_publishCurrentValues(); sendLog(logBuf); } } void thermostat_setPresetTo(unsigned char _setTo) { if(_setTo != thermostat_preset) { if(_setTo >= 0 && _setTo <=2) { thermostat_preset = _setTo; thermostat_pendingPreset = _setTo; thermostat_updateCurrSetTemp(); thermostat_lastValueChange = millis(); thermostat_presetAlreadySaved = false; thermostat_updateCurrentPresetName(); thermostat_mainFunction(); display_update(); thermostat_publishCurrentValues(); sprintf_P(logBuf, "%s: %s %s %u", PGMStr_thermostat, PGMStr_preset, PGMStr_changedTo, thermostat_preset); sendLog(logBuf); } } } void thermostat_checkValuesChanged() { // called every second by everySecond() / scheduler.ino if ( !thermostat_setTempAlreadySaved || !thermostat_heatingModeAlreadySaved || !thermostat_presetAlreadySaved || !thermostat_setTempLowAlreadySaved || !thermostat_setTempLow2AlreadySaved ) { if ( (millis() - thermostat_lastValueChange) > thermostat_saveValuesTimeout ) { // value was changed 5s ago. now save if auto-save enabled if (!thermostat_setTempAlreadySaved) { thermostat_lastUpdate_setTemp = millis(); if (confTherm.autoSaveSetTemp && thermostat_setTemp != thermostat_setTempSaved) { thermostat_saveSetTemp(); sendLog(F("TSTAT: setTemp autosave done")); } thermostat_setTempAlreadySaved = true; } if (!thermostat_setTempLowAlreadySaved) { thermostat_lastUpdate_setTempLow = millis(); if (confTherm.autoSaveSetTemp && thermostat_setTempLow != thermostat_setTempLowSaved) { thermostat_saveSetTempLow(); sendLog(F("TSTAT: setTempLow autosave done")); } thermostat_setTempLowAlreadySaved = true; } if (!thermostat_setTempLow2AlreadySaved) { thermostat_lastUpdate_setTempLow2 = millis(); if (confTherm.autoSaveSetTemp && thermostat_setTempLow2 != thermostat_setTempLow2Saved) { thermostat_saveSetTempLow2(); sendLog(F("TSTAT: setTempLow2 autosave done")); } thermostat_setTempLow2AlreadySaved = true; } if (!thermostat_heatingModeAlreadySaved) { thermostat_lastUpdate_heatingMode = millis(); if (confTherm.autoSaveHeatingMode && thermostat_heatingMode != thermostat_heatingModeSaved) { thermostat_saveHeatingMode(); sendLog(F("TSTAT: heatingMode autosave done")); } thermostat_heatingModeAlreadySaved = true; } if (!thermostat_presetAlreadySaved) { thermostat_lastUpdate_preset = millis(); thermostat_preset = thermostat_pendingPreset; if (confTherm.autoSaveHeatingMode && thermostat_preset != thermostat_presetSaved) { thermostat_savePreset(); sendLog(F("TSTAT: preset autosave done")); } thermostat_presetAlreadySaved = true; } thermostat_publishCurrentValues(); } } } #endif