diff --git a/lib/HomeAssistantHelper/HomeAssistantHelper.h b/lib/HomeAssistantHelper/HomeAssistantHelper.h index 41f39a0..81cae9f 100644 --- a/lib/HomeAssistantHelper/HomeAssistantHelper.h +++ b/lib/HomeAssistantHelper/HomeAssistantHelper.h @@ -8,6 +8,16 @@ public: this->client = &client; } + void setYieldCallback(void(*yieldCallback)(void*)) { + this->yieldCallback = yieldCallback; + this->yieldArg = nullptr; + } + + void setYieldCallback(void(*yieldCallback)(void*), void* arg) { + this->yieldCallback = yieldCallback; + this->yieldArg = arg; + } + void setBufferedClient() { this->bClient = nullptr; } @@ -68,7 +78,13 @@ public: } else { serializeJson(doc, *client); } - return client->endPublish(); + + int pubResult = client->endPublish(); + if (this->yieldCallback != nullptr) { + this->yieldCallback(yieldArg); + } + + return pubResult; } bool publish(const char* topic) { @@ -89,6 +105,8 @@ public: } protected: + void(*yieldCallback)(void*) = nullptr; + void* yieldArg = nullptr; PubSubClient* client; BufferingPrint* bClient = nullptr; String prefix = "homeassistant"; diff --git a/lib/WiFiManagerParameters/HeaderParameter.h b/lib/WiFiManagerParameters/HeaderParameter.h new file mode 100644 index 0000000..1722866 --- /dev/null +++ b/lib/WiFiManagerParameters/HeaderParameter.h @@ -0,0 +1,27 @@ +#pragma once +#include + + +class HeaderParameter : public WiFiManagerParameter { +public: + HeaderParameter(const char* title) { + WiFiManagerParameter(""); + byte size = strlen(title) + strlen(this->tpl) + 1; + this->buffer = new char[size]; + this->title = title; + } + + ~HeaderParameter() { + delete[] this->buffer; + } + + const char* getCustomHTML() const override { + sprintf(this->buffer, this->tpl, title); + return this->buffer; + } + +protected: + const char* title; + char* buffer; + const char* tpl = "
%s
"; +}; \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index ed77281..7ea1684 100644 --- a/platformio.ini +++ b/platformio.ini @@ -17,7 +17,8 @@ lib_deps = https://github.com/Laxilef/opentherm_library/archive/refs/heads/master.zip knolleary/PubSubClient@^2.8 bblanchon/StreamUtils@^1.7.3 - lennarthennigs/ESP Telnet@^2.1.2 + ;lennarthennigs/ESP Telnet@^2.1.2 + https://github.com/Laxilef/ESPTelnet gyverlibs/EEManager@^2.0 gyverlibs/GyverPID@^3.3 gyverlibs/GyverBlinker@^1.0 diff --git a/src/MainTask.h b/src/MainTask.h index 0ae4ba8..142b165 100644 --- a/src/MainTask.h +++ b/src/MainTask.h @@ -45,7 +45,11 @@ protected: pinMode(LED_STATUS_PIN, OUTPUT); digitalWrite(LED_STATUS_PIN, false); #endif - pinMode(settings.externalPump.pin, OUTPUT); + + if (settings.externalPump.pin != 0) { + pinMode(settings.externalPump.pin, OUTPUT); + digitalWrite(settings.externalPump.pin, false); + } #if defined(ESP32) heapSize = ESP.getHeapSize(); @@ -224,9 +228,11 @@ protected: this->heatingEnabled = true; } - if (!settings.externalPump.use) { + if (!settings.externalPump.use || settings.externalPump.pin == 0) { if (vars.externalPump.enable) { - digitalWrite(settings.externalPump.pin, false); + if (settings.externalPump.pin != 0) { + digitalWrite(settings.externalPump.pin, false); + } vars.externalPump.enable = false; vars.externalPump.lastEnableTime = millis(); diff --git a/src/MqttTask.h b/src/MqttTask.h index 0b3d826..e8c8c8a 100644 --- a/src/MqttTask.h +++ b/src/MqttTask.h @@ -43,6 +43,14 @@ protected: client.setCallback(std::bind(&MqttTask::__callback, this, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)); client.setBufferSize(1024); + haHelper.setYieldCallback([](void* self) { + MqttTask* task = static_cast(self); + task->delay(50); + + if (client.connected()) { + client.loop(); + } + }, this); haHelper.setBufferedClient(this->bClient); haHelper.setDevicePrefix(settings.mqtt.prefix); haHelper.setDeviceVersion(PROJECT_VERSION); @@ -85,6 +93,7 @@ protected: lastReconnectAttempt = millis(); } + delay(100); } @@ -399,13 +408,11 @@ protected: haHelper.publishNumberOutdoorSensorOffset(false); haHelper.publishNumberIndoorSensorOffset(false); haHelper.publishSwitchDebug(false); - yield(); // emergency haHelper.publishSwitchEmergency(); haHelper.publishNumberEmergencyTarget(); haHelper.publishSwitchEmergencyUseEquitherm(); - yield(); // heating haHelper.publishSwitchHeating(false); @@ -413,12 +420,10 @@ protected: haHelper.publishNumberHeatingHysteresis(); haHelper.publishSensorHeatingSetpoint(false); haHelper.publishSensorCurrentHeatingMinTemp(false); - yield(); haHelper.publishSensorCurrentHeatingMaxTemp(false); haHelper.publishNumberHeatingMinTemp(false); haHelper.publishNumberHeatingMaxTemp(false); haHelper.publishNumberHeatingMaxModulation(false); - yield(); // pid haHelper.publishSwitchPID(); @@ -427,19 +432,16 @@ protected: haHelper.publishNumberPIDFactorD(); haHelper.publishNumberPIDMinTemp(false); haHelper.publishNumberPIDMaxTemp(false); - yield(); // equitherm haHelper.publishSwitchEquitherm(); haHelper.publishNumberEquithermFactorN(); haHelper.publishNumberEquithermFactorK(); haHelper.publishNumberEquithermFactorT(); - yield(); // tuning haHelper.publishSwitchTuning(); haHelper.publishSelectTuningRegulator(); - yield(); // states haHelper.publishBinSensorStatus(); @@ -448,7 +450,6 @@ protected: haHelper.publishBinSensorFlame(); haHelper.publishBinSensorFault(); haHelper.publishBinSensorDiagnostic(); - yield(); // sensors haHelper.publishSensorModulation(false); @@ -456,12 +457,10 @@ protected: haHelper.publishSensorFaultCode(); haHelper.publishSensorRssi(false); haHelper.publishSensorUptime(false); - yield(); // temperatures haHelper.publishNumberIndoorTemp(); haHelper.publishSensorHeatingTemp(); - yield(); // buttons haHelper.publishButtonRestart(false); @@ -507,7 +506,6 @@ protected: } published = true; - yield(); } if (force || _heatingMinTemp != heatingMinTemp || _heatingMaxTemp != heatingMaxTemp) { @@ -520,17 +518,23 @@ protected: _isStupidMode = isStupidMode; haHelper.publishNumberHeatingTarget(heatingMinTemp, heatingMaxTemp, false); - haHelper.publishClimateHeating(heatingMinTemp, heatingMaxTemp, isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR); + haHelper.publishClimateHeating( + heatingMinTemp, + heatingMaxTemp, + isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR + ); published = true; - yield(); } else if (_isStupidMode != isStupidMode) { _isStupidMode = isStupidMode; - haHelper.publishClimateHeating(heatingMinTemp, heatingMaxTemp, isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR); + haHelper.publishClimateHeating( + heatingMinTemp, + heatingMaxTemp, + isStupidMode ? HaHelper::TEMP_SOURCE_HEATING : HaHelper::TEMP_SOURCE_INDOOR + ); published = true; - yield(); } if (_dhwPresent && (force || _dhwMinTemp != settings.dhw.minTemp || _dhwMaxTemp != settings.dhw.maxTemp)) { @@ -541,7 +545,6 @@ protected: haHelper.publishClimateDhw(settings.dhw.minTemp, settings.dhw.maxTemp); published = true; - yield(); } if (force || _editableOutdoorTemp != editableOutdoorTemp) { @@ -556,7 +559,6 @@ protected: } published = true; - yield(); } if (force || _editableIndoorTemp != editableIndoorTemp) { diff --git a/src/OpenThermTask.h b/src/OpenThermTask.h index c0fb94a..bfd5bf0 100644 --- a/src/OpenThermTask.h +++ b/src/OpenThermTask.h @@ -41,7 +41,7 @@ protected: } void setup() { - Log.sinfoln(FPSTR(S_OT), F("Started. GPIO IN: %d, GPIO OUT: %d"), settings.opentherm.inPin, settings.opentherm.outPin); + Log.sinfoln(FPSTR(S_OT), F("Started. GPIO IN: %hhu, GPIO OUT: %hhu"), settings.opentherm.inPin, settings.opentherm.outPin); ot = new CustomOpenTherm(settings.opentherm.inPin, settings.opentherm.outPin); @@ -144,10 +144,10 @@ protected: } else { if (setMaxModulationLevel(settings.heating.maxModulation)) { - Log.snoticeln(FPSTR(S_OT_HEATING), F("Set max modulation %d\%"), settings.heating.maxModulation); + Log.snoticeln(FPSTR(S_OT_HEATING), F("Set max modulation %hhu%%"), settings.heating.maxModulation); } else { - Log.swarningln(FPSTR(S_OT_HEATING), F("Failed set max modulation %d\%"), settings.heating.maxModulation); + Log.swarningln(FPSTR(S_OT_HEATING), F("Failed set max modulation %hhu%%"), settings.heating.maxModulation); } } //yield(); @@ -158,13 +158,13 @@ protected: if (settings.dhw.minTemp < vars.parameters.dhwMinTemp) { settings.dhw.minTemp = vars.parameters.dhwMinTemp; eeSettings.update(); - Log.snoticeln(FPSTR(S_OT_DHW), F("Updated min temp: %d"), settings.dhw.minTemp); + Log.snoticeln(FPSTR(S_OT_DHW), F("Updated min temp: %hhu"), settings.dhw.minTemp); } if (settings.dhw.maxTemp > vars.parameters.dhwMaxTemp) { settings.dhw.maxTemp = vars.parameters.dhwMaxTemp; eeSettings.update(); - Log.snoticeln(FPSTR(S_OT_DHW), F("Updated max temp: %d"), settings.dhw.maxTemp); + Log.snoticeln(FPSTR(S_OT_DHW), F("Updated max temp: %hhu"), settings.dhw.maxTemp); } } else { @@ -186,13 +186,13 @@ protected: if (settings.heating.minTemp < vars.parameters.heatingMinTemp) { settings.heating.minTemp = vars.parameters.heatingMinTemp; eeSettings.update(); - Log.snoticeln(FPSTR(S_OT_HEATING), F("Updated min temp: %d"), settings.heating.minTemp); + Log.snoticeln(FPSTR(S_OT_HEATING), F("Updated min temp: %hhu"), settings.heating.minTemp); } if (settings.heating.maxTemp > vars.parameters.heatingMaxTemp) { settings.heating.maxTemp = vars.parameters.heatingMaxTemp; eeSettings.update(); - Log.snoticeln(FPSTR(S_OT_HEATING), F("Updated max temp: %d"), settings.heating.maxTemp); + Log.snoticeln(FPSTR(S_OT_HEATING), F("Updated max temp: %hhu"), settings.heating.maxTemp); } } else { diff --git a/src/WifiManagerTask.h b/src/WifiManagerTask.h index e2a4721..e7e8d37 100644 --- a/src/WifiManagerTask.h +++ b/src/WifiManagerTask.h @@ -3,7 +3,7 @@ #include #include #include -#include +#include #include WiFiManager wm; @@ -36,7 +36,12 @@ UnsignedShortParameter* wmExtPumpPostCirculationTime; UnsignedIntParameter* wmExtPumpAntiStuckInterval; UnsignedShortParameter* wmExtPumpAntiStuckTime; -SeparatorParameter* wmSep; +HeaderParameter* wmMqttHeader; +HeaderParameter* wmOtHeader; +HeaderParameter* wmOtFlagsHeader; +HeaderParameter* wmSensorsHeader; +HeaderParameter* wmExtPumpHeader; + extern EEManager eeSettings; #if USE_TELNET @@ -80,6 +85,12 @@ protected: wm.setDebugOutput(settings.debug, (wm_debuglevel_t) WM_DEBUG_MODE); wm.setTitle(PROJECT_NAME); + wm.setCustomHeadElement(PSTR( + "" + )); wm.setCustomMenuHTML(PSTR( "" "
" @@ -91,62 +102,68 @@ protected: std::vector menu = {"custom", "wifi", "param", "sep", "info", "update", "restart"}; wm.setMenu(menu); - wmSep = new SeparatorParameter(); - wmHostname = new WiFiManagerParameter("hostname", "Hostname", settings.hostname, 80); wm.addParameter(wmHostname); - wmMqttServer = new WiFiManagerParameter("mqtt_server", "MQTT server", settings.mqtt.server, 80); + wmMqttHeader = new HeaderParameter("MQTT"); + wm.addParameter(wmMqttHeader); + + wmMqttServer = new WiFiManagerParameter("mqtt_server", "Server", settings.mqtt.server, 80); wm.addParameter(wmMqttServer); - wmMqttPort = new UnsignedIntParameter("mqtt_port", "MQTT port", settings.mqtt.port, 6); + wmMqttPort = new UnsignedIntParameter("mqtt_port", "Port", settings.mqtt.port, 6); wm.addParameter(wmMqttPort); - wmMqttUser = new WiFiManagerParameter("mqtt_user", "MQTT username", settings.mqtt.user, 32); + wmMqttUser = new WiFiManagerParameter("mqtt_user", "Username", settings.mqtt.user, 32); wm.addParameter(wmMqttUser); - wmMqttPassword = new WiFiManagerParameter("mqtt_password", "MQTT password", settings.mqtt.password, 32, "type=\"password\""); + wmMqttPassword = new WiFiManagerParameter("mqtt_password", "Password", settings.mqtt.password, 32, "type=\"password\""); wm.addParameter(wmMqttPassword); - wmMqttPrefix = new WiFiManagerParameter("mqtt_prefix", "MQTT prefix", settings.mqtt.prefix, 32); + wmMqttPrefix = new WiFiManagerParameter("mqtt_prefix", "Prefix", settings.mqtt.prefix, 32); wm.addParameter(wmMqttPrefix); - wmMqttPublishInterval = new UnsignedIntParameter("mqtt_publish_interval", "MQTT publish interval", settings.mqtt.interval, 5); + wmMqttPublishInterval = new UnsignedIntParameter("mqtt_publish_interval", "Publish interval", settings.mqtt.interval, 5); wm.addParameter(wmMqttPublishInterval); - wm.addParameter(wmSep); + wmOtHeader = new HeaderParameter("OpenTherm"); + wm.addParameter(wmOtHeader); - wmOtInPin = new UnsignedIntParameter("ot_in_pin", "Opentherm GPIO IN", settings.opentherm.inPin, 2); + wmOtInPin = new UnsignedIntParameter("ot_in_pin", "GPIO IN", settings.opentherm.inPin, 2); wm.addParameter(wmOtInPin); - wmOtOutPin = new UnsignedIntParameter("ot_out_pin", "Opentherm GPIO OUT", settings.opentherm.outPin, 2); + wmOtOutPin = new UnsignedIntParameter("ot_out_pin", "GPIO OUT", settings.opentherm.outPin, 2); wm.addParameter(wmOtOutPin); - wmOtMemberIdCode = new UnsignedIntParameter("ot_member_id_code", "Opentherm Master Member ID", settings.opentherm.memberIdCode, 5); + wmOtMemberIdCode = new UnsignedIntParameter("ot_member_id_code", "Master Member ID", settings.opentherm.memberIdCode, 5); wm.addParameter(wmOtMemberIdCode); - wmOtDhwPresent = new CheckboxParameter("ot_dhw_present", "Opentherm DHW present", settings.opentherm.dhwPresent); + wmOtFlagsHeader = new HeaderParameter("OpenTherm flags"); + wm.addParameter(wmOtFlagsHeader); + + wmOtDhwPresent = new CheckboxParameter("ot_dhw_present", "DHW present", settings.opentherm.dhwPresent); wm.addParameter(wmOtDhwPresent); - wmOtSummerWinterMode = new CheckboxParameter("ot_summer_winter_mode", "Opentherm summer/winter mode", settings.opentherm.summerWinterMode); + wmOtSummerWinterMode = new CheckboxParameter("ot_summer_winter_mode", "Summer/winter mode", settings.opentherm.summerWinterMode); wm.addParameter(wmOtSummerWinterMode); - wmOtHeatingCh2Enabled = new CheckboxParameter("ot_heating_ch2_enabled", "Opentherm CH2 enabled", settings.opentherm.heatingCh2Enabled); + wmOtHeatingCh2Enabled = new CheckboxParameter("ot_heating_ch2_enabled", "CH2 enabled", settings.opentherm.heatingCh2Enabled); wm.addParameter(wmOtHeatingCh2Enabled); - wmOtHeatingCh1ToCh2 = new CheckboxParameter("ot_heating_ch1_to_ch2", "Opentherm heating CH1 to CH2", settings.opentherm.heatingCh1ToCh2); + wmOtHeatingCh1ToCh2 = new CheckboxParameter("ot_heating_ch1_to_ch2", "Heating CH1 to CH2", settings.opentherm.heatingCh1ToCh2); wm.addParameter(wmOtHeatingCh1ToCh2); - wmOtDhwToCh2 = new CheckboxParameter("ot_dhw_to_ch2", "Opentherm DHW to CH2", settings.opentherm.dhwToCh2); + wmOtDhwToCh2 = new CheckboxParameter("ot_dhw_to_ch2", "DHW to CH2", settings.opentherm.dhwToCh2); wm.addParameter(wmOtDhwToCh2); - wmOtDhwBlocking = new CheckboxParameter("ot_dhw_blocking", "Opentherm DHW blocking", settings.opentherm.dhwBlocking); + wmOtDhwBlocking = new CheckboxParameter("ot_dhw_blocking", "DHW blocking", settings.opentherm.dhwBlocking); wm.addParameter(wmOtDhwBlocking); wmOtModSyncWithHeating = new CheckboxParameter("ot_mod_sync_with_heating", "Modulation sync with heating", settings.opentherm.modulationSyncWithHeating); wm.addParameter(wmOtModSyncWithHeating); - wm.addParameter(wmSep); + wmSensorsHeader = new HeaderParameter("Sensors"); + wm.addParameter(wmSensorsHeader); wmOutdoorSensorPin = new UnsignedIntParameter("outdoor_sensor_pin", "Outdoor sensor GPIO", settings.sensors.outdoor.pin, 2); wm.addParameter(wmOutdoorSensorPin); @@ -157,21 +174,25 @@ protected: wmBleAddress = new WiFiManagerParameter("ble_address", "BLE sensor address", settings.sensors.indoor.bleAddresss, 17); wm.addParameter(wmBleAddress); - wm.addParameter(wmSep); + wmBleAddress = new WiFiManagerParameter("ble_address", "BLE sensor address", settings.sensors.indoor.bleAddresss, 17); + wm.addParameter(wmBleAddress); - wmExtPumpUse = new CheckboxParameter("ext_pump_use", "Use external pump", settings.externalPump.use); + wmExtPumpHeader = new HeaderParameter("External pump"); + wm.addParameter(wmExtPumpHeader); + + wmExtPumpUse = new CheckboxParameter("ext_pump_use", "Use external pump
", settings.externalPump.use); wm.addParameter(wmExtPumpUse); - wmExtPumpPin = new UnsignedIntParameter("ext_pump_pin", "External pump GPIO", settings.externalPump.pin, 2); + wmExtPumpPin = new UnsignedIntParameter("ext_pump_pin", "Relay GPIO", settings.externalPump.pin, 2); wm.addParameter(wmExtPumpPin); - wmExtPumpPostCirculationTime = new UnsignedShortParameter("ext_pump_ps_time", "External pump post circulation time", settings.externalPump.postCirculationTime, 5); + wmExtPumpPostCirculationTime = new UnsignedShortParameter("ext_pump_ps_time", "Post circulation time", settings.externalPump.postCirculationTime, 5); wm.addParameter(wmExtPumpPostCirculationTime); - wmExtPumpAntiStuckInterval = new UnsignedIntParameter("ext_pump_as_interval", "External pump anti stuck interval", settings.externalPump.antiStuckInterval, 7); + wmExtPumpAntiStuckInterval = new UnsignedIntParameter("ext_pump_as_interval", "Anti stuck interval", settings.externalPump.antiStuckInterval, 7); wm.addParameter(wmExtPumpAntiStuckInterval); - wmExtPumpAntiStuckTime = new UnsignedShortParameter("ext_pump_as_time", "External pump anti stuck time", settings.externalPump.antiStuckTime, 5); + wmExtPumpAntiStuckTime = new UnsignedShortParameter("ext_pump_as_time", "Anti stuck time", settings.externalPump.antiStuckTime, 5); wm.addParameter(wmExtPumpAntiStuckTime); //wm.setCleanConnect(true); diff --git a/src/main.cpp b/src/main.cpp index 6dcf2c9..a5e1ccb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,6 +54,7 @@ void setup() { #endif #if USE_TELNET + TelnetStream.setKeepAliveInterval(500); Log.addStream(&TelnetStream); #endif //Log.setNtpClient(&timeClient);