mirror of
https://github.com/emsesp/EMS-ESP32.git
synced 2025-12-06 07:49:52 +03:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
12
CHANGELOG.md
12
CHANGELOG.md
@@ -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
|
||||
|
||||
10
README.md
10
README.md
@@ -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.
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
@@ -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,7 +191,7 @@ class MyESP {
|
||||
void _telnetCommand(char * commandLine);
|
||||
char * _telnet_readWord();
|
||||
void _telnet_setup();
|
||||
char * _command; // the input command from either Serial or Telnet
|
||||
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();
|
||||
|
||||
@@ -61,6 +61,8 @@ 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 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);
|
||||
@@ -951,6 +975,8 @@ void initEMSESP() {
|
||||
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
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
#define EMSUART_recvTaskQueueLen 64
|
||||
|
||||
typedef struct {
|
||||
int16_t writePtr;
|
||||
uint8_t writePtr;
|
||||
uint8_t buffer[EMS_MAXBUFFERSIZE];
|
||||
} _EMSRxBuf;
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user