added mqtt for hot water & heating on/off

This commit is contained in:
proddy
2018-12-08 16:32:21 +01:00
parent 357d2a56ad
commit 30e73cbd0c
20 changed files with 213 additions and 172 deletions

View File

@@ -61,7 +61,10 @@ uint8_t regularUpdatesCount = 0;
// boiler
#define TOPIC_BOILER_DATA MQTT_BOILER "boiler_data" // for sending boiler values
#define TOPIC_BOILER_ MQTT_BOILER "boiler_wwtemp" // warm water selected temp
#define TOPIC_BOILER_WARM_WATER_SELECTED_TEMPERATURE MQTT_BOILER "boiler_wwtemp" // warm water selected temp
#define TOPIC_BOILER_TAPWATER_ACTIVE MQTT_BOILER "tapwater_active" // if hot tap water is running
#define TOPIC_BOILER_HEATING_ACTIVE MQTT_BOILER "heating_active" // if heating is on
// shower time
#define TOPIC_SHOWERTIME MQTT_BOILER "showertime" // for sending shower time results
@@ -95,7 +98,6 @@ const unsigned long SHOWER_COLDSHOT_DURATION = 5; // in seconds! how long for co
const unsigned long SHOWER_OFFSET_TIME = 0; // 0 seconds grace time, to calibrate actual time under the shower
#endif
const uint8_t SHOWER_BURNPOWER_MIN = 80;
typedef struct {
bool wifi_connected;
bool boiler_online;
@@ -106,7 +108,6 @@ typedef struct {
typedef struct {
bool showerOn;
bool hotWaterOn;
unsigned long timerStart; // ms
unsigned long timerPause; // ms
unsigned long duration; // ms
@@ -124,18 +125,18 @@ netInfo homeNet = {.mqttHost = MQTT_IP,
ESPHelper myESP(&homeNet);
command_t PROGMEM project_cmds[] = {{"s", "show statistics"},
{"h", "list supported EMS telegram type ids"},
{"h", "list EMS telegram type ids with supported logic"},
{"P", "publish all stat to MQTT"},
{"v", "[n] set logging (0=none, 1=basic, 2=verbose)"},
{"p", "poll ems response on/off (default is off)"},
{"T", "thermostat monitoring on/off"},
{"S", "shower timer on/off"},
{"A", "shower alert on/off"},
{"r", "[n] send EMS request (n=telegram type id. Use 'h' for list)"},
{"t", "[n] set thermostat temperature to n"},
{"p", "toggle EMS Poll response on/off"},
{"T", "toggle Thermostat monitoring on/off"},
{"S", "toggle Shower timer on/off"},
{"A", "toggle shower Alert on/off"},
{"r", "[n] send EMS request (n=any telegram type id. Use 'h' for suppported types)"},
{"t", "[n] set thermostat temperature"},
{"m", "[n] set thermostat mode (1=manual, 2=auto)"},
{"w", "[n] set boiler warm water temperature to n (min 30)"},
{"a", "[n] boiler warm water on (n=1) or off (n=0)"},
{"w", "[n] set boiler warm water temperature (min 30)"},
{"a", "[n] boiler warm water (1=on, 2=off)"},
{"x", "[n] experimental (warning: for debugging only!)"}};
// calculates size of an 2d array at compile time
@@ -163,6 +164,8 @@ unsigned long timestamp; // for internal timings, via millis()
static int connectionStatus = NO_CONNECTION;
bool startMQTTsent = false;
uint8_t last_boilerActive = 0xFF; // for remembering last setting of the tap water or heating on/off
// toggle for heartbeat LED
bool heartbeatEnabled;
@@ -322,6 +325,10 @@ void showInfo() {
myDebug("\n\n%sBoiler stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
// active stats
myDebug(" Hot tap water is %s\n", (EMS_Boiler.tapwaterActive ? "running" : "off"));
myDebug(" Central Heating is %s\n", (EMS_Boiler.heatingActive ? "active" : "off"));
// UBAParameterWW
_renderBoolValue("Warm Water activated", EMS_Boiler.wWActivated);
_renderBoolValue("Warm Water circulation pump available", EMS_Boiler.wWCircPump);
@@ -348,7 +355,7 @@ void showInfo() {
_renderBoolValue("Circulation pump", EMS_Boiler.wWCirc);
_renderIntValue("Burner selected max power", "%", EMS_Boiler.selBurnPow);
_renderIntValue("Burner current power", "%", EMS_Boiler.curBurnPow);
_renderFloatValue("Flame current", "uA", EMS_Boiler.flameCurr);
_renderFloatValue("Flame current", "mA", EMS_Boiler.flameCurr);
_renderFloatValue("System pressure", "bar", EMS_Boiler.sysPress);
// UBAMonitorSlow
@@ -392,15 +399,16 @@ void showInfo() {
// show the Shower Info
if (Boiler_Status.shower_timer) {
myDebug("\n%sShower stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" Hot water is %s\n", (Boiler_Shower.hotWaterOn ? "running" : "stopped"));
myDebug(" Shower is %s\n", (Boiler_Shower.showerOn ? "on" : "off"));
myDebug("\n%s Shower stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" Shower Timer is %s\n", (Boiler_Shower.showerOn ? "active" : "off"));
}
myDebug("\n");
}
// send values to HA via MQTT
// a json object is created for the boiler and one for the thermostat
// CRC check is done to see if there are changes in the values since the last send to avoid too much wifi traffic
void publishValues(bool force) {
char s[20]; // for formatting strings
@@ -435,7 +443,7 @@ void publishValues(bool force) {
crc.update(data[i]);
}
uint32_t checksum = crc.finalize();
//myDebug("HASH=%d %08x, len=%d, s=%s\n", checksum, checksum, len, data);
//myDebug("Boiler HASH=%d %08x, len=%d, s=%s\n", checksum, checksum, len, data);
if ((previousBoilerPublishCRC != checksum) || force) {
previousBoilerPublishCRC = checksum;
@@ -447,6 +455,19 @@ void publishValues(bool force) {
myESP.publish(TOPIC_BOILER_DATA, data);
}
// see if the heating or hot tap water has changed, if so send
// last_boilerActive stores heating in bit 1 and tap water in bit 2
if (last_boilerActive != ((EMS_Boiler.tapwaterActive << 1) + EMS_Boiler.heatingActive)) {
if (ems_getLogging() != EMS_SYS_LOGGING_NONE) {
myDebug("Publishing hot water and heating state via MQTT\n");
}
myESP.publish(TOPIC_BOILER_TAPWATER_ACTIVE, EMS_Boiler.tapwaterActive == 1 ? "1" : "0");
myESP.publish(TOPIC_BOILER_HEATING_ACTIVE, EMS_Boiler.heatingActive == 1 ? "1" : "0");
last_boilerActive = ((EMS_Boiler.tapwaterActive << 1) + EMS_Boiler.heatingActive); // remember last state
}
// handle the thermostat values separately
if (EMS_Sys_Status.emsThermostatEnabled) {
// only send thermostat values if we actually have them
@@ -476,6 +497,7 @@ void publishValues(bool force) {
crc.update(data[i]);
}
uint32_t checksum = crc.finalize();
//myDebug("Thermostat HASH=%d %08x, len=%d, s=%s\n", checksum, checksum, len, data);
if ((previousThermostatPublishCRC != checksum) || force) {
previousThermostatPublishCRC = checksum;
@@ -517,7 +539,7 @@ void myDebugCallback() {
ems_setPoll(b);
break;
case 'P':
myESP.logger(LOG_HA, "Force publish values");
//myESP.logger(LOG_HA, "Force publish values");
publishValues(true);
break;
case 'r': // read command for Boiler or Thermostat
@@ -751,6 +773,8 @@ void setup() {
myESP.addSubscription(TOPIC_SHOWER_TIMER);
myESP.addSubscription(TOPIC_SHOWER_ALERT);
myESP.addSubscription(TOPIC_BOILER_WARM_WATER_SELECTED_TEMPERATURE);
myESP.addSubscription(TOPIC_BOILER_TAPWATER_ACTIVE);
myESP.addSubscription(TOPIC_BOILER_HEATING_ACTIVE);
myESP.addSubscription(TOPIC_SHOWER_COLDSHOT);
myESP.consoleSetCallBackProjectCmds(project_cmds, ArraySize(project_cmds), myDebugCallback); // set up Telnet commands
@@ -812,11 +836,8 @@ void regularUpdates() {
// only do calls if the EMS is connected and alive
if (Boiler_Status.boiler_online) {
if ((cycle == 0) && Boiler_Status.thermostat_enabled) {
// force get the thermostat mode which is not broadcasted
// important! this is only configured for the RC20. Look up the correct telegram type for other thermostat versions
if (EMS_ID_THERMOSTAT == 0x17) { // RC20 is type 0x17
ems_doReadCommand(EMS_TYPE_RC20Temperature);
}
// force get the thermostat data which are not usually automatically broadcasted
ems_getThermostatTemps();
} else if (cycle == 1) {
ems_doReadCommand(EMS_TYPE_UBAParameterWW); // get Warm Water values
}
@@ -880,10 +901,11 @@ void loop() {
#endif
}
// publish the values to MQTT (only if there are changes)
// if we received new data and flagged for pushing, do it
if (EMS_Sys_Status.emsRefreshed) {
EMS_Sys_Status.emsRefreshed = false;
publishValues(true);
publishValues(false);
}
/*
@@ -892,13 +914,8 @@ void loop() {
if (Boiler_Status.shower_timer) {
// if already in cold mode, ignore all this logic until we're out of the cold blast
if (!Boiler_Shower.doingColdShot) {
// these values come from UBAMonitorFast - type 0x18) which is broadcasted every second so our timings are accurate enough
// and no need to fetch the values from the boiler
Boiler_Shower.hotWaterOn =
((EMS_Boiler.selBurnPow >= SHOWER_BURNPOWER_MIN) && (EMS_Boiler.selFlowTemp == 0) && EMS_Boiler.burnGas);
// is the hot water running?
if (Boiler_Shower.hotWaterOn) {
if (EMS_Boiler.tapwaterActive) {
// if heater was previously off, start the timer
if (Boiler_Shower.timerStart == 0) {
// hot water just started...

View File

@@ -10,6 +10,16 @@
#include <Arduino.h>
#include <TimeLib.h>
// add you custom setings here like thermostat IDs and thresholds
const uint8_t SHOWER_BURNPOWER_MIN = 80;
// define here the Thermostat type
#define EMS_ID_THERMOSTAT EMS_ID_THERMOSTAT_RC20 // your thermostat ID
// define here the boiler power settings (selBurnPow) when hot tap water is running and the heating is on
#define EMS_BOILER_BURNPOWER_TAPWATER 115
#define EMS_BOILER_BURNPOWER_HEATING 75
// Check for ESPurna vs ESPHelper (standalone)
#ifdef USE_CUSTOM_H
#include "debug.h"
@@ -41,21 +51,24 @@ bool _process_RC20Temperature(uint8_t * data, uint8_t length);
bool _process_RCTempMessage(uint8_t * data, uint8_t length);
bool _process_Version(uint8_t * data, uint8_t length);
const _EMS_Types EMS_Types[] =
{{EMS_ID_BOILER, EMS_TYPE_UBAMonitorFast, "UBAMonitorFast", _process_UBAMonitorFast},
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorSlow, "UBAMonitorSlow", _process_UBAMonitorSlow},
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorWWMessage, "UBAMonitorWWMessage", _process_UBAMonitorWWMessage},
{EMS_ID_BOILER, EMS_TYPE_UBAParameterWW, "UBAParameterWW", _process_UBAParameterWW},
{EMS_ID_BOILER, EMS_TYPE_UBATotalUptimeMessage, "UBATotalUptimeMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAMaintenanceSettingsMessage, "UBAMaintenanceSettingsMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAParametersMessage, "UBAParametersMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAMaintenanceStatusMessage, "UBAMaintenanceStatusMessage", NULL},
const _EMS_Types EMS_Types[] = {
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20StatusMessage, "RC20StatusMessage", _process_RC20StatusMessage},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Time, "RC20Time", _process_RC20Time},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Temperature, "RC20Temperature", _process_RC20Temperature},
{EMS_ID_THERMOSTAT, EMS_TYPE_RCTempMessage, "RCTempMessage", _process_RCTempMessage},
{EMS_ID_THERMOSTAT, EMS_TYPE_Version, "Version", _process_Version}};
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorFast, "UBAMonitorFast", _process_UBAMonitorFast},
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorSlow, "UBAMonitorSlow", _process_UBAMonitorSlow},
{EMS_ID_BOILER, EMS_TYPE_UBAMonitorWWMessage, "UBAMonitorWWMessage", _process_UBAMonitorWWMessage},
{EMS_ID_BOILER, EMS_TYPE_UBAParameterWW, "UBAParameterWW", _process_UBAParameterWW},
{EMS_ID_BOILER, EMS_TYPE_UBATotalUptimeMessage, "UBATotalUptimeMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAMaintenanceSettingsMessage, "UBAMaintenanceSettingsMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAParametersMessage, "UBAParametersMessage", NULL},
{EMS_ID_BOILER, EMS_TYPE_UBAMaintenanceStatusMessage, "UBAMaintenanceStatusMessage", NULL},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20StatusMessage, "RC20StatusMessage", _process_RC20StatusMessage},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Time, "RC20Time", _process_RC20Time},
{EMS_ID_THERMOSTAT, EMS_TYPE_RC20Temperature, "RC20Temperature", _process_RC20Temperature},
{EMS_ID_THERMOSTAT, EMS_TYPE_RCTempMessage, "RCTempMessage", _process_RCTempMessage},
{EMS_ID_THERMOSTAT, EMS_TYPE_Version, "Version", _process_Version}
};
uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types
// reserve space for the data we collect from the Boiler and Thermostat
@@ -89,20 +102,21 @@ uint8_t emsLastRxCount; // used for retries when sending failed
// uses -1 or 255 for values that haven't been set yet (EMS_VALUE_INT_NOTSET and EMS_VALUE_FLOAT_NOTSET)
void ems_init() {
// overall status
EMS_Sys_Status.emsRxPgks = 0;
EMS_Sys_Status.emsTxPkgs = 0;
EMS_Sys_Status.emxCrcErr = 0;
EMS_Sys_Status.emsRxStatus = EMS_RX_IDLE;
EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE;
EMS_Sys_Status.emsLastPoll = 0;
EMS_Sys_Status.emsLastRx = 0;
EMS_Sys_Status.emsLastTx = 0;
EMS_Sys_Status.emsRefreshed = false;
EMS_Sys_Status.emsRxPgks = 0;
EMS_Sys_Status.emsTxPkgs = 0;
EMS_Sys_Status.emxCrcErr = 0;
EMS_Sys_Status.emsRxStatus = EMS_RX_IDLE;
EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE;
EMS_Sys_Status.emsLastPoll = 0;
EMS_Sys_Status.emsLastRx = 0;
EMS_Sys_Status.emsLastTx = 0;
EMS_Sys_Status.emsRefreshed = false;
EMS_Sys_Status.emsPollEnabled = false; // start up with Poll disabled
EMS_Sys_Status.emsThermostatEnabled = true; // there is a RCxx thermostat active as default
EMS_Sys_Status.emsLogging = EMS_SYS_LOGGING_NONE; // Verbose logging is off
// thermostat
EMS_Thermostat.type = EMS_ID_THERMOSTAT; // type, see ems.h
EMS_Thermostat.hour = 0;
EMS_Thermostat.minute = 0;
EMS_Thermostat.second = 0;
@@ -146,6 +160,9 @@ void ems_init() {
EMS_Boiler.wWWorkM = EMS_VALUE_INT_NOTSET; // Warm Water # minutes
EMS_Boiler.wWOneTime = EMS_VALUE_INT_NOTSET; // Warm Water one time function on/off
EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off
EMS_Boiler.heatingActive = EMS_VALUE_INT_NOTSET; // Central heating is on/off
// init the Tx package
_initTxBuffer();
}
@@ -316,13 +333,18 @@ void ems_parseTelegram(uint8_t * telegram, uint8_t length) {
&& ((millis() - EMS_Sys_Status.emsLastTx) > RX_READ_TIMEOUT)) {
if (emsLastRxCount++ >= RX_READ_TIMEOUT_COUNT) {
// give up and reset tx
myDebug("Error! Failed to send telegram, cancelling last write command.\n");
if (EMS_Sys_Status.emsLogging != EMS_SYS_LOGGING_NONE) {
myDebug("Error! Failed to send telegram, cancelling last write command.\n");
}
// re-initialise
_initTxBuffer();
} else {
myDebug("Didn't receive acknowledgement from the 0x%02x, so resending (attempt #%d/%d)...\n",
EMS_TxTelegram.type,
emsLastRxCount,
RX_READ_TIMEOUT_COUNT);
if (EMS_Sys_Status.emsLogging != EMS_SYS_LOGGING_NONE) {
myDebug("Didn't receive acknowledgement from the 0x%02x, so resending (attempt #%d/%d)...\n",
EMS_TxTelegram.type,
emsLastRxCount,
RX_READ_TIMEOUT_COUNT);
}
EMS_Sys_Status.emsTxStatus = EMS_TX_PENDING; // set to pending will trigger sending the same package again
}
}
@@ -415,10 +437,11 @@ void _processType(uint8_t * telegram, uint8_t length) {
// we have a match
typeFound = true;
// call callback to fetch the values from the telegram
// ignoring the return value for now
// return value tells us if we need to force send values back to MQTT
if ((EMS_Types[i].processType_cb) != (void *)NULL) {
(void)EMS_Types[i].processType_cb(data, length);
EMS_Sys_Status.emsRefreshed = EMS_Types[i].processType_cb(data, length);
}
break;
}
i++;
@@ -530,7 +553,7 @@ bool _checkWriteQueueFull() {
myDebug("Delaying write command as there is already a telegram (type 0x%02x) in the queue\n",
EMS_TxTelegram.type);
}
return true;
return true; // something in queue
}
return false; // nothing queue, we can do a write command
@@ -538,7 +561,7 @@ bool _checkWriteQueueFull() {
/*
* UBAParameterWW - type 0x33 - warm water parameters
* received only after requested
* received only after requested (not broadcasted)
*/
bool _process_UBAParameterWW(uint8_t * data, uint8_t length) {
EMS_Boiler.wWSelTemp = data[2];
@@ -546,9 +569,7 @@ bool _process_UBAParameterWW(uint8_t * data, uint8_t length) {
EMS_Boiler.wWCircPump = (data[6] == 0xFF); // 0xFF means on
EMS_Boiler.wWDesiredTemp = data[8];
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back to Home Assistant via MQTT
return true;
return true; // triggers a send the values back to Home Assistant via MQTT
}
/*
@@ -561,7 +582,7 @@ bool _process_UBAMonitorWWMessage(uint8_t * data, uint8_t length) {
EMS_Boiler.wWWorkM = _toLong(10, data);
EMS_Boiler.wWOneTime = bitRead(data[5], 1);
return true;
return false; // no need to update mqtt
}
/*
@@ -573,16 +594,23 @@ bool _process_UBAMonitorFast(uint8_t * data, uint8_t length) {
EMS_Boiler.curFlowTemp = _toFloat(1, data);
EMS_Boiler.retTemp = _toFloat(13, data);
uint8_t v = data[7];
EMS_Boiler.burnGas = bitRead(v, 0);
EMS_Boiler.fanWork = bitRead(v, 2);
EMS_Boiler.ignWork = bitRead(v, 3);
EMS_Boiler.heatPmp = bitRead(v, 5);
EMS_Boiler.wWHeat = bitRead(v, 6);
EMS_Boiler.wWCirc = bitRead(v, 7);
EMS_Boiler.selBurnPow = data[3]; // max power
uint8_t v = data[7];
EMS_Boiler.burnGas = bitRead(v, 0);
EMS_Boiler.fanWork = bitRead(v, 2);
EMS_Boiler.ignWork = bitRead(v, 3);
EMS_Boiler.heatPmp = bitRead(v, 5);
EMS_Boiler.wWHeat = bitRead(v, 6);
EMS_Boiler.wWCirc = bitRead(v, 7);
EMS_Boiler.curBurnPow = data[4];
EMS_Boiler.selBurnPow = data[3]; // burn power max setting
// check if the boiler is providing hot water to the tap or hot water to the central heating
// we use a quick hack:
// the heating on, if burner selected max power = 75 (UBAMonitorFast:EMS_Boiler.selBurnPow)
// hot tap water running, if burner selected max power=115 (UBAMonitorFast:EMS_Boiler.selBurnPow)
// we could also add (EMS_Boiler.selFlowTemp == 0) && EMS_Boiler.burnGas) for more precision
EMS_Boiler.tapwaterActive = ((EMS_Boiler.selBurnPow == EMS_BOILER_BURNPOWER_TAPWATER) ? 1 : 0);
EMS_Boiler.heatingActive = ((EMS_Boiler.selBurnPow == EMS_BOILER_BURNPOWER_HEATING) ? 1 : 0);
EMS_Boiler.flameCurr = _toFloat(15, data);
@@ -592,7 +620,7 @@ bool _process_UBAMonitorFast(uint8_t * data, uint8_t length) {
EMS_Boiler.sysPress = (((float)data[17]) / (float)10);
}
return true;
return false; // no need to update mqtt
}
/*
@@ -607,9 +635,7 @@ bool _process_UBAMonitorSlow(uint8_t * data, uint8_t length) {
EMS_Boiler.burnWorkMin = _toLong(13, data);
EMS_Boiler.heatWorkMin = _toLong(19, data);
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back to Home Assistant via MQTT
return true;
return true; // triggers a send the values back to Home Assistant via MQTT
}
/*
@@ -620,9 +646,7 @@ bool _process_RC20StatusMessage(uint8_t * data, uint8_t length) {
EMS_Thermostat.setpoint_roomTemp = ((float)data[1]) / (float)2;
EMS_Thermostat.curr_roomTemp = _toFloat(2, data);
EMS_Sys_Status.emsRefreshed = true; // set the updated flag to trigger a send back to HA
return true;
return true; // triggers a send the values back to Home Assistant via MQTT
}
/*
@@ -642,13 +666,12 @@ bool _process_RC20Temperature(uint8_t * data, uint8_t length) {
}
// and send the values back to HA (Home Assistant MQTT)
EMS_Sys_Status.emsRefreshed = true;
} else {
// Process the whole telegram package
EMS_Thermostat.mode = data[EMS_OFFSET_RC20Temperature_mode]; // get the mode
return true;
}
return true;
// Process the whole telegram package
EMS_Thermostat.mode = data[EMS_OFFSET_RC20Temperature_mode]; // get the mode
return false; // don't update mqtt
}
/*
@@ -657,21 +680,24 @@ bool _process_RC20Temperature(uint8_t * data, uint8_t length) {
bool _process_RCTempMessage(uint8_t * data, uint8_t length) {
// add support here if you're reading external sensors
return true;
return false; // don't update mqtt
}
/*
* Version - type 0x02 - get the version of the Thermostat firmware
* We don't bother storing these values anywhere
* When a thermostat is connecting it will send out 0x02 messages too, which we'll ignore
* We don't bother storing these values anywhere, just print
*/
bool _process_Version(uint8_t * data, uint8_t length) {
uint8_t major = data[1];
uint8_t minor = data[2];
// ignore short messages
if (length == 8) {
uint8_t major = data[1];
uint8_t minor = data[2];
myDebug("Version %d.%d\n", major, minor);
}
myDebug("Version %d.%d\n", major, minor);
return true;
return false; // don't update mqtt
}
/*
@@ -696,7 +722,7 @@ bool _process_RC20Time(uint8_t * data, uint8_t length) {
EMS_Thermostat.year + 2000);
*/
return true;
return false; // don't update mqtt
}
/*
@@ -720,6 +746,15 @@ void _buildTxTelegram(uint8_t data_value) {
EMS_Sys_Status.emsTxStatus = EMS_TX_PENDING; // armed and ready to send
}
/*
* Generic function to return temperature settings from the thermostat
*/
void ems_getThermostatTemps() {
if (EMS_Thermostat.type == EMS_ID_THERMOSTAT_RC20) {
ems_doReadCommand(EMS_TYPE_RC20Temperature);
}
}
/*
* Send a command to UART Tx to Read from another device
* Read commands when sent must respond by the destination (target) immediately (or within 10ms)

View File

@@ -21,8 +21,10 @@
#define EMS_TX_MAXBUFFERSIZE 128 // max size of the buffer. packets are 32 bits
// define here the Thermostat type
#define EMS_ID_THERMOSTAT 0x17 // x17=RC20 (Moduline300), x10=RC30/RC35 (Moduline 400)
#define EMS_ID_THERMOSTAT_RC20 0x17 // RC20 (older Moduline 300)
#define EMS_ID_THERMOSTAT_RC30 0x10 // RC30 (Moduline 300)
#define EMS_ID_THERMOSTAT_RC35 0x10 // RC35 (Moduline 400)
#define EMS_ID_THERMOSTAT_EASY 0x18 // Nefit Easy
// define here the EMS telegram types you need
@@ -143,10 +145,16 @@ typedef struct {
uint32_t wWStarts; // Warm Water # starts
uint32_t wWWorkM; // Warm Water # minutes
uint8_t wWOneTime; // Warm Water one time function on/off
// calculated values
uint8_t tapwaterActive; // Hot tap water is on/off
uint8_t heatingActive; // Central heating is on/off
} _EMS_Boiler;
// RC20 data
// Thermostat data
typedef struct {
uint8_t type; // thermostat type (RC20, RC30, RC35 etc)
float setpoint_roomTemp; // current set temp
float curr_roomTemp; // current room temp
uint8_t mode; // 0=low, 1=manual, 2=auto
@@ -183,22 +191,26 @@ typedef struct {
#define COLOR_BOLD_OFF "\x1B[21m"
// function definitions
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
void ems_init();
void ems_doReadCommand(uint8_t type);
void ems_setThermostatTemp(float temp);
void ems_setThermostatMode(uint8_t mode);
void ems_setWarmWaterTemp(uint8_t temperature);
void ems_setWarmWaterActivated(bool activated);
void ems_setExperimental(uint8_t value);
void ems_setPoll(bool b);
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
void ems_init();
void ems_doReadCommand(uint8_t type);
void ems_setThermostatTemp(float temp);
void ems_setThermostatMode(uint8_t mode);
void ems_setWarmWaterTemp(uint8_t temperature);
void ems_setWarmWaterActivated(bool activated);
void ems_setExperimental(uint8_t value);
void ems_setPoll(bool b);
void ems_setThermostatEnabled(bool b);
void ems_setLogging(_EMS_SYS_LOGGING loglevel);
void ems_getThermostatTemps();
bool ems_getPoll();
bool ems_getThermostatEnabled();
void ems_setThermostatEnabled(bool b);
void ems_setLogging(_EMS_SYS_LOGGING loglevel);
_EMS_SYS_LOGGING ems_getLogging();
uint8_t ems_getEmsTypesCount();
void ems_printAllTypes();
void ems_printAllTypes();
// private functions
uint8_t _crcCalculator(uint8_t * data, uint8_t len);