added support for heatpumps

This commit is contained in:
proddy
2019-05-26 17:43:11 +02:00
parent 4651987da8
commit dfb3ae856c
8 changed files with 100 additions and 17 deletions

View File

@@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- HeatPump (e.g. Nefit Enviline)
- MM50 Mixer
- tx_mode takes a value from 0 to 3 for the different Tx logic

View File

@@ -110,6 +110,11 @@ command_t project_cmds[] = {
{false, "info", "show data captured on the EMS bus"},
{false, "log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
#ifdef TESTS
{false, "test <n>", "insert a test telegram on to the EMS bus"},
#endif
{false, "publish", "publish all values to MQTT"},
{false, "refresh", "fetch values from the EMS devices"},
{false, "devices", "list all supported and detected EMS devices and types IDs"},
@@ -458,6 +463,14 @@ void showInfo() {
_renderShortValue("Energy Total", "kWH", EMS_Other.SMEnergyTotal, 1); // *10
}
// For HeatPumps
if (EMS_Other.HP) {
myDebug_P(PSTR("")); // newline
myDebug_P(PSTR("%sHeat Pump stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF);
_renderIntValue("Pump modulation", "%", EMS_Other.HPModulation);
_renderIntValue("Pump speed", "%", EMS_Other.HPSpeed);
}
// Thermostat stats
if (ems_getThermostatEnabled()) {
myDebug_P(PSTR("")); // newline
@@ -567,6 +580,7 @@ void publishSensorValues() {
// CRC check is done to see if there are changes in the values since the last send to avoid too much wifi traffic
// a check is done against the previous values and if there are changes only then they are published. Unless force=true
void publishValues(bool force) {
// don't send if MQTT is connected
if (!myESP.isMQTTConnected()) {
return;
@@ -751,6 +765,7 @@ void publishValues(bool force) {
}
// handle the other values separately
// For SM10 and SM100 Solar Modules
if (EMS_Other.SM) {
// build new json object
@@ -796,6 +811,27 @@ void publishValues(bool force) {
myESP.mqttPublish(TOPIC_SM_DATA, data);
}
}
// handle HeatPump
if (EMS_Other.HP) {
// build new json object
doc.clear();
JsonObject rootSM = doc.to<JsonObject>();
if (EMS_Other.HPModulation != EMS_VALUE_INT_NOTSET)
rootSM[HP_PUMPMODULATION] = EMS_Other.HPModulation;
if (EMS_Other.HPSpeed != EMS_VALUE_INT_NOTSET)
rootSM[HP_PUMPSPEED] = EMS_Other.HPSpeed;
data[0] = '\0'; // reset data for next package
serializeJson(doc, data, sizeof(data));
myDebugLog("Publishing HeatPump data via MQTT");
// send values via MQTT
myESP.mqttPublish(TOPIC_HP_DATA, data);
}
}
// sets the shower timer on/off
@@ -977,7 +1013,7 @@ void runUnitTest(uint8_t test_num) {
publishValuesTimer.detach();
systemCheckTimer.detach();
regularUpdatesTimer.detach();
EMSESP_Status.listen_mode = true; // temporary go into listen mode to disable Tx
// EMSESP_Status.listen_mode = true; // temporary go into listen mode to disable Tx
ems_testTelegram(test_num);
}
@@ -1092,7 +1128,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
EMSESP_Status.listen_mode = false;
ok = true;
ems_setTxDisabled(false);
myDebug_P(PSTR("* out of listen mode. Tx is enabled."));
myDebug_P(PSTR("* out of listen mode. Tx is now enabled."));
} else {
myDebug_P(PSTR("Error. Usage: set listen_mode <on | off>"));
}
@@ -1451,7 +1487,6 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) {
if ((hc >= 1) && (hc <= 2)) {
EMSESP_Status.heating_circuit = hc;
ems_setThermostatHC(hc);
// TODO: save setting to SPIFFS??
}
}

View File

@@ -50,7 +50,6 @@ void _process_UBAMonitorWWMessage(_EMS_RxTelegram * EMS_RxTelegram);
void _process_UBAParameterWW(_EMS_RxTelegram * EMS_RxTelegram);
void _process_UBATotalUptimeMessage(_EMS_RxTelegram * EMS_RxTelegram);
void _process_UBAParametersMessage(_EMS_RxTelegram * EMS_RxTelegram);
void _process_SetPoints(_EMS_RxTelegram * EMS_RxTelegram);
// SM10
@@ -62,6 +61,10 @@ void _process_SM100Status(_EMS_RxTelegram * EMS_RxTelegram);
void _process_SM100Status2(_EMS_RxTelegram * EMS_RxTelegram);
void _process_SM100Energy(_EMS_RxTelegram * EMS_RxTelegram);
// HeatPump HP
void _process_HPMonitor1(_EMS_RxTelegram * EMS_RxTelegram);
void _process_HPMonitor2(_EMS_RxTelegram * EMS_RxTelegram);
// Common for most thermostats
void _process_RCTime(_EMS_RxTelegram * EMS_RxTelegram);
void _process_RCOutdoorTempMessage(_EMS_RxTelegram * EMS_RxTelegram);
@@ -120,6 +123,8 @@ const _EMS_Type EMS_Types[] = {
{EMS_MODEL_OTHER, EMS_TYPE_SM100Status, "SM100Status", _process_SM100Status},
{EMS_MODEL_OTHER, EMS_TYPE_SM100Status2, "SM100Status2", _process_SM100Status2},
{EMS_MODEL_OTHER, EMS_TYPE_SM100Energy, "SM100Energy", _process_SM100Energy},
{EMS_MODEL_OTHER, EMS_TYPE_HPMonitor1, "HeatPumpMonitor1", _process_HPMonitor1},
{EMS_MODEL_OTHER, EMS_TYPE_HPMonitor2, "HeatPumpMonitor2", _process_HPMonitor2},
// RC10
{EMS_MODEL_RC10, EMS_TYPE_RCTime, "RCTime", _process_RCTime},
@@ -299,6 +304,8 @@ void ems_init() {
EMS_Other.SMEnergyLastHour = EMS_VALUE_SHORT_NOTSET;
EMS_Other.SMEnergyToday = EMS_VALUE_SHORT_NOTSET;
EMS_Other.SMEnergyTotal = EMS_VALUE_SHORT_NOTSET;
EMS_Other.HPModulation = EMS_VALUE_INT_NOTSET;
EMS_Other.HPSpeed = EMS_VALUE_INT_NOTSET;
// calculated values
EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off
@@ -315,6 +322,7 @@ void ems_init() {
// set other types
EMS_Other.SM = false;
EMS_Other.HP = false;
// default logging is none
ems_setLogging(EMS_SYS_LOGGING_DEFAULT);
@@ -695,7 +703,6 @@ void _ems_readTelegram(uint8_t * telegram, uint8_t length) {
// check first for a Poll for us
// the poll has the MSB set - seems to work on both EMS and Junkers
if (value == (EMS_ID_ME | 0x80)) {
EMS_Sys_Status.emsTxCapable = true;
uint32_t timenow_microsecs = micros();
EMS_Sys_Status.emsPollFrequency = (timenow_microsecs - _last_emsPollFrequency);
@@ -1427,10 +1434,9 @@ void _process_SM100Status2(_EMS_RxTelegram * EMS_RxTelegram) {
/*
* SM100Energy - type 0x028E EMS+ for energy readings
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
*/
void _process_SM100Energy(_EMS_RxTelegram * EMS_RxTelegram) {
// e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35
EMS_Other.SMEnergyLastHour = _toShort(2); // last hour / 10 in Wh
EMS_Other.SMEnergyToday = _toShort(6); // todays in Wh
EMS_Other.SMEnergyTotal = _toShort(10); // total / 10 in kWh
@@ -1439,6 +1445,26 @@ void _process_SM100Energy(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
}
/*
* Type 0xE3 - HeatPump Monitor 1
*/
void _process_HPMonitor1(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Other.HPModulation = _toByte(14); // modulation %
EMS_Other.HP = true;
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
}
/*
* Type 0xE5 - HeatPump Monitor 2
*/
void _process_HPMonitor2(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Other.HPSpeed = _toByte(25); // speed %
EMS_Other.HP = true;
EMS_Sys_Status.emsRefreshed = true; // triggers a send the values back via MQTT
}
/**
* UBASetPoint 0x1A
*/
@@ -1631,6 +1657,12 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
myDebug_P(PSTR("SM10 Solar Module support enabled."));
}
// see if this is a HeatPump
if (Other_Types[i].device_id == EMS_ID_HP) {
EMS_Other.HP = true; // we have detected a HP
myDebug_P(PSTR("HeatPump support enabled."));
}
// fetch other values
ems_getOtherValues();
return;

View File

@@ -18,6 +18,7 @@
#define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as the "Service Key"
#define EMS_ID_DEFAULT_BOILER 0x08
#define EMS_ID_SM 0x30 // Solar Module SM10 and SM100
#define EMS_ID_HP 0x38 // HeatPump
#define EMS_ID_GATEWAY 0x48 // KM200 Web Gateway
#define EMS_MIN_TELEGRAM_LENGTH 6 // minimal length for a validation telegram, including CRC
@@ -242,7 +243,8 @@ typedef struct { // UBAParameterWW
// SM Solar Module - SM10Monitor/SM100Monitor
typedef struct {
bool SM; // set true if there is a SM available
bool SM; // set true if there is a Solar Module available
bool HP; // set true if there is a Heat Pump available
int16_t SMcollectorTemp; // collector temp
int16_t SMbottomTemp; // bottom temp
uint8_t SMpumpModulation; // modulation solar pump
@@ -250,6 +252,8 @@ typedef struct {
int16_t SMEnergyLastHour;
int16_t SMEnergyToday;
int16_t SMEnergyTotal;
uint8_t HPModulation; // heatpump modulation in %
uint8_t HPSpeed; // speed 0-100 %
} _EMS_Other;
// Thermostat data

View File

@@ -46,6 +46,8 @@
#define EMS_TYPE_SM100Status 0x0264 // SM100Status
#define EMS_TYPE_SM100Status2 0x026A // SM100Status2
#define EMS_TYPE_SM100Energy 0x028E // SM100Energy
#define EMS_TYPE_HPMonitor1 0xE3 // HeatPump Monitor 1
#define EMS_TYPE_HPMonitor2 0xE5 // HeatPump Monitor 2
/*
* Thermostats...

View File

@@ -58,6 +58,11 @@
#define SM_ENERGYTODAY "energytoday" // energy today
#define SM_ENERGYTOTAL "energytotal" // energy total
// MQTT for HP (HeatPump)
#define TOPIC_HP_DATA "hp_data" // topic name
#define HP_PUMPMODULATION "pumpmodulation" // pump modulation
#define HP_PUMPSPEED "pumpspeed" // pump speed
// shower time
#define TOPIC_SHOWERTIME "showertime" // for sending shower time results
#define TOPIC_SHOWER_TIMER "shower_timer" // toggle switch for enabling the shower logic

View File

@@ -46,7 +46,11 @@ static const char * TEST_DATA[] = {
"10 48 F7 00 FF 01 A5 DF FF F7 7F 1F", // test 41 - gateway
"30 00 FF 09 02 64 1E", // test 42 - SM100
"08 00 18 00 05 03 30 00 00 00 00 04 40 80 00 02 17 80 00 00 00 FF 30 48 00 CB 00 00 00", // test 43 - sys pressure
"90 00 FF 00 00 6F 03 01 00 BE 00 BF" // test 44 - FR10
"90 00 FF 00 00 6F 03 01 00 BE 00 BF", // test 44 - FR10
"08 00 E3 00 01 00 01 00 00 00 00 00 00 00 00 00 DF 00 64 55", // test 45 - heatpump Enviline
"08 00 E5 00 00 00 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 0A", // test 46 - heatpump Enviline
"38 10 FF 00 03 2B 00 C7 07 C3 01" // test 47 - heatpump Enviline
};

View File

@@ -6,5 +6,5 @@
#pragma once
#define APP_NAME "EMS-ESP"
#define APP_VERSION "1.8.0b5"
#define APP_VERSION "1.8.0b6"
#define APP_HOSTNAME "ems-esp"