ems+ updates

This commit is contained in:
Paul
2019-08-22 21:18:31 +02:00
parent dee620cd52
commit 6274990353
6 changed files with 131 additions and 88 deletions

View File

@@ -9,7 +9,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Building with EEPROM (-DCRASH option) to capture stack dumps doesn't work with the web server, so only compile for debugging and use Telnet. - Building with EEPROM (-DCRASH option) to capture stack dumps doesn't work with the web server, so only compile for debugging and use Telnet.
## How to build the firmware with 1.9.x ## How to build the firmware with 1.9.x
- Make sure you update your local `platformio.ini` using the example one and set the target to `debug`. - Make sure you update your local `platformio.ini` using the example one and set the target to `debug`.
- On first boot it will re-build the SPIFFS config file so if you're upgrading from 1.8.x all the settings will be deleted and you will need to re-enter. This can be doen now via the web interface by connecting to WiFi AP called 'ems-esp'. - On first boot it will re-build the SPIFFS config file so if you're upgrading from 1.8.x all the settings will be deleted and you will need to re-enter. This can be doen now via the web interface by connecting to WiFi AP called 'ems-esp'.
@@ -17,12 +16,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- When building the firmware with the `debug` target all the web front-end code is assembled and compressed. It only takes a second or two. However you'll need nodeJS and the gulp module installed for this. - When building the firmware with the `debug` target all the web front-end code is assembled and compressed. It only takes a second or two. However you'll need nodeJS and the gulp module installed for this.
- Download and install NodeJS from https://nodejs.org/en/download/ - Download and install NodeJS from https://nodejs.org/en/download/
- Navigate to the folder tools/webfilesbuilder, and in that folder do a: - Navigate to the folder tools/webfilesbuilder, and in that folder do a:
```
```
npm install --global gulp-cli npm install --global gulp-cli
npm install gulp npm install gulp
``` ```
(ignore any errors as I need to upgrade the gulp file to the latest 4.1 format) (ignore any errors as I need to upgrade the gulp file to the latest 4.1 format)
- You can test if it worked by then typing `gulp`.
You can test if it worked by then typing `gulp`.
--- ---
@@ -39,7 +41,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
- HAndle Read and Write to EMS+ device logic changed. - Handle Read and Write to EMS+ device logic changed.
## [1.8.1] 2019-07-27 ## [1.8.1] 2019-07-27

View File

