updated to latest ESPurna

This commit is contained in:
proddy
2018-10-21 18:39:05 +02:00
parent 5ab25238a9
commit 8723bd5379
8 changed files with 897 additions and 729 deletions

View File

@@ -82,12 +82,13 @@ To see the current values of the Boiler and its parameters type 's' and hit Ente
Commands can be issued directly to the EMS bus typing in a letter followed by an optional parameter and pressing Enter. Supported commands are:
- **r** to send a read command to all devices to fetch values. The 2nd parameter is the type. For example 'r 33' will request type UBAParameterWW and bring back the Warm Water temperatures (not the heating) from the Boiler. You can issue any type here.
- **t** set the thermostat temperature to the given value
- **t** set the thermostat temperature to the given celsius value
- **w** to adjust the temperature of the warm water from the boiler
- **a** to turn the warm water on and off
- **h** to list all the recognized EMS types
- **p** to toggle the Polling response on/off. It's not necessary to have Polling enabled to work. I use this for debugging purposes.
- **m** to set the thermostat mode from low, manual and clock/auto.
- **T** to toggle thermostat reading on/off
- **T** to toggle thermostat readings on/off
- **S** to toggle the Shower Timer functionality on/off
**Disclaimer: be careful when sending values to the boiler. If in doubt you can always reset the boiler to its original factory settings by following the instructions in the user guide. On my **Nefit Trendline HRC30** that is done by holding down the Home and Menu buttons simultaneously for a few seconds, selecting factory settings from the scroll menu and lastly pressing the Reset button.**
@@ -220,13 +221,13 @@ The code is built on the Arduino framework and is dependent on these external li
In `boiler.ino` you can make calls to automatically send these read commands. See the function *regularUpdates()*
#### Support for RC35 type Thermostats
#### Supporting RC35 model Thermostats
An RC35 thermostat has 4 heating circuits. To read the values use the Monitor type IDs (e.g. 0x3E, 0x48, etc). The mode (0=night, 1=day, 2=holiday) is the first byte of the telegram and the temperature is the value of the 2nd byte divided by 2.
The code is designed for a Moduline300 (RC20) thermostat. To adjust for a RC35 first change `EMS_ID_THERMOSTAT` in `ems.h`. A RC35 thermostat has 4 heating circuits and to read the values use different Monitor type IDs (e.g. 0x3E, 0x48, etc). The mode (0=night, 1=day, 2=holiday) is the first byte of the telegram and the temperature is the value of the 2nd byte divided by 2.
Then to set temperature values use the Working Mode with type IDs (0x3D, 0x47,0x51 and 0x5B) respectively. Set the offset (byte 4 of the header) to determine which temperature you're changing; 1 for night, 2 for day and 3 for holiday. The data value is the desired temperature multiplied by 2 as a single byte.
Consult the wiki documentation for the data format.
Consult the wiki documentation for the actual data format.
### Customizing the code
@@ -244,7 +245,7 @@ I'm using the standard PubSubClient client so make sure you set `-DMQTT_MAX_PACK
I run Mosquitto on my Raspberry PI 3 as the MQTT broker.
The boiler data is collected and sent as a single JSON object to MQTT TOPIC `home/boiler/boiler_data`. A hash is generated (CRC32 based) to determine if the payload has changed, otherwise don't send it. An example payload looks like:
The boiler data is collected and sent as a single JSON object to MQTT TOPIC `home/boiler/boiler_data` (or `{hostname}/boiler_data` for ESPurna). A hash is generated (CRC32 based) to determine if the payload has changed, otherwise don't send it. An example payload looks like:
`{"wWCurTmp":"43.0","wWHeat":"on","curFlowTemp":"51.7","retTemp":"48.0","burnGas":"off","heatPmp":"off","fanWork":"off","ignWork":"off","wWCirc":"off","selBurnPow":"0","curBurnPow":"0","sysPress":"1.6","boilTemp":"54.7","pumpMod":"4"}`
@@ -290,30 +291,34 @@ Roughly these are the steps needed when running Windows:
### Using ESPurna
[ESPurna](https://github.com/xoseperez/espurna/wiki) is framework that handles most of the tedious tasks of building IoT devices so you can focus on the functionality you need. This replaces my ESPHelper code in the standalone version above. ESPurna is natively built on PlatformIO and Visual Studio Code too which is nice. So if you're brave, follow these steps:
[ESPurna](https://github.com/xoseperez/espurna/wiki) is framework that handles most of the tedious tasks of building IoT devices so you can focus on the functionality you need. This replaces my ESPHelper code in the standalone version above. ESPurna is natively built on PlatformIO and Visual Studio Code too which is nice. The latest version supported is 1.13.3. So if you're brave, follow these steps:
1. Download and install [NodeJS](https://nodejs.org/en/download). This gives you npm. Choose the LTS version
2. Download ESPurna by cloning the ESPurna git repository from `https://github.com/xoseperez/espurna.git`
3. Restart VSC. PlatformIO should detect and set some things up for you automagically
4. From VSC open the folder `espurna\code`
2. Download ESPurna by cloning the ESPurna git repository (command palette, git clone, https://github.com/xoseperez/espurna.git)
3. Restart VSC.
4. From VSC open the folder `espurna\code`. PlatformIO should detect and set some things up for you automagically
5. open a terminal window (*ctrl-`*)
6. Install the node modules: `npm install --only=dev`
7. Build the web interface: `node node_modules/gulp/bin/gulp.js`. This will create a compressed `code/espurna/static/index.html.gz.h`
8. First time users build the filesystem by *ctrl-alt-t* and run the task 'uploadfs'
9. Copy these files from this repo's *espurna* directory to where you installed ESPurna
7. Build the web interface: `node node_modules/gulp/bin/gulp.js`. This will create a compressed `code/espurna/static/index.html.gz.h`. If you get warnings about lf during the building edit `gulpfile.js` and change the line `'failOnError': true` to `false` as a temporary workaround.
8. Modify the platformio.ini file making sure you add `-DUSE_CUSTOM_H -DUSE_EXTRA` to the `debug_flags`
9. Copy the following files from EMS-ESP-Boiler repo to where you installed ESPurna
```
code/html/index.html
code/config/custom.h
code/espurna/boiler-espurna.ino
code/espurna/ems*.*
espurna/index.html -> code/html/index.html
espurna/custom.h -> code/config/custom.h
espurna/boiler-espurna.ino -> code/espurna/boiler-espurna.ino
ems*.* -> code/espurna/
```
10. Now build and upload as you usually would. Look at my version of platformio.ini as an example.
10. Now build and upload as you usually would with PlatformIO (or ctrl-arl-t and choose the right build). Look at my version of platformio.ini as an example.
11. When the firmware loads, use a wifi connected pc/mobile to connect to the Access Point called ESPURNA_XXXXXX. Use 'fibonacci' as the password. Navigate to `http://192.168.4.1` from a browser, set a new username and password when prompted, log off the wifi and reconnect to the AP using these new credentials. Again go to 192.168.4.1
12. In the ADMIN page enable Telnet and SAVE
13. In the WIFI page add your home wifi details, click SAVE and reboot, and go to the new IP
14. Configure MQTT
The Telnet functions are `BOILER.READ`, `BOILER.INFO` and a few others for reference. `HELP` will list them. Add your own functions to expand the functionality by calling the EMS* functions as in the examples.
If you run into issues refer to ESPurna's official setup instructions [here](https://github.com/xoseperez/espurna/wiki/Build-and-update-from-Visual-Studio-Code-using-PlatformIO).
If you run into issues refer to ESPurna's official setup instructions [here](https://github.com/xoseperez/espurna/wiki/Build-and-update-from-Visual-Studio-Code-using-PlatformIO) and [here](https://github.com/xoseperez/espurna/wiki/Configuration).
This is what ESPurna looks like with the custom boiler code:
@@ -328,10 +333,8 @@ pre-baked firmwares for some ESP8266 devices based on ESPurna are available in t
2. Install the ESPTool by running `pip install esptool` from a command prompt
3. Connect the ESP via USB, figure out the COM port
4. run `esptool.py -p <com> write_flash 0x00000 <firmware>` where firmware is the `.bin` file and \<com\> is the COM port, e.g. `COM3`
5. Connect using WiFi from a phone or PC to the "**ESPURNA_XXXXXX**" network. Password is '**fibonacci**'
6. Once connected browse to "http://192.168.4.1" and setup your wifi, mqtt etc
Again, if you run into problems read [this](https://github.com/xoseperez/espurna/wiki/Configuration) from ESPurna's configuration help page.
now follow the steps in ESPurna section above from #10 on to configure the device.
### Using the Arduino IDE

View File

@@ -13,20 +13,31 @@
#define BOILER_POLLING_ENABLED 0
#define BOILER_LOGGING_NONE 1
// home/boiler/
#define TOPIC_BOILER_DATA "boiler_data" // for sending boiler values
#define TOPIC_THERMOSTAT_TEMP "thermostat_temp" // for received thermostat temp changes
#define TOPIC_THERMOSTAT_CURRTEMP "thermostat_currtemp" // current temperature
#define TOPIC_THERMOSTAT_SELTEMP "thermostat_seltemp" // selected temperature
#define TOPIC_THERMOSTAT_MODE "thermostat_mode" // selected temperature
#define TOPIC_BOILER_WARM_WATER_SELECTED_TEMPERATURE "boiler_wwtemp" // warm water selected temp
#define BOILERSEND_INTERVAL 60000 // send every minute to HA
typedef struct {
bool wifi_connected;
bool boiler_online;
bool thermostat_enabled;
bool shower_enabled; // true if we want to report back on shower times
bool shower_timer; // true if we want the cold water reminder
bool shower_timer; // true if we want to report back on shower times
bool shower_alert; // true if we want the cold water reminder
} _Boiler_Status;
typedef struct {
bool showerOn;
unsigned long timerStart; // ms
unsigned long timerPause; // ms
unsigned long duration; // ms
bool isColdShot; // true if we've just sent a jolt of cold water
bool hotWaterOn;
unsigned long timerStart; // ms
unsigned long timerPause; // ms
unsigned long duration; // ms
bool doingColdShot; // true if we've just sent a jolt of cold water
} _Boiler_Shower;
// store for overall system status
@@ -44,7 +55,7 @@ void _boilerConfigure() {
uint8_t _boilerLogging = getSetting("boilerLogging", BOILER_LOGGING_NONE).toInt();
ems_setLogging((_EMS_SYS_LOGGING)_boilerLogging);
Boiler_Status.shower_enabled = getSetting("boilerShower", BOILER_SHOWER_ENABLED).toInt() == 1;
Boiler_Status.shower_timer = getSetting("boilerShower", BOILER_SHOWER_ENABLED).toInt() == 1;
}
// WEB callbacks
@@ -63,38 +74,111 @@ void _boilerWebSocketOnSend(JsonObject & root) {
void _boilerWebSocketOnAction(uint32_t client_id, const char * action, JsonObject & data) {
}
// send to HA
void sendHA() {
String topic = getSetting("haPrefix", HOMEASSISTANT_PREFIX);
String output;
// assume ha is enabled
DynamicJsonBuffer jsonBuffer;
JsonObject & config = jsonBuffer.createObject();
String name = getSetting("hostname");
config.set("name", name);
config.set("platform", "mqtt");
config.printTo(output);
// convert float to char
//char * _float_to_char(char * a, float f, uint8_t precision = 1);
char * _float_to_char(char * a, float f, uint8_t precision = 1) {
long p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};
mqttSendRaw(topic.c_str(), output.c_str());
mqttSend(MQTT_TOPIC_STATUS, MQTT_STATUS_ONLINE, true);
char * ret = a;
// check for 0x8000 (sensor missing), which has a -1 value
if (f == EMS_VALUE_FLOAT_NOTSET) {
strcpy(ret, "?");
} else {
long whole = (long)f;
itoa(whole, a, 10);
while (*a != '\0')
a++;
*a++ = '.';
long decimal = abs((long)((f - whole) * p[precision]));
itoa(decimal, a, 10);
}
return ret;
}
// convert bool to text
char * _bool_to_char(char * s, uint8_t value) {
if (value == EMS_VALUE_INT_ON) {
strcpy(s, "on");
} else if (value == EMS_VALUE_INT_OFF) {
strcpy(s, "off");
} else {
strcpy(s, "?");
}
return s;
}
// convert int to text value
char * _int_to_char(char * s, uint8_t value) {
if (value == EMS_VALUE_INT_NOTSET) {
strcpy(s, "?");
} else {
itoa(value, s, 10);
}
return s;
}
// takes a float value at prints it to debug log
void _renderFloatValue(const char * prefix, const char * postfix, float value) {
myDebug(" %s: ", prefix);
char s[20];
myDebug("%s", _float_to_char(s, value));
if (postfix != NULL) {
myDebug(" %s", postfix);
}
myDebug("\n");
}
// takes an int value at prints it to debug log
void _renderIntValue(const char * prefix, const char * postfix, uint8_t value) {
myDebug(" %s: ", prefix);
char s[20];
myDebug("%s", _int_to_char(s, value));
if (postfix != NULL) {
myDebug(" %s", postfix);
}
myDebug("\n");
}
// takes a bool value at prints it to debug log
void _renderBoolValue(const char * prefix, uint8_t value) {
myDebug(" %s: ", prefix);
char s[20];
myDebug("%s\n", _bool_to_char(s, value));
}
// Show command - display stats on an 's' command
void showInfo() {
char s[10]; // for formatting floats using the _float_to_char() function
// General stats from EMS bus
myDebug("EMS Bus stats:\n");
myDebug(" Thermostat is %s, Poll is %s, Shower is %s, Shower timer is %s, RxPgks=%d, TxPkgs=%d, #CrcErrors=%d",
myDebug("%sEMS-ESP-Boiler system stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" System Logging is set to ");
_EMS_SYS_LOGGING sysLog = ems_getLogging();
if (sysLog == EMS_SYS_LOGGING_BASIC) {
myDebug("Basic");
} else if (sysLog == EMS_SYS_LOGGING_VERBOSE) {
myDebug("Verbose");
} else {
myDebug("None");
}
myDebug("\n # EMS type handlers: %d\n", ems_getEmsTypesCount());
myDebug(" Thermostat is %s, Poll is %s, Shower timer is %s, Shower alert is %s\n",
((Boiler_Status.thermostat_enabled) ? "enabled" : "disabled"),
((EMS_Sys_Status.emsPollEnabled) ? "enabled" : "disabled"),
((Boiler_Status.shower_enabled) ? "enabled" : "disabled"),
((Boiler_Status.shower_timer) ? "enabled" : "disabled"),
((Boiler_Status.shower_alert) ? "enabled" : "disabled"));
myDebug(" EMS Bus Stats: Connected=%s, # Rx telegrams=%d, # Tx telegrams=%d, # Crc Errors=%d, ",
(Boiler_Status.boiler_online ? "yes" : "no"),
EMS_Sys_Status.emsRxPgks,
EMS_Sys_Status.emsTxPkgs,
EMS_Sys_Status.emxCrcErr);
myDebug(", RxStatus=");
myDebug("Rx Status=");
switch (EMS_Sys_Status.emsRxStatus) {
case EMS_RX_IDLE:
myDebug("idle");
@@ -104,7 +188,7 @@ void showInfo() {
break;
}
myDebug(", TxStatus=");
myDebug(", Tx Status=");
switch (EMS_Sys_Status.emsTxStatus) {
case EMS_TX_IDLE:
myDebug("idle");
@@ -117,7 +201,7 @@ void showInfo() {
break;
}
myDebug(", TxAction=");
myDebug(", Last Tx Action=");
switch (EMS_TxTelegram.action) {
case EMS_TX_READ:
myDebug("read");
@@ -133,41 +217,42 @@ void showInfo() {
break;
}
myDebug("\nBoiler stats:\n");
myDebug("\n\n%sBoiler stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
// UBAMonitorWWMessage & UBAParameterWW
myDebug(" Warm Water activated: %s\n", (EMS_Boiler.wWActivated ? "yes" : "no"));
myDebug(" Warm Water selected temperature: %d C\n", EMS_Boiler.wWSelTemp);
myDebug(" Warm Water circulation pump available: %s\n", (EMS_Boiler.wWCircPump ? "yes" : "no"));
myDebug(" Warm Water desired temperature: %d C\n", EMS_Boiler.wWDesiredTemp);
myDebug(" Warm Water current temperature: %s C\n", _float_to_char(s, EMS_Boiler.wWCurTmp));
myDebug(" Warm Water # starts: %d times\n", EMS_Boiler.wWStarts);
// UBAParameterWW
_renderBoolValue("Warm Water activated", EMS_Boiler.wWActivated);
_renderBoolValue("Warm Water circulation pump available", EMS_Boiler.wWCircPump);
_renderIntValue("Warm Water selected temperature", "C", EMS_Boiler.wWSelTemp);
_renderIntValue("Warm Water desired temperature", "C", EMS_Boiler.wWDesiredTemp);
// UBAMonitorWWMessage
_renderFloatValue("Warm Water current temperature", "C", EMS_Boiler.wWCurTmp);
_renderIntValue("Warm Water # starts", "times", EMS_Boiler.wWStarts);
myDebug(" Warm Water active time: %d days %d hours %d minutes\n",
EMS_Boiler.wWWorkM / 1440,
(EMS_Boiler.wWWorkM % 1440) / 60,
EMS_Boiler.wWWorkM % 60);
myDebug(" Warm Water 3-way valve: %s\n", EMS_Boiler.wWHeat ? "on" : "off");
_renderBoolValue("Warm Water 3-way valve", EMS_Boiler.wWHeat);
// UBAMonitorFast
myDebug(" Selected flow temperature: %d C\n", EMS_Boiler.selFlowTemp);
myDebug(" Current flow temperature: %s C\n", _float_to_char(s, EMS_Boiler.curFlowTemp));
myDebug(" Return temperature: %s C\n", _float_to_char(s, EMS_Boiler.retTemp));
myDebug(" Gas: %s\n", EMS_Boiler.burnGas ? "on" : "off");
myDebug(" Boiler pump: %s\n", EMS_Boiler.heatPmp ? "on" : "off");
myDebug(" Fan: %s\n", EMS_Boiler.fanWork ? "on" : "off");
myDebug(" Ignition: %s\n", EMS_Boiler.ignWork ? "on" : "off");
myDebug(" Circulation pump: %s\n", EMS_Boiler.wWCirc ? "on" : "off");
myDebug(" Burner max power: %d %%\n", EMS_Boiler.selBurnPow);
myDebug(" Burner current power: %d %%\n", EMS_Boiler.curBurnPow);
myDebug(" Flame current: %s uA\n", _float_to_char(s, EMS_Boiler.flameCurr));
myDebug(" System pressure: %s bar\n", _float_to_char(s, EMS_Boiler.sysPress));
_renderIntValue("Selected flow temperature", "C", EMS_Boiler.selFlowTemp);
_renderFloatValue("Current flow temperature", "C", EMS_Boiler.curFlowTemp);
_renderFloatValue("Return temperature", "C", EMS_Boiler.retTemp);
_renderBoolValue("Gas", EMS_Boiler.burnGas);
_renderBoolValue("Boiler pump", EMS_Boiler.heatPmp);
_renderBoolValue("Fan", EMS_Boiler.fanWork);
_renderBoolValue("Ignition", EMS_Boiler.ignWork);
_renderBoolValue("Circulation pump", EMS_Boiler.wWCirc);
_renderIntValue("Burner selected max power", "%", EMS_Boiler.selBurnPow);
_renderIntValue("Burner current power", "%", EMS_Boiler.curBurnPow);
_renderFloatValue("Flame current", "uA", EMS_Boiler.flameCurr);
_renderFloatValue("System pressure", "bar", EMS_Boiler.sysPress);
// UBAMonitorSlow
myDebug(" Outside temperature: %s C\n", _float_to_char(s, EMS_Boiler.extTemp));
myDebug(" Boiler temperature: %s C\n", _float_to_char(s, EMS_Boiler.boilTemp));
myDebug(" Pump modulation: %d %%\n", EMS_Boiler.pumpMod);
myDebug(" # burner restarts: %d\n", EMS_Boiler.burnStarts);
_renderFloatValue("Outside temperature", "C", EMS_Boiler.extTemp);
_renderFloatValue("Boiler temperature", "C", EMS_Boiler.boilTemp);
_renderIntValue("Pump modulation", "%", EMS_Boiler.pumpMod);
_renderIntValue("Burner # restarts", "times", EMS_Boiler.burnStarts);
myDebug(" Total burner operating time: %d days %d hours %d minutes\n",
EMS_Boiler.burnWorkMin / 1440,
(EMS_Boiler.burnWorkMin % 1440) / 60,
@@ -179,7 +264,8 @@ void showInfo() {
// Thermostat stats
if (Boiler_Status.thermostat_enabled) {
myDebug("Thermostat stats:\n Thermostat time is %02d:%02d:%02d %d/%d/%d\n",
myDebug("\n%sThermostat stats:%s\n", COLOR_BOLD_ON, COLOR_BOLD_OFF);
myDebug(" Thermostat time is %02d:%02d:%02d %d/%d/%d\n",
EMS_Thermostat.hour,
EMS_Thermostat.minute,
EMS_Thermostat.second,
@@ -187,8 +273,8 @@ void showInfo() {
EMS_Thermostat.month,
EMS_Thermostat.year + 2000);
myDebug(" Setpoint room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.setpoint_roomTemp));
myDebug(" Current room temperature is %s C\n", _float_to_char(s, EMS_Thermostat.curr_roomTemp));
_renderFloatValue("Setpoint room temperature", "C", EMS_Thermostat.setpoint_roomTemp);
_renderFloatValue("Current room temperature", "C", EMS_Thermostat.curr_roomTemp);
myDebug(" Mode is set to ");
if (EMS_Thermostat.mode == 0) {
myDebug("low\n");
@@ -197,20 +283,10 @@ void showInfo() {
} else if (EMS_Thermostat.mode == 2) {
myDebug("clock/auto\n");
} else {
myDebug("<unknown>\n");
myDebug("?\n");
}
}
// show the Shower Info
if (Boiler_Status.shower_enabled) {
myDebug("Shower stats:\n Shower is %s\n", (Boiler_Shower.showerOn ? "on" : "off"));
char s[70];
uint8_t sec = (uint8_t)((Boiler_Shower.duration / 1000) % 60);
uint8_t min = (uint8_t)((Boiler_Shower.duration / (1000 * 60)) % 60);
sprintf(s, " Last shower duration was %d minutes and %d %s\n", min, sec, (sec == 1) ? "second" : "seconds");
myDebug(s);
}
myDebug("\n");
}
@@ -242,7 +318,7 @@ void _boilerInitCommands() {
settingsRegisterCommand(F("BOILER.LOGGING"), [](Embedis * e) {
if (e->argc < 2) {
DEBUG_MSG_P(PSTR("-ERROR: arg is 0 or 1\n"));
DEBUG_MSG_P(PSTR("-ERROR: arg is 0, 1 or 2\n"));
return;
}
@@ -269,43 +345,60 @@ void _boilerInitCommands() {
});
}
void _boilerMQTTCallback(unsigned int type, const char * topic, const char * payload) {
/*
if (type == MQTT_CONNECT_EVENT) {
char buffer[strlen(MQTT_TOPIC_LED) + 3];
snprintf_P(buffer, sizeof(buffer), PSTR("%s/+"), MQTT_TOPIC_LED);
mqttSubscribe(buffer);
}
// send values to HA via MQTT
void publishValues() {
char s[20]; // for formatting strings
if (type == MQTT_MESSAGE_EVENT) {
// Boiler values as one JSON object
StaticJsonBuffer<512> jsonBuffer;
char data[512];
JsonObject & root = jsonBuffer.createObject();
// Match topic
String t = mqttMagnitude((char *) topic);
if (!t.startsWith(MQTT_TOPIC_LED)) return;
root["wWSelTemp"] = _int_to_char(s, EMS_Boiler.wWSelTemp);
root["wWActivated"] = _bool_to_char(s, EMS_Boiler.wWActivated);
root["wWCurTmp"] = _float_to_char(s, EMS_Boiler.wWCurTmp);
root["wWHeat"] = _bool_to_char(s, EMS_Boiler.wWHeat);
root["curFlowTemp"] = _float_to_char(s, EMS_Boiler.curFlowTemp);
root["retTemp"] = _float_to_char(s, EMS_Boiler.retTemp);
root["burnGas"] = _bool_to_char(s, EMS_Boiler.burnGas);
root["heatPmp"] = _bool_to_char(s, EMS_Boiler.heatPmp);
root["fanWork"] = _bool_to_char(s, EMS_Boiler.fanWork);
root["ignWork"] = _bool_to_char(s, EMS_Boiler.ignWork);
root["wWCirc"] = _bool_to_char(s, EMS_Boiler.wWCirc);
root["selBurnPow"] = _int_to_char(s, EMS_Boiler.selBurnPow);
root["curBurnPow"] = _int_to_char(s, EMS_Boiler.curBurnPow);
root["sysPress"] = _float_to_char(s, EMS_Boiler.sysPress);
root["boilTemp"] = _float_to_char(s, EMS_Boiler.boilTemp);
root["pumpMod"] = _int_to_char(s, EMS_Boiler.pumpMod);
// Get led ID
unsigned int ledID = t.substring(strlen(MQTT_TOPIC_LED)+1).toInt();
if (ledID >= _ledCount()) {
DEBUG_MSG_P(PSTR("[LED] Wrong ledID (%d)\n"), ledID);
size_t len = root.measureLength();
root.printTo(data, len + 1); // form the json string
mqttSend(TOPIC_BOILER_DATA, data);
// handle the thermostat values separately
if (EMS_Sys_Status.emsThermostatEnabled) {
// only send thermostat values if we actually have them
if (((int)EMS_Thermostat.curr_roomTemp == (int)0) || ((int)EMS_Thermostat.setpoint_roomTemp == (int)0)) {
return;
}
// Check if LED is managed
if (_ledMode(ledID) != LED_MODE_MQTT) return;
mqttSend(TOPIC_THERMOSTAT_CURRTEMP, _float_to_char(s, EMS_Thermostat.curr_roomTemp));
mqttSend(TOPIC_THERMOSTAT_SELTEMP, _float_to_char(s, EMS_Thermostat.setpoint_roomTemp));
// get value
unsigned char value = relayParsePayload(payload);
// Action to perform
if (value == 2) {
_ledToggle(ledID);
// send mode 0=low, 1=manual, 2=clock/auto
if (EMS_Thermostat.mode == 0) {
mqttSend(TOPIC_THERMOSTAT_MODE, "low");
} else if (EMS_Thermostat.mode == 1) {
mqttSend(TOPIC_THERMOSTAT_MODE, "manual");
} else {
_ledStatus(ledID, value == 1);
mqttSend(TOPIC_THERMOSTAT_MODE, "auto"); // must be auto
}
}
*/
}
void _boilerMQTTCallback(unsigned int type, const char * topic, const char * payload) {
}
// TELNET commands
@@ -330,19 +423,18 @@ void boilerSetup() {
_boilerConfigure();
wsOnSendRegister(_boilerWebSocketOnSend);
wsOnAfterParseRegister(_boilerConfigure);
wsOnActionRegister(_boilerWebSocketOnAction);
wsOnReceiveRegister(_boilerWebSocketOnReceive);
mqttRegister(_boilerMQTTCallback);
_boilerInitCommands();
_boilerInitCommands(); // telnet
// init shower
Boiler_Shower.timerStart = 0;
Boiler_Shower.timerPause = 0;
Boiler_Shower.duration = 0;
Boiler_Shower.isColdShot = false;
Boiler_Shower.timerStart = 0;
Boiler_Shower.timerPause = 0;
Boiler_Shower.duration = 0;
Boiler_Shower.doingColdShot = false;
// ems init values
ems_init();
@@ -352,8 +444,22 @@ void boilerSetup() {
// Register loop
espurnaRegisterLoop(_boilerLoop);
espurnaRegisterReload([]() { _boilerConfigure(); });
}
// LOOP
void _boilerLoop() {
static unsigned long last_boilersend = 0;
if ((last_boilersend == 0) || (millis() - last_boilersend > BOILERSEND_INTERVAL)) {
last_boilersend = millis();
// get 0x33 WW values manually
ems_doReadCommand(EMS_TYPE_UBAParameterWW);
#if MQTT_SUPPORT
// send MQTT
publishValues();
#endif
}
}

View File

@@ -5,9 +5,6 @@
#undef EMBEDDED_WEB
#define EMBEDDED_WEB 1
#undef NTP_SERVER
#define NTP_SERVER "nl.pool.ntp.org"
//#undef MQTT_TOPIC
//#define MQTT_TOPIC "/{identifier}"
// default is "{hostname}"

File diff suppressed because it is too large Load Diff

Binary file not shown.

BIN
firmware/nodemcu2.bin Normal file

Binary file not shown.

Binary file not shown.

BIN
firmware/wemos-d1mini.bin Normal file

Binary file not shown.