Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Glenn Arens
2019-03-11 18:01:14 +01:00
11 changed files with 105 additions and 52 deletions

View File

@@ -5,6 +5,18 @@ 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/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.5.6] 2019-03-09
### Added
- test_mode option
### Changed
- upgraded MyESP library
- minor changes
## [1.5.5] 2019-03-07
### Fixed

View File

@@ -341,19 +341,17 @@ Porting to the Arduino IDE can be a little tricky but it did it once. Something
## Using the Pre-built Firmware
pre-baked firmwares for some ESP8266 devices are available in the directory `/firmware` which you can upload yourself using [esptool](https://github.com/espressif/esptool) bootloader. On Windows, follow these instructions:
pre-baked firmware for the Wemos D1 mini is available in the GitHub [releases](https://github.com/proddy/EMS-ESP/releases) which you can upload yourself using the [esptool](https://github.com/espressif/esptool) bootloader like `esptool.py -p <com port> write_flash 0x00000 <firmware.bin file>`. Here's how to set it up on Windows:
1. Check if you have **python 2.7** installed. If not [download it](https://www.python.org/downloads/) and make sure you select the option to add Python to the windows PATH
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`
2. Then install the ESPTool by running `pip install esptool` from a command prompt
The ESP8266 will start in Access Point (AP) mode. Connect via WiFi to the SSID **EMS-ESP** and telnet to **192.168.4.1**. Then use the `set wifi` command to configure your own network settings like `set wifi your_ssid your_password`. Alternatively connect the ESP8266 to your PC and open a Serial monitor (with baud 115200) to configure the settings. Make sure you disable Serial support before connecting the EMS lines using `set serial off`.
`set erase` will clear all settings.
`set` wil list all currently stored settings.
`set erase` will clear all settings.
## Troubleshooting
When flashing for the first time the Serial port is enabled by default with baud 115200. You can then use a PC with USB to the ESP8266 to set the settings like wifi, mqtt etc and also monitor the boot up procedure. Remember to disable the serial (`set serial off`) when connecting to the EMS lines.

Binary file not shown.

View File

@@ -106,14 +106,14 @@ void TelnetSpy::setPort(uint16_t portToUse) {
}
}
void TelnetSpy::setWelcomeMsg(char * msg) {
void TelnetSpy::setWelcomeMsg(const char * msg) {
if (welcomeMsg) {
free(welcomeMsg);
}
welcomeMsg = strdup(msg);
}
void TelnetSpy::setRejectMsg(char * msg) {
void TelnetSpy::setRejectMsg(const char * msg) {
if (rejectMsg) {
free(rejectMsg);
}
@@ -434,22 +434,24 @@ TelnetSpy::operator bool() const {
void TelnetSpy::setDebugOutput(bool en) {
debugOutput = en;
// TODO: figure out how to disable system printing for the ESP32
if (debugOutput) {
actualObject = this;
#ifdef ESP8266
os_install_putc1((void *)TelnetSpy_putc); // Set system printing (os_printf) to TelnetSpy
system_set_os_print(true);
#else // ESP32 \
// ToDo: How can be done this for ESP32 ?
#endif
} else {
if (actualObject == this) {
#ifdef ESP8266
system_set_os_print(false);
os_install_putc1((void *)TelnetSpy_ignore_putc); // Ignore system printing
#else // ESP32 \
// ToDo: How can be done this for ESP32 ?
#endif
actualObject = NULL;
}
}

View File

@@ -174,8 +174,8 @@ class TelnetSpy : public Stream {
~TelnetSpy();
void handle(void);
void setPort(uint16_t portToUse);
void setWelcomeMsg(char * msg);
void setRejectMsg(char * msg);
void setWelcomeMsg(const char * msg);
void setRejectMsg(const char * msg);
void setMinBlockSize(uint16_t minSize);
void setCollectingTime(uint16_t colTime);
void setMaxBlockSize(uint16_t maxSize);

View File

@@ -33,7 +33,6 @@ MyESP::MyESP() {
_helpProjectCmds = NULL;
_helpProjectCmds_count = 0;
_command = (char *)malloc(TELNET_MAX_COMMAND_LENGTH); // reserve buffer for Serial/Telnet commands
_use_serial = true;
_mqtt_host = NULL;
@@ -65,7 +64,6 @@ MyESP::~MyESP() {
// end
void MyESP::end() {
free(_command);
SerialAndTelnet.end();
jw.disconnect();
}
@@ -266,7 +264,8 @@ void MyESP::_mqtt_setup() {
mqttClient.onDisconnect([this](AsyncMqttClientDisconnectReason reason) {
if (reason == AsyncMqttClientDisconnectReason::TCP_DISCONNECTED) {
myDebug_P(PSTR("[MQTT] TCP Disconnected. Check mqtt logs."));
(_mqtt_callback)(MQTT_DISCONNECT_EVENT, NULL, NULL); // call callback with disconnect
(_mqtt_callback)(MQTT_DISCONNECT_EVENT, NULL,
NULL); // call callback with disconnect
}
if (reason == AsyncMqttClientDisconnectReason::MQTT_IDENTIFIER_REJECTED) {
myDebug_P(PSTR("[MQTT] Identifier Rejected"));
@@ -391,7 +390,7 @@ void MyESP::_telnetDisconnected() {
// Initialize the telnet server
void MyESP::_telnet_setup() {
SerialAndTelnet.setWelcomeMsg((char *)"");
SerialAndTelnet.setWelcomeMsg("");
SerialAndTelnet.setCallbackOnConnect([this]() { _telnetConnected(); });
SerialAndTelnet.setCallbackOnDisconnect([this]() { _telnetDisconnected(); });
SerialAndTelnet.setDebugOutput(false);
@@ -738,9 +737,7 @@ void MyESP::_telnetHandle() {
while (SerialAndTelnet.available()) {
char c = SerialAndTelnet.read();
if (_use_serial) {
SerialAndTelnet.serialPrint(c); // echo to Serial if connected
}
SerialAndTelnet.serialPrint(c); // echo to Serial if connected
switch (c) {
case '\r': // likely have full command in buffer now, commands are terminated by CR and/or LF
@@ -750,17 +747,24 @@ void MyESP::_telnetHandle() {
charsRead = 0; // is static, so have to reset
_suspendOutput = false;
if (_use_serial) {
SerialAndTelnet.println(); // force newline if in Telnet
SerialAndTelnet.serialPrint('\n'); // force newline if in Serial
}
_telnetCommand(_command);
}
break;
case '\b': // handle backspace in input: put a space in last char
case '\b': // (^H) handle backspace in input: put a space in last char - coded by Simon Arlott
case 0x7F: // (^?)
if (charsRead > 0) {
_command[--charsRead] = '\0';
SerialAndTelnet << byte('\b') << byte(' ') << byte('\b');
SerialAndTelnet.write(' ');
SerialAndTelnet.write('\b');
}
break;
case '?':
if (!_suspendOutput) {
_consoleShowHelp();
@@ -814,7 +818,8 @@ void MyESP::_mqttConnect() {
// last will
if (_mqtt_will_topic) {
//myDebug_P(PSTR("[MQTT] Setting last will topic %s"), _mqttTopic(_mqtt_will_topic));
mqttClient.setWill(_mqttTopic(_mqtt_will_topic), 1, true, _mqtt_will_offline_payload); // retain always true
mqttClient.setWill(_mqttTopic(_mqtt_will_topic), 1, true,
_mqtt_will_offline_payload); // retain always true
}
if (_mqtt_username && _mqtt_password) {
@@ -955,7 +960,8 @@ void MyESP::_fs_printConfig() {
// format File System
void MyESP::_fs_eraseConfig() {
myDebug_P(PSTR("[FS] Erasing settings, please wait a few seconds. ESP will automatically restart when finished."));
myDebug_P(PSTR("[FS] Erasing settings, please wait a few seconds. ESP will "
"automatically restart when finished."));
if (SPIFFS.format()) {
delay(1000); // wait 1 seconds
@@ -1037,6 +1043,12 @@ bool MyESP::fs_saveConfig() {
// callback for saving custom settings
(void)(_fs_callback)(MYESP_FSACTION_SAVE, json);
// if file exists, remove it just to be safe
if (SPIFFS.exists(MYEMS_CONFIG_FILE)) {
// delete it
SPIFFS.remove(MYEMS_CONFIG_FILE);
}
File configFile = SPIFFS.open(MYEMS_CONFIG_FILE, "w");
if (!configFile) {
Serial.println("[FS] Failed to open config file for writing");
@@ -1069,7 +1081,7 @@ void MyESP::_fs_setup() {
fs_saveConfig();
}
// _fs_printConfig(); // TODO: for debugging
//_fs_printConfig(); // TODO: for debugging
}
uint16_t MyESP::getSystemLoadAverage() {

View File

@@ -9,7 +9,7 @@
#ifndef MyEMS_h
#define MyEMS_h
#define MYESP_VERSION "1.1.4"
#define MYESP_VERSION "1.1.5"
#include <ArduinoJson.h>
#include <ArduinoOTA.h>
@@ -68,7 +68,7 @@
#define COLOR_CYAN "\x1B[0;36m"
#define COLOR_WHITE "\x1B[0;37m"
#define COLOR_BOLD_ON "\x1B[1m"
#define COLOR_BOLD_OFF "\x1B[21m"
#define COLOR_BOLD_OFF "\x1B[22m" // fixed by Scott Arlott
// SPIFFS
#define SPIFFS_MAXSIZE 500 // https://arduinojson.org/v5/assistant/
@@ -191,9 +191,9 @@ class MyESP {
void _telnetCommand(char * commandLine);
char * _telnet_readWord();
void _telnet_setup();
char * _command; // the input command from either Serial or Telnet
command_t * _helpProjectCmds; // Help of commands setted by project
uint8_t _helpProjectCmds_count; // # available commands
char _command[TELNET_MAX_COMMAND_LENGTH]; // the input command from either Serial or Telnet
command_t * _helpProjectCmds; // Help of commands setted by project
uint8_t _helpProjectCmds_count; // # available commands
void _consoleShowHelp();
telnetcommand_callback_f _telnetcommand_callback; // Callable for projects commands
telnet_callback_f _telnet_callback; // callback for connect/disconnect

View File

@@ -58,9 +58,11 @@ Ticker showerColdShotStopTimer;
#define SHOWER_COLDSHOT_DURATION 10 // in seconds. 10 seconds for cold water before turning back hot water
typedef struct {
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 led_enabled; // LED on/off
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 led_enabled; // LED on/off
bool test_mode; // test mode to stop automatic Tx on/off
unsigned long timestamp; // for internal timings, via millis()
uint8_t dallas_sensors; // count of dallas sensors
uint8_t led_gpio;
@@ -82,9 +84,10 @@ command_t PROGMEM project_cmds[] = {
{"set dallas_gpio <pin>", "set the pin for external Dallas temperature sensors (D5=14)"},
{"set thermostat_type <type ID>", "set the thermostat type id (e.g. 10 for 0x10)"},
{"set boiler_type <type ID>", "set the boiler type id (e.g. 8 for 0x08)"},
{"set test_mode <on | off>", "test_mode turns off all automatic reads"},
{"info", "show data captured on the EMS bus"},
{"log <n | b | t | r | v>", "set logging mode to none, basic, thermostat only, raw or verbose"},
{"publish", "forice a publish of all values to MQTT"},
{"publish", "publish all values to MQTT"},
{"types", "list supported EMS telegram type IDs"},
{"queue", "show current Tx queue"},
{"autodetect", "discover EMS devices and attempt to automatically set boiler and thermostat"},
@@ -261,6 +264,7 @@ void showInfo() {
}
myDebug(" LED is %s", EMSESP_Status.led_enabled ? "on" : "off");
myDebug(" Test Mode is %s", EMSESP_Status.test_mode ? "on" : "off");
myDebug(" # connected Dallas temperature sensors=%d", EMSESP_Status.dallas_sensors);
@@ -469,8 +473,7 @@ void publishValues(bool force) {
}
// handle the thermostat values separately
//if (ems_getThermostatEnabled()) {
if (true) {
if (ems_getThermostatEnabled()) {
// 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;
@@ -607,6 +610,11 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
EMS_Boiler.type_id = EMSESP_BOILER_TYPE; // set default
}
// test mode
if (!(EMSESP_Status.test_mode = json["test_mode"])) {
EMSESP_Status.test_mode = false; // default value
}
return false; // always save the settings
}
@@ -616,9 +624,12 @@ bool FSCallback(MYESP_FSACTION action, const JsonObject json) {
json["dallas_gpio"] = EMSESP_Status.dallas_gpio;
json["thermostat_type"] = EMS_Thermostat.type_id;
json["boiler_type"] = EMS_Boiler.type_id;
json["test_mode"] = EMSESP_Status.test_mode;
return true;
}
return false;
}
// callback for custom settings when showing Stored Settings
@@ -641,6 +652,18 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
}
}
// test mode
if ((strcmp(setting, "test_mode") == 0) && (wc == 2)) {
if (strcmp(value, "on") == 0) {
EMSESP_Status.test_mode = true;
ok = true;
myDebug("* Reboot to go into test mode.");
} else if (strcmp(value, "off") == 0) {
EMSESP_Status.test_mode = false;
ok = true;
}
}
// led_gpio
if ((strcmp(setting, "led_gpio") == 0) && (wc == 2)) {
EMSESP_Status.led_gpio = atoi(value);
@@ -670,6 +693,7 @@ bool SettingsCallback(MYESP_FSACTION action, uint8_t wc, const char * setting, c
}
if (action == MYESP_FSACTION_LIST) {
myDebug(" test_mode=%s", EMSESP_Status.test_mode ? "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);
@@ -948,9 +972,11 @@ void WIFICallback() {
// Initialize the boiler settings and shower settings
void initEMSESP() {
// general settings
EMSESP_Status.shower_timer = BOILER_SHOWER_TIMER;
EMSESP_Status.shower_alert = BOILER_SHOWER_ALERT;
EMSESP_Status.led_enabled = true; // LED is on by default
EMSESP_Status.shower_timer = BOILER_SHOWER_TIMER;
EMSESP_Status.shower_alert = BOILER_SHOWER_ALERT;
EMSESP_Status.led_enabled = true; // LED is on by default
EMSESP_Status.test_mode = false;
EMSESP_Status.timestamp = millis();
EMSESP_Status.dallas_sensors = 0;
@@ -1108,10 +1134,7 @@ void setup() {
// call ems.cpp's init function to set all the internal params
ems_init();
// Timers using Ticker library
publishValuesTimer.attach(PUBLISHVALUES_TIME, do_publishValues); // post MQTT values
systemCheckTimer.attach(SYSTEMCHECK_TIME, do_systemCheck); // check if Boiler is online
regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS
systemCheckTimer.attach(SYSTEMCHECK_TIME, do_systemCheck); // check if Boiler is online
// set up myESP for Wifi, MQTT, MDNS and Telnet
myESP.setTelnet(project_cmds, ArraySize(project_cmds), TelnetCommandCallback, TelnetCallback); // set up Telnet commands
@@ -1143,6 +1166,12 @@ void setup() {
// start up all the services
myESP.begin(APP_HOSTNAME, APP_NAME, APP_VERSION);
// enable regular checks if not in test mode
if (!EMSESP_Status.test_mode) {
publishValuesTimer.attach(PUBLISHVALUES_TIME, do_publishValues); // post MQTT values
regularUpdatesTimer.attach(REGULARUPDATES_TIME, do_regularUpdates); // regular reads from the EMS
}
// set pin for LED
if (EMSESP_Status.led_gpio != EMS_VALUE_INT_NOTSET) {
pinMode(EMSESP_Status.led_gpio, OUTPUT);
@@ -1170,7 +1199,7 @@ void loop() {
// publish the values to MQTT, only if the values have changed
// although we don't want to publish when doing a deep scan of the thermostat
if (ems_getEmsRefreshed() && (scanThermostat_count == 0)) {
if (ems_getEmsRefreshed() && (scanThermostat_count == 0) && (!EMSESP_Status.test_mode)) {
publishValues(false);
ems_setEmsRefreshed(false); // reset
}

View File

@@ -884,7 +884,7 @@ void _processType(uint8_t * telegram, uint8_t length) {
* Check if hot tap water or heating is active
* using a quick hack for checking the heating. Selected Flow Temp >= 70
*/
bool _checkActive() {
void _checkActive() {
// hot tap water, using flow to check insread of the burner power
EMS_Boiler.tapwaterActive = ((EMS_Boiler.wWCurFlow != 0) && (EMS_Boiler.burnGas == EMS_VALUE_INT_ON));
@@ -969,7 +969,7 @@ void _process_UBAMonitorFast(uint8_t type, uint8_t * data, uint8_t length) {
}
// at this point do a quick check to see if the hot water or heating is active
(void)_checkActive();
_checkActive();
}
/**
@@ -1587,13 +1587,13 @@ void ems_sendRawTelegram(char * telegram) {
EMS_Sys_Status.txRetryCount = 0; // reset retry counter
// get first value, which should be the src
if (p = strtok(telegram, " ,")) { // delimiter
if ( (p = strtok(telegram, " ,")) ) { // delimiter
strlcpy(value, p, sizeof(value));
EMS_TxTelegram.data[0] = (uint8_t)strtol(value, 0, 16);
}
// and interate until end
while (p != 0) {
if (p = strtok(NULL, " ,")) {
if ( (p = strtok(NULL, " ,")) ) {
strlcpy(value, p, sizeof(value));
uint8_t val = (uint8_t)strtol(value, 0, 16);
EMS_TxTelegram.data[++count] = val;

View File

@@ -25,7 +25,7 @@
#define EMSUART_recvTaskQueueLen 64
typedef struct {
int16_t writePtr;
uint8_t writePtr;
uint8_t buffer[EMS_MAXBUFFERSIZE];
} _EMSRxBuf;

View File

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