diff --git a/README.md b/README.md index 1e0a5d3d0..8c4005acd 100644 --- a/README.md +++ b/README.md @@ -187,7 +187,7 @@ The Boiler (ID 0x08) will send out these broadcast telegrams regularly: And a thermostat (ID 0x17 for a RC20) would broadcast these messages regularly: | Type | Description | -| ---- | ----------- | undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined | +| ---- | ----------- | undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined |undefined | | 0x06 | time on thermostat Y,M,H,D,M,S,wd | Refer to the code in `ems.cpp` for further explanation on how to parse these message types and also reference the EMS Wiki. @@ -233,14 +233,15 @@ Every telegram sent is echo'd back to Rx. | Thermostat (0x17) | 0xA8 | RC20Temperature | sets temperature and operating modes | | Thermostat (0x17) | 0xA3 | RCOutdoorTempMessage | | | Thermostat (0x17) | 0x91 | RC20StatusMessage | reads set & current room temperatures | +| Thermostat (0x17) | 0x02 | Version | reads Version major/minor | Note the thermostat types are based on a RC20 model thermostat. If using an RC30/RC35 use types 0x3E and 0x48 to read the values. ### Customizing Most of the changes will be done in `boiler.ino` and `ems.cpp`. - * To add new handlers for data types, create a callback function and add to the `EMS_Types` at the top of the file `ems.cpp` and the DEFINES in `ems.h` - * To change your thermostat type set `EMS_ID_THERMOSTAT` in `ems.h`. The default is 0x17 for an RC20. + * To add new handlers for data types, create a callback function and add to the `EMS_Types` at the top of the file `ems.cpp` + * To change your thermostat type set `EMS_ID_THERMOSTAT` in `ems.cpp`. The default is 0x17 for an RC20. * The DEFINES `BOILER_THERMOSTAT_ENABLED`, `BOILER_SHOWER_ENABLED` and `BOILER_SHOWER_TIMER` enabled the thermostat logic, the shower logic and the shower timer alert logic respectively. 1 is on and 0 is off. ### MQTT diff --git a/src/boiler.ino b/src/boiler.ino index 5e044265a..9afb25de4 100644 --- a/src/boiler.ino +++ b/src/boiler.ino @@ -52,7 +52,7 @@ Ticker showerResetTimer; "* S=toggle Shower Timer on/off\n\r" \ "* r [n] to request for data from EMS " \ "(33=UBAParameterWW, 18=UBAMonitorFast, 19=UBAMonitorSlow, " \ - "34=UBAMonitorWWMessage, 91=RC20StatusMessage, 6=RC20Time)\n\r" \ + "34=UBAMonitorWWMessage, 91=RC20StatusMessage, 6=RC20Time, 2=Version)\n\r" \ "* t [n] set thermostat temperature to n\n\r" \ "* w [n] set boiler warm water temperature to n (min 30)\n\r" \ "* a [n] activate boiler warm water on (n=1) or off (n=0)" diff --git a/src/ems.cpp b/src/ems.cpp index 7e7832581..79877b602 100644 --- a/src/ems.cpp +++ b/src/ems.cpp @@ -15,8 +15,41 @@ _EMS_Sys_Status EMS_Sys_Status; // EMS Status _EMS_TxTelegram EMS_TxTelegram; // Empty buffer for sending telegrams -// call back for handling Types -#define MAX_TYPECALLBACK 11 +// define here the Thermostat type +#define EMS_ID_THERMOSTAT 0x17 // x17=RC20, x10=RC30 (Moduline 300) + +// define here the EMS telegram types you need +// Boiler... +#define EMS_TYPE_UBAMonitorFast 0x18 // is an automatic monitor broadcast +#define EMS_TYPE_UBAMonitorSlow 0x19 // is an automatic monitor broadcast +#define EMS_TYPE_UBAMonitorWWMessage 0x34 // is an automatic monitor broadcast +#define EMS_TYPE_UBAMaintenanceStatusMessage 0x1c // is an automatic monitor broadcast +#define EMS_TYPE_UBAParameterWW 0x33 + +#define EMS_TYPE_UBATotalUptimeMessage 0x14 +#define EMS_TYPE_UBAMaintenanceSettingsMessage 0x15 +#define EMS_TYPE_UBAParametersMessage 0x16 + +// Thermostat... +#define EMS_TYPE_RC20StatusMessage 0x91 +#define EMS_TYPE_RC20Time 0x06 // is an automatic monitor broadcast +#define EMS_TYPE_RC20Temperature 0xA8 +#define EMS_TYPE_RCOutdoorTempMessage 0xa3 // we can ignore +#define EMS_TYPE_Version 0x02 // version of the controller + +// and call backs +#define MAX_TYPECALLBACK 12 // make sure it matches the #types you have +// callbacks per type +bool _process_UBAMonitorFast(uint8_t * data, uint8_t length); +bool _process_UBAMonitorSlow(uint8_t * data, uint8_t length); +bool _process_UBAMonitorWWMessage(uint8_t * data, uint8_t length); +bool _process_UBAParameterWW(uint8_t * data, uint8_t length); +bool _process_RC20StatusMessage(uint8_t * data, uint8_t length); +bool _process_RC20Time(uint8_t * data, uint8_t length); +bool _process_RC20Temperature(uint8_t * data, uint8_t length); +bool _process_RC20Temperature(uint8_t * data, uint8_t length); +bool _process_Version(uint8_t * data, uint8_t length); + const _EMS_Types EMS_Types[MAX_TYPECALLBACK] = { {EMS_ID_BOILER, EMS_TYPE_UBAMonitorFast, "UBAMonitorFast", 36, _process_UBAMonitorFast}, {EMS_ID_BOILER, EMS_TYPE_UBAMonitorSlow, "UBAMonitorSlow", 28, _process_UBAMonitorSlow}, @@ -29,7 +62,8 @@ const _EMS_Types EMS_Types[MAX_TYPECALLBACK] = {EMS_ID_THERMOSTAT, EMS_TYPE_RC20StatusMessage, "RC20StatusMessage", 3, _process_RC20StatusMessage}, {EMS_ID_THERMOSTAT, EMS_TYPE_RC20Time, "RC20Time", 20, _process_RC20Time}, - {EMS_ID_THERMOSTAT, EMS_TYPE_RC20Temperature, "RC20Temperature", 10, _process_RC20Temperature} + {EMS_ID_THERMOSTAT, EMS_TYPE_RC20Temperature, "RC20Temperature", 10, _process_RC20Temperature}, + {EMS_ID_THERMOSTAT, EMS_TYPE_Version, "Version", 2, _process_Version} }; // reserve space for the data we collect from the Boiler and Thermostat @@ -168,7 +202,7 @@ void ems_setLogVerbose(bool b) { } /* - * Calculate CRC checksum using lookup table + * Calculate CRC checksum using lookup table for speed * len is length of data in bytes (including the CRC byte at end) */ uint8_t _crcCalculator(uint8_t * data, uint8_t len) { @@ -238,7 +272,7 @@ void _ems_sendTelegram() { * When we receive a Poll Request we need to send quickly */ void ems_parseTelegram(uint8_t * telegram, uint8_t length) { - // if we're waiting on a reponse from a read and it hasn't come, try again + // if we're waiting on a response from a previous read and it hasn't come, try again if ((EMS_Sys_Status.emsTxStatus != EMS_TX_PENDING) && ((EMS_TxTelegram.action == EMS_TX_READ) || (EMS_TxTelegram.action == EMS_TX_VALIDATE)) && ((millis() - EMS_Sys_Status.emsLastTx) > RX_READ_TIMEOUT)) { @@ -325,6 +359,7 @@ void _processType(uint8_t * telegram, uint8_t length) { // if its an echo of ourselves from the master, ignore if (src == EMS_ID_ME) { _debugPrintTelegram("Telegram echo:", telegram, length, COLOR_BLUE); + return; } // header @@ -338,7 +373,8 @@ void _processType(uint8_t * telegram, uint8_t length) { char src_s[20]; char dest_s[20]; - // scan through known types + // scan through known types we understand + // set typeFound if we found a match int i = 0; bool typeFound = false; while (i < MAX_TYPECALLBACK) { @@ -370,7 +406,7 @@ void _processType(uint8_t * telegram, uint8_t length) { // did we actually ask for it from an earlier read/write request? // note when we issue a read command the responder (dest) has to return a telegram back immediately - if ((EMS_TxTelegram.action == EMS_TX_READ) && (EMS_TxTelegram.type == type) && typeFound) { + if ((EMS_TxTelegram.action == EMS_TX_READ) && (EMS_TxTelegram.type == type)) { // yes we were expecting this one one EMS_Sys_Status.emsRxPgks++; // increment rx counter EMS_Sys_Status.emsLastRx = millis(); @@ -522,6 +558,18 @@ bool _process_RC20Temperature(uint8_t * data, uint8_t length) { return true; } +/* + * Version - type 0x02 - get the version of the Thermostat + */ +bool _process_Version(uint8_t * data, uint8_t length) { + uint8_t major = data[1]; + uint8_t minor = data[2]; + + // TODO: finish this + + return true; +} + /* * process_RC20Time - type 0x06 - date and time from the RC20 thermostat (0x17) - 14 bytes long */ diff --git a/src/ems.h b/src/ems.h index 6940e9d48..6dcbcec4d 100644 --- a/src/ems.h +++ b/src/ems.h @@ -1,5 +1,7 @@ /* * Header file for EMS.cpp + * + * You shouldn't need to change much in this file */ #ifndef __EMS_H @@ -8,32 +10,13 @@ #include // EMS IDs -#define EMS_ID_THERMOSTAT 0x17 // x17=RC20, x10=RC30 (Moduline 300) - #define EMS_ID_NONE 0x00 // Fixed - used as a dest in broadcast messages #define EMS_ID_BOILER 0x08 // Fixed - also known as MC10. #define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as "Service Key" -// EMS Telegram Types +// Special EMS Telegram Types #define EMS_TYPE_NONE 0x00 // none -#define EMS_TYPE_UBAMonitorFast 0x18 // is an automatic monitor broadcast -#define EMS_TYPE_UBAMonitorSlow 0x19 // is an automatic monitor broadcast -#define EMS_TYPE_UBAMonitorWWMessage 0x34 // is an automatic monitor broadcast -#define EMS_TYPE_UBAMaintenanceStatusMessage 0x1c // is an automatic monitor broadcast -#define EMS_TYPE_UBAParameterWW 0x33 - -#define EMS_TYPE_UBATotalUptimeMessage 0x14 -#define EMS_TYPE_UBAMaintenanceSettingsMessage 0x15 -#define EMS_TYPE_UBAParametersMessage 0x16 - -// EMS Telegram types from Thermostat -// types 1A and 35 and used for errors from Thermostat -#define EMS_TYPE_RC20StatusMessage 0x91 -#define EMS_TYPE_RC20Time 0x06 // is an automatic monitor broadcast -#define EMS_TYPE_RC20Temperature 0xA8 -#define EMS_TYPE_RCOutdoorTempMessage 0xa3 // we can ignore - #define EMS_TX_MAXBUFFERSIZE 128 // max size of the buffer. packets are 32 bits /* EMS UART transfer status */ @@ -86,7 +69,6 @@ typedef struct { /* * Telegram package defintions */ - typedef struct { // UBAParameterWW bool wWActivated; // Warm Water activated @@ -170,15 +152,6 @@ void _initTxBuffer(); void _buildTxTelegram(uint8_t data_value); void _debugPrintPackage(const char * prefix, uint8_t * data, uint8_t len, const char * color); -// callbacks per type -bool _process_UBAMonitorFast(uint8_t * data, uint8_t length); -bool _process_UBAMonitorSlow(uint8_t * data, uint8_t length); -bool _process_UBAMonitorWWMessage(uint8_t * data, uint8_t length); -bool _process_UBAParameterWW(uint8_t * data, uint8_t length); -bool _process_RC20StatusMessage(uint8_t * data, uint8_t length); -bool _process_RC20Time(uint8_t * data, uint8_t length); -bool _process_RC20Temperature(uint8_t * data, uint8_t length); - // helper functions float _toFloat(uint8_t i, uint8_t * data); uint16_t _toLong(uint8_t i, uint8_t * data); diff --git a/src/emsuart.cpp b/src/emsuart.cpp index 1412b6f82..0205c54c6 100644 --- a/src/emsuart.cpp +++ b/src/emsuart.cpp @@ -1,5 +1,6 @@ /* * emsuart.cpp + * * The low level UART code for ESP8266 to read and write to the EMS bus via uart * Paul Derbyshire - https://github.com/proddy/EMS-ESP-Boiler */ @@ -32,7 +33,7 @@ static void emsuart_rx_intr_handler(void * para) { length = 0; } - // fill IRQ buffer, by emptying Rx FIFO + // fill IRQ buffer, by emptying Rx FIFO if (U0IS & ((1 << UIFF) | (1 << UITO) | (1 << UIBD))) { while ((USS(EMSUART_UART) >> USRXC) & 0xFF) { uart_buffer[length++] = USF(EMSUART_UART); @@ -157,7 +158,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() { } /* - * Send to Tx, ending with a BRK + * Send to Tx, ending with a */ void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { for (uint8_t i = 0; i < len; i++) {