SplitSolarModuleFromOtherDevices

Solar modules upgrades: a separate Solar Module types list (no longer part of other devices). Made a separate _EMS_SolarModule class (no longer part of _EMS_Other). And updated all code that was impacted by that change.
Also added a device description for solar modules.
Tests on my setup (telnet & MQTT) work as before.
This commit is contained in:
Vuego123
2019-06-20 00:16:34 +02:00
parent 1a125763c3
commit b984b9e3d8
4 changed files with 290 additions and 93 deletions

View File

@@ -450,22 +450,24 @@ void showInfo() {
} }
// For SM10/SM100 Solar Module // For SM10/SM100 Solar Module
if (EMS_Other.SM) { if (ems_getThermostatEnabled()) {
myDebug_P(PSTR("")); // newline myDebug_P(PSTR("")); // newline
myDebug_P(PSTR("%sSolar Module stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF); myDebug_P(PSTR("%sSolar Module stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF);
_renderShortValue("Collector temperature", "C", EMS_Other.SMcollectorTemp); myDebug_P(PSTR(" Solar Module: %s"), ems_getSolarModuleDescription(buffer_type));
_renderShortValue("Bottom temperature", "C", EMS_Other.SMbottomTemp); _renderShortValue("Collector temperature", "C", EMS_SolarModule.collectorTemp);
_renderIntValue("Pump modulation", "%", EMS_Other.SMpumpModulation); _renderShortValue("Bottom temperature", "C", EMS_SolarModule.bottomTemp);
_renderBoolValue("Pump active", EMS_Other.SMpump); _renderIntValue("Pump modulation", "%", EMS_SolarModule.pumpModulation);
_renderShortValue("Energy Last Hour", "Wh", EMS_Other.SMEnergyLastHour, 1); // *10 _renderBoolValue("Pump active", EMS_SolarModule.pump);
_renderShortValue("Energy Today", "Wh", EMS_Other.SMEnergyToday, 0); _renderShortValue("Energy Last Hour", "Wh", EMS_SolarModule.EnergyLastHour, 1); // *10
_renderShortValue("Energy Total", "kWH", EMS_Other.SMEnergyTotal, 1); // *10 _renderShortValue("Energy Today", "Wh", EMS_SolarModule.EnergyToday, 0);
_renderShortValue("Energy Total", "kWH", EMS_SolarModule.EnergyTotal, 1); // *10
} }
// For HeatPumps // For HeatPumps
if (EMS_Other.HP) { if (EMS_Other.HP) {
myDebug_P(PSTR("")); // newline myDebug_P(PSTR("")); // newline
myDebug_P(PSTR("%sHeat Pump stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF); myDebug_P(PSTR("%sHeat Pump stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug_P(PSTR(" Solar Module: %s"), ems_getHeatPumpDescription(buffer_type));
_renderIntValue("Pump modulation", "%", EMS_Other.HPModulation); _renderIntValue("Pump modulation", "%", EMS_Other.HPModulation);
_renderIntValue("Pump speed", "%", EMS_Other.HPSpeed); _renderIntValue("Pump speed", "%", EMS_Other.HPSpeed);
} }
@@ -762,32 +764,32 @@ void publishValues(bool force) {
// handle the other values separately // handle the other values separately
// For SM10 and SM100 Solar Modules // For SM10 and SM100 Solar Modules
if (EMS_Other.SM) { if (ems_getSolarModuleEnabled()) {
// build new json object // build new json object
doc.clear(); doc.clear();
JsonObject rootSM = doc.to<JsonObject>(); JsonObject rootSM = doc.to<JsonObject>();
if (abs(EMS_Other.SMcollectorTemp) != EMS_VALUE_SHORT_NOTSET) if (abs(EMS_SolarModule.collectorTemp) != EMS_VALUE_SHORT_NOTSET)
rootSM[SM_COLLECTORTEMP] = (double)EMS_Other.SMcollectorTemp / 10; rootSM[SM_COLLECTORTEMP] = (double)EMS_SolarModule.collectorTemp / 10;
if (abs(EMS_Other.SMbottomTemp) != EMS_VALUE_SHORT_NOTSET) if (abs(EMS_SolarModule.bottomTemp) != EMS_VALUE_SHORT_NOTSET)
rootSM[SM_BOTTOMTEMP] = (double)EMS_Other.SMbottomTemp / 10; rootSM[SM_BOTTOMTEMP] = (double)EMS_SolarModule.bottomTemp / 10;
if (EMS_Other.SMpumpModulation != EMS_VALUE_INT_NOTSET) if (EMS_SolarModule.pumpModulation != EMS_VALUE_INT_NOTSET)
rootSM[SM_PUMPMODULATION] = EMS_Other.SMpumpModulation; rootSM[SM_PUMPMODULATION] = EMS_SolarModule.pumpModulation;
if (EMS_Other.SMpump != EMS_VALUE_INT_NOTSET) { if (EMS_SolarModule.pump != EMS_VALUE_INT_NOTSET) {
rootSM[SM_PUMP] = _bool_to_char(s, EMS_Other.SMpump); rootSM[SM_PUMP] = _bool_to_char(s, EMS_SolarModule.pump);
} }
if (abs(EMS_Other.SMEnergyLastHour) != EMS_VALUE_SHORT_NOTSET) if (abs(EMS_SolarModule.EnergyLastHour) != EMS_VALUE_SHORT_NOTSET)
rootSM[SM_ENERGYLASTHOUR] = (double)EMS_Other.SMEnergyLastHour / 10; rootSM[SM_ENERGYLASTHOUR] = (double)EMS_SolarModule.EnergyLastHour / 10;
if (abs(EMS_Other.SMEnergyToday) != EMS_VALUE_SHORT_NOTSET) if (abs(EMS_SolarModule.EnergyToday) != EMS_VALUE_SHORT_NOTSET)
rootSM[SM_ENERGYTODAY] = EMS_Other.SMEnergyToday; rootSM[SM_ENERGYTODAY] = EMS_SolarModule.EnergyToday;
if (abs(EMS_Other.SMEnergyTotal) != EMS_VALUE_SHORT_NOTSET) if (abs(EMS_SolarModule.EnergyTotal) != EMS_VALUE_SHORT_NOTSET)
rootSM[SM_ENERGYTOTAL] = (double)EMS_Other.SMEnergyTotal / 10; rootSM[SM_ENERGYTOTAL] = (double)EMS_SolarModule.EnergyTotal / 10;
data[0] = '\0'; // reset data for next package data[0] = '\0'; // reset data for next package
serializeJson(doc, data, sizeof(data)); serializeJson(doc, data, sizeof(data));
@@ -927,7 +929,7 @@ void do_regularUpdates() {
myDebugLog("Requesting scheduled EMS device data"); myDebugLog("Requesting scheduled EMS device data");
ems_getThermostatValues(); ems_getThermostatValues();
ems_getBoilerValues(); ems_getBoilerValues();
ems_getOtherValues(); ems_getSolarModuleValues();
} }
} }

View File

@@ -184,12 +184,14 @@ const _EMS_Type EMS_Types[] = {
// calculate sizes of arrays at compile // calculate sizes of arrays at compile
uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types uint8_t _EMS_Types_max = ArraySize(EMS_Types); // number of defined types
uint8_t _Boiler_Types_max = ArraySize(Boiler_Types); // number of boiler models uint8_t _Boiler_Types_max = ArraySize(Boiler_Types); // number of boiler models
uint8_t _Solar_Module_Types_max = ArraySize(SolarModule_Types);// number of solar module types
uint8_t _Other_Types_max = ArraySize(Other_Types); // number of other ems devices uint8_t _Other_Types_max = ArraySize(Other_Types); // number of other ems devices
uint8_t _Thermostat_Types_max = ArraySize(Thermostat_Types); // number of defined thermostat types uint8_t _Thermostat_Types_max = ArraySize(Thermostat_Types); // number of defined thermostat types
// these structs contain the data we store from the Boiler and Thermostat // these structs contain the data we store from the Boiler and Thermostat
_EMS_Boiler EMS_Boiler; // for boiler _EMS_Boiler EMS_Boiler; // for boiler
_EMS_Thermostat EMS_Thermostat; // for thermostat _EMS_Thermostat EMS_Thermostat; // for thermostat
_EMS_SolarModule EMS_SolarModule; // for solar modules
_EMS_Other EMS_Other; // for other known EMS devices _EMS_Other EMS_Other; // for other known EMS devices
// CRC lookup table with poly 12 for faster checking // CRC lookup table with poly 12 for faster checking
@@ -298,16 +300,24 @@ void ems_init() {
EMS_Boiler.pump_mod_max = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation max. power EMS_Boiler.pump_mod_max = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation max. power
EMS_Boiler.pump_mod_min = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation min. power EMS_Boiler.pump_mod_min = EMS_VALUE_INT_NOTSET; // Boiler circuit pump modulation min. power
// Solar Module values
EMS_SolarModule.collectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100
EMS_SolarModule.bottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100
EMS_SolarModule.pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100
EMS_SolarModule.pump = EMS_VALUE_INT_NOTSET; // pump active
EMS_SolarModule.EnergyLastHour = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyToday = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.EnergyTotal = EMS_VALUE_SHORT_NOTSET;
EMS_SolarModule.device_id = EMS_ID_NONE;
EMS_SolarModule.model_id = EMS_MODEL_NONE;
EMS_SolarModule.product_id = EMS_ID_NONE;
// Other EMS devices values // Other EMS devices values
EMS_Other.SMcollectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100
EMS_Other.SMbottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100
EMS_Other.SMpumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100
EMS_Other.SMpump = EMS_VALUE_INT_NOTSET; // pump active
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.HPModulation = EMS_VALUE_INT_NOTSET;
EMS_Other.HPSpeed = EMS_VALUE_INT_NOTSET; EMS_Other.HPSpeed = EMS_VALUE_INT_NOTSET;
EMS_Other.device_id = EMS_ID_NONE;
EMS_Other.model_id = EMS_MODEL_NONE;
EMS_Other.product_id = EMS_ID_NONE;
// calculated values // calculated values
EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off EMS_Boiler.tapwaterActive = EMS_VALUE_INT_NOTSET; // Hot tap water is on/off
@@ -323,7 +333,6 @@ void ems_init() {
strlcpy(EMS_Thermostat.version, "?", sizeof(EMS_Thermostat.version)); strlcpy(EMS_Thermostat.version, "?", sizeof(EMS_Thermostat.version));
// set other types // set other types
EMS_Other.SM = false;
EMS_Other.HP = false; EMS_Other.HP = false;
// default logging is none // default logging is none
@@ -360,10 +369,22 @@ bool ems_getThermostatEnabled() {
return (EMS_Thermostat.device_id != EMS_ID_NONE); return (EMS_Thermostat.device_id != EMS_ID_NONE);
} }
bool ems_getSolarModuleEnabled() {
return (EMS_SolarModule.device_id != EMS_ID_NONE);
}
uint8_t ems_getThermostatModel() { uint8_t ems_getThermostatModel() {
return (EMS_Thermostat.model_id); return (EMS_Thermostat.model_id);
} }
uint8_t ems_getOtherModel() {
return (EMS_Other.model_id);
}
uint8_t ems_getSolarModuleModel() {
return (EMS_SolarModule.model_id);
}
void ems_setTxDisabled(bool b) { void ems_setTxDisabled(bool b) {
EMS_Sys_Status.emsTxDisabled = b; EMS_Sys_Status.emsTxDisabled = b;
} }
@@ -1350,12 +1371,12 @@ void _process_RCOutdoorTempMessage(_EMS_RxTelegram * EMS_RxTelegram) {
* SM10Monitor - type 0x97 * SM10Monitor - type 0x97
*/ */
void _process_SM10Monitor(_EMS_RxTelegram * EMS_RxTelegram) { void _process_SM10Monitor(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Other.SMcollectorTemp = _toShort(2); // collector temp from SM10, is *10 EMS_SolarModule.collectorTemp = _toShort(2); // collector temp from SM10, is *10
EMS_Other.SMbottomTemp = _toShort(5); // bottom temp from SM10, is *10 EMS_SolarModule.bottomTemp = _toShort(5); // bottom temp from SM10, is *10
EMS_Other.SMpumpModulation = _toByte(4); // modulation solar pump EMS_SolarModule.pumpModulation = _toByte(4); // modulation solar pump
EMS_Other.SMpump = _bitRead(7, 1); // active if bit 1 is set EMS_SolarModule.pump = _bitRead(7, 1); // active if bit 1 is set
EMS_Other.SM = true; // EMS_Other.SM = true;
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
} }
@@ -1371,13 +1392,13 @@ void _process_SM100Monitor(_EMS_RxTelegram * EMS_RxTelegram) {
return; return;
} }
EMS_Other.SMcollectorTemp = _toShort(0); // collector temp from SM100, is *10 EMS_SolarModule.collectorTemp = _toShort(0); // collector temp from SM100, is *10
if (EMS_RxTelegram->data_length > 2) { if (EMS_RxTelegram->data_length > 2) {
EMS_Other.SMbottomTemp = _toShort(2); // bottom temp from SM100, is *10 EMS_SolarModule.bottomTemp = _toShort(2); // bottom temp from SM100, is *10
} }
EMS_Other.SM = true; // EMS_Other.SM = true;
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
} }
@@ -1389,13 +1410,13 @@ void _process_SM100Monitor(_EMS_RxTelegram * EMS_RxTelegram) {
void _process_SM100Status(_EMS_RxTelegram * EMS_RxTelegram) { void _process_SM100Status(_EMS_RxTelegram * EMS_RxTelegram) {
// check for complete telegram // check for complete telegram
if (EMS_RxTelegram->offset == 0) { if (EMS_RxTelegram->offset == 0) {
EMS_Other.SMpumpModulation = _toByte(9); // modulation solar pump EMS_SolarModule.pumpModulation = _toByte(9); // modulation solar pump
} else if (EMS_RxTelegram->offset == 0x09) { } else if (EMS_RxTelegram->offset == 0x09) {
// or short telegram with a single byte with offset 09 // or short telegram with a single byte with offset 09
EMS_Other.SMpumpModulation = _toByte(0); // modulation solar pump EMS_SolarModule.pumpModulation = _toByte(0); // modulation solar pump
} }
EMS_Other.SM = true; // EMS_Other.SM = true;
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
} }
@@ -1405,13 +1426,13 @@ void _process_SM100Status(_EMS_RxTelegram * EMS_RxTelegram) {
void _process_SM100Status2(_EMS_RxTelegram * EMS_RxTelegram) { void _process_SM100Status2(_EMS_RxTelegram * EMS_RxTelegram) {
// check for complete telegram // check for complete telegram
if (EMS_RxTelegram->offset == 0) { if (EMS_RxTelegram->offset == 0) {
EMS_Other.SMpump = _bitRead(10, 2); // 03=off 04=on at offset 10 which is byte 10 EMS_SolarModule.pump = _bitRead(10, 2); // 03=off 04=on at offset 10 which is byte 10
} else if (EMS_RxTelegram->offset == 0x0A) { } else if (EMS_RxTelegram->offset == 0x0A) {
// or short telegram with a single byte with offset 0A // or short telegram with a single byte with offset 0A
EMS_Other.SMpump = _bitRead(0, 2); // 03=off 04=on EMS_SolarModule.pump = _bitRead(0, 2); // 03=off 04=on
} }
EMS_Other.SM = true; // EMS_Other.SM = true;
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
} }
@@ -1420,11 +1441,11 @@ void _process_SM100Status2(_EMS_RxTelegram * EMS_RxTelegram) {
* e.g. 30 00 FF 00 02 8E 00 00 00 00 00 00 06 C5 00 00 76 35 * 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) { void _process_SM100Energy(_EMS_RxTelegram * EMS_RxTelegram) {
EMS_Other.SMEnergyLastHour = _toShort(2); // last hour / 10 in Wh EMS_SolarModule.EnergyLastHour = _toShort(2); // last hour / 10 in Wh
EMS_Other.SMEnergyToday = _toShort(6); // todays in Wh EMS_SolarModule.EnergyToday = _toShort(6); // todays in Wh
EMS_Other.SMEnergyTotal = _toShort(10); // total / 10 in kWh EMS_SolarModule.EnergyTotal = _toShort(10); // total / 10 in kWh
EMS_Other.SM = true; // EMS_Other.SM = true;
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
} }
@@ -1455,17 +1476,17 @@ void _process_ISM1StatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
if (EMS_RxTelegram->offset == 0) { if (EMS_RxTelegram->offset == 0) {
// e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0 // e.g. B0 00 FF 00 00 03 32 00 00 00 00 13 00 D6 00 00 00 FB D0 F0
EMS_Other.SMcollectorTemp = _toShort(4); // Collector Temperature EMS_SolarModule.collectorTemp = _toShort(4); // Collector Temperature
EMS_Other.SMbottomTemp = _toShort(6); // Temperature Bottom of Solar Boiler EMS_SolarModule.bottomTemp = _toShort(6); // Temperature Bottom of Solar Boiler
EMS_Other.SMEnergyLastHour = _toShort(2) * 10; // Solar Energy produced in last hour EMS_SolarModule.EnergyLastHour = _toShort(2) * 10; // Solar Energy produced in last hour
EMS_Other.SMpump = _bitRead(8,0); // Solar pump on (1) or off (0) EMS_SolarModule.pump = _bitRead(8,0); // Solar pump on (1) or off (0)
EMS_Other.SM = true; // EMS_Other.SM = true;
} }
if (EMS_RxTelegram->offset == 4) { if (EMS_RxTelegram->offset == 4) {
// e.g. B0 00 FF 04 00 03 02 E5 // e.g. B0 00 FF 04 00 03 02 E5
EMS_Other.SMcollectorTemp = _toShort(0); // Collector Temperature EMS_SolarModule.collectorTemp = _toShort(0); // Collector Temperature
EMS_Other.SM = true; // EMS_Other.SM = true;
} }
} }
@@ -1521,7 +1542,6 @@ void ems_clearDeviceList() {
*/ */
void _addDevice(uint8_t product_id, uint8_t device_id, char * version, const char * model_string) { void _addDevice(uint8_t product_id, uint8_t device_id, char * version, const char * model_string) {
_Generic_Type device; _Generic_Type device;
// if its a duplicate don't add // if its a duplicate don't add
bool found = false; bool found = false;
for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) { for (std::list<_Generic_Type>::iterator it = Devices.begin(); it != Devices.end(); it++) {
@@ -1529,7 +1549,6 @@ void _addDevice(uint8_t product_id, uint8_t device_id, char * version, const cha
found = true; found = true;
} }
} }
if (!found) { if (!found) {
device.product_id = product_id; device.product_id = product_id;
device.device_id = device_id; device.device_id = device_id;
@@ -1644,6 +1663,37 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
return; return;
} }
// finally look for Solar Modules
i = 0;
while (i < _Solar_Module_Types_max) {
if (SolarModule_Types[i].product_id == product_id) {
typeFound = true; // we have a matching product id. i is the index.
break;
}
i++;
}
if (typeFound) {
myDebug_P(PSTR("Solar Module found: %s (DeviceID:0x%02X ProductID:%d Version:%s)"), SolarModule_Types[i].model_string, SolarModule_Types[i].device_id, product_id, version);
// add to list
_addDevice(product_id, SolarModule_Types[i].device_id, version, SolarModule_Types[i].model_string);
// EMS_Other.SM = true; // we have detected a Solar Module (SM10, SM100, ISM1 ...)
myDebug_P(PSTR("Solar Module support enabled."));
EMS_SolarModule.model_id = Other_Types[i].model_id;
EMS_SolarModule.device_id = Other_Types[i].device_id;
EMS_SolarModule.product_id = product_id;
strlcpy(EMS_SolarModule.version, version, sizeof(EMS_SolarModule.version));
// fetch Solar Module values
ems_getSolarModuleValues();
return;
}
// finally look for the other EMS devices // finally look for the other EMS devices
i = 0; i = 0;
while (i < _Other_Types_max) { while (i < _Other_Types_max) {
@@ -1660,20 +1710,18 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
// add to list // add to list
_addDevice(product_id, Other_Types[i].device_id, version, Other_Types[i].model_string); _addDevice(product_id, Other_Types[i].device_id, version, Other_Types[i].model_string);
// see if this is a Solar Module SM10
if (Other_Types[i].device_id == EMS_ID_SM) {
EMS_Other.SM = true; // we have detected a SM10
myDebug_P(PSTR("SM10 Solar Module support enabled."));
}
// see if this is a HeatPump // see if this is a HeatPump
if (Other_Types[i].device_id == EMS_ID_HP) { if (Other_Types[i].device_id == EMS_ID_HP) {
EMS_Other.HP = true; // we have detected a HP EMS_Other.HP = true; // we have detected a HP
myDebug_P(PSTR("HeatPump support enabled.")); myDebug_P(PSTR("HeatPump support enabled."));
EMS_Other.model_id = Other_Types[i].model_id;
EMS_Other.device_id = Other_Types[i].device_id;
EMS_Other.product_id = product_id;
strlcpy(EMS_Other.version, version, sizeof(EMS_Other.version));
// fetch Solar Module values > not yet implemented
} }
// fetch other values
ems_getOtherValues();
return; return;
} else { } else {
@@ -1822,10 +1870,19 @@ void ems_getBoilerValues() {
/* /*
* Get other values from EMS devices * Get other values from EMS devices
*/ */
void ems_getOtherValues() { void ems_getSolarModuleValues() {
if (EMS_Other.SM) {
uint8_t product_id = EMS_SolarModule.product_id;
if (ems_getSolarModuleEnabled()) {
if (product_id == EMS_PRODUCTID_SM10) {
ems_doReadCommand(EMS_TYPE_SM10Monitor, EMS_ID_SM); // fetch all from SM10Monitor ems_doReadCommand(EMS_TYPE_SM10Monitor, EMS_ID_SM); // fetch all from SM10Monitor
} }
else if (product_id == EMS_PRODUCTID_SM100) {
ems_doReadCommand(EMS_TYPE_SM100Monitor, EMS_ID_SM); // fetch all from SM100Monitor
}
}
} }
/** /**
@@ -1912,6 +1969,88 @@ char * ems_getBoilerDescription(char * buffer) {
return buffer; return buffer;
} }
/**
* returns current Solar Module type as a string
*/
char * ems_getSolarModuleDescription(char * buffer) {
uint8_t size = 128;
if (!ems_getSolarModuleEnabled()) {
strlcpy(buffer, "<not enabled>", size);
} else {
int i = 0;
bool found = false;
char tmp[6] = {0};
// scan through known ID types
while (i < _Solar_Module_Types_max) {
if (SolarModule_Types[i].product_id == EMS_SolarModule.product_id) {
found = true; // we have a match
break;
}
i++;
}
if (found) {
strlcpy(buffer, SolarModule_Types[i].model_string, size);
} else {
strlcpy(buffer, "DeviceID: 0x", size);
strlcat(buffer, _hextoa(EMS_SolarModule.device_id, tmp), size);
}
strlcat(buffer, " (ProductID:", size);
if (EMS_SolarModule.product_id == EMS_ID_NONE) {
strlcat(buffer, "?", size);
} else {
strlcat(buffer, itoa(EMS_SolarModule.product_id, tmp, 10), size);
}
strlcat(buffer, " Version:", size);
strlcat(buffer, EMS_SolarModule.version, size);
strlcat(buffer, ")", size);
}
return buffer;
}
/**
* returns current Heat Pump type as a string
*/
char * ems_getHeatPumpDescription(char * buffer) {
uint8_t size = 128;
if (!EMS_Other.HP) {
strlcpy(buffer, "<not enabled>", size);
} else {
int i = 0;
bool found = false;
char tmp[6] = {0};
// scan through known ID types
while (i < _Other_Types_max) {
if (Other_Types[i].product_id == EMS_Other.product_id) {
found = true; // we have a match
break;
}
i++;
}
if (found) {
strlcpy(buffer, Other_Types[i].model_string, size);
} else {
strlcpy(buffer, "DeviceID: 0x", size);
strlcat(buffer, _hextoa(EMS_Other.device_id, tmp), size);
}
strlcat(buffer, " (ProductID:", size);
if (EMS_Other.product_id == EMS_ID_NONE) {
strlcat(buffer, "?", size);
} else {
strlcat(buffer, itoa(EMS_Other.product_id, tmp, 10), size);
}
strlcat(buffer, " Version:", size);
strlcat(buffer, EMS_Other.version, size);
strlcat(buffer, ")", size);
}
return buffer;
}
/** /**
* Find the versions of our connected devices * Find the versions of our connected devices
*/ */
@@ -1928,6 +2067,11 @@ void ems_scanDevices() {
Device_Ids.push_back(tt.device_id); Device_Ids.push_back(tt.device_id);
} }
// copy over solar modules
for (_SolarModule_Type sm : SolarModule_Types) {
Device_Ids.push_back(sm.device_id);
}
// copy over others // copy over others
for (_Other_Type ot : Other_Types) { for (_Other_Type ot : Other_Types) {
Device_Ids.push_back(ot.device_id); Device_Ids.push_back(ot.device_id);
@@ -1963,6 +2107,16 @@ void ems_printAllDevices() {
Boiler_Types[i].product_id); Boiler_Types[i].product_id);
} }
myDebug_P(PSTR("\nThese %d devices are supported as solar module devices:"), _Solar_Module_Types_max);
for (i = 0; i < _Solar_Module_Types_max; i++) {
myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"),
COLOR_BOLD_ON,
SolarModule_Types[i].model_string,
COLOR_BOLD_OFF,
SolarModule_Types[i].device_id,
SolarModule_Types[i].product_id);
}
myDebug_P(PSTR("\nThese %d devices are supported as other known EMS devices:"), _Other_Types_max); myDebug_P(PSTR("\nThese %d devices are supported as other known EMS devices:"), _Other_Types_max);
for (i = 0; i < _Other_Types_max; i++) { for (i = 0; i < _Other_Types_max; i++) {
myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"), myDebug_P(PSTR(" %s%s%s (DeviceID:0x%02X ProductID:%d)"),

View File

@@ -17,12 +17,17 @@
// Fixed EMS IDs // Fixed EMS IDs
#define EMS_ID_ME 0x0B // our device, hardcoded as the "Service Key" #define EMS_ID_ME 0x0B // our device, hardcoded as the "Service Key"
#define EMS_ID_BOILER 0x08 // all UBA Boilers have 0x08 #define EMS_ID_BOILER 0x08 // all UBA Boilers have 0x08
#define EMS_ID_SM 0x30 // Solar Module SM10 and SM100 #define EMS_ID_SM 0x30 // Solar Module SM10, SM100 and ISM1
#define EMS_ID_HP 0x38 // HeatPump #define EMS_ID_HP 0x38 // HeatPump
#define EMS_ID_GATEWAY 0x48 // KM200 Web Gateway #define EMS_ID_GATEWAY 0x48 // KM200 Web Gateway
#define EMS_PRODUCTID_HEATRONICS 95 // ProductID for a Junkers Heatronic3 device #define EMS_PRODUCTID_HEATRONICS 95 // ProductID for a Junkers Heatronic3 device
#define EMS_PRODUCTID_SM10 73 // ProductID for SM10 solar module
#define EMS_PRODUCTID_SM100 163 // ProductID for SM10 solar module
#define EMS_PRODUCTID_ISM1 101 // ProductID for SM10 solar module
#define EMS_MIN_TELEGRAM_LENGTH 6 // minimal length for a validation telegram, including CRC #define EMS_MIN_TELEGRAM_LENGTH 6 // minimal length for a validation telegram, including CRC
// max length of a telegram, including CRC, for Rx and Tx. // max length of a telegram, including CRC, for Rx and Tx.
@@ -154,6 +159,13 @@ typedef struct {
char model_string[50]; char model_string[50];
} _Boiler_Type; } _Boiler_Type;
typedef struct {
uint8_t model_id;
uint8_t product_id;
uint8_t device_id;
char model_string[50];
} _SolarModule_Type;
typedef struct { typedef struct {
uint8_t model_id; uint8_t model_id;
uint8_t product_id; uint8_t product_id;
@@ -241,21 +253,32 @@ typedef struct { // UBAParameterWW
* Telegram package defintions for Other EMS devices * Telegram package defintions for Other EMS devices
*/ */
// SM Solar Module - SM10Monitor/SM100Monitor // Other ems devices than solar modules, thermostats and boilers
typedef struct { typedef struct {
bool SM; // set true if there is a Solar Module available
bool HP; // set true if there is a Heat Pump 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
uint8_t SMpump; // pump active
int16_t SMEnergyLastHour;
int16_t SMEnergyToday;
int16_t SMEnergyTotal;
uint8_t HPModulation; // heatpump modulation in % uint8_t HPModulation; // heatpump modulation in %
uint8_t HPSpeed; // speed 0-100 % uint8_t HPSpeed; // speed 0-100 %
uint8_t device_id; // the device ID of the Solar Module / Heat Pump (e.g. 0x30)
uint8_t model_id; // Solar Module / Heat Pump model (e.g. 3 > EMS_MODEL_OTHER )
uint8_t product_id; // (e.g. 101)
char version[10];
} _EMS_Other; } _EMS_Other;
// SM Solar Module - SM10/SM100/ISM1
typedef struct {
int16_t collectorTemp; // collector temp
int16_t bottomTemp; // bottom temp
uint8_t pumpModulation; // modulation solar pump
uint8_t pump; // pump active
int16_t EnergyLastHour;
int16_t EnergyToday;
int16_t EnergyTotal;
uint8_t device_id; // the device ID of the Solar Module / Heat Pump (e.g. 0x30)
uint8_t model_id; // Solar Module / Heat Pump model (e.g. 3 > EMS_MODEL_OTHER )
uint8_t product_id; // (e.g. 101)
char version[10];
} _EMS_SolarModule;
// Thermostat data // Thermostat data
typedef struct { typedef struct {
uint8_t device_id; // the device ID of the thermostat uint8_t device_id; // the device ID of the thermostat
@@ -322,17 +345,22 @@ void ems_setTxDisabled(bool b);
char * ems_getThermostatDescription(char * buffer); char * ems_getThermostatDescription(char * buffer);
char * ems_getBoilerDescription(char * buffer); char * ems_getBoilerDescription(char * buffer);
char * ems_getSolarModuleDescription(char * buffer);
char * ems_getHeatPumpDescription(char * buffer);
void ems_getThermostatValues(); void ems_getThermostatValues();
void ems_getBoilerValues(); void ems_getBoilerValues();
void ems_getOtherValues(); void ems_getSolarModuleValues();
bool ems_getPoll(); bool ems_getPoll();
bool ems_getTxEnabled(); bool ems_getTxEnabled();
bool ems_getThermostatEnabled(); bool ems_getThermostatEnabled();
bool ems_getBoilerEnabled(); bool ems_getBoilerEnabled();
bool ems_getSolarModuleEnabled();
bool ems_getBusConnected(); bool ems_getBusConnected();
_EMS_SYS_LOGGING ems_getLogging(); _EMS_SYS_LOGGING ems_getLogging();
bool ems_getEmsRefreshed(); bool ems_getEmsRefreshed();
uint8_t ems_getThermostatModel(); uint8_t ems_getThermostatModel();
uint8_t ems_getSolarModuleModel();
uint8_t ems_getOtherModel();
void ems_discoverModels(); void ems_discoverModels();
bool ems_getTxCapable(); bool ems_getTxCapable();
uint32_t ems_getPollFrequency(); uint32_t ems_getPollFrequency();
@@ -350,4 +378,5 @@ void _removeTxQueue();
extern _EMS_Sys_Status EMS_Sys_Status; extern _EMS_Sys_Status EMS_Sys_Status;
extern _EMS_Boiler EMS_Boiler; extern _EMS_Boiler EMS_Boiler;
extern _EMS_Thermostat EMS_Thermostat; extern _EMS_Thermostat EMS_Thermostat;
extern _EMS_SolarModule EMS_SolarModule;
extern _EMS_Other EMS_Other; extern _EMS_Other EMS_Other;

View File

@@ -124,6 +124,9 @@ typedef enum {
// generic ID for the boiler // generic ID for the boiler
EMS_MODEL_UBA, EMS_MODEL_UBA,
// generic ID for the solar module
EMS_MODEL_SOLAR_MODULE,
// generic ID for all the other weird devices // generic ID for all the other weird devices
EMS_MODEL_OTHER, EMS_MODEL_OTHER,
@@ -147,7 +150,7 @@ typedef enum {
} _EMS_MODEL_ID; } _EMS_MODEL_ID;
// EMS types for known devices. This list will be extended when new devices are recognized. // EMS types for known boilers. This list will be extended when new devices are recognized.
// The device_id is always 0x08 // The device_id is always 0x08
// format is MODEL_ID, PRODUCT ID, DESCRIPTION // format is MODEL_ID, PRODUCT ID, DESCRIPTION
const _Boiler_Type Boiler_Types[] = { const _Boiler_Type Boiler_Types[] = {
@@ -164,7 +167,19 @@ const _Boiler_Type Boiler_Types[] = {
}; };
// Other EMS devices which are not considered boilers or thermostats /*
* Known Solar Module types
*/
const _SolarModule_Type SolarModule_Types[] = {
{EMS_MODEL_OTHER, EMS_PRODUCTID_SM10, EMS_ID_SM, "SM10 Solar Module"},
{EMS_MODEL_OTHER, EMS_PRODUCTID_SM100, EMS_ID_SM, "SM100 Solar Module"},
{EMS_MODEL_OTHER, EMS_PRODUCTID_ISM1, EMS_ID_SM, "Junkers ISM1 Solar Module"}
};
// Other EMS devices which are not considered boilers, thermostats or solar modules
const _Other_Type Other_Types[] = { const _Other_Type Other_Types[] = {
{EMS_MODEL_OTHER, 69, 0x21, "MM10 Mixer Module"}, {EMS_MODEL_OTHER, 69, 0x21, "MM10 Mixer Module"},
@@ -178,11 +193,8 @@ const _Other_Type Other_Types[] = {
{EMS_MODEL_OTHER, 125, 0x09, "BC25 Base Controller"}, {EMS_MODEL_OTHER, 125, 0x09, "BC25 Base Controller"},
{EMS_MODEL_OTHER, 152, 0x09, "Junkers Controller"}, {EMS_MODEL_OTHER, 152, 0x09, "Junkers Controller"},
{EMS_MODEL_OTHER, 205, 0x02, "Nefit Moduline Easy Connect"}, {EMS_MODEL_OTHER, 205, 0x02, "Nefit Moduline Easy Connect"},
{EMS_MODEL_OTHER, 73, EMS_ID_SM, "SM10 Solar Module"},
{EMS_MODEL_OTHER, 163, EMS_ID_SM, "SM100 Solar Module"},
{EMS_MODEL_OTHER, 171, 0x02, "EMS-OT OpenTherm converter"}, {EMS_MODEL_OTHER, 171, 0x02, "EMS-OT OpenTherm converter"},
{EMS_MODEL_OTHER, 252, EMS_ID_HP, "HeatPump Module"}, // warning, fake product id! {EMS_MODEL_OTHER, 252, EMS_ID_HP, "HeatPump Module"}, // warning, fake product id!
{EMS_MODEL_OTHER, 101, 0x30, "Junkers ISM1 Solar Controller"},
{EMS_MODEL_OTHER, 189, EMS_ID_GATEWAY, "Web Gateway KM200"} {EMS_MODEL_OTHER, 189, EMS_ID_GATEWAY, "Web Gateway KM200"}
}; };