added new Version type

This commit is contained in:
proddy
2018-05-29 21:20:34 +02:00
parent d71128861b
commit e1b06328ad
5 changed files with 66 additions and 43 deletions

View File

@@ -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: And a thermostat (ID 0x17 for a RC20) would broadcast these messages regularly:
| Type | Description | | 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 | | 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. 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) | 0xA8 | RC20Temperature | sets temperature and operating modes |
| Thermostat (0x17) | 0xA3 | RCOutdoorTempMessage | | | Thermostat (0x17) | 0xA3 | RCOutdoorTempMessage | |
| Thermostat (0x17) | 0x91 | RC20StatusMessage | reads set & current room temperatures | | 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. 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 ### Customizing
Most of the changes will be done in `boiler.ino` and `ems.cpp`. 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 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.h`. The default is 0x17 for an RC20. * 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. * 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 ### MQTT

View File

@@ -52,7 +52,7 @@ Ticker showerResetTimer;
"* S=toggle Shower Timer on/off\n\r" \ "* S=toggle Shower Timer on/off\n\r" \
"* r [n] to request for data from EMS " \ "* r [n] to request for data from EMS " \
"(33=UBAParameterWW, 18=UBAMonitorFast, 19=UBAMonitorSlow, " \ "(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" \ "* t [n] set thermostat temperature to n\n\r" \
"* w [n] set boiler warm water temperature to n (min 30)\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)" "* a [n] activate boiler warm water on (n=1) or off (n=0)"

View File

@@ -15,8 +15,41 @@
_EMS_Sys_Status EMS_Sys_Status; // EMS Status _EMS_Sys_Status EMS_Sys_Status; // EMS Status
_EMS_TxTelegram EMS_TxTelegram; // Empty buffer for sending telegrams _EMS_TxTelegram EMS_TxTelegram; // Empty buffer for sending telegrams
// call back for handling Types // define here the Thermostat type
#define MAX_TYPECALLBACK 11 #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] = const _EMS_Types EMS_Types[MAX_TYPECALLBACK] =
{ {EMS_ID_BOILER, EMS_TYPE_UBAMonitorFast, "UBAMonitorFast", 36, _process_UBAMonitorFast}, { {EMS_ID_BOILER, EMS_TYPE_UBAMonitorFast, "UBAMonitorFast", 36, _process_UBAMonitorFast},
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorSlow, "UBAMonitorSlow", 28, _process_UBAMonitorSlow}, {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_RC20StatusMessage, "RC20StatusMessage", 3, _process_RC20StatusMessage},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Time, "RC20Time", 20, _process_RC20Time}, {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 // 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) * len is length of data in bytes (including the CRC byte at end)
*/ */
uint8_t _crcCalculator(uint8_t * data, uint8_t len) { 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 * When we receive a Poll Request we need to send quickly
*/ */
void ems_parseTelegram(uint8_t * telegram, uint8_t length) { 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) if ((EMS_Sys_Status.emsTxStatus != EMS_TX_PENDING)
&& ((EMS_TxTelegram.action == EMS_TX_READ) || (EMS_TxTelegram.action == EMS_TX_VALIDATE)) && ((EMS_TxTelegram.action == EMS_TX_READ) || (EMS_TxTelegram.action == EMS_TX_VALIDATE))
&& ((millis() - EMS_Sys_Status.emsLastTx) > RX_READ_TIMEOUT)) { && ((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 its an echo of ourselves from the master, ignore
if (src == EMS_ID_ME) { if (src == EMS_ID_ME) {
_debugPrintTelegram("Telegram echo:", telegram, length, COLOR_BLUE); _debugPrintTelegram("Telegram echo:", telegram, length, COLOR_BLUE);
return;
} }
// header // header
@@ -338,7 +373,8 @@ void _processType(uint8_t * telegram, uint8_t length) {
char src_s[20]; char src_s[20];
char dest_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; int i = 0;
bool typeFound = false; bool typeFound = false;
while (i < MAX_TYPECALLBACK) { 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? // 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 // 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 // yes we were expecting this one one
EMS_Sys_Status.emsRxPgks++; // increment rx counter EMS_Sys_Status.emsRxPgks++; // increment rx counter
EMS_Sys_Status.emsLastRx = millis(); EMS_Sys_Status.emsLastRx = millis();
@@ -522,6 +558,18 @@ bool _process_RC20Temperature(uint8_t * data, uint8_t length) {
return true; 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 * process_RC20Time - type 0x06 - date and time from the RC20 thermostat (0x17) - 14 bytes long
*/ */

View File

@@ -1,5 +1,7 @@
/* /*
* Header file for EMS.cpp * Header file for EMS.cpp
*
* You shouldn't need to change much in this file
*/ */
#ifndef __EMS_H #ifndef __EMS_H
@@ -8,32 +10,13 @@
#include <Arduino.h> #include <Arduino.h>
// EMS IDs // 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_NONE 0x00 // Fixed - used as a dest in broadcast messages
#define EMS_ID_BOILER 0x08 // Fixed - also known as MC10. #define EMS_ID_BOILER 0x08 // Fixed - also known as MC10.
#define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as "Service Key" #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_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 #define EMS_TX_MAXBUFFERSIZE 128 // max size of the buffer. packets are 32 bits
/* EMS UART transfer status */ /* EMS UART transfer status */
@@ -86,7 +69,6 @@ typedef struct {
/* /*
* Telegram package defintions * Telegram package defintions
*/ */
typedef struct { typedef struct {
// UBAParameterWW // UBAParameterWW
bool wWActivated; // Warm Water activated bool wWActivated; // Warm Water activated
@@ -170,15 +152,6 @@ void _initTxBuffer();
void _buildTxTelegram(uint8_t data_value); void _buildTxTelegram(uint8_t data_value);
void _debugPrintPackage(const char * prefix, uint8_t * data, uint8_t len, const char * color); 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 // helper functions
float _toFloat(uint8_t i, uint8_t * data); float _toFloat(uint8_t i, uint8_t * data);
uint16_t _toLong(uint8_t i, uint8_t * data); uint16_t _toLong(uint8_t i, uint8_t * data);

View File

@@ -1,5 +1,6 @@
/* /*
* emsuart.cpp * emsuart.cpp
*
* The low level UART code for ESP8266 to read and write to the EMS bus via uart * 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 * Paul Derbyshire - https://github.com/proddy/EMS-ESP-Boiler
*/ */
@@ -157,7 +158,7 @@ void ICACHE_FLASH_ATTR emsuart_tx_brk() {
} }
/* /*
* Send to Tx, ending with a BRK * Send to Tx, ending with a <BRK>
*/ */
void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) { void ICACHE_FLASH_ATTR emsuart_tx_buffer(uint8_t * buf, uint8_t len) {
for (uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; i++) {