version 1.4.1

This commit is contained in:
proddy
2019-01-29 22:48:38 +01:00
parent 817c8a263c
commit f6550b45e4
9 changed files with 287 additions and 139 deletions

View File

@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.4.1] 2019-01-29
### Added
- The led pin, dallas pin and both thermostat and boiler type IDs can be set with the application, and stored.
### Changed
- some minor improvements to autodetect
## [1.4.0] 2019-01-27 ## [1.4.0] 2019-01-27
### Changed ### Changed

View File

@@ -402,10 +402,8 @@ void MyESP::_consoleShowHelp() {
SerialAndTelnet.println(FPSTR("* set")); SerialAndTelnet.println(FPSTR("* set"));
SerialAndTelnet.println(FPSTR("* set <wifi_ssid | wifi_password | mqtt_host | mqtt_username | mqtt_password> [value]")); SerialAndTelnet.println(FPSTR("* set <wifi_ssid | wifi_password | mqtt_host | mqtt_username | mqtt_password> [value]"));
SerialAndTelnet.println(FPSTR("* set erase")); SerialAndTelnet.println(FPSTR("* set erase"));
SerialAndTelnet.println(FPSTR("* set led <on | off>"));
SerialAndTelnet.println(FPSTR("*"));
// print custom commands if available. Take from progmem // print custom commands if available. Taken from progmem
if (_telnetcommand_callback) { if (_telnetcommand_callback) {
// find the longest key length so we can right align it // find the longest key length so we can right align it
uint8_t max_len = 0; uint8_t max_len = 0;
@@ -513,8 +511,8 @@ void MyESP::_changeSetting(uint8_t wc, const char * setting, const char * value)
SerialAndTelnet.printf("%s changed to %s\n\r", setting, value); SerialAndTelnet.printf("%s changed to %s\n\r", setting, value);
} }
if (_fs_saveConfig()) { if (fs_saveConfig()) {
SerialAndTelnet.println("Note, some changes will only have effect after a device reboot (use ! command)"); SerialAndTelnet.println("Note, some changes will only have effect after the ESP is restarted (use ! command)");
} }
} }
@@ -811,7 +809,7 @@ bool MyESP::_fs_loadConfig() {
// use configFile.readString // use configFile.readString
configFile.readBytes(buf.get(), size); configFile.readBytes(buf.get(), size);
StaticJsonBuffer<500> jsonBuffer; // https://arduinojson.org/v5/assistant/ StaticJsonBuffer<SPIFFS_MAXSIZE> jsonBuffer;
JsonObject & json = jsonBuffer.parseObject(buf.get()); JsonObject & json = jsonBuffer.parseObject(buf.get());
const char * value; const char * value;
@@ -831,17 +829,18 @@ bool MyESP::_fs_loadConfig() {
value = json["mqtt_password"]; value = json["mqtt_password"];
_mqtt_password = (value) ? strdup(value) : NULL; _mqtt_password = (value) ? strdup(value) : NULL;
// callback for custom settings // callback for loading custom settings
(_fs_callback)(MYESP_FSACTION_LOAD, json); // ok is false if there's a problem loading a custom setting (e.g. does not exist)
bool ok = (_fs_callback)(MYESP_FSACTION_LOAD, json);
configFile.close(); configFile.close();
return true; return ok;
} }
// save settings to spiffs // save settings to spiffs
bool MyESP::_fs_saveConfig() { bool MyESP::fs_saveConfig() {
StaticJsonBuffer<500> jsonBuffer; // https://arduinojson.org/v5/assistant/ StaticJsonBuffer<SPIFFS_MAXSIZE> jsonBuffer;
JsonObject & json = jsonBuffer.createObject(); JsonObject & json = jsonBuffer.createObject();
json["wifi_ssid"] = _wifi_ssid; json["wifi_ssid"] = _wifi_ssid;
@@ -850,8 +849,8 @@ bool MyESP::_fs_saveConfig() {
json["mqtt_username"] = _mqtt_username; json["mqtt_username"] = _mqtt_username;
json["mqtt_password"] = _mqtt_password; json["mqtt_password"] = _mqtt_password;
// callback for custom settings // callback for saving custom settings
(_fs_callback)(MYESP_FSACTION_SAVE, json); (void)(_fs_callback)(MYESP_FSACTION_SAVE, json);
File configFile = SPIFFS.open("/config.json", "w"); File configFile = SPIFFS.open("/config.json", "w");
if (!configFile) { if (!configFile) {
@@ -874,9 +873,10 @@ void MyESP::_fs_setup() {
//_fs_printConfig(); // for debugging //_fs_printConfig(); // for debugging
// load the config file. if it doesn't exist create it with anything that was specified // load the config file. if it doesn't exist create it
if (!_fs_loadConfig()) { if (!_fs_loadConfig()) {
_fs_saveConfig(); myDebug_P(PSTR("[FS] Re-creating config file"));
fs_saveConfig();
} }
} }
@@ -939,4 +939,4 @@ void MyESP::loop() {
yield(); // ...and breath yield(); // ...and breath
} }
MyESP myESP; MyESP myESP; // create instance

View File

@@ -61,8 +61,11 @@
#define COLOR_CYAN "\x1B[0;36m" #define COLOR_CYAN "\x1B[0;36m"
#define COLOR_WHITE "\x1B[0;37m" #define COLOR_WHITE "\x1B[0;37m"
// SPIFFS
#define SPIFFS_MAXSIZE 500 // https://arduinojson.org/v5/assistant/
typedef struct { typedef struct {
char key[30]; char key[40];
char description[100]; char description[100];
} command_t; } command_t;
@@ -72,7 +75,7 @@ typedef std::function<void(unsigned int, const char *, const char *)>
typedef std::function<void()> wifi_callback_f; typedef std::function<void()> wifi_callback_f;
typedef std::function<void(uint8_t, const char *)> telnetcommand_callback_f; typedef std::function<void(uint8_t, const char *)> telnetcommand_callback_f;
typedef std::function<void(uint8_t)> telnet_callback_f; typedef std::function<void(uint8_t)> telnet_callback_f;
typedef std::function<void(MYESP_FSACTION, JsonObject & json)> fs_callback_f; typedef std::function<bool(MYESP_FSACTION, JsonObject & json)> fs_callback_f;
typedef std::function<bool(MYESP_FSACTION, uint8_t, const char *, const char *)> fs_settings_callback_f; typedef std::function<bool(MYESP_FSACTION, uint8_t, const char *, const char *)> fs_settings_callback_f;
// calculates size of an 2d array at compile time // calculates size of an 2d array at compile time
@@ -113,6 +116,7 @@ class MyESP {
// FS // FS
void setSettings(fs_callback_f callback, fs_settings_callback_f fs_settings_callback); void setSettings(fs_callback_f callback, fs_settings_callback_f fs_settings_callback);
bool fs_saveConfig();
// general // general
void end(); void end();
@@ -178,7 +182,6 @@ class MyESP {
// fs // fs
void _fs_setup(); void _fs_setup();
bool _fs_saveConfig();
bool _fs_loadConfig(); bool _fs_loadConfig();
void _fs_printConfig(); void _fs_printConfig();
void _fs_eraseConfig(); void _fs_eraseConfig();

View File

@@ -32,7 +32,7 @@ DS18 ds18;
#define myDebug_P(...) myESP.myDebug_P(__VA_ARGS__) #define myDebug_P(...) myESP.myDebug_P(__VA_ARGS__)
// timers, all values are in seconds // timers, all values are in seconds
#define PUBLISHVALUES_TIME 120 // every 2 minutes post MQTT values #define PUBLISHVALUES_TIME 120 // every 2 minutes publish MQTT values
Ticker publishValuesTimer; Ticker publishValuesTimer;
#define SYSTEMCHECK_TIME 20 // every 20 seconds check if Boiler is online #define SYSTEMCHECK_TIME 20 // every 20 seconds check if Boiler is online
@@ -41,7 +41,7 @@ Ticker systemCheckTimer;
#define REGULARUPDATES_TIME 60 // every minute a call is made to fetch data from EMS devices manually #define REGULARUPDATES_TIME 60 // every minute a call is made to fetch data from EMS devices manually
Ticker regularUpdatesTimer; Ticker regularUpdatesTimer;
#define LEDCHECK_TIME 1 // every second blink heartbeat LED #define LEDCHECK_TIME 1 // every second blink the heartbeat LED
Ticker ledcheckTimer; Ticker ledcheckTimer;
// thermostat scan - for debugging // thermostat scan - for debugging
@@ -51,26 +51,6 @@ uint8_t scanThermostat_count = 0;
Ticker showerColdShotStopTimer; Ticker showerColdShotStopTimer;
// thermostat
#define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values
#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // for received thermostat temp changes
#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // for received thermostat mode changes
#define THERMOSTAT_CURRTEMP "thermostat_currtemp" // current temperature
#define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature
#define THERMOSTAT_MODE "thermostat_mode" // mode
// boiler
#define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values
#define TOPIC_BOILER_TAPWATER_ACTIVE "tapwater_active" // if hot tap water is running
#define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on
// shower time
#define TOPIC_SHOWERTIME "showertime" // for sending shower time results
#define TOPIC_SHOWER_TIMER "shower_timer" // toggle switch for enabling the shower logic
#define TOPIC_SHOWER_ALERT "shower_alert" // toggle switch for enabling the shower alarm logic
#define TOPIC_SHOWER_COLDSHOT "shower_coldshot" // used to trigger a coldshot from an MQTT command
#define SHOWER_ALARM "shower_alarm" // for notifying that shower time has reached its limit
// if using the shower timer, change these settings // if using the shower timer, change these settings
#define SHOWER_PAUSE_TIME 15000 // in ms. 15 seconds, max time if water is switched off & on during a shower #define SHOWER_PAUSE_TIME 15000 // in ms. 15 seconds, max time if water is switched off & on during a shower
#define SHOWER_MIN_DURATION 120000 // in ms. 2 minutes, before recognizing its a shower #define SHOWER_MIN_DURATION 120000 // in ms. 2 minutes, before recognizing its a shower
@@ -83,6 +63,8 @@ typedef struct {
bool led_enabled; // LED on/off bool led_enabled; // LED on/off
unsigned long timestamp; // for internal timings, via millis() unsigned long timestamp; // for internal timings, via millis()
uint8_t dallas_sensors; // count of dallas sensors uint8_t dallas_sensors; // count of dallas sensors
uint8_t led_gpio;
uint8_t dallas_gpio;
} _EMSESP_Status; } _EMSESP_Status;
typedef struct { typedef struct {
@@ -95,10 +77,16 @@ typedef struct {
command_t PROGMEM project_cmds[] = { command_t PROGMEM project_cmds[] = {
{"set led <on | off>", "toggle status LED on/off"},
{"set led_gpio <pin>", "set the LED pin (onboard=2)"},
{"set dallas_gpio <pin>", "set the pin for the external Dallas temperature sensor (D5=14)"},
{"set thermostat_type <hex type ID>", "set the thermostat type id (e.g. 10 for 0x10)"},
{"set boiler_type <hex type ID>", "set the boiler type id (e.g. 8 for 0x08)"},
{"info", "show the values"}, {"info", "show the values"},
{"log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"}, {"log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
{"poll", "toggle EMS poll request on/off"}, {"poll", "toggle EMS poll request on/off"},
{"tx", "toggle EMX Tx on/off"}, {"tx", "toggle EMX Tx line on/off"},
{"publish", "publish values to MQTT"}, {"publish", "publish values to MQTT"},
{"types", "list supported EMS telegram type IDs"}, {"types", "list supported EMS telegram type IDs"},
{"queue", "print the Tx queue"}, {"queue", "print the Tx queue"},
@@ -349,7 +337,9 @@ void showInfo() {
_renderIntValue("Boiler circuit pump modulation min. power", "%", EMS_Boiler.pump_mod_min); _renderIntValue("Boiler circuit pump modulation min. power", "%", EMS_Boiler.pump_mod_min);
// UBAMonitorSlow // UBAMonitorSlow
if (EMS_Boiler.extTemp != EMS_VALUE_FLOAT_NOTSET) {
_renderFloatValue("Outside temperature", "C", EMS_Boiler.extTemp); _renderFloatValue("Outside temperature", "C", EMS_Boiler.extTemp);
}
_renderFloatValue("Boiler temperature", "C", EMS_Boiler.boilTemp); _renderFloatValue("Boiler temperature", "C", EMS_Boiler.boilTemp);
_renderIntValue("Pump modulation", "%", EMS_Boiler.pumpMod); _renderIntValue("Pump modulation", "%", EMS_Boiler.pumpMod);
_renderLongValue("Burner # restarts", "times", EMS_Boiler.burnStarts); _renderLongValue("Burner # restarts", "times", EMS_Boiler.burnStarts);
@@ -576,7 +566,7 @@ char * _readWord() {
} }
// initiate a force scan by sending type read requests from 0 to FF to the thermostat // initiate a force scan by sending type read requests from 0 to FF to the thermostat
// used to analyze repsonses for debugging // used to analyze responses for debugging
void startThermostatScan(uint8_t start) { void startThermostatScan(uint8_t start) {
ems_setLogging(EMS_SYS_LOGGING_THERMOSTAT); ems_setLogging(EMS_SYS_LOGGING_THERMOSTAT);
publishValuesTimer.detach(); publishValuesTimer.detach();
@@ -589,22 +579,66 @@ void startThermostatScan(uint8_t start) {
// callback for loading/saving settings to the file system (SPIFFS) // callback for loading/saving settings to the file system (SPIFFS)
void FSCallback(MYESP_FSACTION action, JsonObject & json) { bool FSCallback(MYESP_FSACTION action, JsonObject & json) {
bool ok = true;
if (action == MYESP_FSACTION_LOAD) { if (action == MYESP_FSACTION_LOAD) {
// led
if (json.containsKey("led")) {
EMSESP_Status.led_enabled = (bool)json["led"]; EMSESP_Status.led_enabled = (bool)json["led"];
} else {
ok = false;
}
// led_gpio
if (json.containsKey("led_gpio")) {
EMSESP_Status.led_gpio = json["led_gpio"];
} else {
ok = false;
}
// dallas_gpio
if (json.containsKey("dallas_gpio")) {
EMSESP_Status.dallas_gpio = json["dallas_gpio"];
} else {
ok = false;
}
// thermostat_type
if (json.containsKey("thermostat_type")) {
EMS_Thermostat.type_id = json["thermostat_type"];
} else {
EMS_Thermostat.type_id = EMSESP_THERMOSTAT_TYPE; // set default
ok = false;
}
// boiler_type
if (json.containsKey("boiler_type")) {
EMS_Boiler.type_id = json["boiler_type"];
} else {
EMS_Boiler.type_id = EMSESP_BOILER_TYPE; // set default
ok = false;
}
} }
if (action == MYESP_FSACTION_SAVE) { if (action == MYESP_FSACTION_SAVE) {
json["led"] = EMSESP_Status.led_enabled; json["led"] = EMSESP_Status.led_enabled;
} json["led_gpio"] = EMSESP_Status.led_gpio;
json["dallas_gpio"] = EMSESP_Status.dallas_gpio;
json["thermostat_type"] = EMS_Thermostat.type_id;
json["boiler_type"] = EMS_Boiler.type_id;
} }
// callback for custom settings return ok; // all ok
}
// callback for custom settings when showing Stored Settings
// wc is number of arguments after the 'set' command // wc is number of arguments after the 'set' command
// returns true if successful
bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, const char * value) { bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, const char * value) {
bool ok = false; bool ok = false;
if (action == MYESP_FSACTION_SET) { if (action == MYESP_FSACTION_SET) {
// led
if ((strcmp(setting, "led") == 0) && (wc == 2)) { if ((strcmp(setting, "led") == 0) && (wc == 2)) {
if (strcmp(value, "on") == 0) { if (strcmp(value, "on") == 0) {
EMSESP_Status.led_enabled = true; EMSESP_Status.led_enabled = true;
@@ -613,13 +647,53 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
EMSESP_Status.led_enabled = false; EMSESP_Status.led_enabled = false;
ok = true; ok = true;
// let's make sure LED is really off // let's make sure LED is really off
digitalWrite(BOILER_LED, (BOILER_LED == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
} }
} }
// led_gpio
if ((strcmp(setting, "led_gpio") == 0) && (wc == 2)) {
EMSESP_Status.led_gpio = atoi(value);
ok = true;
}
// dallas_gpio
if ((strcmp(setting, "dallas_gpio") == 0) && (wc == 2)) {
EMSESP_Status.dallas_gpio = atoi(value);
ok = true;
}
// thermostat_type
if (strcmp(setting, "thermostat_type") == 0) {
EMS_Thermostat.type_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
ok = true;
}
// boiler_type
if (strcmp(setting, "boiler_type") == 0) {
EMS_Boiler.type_id = ((wc == 2) ? (uint8_t)strtol(value, 0, 16) : EMS_ID_NONE);
ok = true;
}
} }
if (action == MYESP_FSACTION_LIST) { if (action == MYESP_FSACTION_LIST) {
myDebug(" led=%s", EMSESP_Status.led_enabled ? "on" : "off"); myDebug(" led=%s", EMSESP_Status.led_enabled ? "on" : "off");
myDebug(" led_gpio=%d", EMSESP_Status.led_gpio);
myDebug(" dallas_gpio=%d", EMSESP_Status.dallas_gpio);
if (EMS_Thermostat.type_id == EMS_ID_NONE) {
myDebug(" thermostat_type=<not set>");
} else {
myDebug(" thermostat_type=%02X", EMS_Thermostat.type_id);
}
if (EMS_Boiler.type_id == EMS_ID_NONE) {
myDebug(" boiler_type=<not set>");
} else {
myDebug(" boiler_type=%02X", EMS_Boiler.type_id);
}
} }
return ok; return ok;
@@ -629,7 +703,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
// we set the logging here // we set the logging here
void TelnetCallback(uint8_t event) { void TelnetCallback(uint8_t event) {
if (event == TELNET_EVENT_CONNECT) { if (event == TELNET_EVENT_CONNECT) {
ems_setLogging(EMS_SYS_LOGGING_NONE); ems_setLogging(EMS_SYS_LOGGING_DEFAULT);
} else if (event == TELNET_EVENT_DISCONNECT) { } else if (event == TELNET_EVENT_DISCONNECT) {
ems_setLogging(EMS_SYS_LOGGING_NONE); ems_setLogging(EMS_SYS_LOGGING_NONE);
} }
@@ -861,9 +935,7 @@ void WIFICallback() {
myDebug("[UART] Opened Rx/Tx connection"); myDebug("[UART] Opened Rx/Tx connection");
#endif #endif
// now that we're connected, set up the boiler and thermostat // now that we're connected, find out what boiler and thermostats we have specified
// the boiler's version will be requested and if there is no thermostat hardcoded it will try
// and find the first one
ems_discoverModels(); ems_discoverModels();
} }
@@ -876,6 +948,9 @@ void initEMSESP() {
EMSESP_Status.timestamp = millis(); EMSESP_Status.timestamp = millis();
EMSESP_Status.dallas_sensors = 0; EMSESP_Status.dallas_sensors = 0;
EMSESP_Status.led_gpio = EMSESP_LED_GPIO;
EMSESP_Status.dallas_gpio = EMSESP_DALLAS_GPIO;
// shower settings // shower settings
EMSESP_Shower.timerStart = 0; EMSESP_Shower.timerStart = 0;
EMSESP_Shower.timerPause = 0; EMSESP_Shower.timerPause = 0;
@@ -892,14 +967,14 @@ void do_publishValues() {
} }
// callback to light up the LED, called via Ticker every second // callback to light up the LED, called via Ticker every second
// fast way is to use WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + (state ? 4 : 8), (1 << BOILER_LED)); // 4 is on, 8 is off // fast way is to use WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + (state ? 4 : 8), (1 << EMSESP_Status.led_gpio)); // 4 is on, 8 is off
void do_ledcheck() { void do_ledcheck() {
if (EMSESP_Status.led_enabled) { if (EMSESP_Status.led_enabled) {
if (ems_getBusConnected()) { if (ems_getBusConnected()) {
digitalWrite(BOILER_LED, (BOILER_LED == LED_BUILTIN) ? LOW : HIGH); // light on. For onboard LED high=off digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? LOW : HIGH); // light on. For onboard LED high=off
} else { } else {
int state = digitalRead(BOILER_LED); int state = digitalRead(EMSESP_Status.led_gpio);
digitalWrite(BOILER_LED, !state); digitalWrite(EMSESP_Status.led_gpio, !state);
} }
} }
} }
@@ -1019,6 +1094,12 @@ void showerCheck() {
// SETUP // SETUP
// //
void setup() { void setup() {
// init our own parameters
initEMSESP();
// call ems.cpp's init function to set all the internal params
ems_init();
#ifndef DEBUG_SUPPORT #ifndef DEBUG_SUPPORT
// Timers using Ticker library // Timers using Ticker library
publishValuesTimer.attach(PUBLISHVALUES_TIME, do_publishValues); // post MQTT values publishValuesTimer.attach(PUBLISHVALUES_TIME, do_publishValues); // post MQTT values
@@ -1031,24 +1112,22 @@ void setup() {
myESP.setWIFI(WIFI_SSID, WIFI_PASSWORD, WIFICallback); myESP.setWIFI(WIFI_SSID, WIFI_PASSWORD, WIFICallback);
myESP.setMQTT( myESP.setMQTT(
MQTT_HOST, MQTT_USER, MQTT_PASS, MQTT_BASE, MQTT_KEEPALIVE, MQTT_QOS, MQTT_RETAIN, MQTT_WILL_TOPIC, MQTT_WILL_PAYLOAD, MQTTCallback); MQTT_HOST, MQTT_USER, MQTT_PASS, MQTT_BASE, MQTT_KEEPALIVE, MQTT_QOS, MQTT_RETAIN, MQTT_WILL_TOPIC, MQTT_WILL_PAYLOAD, MQTTCallback);
// custom settings in SPIFFS
myESP.setSettings(FSCallback, SettingsCallback); myESP.setSettings(FSCallback, SettingsCallback);
myESP.begin(APP_HOSTNAME, APP_NAME, APP_VERSION); // start it all up // start up all the services
myESP.begin(APP_HOSTNAME, APP_NAME, APP_VERSION);
// init our own parameters
initEMSESP();
// set pin for LED // set pin for LED
pinMode(BOILER_LED, OUTPUT); if (EMSESP_Status.led_gpio != EMS_VALUE_INT_NOTSET) {
digitalWrite(BOILER_LED, (BOILER_LED == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off pinMode(EMSESP_Status.led_gpio, OUTPUT);
digitalWrite(EMSESP_Status.led_gpio, (EMSESP_Status.led_gpio == LED_BUILTIN) ? HIGH : LOW); // light off. For onboard high=off
ledcheckTimer.attach(LEDCHECK_TIME, do_ledcheck); // blink heartbeat LED ledcheckTimer.attach(LEDCHECK_TIME, do_ledcheck); // blink heartbeat LED
}
// check for Dallas sensors // check for Dallas sensors
EMSESP_Status.dallas_sensors = ds18.setup(TEMPERATURE_SENSOR_PIN); EMSESP_Status.dallas_sensors = ds18.setup(EMSESP_Status.dallas_gpio); // returns #sensors
// init the EMS bus
// call ems.cpp's init function to set all the internal params
ems_init(MY_THERMOSTAT_MODELID);
} }
// //

View File

@@ -143,7 +143,7 @@ uint8_t _last_TxTelgramCRC; // CRC of last Tx sent, for checking duplicates
// init stats and counters and buffers // init stats and counters and buffers
// uses -255 or 255 for values that haven't been set yet (EMS_VALUE_INT_NOTSET and EMS_VALUE_FLOAT_NOTSET) // uses -255 or 255 for values that haven't been set yet (EMS_VALUE_INT_NOTSET and EMS_VALUE_FLOAT_NOTSET)
void ems_init(uint8_t thermostat_modelid) { void ems_init() {
// overall status // overall status
EMS_Sys_Status.emsRxPgks = 0; EMS_Sys_Status.emsRxPgks = 0;
EMS_Sys_Status.emsTxPkgs = 0; EMS_Sys_Status.emsTxPkgs = 0;
@@ -224,15 +224,13 @@ void ems_init(uint8_t thermostat_modelid) {
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
EMS_Boiler.heatingActive = EMS_VALUE_INT_NOTSET; // Central heating is on/off EMS_Boiler.heatingActive = EMS_VALUE_INT_NOTSET; // Central heating is on/off
// boiler is hardcoded // set boiler type
EMS_Boiler.type_id = EMS_ID_BOILER; // fixed at 0x08
EMS_Boiler.product_id = 0; EMS_Boiler.product_id = 0;
strlcpy(EMS_Boiler.version, "not set", sizeof(EMS_Boiler.version)); strlcpy(EMS_Boiler.version, "not set", sizeof(EMS_Boiler.version));
// set thermostat model // set thermostat model
EMS_Thermostat.type_id = EMS_ID_NONE; // fixed at 0x08 EMS_Thermostat.model_id = EMS_MODEL_NONE;
EMS_Thermostat.product_id = 0; EMS_Thermostat.product_id = 0;
_ems_setThermostatModel(thermostat_modelid);
strlcpy(EMS_Thermostat.version, "not set", sizeof(EMS_Thermostat.version)); strlcpy(EMS_Thermostat.version, "not set", sizeof(EMS_Thermostat.version));
// counters // counters
@@ -240,8 +238,8 @@ void ems_init(uint8_t thermostat_modelid) {
_emsTxRetryCount = 0; _emsTxRetryCount = 0;
_last_TxTelgramCRC = 0; _last_TxTelgramCRC = 0;
// default logging is non // default logging is none
ems_setLogging(EMS_SYS_LOGGING_NONE); ems_setLogging(EMS_SYS_LOGGING_DEFAULT);
} }
// Getters and Setters for parameters // Getters and Setters for parameters
@@ -469,15 +467,15 @@ void _ems_sendTelegram() {
return; return;
} }
// if Tx is disabled, don't do anything and ignore the request // if there is no destination, also delete it from the queue
// this could be because the boiler has yet to be found and the type_id is still empty
if (EMS_TxTelegram.dest == EMS_ID_NONE) { if (EMS_TxTelegram.dest == EMS_ID_NONE) {
EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE; // finished sending EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE; // finished sending
EMS_TxQueue.shift(); // remove from queue EMS_TxQueue.shift(); // remove from queue
return; return;
} }
// if there is no destination, also delete it from the queue // if Tx is disabled, don't do anything and ignore the request
// this could be because the boiler has yet to be found and the type_id is still empty
if (!EMS_Sys_Status.emsTxEnabled) { if (!EMS_Sys_Status.emsTxEnabled) {
myDebug("Tx is disabled. Ignoring %s request to 0x%02X.", myDebug("Tx is disabled. Ignoring %s request to 0x%02X.",
((EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) ? "write" : "read"), ((EMS_TxTelegram.action == EMS_TX_TELEGRAM_WRITE) ? "write" : "read"),
@@ -516,6 +514,7 @@ void _ems_sendTelegram() {
// myDebug("Duplicate message, just sent this one, so removing from queue!"); // myDebug("Duplicate message, just sent this one, so removing from queue!");
EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE; // finished sending EMS_Sys_Status.emsTxStatus = EMS_TX_IDLE; // finished sending
EMS_TxQueue.shift(); // remove the last Tx from the queue EMS_TxQueue.shift(); // remove the last Tx from the queue
return;
} }
_last_TxTelgramCRC = crc; _last_TxTelgramCRC = crc;
@@ -770,8 +769,8 @@ void _ems_processTelegram(uint8_t * telegram, uint8_t length) {
*/ */
void _processType(uint8_t * telegram, uint8_t length) { void _processType(uint8_t * telegram, uint8_t length) {
// header // header
uint8_t src = telegram[0] & 0x7F; // removing 8th bit as we deal with both reads and writes uint8_t src = telegram[0] & 0x7F; // removing 8th bit as we deal with both reads and writes here
uint8_t dest = telegram[1] & 0x7F; // remove 8th bit to handle both reads and writes uint8_t dest = telegram[1] & 0x7F;
uint8_t type = telegram[2]; uint8_t type = telegram[2];
uint8_t * data = telegram + 4; // data block starts at position 5 uint8_t * data = telegram + 4; // data block starts at position 5
@@ -781,27 +780,33 @@ void _processType(uint8_t * telegram, uint8_t length) {
return; return;
} }
// did we request this telegram? If so it would be either a read or a validate telegram and still on the // did we request this telegram? If so it would be either a read or a validate telegram and still
// Tx queue with the same type // on top of the Tx queue with the same type. because we don't remove a Tx from the queue after a send
// if its a validate check the value, or if its a read, update the Read counter // if its a validate check the value, or if its a read, update the Read counter
// then we can safely removed the read/validate from the queue // then we can safely removed the read/validate from the queue
if ((dest == EMS_ID_ME) && (!EMS_TxQueue.isEmpty())) { if ((dest == EMS_ID_ME) && (!EMS_TxQueue.isEmpty())) {
_EMS_TxTelegram EMS_TxTelegram = EMS_TxQueue.first(); // get current Tx package we last sent _EMS_TxTelegram EMS_TxTelegram = EMS_TxQueue.first(); // get current Tx package we last sent
// do the types match? If so we were expecting this response back to us // do the types match? If so we were expecting this telegram response back to us
if (EMS_TxTelegram.type == type) { if (EMS_TxTelegram.type == type) {
emsaurt_tx_poll(); // send Acknowledgement back to free the EMS bus emsaurt_tx_poll(); // send Acknowledgement back to free the EMS bus since we have the telegram
// if last action was a read, we are just happy that we actually got a response back // if last action was a read, go ahead and process it
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_READ) { if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_READ) {
EMS_Sys_Status.emsRxPgks++; // increment rx counter EMS_Sys_Status.emsRxPgks++; // increment rx counter
_emsTxRetryCount = 0; // reset retry count _emsTxRetryCount = 0; // reset retry count
_ems_processTelegram(telegram, length); // and process the telegram //
// and process the telegram. This calls the main function to process each type
//
_ems_processTelegram(telegram, length);
if (EMS_TxTelegram.forceRefresh) { if (EMS_TxTelegram.forceRefresh) {
ems_setEmsRefreshed(true); // set the MQTT refresh flag to force sending to MQTT ems_setEmsRefreshed(true); // set the MQTT refresh flag to force sending to MQTT
} }
EMS_TxQueue.shift(); // remove read from queue, all done now EMS_TxQueue.shift(); // remove read from queue, all done now
} else if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_VALIDATE) { return; // quit
}
if (EMS_TxTelegram.action == EMS_TX_TELEGRAM_VALIDATE) {
// this read was for a validate. Do a compare on the 1 byte result from the last write // this read was for a validate. Do a compare on the 1 byte result from the last write
uint8_t dataReceived = data[0]; // only a single byte is returned after a read uint8_t dataReceived = data[0]; // only a single byte is returned after a read
if (EMS_TxTelegram.comparisonValue == dataReceived) { if (EMS_TxTelegram.comparisonValue == dataReceived) {
@@ -816,7 +821,7 @@ void _processType(uint8_t * telegram, uint8_t length) {
} else { } else {
// write failed. // write failed.
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug("Last write failed. Compared set value 0x%02X with received value 0x%02X.", myDebug("Last write failed. Compared set value 0x%02X with received value 0x%02X",
EMS_TxTelegram.comparisonValue, EMS_TxTelegram.comparisonValue,
dataReceived); dataReceived);
} }
@@ -838,9 +843,18 @@ void _processType(uint8_t * telegram, uint8_t length) {
EMS_TxQueue.unshift(EMS_TxTelegram); // add back to queue making it next in line EMS_TxQueue.unshift(EMS_TxTelegram); // add back to queue making it next in line
} }
} }
return;
} }
} }
// telegram was for us, but seems we didn't ask for it // telegram was for us, but seems we didn't ask for it
// so kinda invalidates the last action on the queue remove from queue
myDebug("Telegram sent to us but we didn't ask for it! (src=0x%02X dest=0x%02X type=0x%02X)",
telegram[0] & 0x7F,
telegram[1] & 0x7F,
telegram[2]);
// ems_printTxQueue();
// EMS_TxQueue.shift(); // remove validate from queue
} else { } else {
// we didn't request it, was for somebody else or a broadcast, process it anyway // we didn't request it, was for somebody else or a broadcast, process it anyway
_ems_processTelegram(telegram, length); _ems_processTelegram(telegram, length);
@@ -1055,6 +1069,7 @@ void _process_Version(uint8_t * data, uint8_t length) {
return; return;
} }
bool do_save = false;
uint8_t product_id = data[0]; uint8_t product_id = data[0];
char version[10] = {0}; char version[10] = {0};
snprintf(version, sizeof(version), "%02d.%02d", data[1], data[2]); snprintf(version, sizeof(version), "%02d.%02d", data[1], data[2]);
@@ -1072,29 +1087,33 @@ void _process_Version(uint8_t * data, uint8_t length) {
if (typeFound) { if (typeFound) {
// its a boiler // its a boiler
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { myDebug("Boiler type device found. Model %s with TypeID 0x%02X, Product ID %d, Version %s",
myDebug("Boiler found. Model %s with TypeID 0x%02X, Product ID %d, Version %s", Boiler_Types[i].model_string,
Boiler_Types[i].type_id,
product_id,
version);
// if its a boiler set it
// it will take the first one found in the list
if ((EMS_Boiler.type_id == EMS_ID_NONE) || (EMS_Boiler.type_id == Boiler_Types[i].type_id)) {
myDebug("* Setting Boiler type to Model %s, TypeID 0x%02X, Product ID %d, Version %s",
Boiler_Types[i].model_string, Boiler_Types[i].model_string,
Boiler_Types[i].type_id, Boiler_Types[i].type_id,
product_id, product_id,
version); version);
}
// if its a boiler set it (even if it was already set)
if (Boiler_Types[i].type_id == EMS_ID_BOILER) {
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) {
myDebug("* Setting boiler to this new type");
}
EMS_Boiler.type_id = Boiler_Types[i].type_id; EMS_Boiler.type_id = Boiler_Types[i].type_id;
EMS_Boiler.product_id = Boiler_Types[i].product_id; EMS_Boiler.product_id = Boiler_Types[i].product_id;
strlcpy(EMS_Boiler.version, version, sizeof(EMS_Boiler.version)); strlcpy(EMS_Boiler.version, version, sizeof(EMS_Boiler.version));
do_save = true;
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
} }
return; return;
} }
// its not a boiler, maybe its a known thermostat // its not a boiler, maybe its a known thermostat?
i = 0; i = 0;
while (i < _Thermostat_Types_max) { while (i < _Thermostat_Types_max) {
if (Thermostat_Types[i].product_id == product_id) { if (Thermostat_Types[i].product_id == product_id) {
@@ -1115,11 +1134,14 @@ void _process_Version(uint8_t * data, uint8_t length) {
} }
// if we don't have a thermostat set, use this one // if we don't have a thermostat set, use this one
// if its the one we hard coded, refresh the data anyway if ((EMS_Thermostat.type_id == EMS_ID_NONE) || (EMS_Thermostat.model_id == EMS_MODEL_NONE)
if ((EMS_Thermostat.model_id == EMS_MODEL_NONE) || (EMS_Thermostat.model_id == Thermostat_Types[i].model_id)) { || (EMS_Thermostat.type_id == Thermostat_Types[i].type_id)) {
if (EMS_Sys_Status.emsLogging >= EMS_SYS_LOGGING_BASIC) { myDebug("* Setting Thermostat type to Model %s, TypeID 0x%02X, Product ID %d, Version %s",
myDebug("* Setting thermostat to this new type"); Thermostat_Types[i].model_string,
} Thermostat_Types[i].type_id,
product_id,
version);
EMS_Thermostat.model_id = Thermostat_Types[i].model_id; EMS_Thermostat.model_id = Thermostat_Types[i].model_id;
EMS_Thermostat.type_id = Thermostat_Types[i].type_id; EMS_Thermostat.type_id = Thermostat_Types[i].type_id;
EMS_Thermostat.read_supported = Thermostat_Types[i].read_supported; EMS_Thermostat.read_supported = Thermostat_Types[i].read_supported;
@@ -1127,12 +1149,19 @@ void _process_Version(uint8_t * data, uint8_t length) {
EMS_Thermostat.product_id = product_id; EMS_Thermostat.product_id = product_id;
strlcpy(EMS_Thermostat.version, version, sizeof(EMS_Thermostat.version)); strlcpy(EMS_Thermostat.version, version, sizeof(EMS_Thermostat.version));
do_save = true;
// get Thermostat values (if supported) // get Thermostat values (if supported)
ems_getThermostatValues(); ems_getThermostatValues();
} }
} else { } else {
myDebug("Unrecognized device found. Product ID %d, Version %s", product_id, version); myDebug("Unrecognized device found. Product ID %d, Version %s", product_id, version);
} }
// if the boiler or thermostat values have changed, save them to SPIFFS
if (do_save) {
myESP.fs_saveConfig();
}
} }
/* /*
@@ -1140,15 +1169,15 @@ void _process_Version(uint8_t * data, uint8_t length) {
*/ */
void ems_discoverModels() { void ems_discoverModels() {
// boiler // boiler
ems_doReadCommand(EMS_TYPE_Version, EMS_ID_BOILER); // get version details of boiler ems_doReadCommand(EMS_TYPE_Version, EMS_Boiler.type_id); // get version details of boiler
ems_getBoilerValues(); // fetch values from boiler, instead of waiting for broadcasts ems_getBoilerValues(); // fetch values from boiler, instead of waiting for broadcasts
// thermostat // thermostat
if (EMS_Thermostat.model_id == EMS_MODEL_NONE) { // if it hasn't been set, auto discover it
if (EMS_Thermostat.type_id == EMS_ID_NONE) {
ems_scanDevices(); // auto-discover it ems_scanDevices(); // auto-discover it
} else { } else {
// set the model as hardcoded (see my_devices.h) and fetch the version and product id // set the model as hardcoded (see my_devices.h) and fetch the version and product id
_ems_setThermostatModel(EMS_Thermostat.model_id);
ems_doReadCommand(EMS_TYPE_Version, EMS_Thermostat.type_id); ems_doReadCommand(EMS_TYPE_Version, EMS_Thermostat.type_id);
ems_getThermostatValues(); ems_getThermostatValues();
} }

View File

@@ -15,17 +15,13 @@
// EMS IDs // EMS IDs
#define EMS_ID_NONE 0x00 // Fixed - used as a dest in broadcast messages and empty type IDs #define EMS_ID_NONE 0x00 // Fixed - used as a dest in broadcast messages and empty type IDs
#define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as the "Service Key" #define EMS_ID_ME 0x0B // Fixed - our device, hardcoded as the "Service Key"
#define EMS_ID_BOILER 0x08 // Fixed - boilers are always 0x08. I think. #define EMS_ID_DEFAULT_BOILER 0x08
#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.
// This can differs per firmware version and typically 32 is the max
#define EMS_MAX_TELEGRAM_LENGTH 99 #define EMS_MAX_TELEGRAM_LENGTH 99
// Common for all EMS devices
#define EMS_TYPE_Version 0x02 // version of the UBA controller (boiler)
// default values // default values
#define EMS_VALUE_INT_ON 1 // boolean true #define EMS_VALUE_INT_ON 1 // boolean true
#define EMS_VALUE_INT_OFF 0 // boolean false #define EMS_VALUE_INT_OFF 0 // boolean false
@@ -60,6 +56,8 @@
#define EMS_TX_TELEGRAM_QUEUE_MAX 50 // max size of Tx FIFO queue #define EMS_TX_TELEGRAM_QUEUE_MAX 50 // max size of Tx FIFO queue
//#define EMS_SYS_LOGGING_DEFAULT EMS_SYS_LOGGING_VERBOSE
#define EMS_SYS_LOGGING_DEFAULT EMS_SYS_LOGGING_NONE
/* EMS UART transfer status */ /* EMS UART transfer status */
typedef enum { typedef enum {
@@ -251,7 +249,7 @@ typedef struct {
// function definitions // function definitions
extern void ems_parseTelegram(uint8_t * telegram, uint8_t len); extern void ems_parseTelegram(uint8_t * telegram, uint8_t len);
void ems_init(uint8_t thermostat_modelid); void ems_init();
void ems_doReadCommand(uint8_t type, uint8_t dest, bool forceRefresh = false); void ems_doReadCommand(uint8_t type, uint8_t dest, bool forceRefresh = false);
void ems_sendRawTelegram(char * telegram); void ems_sendRawTelegram(char * telegram);

View File

@@ -3,7 +3,7 @@
* *
* Paul Derbyshire - https://github.com/proddy/EMS-ESP * Paul Derbyshire - https://github.com/proddy/EMS-ESP
* *
* See ChangeLog.md for history * See ChangeLog.md for History
* See README.md for Acknowledgments * See README.md for Acknowledgments
* *
*/ */
@@ -12,6 +12,12 @@
#include "ems.h" #include "ems.h"
/*
* Common
*/
#define EMS_TYPE_Version 0x02
/* /*
* Boiler... * Boiler...
*/ */
@@ -91,11 +97,10 @@ typedef enum {
} _EMS_MODEL_ID; } _EMS_MODEL_ID;
// EMS types for known Buderus devices. This list will be extended when new devices are recognized. // EMS types for known Buderus/Bosch devices. This list will be extended when new devices are recognized.
// format is MODEL_ID, PRODUCT ID, TYPE_ID, DESCRIPTION // format is MODEL_ID, PRODUCT ID, TYPE_ID, DESCRIPTION
const _Boiler_Type Boiler_Types[] = { const _Boiler_Type Boiler_Types[] = {
// various boilers and buderus type devices
{EMS_MODEL_UBA, 72, 0x08, "MC10"}, {EMS_MODEL_UBA, 72, 0x08, "MC10"},
{EMS_MODEL_UBA, 123, 0x08, "Buderus GB172/Nefit Trendline"}, {EMS_MODEL_UBA, 123, 0x08, "Buderus GB172/Nefit Trendline"},
{EMS_MODEL_UBA, 115, 0x08, "Nefit Topline Compact"}, {EMS_MODEL_UBA, 115, 0x08, "Nefit Topline Compact"},

View File

@@ -10,15 +10,6 @@
#include "ems.h" #include "ems.h"
// Set your wifi and mqtt params
// If set to NULL (default) you'll need to set them in AP mode using the 'set' command
// as these values are stored in SPIFFs for persisted
#define WIFI_SSID NULL
#define WIFI_PASSWORD NULL
#define MQTT_HOST NULL
#define MQTT_USER NULL
#define MQTT_PASS NULL
// All MQTT topics are prefixed with the following string // All MQTT topics are prefixed with the following string
#define MQTT_BASE "home" #define MQTT_BASE "home"
#define MQTT_TOPIC_START "start" #define MQTT_TOPIC_START "start"
@@ -29,21 +20,53 @@
#define MQTT_KEEPALIVE 300 #define MQTT_KEEPALIVE 300
#define MQTT_QOS 1 #define MQTT_QOS 1
// thermostat
#define TOPIC_THERMOSTAT_DATA "thermostat_data" // for sending thermostat values
#define TOPIC_THERMOSTAT_CMD_TEMP "thermostat_cmd_temp" // for received thermostat temp changes
#define TOPIC_THERMOSTAT_CMD_MODE "thermostat_cmd_mode" // for received thermostat mode changes
#define THERMOSTAT_CURRTEMP "thermostat_currtemp" // current temperature
#define THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature
#define THERMOSTAT_MODE "thermostat_mode" // mode
// boiler
#define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values
#define TOPIC_BOILER_TAPWATER_ACTIVE "tapwater_active" // if hot tap water is running
#define TOPIC_BOILER_HEATING_ACTIVE "heating_active" // if heating is on
// shower time
#define TOPIC_SHOWERTIME "showertime" // for sending shower time results
#define TOPIC_SHOWER_TIMER "shower_timer" // toggle switch for enabling the shower logic
#define TOPIC_SHOWER_ALERT "shower_alert" // toggle switch for enabling the shower alarm logic
#define TOPIC_SHOWER_COLDSHOT "shower_coldshot" // used to trigger a coldshot from an MQTT command
// default values for shower logic on/off // default values for shower logic on/off
#define BOILER_SHOWER_TIMER 1 // enable (1) to monitor shower time #define BOILER_SHOWER_TIMER 1 // enable (1) to monitor shower time
#define BOILER_SHOWER_ALERT 0 // enable (1) to send alert of cold water when shower time limit has exceeded #define BOILER_SHOWER_ALERT 0 // enable (1) to send alert of cold water when shower time limit has exceeded
#define SHOWER_MAX_DURATION 420000 // in ms. 7 minutes, before trigger a shot of cold water #define SHOWER_MAX_DURATION 420000 // in ms. 7 minutes, before trigger a shot of cold water
//////////////////////////////////////////////////////////////////////////////////////////////////
// THESE DEFAULT VALUES CAN ALSO BE SET AND STORED WITHTIN THE APPLICATION (see 'set' command) //
//////////////////////////////////////////////////////////////////////////////////////////////////
// Set your wifi and mqtt params
// If set to NULL (default) you'll need to set them in AP mode using the 'set' command
#define WIFI_SSID NULL
#define WIFI_PASSWORD NULL
#define MQTT_HOST NULL
#define MQTT_USER NULL
#define MQTT_PASS NULL
// Set LED pin used for showing ems bus connection status. Solid is connected, Flashing is error // Set LED pin used for showing ems bus connection status. Solid is connected, Flashing is error
// can be either the onboard LED on the ESP8266 or external via an external pull-up LED (e.g. D1 on bbqkees' board) // can be either the onboard LED on the ESP8266 (LED_BULLETIN) or external via an external pull-up LED (e.g. D1 on bbqkees' board)
// can be enabled and disabled via the 'set led' command // can be enabled and disabled via the 'set led' command
#define BOILER_LED LED_BUILTIN // LED_BULLETIN for onboard LED // pin can be set by 'set led_gpio'
#define EMSESP_LED_GPIO LED_BUILTIN
// set this if using an external temperature sensor like a DS18B20 // set this if using an external temperature sensor like a DS18B20
// D5 is the default on bbqkees' board // D5 is the default on bbqkees' board
#define TEMPERATURE_SENSOR_PIN D5 #define EMSESP_DALLAS_GPIO D5
// By default the EMS bus will be scanned for known devices based on product ids in ems_devices.h // By default the EMS bus will be scanned for known devices based on product ids in ems_devices.h
// You can override the Thermostat model by hardcoding the model type // You can override the Thermostat and Boiler types here
#define MY_THERMOSTAT_MODELID EMS_MODEL_NONE #define EMSESP_BOILER_TYPE EMS_ID_NONE
//#define MY_THERMOSTAT_MODELID EMS_MODEL_RC35 #define EMSESP_THERMOSTAT_TYPE EMS_ID_NONE

View File

@@ -6,5 +6,5 @@
#pragma once #pragma once
#define APP_NAME "EMS-ESP" #define APP_NAME "EMS-ESP"
#define APP_VERSION "1.4.0" #define APP_VERSION "1.4.1"
#define APP_HOSTNAME "ems-esp" #define APP_HOSTNAME "ems-esp"