mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 15:59:52 +03:00
add hanlding for thermostat mode
This commit is contained in:
11
README.md
11
README.md
@@ -76,22 +76,23 @@ I've tested the code and circuit with a few ESP8266 development boards such as t
|
|||||||
|
|
||||||
Use the telnet client to inform you of all activity and errors real-time. This is an example of the telnet output:
|
Use the telnet client to inform you of all activity and errors real-time. This is an example of the telnet output:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
If you hit 'q' and Enter, it will toggle verbose logging showing you more detailed messages. I use ANSI colors with white text for info messages, green for well formatted telegram packages (which have validated CRC checks), red for corrupt packages and yellow for send responses.
|
If you hit 'q' and Enter, it will toggle verbose logging showing you more detailed messages. I use ANSI colors with white text for info messages, green for well formatted telegram packages (which have validated CRC checks), red for corrupt packages and yellow for send responses.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
To see the current values of the Boiler and its parameters type 's' and hit Enter. Watch out for unsuccessful telegram packets in the #CrcErrors line.
|
To see the current values of the Boiler and its parameters type 's' and hit Enter. Watch out for unsuccessful telegram packets in the #CrcErrors line.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Commands can be issued directly to the EMS bus typing in a letter followed by an optional parameter and pressing Enter. Supported commands are:
|
Commands can be issued directly to the EMS bus typing in a letter followed by an optional parameter and pressing Enter. Supported commands are:
|
||||||
* **r** to send a read command to all devices to fetch values. The 2nd parameter is the type. For example 'r 33' will request type UBAParameterWW and bring back the Warm Water temperatures (not the heating) from the Boiler
|
* **r** to send a read command to all devices to fetch values. The 2nd parameter is the type. For example 'r 33' will request type UBAParameterWW and bring back the Warm Water temperatures (not the heating) from the Boiler
|
||||||
* **t** set the thermostat temperature to the given value
|
* **t** set the thermostat temperature to the given value
|
||||||
* **w** to adjust the temperature of the warm water from the boiler
|
* **w** to adjust the temperature of the warm water from the boiler
|
||||||
* **a** to turn the warm water on and off
|
* **a** to turn the warm water on and off
|
||||||
* **p** to toggle the Polling response on/off. It's not necessary to have Polling enabled to work
|
* **p** to toggle the Polling response on/off. It's not necessary to have Polling enabled to work. I use this for debugging purposes.
|
||||||
|
* **m** to set the thermostat mode from low, manual and clock/auto.
|
||||||
* **T** to toggle thermostat reading on/off
|
* **T** to toggle thermostat reading on/off
|
||||||
* **S** to toggle the Shower Timer functionality on/off
|
* **S** to toggle the Shower Timer functionality on/off
|
||||||
|
|
||||||
@@ -187,7 +188,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 |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.
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 86 KiB |
BIN
doc/telnet/telnet_example.PNG
Normal file
BIN
doc/telnet/telnet_example.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 45 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 110 KiB |
BIN
doc/telnet/telnet_stats.PNG
Normal file
BIN
doc/telnet/telnet_stats.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 214 KiB |
BIN
doc/telnet/telnet_verbose.PNG
Normal file
BIN
doc/telnet/telnet_verbose.PNG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 180 KiB |
@@ -46,14 +46,15 @@ Ticker showerResetTimer;
|
|||||||
#define PROJECT_CMDS \
|
#define PROJECT_CMDS \
|
||||||
"s=show statistics\n\r" \
|
"s=show statistics\n\r" \
|
||||||
"* q=toggle Verbose telegram logging\n\r" \
|
"* q=toggle Verbose telegram logging\n\r" \
|
||||||
"* m=publish stats to MQTT\n\r" \
|
"* P=publish stats to MQTT\n\r" \
|
||||||
"* p=toggle Poll response\n\r" \
|
"* p=toggle Poll response (for debugging)\n\r" \
|
||||||
"* T=toggle Thermostat suport on/off\n\r" \
|
"* T=toggle Thermostat suport on/off\n\r" \
|
||||||
"* 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, some examples:\n\r" \
|
||||||
"(33=UBAParameterWW, 18=UBAMonitorFast, 19=UBAMonitorSlow, " \
|
"* from Boiler: 33=UBAParameterWW, 18=UBAMonitorFast, 19=UBAMonitorSlow, 34=UBAMonitorWWMessage\n\r" \
|
||||||
"34=UBAMonitorWWMessage, 91=RC20StatusMessage, 6=RC20Time, 2=Version)\n\r" \
|
"* from Thermostat: 91=RC20StatusMessage, A8=RC20Temperature, 6=RC20Time, 2=Version\n\r" \
|
||||||
"* t [n] set thermostat temperature to n\n\r" \
|
"* t [n] set thermostat temperature to n\n\r" \
|
||||||
|
"* m [n] set thermostat mode (0=low, 1=manual, 2=clock)\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)"
|
||||||
|
|
||||||
@@ -106,7 +107,8 @@ netInfo homeNet = {.mqttHost = MQTT_IP,
|
|||||||
.mqttPass = MQTT_PASS,
|
.mqttPass = MQTT_PASS,
|
||||||
.mqttPort = 1883, // this is the default, change if using another port
|
.mqttPort = 1883, // this is the default, change if using another port
|
||||||
.ssid = WIFI_SSID,
|
.ssid = WIFI_SSID,
|
||||||
.pass = WIFI_PASSWORD};
|
.pass = WIFI_PASSWORD
|
||||||
|
};
|
||||||
|
|
||||||
ESPHelper myESP(&homeNet);
|
ESPHelper myESP(&homeNet);
|
||||||
|
|
||||||
@@ -236,6 +238,16 @@ void showInfo() {
|
|||||||
|
|
||||||
myDebug(" Setpoint room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.setpoint_roomTemp));
|
myDebug(" Setpoint room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.setpoint_roomTemp));
|
||||||
myDebug(" Current room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.curr_roomTemp));
|
myDebug(" Current room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.curr_roomTemp));
|
||||||
|
myDebug(" Mode is set to ");
|
||||||
|
if (EMS_Thermostat.mode == 0) {
|
||||||
|
myDebug("low\n");
|
||||||
|
} else if (EMS_Thermostat.mode == 1) {
|
||||||
|
myDebug("manual\n");
|
||||||
|
} else if (EMS_Thermostat.mode == 2) {
|
||||||
|
myDebug("clock/auto\n");
|
||||||
|
} else {
|
||||||
|
myDebug("<unknown>\n");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// show the Shower Info
|
// show the Shower Info
|
||||||
@@ -303,7 +315,7 @@ void myDebugCallback() {
|
|||||||
b = !ems_getPoll();
|
b = !ems_getPoll();
|
||||||
ems_setPoll(b);
|
ems_setPoll(b);
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'P':
|
||||||
publishValues();
|
publishValues();
|
||||||
break;
|
break;
|
||||||
case 'r': // read command for Boiler or Thermostat
|
case 'r': // read command for Boiler or Thermostat
|
||||||
@@ -312,6 +324,9 @@ void myDebugCallback() {
|
|||||||
case 't': // set thermostat temp
|
case 't': // set thermostat temp
|
||||||
ems_setThermostatTemp(strtof(&cmd[2], 0));
|
ems_setThermostatTemp(strtof(&cmd[2], 0));
|
||||||
break;
|
break;
|
||||||
|
case 'm': // set thermostat mode
|
||||||
|
ems_setThermostatMode(cmd[2] - '0');
|
||||||
|
break;
|
||||||
case 'w': // set warm water temp
|
case 'w': // set warm water temp
|
||||||
ems_setWarmWaterTemp((uint8_t)strtol(&cmd[2], 0, 10));
|
ems_setWarmWaterTemp((uint8_t)strtol(&cmd[2], 0, 10));
|
||||||
break;
|
break;
|
||||||
|
|||||||
149
src/ems.cpp
149
src/ems.cpp
@@ -37,6 +37,12 @@ _EMS_TxTelegram EMS_TxTelegram; // Empty buffer for sending telegrams
|
|||||||
#define EMS_TYPE_RCOutdoorTempMessage 0xa3 // we can ignore
|
#define EMS_TYPE_RCOutdoorTempMessage 0xa3 // we can ignore
|
||||||
#define EMS_TYPE_Version 0x02 // version of the controller
|
#define EMS_TYPE_Version 0x02 // version of the controller
|
||||||
|
|
||||||
|
// Offsets for specific values in a telegram, per type, used for validation
|
||||||
|
#define EMS_OFFSET_RC20Temperature_temp 0x1C // thermostat set temp
|
||||||
|
#define EMS_OFFSET_RC20Temperature_mode 0x17 // thermostat mode
|
||||||
|
#define EMS_OFFSET_UBAParameterWW_wwtemp 0x02 // WW Temperature
|
||||||
|
#define EMS_OFFSET_UBAParameterWW_wwactivated 0x01 // WW Activated
|
||||||
|
|
||||||
// and call backs
|
// and call backs
|
||||||
#define MAX_TYPECALLBACK 12 // make sure it matches the #types you have
|
#define MAX_TYPECALLBACK 12 // make sure it matches the #types you have
|
||||||
// callbacks per type
|
// callbacks per type
|
||||||
@@ -47,7 +53,6 @@ bool _process_UBAParameterWW(uint8_t * data, uint8_t length);
|
|||||||
bool _process_RC20StatusMessage(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_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_RC20Temperature(uint8_t * data, uint8_t length);
|
|
||||||
bool _process_Version(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] =
|
||||||
@@ -62,9 +67,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", 27, _process_RC20Temperature},
|
||||||
{EMS_ID_THERMOSTAT, EMS_TYPE_Version, "Version", 2, _process_Version}
|
{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
|
||||||
_EMS_Boiler EMS_Boiler;
|
_EMS_Boiler EMS_Boiler;
|
||||||
@@ -85,8 +89,7 @@ const uint8_t ems_crc_table[] =
|
|||||||
0x65, 0x67, 0x99, 0x9B, 0x9D, 0x9F, 0x91, 0x93, 0x95, 0x97, 0x89, 0x8B, 0x8D, 0x8F, 0x81, 0x83, 0x85, 0x87, 0xB9,
|
0x65, 0x67, 0x99, 0x9B, 0x9D, 0x9F, 0x91, 0x93, 0x95, 0x97, 0x89, 0x8B, 0x8D, 0x8F, 0x81, 0x83, 0x85, 0x87, 0xB9,
|
||||||
0xBB, 0xBD, 0xBF, 0xB1, 0xB3, 0xB5, 0xB7, 0xA9, 0xAB, 0xAD, 0xAF, 0xA1, 0xA3, 0xA5, 0xA7, 0xD9, 0xDB, 0xDD, 0xDF,
|
0xBB, 0xBD, 0xBF, 0xB1, 0xB3, 0xB5, 0xB7, 0xA9, 0xAB, 0xAD, 0xAF, 0xA1, 0xA3, 0xA5, 0xA7, 0xD9, 0xDB, 0xDD, 0xDF,
|
||||||
0xD1, 0xD3, 0xD5, 0xD7, 0xC9, 0xCB, 0xCD, 0xCF, 0xC1, 0xC3, 0xC5, 0xC7, 0xF9, 0xFB, 0xFD, 0xFF, 0xF1, 0xF3, 0xF5,
|
0xD1, 0xD3, 0xD5, 0xD7, 0xC9, 0xCB, 0xCD, 0xCF, 0xC1, 0xC3, 0xC5, 0xC7, 0xF9, 0xFB, 0xFD, 0xFF, 0xF1, 0xF3, 0xF5,
|
||||||
0xF7, 0xE9, 0xEB, 0xED, 0xEF, 0xE1, 0xE3, 0xE5, 0xE7
|
0xF7, 0xE9, 0xEB, 0xED, 0xEF, 0xE1, 0xE3, 0xE5, 0xE7};
|
||||||
};
|
|
||||||
|
|
||||||
extern ESPHelper myESP; // needed for the DEBUG statements below
|
extern ESPHelper myESP; // needed for the DEBUG statements below
|
||||||
#define myDebug(x, ...) myESP.printf(x, ##__VA_ARGS__);
|
#define myDebug(x, ...) myESP.printf(x, ##__VA_ARGS__);
|
||||||
@@ -95,9 +98,10 @@ extern ESPHelper myESP; // needed for the DEBUG statements below
|
|||||||
const uint64_t RX_READ_TIMEOUT = 5000; // in ms. 5 seconds timeout for read replies
|
const uint64_t RX_READ_TIMEOUT = 5000; // in ms. 5 seconds timeout for read replies
|
||||||
const uint8_t RX_READ_TIMEOUT_COUNT = 4; // 4 retries before timeout
|
const uint8_t RX_READ_TIMEOUT_COUNT = 4; // 4 retries before timeout
|
||||||
|
|
||||||
uint8_t emsLastRxCount = 0;
|
uint8_t emsLastRxCount; // used for retries when sending failed
|
||||||
|
|
||||||
// init stats and counters and buffers
|
// init stats and counters and buffers
|
||||||
|
// uses -1 or 255 for values that haven't been set yet
|
||||||
void ems_init() {
|
void ems_init() {
|
||||||
// overall status
|
// overall status
|
||||||
EMS_Sys_Status.emsRxPgks = 0;
|
EMS_Sys_Status.emsRxPgks = 0;
|
||||||
@@ -120,6 +124,7 @@ void ems_init() {
|
|||||||
EMS_Thermostat.day = 0;
|
EMS_Thermostat.day = 0;
|
||||||
EMS_Thermostat.month = 0;
|
EMS_Thermostat.month = 0;
|
||||||
EMS_Thermostat.year = 0;
|
EMS_Thermostat.year = 0;
|
||||||
|
EMS_Thermostat.mode = 255; // dummy value
|
||||||
|
|
||||||
// UBAParameterWW
|
// UBAParameterWW
|
||||||
EMS_Boiler.wWActivated = false; // Warm Water activated
|
EMS_Boiler.wWActivated = false; // Warm Water activated
|
||||||
@@ -460,6 +465,18 @@ void _processType(uint8_t * telegram, uint8_t length) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Report back true if there is a package pending a write in the queue
|
||||||
|
*/
|
||||||
|
bool _checkWriteQueueFull() {
|
||||||
|
if (EMS_Sys_Status.emsTxStatus == EMS_TX_PENDING) { // send is already pending
|
||||||
|
myDebug("Cannot write - already a telegram pending send.\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // nothing queue, we can do a write command
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UBAParameterWW - type 0x33 - warm water parameters
|
* UBAParameterWW - type 0x33 - warm water parameters
|
||||||
*/
|
*/
|
||||||
@@ -544,28 +561,38 @@ bool _process_RC20StatusMessage(uint8_t * data, uint8_t length) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* RC20Temperature - type 0xa8 - set temp value from the RC20 thermostat (0x17)
|
* RC20Temperature - type 0xa8 - for set temp value and mode from the RC20 thermostat (0x17)
|
||||||
* Special case as we only want to store the value after a write command
|
|
||||||
*/
|
*/
|
||||||
bool _process_RC20Temperature(uint8_t * data, uint8_t length) {
|
bool _process_RC20Temperature(uint8_t * data, uint8_t length) {
|
||||||
// only interested in the single byte response we send to validate a temp change
|
// check if this was called specifically to validate a single value
|
||||||
if (length == 6) {
|
// which is always stored in data[0] because we request only 1 byte
|
||||||
|
if (length == EMS_MIN_TELEGRAM_LENGTH) {
|
||||||
|
if (EMS_TxTelegram.type_validate == EMS_OFFSET_RC20Temperature_temp) {
|
||||||
|
// validate the set temp
|
||||||
EMS_Thermostat.setpoint_roomTemp = ((float)data[0]) / (float)2;
|
EMS_Thermostat.setpoint_roomTemp = ((float)data[0]) / (float)2;
|
||||||
|
} else if (EMS_TxTelegram.type_validate == EMS_OFFSET_RC20Temperature_mode) {
|
||||||
|
// validate the mode
|
||||||
|
EMS_Thermostat.mode = data[0];
|
||||||
|
}
|
||||||
|
|
||||||
EMS_Sys_Status.emsRefreshed = true; // set the updated flag to trigger a send back to HA
|
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Version - type 0x02 - get the version of the Thermostat
|
* Version - type 0x02 - get the version of the Thermostat firmware
|
||||||
*/
|
*/
|
||||||
bool _process_Version(uint8_t * data, uint8_t length) {
|
bool _process_Version(uint8_t * data, uint8_t length) {
|
||||||
uint8_t major = data[1];
|
uint8_t major = data[1];
|
||||||
uint8_t minor = data[2];
|
uint8_t minor = data[2];
|
||||||
|
|
||||||
// TODO: finish this
|
myDebug("Version %d.%d\n", major, minor); // TODO: finish this
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -581,7 +608,7 @@ bool _process_RC20Time(uint8_t * data, uint8_t length) {
|
|||||||
EMS_Thermostat.month = data[1];
|
EMS_Thermostat.month = data[1];
|
||||||
EMS_Thermostat.year = data[0];
|
EMS_Thermostat.year = data[0];
|
||||||
|
|
||||||
// we can optional set the time based on the Thermostat's time if we want
|
// we can optional set the time based on the thermostat's time if we want
|
||||||
setTime(EMS_Thermostat.hour,
|
setTime(EMS_Thermostat.hour,
|
||||||
EMS_Thermostat.minute,
|
EMS_Thermostat.minute,
|
||||||
EMS_Thermostat.second,
|
EMS_Thermostat.second,
|
||||||
@@ -621,11 +648,8 @@ void ems_doReadCommand(uint8_t type) {
|
|||||||
if (type == EMS_TYPE_NONE)
|
if (type == EMS_TYPE_NONE)
|
||||||
return; // not a valid type, quit
|
return; // not a valid type, quit
|
||||||
|
|
||||||
// check if there is already something in the queue
|
if (_checkWriteQueueFull())
|
||||||
if (EMS_Sys_Status.emsTxStatus == EMS_TX_PENDING) { // send is already pending
|
return; // check if there is already something in the queue
|
||||||
myDebug("Cannot write - already a telegram pending send.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t dest, size;
|
uint8_t dest, size;
|
||||||
|
|
||||||
@@ -655,7 +679,7 @@ void ems_doReadCommand(uint8_t type) {
|
|||||||
EMS_TxTelegram.action = EMS_TX_READ; // read command
|
EMS_TxTelegram.action = EMS_TX_READ; // read command
|
||||||
EMS_TxTelegram.dest = dest | 0x80; // set 7th bit to indicate a read
|
EMS_TxTelegram.dest = dest | 0x80; // set 7th bit to indicate a read
|
||||||
EMS_TxTelegram.offset = 0; // 0 for all data
|
EMS_TxTelegram.offset = 0; // 0 for all data
|
||||||
EMS_TxTelegram.length = 6; // is always 6 bytes long (including CRC at end)
|
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH; // is always 6 bytes long (including CRC at end)
|
||||||
EMS_TxTelegram.type = type;
|
EMS_TxTelegram.type = type;
|
||||||
|
|
||||||
_buildTxTelegram(size); // we send the # bytes we want back
|
_buildTxTelegram(size); // we send the # bytes we want back
|
||||||
@@ -665,24 +689,42 @@ void ems_doReadCommand(uint8_t type) {
|
|||||||
* Set the temperature of the thermostat
|
* Set the temperature of the thermostat
|
||||||
*/
|
*/
|
||||||
void ems_setThermostatTemp(float temperature) {
|
void ems_setThermostatTemp(float temperature) {
|
||||||
// check if there is already something in the queue
|
if (_checkWriteQueueFull())
|
||||||
if (EMS_Sys_Status.emsTxStatus == EMS_TX_PENDING) { // send is already pending
|
return; // check if there is already something in the queue
|
||||||
myDebug("Cannot write - already a telegram pending send.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
char s[10];
|
char s[10];
|
||||||
myDebug("Setting thermostat temperature to %s C\n", _float_to_char(s, temperature));
|
myDebug("Setting thermostat temperature to %s C\n", _float_to_char(s, temperature));
|
||||||
|
|
||||||
EMS_TxTelegram.action = EMS_TX_WRITE; // write command
|
EMS_TxTelegram.action = EMS_TX_WRITE;
|
||||||
EMS_TxTelegram.dest = EMS_ID_THERMOSTAT;
|
EMS_TxTelegram.dest = EMS_ID_THERMOSTAT;
|
||||||
EMS_TxTelegram.type = EMS_TYPE_RC20Temperature;
|
EMS_TxTelegram.type = EMS_TYPE_RC20Temperature;
|
||||||
EMS_TxTelegram.offset = 0x1C; // manual setpoint temperature
|
EMS_TxTelegram.offset = EMS_OFFSET_RC20Temperature_temp;
|
||||||
EMS_TxTelegram.length = 6; // includes CRC
|
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
|
||||||
EMS_TxTelegram.checkValue = (uint8_t)((float)temperature * (float)2); // value to compare against. must be a single int
|
EMS_TxTelegram.checkValue = (uint8_t)((float)temperature * (float)2); // value to compare against. must be a single int
|
||||||
|
|
||||||
// post call is RC20StatusMessage to fetch temps and send to HA
|
// post call is back to EMS_TYPE_RC20Temperature to fetch temps and send to HA
|
||||||
EMS_TxTelegram.type_validate = EMS_TYPE_RC20Temperature;
|
EMS_TxTelegram.type_validate = EMS_OFFSET_RC20Temperature_temp;
|
||||||
|
_buildTxTelegram(EMS_TxTelegram.checkValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the thermostat working mode (0=low, 1=manual, 2=clock/auto)
|
||||||
|
*/
|
||||||
|
void ems_setThermostatMode(uint8_t mode) {
|
||||||
|
if (_checkWriteQueueFull())
|
||||||
|
return; // check if there is already something in the queue
|
||||||
|
|
||||||
|
myDebug("Setting thermostat mode to %d\n", mode);
|
||||||
|
|
||||||
|
EMS_TxTelegram.action = EMS_TX_WRITE;
|
||||||
|
EMS_TxTelegram.dest = EMS_ID_THERMOSTAT;
|
||||||
|
EMS_TxTelegram.type = EMS_TYPE_RC20Temperature;
|
||||||
|
EMS_TxTelegram.offset = EMS_OFFSET_RC20Temperature_mode;
|
||||||
|
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
|
||||||
|
EMS_TxTelegram.checkValue = mode; // value to compare against. must be a single int
|
||||||
|
|
||||||
|
// post call is back to EMS_TYPE_RC20Temperature to fetch temps and send to HA
|
||||||
|
EMS_TxTelegram.type_validate = EMS_OFFSET_RC20Temperature_mode;
|
||||||
_buildTxTelegram(EMS_TxTelegram.checkValue);
|
_buildTxTelegram(EMS_TxTelegram.checkValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -690,22 +732,18 @@ void ems_setThermostatTemp(float temperature) {
|
|||||||
* Set the warm water temperature
|
* Set the warm water temperature
|
||||||
*/
|
*/
|
||||||
void ems_setWarmWaterTemp(uint8_t temperature) {
|
void ems_setWarmWaterTemp(uint8_t temperature) {
|
||||||
// check if there is already something in the queue
|
if (_checkWriteQueueFull())
|
||||||
if (EMS_Sys_Status.emsTxStatus == EMS_TX_PENDING) { // send is already pending
|
return; // check if there is already something in the queue
|
||||||
myDebug("Cannot write - already a telegram pending send.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
myDebug("Setting boiler warm water temperature to %d C\n", temperature);
|
myDebug("Setting boiler warm water temperature to %d C\n", temperature);
|
||||||
|
|
||||||
EMS_TxTelegram.action = EMS_TX_WRITE; // write command
|
EMS_TxTelegram.action = EMS_TX_WRITE;
|
||||||
EMS_TxTelegram.dest = EMS_ID_BOILER;
|
EMS_TxTelegram.dest = EMS_ID_BOILER;
|
||||||
EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW;
|
EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW;
|
||||||
EMS_TxTelegram.offset = 0x02; // Temperature
|
EMS_TxTelegram.offset = EMS_OFFSET_UBAParameterWW_wwtemp;
|
||||||
EMS_TxTelegram.length = 6; // includes CRC
|
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
|
||||||
EMS_TxTelegram.checkValue = temperature; // value to compare against. must be a single int
|
EMS_TxTelegram.checkValue = temperature; // value to compare against. must be a single int
|
||||||
|
EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't force a send to check the value but do it during next broadcast
|
||||||
EMS_TxTelegram.type_validate = EMS_ID_NONE; // this means don't send and we'll pick up the data from the next broadcast
|
|
||||||
|
|
||||||
_buildTxTelegram(temperature);
|
_buildTxTelegram(temperature);
|
||||||
}
|
}
|
||||||
@@ -715,28 +753,21 @@ void ems_setWarmWaterTemp(uint8_t temperature) {
|
|||||||
* true = on, false = off
|
* true = on, false = off
|
||||||
*/
|
*/
|
||||||
void ems_setWarmWaterActivated(bool activated) {
|
void ems_setWarmWaterActivated(bool activated) {
|
||||||
// check if there is already something in the queue
|
if (_checkWriteQueueFull())
|
||||||
if (EMS_Sys_Status.emsTxStatus == EMS_TX_PENDING) { // send is already pending
|
return; // check if there is already something in the queue
|
||||||
myDebug("Cannot write - already a telegram pending send.\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
myDebug("Setting boiler warm water to %s\n", activated ? "on" : "off");
|
myDebug("Setting boiler warm water to %s\n", activated ? "on" : "off");
|
||||||
|
|
||||||
EMS_TxTelegram.action = EMS_TX_WRITE; // write command
|
EMS_TxTelegram.action = EMS_TX_WRITE;
|
||||||
EMS_TxTelegram.dest = EMS_ID_BOILER;
|
EMS_TxTelegram.dest = EMS_ID_BOILER;
|
||||||
EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW;
|
EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW;
|
||||||
EMS_TxTelegram.offset = 0x01; // WW activation
|
EMS_TxTelegram.offset = EMS_OFFSET_UBAParameterWW_wwactivated;
|
||||||
EMS_TxTelegram.length = 6; // includes CRC
|
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
|
||||||
EMS_TxTelegram.type_validate = EMS_ID_NONE; // this means don't send and we'll pick up the data from the next broadcast
|
EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't force a send to check the value but do it during next broadcast
|
||||||
|
|
||||||
if (activated) {
|
// 0xFF is on, 0x00 is off
|
||||||
EMS_TxTelegram.checkValue = 0xFF; // the EMS value for on
|
EMS_TxTelegram.checkValue = (activated ? 0xFF : 0x00);
|
||||||
_buildTxTelegram(0xFF);
|
_buildTxTelegram(EMS_TxTelegram.checkValue);
|
||||||
} else {
|
|
||||||
EMS_TxTelegram.checkValue = 0x00; // the EMS value for off
|
|
||||||
_buildTxTelegram(0x00);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -747,7 +778,7 @@ void ems_setWarmWaterActivated(bool activated) {
|
|||||||
// function to turn a telegram int (2 bytes) to a float
|
// function to turn a telegram int (2 bytes) to a float
|
||||||
float _toFloat(uint8_t i, uint8_t * data) {
|
float _toFloat(uint8_t i, uint8_t * data) {
|
||||||
if ((data[i] == 0x80) && (data[i + 1] == 0)) // 0x8000 is used when sensor is missing
|
if ((data[i] == 0x80) && (data[i + 1] == 0)) // 0x8000 is used when sensor is missing
|
||||||
return (float)-1;
|
return (float)-1; // return -1 to indicate that is unknown
|
||||||
|
|
||||||
return ((float)(((data[i] << 8) + data[i + 1]))) / 10;
|
return ((float)(((data[i] << 8) + data[i + 1]))) / 10;
|
||||||
}
|
}
|
||||||
@@ -762,7 +793,7 @@ char * _float_to_char(char * a, float f, uint8_t precision) {
|
|||||||
long p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
|
long p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
|
||||||
|
|
||||||
char * ret = a;
|
char * ret = a;
|
||||||
// check for 0x8000 (sensor missing)
|
// check for 0x8000 (sensor missing), which has a -1 value
|
||||||
if (f == -1) {
|
if (f == -1) {
|
||||||
strcpy(ret, "<n/a>");
|
strcpy(ret, "<n/a>");
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
// Special EMS Telegram Types
|
// Special EMS Telegram Types
|
||||||
#define EMS_TYPE_NONE 0x00 // none
|
#define EMS_TYPE_NONE 0x00 // none
|
||||||
|
|
||||||
|
#define EMS_MIN_TELEGRAM_LENGTH 6 // minimal length for a validation telegram, including CRC
|
||||||
|
|
||||||
#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 */
|
||||||
@@ -108,8 +110,9 @@ typedef struct {
|
|||||||
|
|
||||||
// RC20 data
|
// RC20 data
|
||||||
typedef struct {
|
typedef struct {
|
||||||
float setpoint_roomTemp;
|
float setpoint_roomTemp; // current set temp
|
||||||
float curr_roomTemp;
|
float curr_roomTemp; // current room temp
|
||||||
|
uint8_t mode; // 0=low, 1=manual, 2=clock/auto
|
||||||
uint8_t hour;
|
uint8_t hour;
|
||||||
uint8_t minute;
|
uint8_t minute;
|
||||||
uint8_t second;
|
uint8_t second;
|
||||||
@@ -135,6 +138,7 @@ extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
|
|||||||
void ems_init();
|
void ems_init();
|
||||||
void ems_doReadCommand(uint8_t type);
|
void ems_doReadCommand(uint8_t type);
|
||||||
void ems_setThermostatTemp(float temp);
|
void ems_setThermostatTemp(float temp);
|
||||||
|
void ems_setThermostatMode(uint8_t mode);
|
||||||
void ems_setWarmWaterTemp(uint8_t temperature);
|
void ems_setWarmWaterTemp(uint8_t temperature);
|
||||||
void ems_setWarmWaterActivated(bool activated);
|
void ems_setWarmWaterActivated(bool activated);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user