@@ -685,7 +685,7 @@ void _ems_sendTelegram() {
/** /**
* Takes the last write command and turns into a validate request * Takes the last write command and turns into a validate request
* placing it on the queue * placing it on the Tx queue
*/ */
void _createValidate() { void _createValidate() {
if (EMS_TxQueue.isEmpty()) { if (EMS_TxQueue.isEmpty()) {
@@ -709,9 +709,10 @@ void _createValidate() {
new_EMS_TxTelegram.action = EMS_TX_TELEGRAM_VALIDATE; new_EMS_TxTelegram.action = EMS_TX_TELEGRAM_VALIDATE;
// copy old Write record // copy old Write record
new_EMS_TxTelegram.type_validate = EMS_TxTelegram.type_validate; new_EMS_TxTelegram.type_validate = EMS_TxTelegram.type; // save the original type in the type_validate, increase we need to re-try
new_EMS_TxTelegram.type = EMS_TxTelegram.type_validate; // new type is the validate type
new_EMS_TxTelegram.dest = EMS_TxTelegram.dest; new_EMS_TxTelegram.dest = EMS_TxTelegram.dest;
new_EMS_TxTelegram.type = EMS_TxTelegram.type;
new_EMS_TxTelegram.comparisonValue = EMS_TxTelegram.comparisonValue; new_EMS_TxTelegram.comparisonValue = EMS_TxTelegram.comparisonValue;
new_EMS_TxTelegram.comparisonPostRead = EMS_TxTelegram.comparisonPostRead; new_EMS_TxTelegram.comparisonPostRead = EMS_TxTelegram.comparisonPostRead;
new_EMS_TxTelegram.comparisonOffset = EMS_TxTelegram.comparisonOffset; new_EMS_TxTelegram.comparisonOffset = EMS_TxTelegram.comparisonOffset;
@@ -802,7 +803,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
return; // ignore the whole telegram Rx Telegram while in DETECT mode return; // ignore the whole telegram Rx Telegram while in DETECT mode
} }
/* It may happen that we where interrupted (f.e. by WIFI activity) and the /* It may happen that we where interrupted (for instance by WIFI activity) and the
* buffer isn't valid anymore, so we must not answer at all... * buffer isn't valid anymore, so we must not answer at all...
*/ */
if (EMS_Sys_Status.emsRxStatus != EMS_RX_STATUS_IDLE) { if (EMS_Sys_Status.emsRxStatus != EMS_RX_STATUS_IDLE) {
@@ -820,6 +821,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
if (length == 1) { if (length == 1) {
uint8_t value = telegram[0]; // 1st byte of data package uint8_t value = telegram[0]; // 1st byte of data package
static uint32_t _last_emsPollFrequency = 0; static uint32_t _last_emsPollFrequency = 0;
static uint8_t delay_tx = 0; // TODO remove, experimental
// check first for a Poll for us // check first for a Poll for us
if ((value ^ 0x80 ^ EMS_Sys_Status.emsIDMask) == EMS_ID_ME) { if ((value ^ 0x80 ^ EMS_Sys_Status.emsIDMask) == EMS_ID_ME) {
@@ -830,7 +832,9 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
// do we have something to send thats waiting in the Tx queue? // do we have something to send thats waiting in the Tx queue?
// if so send it if the Queue is not in a wait state // if so send it if the Queue is not in a wait state
if ((!EMS_TxQueue.isEmpty()) && (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE)) { // TODO: but only do this at defined rate otherwise it'll be too quick, so skip a few polls
if ((!EMS_TxQueue.isEmpty()) && (EMS_Sys_Status.emsTxStatus == EMS_TX_STATUS_IDLE) && (++delay_tx == 2)) {
delay_tx = 0;
_ems_sendTelegram(); // perform the read/write command immediately _ems_sendTelegram(); // perform the read/write command immediately
} else { } else {
// nothing to send so just send a poll acknowledgement back // nothing to send so just send a poll acknowledgement back
@@ -848,7 +852,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
} else if (value == EMS_TX_ERROR) { } else if (value == EMS_TX_ERROR) {
// last write failed (04), delete it from queue and dont bother to retry // last write failed (04), delete it from queue and dont bother to retry
if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) { if (EMS_Sys_Status.emsLogging == EMS_SYS_LOGGING_VERBOSE) {
myDebug_P(PSTR("** Write command failed from host")); myDebug_P(PSTR("-> Error: Write command failed from host"));
} }
ems_tx_pollAck(); // send a poll to free the EMS bus ems_tx_pollAck(); // send a poll to free the EMS bus
_removeTxQueue(); // remove from queue _removeTxQueue(); // remove from queue
@@ -859,7 +863,7 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
} }
// ignore anything that doesn't resemble a proper telegram package // ignore anything that doesn't resemble a proper telegram package
// minimal is 5 bytes, excluding CRC at the end // minimal is 5 bytes, excluding CRC at the end (for EMS1.0)
if (length <= 4) { if (length <= 4) {
// _debugPrintTelegram("Noisy data:", &EMS_RxTelegram, COLOR_RED); // _debugPrintTelegram("Noisy data:", &EMS_RxTelegram, COLOR_RED);
return; return;
@@ -1118,8 +1122,8 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
// release the lock on the TxQueue // release the lock on the TxQueue
EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE; EMS_Sys_Status.emsTxStatus = EMS_TX_STATUS_IDLE;
// at this point we can assume Txstatus is EMS_TX_STATUS_WAIT so we just sent a read/write/validate // at this point we can assume TxStatus is EMS_TX_STATUS_WAIT as we just sent a read or validate
// for READ, WRITE or VALIDATE the dest (telegram[1]) is always us, so check for this // for READ or VALIDATE the dest (telegram[1]) is always us, so check for this
// and if not we probably didn't get any response so remove the last Tx from the queue and process the telegram anyway // 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) { if ((telegram[1] & 0x7F) != EMS_ID_ME) {
_removeTxQueue(); _removeTxQueue();
@@ -1159,12 +1163,12 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
// if retried too many times, give up and remove it // if retried too many times, give up and remove it
if (EMS_Sys_Status.txRetryCount >= TX_WRITE_TIMEOUT_COUNT) { if (EMS_Sys_Status.txRetryCount >= TX_WRITE_TIMEOUT_COUNT) {
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("Read failed. Giving up, removing from queue")); myDebug_P(PSTR("-> Read failed. Giving up and removing write from queue"));
} }
_removeTxQueue(); _removeTxQueue();
} else { } else {
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("Read failed. Retrying attempt %d/%d..."), EMS_Sys_Status.txRetryCount, TX_WRITE_TIMEOUT_COUNT); myDebug_P(PSTR("-> Read failed. Retrying (%d/%d)..."), EMS_Sys_Status.txRetryCount, TX_WRITE_TIMEOUT_COUNT);
} }
} }
} }
@@ -1174,7 +1178,7 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) { if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) {
// should not get here, since this is handled earlier receiving a 01 or 04 // should not get here, since this is handled earlier receiving a 01 or 04
myDebug_P(PSTR("** Error! Write - should not be here")); myDebug_P(PSTR("-> Write error - panic! should never get here"));
} }
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_VALIDATE) { if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_VALIDATE) {
@@ -1188,30 +1192,32 @@ void _processType(_EMS_RxTelegram * EMS_RxTelegram) {
// validate was successful, the write changed the value // validate was successful, the write changed the value
_removeTxQueue(); // now we can remove the Tx validate command the queue _removeTxQueue(); // now we can remove the Tx validate command the queue
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("Write to 0x%02X was successful"), EMS_TxTelegram.dest); myDebug_P(PSTR("-> Validate confirmed, last Write to 0x%02X was successful"), EMS_TxTelegram.dest);
} }
// follow up with the post read command // follow up with the post read command
ems_doReadCommand(EMS_TxTelegram.comparisonPostRead, EMS_TxTelegram.dest, true); ems_doReadCommand(EMS_TxTelegram.comparisonPostRead, EMS_TxTelegram.dest, true);
} else { } else {
// write failed // write failed
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("Last write failed. Compared set value 0x%02X with received value 0x%02X"), EMS_TxTelegram.comparisonValue, dataReceived); myDebug_P(PSTR("-> Write failed. Compared set value 0x%02X with received value of 0x%02X"), EMS_TxTelegram.comparisonValue, dataReceived);
} }
if (++EMS_Sys_Status.txRetryCount > TX_WRITE_TIMEOUT_COUNT) { if (++EMS_Sys_Status.txRetryCount > TX_WRITE_TIMEOUT_COUNT) {
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("Write failed. Giving up, removing from queue")); myDebug_P(PSTR("-> Write failed. Giving up, removing from queue"));
} }
_removeTxQueue(); _removeTxQueue();
} else { } else {
// retry, turn the validate back into a write and try again // retry, turn the validate back into a write and try again
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug_P(PSTR("...Retrying write. Attempt %d/%d..."), EMS_Sys_Status.txRetryCount, TX_WRITE_TIMEOUT_COUNT); myDebug_P(PSTR("-> Write didn't work, retrying (%d/%d)..."), EMS_Sys_Status.txRetryCount, TX_WRITE_TIMEOUT_COUNT);
} }
EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE; EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE;
EMS_TxTelegram.dataValue = EMS_TxTelegram.comparisonValue; // restore old value EMS_TxTelegram.dataValue = EMS_TxTelegram.comparisonValue; // restore old value
EMS_TxTelegram.offset = EMS_TxTelegram.comparisonOffset; // restore old value EMS_TxTelegram.offset = EMS_TxTelegram.comparisonOffset; // restore old value
EMS_TxQueue.shift(); // remove validate from queue EMS_TxTelegram.type = EMS_TxTelegram.type_validate; // restore old value, we swapped them to save the original type
EMS_TxQueue.unshift(EMS_TxTelegram); // add back to queue making it next in line
EMS_TxQueue.shift(); // remove validate from queue
EMS_TxQueue.unshift(EMS_TxTelegram); // add back to queue making it next in line
} }
} }
} }
@@ -1378,7 +1384,7 @@ void _process_RC35StatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
} else { } else {
EMS_Thermostat.curr_roomTemp = _toShort(EMS_OFFSET_RC35StatusMessage_curr); EMS_Thermostat.curr_roomTemp = _toShort(EMS_OFFSET_RC35StatusMessage_curr);
} }
EMS_Thermostat.day_mode = _bitRead(EMS_OFFSET_RC35Get_mode_day, 1); // get day mode flag EMS_Thermostat.day_mode = _bitRead(EMS_OFFSET_RC35StatusMessage_mode, 1); // get day mode flag
EMS_Thermostat.circuitcalctemp = _toByte(EMS_OFFSET_RC35Set_circuitcalctemp); // 0x48 calculated temperature EMS_Thermostat.circuitcalctemp = _toByte(EMS_OFFSET_RC35Set_circuitcalctemp); // 0x48 calculated temperature
@@ -1408,7 +1414,7 @@ void _process_RCPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Thermostat.curr_roomTemp = _toShort(EMS_OFFSET_RCPLUSStatusMessage_curr); // value is * 10 EMS_Thermostat.curr_roomTemp = _toShort(EMS_OFFSET_RCPLUSStatusMessage_curr); // value is * 10
EMS_Thermostat.setpoint_roomTemp = _toByte(EMS_OFFSET_RCPLUSStatusMessage_setpoint); // value is * 2 EMS_Thermostat.setpoint_roomTemp = _toByte(EMS_OFFSET_RCPLUSStatusMessage_setpoint); // value is * 2
EMS_Thermostat.day_mode = _bitRead(EMS_OFFSET_RCPLUSGet_mode_day, 1); // get day mode flag EMS_Thermostat.day_mode = _bitRead(EMS_OFFSET_RCPLUSStatusMessage_mode, 1); // get day mode flag
EMS_Thermostat.mode = _bitRead(EMS_OFFSET_RCPLUSStatusMessage_mode, 0); // bit 1, mode (auto=1 or manual=0) EMS_Thermostat.mode = _bitRead(EMS_OFFSET_RCPLUSStatusMessage_mode, 0); // bit 1, mode (auto=1 or manual=0)
} }
@@ -1456,11 +1462,25 @@ void _process_JunkersStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
* type 0x01B9 EMS+ for reading the mode from RC300/RC310 thermostat * type 0x01B9 EMS+ for reading the mode from RC300/RC310 thermostat
*/ */
void _process_RCPLUSSetMessage(_EMS_RxTelegram * EMS_RxTelegram) { void _process_RCPLUSSetMessage(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Thermostat.mode = _toByte(EMS_OFFSET_RCPLUSSet_mode); if (EMS_RxTelegram->offset == 0) {
EMS_Thermostat.daytemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_comfort2); // is * 2 EMS_Thermostat.mode = _toByte(EMS_OFFSET_RCPLUSSet_mode);
EMS_Thermostat.nighttemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_eco); // is * 2 EMS_Thermostat.daytemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_comfort2); // is * 2
EMS_Thermostat.nighttemp = _toByte(EMS_OFFSET_RCPLUSSet_temp_eco); // is * 2
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
}
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT if (EMS_RxTelegram->data_length == 1) {
// check for setpoint temps, e.g. Thermostat -> all, type 0x01B9, telegram: 10 00 FF 08 01 B9 26 (CRC=1A) #data=1
if ((EMS_RxTelegram->offset == EMS_OFFSET_RCPLUSSet_temp_setpoint) || (EMS_RxTelegram->offset == EMS_OFFSET_RCPLUSSet_manual_setpoint)) {
EMS_Thermostat.setpoint_roomTemp = _toByte(0); // value is * 2
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
// check for mode, eg. 10 00 FF 08 01 B9 FF
} else if (EMS_RxTelegram->offset == EMS_OFFSET_RCPLUSSet_mode) {
EMS_Thermostat.mode = (_toByte(0) == 0xFF); // Auto = xFF, Manual = x00 (auto=1 or manual=0)
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
}
}
} }
/** /**
@@ -1917,12 +1937,6 @@ void ems_discoverModels() {
// heatpump module... // heatpump module...
ems_doReadCommand(EMS_TYPE_Version, EMS_ID_HP); // check if there is HeatPump Module available ems_doReadCommand(EMS_TYPE_Version, EMS_ID_HP); // check if there is HeatPump Module available
// TODO remove! test for EMS+
//EMS_Thermostat.model_id = EMS_MODEL_RC300;
//EMS_Thermostat.device_id = 0x10;
//EMS_Thermostat.write_supported = true;
//EMS_Thermostat.product_id = 158;
// thermostat... // thermostat...
// if it hasn't been set, auto discover it // if it hasn't been set, auto discover it
if (EMS_Thermostat.device_id == EMS_ID_NONE) { if (EMS_Thermostat.device_id == EMS_ID_NONE) {
@@ -2496,7 +2510,11 @@ void ems_setThermostatTemp(float temperature, uint8_t temptype) {
} else if (EMS_Thermostat.mode == 0) { // manuaL } else if (EMS_Thermostat.mode == 0) { // manuaL
EMS_TxTelegram.offset = 0x0A; // manual offset EMS_TxTelegram.offset = 0x0A; // manual offset
} }
EMS_TxTelegram.type_validate = EMS_TYPE_RCPLUSStatusMessage; // validate by reading from a different telegram // TODO: commented out because it's too fast
// EMS_TxTelegram.type_validate = EMS_TYPE_RCPLUSStatusMessage; // validate by reading from a different telegram
EMS_TxTelegram.type_validate = EMS_ID_NONE; // validate by reading from a different telegram
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RCPLUSStatusMessage; // after write, do a full fetch of all values
} else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) { } else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) {
switch (temptype) { switch (temptype) {
@@ -2574,32 +2592,47 @@ void ems_setThermostatMode(uint8_t mode) {
EMS_TxTelegram.timestamp = millis(); // set timestamp EMS_TxTelegram.timestamp = millis(); // set timestamp
EMS_Sys_Status.txRetryCount = 0; // reset retry counter EMS_Sys_Status.txRetryCount = 0; // reset retry counter
EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE; EMS_TxTelegram.action = EMS_TX_TELEGRAM_WRITE;
EMS_TxTelegram.dest = device_id; EMS_TxTelegram.dest = device_id;
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH; EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
EMS_TxTelegram.dataValue = mode; EMS_TxTelegram.dataValue = mode;
EMS_TxTelegram.type_validate = EMS_TxTelegram.type;
// handle different thermostat types // handle different thermostat types
if (model_id == EMS_MODEL_RC20) { if (model_id == EMS_MODEL_RC20) {
EMS_TxTelegram.type = EMS_TYPE_RC20Set; EMS_TxTelegram.type = EMS_TYPE_RC20Set;
EMS_TxTelegram.offset = EMS_OFFSET_RC20Set_mode; EMS_TxTelegram.offset = EMS_OFFSET_RC20Set_mode;
EMS_TxTelegram.type_validate = EMS_TxTelegram.type;
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RC20StatusMessage;
} else if (model_id == EMS_MODEL_RC30) { } else if (model_id == EMS_MODEL_RC30) {
EMS_TxTelegram.type = EMS_TYPE_RC30Set; EMS_TxTelegram.type = EMS_TYPE_RC30Set;
EMS_TxTelegram.offset = EMS_OFFSET_RC30Set_mode; EMS_TxTelegram.offset = EMS_OFFSET_RC30Set_mode;
EMS_TxTelegram.type_validate = EMS_TxTelegram.type;
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RC30StatusMessage;
} else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) { } else if ((model_id == EMS_MODEL_RC35) || (model_id == EMS_MODEL_ES73)) {
EMS_TxTelegram.type = (hc == 2) ? EMS_TYPE_RC35Set_HC2 : EMS_TYPE_RC35Set_HC1; EMS_TxTelegram.type = (hc == 2) ? EMS_TYPE_RC35Set_HC2 : EMS_TYPE_RC35Set_HC1;
EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_mode; EMS_TxTelegram.offset = EMS_OFFSET_RC35Set_mode;
EMS_TxTelegram.type_validate = EMS_TxTelegram.type;
if (hc == 1) {
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RC35StatusMessage_HC1;
} else {
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RC35StatusMessage_HC2;
}
} else if (model_id == EMS_MODEL_RC300) { } else if (model_id == EMS_MODEL_RC300) {
EMS_TxTelegram.type = EMS_TYPE_RCPLUSSet; // for 3000 and 1010, e.g. 48 10 FF 00 01 B9 00 for manual EMS_TxTelegram.type = EMS_TYPE_RCPLUSSet; // for 3000 and 1010, e.g. 48 10 FF 00 01 B9 00 for manual
EMS_TxTelegram.offset = EMS_OFFSET_RCPLUSSet_mode; EMS_TxTelegram.offset = EMS_OFFSET_RCPLUSSet_mode;
EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't validate after the write
// TODO: commented out because it's too fast
// EMS_TxTelegram.type_validate = EMS_TYPE_RCPLUSStatusMessage; // validate by reading from a different telegram
EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't validate after the write
EMS_TxTelegram.comparisonPostRead = EMS_TYPE_RCPLUSStatusMessage; // after write, do a full fetch of all values
} }
EMS_TxTelegram.comparisonOffset = EMS_TxTelegram.offset; EMS_TxTelegram.comparisonOffset = EMS_TxTelegram.offset;
EMS_TxTelegram.comparisonValue = EMS_TxTelegram.dataValue; EMS_TxTelegram.comparisonValue = EMS_TxTelegram.dataValue;
EMS_TxTelegram.comparisonPostRead = EMS_TxTelegram.type; EMS_TxTelegram.forceRefresh = false; // send to MQTT is done automatically in 0xA8 process
EMS_TxTelegram.forceRefresh = false; // send to MQTT is done automatically in 0xA8 process
EMS_TxQueue.push(EMS_TxTelegram); EMS_TxQueue.push(EMS_TxTelegram);
} }

View File

@@ -155,8 +155,8 @@ typedef enum {
typedef struct { typedef struct {
_EMS_RX_STATUS emsRxStatus; _EMS_RX_STATUS emsRxStatus;
_EMS_TX_STATUS emsTxStatus; _EMS_TX_STATUS emsTxStatus;
uint16_t emsRxPgks; // received uint16_t emsRxPgks; // # successfull received
uint16_t emsTxPkgs; // sent uint16_t emsTxPkgs; // # successfull sent
uint16_t emxCrcErr; // CRC errors uint16_t emxCrcErr; // CRC errors
bool emsPollEnabled; // flag enable the response to poll messages bool emsPollEnabled; // flag enable the response to poll messages
_EMS_SYS_LOGGING emsLogging; // logging _EMS_SYS_LOGGING emsLogging; // logging
@@ -168,7 +168,7 @@ typedef struct {
bool emsTxDisabled; // true to prevent all Tx bool emsTxDisabled; // true to prevent all Tx
uint8_t txRetryCount; // # times the last Tx was re-sent uint8_t txRetryCount; // # times the last Tx was re-sent
uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80 uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80
uint8_t emsPollAck[1]; // acknowledge buffer uint8_t emsPollAck[1]; // acknowledge buffer for Poll
} _EMS_Sys_Status; } _EMS_Sys_Status;
// The Tx send package // The Tx send package
@@ -180,9 +180,9 @@ typedef struct {
uint8_t length; // full length of complete telegram, including CRC uint8_t length; // full length of complete telegram, including CRC
uint8_t dataValue; // value to validate against uint8_t dataValue; // value to validate against
uint16_t type_validate; // type to call after a successful Write command uint16_t type_validate; // type to call after a successful Write command
uint8_t comparisonValue; // value to compare against during a validate uint8_t comparisonValue; // value to compare against during a validate command
uint8_t comparisonOffset; // offset of where the byte is we want to compare too later uint8_t comparisonOffset; // offset of where the byte is we want to compare too during validation
uint16_t comparisonPostRead; // after a successful write call this to read from this type ID uint16_t comparisonPostRead; // after a successful write, do a read from this type ID
bool forceRefresh; // should we send to MQTT after a successful Tx? bool forceRefresh; // should we send to MQTT after a successful Tx?
uint32_t timestamp; // when created uint32_t timestamp; // when created
uint8_t data[EMS_MAX_TELEGRAM_LENGTH]; uint8_t data[EMS_MAX_TELEGRAM_LENGTH];

View File

@@ -63,41 +63,46 @@
// RC10 specific // RC10 specific
#define EMS_TYPE_RC10StatusMessage 0xB1 // is an automatic thermostat broadcast giving us temps #define EMS_TYPE_RC10StatusMessage 0xB1 // is an automatic thermostat broadcast giving us temps
#define EMS_TYPE_RC10Set 0xB0 // for setting values like temp and mode
#define EMS_OFFSET_RC10Set_temp 4 // position of thermostat setpoint temperature
#define EMS_OFFSET_RC10StatusMessage_setpoint 1 // setpoint temp #define EMS_OFFSET_RC10StatusMessage_setpoint 1 // setpoint temp
#define EMS_OFFSET_RC10StatusMessage_curr 2 // current temp #define EMS_OFFSET_RC10StatusMessage_curr 2 // current temp
#define EMS_TYPE_RC10Set 0xB0 // for setting values like temp and mode
#define EMS_OFFSET_RC10Set_temp 4 // position of thermostat setpoint temperature
// RC20 specific // RC20 specific
#define EMS_TYPE_RC20StatusMessage 0x91 // is an automatic thermostat broadcast giving us temps #define EMS_TYPE_RC20StatusMessage 0x91 // is an automatic thermostat broadcast giving us temps
#define EMS_TYPE_RC20Set 0xA8 // for setting values like temp and mode
#define EMS_OFFSET_RC20Set_mode 23 // position of thermostat mode
#define EMS_OFFSET_RC20Set_temp 28 // position of thermostat setpoint temperature
#define EMS_OFFSET_RC20StatusMessage_setpoint 1 // setpoint temp #define EMS_OFFSET_RC20StatusMessage_setpoint 1 // setpoint temp
#define EMS_OFFSET_RC20StatusMessage_curr 2 // current temp #define EMS_OFFSET_RC20StatusMessage_curr 2 // current temp
#define EMS_TYPE_RC20Set 0xA8 // for setting values like temp and mode
#define EMS_OFFSET_RC20Set_mode 23 // position of thermostat mode
#define EMS_OFFSET_RC20Set_temp 28 // position of thermostat setpoint temperature
// RC30 specific // RC30 specific
#define EMS_TYPE_RC30StatusMessage 0x41 // is an automatic thermostat broadcast giving us temps #define EMS_TYPE_RC30StatusMessage 0x41 // is an automatic thermostat broadcast giving us temps
#define EMS_TYPE_RC30Set 0xA7 // for setting values like temp and mode
#define EMS_OFFSET_RC30Set_mode 23 // position of thermostat mode
#define EMS_OFFSET_RC30Set_temp 28 // position of thermostat setpoint temperature
#define EMS_OFFSET_RC30StatusMessage_setpoint 1 // setpoint temp #define EMS_OFFSET_RC30StatusMessage_setpoint 1 // setpoint temp
#define EMS_OFFSET_RC30StatusMessage_curr 2 // current temp #define EMS_OFFSET_RC30StatusMessage_curr 2 // current temp
#define EMS_TYPE_RC30Set 0xA7 // for setting values like temp and mode
#define EMS_OFFSET_RC30Set_mode 23 // position of thermostat mode
#define EMS_OFFSET_RC30Set_temp 28 // position of thermostat setpoint temperature
// RC35 specific // RC35 specific
#define EMS_TYPE_RC35StatusMessage_HC1 0x3E // is an automatic thermostat broadcast giving us temps on HC1 #define EMS_TYPE_RC35StatusMessage_HC1 0x3E // is an automatic thermostat broadcast giving us temps on HC1
#define EMS_TYPE_RC35StatusMessage_HC2 0x48 // is an automatic thermostat broadcast giving us temps on HC2 #define EMS_TYPE_RC35StatusMessage_HC2 0x48 // is an automatic thermostat broadcast giving us temps on HC2
#define EMS_TYPE_RC35Set_HC1 0x3D // for setting values like temp and mode (Working mode HC1)
#define EMS_TYPE_RC35Set_HC2 0x47 // for setting values like temp and mode (Working mode HC2)
#define EMS_OFFSET_RC35StatusMessage_setpoint 2 // desired temp #define EMS_OFFSET_RC35StatusMessage_setpoint 2 // desired temp
#define EMS_OFFSET_RC35StatusMessage_curr 3 // current temp #define EMS_OFFSET_RC35StatusMessage_curr 3 // current temp
#define EMS_OFFSET_RC35Set_mode 7 // position of thermostat mode #define EMS_OFFSET_RC35StatusMessage_mode 1 //day mode
#define EMS_OFFSET_RC35Set_temp_day 2 // position of thermostat setpoint temperature for day time
#define EMS_OFFSET_RC35Set_temp_night 1 // position of thermostat setpoint temperature for night time #define EMS_TYPE_RC35Set_HC1 0x3D // for setting values like temp and mode (Working mode HC1)
#define EMS_OFFSET_RC35Get_mode_day 1 // position of thermostat day mode #define EMS_TYPE_RC35Set_HC2 0x47 // for setting values like temp and mode (Working mode HC2)
#define EMS_OFFSET_RC35Set_temp_holiday 3 // temp during holiday 0x47 #define EMS_OFFSET_RC35Set_mode 7 // position of thermostat mode
#define EMS_OFFSET_RC35Set_heatingtype 0 // floor heating = 3 0x47 #define EMS_OFFSET_RC35Set_temp_day 2 // position of thermostat setpoint temperature for day time
#define EMS_OFFSET_RC35Set_circuitcalctemp 14 // calculated circuit temperature 0x48 #define EMS_OFFSET_RC35Set_temp_night 1 // position of thermostat setpoint temperature for night time
#define EMS_OFFSET_RC35Set_temp_holiday 3 // temp during holiday 0x47
#define EMS_OFFSET_RC35Set_heatingtype 0 // floor heating = 3 0x47
#define EMS_OFFSET_RC35Set_circuitcalctemp 14 // calculated circuit temperature 0x48
// Easy specific // Easy specific
#define EMS_TYPE_EasyStatusMessage 0x0A // reading values on an Easy Thermostat #define EMS_TYPE_EasyStatusMessage 0x0A // reading values on an Easy Thermostat
@@ -105,18 +110,20 @@
#define EMS_OFFSET_EasyStatusMessage_curr 8 // current temp #define EMS_OFFSET_EasyStatusMessage_curr 8 // current temp
// RC1010, RC310 and RC300 specific (EMS Plus) // RC1010, RC310 and RC300 specific (EMS Plus)
#define EMS_TYPE_RCPLUSStatusMessage 0x01A5 // is an automatic thermostat broadcast giving us temps #define EMS_TYPE_RCPLUSStatusMessage 0x01A5 // is an automatic thermostat broadcast giving us temps, also reading
#define EMS_TYPE_RCPLUSStatusMode 0x1AF // summer/winter mode #define EMS_TYPE_RCPLUSStatusMode 0x1AF // summer/winter mode
#define EMS_TYPE_RCPLUSSet 0x01B9 // setpoint temp message and mode #define EMS_OFFSET_RCPLUSStatusMessage_mode 10 // thermostat mode (auto, manual)
#define EMS_OFFSET_RCPLUSStatusMessage_setpoint 3 // setpoint temp #define EMS_OFFSET_RCPLUSStatusMessage_setpoint 3 // setpoint temp
#define EMS_OFFSET_RCPLUSStatusMessage_curr 0 // current temp #define EMS_OFFSET_RCPLUSStatusMessage_curr 0 // current temp
#define EMS_OFFSET_RCPLUSGet_mode_day 10 // day/night mode
#define EMS_OFFSET_RCPLUSSet_mode 0 // operation mode (Auto=xFF, Manual=x00) #define EMS_TYPE_RCPLUSSet 0x01B9 // setpoint temp message and mode
#define EMS_OFFSET_RCPLUSStatusMessage_mode 0x0A // thermostat mode (auto, manual) #define EMS_OFFSET_RCPLUSSet_mode 0 // operation mode(Auto=0xFF, Manual=0x00)
#define EMS_OFFSET_RCPLUSSet_temp_comfort3 1 // comfort3 level #define EMS_OFFSET_RCPLUSSet_temp_comfort3 1 // comfort3 level
#define EMS_OFFSET_RCPLUSSet_temp_comfort2 2 // comfort2 level #define EMS_OFFSET_RCPLUSSet_temp_comfort2 2 // comfort2 level
#define EMS_OFFSET_RCPLUSSet_temp_comfort1 3 // comfort1 level #define EMS_OFFSET_RCPLUSSet_temp_comfort1 3 // comfort1 level
#define EMS_OFFSET_RCPLUSSet_temp_eco 4 // eco level #define EMS_OFFSET_RCPLUSSet_temp_eco 4 // eco level
#define EMS_OFFSET_RCPLUSSet_temp_setpoint 8 // temp setpoint, when changing of templevel (in auto) value is reset and set to FF
#define EMS_OFFSET_RCPLUSSet_manual_setpoint 10 // manual setpoint
// Junkers FR10, FW100 (EMS Plus) // Junkers FR10, FW100 (EMS Plus)
#define EMS_TYPE_JunkersStatusMessage 0x6F // is an automatic thermostat broadcast giving us temps #define EMS_TYPE_JunkersStatusMessage 0x6F // is an automatic thermostat broadcast giving us temps

View File

@@ -52,7 +52,8 @@ static const char * TEST_DATA[] = {
"38 10 FF 00 03 2B 00 C7 07 C3 01", // test 47 - heatpump Enviline "38 10 FF 00 03 2B 00 C7 07 C3 01", // test 47 - heatpump Enviline
"08 0B 19 00 00 F7 80 00 80 00 00 00 00 00 03 58 97 0C 7B 1F 00 00 00 06 C4 DF 02 64 48 80 00", // test 48 - outdoor temp check "08 0B 19 00 00 F7 80 00 80 00 00 00 00 00 03 58 97 0C 7B 1F 00 00 00 06 C4 DF 02 64 48 80 00", // test 48 - outdoor temp check
"88 00 19 00 00 DC 80 00 80 00 FF FF 00 00 00 21 9A 06 E1 7C 00 00 00 06 C2 13 00 1E 90 80 00", // test 49 - check max length "88 00 19 00 00 DC 80 00 80 00 FF FF 00 00 00 21 9A 06 E1 7C 00 00 00 06 C2 13 00 1E 90 80 00", // test 49 - check max length
"30 00 FF 00 02 8E 00 00 41 82 00 00 28 36 00 00 82 21" // test 50 - SM100 "30 00 FF 00 02 8E 00 00 41 82 00 00 28 36 00 00 82 21", // test 50 - SM100
"10 00 FF 08 01 B9 26" // test 51 - EMS+ 0x1B9 set temp
}; };

View File

@@ -1,6 +1,6 @@
#define APP_NAME "EMS-ESP" #define APP_NAME "EMS-ESP"
#define APP_VERSION "1.9.0b4" #define APP_VERSION "1.9.0b5"
#define APP_HOSTNAME "ems-esp" #define APP_HOSTNAME "ems-esp"
#define APP_URL "https://github.com/proddy/EMS-ESP" #define APP_URL "https://github.com/proddy/EMS-ESP"
#define APP_UPDATEURL "https://api.github.com/repos/proddy/EMS-ESP/releases/latest" #define APP_UPDATEURL "https://api.github.com/repos/proddy/EMS-ESP/releases/latest"