diff --git a/src/ems-esp.ino b/src/ems-esp.ino index ce967b881..21da5807f 100644 --- a/src/ems-esp.ino +++ b/src/ems-esp.ino @@ -67,7 +67,7 @@ typedef struct { bool shower_timer; // true if we want to report back on shower times 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 + bool silent_mode; // stop automatic Tx on/off uint16_t publish_time; // frequency of MQTT publish in seconds uint8_t led_gpio; uint8_t dallas_gpio; @@ -90,7 +90,7 @@ command_t PROGMEM project_cmds[] = { {true, "dallas_parasite ", "set to on if powering Dallas via parasite"}, {true, "thermostat_type ", "set the thermostat type id (e.g. 10 for 0x10)"}, {true, "boiler_type ", "set the boiler type id (e.g. 8 for 0x08)"}, - {true, "test_mode ", "test_mode turns on/off all automatic reads"}, + {true, "silent_mode ", "when on all automatic Tx is disabled"}, {true, "shower_timer ", "notify via MQTT all shower durations"}, {true, "shower_alert ", "send a warning of cold water after shower time is exceeded"}, {false, "info", "show data captured on the EMS bus"}, @@ -109,7 +109,8 @@ command_t PROGMEM project_cmds[] = { {false, "boiler read ", "send read request to boiler"}, {false, "boiler wwtemp ", "set boiler warm water temperature"}, {false, "boiler tapwater ", "set boiler warm tap water on/off"}, - {false, "boiler comfort ", "set boiler warm water comfort setting"} + {false, "boiler comfort ", "set boiler warm water comfort setting"}, + {false, "startup", "send startup sequence to bus master - still experimental"} }; @@ -275,7 +276,7 @@ void showInfo() { myDebug(" System logging set to None"); } - myDebug(" LED is %s, Test Mode is %s", EMSESP_Status.led_enabled ? "on" : "off", EMSESP_Status.test_mode ? "on" : "off"); + myDebug(" LED is %s, Silent mode is %s", EMSESP_Status.led_enabled ? "on" : "off", EMSESP_Status.silent_mode ? "on" : "off"); myDebug(" # connected Dallas temperature sensors=%d", EMSESP_Status.dallas_sensors); myDebug(" Thermostat is %s, Boiler is %s, Shower Timer is %s, Shower Alert is %s", @@ -285,8 +286,9 @@ void showInfo() { ((EMSESP_Status.shower_alert) ? "enabled" : "disabled")); 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", + myDebug(" Bus Connected=%s, Tx is %s, # Rx telegrams=%d, # Tx telegrams=%d, # Crc Errors=%d", (ems_getBusConnected() ? "yes" : "no"), + (ems_getTxCapable() ? "active" : "not active"), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emsTxPkgs, EMS_Sys_Status.emxCrcErr); @@ -365,7 +367,7 @@ void showInfo() { } _renderFloatValue("Boiler temperature", "C", EMS_Boiler.boilTemp); _renderIntValue("Pump modulation", "%", EMS_Boiler.pumpMod); - _renderLongValue("Burner # restarts", "times", EMS_Boiler.burnStarts); + _renderLongValue("Burner # starts", "times", EMS_Boiler.burnStarts); if (EMS_Boiler.burnWorkMin != EMS_VALUE_LONG_NOTSET) { myDebug(" Total burner operating time: %d days %d hours %d minutes", EMS_Boiler.burnWorkMin / 1440, @@ -685,9 +687,12 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) { } // test mode - if (!(EMSESP_Status.test_mode = json["test_mode"])) { - EMSESP_Status.test_mode = false; // default value - recreate_config = true; + if (!(EMSESP_Status.silent_mode = json["silent_mode"])) { + EMSESP_Status.silent_mode = false; // default value + ems_setTxDisabled(false); + recreate_config = true; + } else { + ems_setTxDisabled(true); // silent_mpde is on } // shower_timer @@ -718,7 +723,7 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) { json["dallas_parasite"] = EMSESP_Status.dallas_parasite; json["thermostat_type"] = EMS_Thermostat.type_id; json["boiler_type"] = EMS_Boiler.type_id; - json["test_mode"] = EMSESP_Status.test_mode; + json["silent_mode"] = EMSESP_Status.silent_mode; json["shower_timer"] = EMSESP_Status.shower_timer; json["shower_alert"] = EMSESP_Status.shower_alert; json["publish_time"] = EMSESP_Status.publish_time; @@ -753,16 +758,19 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c } // test mode - if ((strcmp(setting, "test_mode") == 0) && (wc == 2)) { + if ((strcmp(setting, "silent_mode") == 0) && (wc == 2)) { if (strcmp(value, "on") == 0) { - EMSESP_Status.test_mode = true; - ok = true; - myDebug("* Reboot to go into test mode."); + EMSESP_Status.silent_mode = true; + ok = true; + myDebug("* in Silent mode. All Tx is disabled."); + ems_setTxDisabled(true); } else if (strcmp(value, "off") == 0) { - EMSESP_Status.test_mode = false; - ok = true; + EMSESP_Status.silent_mode = false; + ok = true; + ems_setTxDisabled(false); + myDebug("* out of Silent mode. Tx is enabled."); } else { - myDebug("Error. Usage: set test_mode "); + myDebug("Error. Usage: set silent_mode "); } } @@ -859,7 +867,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c myDebug(" boiler_type=%02X", EMS_Boiler.type_id); } - myDebug(" test_mode=%s", EMSESP_Status.test_mode ? "on" : "off"); + myDebug(" silent_mode=%s", EMSESP_Status.silent_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); @@ -910,6 +918,11 @@ void TelnetCommandCallback(uint8_t wc, const char * commandLine) { ok = true; } + if (strcmp(first_cmd, "startup") == 0) { + ems_startupTelegrams(); + ok = true; + } + // shower settings if ((strcmp(first_cmd, "shower") == 0) && (wc == 2)) { char * second_cmd = _readWord(); @@ -1140,8 +1153,10 @@ void WIFICallback() { } else { emsuart_init(); myDebug("[UART] Opened Rx/Tx connection"); - // go and find the boiler and thermostat types - ems_discoverModels(); + if (!EMSESP_Status.silent_mode) { + // go and find the boiler and thermostat types, if not in silent mode + ems_discoverModels(); + } } } @@ -1152,7 +1167,7 @@ void initEMSESP() { 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.silent_mode = false; EMSESP_Status.publish_time = DEFAULT_PUBLISHVALUES_TIME; EMSESP_Status.timestamp = millis(); @@ -1354,7 +1369,7 @@ void setup() { // 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) { + if (!EMSESP_Status.silent_mode) { 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 @@ -1387,7 +1402,7 @@ void loop() { // publish the values to MQTT, only if the values have changed // although we don't want to publish when doing a deep scan of the thermostat - if (ems_getEmsRefreshed() && (scanThermostat_count == 0) && (!EMSESP_Status.test_mode)) { + if (ems_getEmsRefreshed() && (scanThermostat_count == 0) && (!EMSESP_Status.silent_mode)) { publishValues(false); ems_setEmsRefreshed(false); // reset } diff --git a/src/ems.cpp b/src/ems.cpp index 1724e2b76..1db816e0b 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -118,7 +118,7 @@ const _EMS_Type EMS_Types[] = { }; -// calculate sizes of arrays +// calculate sizes of arrays at compile uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types uint8_t _Boiler_Types_max = ArraySize(Boiler_Types); // number of models uint8_t _Thermostat_Types_max = ArraySize(Thermostat_Types); // number of defined thermostat types @@ -162,6 +162,7 @@ void ems_init() { EMS_Sys_Status.emsBusConnected = false; EMS_Sys_Status.emsRxTimestamp = 0; EMS_Sys_Status.emsTxCapable = false; + EMS_Sys_Status.emsTxDisabled = false; EMS_Sys_Status.emsPollTimestamp = 0; EMS_Sys_Status.txRetryCount = 0; @@ -234,12 +235,12 @@ void ems_init() { // set boiler type EMS_Boiler.product_id = 0; - strlcpy(EMS_Boiler.version, "not set", sizeof(EMS_Boiler.version)); + strlcpy(EMS_Boiler.version, "?", sizeof(EMS_Boiler.version)); // set thermostat model EMS_Thermostat.model_id = EMS_MODEL_NONE; EMS_Thermostat.product_id = 0; - strlcpy(EMS_Thermostat.version, "not set", sizeof(EMS_Thermostat.version)); + strlcpy(EMS_Thermostat.version, "?", sizeof(EMS_Thermostat.version)); // default logging is none ems_setLogging(EMS_SYS_LOGGING_DEFAULT); @@ -275,6 +276,10 @@ uint8_t ems_getThermostatModel() { return (EMS_Thermostat.model_id); } +void ems_setTxDisabled(bool b) { + EMS_Sys_Status.emsTxDisabled = b; +} + bool ems_getTxCapable() { if ((millis() - EMS_Sys_Status.emsPollTimestamp) > EMS_POLL_TIMEOUT) { EMS_Sys_Status.emsTxCapable = false; @@ -392,7 +397,7 @@ char * _smallitoa(uint8_t value, char * buffer) { } /* for decimals 0 to 999, printed as a string - * From Simon Arlott @nomis + * From @nomis */ char * _smallitoa3(uint16_t value, char * buffer) { buffer[0] = ((value / 100) == 0) ? '0' : (value / 100) + '0'; @@ -406,24 +411,24 @@ char * _smallitoa3(uint16_t value, char * buffer) { * debug print a telegram to telnet/serial including the CRC * len is length in bytes including the CRC */ -void _debugPrintTelegram(const char * prefix, uint8_t * data, uint8_t len, const char * color) { +void _debugPrintTelegram(const char * prefix, _EMS_RxTelegram EMS_RxTelegram, const char * color) { if (EMS_Sys_Status.emsLogging <= EMS_SYS_LOGGING_BASIC) return; - char output_str[200] = {0}; - char buffer[16] = {0}; + char output_str[200] = {0}; + char buffer[16] = {0}; + uint8_t len = EMS_RxTelegram.length; + uint8_t * data = EMS_RxTelegram.telegram; - unsigned long upt = millis(); - strlcpy(output_str, "(", sizeof(output_str)); strlcat(output_str, COLOR_CYAN, sizeof(output_str)); - strlcat(output_str, _smallitoa((uint8_t)((upt / 3600000) % 24), buffer), sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((EMS_RxTelegram.timestamp / 3600000) % 24), buffer), sizeof(output_str)); strlcat(output_str, ":", sizeof(output_str)); - strlcat(output_str, _smallitoa((uint8_t)((upt / 60000) % 60), buffer), sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((EMS_RxTelegram.timestamp / 60000) % 60), buffer), sizeof(output_str)); strlcat(output_str, ":", sizeof(output_str)); - strlcat(output_str, _smallitoa((uint8_t)((upt / 1000) % 60), buffer), sizeof(output_str)); + strlcat(output_str, _smallitoa((uint8_t)((EMS_RxTelegram.timestamp / 1000) % 60), buffer), sizeof(output_str)); strlcat(output_str, ".", sizeof(output_str)); - strlcat(output_str, _smallitoa3(upt % 1000, buffer), sizeof(output_str)); + strlcat(output_str, _smallitoa3(EMS_RxTelegram.timestamp % 1000, buffer), sizeof(output_str)); strlcat(output_str, COLOR_RESET, sizeof(output_str)); strlcat(output_str, ") ", sizeof(output_str)); @@ -468,9 +473,13 @@ void _ems_sendTelegram() { // if we're in raw mode just fire and forget if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_RAW) { EMS_TxTelegram.data[EMS_TxTelegram.length - 1] = _crcCalculator(EMS_TxTelegram.data, EMS_TxTelegram.length); // add the CRC - _debugPrintTelegram("Sending raw", EMS_TxTelegram.data, EMS_TxTelegram.length, COLOR_CYAN); // always show - emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx - EMS_TxQueue.shift(); // remove from queue + _EMS_RxTelegram EMS_RxTelegram; + EMS_RxTelegram.length = EMS_TxTelegram.length; + EMS_RxTelegram.telegram = EMS_TxTelegram.data; + EMS_RxTelegram.timestamp = millis(); // now + _debugPrintTelegram("Sending raw", EMS_RxTelegram, COLOR_CYAN); // always show + emsuart_tx_buffer(EMS_TxTelegram.data, EMS_TxTelegram.length); // send the telegram to the UART Tx + EMS_TxQueue.shift(); // remove from queue return; } @@ -514,7 +523,11 @@ void _ems_sendTelegram() { snprintf(s, sizeof(s), "Sending validate of type 0x%02X to 0x%02X:", EMS_TxTelegram.type, EMS_TxTelegram.dest & 0x7F); } - _debugPrintTelegram(s, EMS_TxTelegram.data, EMS_TxTelegram.length, COLOR_CYAN); + _EMS_RxTelegram EMS_RxTelegram; + EMS_RxTelegram.length = EMS_TxTelegram.length; + EMS_RxTelegram.telegram = EMS_TxTelegram.data; + EMS_RxTelegram.timestamp = millis(); // now + _debugPrintTelegram(s, EMS_RxTelegram, COLOR_CYAN); } // send the telegram to the UART Tx @@ -577,12 +590,19 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { // check if we just received a single byte // it could well be a Poll request from the boiler for us, which will have a value of 0x8B (0x0B | 0x80) // or either a return code like 0x01 or 0x04 from the last Write command + + // create the Rx package + _EMS_RxTelegram EMS_RxTelegram; + EMS_RxTelegram.length = length; + EMS_RxTelegram.telegram = telegram; + EMS_RxTelegram.timestamp = millis(); + if (length == 1) { uint8_t value = telegram[0]; // 1st byte of data package // check first for a Poll for us if (value == (EMS_ID_ME | 0x80)) { - EMS_Sys_Status.emsPollTimestamp = millis(); // store when we received a last poll + EMS_Sys_Status.emsPollTimestamp = EMS_RxTelegram.timestamp; // store when we received a last poll EMS_Sys_Status.emsTxCapable = true; // do we have something to send thats waiting in the Tx queue? @@ -628,7 +648,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { if (telegram[length - 1] != crc) { EMS_Sys_Status.emxCrcErr++; if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { - _debugPrintTelegram("Corrupt telegram:", telegram, length, COLOR_RED); + _debugPrintTelegram("Corrupt telegram:", EMS_RxTelegram, COLOR_RED); } return; } @@ -647,24 +667,25 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { // here we know its a valid incoming telegram of at least 6 bytes // we use this to see if we always have a connection to the boiler, in case of drop outs - EMS_Sys_Status.emsRxTimestamp = millis(); // timestamp of last read + EMS_Sys_Status.emsRxTimestamp = EMS_RxTelegram.timestamp; // timestamp of last read EMS_Sys_Status.emsBusConnected = true; // now lets process it and see what to do next - _processType(telegram, length); + _processType(EMS_RxTelegram); } /** * print detailed telegram * and then call its callback if there is one defined */ -void _ems_processTelegram(uint8_t * telegram, uint8_t length) { +void _ems_processTelegram(_EMS_RxTelegram EMS_RxTelegram) { // header - uint8_t src = telegram[0] & 0x7F; - uint8_t dest = telegram[1] & 0x7F; // remove 8th bit to handle both reads and writes - uint8_t type = telegram[2]; - uint8_t offset = telegram[3]; - uint8_t * data = telegram + 4; // data block starts at position 5 + uint8_t * telegram = EMS_RxTelegram.telegram; + uint8_t src = telegram[0] & 0x7F; + uint8_t dest = telegram[1] & 0x7F; // remove 8th bit to handle both reads and writes + uint8_t type = telegram[2]; + uint8_t offset = telegram[3]; + uint8_t * data = telegram + 4; // data block starts at position 5 // print detailed telegram data if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_THERMOSTAT) { @@ -710,11 +731,11 @@ void _ems_processTelegram(uint8_t * telegram, uint8_t length) { if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_THERMOSTAT) { // only print ones to/from thermostat if logging is set to thermostat only if ((src == EMS_Thermostat.type_id) || (dest == EMS_Thermostat.type_id)) { - _debugPrintTelegram(output_str, telegram, length, color_s); + _debugPrintTelegram(output_str, EMS_RxTelegram, color_s); } } else { // always print - _debugPrintTelegram(output_str, telegram, length, color_s); + _debugPrintTelegram(output_str, EMS_RxTelegram, color_s); } } @@ -746,7 +767,7 @@ void _ems_processTelegram(uint8_t * telegram, uint8_t length) { // call callback function to process it // as we only handle complete telegrams (not partial) check that the offset is 0 if (offset == EMS_ID_NONE) { - (void)EMS_Types[i].processType_cb(type, data, length - 5); + (void)EMS_Types[i].processType_cb(type, data, EMS_RxTelegram.length - 5); } } } @@ -767,19 +788,22 @@ void _removeTxQueue() { * length is only data bytes, excluding the BRK * We only remove from the Tx queue if the read or write was successful */ -void _processType(uint8_t * telegram, uint8_t length) { +void _processType(_EMS_RxTelegram EMS_RxTelegram) { + uint8_t * telegram = EMS_RxTelegram.telegram; + uint8_t length = EMS_RxTelegram.length; + // header uint8_t src = telegram[0] & 0x7F; // removing 8th bit as we deal with both reads and writes here // if its an echo of ourselves from the master UBA, ignore if (src == EMS_ID_ME) { - //_debugPrintTelegram("Telegram echo:", telegram, length, COLOR_BLUE); + _debugPrintTelegram("echo:", EMS_RxTelegram, COLOR_WHITE); return; } // if its a broadcast and we didn't just send anything, process it and exit if (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE) { - _ems_processTelegram(telegram, length); + _ems_processTelegram(EMS_RxTelegram); return; } @@ -791,13 +815,13 @@ void _processType(uint8_t * telegram, uint8_t length) { // and if not we probably didn't get any response so remove the last Tx from the queue and process the telegram anyway if ((telegram[1] & 0x7F) != EMS_ID_ME) { _removeTxQueue(); - _ems_processTelegram(telegram, length); + _ems_processTelegram(EMS_RxTelegram); return; } // first double check we actually have something in the queue if (EMS_TxQueue.isEmpty()) { - _ems_processTelegram(telegram, length); + _ems_processTelegram(EMS_RxTelegram); return; } @@ -832,7 +856,7 @@ void _processType(uint8_t * telegram, uint8_t length) { } } } - _ems_processTelegram(telegram, length); // process it always + _ems_processTelegram(EMS_RxTelegram); // process it always } if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) { @@ -1128,7 +1152,7 @@ void _process_Version(uint8_t type, uint8_t * data, uint8_t length) { if (typeFound) { // its a boiler - myDebug("Boiler type device found. Model %s with TypeID 0x%02X, Product ID %d, Version %s", + myDebug("Boiler found. Model %s with TypeID 0x%02X, Product ID %d, Version %s", Boiler_Types[i].model_string, Boiler_Types[i].type_id, product_id, @@ -1198,7 +1222,6 @@ void _process_Version(uint8_t type, uint8_t * data, uint8_t length) { } else { myDebug("Unrecognized device found. TypeID 0x%02X, Product ID %d, Version %s", type, product_id, version); } - } /* @@ -1531,6 +1554,11 @@ void ems_doReadCommand(uint8_t type, uint8_t dest, bool forceRefresh) { return; } + // if we're preventing all outbound traffic, quit + if (EMS_Sys_Status.emsTxDisabled) { + return; + } + _EMS_TxTelegram EMS_TxTelegram = EMS_TX_TELEGRAM_NEW; // create new Tx EMS_TxTelegram.timestamp = millis(); // set timestamp EMS_Sys_Status.txRetryCount = 0; // reset retry counter @@ -1569,6 +1597,10 @@ void ems_sendRawTelegram(char * telegram) { char * p; char value[10] = {0}; + if (EMS_Sys_Status.emsTxDisabled) { + return; // user has disabled all Tx + } + _EMS_TxTelegram EMS_TxTelegram = EMS_TX_TELEGRAM_NEW; // create new Tx EMS_TxTelegram.timestamp = millis(); // set timestamp EMS_Sys_Status.txRetryCount = 0; // reset retry counter @@ -1594,6 +1626,10 @@ void ems_sendRawTelegram(char * telegram) { } } + if (count == 0) { + return; // nothing to send + } + // calculate length including header and CRC EMS_TxTelegram.length = count + 2; EMS_TxTelegram.type_validate = EMS_ID_NONE; @@ -1845,3 +1881,26 @@ void ems_setWarmTapWaterActivated(bool activated) { EMS_TxQueue.push(EMS_TxTelegram); // add to queue } + +/* + * Start up sequence for UBA Master + * Still experimental + */ +void ems_startupTelegrams() { + if ((EMS_Sys_Status.emsTxDisabled) || (!EMS_Sys_Status.emsBusConnected)) { + myDebug("Unable to send startup sequence when in silent mode or bus is disabled"); + } + + myDebug("Sending startup sequence..."); + char s[20] = {0}; + + // (00:07:27.512) Telegram echo: telegram: 0B 08 1D 00 00 (CRC=84), #data=1 + // Write type 0x1D to get out of function test mode + snprintf(s, sizeof(s), "%02X %02X 1D 00 00", EMS_ID_ME, EMS_Boiler.type_id); + ems_sendRawTelegram(s); + + // (00:07:35.555) Telegram echo: telegram: 0B 88 01 00 1B (CRC=8B), #data=1 + // Read type 0x01 + snprintf(s, sizeof(s), "%02X %02X 01 00 1B", EMS_ID_ME, EMS_Boiler.type_id | 0x80); + ems_sendRawTelegram(s); +} diff --git a/src/ems.h b/src/ems.h index 0b4dc20be..8fb3caa94 100644 --- a/src/ems.h +++ b/src/ems.h @@ -92,6 +92,7 @@ typedef struct { unsigned long emsRxTimestamp; // timestamp of last EMS message received unsigned long emsPollTimestamp; // timestamp of last EMS poll sent to us bool emsTxCapable; // able to send via Tx + bool emsTxDisabled; // true to prevent all Tx uint8_t txRetryCount; // # times the last Tx was re-sent } _EMS_Sys_Status; @@ -112,6 +113,12 @@ typedef struct { uint8_t data[EMS_MAX_TELEGRAM_LENGTH]; } _EMS_TxTelegram; +// The Rx receive package +typedef struct { + uint32_t timestamp; // timestamp from millis() + uint8_t * telegram; // the full data package + uint8_t length; // length in bytes +} _EMS_RxTelegram; // default empty Tx @@ -179,7 +186,7 @@ typedef struct { // UBAParameterWW float extTemp; // Outside temperature float boilTemp; // Boiler temperature uint8_t pumpMod; // Pump modulation - uint32_t burnStarts; // # burner restarts + uint32_t burnStarts; // # burner starts uint32_t burnWorkMin; // Total burner operating time uint32_t heatWorkMin; // Total heat operating time @@ -251,12 +258,12 @@ void ems_setWarmWaterTemp(uint8_t temperature); void ems_setWarmWaterActivated(bool activated); void ems_setWarmTapWaterActivated(bool activated); void ems_setPoll(bool b); -void ems_setTxEnabled(bool b); void ems_setLogging(_EMS_SYS_LOGGING loglevel); void ems_setEmsRefreshed(bool b); void ems_setWarmWaterModeComfort(uint8_t comfort); bool ems_checkEMSBUSAlive(); void ems_setModels(); +void ems_setTxDisabled(bool b); void ems_getThermostatValues(); void ems_getBoilerValues(); @@ -277,10 +284,12 @@ char * ems_getThermostatDescription(char * buffer); void ems_printTxQueue(); char * ems_getBoilerDescription(char * buffer); +void ems_startupTelegrams(); + // private functions uint8_t _crcCalculator(uint8_t * data, uint8_t len); -void _processType(uint8_t * telegram, uint8_t length); -void _debugPrintPackage(const char * prefix, uint8_t * data, uint8_t len, const char * color); +void _processType(_EMS_RxTelegram EMS_RxTelegram); +void _debugPrintPackage(const char * prefix, _EMS_RxTelegram EMS_RxTelegram, const char * color); void _ems_clearTxData(); int _ems_findBoilerModel(uint8_t model_id); bool _ems_setModel(uint8_t model_id);