diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 0f13bcf7..3f52781d 100755
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -2,19 +2,24 @@ name: Build binary
on: [push, pull_request]
+env:
+ ARDUINO_BOARD_MANAGER_ADDITIONAL_URLS: http://arduino.esp8266.com/stable/package_esp8266com_index.json
+
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
- name: Setup Arduino CLI
- uses: arduino/setup-arduino-cli@v1
+ uses: arduino/setup-arduino-cli@v1.1.1
- name: Install platform
- run: arduino-cli core install esp8266:esp8266 --additional-urls https://arduino.esp8266.com/stable/package_esp8266com_index.json -v
+ run: |
+ arduino-cli core update-index
+ arduino-cli core install esp8266:esp8266
- name: Install dependencies
run: arduino-cli lib install ringbuffer pubsubclient doubleresetdetect arduinojson dallastemperature onewire WebSockets
diff --git a/HeatPumpType.md b/HeatPumpType.md
index 16dea466..b678b539 100644
--- a/HeatPumpType.md
+++ b/HeatPumpType.md
@@ -27,6 +27,12 @@ Assuming that bytes from #129 to #138 are unique for each model of Aquarea heat
|20 | C2 D3 0B 34 65 B2 D3 0B 95 65 | Monoblock | WH-MDC07J3E5 | Monoblock | 7 | 1ph | HP |
|21 | C2 D3 0B 35 65 B2 D3 0B 96 65 | Monoblock | WH-MDC09J3E5 | Monoblock | 9 | 1ph | HP |
|22 | 62 D2 0B 41 54 32 D2 0C 45 55 | WH-SDC0305J3E5 | WH-UD05JE5 | KIT-WC05J3E5 | 5 | 1ph | HP |
+|23 | 32 D4 0B 87 84 73 90 0C 84 84 | Monoblock | WH-MXC09J3E8 | Monoblock | 9 | 3ph | T-CAP |
+|24 | 32 D4 0B 88 84 73 90 0C 85 84 | MonoBlock | WH-MXC12J9E8 | Monoblock | 12 | 3ph | T-CAP |
+|25 | E2 CF 0B 75 09 12 D0 0C 06 11 | WH-ADC1216H6E5 | WH-UD12HE5 | KIT-ADC12HE5 | 12 | 1ph | T-CAP |
+|26 | 42 D4 0B 83 71 42 D2 0C 46 55 | WH-ADC0309J3E5C | WH-UD07JE5 | KIT-ADC07JE5C | 7 | 1ph | HP - All-In-One Compact |
+|27 | C2 D3 0C 34 65 B2 D3 0B 95 65 | Monoblock | WH-MDC07J3E5 | Monoblock | 7 | 1ph | HP (new version?) |
+|28 | C2 D3 0C 33 65 B2 D3 0B 94 65 | Monoblcok | WH-MDC05J3E5 | Monoblock | 5 | 1ph | HP (new version? |
All bytes are used for Heat Pump model identification in the code.
diff --git a/HeishaMon/HeishaMon.ino b/HeishaMon/HeishaMon.ino
index 2dbd58a3..d076e068 100755
--- a/HeishaMon/HeishaMon.ino
+++ b/HeishaMon/HeishaMon.ino
@@ -69,7 +69,7 @@ static int uploadpercentage = 0;
char data[MAXDATASIZE] = { '\0' };
byte data_length = 0;
-// store actual data
+// store actual data
String openTherm[2];
char actData[DATASIZE] = { '\0' };
#define OPTDATASIZE 20
@@ -117,7 +117,7 @@ void check_wifi()
if ((WiFi.status() != WL_CONNECTED) && (WiFi.localIP())) {
// special case where it seems that we are not connect but we do have working IP (causing the -1% wifi signal), do a reset.
log_message((char *)"Weird case, WiFi seems disconnected but is not. Resetting WiFi!");
- setupWifi(&heishamonSettings);
+ setupWifi(&heishamonSettings);
} else if ((WiFi.status() != WL_CONNECTED) || (!WiFi.localIP())) {
/*
if we are not connected to an AP
@@ -231,8 +231,8 @@ void mqtt_reconnect()
void log_message(const __FlashStringHelper *msg) {
PGM_P p = (PGM_P)msg;
int len = strlen_P((const char *)p);
- char *str = (char *)MALLOC(len+1);
- if(str == NULL) {
+ char *str = (char *)MALLOC(len + 1);
+ if (str == NULL) {
OUT_OF_MEMORY
}
strcpy_P(str, p);
@@ -307,7 +307,7 @@ bool readSerial()
{
int len = 0;
while ((Serial.available()) && (len < MAXDATASIZE)) {
- data[data_length+len] = Serial.read(); //read available data and place it after the last received data
+ data[data_length + len] = Serial.read(); //read available data and place it after the last received data
len++;
if (data[0] != 113) { //wrong header received!
log_message(F("Received bad header. Ignoring this data!"));
@@ -320,7 +320,7 @@ bool readSerial()
if ((len > 0) && (data_length == 0 )) totalreads++; //this is the start of a new read
data_length += len;
-
+
if (data_length > 1) { //should have received length part of header now
if ((data_length > (data[1] + 3)) || (data_length >= MAXDATASIZE) ) {
@@ -534,7 +534,7 @@ int8_t webserver_cb(struct webserver_t *client, void *dat) {
} else if (strcmp_P((char *)dat, PSTR("/factoryreset")) == 0) {
client->route = 90;
} else if (strcmp_P((char *)dat, PSTR("/command")) == 0) {
- if((client->userdata = malloc(1)) == NULL) {
+ if ((client->userdata = malloc(1)) == NULL) {
Serial1.printf(PSTR("Out of memory %s:#%d\n"), __FUNCTION__, __LINE__);
ESP.restart();
exit(-1);
@@ -701,7 +701,7 @@ int8_t webserver_cb(struct webserver_t *client, void *dat) {
case WEBSERVER_CLIENT_WRITE: {
switch (client->route) {
case 0: {
- if(client->content == 0) {
+ if (client->content == 0) {
webserver_send(client, 404, (char *)"text/plain", 13);
webserver_send_content_P(client, PSTR("404 Not found"), 13);
}
@@ -745,6 +745,12 @@ int8_t webserver_cb(struct webserver_t *client, void *dat) {
} break;
case 110: {
int ret = saveSettings(client, &heishamonSettings);
+ if (heishamonSettings.listenonly) {
+ //make sure we disable TX to heatpump-RX using the mosfet so this line is floating and will not disturb cz-taw1
+ digitalWrite(5, LOW);
+ } else {
+ digitalWrite(5, HIGH);
+ }
switch (client->route) {
case 111: {
return settingsNewPassword(client, &heishamonSettings);
@@ -825,7 +831,7 @@ int8_t webserver_cb(struct webserver_t *client, void *dat) {
return -1;
} break;
default: {
- if(client->route != 0) {
+ if (client->route != 0) {
header->ptr += sprintf_P((char *)header->buffer, PSTR("Access-Control-Allow-Origin: *"));
}
} break;
@@ -835,33 +841,33 @@ int8_t webserver_cb(struct webserver_t *client, void *dat) {
case WEBSERVER_CLIENT_CLOSE: {
switch (client->route) {
case 100: {
- if (client->userdata != NULL) {
- free(client->userdata);
- }
- } break;
+ if (client->userdata != NULL) {
+ free(client->userdata);
+ }
+ } break;
case 110: {
- struct websettings_t *tmp = NULL;
- while (client->userdata) {
- tmp = (struct websettings_t *)client->userdata;
- client->userdata = ((struct websettings_t *)(client->userdata))->next;
- free(tmp);
- }
- } break;
+ struct websettings_t *tmp = NULL;
+ while (client->userdata) {
+ tmp = (struct websettings_t *)client->userdata;
+ client->userdata = ((struct websettings_t *)(client->userdata))->next;
+ free(tmp);
+ }
+ } break;
case 160:
case 170: {
- if (client->userdata != NULL) {
- File *f = (File *)client->userdata;
- if (f) {
- if (*f) {
- f->close();
+ if (client->userdata != NULL) {
+ File *f = (File *)client->userdata;
+ if (f) {
+ if (*f) {
+ f->close();
+ }
+ delete f;
}
- delete f;
}
- }
- } break;
+ } break;
}
client->userdata = NULL;
- } break;
+ } break;
default: {
return 0;
} break;
@@ -928,9 +934,21 @@ void switchSerial() {
setupGPIO(heishamonSettings.gpioSettings); //switch extra GPIOs to configured mode
- //enable gpio15 after boot using gpio5 (D1) which enables the level shifter for the tx to panasonic
+ //mosfet output enable
pinMode(5, OUTPUT);
- digitalWrite(5, HIGH);
+
+ //try to detect if cz-taw1 is connected in parallel
+ if (!heishamonSettings.listenonly) {
+ if (Serial.available() > 0) {
+ log_message(F("There is data on the line without asking for it. Switching to listen only mode."));
+ heishamonSettings.listenonly = true;
+ }
+ else {
+ //enable gpio15 after boot using gpio5 (D1) which enables the level shifter for the tx to panasonic
+ //do not enable if listen only to keep the line floating
+ digitalWrite(5, HIGH);
+ }
+ }
}
void setupMqtt() {
@@ -941,6 +959,8 @@ void setupMqtt() {
}
void setupConditionals() {
+ //send_initial_query(); //maybe necessary but for now disable. CZ-TAW1 sends this query on boot
+
//load optional PCB data from flash
if (heishamonSettings.optionalPCB) {
if (loadOptionalPCB(optionalPCBQuery, OPTIONALPCBQUERYSIZE)) {
@@ -957,10 +977,12 @@ void setupConditionals() {
//these two after optional pcb because it needs to send a datagram fast after boot
if (heishamonSettings.use_1wire) initDallasSensors(log_message, heishamonSettings.updataAllDallasTime, heishamonSettings.waitDallasTime, heishamonSettings.dallasResolution);
if (heishamonSettings.use_s0) initS0Sensors(heishamonSettings.s0Settings);
+
+
}
void timer_cb(int nr) {
- if(nr > 0) {
+ if (nr > 0) {
rules_timer_cb(nr);
} else {
switch (nr) {
@@ -977,12 +999,12 @@ void timer_cb(int nr) {
setupWifi(&heishamonSettings);
} break;
case -4: {
- if(rules_parse("/rules.new") == -1) {
+ if (rules_parse("/rules.new") == -1) {
logprintln_P(F("new ruleset failed to parse, using previous ruleset"));
rules_parse("/rules.txt");
} else {
logprintln_P(F("new ruleset successfully parsed"));
- if(LittleFS.begin()) {
+ if (LittleFS.begin()) {
LittleFS.rename("/rules.new", "/rules.txt");
}
}
@@ -1034,18 +1056,15 @@ void setup() {
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(DNS_PORT, "*", apIP);
- //maybe necessary but for now disable. CZ-TAW1 sends this query on boot
- //if (!heishamonSettings.listenonly) send_initial_query();
-
rst_info *resetInfo = ESP.getResetInfoPtr();
Serial1.printf(PSTR("Reset reason: %d, exception cause: %d\n"), resetInfo->reason, resetInfo->exccause);
- if(resetInfo->reason > 0 && resetInfo->reason < 4) {
- if(LittleFS.begin()) {
+ if (resetInfo->reason > 0 && resetInfo->reason < 4) {
+ if (LittleFS.begin()) {
LittleFS.rename("/rules.txt", "/rules.old");
}
rules_setup();
- if(LittleFS.begin()) {
+ if (LittleFS.begin()) {
LittleFS.rename("/rules.old", "/rules.txt");
}
} else {
diff --git a/HeishaMon/commands.cpp b/HeishaMon/commands.cpp
index 068b5693..6a106312 100644
--- a/HeishaMon/commands.cpp
+++ b/HeishaMon/commands.cpp
@@ -595,6 +595,74 @@ unsigned int set_main_schedule(char *msg, unsigned char *cmd, char *log_msg) {
return sizeof(panasonicSendQuery);
}
+unsigned int set_alt_external_sensor(char *msg, unsigned char *cmd, char *log_msg) {
+
+ String set_alt_string(msg);
+
+ byte set_alt = 16;
+ if ( set_alt_string.toInt() == 1 ) {
+ set_alt = 32;
+ }
+
+ {
+ char tmp[256] = { 0 };
+ snprintf_P(tmp, 255, PSTR("set alternative external sensor to %d"), ((set_alt / 16) - 1) );
+ memcpy(log_msg, tmp, sizeof(tmp));
+ }
+
+ {
+ memcpy_P(cmd, panasonicSendQuery, sizeof(panasonicSendQuery));
+ cmd[20] = set_alt;
+ }
+
+ return sizeof(panasonicSendQuery);
+}
+
+unsigned int set_external_pad_heater(char *msg, unsigned char *cmd, char *log_msg) {
+
+ String set_pad_string(msg);
+
+ byte set_pad = 16;
+ if ( set_pad_string.toInt() == 1 ) {
+ set_pad = 32;
+ }
+ if ( set_pad_string.toInt() == 2 ) {
+ set_pad = 48;
+ }
+ {
+ char tmp[256] = { 0 };
+ snprintf_P(tmp, 255, PSTR("set external pad heater to %d"), ((set_pad / 16) - 1) );
+ memcpy(log_msg, tmp, sizeof(tmp));
+ }
+
+ {
+ memcpy_P(cmd, panasonicSendQuery, sizeof(panasonicSendQuery));
+ cmd[25] = set_pad;
+ }
+
+ return sizeof(panasonicSendQuery);
+}
+
+unsigned int set_buffer_delta(char *msg, unsigned char *cmd, char *log_msg) {
+
+ String set_temperature_string(msg);
+
+ byte request_temp = set_temperature_string.toInt() + 128;
+
+ {
+ char tmp[256] = { 0 };
+ snprintf_P(tmp, 255, PSTR("set buffer tank delta to %d"), request_temp - 128 );
+ memcpy(log_msg, tmp, sizeof(tmp));
+ }
+
+ {
+ memcpy_P(cmd, panasonicSendQuery, sizeof(panasonicSendQuery));
+ cmd[59] = request_temp;
+ }
+
+ return sizeof(panasonicSendQuery);
+}
+
//start of optional pcb commands
unsigned int set_byte_6(int val, int base, int bit, char *log_msg, const char *func) {
unsigned char hex = (optionalPCBQuery[6] & ~(base << bit)) | (val << bit);
diff --git a/HeishaMon/commands.h b/HeishaMon/commands.h
index 853a5e58..a4ef3daf 100644
--- a/HeishaMon/commands.h
+++ b/HeishaMon/commands.h
@@ -52,6 +52,9 @@ unsigned int set_heater_delay_time(char *msg, unsigned char *cmd, char *log_msg)
unsigned int set_heater_start_delta(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_heater_stop_delta(char *msg, unsigned char *cmd, char *log_msg);
unsigned int set_main_schedule(char *msg, unsigned char *cmd, char *log_msg);
+unsigned int set_alt_external_sensor(char *msg, unsigned char *cmd, char *log_msg);
+unsigned int set_external_pad_heater(char *msg, unsigned char *cmd, char *log_msg);
+unsigned int set_buffer_delta(char *msg, unsigned char *cmd, char *log_msg);
//optional pcb commands
unsigned int set_heat_cool_mode(char *msg, char *log_msg);
@@ -117,6 +120,9 @@ const cmdStruct commands[] PROGMEM = {
{ "SetHeaterStartDelta", set_heater_start_delta },
{ "SetHeaterStopDelta", set_heater_stop_delta },
{ "SetMainSchedule", set_main_schedule },
+ { "SetAltExternalSensor", set_alt_external_sensor },
+ { "SetExternalPadHeater", set_external_pad_heater },
+ { "SetBufferDelta", set_buffer_delta },
};
struct optCmdStruct{
diff --git a/HeishaMon/decode.cpp b/HeishaMon/decode.cpp
index a45a1c73..a3763688 100644
--- a/HeishaMon/decode.cpp
+++ b/HeishaMon/decode.cpp
@@ -5,6 +5,10 @@
unsigned long lastalldatatime = 0;
unsigned long lastalloptdatatime = 0;
+String getBit1(byte input) {
+ return String(input >> 7);
+}
+
String getBit1and2(byte input) {
return String((input >> 6) - 1);
}
@@ -142,6 +146,52 @@ String getDataValue(char* data, unsigned int Topic_Number) {
case 1:
Topic_Value = getPumpFlow(data);
break;
+ case 5: {
+ byte cpy;
+ memcpy_P(&cpy, &topicBytes[Topic_Number], sizeof(byte));
+ Input_Byte = data[cpy];
+ Topic_Value = topicFunctions[Topic_Number](Input_Byte);
+ int fractional = (int)(data[118] & 0b111);
+ switch (fractional) {
+ case 1: // fractional .00
+ break;
+ case 2: // fractional .25
+ Topic_Value = Topic_Value + ".25";
+ break;
+ case 3: // fractional .50
+ Topic_Value = Topic_Value + ".50";
+ break;
+ case 4: // fractional .75
+ Topic_Value = Topic_Value + ".75";
+ break;
+ default:
+ break;
+ }
+ }
+ break;
+ case 6: {
+ byte cpy;
+ memcpy_P(&cpy, &topicBytes[Topic_Number], sizeof(byte));
+ Input_Byte = data[cpy];
+ Topic_Value = topicFunctions[Topic_Number](Input_Byte);
+ int fractional = (int)((data[118] >> 3) & 0b111) ;
+ switch (fractional) {
+ case 1: // fractional .00
+ break;
+ case 2: // fractional .25
+ Topic_Value = Topic_Value + ".25";
+ break;
+ case 3: // fractional .50
+ Topic_Value = Topic_Value + ".50";
+ break;
+ case 4: // fractional .75
+ Topic_Value = Topic_Value + ".75";
+ break;
+ default:
+ break;
+ }
+ }
+ break;
case 11:
Topic_Value = String(word(data[183], data[182]) - 1);
break;
@@ -200,6 +250,16 @@ String getOptDataValue(char* data, unsigned int Topic_Number) {
return Topic_Value;
}
+String getFirstByte(byte input) {
+ return String((input >> 4) - 1);
+}
+
+String getSecondByte(byte input) {
+ return String((input & 0b1111) - 1);
+}
+
+
+
// Decode ////////////////////////////////////////////////////////////////////////////
void decode_heatpump_data(char* data, char* actData, PubSubClient &mqtt_client, void (*log_message)(char*), char* mqtt_topic_base, unsigned int updateAllTime) {
bool updatenow = false;
diff --git a/HeishaMon/decode.h b/HeishaMon/decode.h
index 18d83df5..608e659e 100644
--- a/HeishaMon/decode.h
+++ b/HeishaMon/decode.h
@@ -12,6 +12,7 @@ void decode_heatpump_data(char* data, char* actData, PubSubClient &mqtt_client,
void decode_optional_heatpump_data(char* data, char* actOptDat, PubSubClient &mqtt_client, void (*log_message)(char*), char* mqtt_topic_base, unsigned int updateAllTime);
String unknown(byte input);
+String getBit1(byte input);
String getBit1and2(byte input);
String getBit3and4(byte input);
String getBit5and6(byte input);
@@ -28,63 +29,77 @@ String getOpMode(byte input);
String getEnergy(byte input);
String getHeatMode(byte input);
String getModel(byte input);
+String getFirstByte(byte input);
+String getSecondByte(byte input);
static const char _unknown[] PROGMEM = "unknown";
static const char *Model[] PROGMEM = {
- "23", //string representation of number of known models
- "WH-MDC05H3E5",
- "WH-MDC07H3E5",
- "IDU:WH-SXC09H3E5, ODU:WH-UX09HE5",
- "IDU:WH-SDC09H3E8, ODU:WH-UD09HE8",
- "IDU:WH-SXC09H3E8, ODU:WH-UX09HE8",
- "IDU:WH-SXC12H9E8, ODU:WH-UX12HE8",
- "IDU:WH-SXC16H9E8, ODU:WH-UX16HE8",
- "IDU:WH-SDC05H3E5, ODU:WH-UD05HE5",
- "IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5",
- "WH-MDC05J3E5",
- "WH-MDC09H3E5",
- "WH-MXC09H3E5",
- "IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5",
- "IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8",
- "IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8",
- "IDU:WH-SDC09H3E5, ODU:WH-UD09HE5",
- "IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5",
- "IDU:WH-ADC0309J3E5, ODU: WH-UD05JE5",
- "IDU: WH-SDC0709J3E5, ODU: WH-UD07JE5",
- "IDU: WH-SDC07H3E5-1 ODU: WH-UD07HE5-1",
- "WH-MDC07J3E5",
- "WH-MDC09J3E5",
- "IDU: WH-SDC0305J3E5 ODU: WH-UD05JE5",
+ "29", //string representation of number of known models (last model number + 1)
+ "WH-MDC05H3E5", //0
+ "WH-MDC07H3E5", //1
+ "IDU:WH-SXC09H3E5, ODU:WH-UX09HE5", //2
+ "IDU:WH-SDC09H3E8, ODU:WH-UD09HE8", //3
+ "IDU:WH-SXC09H3E8, ODU:WH-UX09HE8", //4
+ "IDU:WH-SXC12H9E8, ODU:WH-UX12HE8", //5
+ "IDU:WH-SXC16H9E8, ODU:WH-UX16HE8", //6
+ "IDU:WH-SDC05H3E5, ODU:WH-UD05HE5", //7
+ "IDU:WH-SDC0709J3E5, ODU:WH-UD09JE5", //8
+ "WH-MDC05J3E5", //9
+ "WH-MDC09H3E5", //10
+ "WH-MXC09H3E5", //11
+ "IDU:WH-ADC0309J3E5, ODU:WH-UD09JE5", //12
+ "IDU:WH-ADC0916H9E8, ODU:WH-UX12HE8", //13
+ "IDU:WH-SQC09H3E8, ODU:WH-UQ09HE8", //14
+ "IDU:WH-SDC09H3E5, ODU:WH-UD09HE5", //15
+ "IDU:WH-ADC0309H3E5, ODU:WH-UD09HE5", //16
+ "IDU:WH-ADC0309J3E5, ODU: WH-UD05JE5", //17
+ "IDU: WH-SDC0709J3E5, ODU: WH-UD07JE5", //18
+ "IDU: WH-SDC07H3E5-1 ODU: WH-UD07HE5-1", //19
+ "WH-MDC07J3E5", //20
+ "WH-MDC09J3E5", //21
+ "IDU: WH-SDC0305J3E5 ODU: WH-UD05JE5", //22
+ "WH-MXC09J3E8", //23
+ "WH-MXC12J9E8", //24
+ "IDU: WH-ADC1216H6E5 ODU: WH-UD12HE5", //25
+ "IDU: WH-ADC0309J3E5C ODU: WH-UD07JE5", //26
+ "WH-MDC07J3E5", //27
+ "WH-MDC05J3E5", //28
};
static const byte knownModels[sizeof(Model) / sizeof(Model[0])][10] PROGMEM = { //stores the bytes #129 to #138 of known models in the same order as the const above
- 0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33,
- 0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33,
- 0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11,
- 0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05,
- 0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05,
- 0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05,
- 0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05,
- 0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81,
- 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66,
- 0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65,
- 0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33,
- 0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35,
- 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55,
- 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05,
- 0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05,
- 0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08,
- 0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08,
- 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55,
- 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55,
- 0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08,
- 0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65,
- 0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65,
- 0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55,
+ 0xE2, 0xCF, 0x0B, 0x13, 0x33, 0x32, 0xD1, 0x0C, 0x16, 0x33, //0
+ 0xE2, 0xCF, 0x0B, 0x14, 0x33, 0x42, 0xD1, 0x0B, 0x17, 0x33, //1
+ 0xE2, 0xCF, 0x0D, 0x77, 0x09, 0x12, 0xD0, 0x0B, 0x05, 0x11, //2
+ 0xE2, 0xCF, 0x0C, 0x88, 0x05, 0x12, 0xD0, 0x0B, 0x97, 0x05, //3
+ 0xE2, 0xCF, 0x0D, 0x85, 0x05, 0x12, 0xD0, 0x0C, 0x94, 0x05, //4
+ 0xE2, 0xCF, 0x0D, 0x86, 0x05, 0x12, 0xD0, 0x0C, 0x95, 0x05, //5
+ 0xE2, 0xCF, 0x0D, 0x87, 0x05, 0x12, 0xD0, 0x0C, 0x96, 0x05, //6
+ 0xE2, 0xCE, 0x0D, 0x71, 0x81, 0x72, 0xCE, 0x0C, 0x92, 0x81, //7
+ 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0B, 0x72, 0x66, //8
+ 0xC2, 0xD3, 0x0B, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //9
+ 0xE2, 0xCF, 0x0B, 0x15, 0x33, 0x42, 0xD1, 0x0B, 0x18, 0x33, //10
+ 0xE2, 0xCF, 0x0B, 0x41, 0x34, 0x82, 0xD1, 0x0B, 0x31, 0x35, //11
+ 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x42, 0xD2, 0x0B, 0x47, 0x55, //12
+ 0xE2, 0xCF, 0x0C, 0x74, 0x09, 0x12, 0xD0, 0x0D, 0x95, 0x05, //13
+ 0xE2, 0xCF, 0x0B, 0x82, 0x05, 0x12, 0xD0, 0x0C, 0x91, 0x05, //14
+ 0xE2, 0xCF, 0x0C, 0x55, 0x14, 0x12, 0xD0, 0x0B, 0x15, 0x08, //15
+ 0xE2, 0xCF, 0x0C, 0x43, 0x00, 0x12, 0xD0, 0x0B, 0x15, 0x08, //16
+ 0x62, 0xD2, 0x0B, 0x45, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //17
+ 0x62, 0xD2, 0x0B, 0x43, 0x54, 0x42, 0xD2, 0x0C, 0x46, 0x55, //18
+ 0xE2, 0xCF, 0x0C, 0x54, 0x14, 0x12, 0xD0, 0x0B, 0x14, 0x08, //19
+ 0xC2, 0xD3, 0x0B, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //20
+ 0xC2, 0xD3, 0x0B, 0x35, 0x65, 0xB2, 0xD3, 0x0B, 0x96, 0x65, //21
+ 0x62, 0xD2, 0x0B, 0x41, 0x54, 0x32, 0xD2, 0x0C, 0x45, 0x55, //22
+ 0x32, 0xD4, 0x0B, 0x87, 0x84, 0x73, 0x90, 0x0C, 0x84, 0x84, //23
+ 0x32, 0xD4, 0x0B, 0x88, 0x84, 0x73, 0x90, 0x0C, 0x85, 0x84, //24
+ 0xE2, 0xCF, 0x0B, 0x75, 0x09, 0x12, 0xD0, 0x0C, 0x06, 0x11, //25
+ 0x42, 0xD4, 0x0B, 0x83, 0x71, 0x42, 0xD2, 0x0C, 0x46, 0x55, //26
+ 0xC2, 0xD3, 0x0C, 0x34, 0x65, 0xB2, 0xD3, 0x0B, 0x95, 0x65, //27
+ 0xC2, 0xD3, 0x0C, 0x33, 0x65, 0xB2, 0xD3, 0x0B, 0x94, 0x65, //28
};
-#define NUMBER_OF_TOPICS 107 //last topic number + 1
+#define NUMBER_OF_TOPICS 115 //last topic number + 1
#define NUMBER_OF_OPT_TOPICS 7 //last topic number + 1
#define MAX_TOPIC_LEN 41 // max length + 1
@@ -189,23 +204,31 @@ static const char topics[][MAX_TOPIC_LEN] PROGMEM = {
"Z2_Cool_Curve_Target_Low_Temp", //TOP87
"Z2_Cool_Curve_Outside_High_Temp", //TOP88
"Z2_Cool_Curve_Outside_Low_Temp", //TOP89
- "Room_Heater_Operations_Hours", //TOP90
- "DHW_Heater_Operations_Hours", //TOP91
- "Heat_Pump_Model", //TOP92,
- "Pump_Duty", //TOP93
- "Zones_State", //TOP94
- "Max_Pump_Duty", //TOP95
- "Heater_Delay_Time", //TOP96
- "Heater_Start_Delta", //TOP97
- "Heater_Stop_Delta", //TOP98
- "Buffer_Installed", //TOP99
- "DHW_Installed", //TOP100
- "Solar_Mode", //TOP101
- "Solar_On_Delta", //TOP102
- "Solar_Off_Delta", //TOP103
- "Solar_Frost_Protection", //TOP104
- "Solar_High_Limit", //TOP105
- "Pump_Flowrate_Mode", //TOP106
+ "Room_Heater_Operations_Hours", //TOP90
+ "DHW_Heater_Operations_Hours", //TOP91
+ "Heat_Pump_Model", //TOP92
+ "Pump_Duty", //TOP93
+ "Zones_State", //TOP94
+ "Max_Pump_Duty", //TOP95
+ "Heater_Delay_Time", //TOP96
+ "Heater_Start_Delta", //TOP97
+ "Heater_Stop_Delta", //TOP98
+ "Buffer_Installed", //TOP99
+ "DHW_Installed", //TOP100
+ "Solar_Mode", //TOP101
+ "Solar_On_Delta", //TOP102
+ "Solar_Off_Delta", //TOP103
+ "Solar_Frost_Protection", //TOP104
+ "Solar_High_Limit", //TOP105
+ "Pump_Flowrate_Mode", //TOP106
+ "Liquid_Type", //TOP107
+ "Alt_External_Sensor", //TOP108
+ "Anti_Freeze_Mode", //TOP109
+ "Optional_PCB", //TOP110
+ "Z1_Sensor_Settings", //TOP111
+ "Z2_Sensor_Settings", //TOP112
+ "Buffer_Tank_Delta", //TOP113
+ "External_Pad_Heater", //TOP114
};
static const byte topicBytes[] PROGMEM = { //can store the index as byte (8-bit unsigned humber) as there aren't more then 255 bytes (actually only 203 bytes) to decode
@@ -316,6 +339,14 @@ static const byte topicBytes[] PROGMEM = { //can store the index as byte (8-bit
63, //TOP104
64, //TOP105
29, //TOP106
+ 20, //TOP107
+ 20, //TOP108
+ 20, //TOP109
+ 20, //TOP110
+ 22, //TOP111
+ 22, //TOP112
+ 59, //TOP113
+ 25, //TOP114
};
typedef String (*topicFP)(byte);
@@ -428,6 +459,14 @@ static const topicFP topicFunctions[] PROGMEM = {
getIntMinus128, //TOP104
getIntMinus128, //TOP105
getBit3and4, //TOP106
+ getBit1, //TOP107
+ getBit3and4, //TOP108
+ getBit5and6, //TOP109
+ getBit7and8, //TOP110
+ getSecondByte, //TOP111
+ getFirstByte, //TOP112
+ getIntMinus128, //TOP113
+ getBit3and4, //TOP114
};
static const char *DisabledEnabled[] PROGMEM = {"2", "Disabled", "Enabled"};
@@ -456,6 +495,9 @@ static const char *Duty[] PROGMEM = {"0", "Duty"};
static const char *ZonesState[] PROGMEM = {"3", "Zone1 active", "Zone2 active", "Zone1 and zone2 active"};
static const char *HeatCoolModeDesc[] PROGMEM = {"2", "Comp. Curve", "Direct"};
static const char *SolarModeDesc[] PROGMEM = {"3", "Disabled", "Buffer", "DHW"};
+static const char *ZonesSensorType[] PROGMEM = {"4", "Water Temperature", "External Thermostat", "Internal Thermostat", "Thermistor"};
+static const char *LiquidType[] PROGMEM = {"2", "Water", "Glycol"};
+static const char *ExtPadHeaterType[] PROGMEM = {"3", "Disabled", "Type-A","Type-B"};
static const char **topicDescription[] PROGMEM = {
OffOn, //TOP0
@@ -565,4 +607,12 @@ static const char **topicDescription[] PROGMEM = {
Celsius, //TOP104
Celsius, //TOP105
PumpFlowRateMode,//TOP106
+ LiquidType, //TOP107
+ DisabledEnabled, //TOP108
+ DisabledEnabled, //TOP109
+ DisabledEnabled, //TOP110
+ ZonesSensorType, //TOP111
+ ZonesSensorType, //TOP112
+ Kelvin, //TOP113
+ ExtPadHeaterType,//TOP114
};
diff --git a/HeishaMon/htmlcode.h b/HeishaMon/htmlcode.h
index 9c5d9454..70610ae7 100644
--- a/HeishaMon/htmlcode.h
+++ b/HeishaMon/htmlcode.h
@@ -203,6 +203,7 @@ static const char webBodyRootStatusMemory[] PROGMEM = "%
Memory free: ";
static const char webBodyRootStatusReceived[] PROGMEM = "%
Correct received data: ";
static const char webBodyRootStatusReconnects[] PROGMEM = "%
MQTT reconnects: ";
static const char webBodyRootStatusUptime[] PROGMEM = "
Uptime: ";
+static const char webBodyRootStatusListenOnly[] PROGMEM = "
Listen only mode active";
static const char webBodyRootHeatpumpValues[] PROGMEM =
"