added boiler ww comfort., via telnet & MQTT

This commit is contained in:
proddy
2019-03-17 17:36:48 +01:00
parent 4a559866c7
commit e8e1cb8921
6 changed files with 167 additions and 121 deletions

View File

@@ -806,31 +806,38 @@ unsigned long MyESP::_getUptime() {
// print out ESP system stats
// for battery power is ESP.getVcc()
void MyESP::showSystemStats() {
myDebug_P(PSTR("[APP] %s version: %s"), _app_name, _app_version);
myDebug_P(PSTR("[APP] MyESP version: %s"), MYESP_VERSION);
myDebug_P(PSTR("[APP] Build timestamp: %s"), _buildTime().c_str());
#if defined(ESP8266)
myDebug_P(PSTR("%sESP8266 System stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF);
#else
myDebug_P(PSTR("ESP32 System stats:"));
#endif
myDebug_P(PSTR(""));
myDebug_P(PSTR(" [APP] %s version: %s"), _app_name, _app_version);
myDebug_P(PSTR(" [APP] MyESP version: %s"), MYESP_VERSION);
myDebug_P(PSTR(" [APP] Build timestamp: %s"), _buildTime().c_str());
if (_boottime != NULL) {
myDebug_P(PSTR("[APP] Boot time: %s"), _boottime);
myDebug_P(PSTR(" [APP] Boot time: %s"), _boottime);
}
myDebug_P(PSTR("[APP] Uptime: %d seconds"), _getUptime());
myDebug_P(PSTR("[APP] System Load: %d%%"), getSystemLoadAverage());
myDebug_P(PSTR(" [APP] Uptime: %d seconds"), _getUptime());
myDebug_P(PSTR(" [APP] System Load: %d%%"), getSystemLoadAverage());
if (isAPmode()) {
myDebug_P(PSTR("[WIFI] Device is in AP mode with SSID %s"), jw.getAPSSID().c_str());
myDebug_P(PSTR(" [WIFI] Device is in AP mode with SSID %s"), jw.getAPSSID().c_str());
} else {
myDebug_P(PSTR("[WIFI] WiFi Hostname: %s"), _getESPhostname().c_str());
myDebug_P(PSTR("[WIFI] WiFi IP: %s"), WiFi.localIP().toString().c_str());
myDebug_P(PSTR("[WIFI] WiFi signal strength: %d%%"), getWifiQuality());
myDebug_P(PSTR(" [WIFI] WiFi Hostname: %s"), _getESPhostname().c_str());
myDebug_P(PSTR(" [WIFI] WiFi IP: %s"), WiFi.localIP().toString().c_str());
myDebug_P(PSTR(" [WIFI] WiFi signal strength: %d%%"), getWifiQuality());
}
myDebug_P(PSTR("[WIFI] WiFi MAC: %s"), WiFi.macAddress().c_str());
myDebug_P(PSTR(" [WIFI] WiFi MAC: %s"), WiFi.macAddress().c_str());
#ifdef CRASH
char output_str[80] = {0};
char buffer[16] = {0};
/* Crash info */
myDebug_P(PSTR("[EEPROM] EEPROM size: %u"), EEPROMr.reserved() * SPI_FLASH_SEC_SIZE);
strlcpy(output_str, PSTR("[EEPROM] EEPROM Sector pool size is "), sizeof(output_str));
myDebug_P(PSTR(" [EEPROM] EEPROM size: %u"), EEPROMr.reserved() * SPI_FLASH_SEC_SIZE);
strlcpy(output_str, PSTR(" [EEPROM] EEPROM Sector pool size is "), sizeof(output_str));
strlcat(output_str, itoa(EEPROMr.size(), buffer, 10), sizeof(output_str));
strlcat(output_str, PSTR(", and in use are: "), sizeof(output_str));
for (uint32_t i = 0; i < EEPROMr.size(); i++) {
@@ -841,39 +848,40 @@ void MyESP::showSystemStats() {
#endif
#ifdef ARDUINO_BOARD
myDebug_P(PSTR("[SYSTEM] Board: %s"), ARDUINO_BOARD);
myDebug_P(PSTR(" [SYSTEM] Board: %s"), ARDUINO_BOARD);
#endif
myDebug_P(PSTR("[SYSTEM] CPU frequency: %u MHz"), ESP.getCpuFreqMHz());
myDebug_P(PSTR("[SYSTEM] SDK version: %s"), ESP.getSdkVersion());
myDebug_P(PSTR(" [SYSTEM] CPU frequency: %u MHz"), ESP.getCpuFreqMHz());
myDebug_P(PSTR(" [SYSTEM] SDK version: %s"), ESP.getSdkVersion());
#if defined(ESP8266)
myDebug_P(PSTR("[SYSTEM] CPU chip ID: 0x%06X"), ESP.getChipId());
myDebug_P(PSTR("[SYSTEM] Core version: %s"), ESP.getCoreVersion().c_str());
myDebug_P(PSTR("[SYSTEM] Boot version: %d"), ESP.getBootVersion());
myDebug_P(PSTR("[SYSTEM] Boot mode: %d"), ESP.getBootMode());
myDebug_P(PSTR(" [SYSTEM] CPU chip ID: 0x%06X"), ESP.getChipId());
myDebug_P(PSTR(" [SYSTEM] Core version: %s"), ESP.getCoreVersion().c_str());
myDebug_P(PSTR(" [SYSTEM] Boot version: %d"), ESP.getBootVersion());
myDebug_P(PSTR(" [SYSTEM] Boot mode: %d"), ESP.getBootMode());
//myDebug_P(PSTR("[SYSTEM] Firmware MD5: %s"), (char *)ESP.getSketchMD5().c_str());
#endif
FlashMode_t mode = ESP.getFlashChipMode();
#if defined(ESP8266)
myDebug_P(PSTR("[FLASH] Flash chip ID: 0x%06X"), ESP.getFlashChipId());
myDebug_P(PSTR(" [FLASH] Flash chip ID: 0x%06X"), ESP.getFlashChipId());
#endif
myDebug_P(PSTR("[FLASH] Flash speed: %u Hz"), ESP.getFlashChipSpeed());
myDebug_P(PSTR("[FLASH] Flash mode: %s"),
myDebug_P(PSTR(" [FLASH] Flash speed: %u Hz"), ESP.getFlashChipSpeed());
myDebug_P(PSTR(" [FLASH] Flash mode: %s"),
mode == FM_QIO ? "QIO" : mode == FM_QOUT ? "QOUT" : mode == FM_DIO ? "DIO" : mode == FM_DOUT ? "DOUT" : "UNKNOWN");
#if defined(ESP8266)
myDebug_P(PSTR("[FLASH] Flash size (CHIP): %d"), ESP.getFlashChipRealSize());
myDebug_P(PSTR(" [FLASH] Flash size (CHIP): %d"), ESP.getFlashChipRealSize());
#endif
myDebug_P(PSTR("[FLASH] Flash size (SDK): %d"), ESP.getFlashChipSize());
myDebug_P(PSTR("[FLASH] Flash Reserved: %d"), 1 * SPI_FLASH_SEC_SIZE);
myDebug_P(PSTR("[MEM] Firmware size: %d"), ESP.getSketchSize());
myDebug_P(PSTR("[MEM] Max OTA size: %d"), (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
myDebug_P(PSTR("[MEM] OTA Reserved: %d"), 4 * SPI_FLASH_SEC_SIZE);
myDebug_P(PSTR("[MEM] Free Heap: %d"), ESP.getFreeHeap());
myDebug_P(PSTR(" [FLASH] Flash size (SDK): %d"), ESP.getFlashChipSize());
myDebug_P(PSTR(" [FLASH] Flash Reserved: %d"), 1 * SPI_FLASH_SEC_SIZE);
myDebug_P(PSTR(" [MEM] Firmware size: %d"), ESP.getSketchSize());
myDebug_P(PSTR(" [MEM] Max OTA size: %d"), (ESP.getFreeSketchSpace() - 0x1000) & 0xFFFFF000);
myDebug_P(PSTR(" [MEM] OTA Reserved: %d"), 4 * SPI_FLASH_SEC_SIZE);
myDebug_P(PSTR(" [MEM] Free Heap: %d"), ESP.getFreeHeap());
#if defined(ESP8266)
myDebug_P(PSTR("[MEM] Stack: %d"), ESP.getFreeContStack());
myDebug_P(PSTR(" [MEM] Stack: %d"), ESP.getFreeContStack());
#endif
myDebug_P(PSTR(""));
}
// handler for Telnet

View File

@@ -112,7 +112,7 @@ void custom_crash_callback(struct rst_info *, uint32_t, uint32_t);
typedef struct {
bool set; // is it a set command
char key[40];
char key[50];
char description[100];
} command_t;

View File

@@ -32,10 +32,8 @@ DS18 ds18;
#define myDebug_P(...) myESP.myDebug_P(__VA_ARGS__)
// timers, all values are in seconds
#define PUBLISHVALUES_TIME 120 // every 2 minutes publish MQTT values
#define DEFAULT_PUBLISHVALUES_TIME 120 // every 2 minutes publish MQTT values, including Dallas sensors
Ticker publishValuesTimer;
#define PUBLISHSENSORVALUES_TIME 180 // every 3 minutes publish MQTT sensor values
Ticker publishSensorValuesTimer;
#define SYSTEMCHECK_TIME 20 // every 20 seconds check if Boiler is online
@@ -70,6 +68,7 @@ typedef struct {
bool shower_alert; // true if we want the alert of cold water
bool led_enabled; // LED on/off
bool test_mode; // test mode to stop automatic Tx on/off
uint16_t publish_time; // frequency of MQTT publish in seconds
uint8_t led_gpio;
uint8_t dallas_gpio;
uint8_t dallas_parasite;
@@ -91,12 +90,13 @@ command_t PROGMEM project_cmds[] = {
{true, "dallas_parasite <on | off>", "set to on if powering Dallas via parasite"},
{true, "thermostat_type <type ID>", "set the thermostat type id (e.g. 10 for 0x10)"},
{true, "boiler_type <type ID>", "set the boiler type id (e.g. 8 for 0x08)"},
{true, "test_mode <on | off>", "test_mode turns off all automatic reads"},
{true, "shower_timer <on | off>", "notify on shower durations"},
{true, "test_mode <on | off>", "test_mode turns on/off all automatic reads"},
{true, "shower_timer <on | off>", "notify via MQTT all shower durations"},
{true, "shower_alert <on | off>", "send a warning of cold water after shower time is exceeded"},
{false, "info", "show data captured on the EMS bus"},
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
{false, "publish", "publish all values to MQTT"},
{false, "publish_time <seconds>", "set frequency for MQTT publishing of values"},
{false, "types", "list supported EMS telegram type IDs"},
{false, "queue", "show current Tx queue"},
{false, "autodetect", "detect EMS devices and attempt to automatically set boiler and thermostat types"},
@@ -108,7 +108,8 @@ command_t PROGMEM project_cmds[] = {
{false, "thermostat scan <type ID>", "do a read on all type IDs"},
{false, "boiler read <type ID>", "send read request to boiler"},
{false, "boiler wwtemp <degrees>", "set boiler warm water temperature"},
{false, "boiler tapwater <on | off>", "set boiler warm tap water on/off"}
{false, "boiler tapwater <on | off>", "set boiler warm tap water on/off"},
{false, "boiler comfort <hot | eco | intelligent>", "set boiler warm water comfort setting"}
};
@@ -262,7 +263,7 @@ void showInfo() {
char buffer_type[128] = {0};
myDebug("%sEMS-ESP System stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug("%sEMS-ESP system stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
_EMS_SYS_LOGGING sysLog = ems_getLogging();
if (sysLog == EMS_SYS_LOGGING_BASIC) {
myDebug(" System logging set to Basic");
@@ -283,7 +284,7 @@ void showInfo() {
((EMSESP_Status.shower_timer) ? "enabled" : "disabled"),
((EMSESP_Status.shower_alert) ? "enabled" : "disabled"));
myDebug("\n%sEMS Bus Stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug("\n%sEMS Bus stats:%s", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" Bus Connected=%s, # Rx telegrams=%d, # Tx telegrams=%d, # Crc Errors=%d",
(ems_getBusConnected() ? "yes" : "no"),
EMS_Sys_Status.emsRxPgks,
@@ -300,11 +301,11 @@ void showInfo() {
// active stats
if (ems_getBusConnected()) {
if (EMS_Boiler.tapwaterActive != EMS_VALUE_INT_NOTSET) {
myDebug(" Hot tap water is %s", EMS_Boiler.tapwaterActive ? "running" : "off");
myDebug(" Hot tap water: %s", EMS_Boiler.tapwaterActive ? "running" : "off");
}
if (EMS_Boiler.heatingActive != EMS_VALUE_INT_NOTSET) {
myDebug(" Central Heating is %s", EMS_Boiler.heatingActive ? "active" : "off");
myDebug(" Central Heating: %s", EMS_Boiler.heatingActive ? "active" : "off");
}
}
@@ -312,11 +313,11 @@ void showInfo() {
_renderBoolValue("Warm Water activated", EMS_Boiler.wWActivated);
_renderBoolValue("Warm Water circulation pump available", EMS_Boiler.wWCircPump);
if (EMS_Boiler.wWComfort == EMS_VALUE_UBAParameterWW_wwComfort_Hot) {
myDebug(" Warm Water comfort is set to Hot");
myDebug(" Warm Water comfort setting: Hot");
} else if (EMS_Boiler.wWComfort == EMS_VALUE_UBAParameterWW_wwComfort_Eco) {
myDebug(" Warm Water comfort is set to Eco");
myDebug(" Warm Water comfort setting: Eco");
} else if (EMS_Boiler.wWComfort == EMS_VALUE_UBAParameterWW_wwComfort_Intelligent) {
myDebug(" Warm Water comfort is set to Intelligent");
myDebug(" Warm Water comfort setting: Intelligent");
}
_renderIntValue("Warm Water selected temperature", "C", EMS_Boiler.wWSelTemp);
@@ -701,6 +702,12 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
recreate_config = true;
}
// publish_time
if (!(EMSESP_Status.publish_time = json["publish_time"])) {
EMSESP_Status.publish_time = DEFAULT_PUBLISHVALUES_TIME; // default value
recreate_config = true;
}
return recreate_config; // return false if some settings are missing and we need to rebuild the file
}
@@ -714,6 +721,7 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
json["test_mode"] = EMSESP_Status.test_mode;
json["shower_timer"] = EMSESP_Status.shower_timer;
json["shower_alert"] = EMSESP_Status.shower_alert;
json["publish_time"] = EMSESP_Status.publish_time;
return true;
}
@@ -823,6 +831,12 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
myDebug("Error. Usage: set shower_alert <on | off>");
}
}
// publish_time
if ((strcmp(setting, "publish_time") == 0) && (wc == 2)) {
EMSESP_Status.publish_time = atoi(value);
ok = true;
}
}
if (action == MYESP_FSACTION_LIST) {
@@ -848,6 +862,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
myDebug(" test_mode=%s", EMSESP_Status.test_mode ? "on" : "off");
myDebug(" shower_timer=%s", EMSESP_Status.shower_timer ? "on" : "off");
myDebug(" shower_alert=%s", EMSESP_Status.shower_alert ? "on" : "off");
myDebug(" publish_time=%d", EMSESP_Status.publish_time);
}
return ok;
@@ -896,8 +911,7 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
}
// shower settings
if (strcmp(first_cmd, "shower") == 0) {
if (wc == 2) {
if ((strcmp(first_cmd, "shower") == 0) && (wc == 2)) {
char * second_cmd = _readWord();
if (strcmp(second_cmd, "timer") == 0) {
EMSESP_Status.shower_timer = !EMSESP_Status.shower_timer;
@@ -909,11 +923,9 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ok = true;
}
}
}
// logging
if (strcmp(first_cmd, "log") == 0) {
if (wc == 2) {
if ((strcmp(first_cmd, "log") == 0) && (wc == 2)) {
char * second_cmd = _readWord();
if (strcmp(second_cmd, "v") == 0) {
ems_setLogging(EMS_SYS_LOGGING_VERBOSE);
@@ -932,11 +944,9 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ok = true;
}
}
}
// thermostat commands
if (strcmp(first_cmd, "thermostat") == 0) {
if (wc == 3) {
if ((strcmp(first_cmd, "thermostat") == 0) && (wc == 3)) {
char * second_cmd = _readWord();
if (strcmp(second_cmd, "temp") == 0) {
ems_setThermostatTemp(_readFloatNumber());
@@ -952,15 +962,25 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
ok = true;
}
}
}
// boiler commands
if (strcmp(first_cmd, "boiler") == 0) {
if (wc == 3) {
if ((strcmp(first_cmd, "boiler") == 0) && (wc == 3)) {
char * second_cmd = _readWord();
if (strcmp(second_cmd, "wwtemp") == 0) {
ems_setWarmWaterTemp(_readIntNumber());
ok = true;
} else if (strcmp(second_cmd, "comfort") == 0) {
char * third_cmd = _readWord();
if (strcmp(third_cmd, "hot") == 0) {
ems_setWarmWaterModeComfort(1);
ok = true;
} else if (strcmp(third_cmd, "eco") == 0) {
ems_setWarmWaterModeComfort(2);
ok = true;
} else if (strcmp(third_cmd, "intelligent") == 0) {
ems_setWarmWaterModeComfort(3);
ok = true;
}
} else if (strcmp(second_cmd, "read") == 0) {
ems_doReadCommand(_readHexNumber(), EMS_Boiler.type_id);
ok = true;
@@ -975,7 +995,6 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) {
}
}
}
}
// send raw
if (strcmp(first_cmd, "send") == 0) {
@@ -1009,6 +1028,7 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) {
myESP.mqttSubscribe(TOPIC_THERMOSTAT_CMD_MODE);
myESP.mqttSubscribe(TOPIC_BOILER_WWACTIVATED);
myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWTEMP);
myESP.mqttSubscribe(TOPIC_BOILER_CMD_COMFORT);
myESP.mqttSubscribe(TOPIC_SHOWER_TIMER);
myESP.mqttSubscribe(TOPIC_SHOWER_ALERT);
myESP.mqttSubscribe(TOPIC_SHOWER_COLDSHOT);
@@ -1070,6 +1090,19 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) {
publishValues(true); // publish back immediately
}
// boiler ww comfort setting
if (strcmp(topic, TOPIC_BOILER_CMD_COMFORT) == 0) {
myDebug("MQTT topic: boiler warm water comfort value is %s", message);
if (strcmp((char *)message, "hot") == 0) {
ems_setWarmWaterModeComfort(1);
} else if (strcmp((char *)message, "comfort") == 0) {
ems_setWarmWaterModeComfort(2);
} else if (strcmp((char *)message, "intelligent") == 0) {
ems_setWarmWaterModeComfort(3);
}
// publishValues(true); // publish back immediately
}
// shower timer
if (strcmp(topic, TOPIC_SHOWER_TIMER) == 0) {
if (message[0] == '1') {
@@ -1113,12 +1146,14 @@ void WIFICallback() {
}
// Initialize the boiler settings and shower settings
// Most of these will be overwritten after the SPIFFS config file is loaded
void initEMSESP() {
// general settings
EMSESP_Status.shower_timer = false;
EMSESP_Status.shower_alert = false;
EMSESP_Status.led_enabled = true; // LED is on by default
EMSESP_Status.test_mode = false;
EMSESP_Status.publish_time = DEFAULT_PUBLISHVALUES_TIME;
EMSESP_Status.timestamp = millis();
EMSESP_Status.dallas_sensors = 0;
@@ -1316,11 +1351,13 @@ void setup() {
// start up all the services
myESP.begin(APP_HOSTNAME, APP_NAME, APP_VERSION);
// at this point we have the settings from our internall SPIFFS config file
// enable regular checks if not in test mode
if (!EMSESP_Status.test_mode) {
publishValuesTimer.attach(PUBLISHVALUES_TIME, do_publishValues); // post MQTT values
publishValuesTimer.attach(EMSESP_Status.publish_time, do_publishValues); // post MQTT EMS values
publishSensorValuesTimer.attach(EMSESP_Status.publish_time, do_publishSensorValues); // post MQTT sensor values
regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS
publishSensorValuesTimer.attach(PUBLISHSENSORVALUES_TIME, do_publishSensorValues); // post MQTT sensor values
}
// set pin for LED
@@ -1360,5 +1397,5 @@ void loop() {
showerCheck();
}
delay(1); // some time to WiFi and everything else to catch up
delay(1); // some time to WiFi and everything else to catch up, and prevent overheating
}

View File

@@ -1740,7 +1740,7 @@ void ems_setWarmWaterModeComfort(uint8_t comfort) {
EMS_Sys_Status.txRetryCount = 0; // reset retry counter
if (comfort == 1) {
myDebug("Setting boiler warm water comfort mode to Comfort");
myDebug("Setting boiler warm water comfort mode to Hot");
EMS_TxTelegram.dataValue = EMS_VALUE_UBAParameterWW_wwComfort_Hot;
} else if (comfort == 2) {
myDebug("Setting boiler warm water comfort mode to Eco");

View File

@@ -37,6 +37,7 @@
#define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on
#define TOPIC_BOILER_WWACTIVATED "wwactivated" // for receiving MQTT message to change water on/off
#define TOPIC_BOILER_CMD_WWTEMP "boiler_cmd_wwtemp" // for received boiler wwtemp changes via MQTT
#define TOPIC_BOILER_CMD_COMFORT "boiler_cmd_comfort" // for received boiler ww comfort setting via MQTT
// shower time
#define TOPIC_SHOWERTIME "showertime" // for sending shower time results

View File

@@ -6,5 +6,5 @@
#pragma once
#define APP_NAME "EMS-ESP"
#define APP_VERSION "1.6.0b2"
#define APP_VERSION "1.6.0b3"
#define APP_HOSTNAME "ems-esp"