multiple thermostat choice - #238

This commit is contained in:
Paul
2019-12-30 14:48:06 +01:00
parent b64c35732e
commit 4fbd135bfe
3 changed files with 117 additions and 48 deletions

View File

@@ -69,15 +69,16 @@ typedef struct {
uint8_t dallas_sensors; // count of dallas sensors uint8_t dallas_sensors; // count of dallas sensors
// custom params // custom params
bool shower_timer; // true if we want to report back on shower times bool shower_timer; // true if we want to report back on shower times
bool shower_alert; // true if we want the alert of cold water bool shower_alert; // true if we want the alert of cold water
bool led; // LED on/off bool led; // LED on/off
bool listen_mode; // stop automatic Tx on/off bool listen_mode; // stop automatic Tx on/off
uint16_t publish_time; // frequency of MQTT publish in seconds uint16_t publish_time; // frequency of MQTT publish in seconds
uint8_t led_gpio; // pin for LED uint8_t led_gpio; // pin for LED
uint8_t dallas_gpio; // pin for attaching external dallas temperature sensors uint8_t dallas_gpio; // pin for attaching external dallas temperature sensors
bool dallas_parasite; // on/off is using parasite bool dallas_parasite; // on/off is using parasite
uint8_t tx_mode; // TX mode 1,2 or 3 uint8_t tx_mode; // TX mode 1,2 or 3
uint8_t master_thermostat; // Product ID of master thermostat to use
} _EMSESP_Settings; } _EMSESP_Settings;
typedef struct { typedef struct {
@@ -99,6 +100,7 @@ static const command_t project_cmds[] PROGMEM = {
{true, "shower_alert <on | off>", "stop hot water to send 3 cold burst warnings after max shower time is exceeded"}, {true, "shower_alert <on | off>", "stop hot water to send 3 cold burst warnings after max shower time is exceeded"},
{true, "publish_time <seconds>", "set frequency for publishing data to MQTT (0=automatic)"}, {true, "publish_time <seconds>", "set frequency for publishing data to MQTT (0=automatic)"},
{true, "tx_mode <n>", "changes Tx logic. 1=EMS generic, 2=EMS+, 3=HT3"}, {true, "tx_mode <n>", "changes Tx logic. 1=EMS generic, 2=EMS+, 3=HT3"},
{true, "master_thermostat [product id]", "product id to use as the master thermostat. Use no args for list."},
{false, "info", "show current values deciphered from the EMS messages"}, {false, "info", "show current values deciphered from the EMS messages"},
{false, "log <n | b | t | s | r | j | v | w [type ID]", "set logging to none, basic, thermostat, solar module, raw, jabber, verbose or watch a specific type"}, {false, "log <n | b | t | s | r | j | v | w [type ID]", "set logging to none, basic, thermostat, solar module, raw, jabber, verbose or watch a specific type"},
@@ -252,7 +254,7 @@ void showInfo() {
myDebug_P(PSTR("\n%sEMS Bus stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF); myDebug_P(PSTR("\n%sEMS Bus stats:%s"), COLOR_BOLD_ON, COLOR_BOLD_OFF);
if (ems_getBusConnected()) { if (ems_getBusConnected()) {
myDebug_P(PSTR(" Bus is connected, protocol: %s"), ((EMS_Sys_Status.emsIDMask == 0x80) ? "HT3" : "Buderus")); myDebug_P(PSTR(" Bus is connected, protocol: %s"), (ems_isHT3() ? "HT3" : "Buderus"));
myDebug_P(PSTR(" Rx: # successful read requests=%d, # CRC errors=%d"), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr); myDebug_P(PSTR(" Rx: # successful read requests=%d, # CRC errors=%d"), EMS_Sys_Status.emsRxPgks, EMS_Sys_Status.emxCrcErr);
if (ems_getTxCapable()) { if (ems_getTxCapable()) {
@@ -360,7 +362,7 @@ void showInfo() {
EMS_Boiler.UBAuptime % 60); EMS_Boiler.UBAuptime % 60);
} }
// For SM10/SM100 Solar Module // For SM10/SM100/SM200 Solar Module
if (ems_getSolarModuleEnabled()) { if (ems_getSolarModuleEnabled()) {
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);
@@ -764,7 +766,7 @@ void publishEMSValues(bool force) {
ems_Device_remove_flags(EMS_DEVICE_UPDATE_FLAG_MIXING); // unset flag ems_Device_remove_flags(EMS_DEVICE_UPDATE_FLAG_MIXING); // unset flag
} }
// For SM10 and SM100 Solar Modules // For SM10 and SM100/SM200 Solar Modules
if (ems_getSolarModuleEnabled() && (ems_Device_has_flags(EMS_DEVICE_UPDATE_FLAG_SOLAR) || force)) { if (ems_getSolarModuleEnabled() && (ems_Device_has_flags(EMS_DEVICE_UPDATE_FLAG_SOLAR) || force)) {
// build new json object // build new json object
doc.clear(); doc.clear();
@@ -855,7 +857,6 @@ void do_publishValues() {
myDebugLog("Starting scheduled MQTT publish..."); myDebugLog("Starting scheduled MQTT publish...");
publishEMSValues(false); publishEMSValues(false);
publishSensorValues(); publishSensorValues();
do_publishShowerData();
} }
// callback to light up the LED, called via Ticker every second // callback to light up the LED, called via Ticker every second
@@ -946,19 +947,23 @@ bool LoadSaveCallback(MYESP_FSACTION_t action, JsonObject settings) {
EMSESP_Settings.tx_mode = settings["tx_mode"] | EMS_TXMODE_DEFAULT; // default to 1 (generic) EMSESP_Settings.tx_mode = settings["tx_mode"] | EMS_TXMODE_DEFAULT; // default to 1 (generic)
ems_setTxMode(EMSESP_Settings.tx_mode); ems_setTxMode(EMSESP_Settings.tx_mode);
EMSESP_Settings.master_thermostat = settings["master_thermostat"] | 0; // default to 0 (none)
ems_setMasterThermostat(EMSESP_Settings.master_thermostat);
return true; return true;
} }
if (action == MYESP_FSACTION_SAVE) { if (action == MYESP_FSACTION_SAVE) {
settings["led"] = EMSESP_Settings.led; settings["led"] = EMSESP_Settings.led;
settings["led_gpio"] = EMSESP_Settings.led_gpio; settings["led_gpio"] = EMSESP_Settings.led_gpio;
settings["dallas_gpio"] = EMSESP_Settings.dallas_gpio; settings["dallas_gpio"] = EMSESP_Settings.dallas_gpio;
settings["dallas_parasite"] = EMSESP_Settings.dallas_parasite; settings["dallas_parasite"] = EMSESP_Settings.dallas_parasite;
settings["listen_mode"] = EMSESP_Settings.listen_mode; settings["listen_mode"] = EMSESP_Settings.listen_mode;
settings["shower_timer"] = EMSESP_Settings.shower_timer; settings["shower_timer"] = EMSESP_Settings.shower_timer;
settings["shower_alert"] = EMSESP_Settings.shower_alert; settings["shower_alert"] = EMSESP_Settings.shower_alert;
settings["publish_time"] = EMSESP_Settings.publish_time; settings["publish_time"] = EMSESP_Settings.publish_time;
settings["tx_mode"] = EMSESP_Settings.tx_mode; settings["tx_mode"] = EMSESP_Settings.tx_mode;
settings["master_thermostat"] = EMSESP_Settings.master_thermostat;
return true; return true;
} }
@@ -1076,6 +1081,27 @@ bool SetListCallback(MYESP_FSACTION_t action, uint8_t wc, const char * setting,
myDebug_P(PSTR("Error. Usage: set tx_mode <1 | 2 | 3>")); myDebug_P(PSTR("Error. Usage: set tx_mode <1 | 2 | 3>"));
} }
} }
// master_thermostat
if (strcmp(setting, "master_thermostat") == 0) {
if (wc == 1) {
// show list
char device_string[100];
myDebug_P(PSTR("Available thermostat Product ids:"));
for (std::list<_Detected_Device>::iterator it = Devices.begin(); it != Devices.end(); ++it) {
if (it->device_type == EMS_DEVICE_TYPE_THERMOSTAT) {
strlcpy(device_string, (it)->device_desc_p, sizeof(device_string));
myDebug_P(PSTR(" %d = %s"), (it)->product_id, device_string);
}
}
myDebug_P(PSTR("Usage: set master_thermostat <product id>"));
} else if (wc == 2) {
uint8_t pid = atoi(value);
EMSESP_Settings.master_thermostat = pid;
ems_setMasterThermostat(pid);
ok = true;
}
}
} }
if (action == MYESP_FSACTION_LIST) { if (action == MYESP_FSACTION_LIST) {
@@ -1087,11 +1113,18 @@ bool SetListCallback(MYESP_FSACTION_t action, uint8_t wc, const char * setting,
myDebug_P(PSTR(" listen_mode=%s"), EMSESP_Settings.listen_mode ? "on" : "off"); myDebug_P(PSTR(" listen_mode=%s"), EMSESP_Settings.listen_mode ? "on" : "off");
myDebug_P(PSTR(" shower_timer=%s"), EMSESP_Settings.shower_timer ? "on" : "off"); myDebug_P(PSTR(" shower_timer=%s"), EMSESP_Settings.shower_timer ? "on" : "off");
myDebug_P(PSTR(" shower_alert=%s"), EMSESP_Settings.shower_alert ? "on" : "off"); myDebug_P(PSTR(" shower_alert=%s"), EMSESP_Settings.shower_alert ? "on" : "off");
if (EMSESP_Settings.publish_time) { if (EMSESP_Settings.publish_time) {
myDebug_P(PSTR(" publish_time=%d"), EMSESP_Settings.publish_time); myDebug_P(PSTR(" publish_time=%d"), EMSESP_Settings.publish_time);
} else { } else {
myDebug_P(PSTR(" publish_time=0 (always publish on data received)"), EMSESP_Settings.publish_time); myDebug_P(PSTR(" publish_time=0 (always publish on data received)"), EMSESP_Settings.publish_time);
} }
if (EMSESP_Settings.master_thermostat) {
myDebug_P(PSTR(" master_thermostat=%d"), EMSESP_Settings.master_thermostat);
} else {
myDebug_P(PSTR(" master_thermostat=0 (use first one detected)"), EMSESP_Settings.master_thermostat);
}
} }
return ok; return ok;
@@ -1360,7 +1393,7 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) {
// this is used for example for comfort, flowtemp // this is used for example for comfort, flowtemp
myESP.mqttSubscribe(TOPIC_BOILER_CMD); myESP.mqttSubscribe(TOPIC_BOILER_CMD);
// these three need to be unqiue topics // these three need to be unique topics
myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWACTIVATED); myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWACTIVATED);
myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWONETIME); myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWONETIME);
myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWTEMP); myESP.mqttSubscribe(TOPIC_BOILER_CMD_WWTEMP);
@@ -1396,6 +1429,8 @@ void MQTTCallback(unsigned int type, const char * topic, const char * message) {
const char * command = doc["cmd"]; const char * command = doc["cmd"];
// Check whatever the command is and act accordingly // Check whatever the command is and act accordingly
// we only have one now, this is for the shower coldshot
if (strcmp(command, TOPIC_SHOWER_COLDSHOT) == 0) { if (strcmp(command, TOPIC_SHOWER_COLDSHOT) == 0) {
_showerColdShotStart(); _showerColdShotStart();
return; return;
@@ -1708,7 +1743,7 @@ void WebCallback(JsonObject root) {
boiler["ok"] = false; boiler["ok"] = false;
} }
// For SM10/SM100 Solar Module // For SM10/SM100/SM200 Solar Module
JsonObject sm = root.createNestedObject("sm"); JsonObject sm = root.createNestedObject("sm");
if (ems_getSolarModuleEnabled()) { if (ems_getSolarModuleEnabled()) {
sm["ok"] = true; sm["ok"] = true;
@@ -1766,15 +1801,16 @@ void WebCallback(JsonObject root) {
// Most of these will be overwritten after the SPIFFS config file is loaded // Most of these will be overwritten after the SPIFFS config file is loaded
void initEMSESP() { void initEMSESP() {
// general settings // general settings
EMSESP_Settings.shower_timer = false; EMSESP_Settings.shower_timer = false;
EMSESP_Settings.shower_alert = false; EMSESP_Settings.shower_alert = false;
EMSESP_Settings.led = true; // LED is on by default EMSESP_Settings.led = true; // LED is on by default
EMSESP_Settings.listen_mode = false; EMSESP_Settings.listen_mode = false;
EMSESP_Settings.publish_time = DEFAULT_PUBLISHTIME; EMSESP_Settings.publish_time = DEFAULT_PUBLISHTIME;
EMSESP_Settings.dallas_sensors = 0; EMSESP_Settings.dallas_sensors = 0;
EMSESP_Settings.led_gpio = EMSESP_LED_GPIO; EMSESP_Settings.led_gpio = EMSESP_LED_GPIO;
EMSESP_Settings.dallas_gpio = EMSESP_DALLAS_GPIO; EMSESP_Settings.dallas_gpio = EMSESP_DALLAS_GPIO;
EMSESP_Settings.tx_mode = EMS_TXMODE_DEFAULT; // default tx mode EMSESP_Settings.tx_mode = EMS_TXMODE_DEFAULT; // default tx mode
EMSESP_Settings.master_thermostat = 0;
// shower settings // shower settings
EMSESP_Shower.timerStart = 0; EMSESP_Shower.timerStart = 0;

View File

@@ -71,6 +71,11 @@ void ems_Device_remove_flags(unsigned int flags) {
EMS_Sys_Status.emsRefreshedFlags &= ~flags; EMS_Sys_Status.emsRefreshedFlags &= ~flags;
} }
// returns true if HT3, other Buderus protocol
bool ems_isHT3() {
return (EMS_Sys_Status.emsIDMask == 0x80);
}
// init stats and counters and buffers // init stats and counters and buffers
void ems_init() { void ems_init() {
ems_clearDeviceList(); // init the device map ems_clearDeviceList(); // init the device map
@@ -171,9 +176,9 @@ void ems_init() {
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 // Solar Module values
EMS_SolarModule.collectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100 EMS_SolarModule.collectorTemp = EMS_VALUE_SHORT_NOTSET; // collector temp from SM10/SM100/SM200
EMS_SolarModule.bottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100 EMS_SolarModule.bottomTemp = EMS_VALUE_SHORT_NOTSET; // bottom temp from SM10/SM100/SM200
EMS_SolarModule.pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100 EMS_SolarModule.pumpModulation = EMS_VALUE_INT_NOTSET; // modulation solar pump SM10/SM100/SM200
EMS_SolarModule.pump = EMS_VALUE_BOOL_NOTSET; // pump active EMS_SolarModule.pump = EMS_VALUE_BOOL_NOTSET; // pump active
EMS_SolarModule.EnergyLastHour = EMS_VALUE_USHORT_NOTSET; EMS_SolarModule.EnergyLastHour = EMS_VALUE_USHORT_NOTSET;
EMS_SolarModule.EnergyToday = EMS_VALUE_USHORT_NOTSET; EMS_SolarModule.EnergyToday = EMS_VALUE_USHORT_NOTSET;
@@ -410,6 +415,10 @@ void ems_setTxMode(uint8_t mode) {
EMS_Sys_Status.emsTxMode = mode; EMS_Sys_Status.emsTxMode = mode;
} }
void ems_setMasterThermostat(uint8_t product_id) {
EMS_Sys_Status.emsMasterThermostat = product_id;
}
/** /**
* debug print a telegram to telnet/serial including the CRC * debug print a telegram to telnet/serial including the CRC
*/ */
@@ -1241,7 +1250,7 @@ void _process_RCPLUSStatusMessage(_EMS_RxTelegram * EMS_RxTelegram) {
// the whole telegram // the whole telegram
// e.g. Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00 // e.g. Thermostat -> all, telegram: 10 00 FF 00 01 A5 00 D7 21 00 00 00 00 30 01 84 01 01 03 01 84 01 F1 00 00 11 01 00 08 63 00
// 10 00 FF 00 01 A5 80 00 01 30 28 00 30 28 01 54 03 03 01 01 54 02 A8 00 00 11 01 03 FF FF 00 // 10 00 FF 00 01 A5 80 00 01 30 28 00 30 28 01 54 03 03 01 01 54 02 A8 00 00 11 01 03 FF FF 00
// or prtial, e.g. for modes: // or partial, e.g. for modes:
// manual : 10 00 FF 0A 01 A5 02 // manual : 10 00 FF 0A 01 A5 02
// auto : 10 00 FF 0A 01 A5 03 // auto : 10 00 FF 0A 01 A5 03
_setValue(EMS_RxTelegram, &EMS_Thermostat.hc[hc].curr_roomTemp, EMS_OFFSET_RCPLUSStatusMessage_curr); // value is * 10 _setValue(EMS_RxTelegram, &EMS_Thermostat.hc[hc].curr_roomTemp, EMS_OFFSET_RCPLUSStatusMessage_curr); // value is * 10
@@ -1665,6 +1674,17 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
strlcat(version, ".", sizeof(version)); strlcat(version, ".", sizeof(version));
strlcat(version, _smallitoa(EMS_RxTelegram->data[offset + 2], buf), sizeof(version)); strlcat(version, _smallitoa(EMS_RxTelegram->data[offset + 2], buf), sizeof(version));
// some devices store the protocol type (HT3, Buderus) in tbe last byte
// we don't do anything with this yet.
if (EMS_RxTelegram->data_length >= 10) {
uint8_t protocol_type = EMS_RxTelegram->data[9];
if (protocol_type == 2) {
// it's a junkers
} else if (protocol_type >= 3) {
// it's buderus
}
}
// scan through known devices matching the productid // scan through known devices matching the productid
uint8_t product_id = EMS_RxTelegram->data[offset]; uint8_t product_id = EMS_RxTelegram->data[offset];
uint8_t i = 0; uint8_t i = 0;
@@ -1677,7 +1697,7 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
i++; i++;
} }
// if not found, just add it // if not found, just add it as an unknown device
if (!typeFound) { if (!typeFound) {
(void)_addDevice(EMS_DEVICE_TYPE_UNKNOWN, product_id, device_id, nullptr, version); (void)_addDevice(EMS_DEVICE_TYPE_UNKNOWN, product_id, device_id, nullptr, version);
return; return;
@@ -1701,13 +1721,17 @@ void _process_Version(_EMS_RxTelegram * EMS_RxTelegram) {
strlcpy(EMS_Boiler.version, version, sizeof(EMS_Boiler.version)); strlcpy(EMS_Boiler.version, version, sizeof(EMS_Boiler.version));
ems_getBoilerValues(); // get Boiler values that we would usually have to wait for ems_getBoilerValues(); // get Boiler values that we would usually have to wait for
} else if (type == EMS_DEVICE_TYPE_THERMOSTAT) { } else if (type == EMS_DEVICE_TYPE_THERMOSTAT) {
EMS_Thermostat.device_id = device_id; // we can only support a single thermostat currently, so check which product_id we may have chosen
EMS_Thermostat.device_flags = (flags & 0x7F); // remove 7th bit // to be the master - see https://github.com/proddy/EMS-ESP/issues/238
EMS_Thermostat.write_supported = (flags & EMS_DEVICE_FLAG_NO_WRITE) == 0; if ((EMS_Sys_Status.emsMasterThermostat == 0) || (EMS_Sys_Status.emsMasterThermostat == product_id)) {
EMS_Thermostat.product_id = product_id; EMS_Thermostat.device_id = device_id;
EMS_Thermostat.device_desc_p = device_desc_p; EMS_Thermostat.device_flags = (flags & 0x7F); // remove 7th bit
strlcpy(EMS_Thermostat.version, version, sizeof(EMS_Thermostat.version)); EMS_Thermostat.write_supported = (flags & EMS_DEVICE_FLAG_NO_WRITE) == 0;
ems_getThermostatValues(); // get Thermostat values EMS_Thermostat.product_id = product_id;
EMS_Thermostat.device_desc_p = device_desc_p;
strlcpy(EMS_Thermostat.version, version, sizeof(EMS_Thermostat.version));
ems_getThermostatValues(); // get Thermostat values
}
} else if (type == EMS_DEVICE_TYPE_SOLAR) { } else if (type == EMS_DEVICE_TYPE_SOLAR) {
EMS_SolarModule.device_id = device_id; EMS_SolarModule.device_id = device_id;
EMS_SolarModule.product_id = product_id; EMS_SolarModule.product_id = product_id;
@@ -2459,8 +2483,14 @@ void ems_setWarmWaterActivated(bool activated) {
EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW; EMS_TxTelegram.type = EMS_TYPE_UBAParameterWW;
EMS_TxTelegram.offset = EMS_OFFSET_UBAParameterWW_wwactivated; EMS_TxTelegram.offset = EMS_OFFSET_UBAParameterWW_wwactivated;
EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH; EMS_TxTelegram.length = EMS_MIN_TELEGRAM_LENGTH;
EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't validate EMS_TxTelegram.type_validate = EMS_ID_NONE; // don't validate
EMS_TxTelegram.dataValue = (activated ? 0xFF : 0x00); // 0xFF is on, 0x00 is off
// https://github.com/proddy/EMS-ESP/issues/268
if (ems_isHT3()) {
EMS_TxTelegram.dataValue = (activated ? 0x08 : 0x00); // 0x08 is on, 0x00 is off
} else {
EMS_TxTelegram.dataValue = (activated ? 0xFF : 0x00); // 0xFF is on, 0x00 is off
}
EMS_TxQueue.push(EMS_TxTelegram); EMS_TxQueue.push(EMS_TxTelegram);
} }

View File

@@ -137,6 +137,7 @@ typedef struct {
uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80 uint8_t emsIDMask; // Buderus: 0x00, Junkers: 0x80
uint8_t emsPollAck[1]; // acknowledge buffer for Poll uint8_t emsPollAck[1]; // acknowledge buffer for Poll
uint8_t emsTxMode; // Tx mode 1, 2 or 3 uint8_t emsTxMode; // Tx mode 1, 2 or 3
uint8_t emsMasterThermostat; // product ID for the default thermostat to use
char emsDeviceMap[EMS_SYS_DEVICEMAP_LENGTH]; // contents of 0x07 telegram with bitmasks for all active EMS devices char emsDeviceMap[EMS_SYS_DEVICEMAP_LENGTH]; // contents of 0x07 telegram with bitmasks for all active EMS devices
} _EMS_Sys_Status; } _EMS_Sys_Status;
@@ -336,7 +337,7 @@ typedef struct {
_EMS_Mixing_HC hc[EMS_THERMOSTAT_MAXHC]; // array for the 4 heating circuits _EMS_Mixing_HC hc[EMS_THERMOSTAT_MAXHC]; // array for the 4 heating circuits
} _EMS_Mixing; } _EMS_Mixing;
// Solar Module - SM10/SM100/ISM1 // Solar Module - SM10/SM100/SM200/ISM1
typedef struct { typedef struct {
uint8_t device_id; // the device ID of the Solar Module uint8_t device_id; // the device ID of the Solar Module
uint8_t device_flags; // Solar Module flags uint8_t device_flags; // Solar Module flags
@@ -421,6 +422,7 @@ void ems_setWarmWaterModeComfort(uint8_t comfort);
void ems_setModels(); void ems_setModels();
void ems_setTxDisabled(bool b); void ems_setTxDisabled(bool b);
void ems_setTxMode(uint8_t mode); void ems_setTxMode(uint8_t mode);
void ems_setMasterThermostat(uint8_t product_id);
char * ems_getDeviceDescription(_EMS_DEVICE_TYPE device_type, char * buffer, bool name_only = false); char * ems_getDeviceDescription(_EMS_DEVICE_TYPE device_type, char * buffer, bool name_only = false);
bool ems_getDeviceTypeDescription(uint8_t device_id, char * buffer); bool ems_getDeviceTypeDescription(uint8_t device_id, char * buffer);
void ems_getThermostatValues(); void ems_getThermostatValues();
@@ -444,6 +446,7 @@ bool ems_getTxDisabled();
void ems_Device_add_flags(unsigned int flags); void ems_Device_add_flags(unsigned int flags);
bool ems_Device_has_flags(unsigned int flags); bool ems_Device_has_flags(unsigned int flags);
void ems_Device_remove_flags(unsigned int flags); void ems_Device_remove_flags(unsigned int flags);
bool ems_isHT3();
// private functions // private functions
uint8_t _crcCalculator(uint8_t * data, uint8_t len); uint8_t _crcCalculator(uint8_t * data, uint8_t len);