Merge branch 'dev2' of https://github.com/emsesp/EMS-ESP32 into dev2

This commit is contained in:
MichaelDvP
2023-07-14 19:15:28 +02:00
29 changed files with 1140 additions and 413 deletions

19
.vscode/tasks.json vendored
View File

@@ -4,20 +4,15 @@
"version": "2.0.0", "version": "2.0.0",
"tasks": [ "tasks": [
{ {
"label": "PlatformIO: Execute EMS-ESP (standalone)",
"type": "shell", "type": "shell",
"command": "./.pio/build/standalone/program", "label": "build standalone emsesp",
"linux": { "command": "make",
"options": { "args": [],
"env": { "problemMatcher": ["$gcc"],
// Workaround for sdl2 `-m32` crash "group": {
// https://bugs.launchpad.net/ubuntu/+source/libsdl2/+bug/1775067/comments/7 "kind": "build",
"DBUS_FATAL_WARNINGS": "0" "isDefault": true
} }
} }
},
"dependsOn": ["PlatformIO: Build EMS-ESP (standalone)"],
"problemMatcher": []
}
] ]
} }

View File

@@ -17,13 +17,13 @@ MAKEFLAGS+="j "
#TARGET := $(notdir $(CURDIR)) #TARGET := $(notdir $(CURDIR))
TARGET := emsesp TARGET := emsesp
BUILD := build BUILD := build
SOURCES := src src/* lib_standalone lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src src/devices lib/ArduinoJson/src lib/PButton lib/semver SOURCES := src src/* lib_standalone lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src src/devices lib/ArduinoJson/src lib/PButton lib/semver lib/espMqttClient/src lib/espMqttClient/src/*
INCLUDES := src lib_standalone lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src lib/semver lib/* src/devices INCLUDES := src lib_standalone lib/espMqttClient/src lib/espMqttClient/src/Transport lib/ArduinoJson/src lib/uuid-common/src lib/uuid-console/src lib/uuid-log/src lib/uuid-telnet/src lib/uuid-syslog/src lib/semver lib/* src/devices
LIBRARIES := LIBRARIES :=
CPPCHECK = cppcheck CPPCHECK = cppcheck
# CHECKFLAGS = -q --force --std=c++17 # CHECKFLAGS = -q --force --std=c++17
CHECKFLAGS = -q --force --std=c++11 CHECKFLAGS = -q --force --std=c++11 -pthread
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Languages Standard # Languages Standard
@@ -36,8 +36,8 @@ CXX_STANDARD := -std=c++11
#---------------------------------------------------------------------- #----------------------------------------------------------------------
# Defined Symbols # Defined Symbols
#---------------------------------------------------------------------- #----------------------------------------------------------------------
DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0 -DARDUINO DEFINES += -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST DEFINES += -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -D__linux__ -DEMC_RX_BUFFER_SIZE=1500
DEFINES += $(ARGS) DEFINES += $(ARGS)
DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" DEFAULTS = -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
@@ -79,7 +79,7 @@ CPPFLAGS += -g3
CPPFLAGS += -Os CPPFLAGS += -Os
CFLAGS += $(CPPFLAGS) CFLAGS += $(CPPFLAGS)
CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter -Wno-inconsistent-missing-override -Wno-unused-lambda-capture CFLAGS += -Wall -Wextra -Werror -Wswitch-enum -Wno-unused-parameter
CXXFLAGS += $(CFLAGS) -MMD CXXFLAGS += $(CFLAGS) -MMD

View File

@@ -52,6 +52,7 @@
"@preact/preset-vite": "^2.5.0", "@preact/preset-vite": "^2.5.0",
"@typescript-eslint/eslint-plugin": "^6.0.0", "@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0", "@typescript-eslint/parser": "^6.0.0",
"cspell": "^6.31.1",
"eslint": "^8.44.0", "eslint": "^8.44.0",
"eslint-config-airbnb": "^19.0.4", "eslint-config-airbnb": "^19.0.4",
"eslint-config-airbnb-typescript": "^17.1.0", "eslint-config-airbnb-typescript": "^17.1.0",
@@ -68,7 +69,7 @@
"prettier": "^3.0.0", "prettier": "^3.0.0",
"rollup-plugin-visualizer": "^5.9.2", "rollup-plugin-visualizer": "^5.9.2",
"terser": "^5.19.0", "terser": "^5.19.0",
"vite": "^4.4.3", "vite": "^4.4.4",
"vite-plugin-svgr": "^3.2.0", "vite-plugin-svgr": "^3.2.0",
"vite-tsconfig-paths": "^4.2.0" "vite-tsconfig-paths": "^4.2.0"
}, },

View File

@@ -1,5 +1,5 @@
/* /*
* Uses font-size 400 (normal) only and Latin (plus extra unicode chars) to keep flash memory to a minimun * Uses font-size 400 (normal) only and Latin (plus extra unicode chars) to keep flash memory to a minimum
* View fonts on https://fonts.google.com/ * View fonts on https://fonts.google.com/
* Download woff2 using e.g. https://fonts.googleapis.com/css2?family=Lato or https://fonts.googleapis.com/css2?family=Roboto * Download woff2 using e.g. https://fonts.googleapis.com/css2?family=Lato or https://fonts.googleapis.com/css2?family=Roboto
*/ */

View File

@@ -21,22 +21,22 @@ export const fetchLog = () => alovaInstance.Post('/rest/fetchLog');
// Get versions from github // Get versions from github
export const getStableVersion = () => export const getStableVersion = () =>
alovaInstanceGH.Get<Version>('releases/latest', { alovaInstanceGH.Get<Version>('releases/latest', {
transformData(reponse: any) { transformData(response: any) {
return { return {
version: reponse.data.name, version: response.data.name,
url: reponse.data.assets[1].browser_download_url, url: response.data.assets[1].browser_download_url,
changelog: reponse.data.assets[0].browser_download_url changelog: response.data.assets[0].browser_download_url
}; };
} }
}); });
export const getDevVersion = () => export const getDevVersion = () =>
alovaInstanceGH.Get<Version>('releases/tags/latest', { alovaInstanceGH.Get<Version>('releases/tags/latest', {
transformData(reponse: any) { transformData(response: any) {
return { return {
version: reponse.data.name.split(/\s+/).splice(-1), version: response.data.name.split(/\s+/).splice(-1),
url: reponse.data.assets[1].browser_download_url, url: response.data.assets[1].browser_download_url,
changelog: reponse.data.assets[0].browser_download_url changelog: response.data.assets[0].browser_download_url
}; };
} }
}); });

File diff suppressed because it is too large Load Diff

View File

@@ -123,7 +123,8 @@ class MqttClient {
#elif defined(ARDUINO_ARCH_ESP8266) && EMC_ESP8266_MULTITHREADING #elif defined(ARDUINO_ARCH_ESP8266) && EMC_ESP8266_MULTITHREADING
std::atomic<bool> _xSemaphore = false; std::atomic<bool> _xSemaphore = false;
#elif defined(__linux__) #elif defined(__linux__)
std::mutex mtx; // added mutable to compile EMS-ESP standalone
mutable std::mutex mtx;
#endif #endif
uint8_t _rxBuffer[EMC_RX_BUFFER_SIZE]; uint8_t _rxBuffer[EMC_RX_BUFFER_SIZE];
@@ -131,9 +132,10 @@ class MqttClient {
uint32_t timeSent; uint32_t timeSent;
espMqttClientInternals::Packet packet; espMqttClientInternals::Packet packet;
template <typename... Args> template <typename... Args>
OutgoingPacket(uint32_t t, espMqttClientTypes::Error error, Args&&... args) : OutgoingPacket(uint32_t t, espMqttClientTypes::Error error, Args &&... args)
timeSent(t), : timeSent(t)
packet(error, std::forward<Args>(args) ...) {} , packet(error, std::forward<Args>(args)...) {
}
}; };
espMqttClientInternals::Outbox<OutgoingPacket> _outbox; espMqttClientInternals::Outbox<OutgoingPacket> _outbox;
size_t _bytesSent; size_t _bytesSent;
@@ -149,7 +151,8 @@ class MqttClient {
bool _addPacket(Args &&... args) { bool _addPacket(Args &&... args) {
espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS); espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS);
espMqttClientInternals::Outbox<OutgoingPacket>::Iterator it = _outbox.emplace(0, error, std::forward<Args>(args)...); espMqttClientInternals::Outbox<OutgoingPacket>::Iterator it = _outbox.emplace(0, error, std::forward<Args>(args)...);
if (it && error == espMqttClientTypes::Error::SUCCESS) return true; if (it && error == espMqttClientTypes::Error::SUCCESS)
return true;
return false; return false;
} }
@@ -157,7 +160,8 @@ class MqttClient {
bool _addPacketFront(Args &&... args) { bool _addPacketFront(Args &&... args) {
espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS); espMqttClientTypes::Error error(espMqttClientTypes::Error::SUCCESS);
espMqttClientInternals::Outbox<OutgoingPacket>::Iterator it = _outbox.emplaceFront(0, error, std::forward<Args>(args)...); espMqttClientInternals::Outbox<OutgoingPacket>::Iterator it = _outbox.emplaceFront(0, error, std::forward<Args>(args)...);
if (it && error == espMqttClientTypes::Error::SUCCESS) return true; if (it && error == espMqttClientTypes::Error::SUCCESS)
return true;
return false; return false;
} }

View File

@@ -172,14 +172,14 @@ void MqttSettingsService::WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info) {
} }
bool MqttSettingsService::configureMqtt() { bool MqttSettingsService::configureMqtt() {
// disconnect if connected // disconnect if already connected
if (_mqttClient->connected()) { if (_mqttClient->connected()) {
emsesp::EMSESP::logger().info("Disconneting to configure"); emsesp::EMSESP::logger().info("Disconnecting to configure");
_mqttClient->disconnect(true); _mqttClient->disconnect(true);
} }
// only connect if WiFi is connected and MQTT is enabled // only connect if WiFi is connected and MQTT is enabled
if (_state.enabled && emsesp::EMSESP::system_.network_connected() && !_state.host.isEmpty()) { if (_state.enabled && emsesp::EMSESP::system_.network_connected() && !_state.host.isEmpty()) {
// if (_state.enabled && !_state.host.isEmpty()) {
_reconfigureMqtt = false; _reconfigureMqtt = false;
#if CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_IDF_TARGET_ESP32S3
if (_state.rootCA.length() > 0) { if (_state.rootCA.length() > 0) {
@@ -212,6 +212,7 @@ bool MqttSettingsService::configureMqtt() {
static_cast<espMqttClient *>(_mqttClient)->setCleanSession(_state.cleanSession); static_cast<espMqttClient *>(_mqttClient)->setCleanSession(_state.cleanSession);
return _mqttClient->connect(); return _mqttClient->connect();
} }
return false; return false;
} }

View File

@@ -21,6 +21,10 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <iostream>
#include <thread>
#include <atomic>
#include <string> #include <string>
#include <Network.h> #include <Network.h>
@@ -43,17 +47,33 @@ static unsigned long __millis = 0;
static bool __output_pins[256]; static bool __output_pins[256];
static int __output_level[256]; static int __output_level[256];
int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) { std::atomic_bool exitProgram(false);
setup();
while (millis() <= 10 * 1000) { void ClientLoop(void * arg) {
(void)arg;
for (;;) {
loop(); loop();
if (exitProgram)
break;
} }
return 0;
} }
unsigned long millis() { int main(int argc __attribute__((unused)), char * argv[] __attribute__((unused))) {
return __millis; setup();
std::thread t = std::thread(ClientLoop, nullptr);
// while (millis() <= 10 * 1000) {
while (1) {
if (exitProgram)
break;
std::this_thread::yield();
} }
t.join();
return EXIT_SUCCESS;
}
// unsigned long millis() {
// return __millis;
// }
int64_t esp_timer_get_time() { int64_t esp_timer_get_time() {
return __millis; return __millis;
@@ -64,6 +84,7 @@ void delay(unsigned long millis) {
} }
void yield(void) { void yield(void) {
std::this_thread::yield();
} }
int snprintf_P(char * str, size_t size, const char * format, ...) { int snprintf_P(char * str, size_t size, const char * format, ...) {

View File

@@ -35,7 +35,7 @@
#include <iostream> #include <iostream>
// #define IPAddress std::string // #define IPAddress std::string
#define IPAddress String // #define IPAddress String
#define ICACHE_FLASH_ATTR #define ICACHE_FLASH_ATTR
#define ICACHE_RAM_ATTR #define ICACHE_RAM_ATTR
@@ -171,7 +171,13 @@ extern NativeConsole Serial;
extern ETHClass ETH; extern ETHClass ETH;
extern WiFiClass WiFi; extern WiFiClass WiFi;
unsigned long millis(); // unsigned long millis();
#if defined(__linux__)
#include <chrono> // NOLINT [build/c++11]
#include <thread> // NOLINT [build/c++11] for yield()
#define millis() std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch()).count()
#endif
int64_t esp_timer_get_time(); int64_t esp_timer_get_time();

View File

@@ -101,7 +101,10 @@ class ESP8266React {
: _settings(server, fs, nullptr) : _settings(server, fs, nullptr)
, _securitySettingsService(server, fs){}; , _securitySettingsService(server, fs){};
void begin(){}; void begin() {
// initialize mqtt
_mqttClient = new espMqttClient();
};
void loop(){}; void loop(){};
SecurityManager * getSecurityManager() { SecurityManager * getSecurityManager() {
@@ -112,6 +115,11 @@ class ESP8266React {
return _mqttClient; return _mqttClient;
} }
void setWill(const char * will_topic) {
}
void onMessage(espMqttClientTypes::OnMessageCallback callback) {
}
StatefulService<DummySettings> * getNetworkSettingsService() { StatefulService<DummySettings> * getNetworkSettingsService() {
return &_settings; return &_settings;
} }

View File

@@ -3,6 +3,7 @@
#include <Arduino.h> #include <Arduino.h>
#include <functional> #include <functional>
#include <IPAddress.h>
#define WiFiMode_t wifi_mode_t #define WiFiMode_t wifi_mode_t
#define WIFI_OFF WIFI_MODE_NULL #define WIFI_OFF WIFI_MODE_NULL

View File

View File

@@ -1,130 +0,0 @@
#ifndef ESPMQTTCLIENT_H_
#define ESPMQTTCLIENT_H_
#include "Arduino.h"
#include <functional>
namespace espMqttClientTypes {
enum class DisconnectReason : uint8_t {
USER_OK = 0,
MQTT_UNACCEPTABLE_PROTOCOL_VERSION = 1,
MQTT_IDENTIFIER_REJECTED = 2,
MQTT_SERVER_UNAVAILABLE = 3,
MQTT_MALFORMED_CREDENTIALS = 4,
MQTT_NOT_AUTHORIZED = 5,
TLS_BAD_FINGERPRINT = 6,
TCP_DISCONNECTED = 7
};
const char * disconnectReasonToString(DisconnectReason reason);
enum class SubscribeReturncode : uint8_t { QOS0 = 0x00, QOS1 = 0x01, QOS2 = 0x02, FAIL = 0X80 };
const char * subscribeReturncodeToString(SubscribeReturncode returnCode);
enum class Error : uint8_t { SUCCESS = 0, OUT_OF_MEMORY = 1, MAX_RETRIES = 2, MALFORMED_PARAMETER = 3, MISC_ERROR = 4 };
const char * errorToString(Error error);
struct MessageProperties {
uint8_t qos;
bool dup;
bool retain;
uint16_t packetId;
};
typedef std::function<void(bool sessionPresent)> OnConnectCallback;
typedef std::function<void(DisconnectReason reason)> OnDisconnectCallback;
typedef std::function<void(uint16_t packetId, const SubscribeReturncode * returncodes, size_t len)> OnSubscribeCallback;
typedef std::function<void(uint16_t packetId)> OnUnsubscribeCallback;
typedef std::function<void(const MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total)> OnMessageCallback;
typedef std::function<void(uint16_t packetId)> OnPublishCallback;
typedef std::function<size_t(uint8_t * data, size_t maxSize, size_t index)> PayloadCallback;
typedef std::function<void(uint16_t packetId, Error error)> OnErrorCallback;
} // namespace espMqttClientTypes
class espMqttClient {
public:
espMqttClient();
~espMqttClient();
espMqttClient & setKeepAlive(uint16_t keepAlive);
espMqttClient & setClientId(const char * clientId);
espMqttClient & setCleanSession(bool cleanSession);
espMqttClient & setMaxTopicLength(uint16_t maxTopicLength);
espMqttClient & setCredentials(const char * username, const char * password = nullptr);
espMqttClient & setWill(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0) {
return *this;
}
espMqttClient & setServer(IPAddress ip, uint16_t port);
espMqttClient & setServer(const char * host, uint16_t port);
espMqttClient & onConnect(espMqttClientTypes::OnConnectCallback callback) {
return *this;
}
espMqttClient & onDisconnect(espMqttClientTypes::OnDisconnectCallback callback) {
return *this;
}
espMqttClient & onSubscribe(espMqttClientTypes::OnSubscribeCallback callback) {
return *this;
}
espMqttClient & onUnsubscribe(espMqttClientTypes::OnUnsubscribeCallback callback) {
return *this;
}
espMqttClient & onMessage(espMqttClientTypes::OnMessageCallback callback) {
return *this;
}
espMqttClient & onPublish(espMqttClientTypes::OnPublishCallback callback) {
return *this;
}
bool connected() const {
return false;
}
void connect() {
}
void disconnect(bool force = false) {
}
uint16_t subscribe(const char * topic, uint8_t qos) {
return 1;
}
uint16_t unsubscribe(const char * topic) {
return 1;
}
uint16_t publish(const char * topic, uint8_t qos, bool retain, const char * payload = nullptr, size_t length = 0, bool dup = false, uint16_t message_id = 0) {
return 1;
}
const char * getClientId() {
return "12";
}
uint16_t getQueue() const {
return 0;
}
private:
bool _connected;
bool _connectPacketNotEnoughSpace;
bool _disconnectOnPoll;
bool _tlsBadFingerprint;
uint32_t _lastClientActivity;
uint32_t _lastServerActivity;
uint32_t _lastPingRequestTime;
char _generatedClientId[18 + 1]; // esp8266-abc123 and esp32-abcdef123456
IPAddress _ip;
const char * _host;
bool _useIp;
uint16_t _port;
uint16_t _keepAlive;
bool _cleanSession;
const char * _clientId;
const char * _username;
const char * _password;
const char * _willTopic;
const char * _willPayload;
uint16_t _willPayloadLength;
uint8_t _willQos;
bool _willRetain;
};
#endif

View File

@@ -13,6 +13,12 @@
; -DEMSESP_EN_ONLY ; only EN translated entity names ; -DEMSESP_EN_ONLY ; only EN translated entity names
; my_build_flags = -DEMSESP_DEBUG ; my_build_flags = -DEMSESP_DEBUG
[platformio]
default_envs = esp32_4M
; default_envs = esp32_16M
; default_envs = lolin_s3
; default_envs = standalone
[env:esp32_4M] [env:esp32_4M]
; if using OTA enter your details below ; if using OTA enter your details below
; upload_protocol = espota ; upload_protocol = espota
@@ -25,19 +31,20 @@ upload_port = /dev/ttyUSB*
; upload_port = COM5 ; upload_port = COM5
; override arduino espressif core ; override arduino espressif core
; platform = espressif32 ; take latest platform = espressif32 ; take latest
; platform = espressif32@5.2.0 ; platform = espressif32@5.3.0
extra_scripts = extra_scripts =
pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time
scripts/rename_fw.py scripts/rename_fw.py
; post:scripts/app-tls-size.py
[env:esp32_16M] [env:esp32_16M]
upload_port = /dev/ttyUSB*
; upload_port = COM3
[env:lolin_s3]
upload_port = /dev/ttyACM0
extra_scripts = extra_scripts =
; pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time pre:scripts/build_interface.py ; comment out if you don't want to re-build the WebUI each time
scripts/rename_fw.py scripts/rename_fw.py
; pio run -e debug ; pio run -e debug

View File

@@ -20,7 +20,6 @@ core_build_flags =
; -std=gnu++17 ; -std=gnu++17
; core_unbuild_flags = -std=gnu++11 ; core_unbuild_flags = -std=gnu++11
; core_unbuild_flags = -std=gnu++17
core_unbuild_flags = core_unbuild_flags =
; my_build_flags is set in pio_local.ini ; my_build_flags is set in pio_local.ini
@@ -41,9 +40,12 @@ unbuild_flags =
[espressi32_base] [espressi32_base]
platform = espressif32 platform = espressif32
; platform = espressif32@5.3.0
; platform = espressif32@5.2.0
framework = arduino framework = arduino
build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
[env] [env]
monitor_speed = 115200 monitor_speed = 115200
@@ -62,7 +64,7 @@ check_flags =
; build for GitHub Actions CI ; build for GitHub Actions CI
; the Web interface is built seperately ; the Web interface is built seperately
[env:ci] [env:ci]
platform = espressif32@5.2.0 platform = espressif32
framework = arduino framework = arduino
extra_scripts = scripts/rename_fw.py extra_scripts = scripts/rename_fw.py
board = esp32dev board = esp32dev
@@ -84,93 +86,63 @@ build_flags = ${common.build_flags} -O2
build_unflags = ${common.unbuild_flags} build_unflags = ${common.unbuild_flags}
[env:esp32_4M] [env:esp32_4M]
platform = espressif32@5.2.0 extends = espressi32_base
framework = arduino
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = esp32dev board = esp32dev
board_upload.flash_size = 4MB board_upload.flash_size = 4MB
board_build.partitions = esp32_partition_4M.csv board_build.partitions = esp32_partition_4M.csv
build_flags = ${common.build_flags} -Os build_flags = ${common.build_flags} -Os
build_unflags = ${common.unbuild_flags}
[env:esp32_4Mplus] [env:esp32_4Mplus]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = esp32dev board = esp32dev
board_upload.flash_size = 4MB board_upload.flash_size = 4MB
board_build.partitions = esp32_asym_partition_4M.csv board_build.partitions = esp32_asym_partition_4M.csv
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
[env:esp32_16M] [env:esp32_16M]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = esp32dev board = esp32dev
board_upload.flash_size = 16MB board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv board_build.partitions = esp32_partition_16M.csv
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
[env:lolin_c3_mini] [env:lolin_c3_mini]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_c3_mini board = lolin_c3_mini
board_upload.flash_size = 4MB board_upload.flash_size = 4MB
board_build.partitions = esp32_asym_partition_4M.csv board_build.partitions = esp32_asym_partition_4M.csv
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
; lolin C3 mini v1 needs special wifi init. ; lolin C3 mini v1 needs special wifi init.
; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi ; https://www.wemos.cc/en/latest/c3/c3_mini_1_0_0.html#about-wifi
[env:lolin_c3_mini_v1] [env:lolin_c3_mini_v1]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_c3_mini board = lolin_c3_mini
board_upload.flash_size = 4MB board_upload.flash_size = 4MB
board_build.partitions = esp32_asym_partition_4M.csv board_build.partitions = esp32_asym_partition_4M.csv
build_flags = ${common.build_flags} -DBOARD_C3_MINI_V1 build_flags = ${common.build_flags} -DBOARD_C3_MINI_V1
build_unflags = ${common.unbuild_flags}
[env:lolin_s2_mini] [env:lolin_s2_mini]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_s2_mini board = lolin_s2_mini
board_upload.flash_size = 4MB board_upload.flash_size = 4MB
board_build.partitions = esp32_asym_partition_4M.csv board_build.partitions = esp32_asym_partition_4M.csv
build_flags = ${common.build_flags} build_flags = ${common.build_flags}
build_unflags = ${common.unbuild_flags}
[env:lolin_s3] [env:lolin_s3]
extends = espressi32_base extends = espressi32_base
extra_scripts =
pre:scripts/build_interface.py
scripts/rename_fw.py
board = lolin_s3 board = lolin_s3
board_build.f_cpu = 240000000L board_build.f_cpu = 240000000L
board_upload.flash_size = 16MB board_upload.flash_size = 16MB
board_build.partitions = esp32_partition_16M.csv board_build.partitions = esp32_partition_16M.csv
build_flags = ${common.build_flags} -O2
build_unflags = ${common.unbuild_flags}
board_upload.use_1200bps_touch = false board_upload.use_1200bps_touch = false
board_upload.wait_for_upload_port = false board_upload.wait_for_upload_port = false
build_flags = ${common.build_flags} -O2
; to build and run: pio run -e standalone -t exec ; to build and run: pio run -e standalone -t exec
[env:standalone] [env:standalone]
platform = native platform = native
build_flags = build_flags =
-DARDUINO
-DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0 -DARDUINOJSON_ENABLE_STD_STRING=1 -DARDUINOJSON_ENABLE_PROGMEM=1 -DARDUINOJSON_ENABLE_ARDUINO_STRING -DARDUINOJSON_USE_DOUBLE=0
-DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST -DEMSESP_DEBUG -DEMSESP_STANDALONE -DEMSESP_TEST
-DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\" -DEMSESP_DEFAULT_LOCALE=\"en\" -DEMSESP_DEFAULT_TX_MODE=8 -DEMSESP_DEFAULT_VERSION=\"3.6.0-dev\" -DEMSESP_DEFAULT_BOARD_PROFILE=\"S32\"
@@ -185,6 +157,8 @@ build_src_flags =
-I./lib/uuid-log/src -I./lib/uuid-log/src
-I./lib/semver -I./lib/semver
-I./lib/PButton -I./lib/PButton
-I./lib/espMqttClient/src
-I./lib/espMqttClient/src/Transport
build_src_filter = build_src_filter =
+<*> +<*>
-<.git/> -<.git/>
@@ -194,5 +168,7 @@ build_src_filter =
+<../lib/uuid-log> +<../lib/uuid-log>
+<../lib/semver> +<../lib/semver>
+<../lib/PButton> +<../lib/PButton>
+<../lib/espMqttClient/src>
+<../lib/espMqttClient/src/Transport>
lib_compat_mode = off lib_compat_mode = off
lib_ldf_mode = off lib_ldf_mode = off

View File

@@ -498,7 +498,7 @@ void AnalogSensor::publish_values(const bool force) {
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}"; config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else " + sample_val + "}}";
char uniq_s[70]; char uniq_s[70];
if (Mqtt::entity_format() == Mqtt::entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
snprintf(uniq_s, sizeof(uniq_s), "%s_analogsensor_%02d", Mqtt::basename().c_str(), sensor.gpio()); snprintf(uniq_s, sizeof(uniq_s), "%s_analogsensor_%02d", Mqtt::basename().c_str(), sensor.gpio());
} else { } else {
snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%02d", sensor.gpio()); snprintf(uniq_s, sizeof(uniq_s), "analogsensor_%02d", sensor.gpio());

View File

@@ -1139,8 +1139,8 @@ void Thermostat::process_RC300Settings(std::shared_ptr<const Telegram> telegram)
// 0x2CC - e.g. wwprio for RC310 hcx parameter // 0x2CC - e.g. wwprio for RC310 hcx parameter
void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) { void Thermostat::process_RC300Set2(std::shared_ptr<const Telegram> telegram) {
// typeids are not in a raw. hc:0x2CC, hc2: 0x2CE for RC310 // typeids are not in a raw. hc:0x2CC, hc2: 0x2CE for RC310
// telegram is either offset 3 with data lenght of 1 and values 0/1 (radiators) - 10 0B FF 03 01 CC 01 F6 // telegram is either offset 3 with data length of 1 and values 0/1 (radiators) - 10 0B FF 03 01 CC 01 F6
// or offset 0 with data lenght of 6 bytes - offset 3 values are 0x00 or 0xFF - 10 0B FF 00 01 CE FF 13 0A FF 1E 00 20 // or offset 0 with data length of 6 bytes - offset 3 values are 0x00 or 0xFF - 10 0B FF 00 01 CE FF 13 0A FF 1E 00 20
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram); std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(telegram);
if (hc == nullptr) { if (hc == nullptr) {
@@ -2727,7 +2727,7 @@ bool Thermostat::set_controlmode(const char * value, const int8_t id) {
return false; return false;
} }
// sets the thermostat time for nightmode for RC10, telegrm 0xB0 // sets the thermostat time for nightmode for RC10, telegram 0xB0
bool Thermostat::set_reducehours(const char * value, const int8_t id) { bool Thermostat::set_reducehours(const char * value, const int8_t id) {
uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id; uint8_t hc_num = (id == -1) ? AUTO_HEATING_CIRCUIT : id;
std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num); std::shared_ptr<Thermostat::HeatingCircuit> hc = heating_circuit(hc_num);

View File

@@ -28,7 +28,7 @@
#include <uuid/log.h> #include <uuid/log.h>
// forward declarators // forward declarator
// used to bind EMS-ESP functions to external frameworks // used to bind EMS-ESP functions to external frameworks
namespace emsesp { namespace emsesp {
class EMSESP { class EMSESP {

View File

@@ -312,7 +312,7 @@ void Mqtt::show_topic_handlers(uuid::console::Shell & shell, const uint8_t devic
// called when an MQTT Publish ACK is received // called when an MQTT Publish ACK is received
void Mqtt::on_publish(uint16_t packetId) const { void Mqtt::on_publish(uint16_t packetId) const {
LOG_DEBUG("Packet %d sent successfull", packetId); LOG_DEBUG("Packet %d sent successful", packetId);
} }
// called when MQTT settings have changed via the Web forms // called when MQTT settings have changed via the Web forms
@@ -390,12 +390,6 @@ void Mqtt::start() {
[this](const espMqttClientTypes::MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total) { [this](const espMqttClientTypes::MessageProperties & properties, const char * topic, const uint8_t * payload, size_t len, size_t index, size_t total) {
on_message(topic, (const char *)payload, len); // receiving mqtt on_message(topic, (const char *)payload, len); // receiving mqtt
}); });
/*
mqttClient_->onPublish([this](uint16_t packetId) {
on_publish(packetId); // publish
});
*/
} }
void Mqtt::set_publish_time_boiler(uint16_t publish_time) { void Mqtt::set_publish_time_boiler(uint16_t publish_time) {
@@ -524,7 +518,7 @@ void Mqtt::ha_status() {
StaticJsonDocument<EMSESP_JSON_SIZE_LARGE> doc; StaticJsonDocument<EMSESP_JSON_SIZE_LARGE> doc;
char uniq[70]; char uniq[70];
if (Mqtt::entity_format() == entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
snprintf(uniq, sizeof(uniq), "%s_system_status", mqtt_basename_.c_str()); snprintf(uniq, sizeof(uniq), "%s_system_status", mqtt_basename_.c_str());
} else { } else {
strcpy(uniq, "system_status"); strcpy(uniq, "system_status");
@@ -591,9 +585,10 @@ bool Mqtt::queue_message(const uint8_t operation, const std::string & topic, con
return true; return true;
} }
} }
if (!enabled() || topic.empty()) { if (!mqtt_enabled_ || topic.empty()) {
return false; return false; // quit, not using MQTT
} }
uint16_t packet_id = 0; uint16_t packet_id = 0;
char fulltopic[MQTT_TOPIC_MAX_SIZE]; char fulltopic[MQTT_TOPIC_MAX_SIZE];
@@ -801,10 +796,10 @@ bool Mqtt::publish_ha_sensor_config(uint8_t type, // EMSdev
// build unique identifier also used as object_id which also becomes the Entity ID in HA // build unique identifier also used as object_id which also becomes the Entity ID in HA
char uniq_id[80]; char uniq_id[80];
if (Mqtt::entity_format() == entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
// prefix base name to each uniq_id and use the shortname // prefix base name to each uniq_id and use the shortname
snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag); snprintf(uniq_id, sizeof(uniq_id), "%s_%s_%s", mqtt_basename_.c_str(), device_name, entity_with_tag);
} else if (Mqtt::entity_format() == entitiyFormat::SINGLE_SHORT) { } else if (Mqtt::entity_format() == entityFormat::SINGLE_SHORT) {
// shortname, no mqtt base. This is the default version. // shortname, no mqtt base. This is the default version.
snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag); snprintf(uniq_id, sizeof(uniq_id), "%s_%s", device_name, entity_with_tag);
} else { } else {
@@ -1168,7 +1163,7 @@ bool Mqtt::publish_ha_climate_config(const uint8_t tag, const bool has_roomtemp,
snprintf(name_s, sizeof(name_s), "Hc%d", hc_num); snprintf(name_s, sizeof(name_s), "Hc%d", hc_num);
if (Mqtt::entity_format() == entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == entityFormat::MULTI_SHORT) {
snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename snprintf(uniq_id_s, sizeof(uniq_id_s), "%s_thermostat_hc%d", mqtt_basename_.c_str(), hc_num); // add basename
} else { } else {
snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); // backward compatible with v3.4 snprintf(uniq_id_s, sizeof(uniq_id_s), "thermostat_hc%d", hc_num); // backward compatible with v3.4

View File

@@ -36,7 +36,7 @@ using mqtt_sub_function_p = std::function<bool(const char * message)>;
class Mqtt { class Mqtt {
public: public:
enum discoveryType : uint8_t { HOMEASSISTANT, DOMOTICZ }; enum discoveryType : uint8_t { HOMEASSISTANT, DOMOTICZ };
enum entitiyFormat : uint8_t { SINGLE_LONG, SINGLE_SHORT, MULTI_SHORT }; enum entityFormat : uint8_t { SINGLE_LONG, SINGLE_SHORT, MULTI_SHORT };
void loop(); void loop();
void start(); void start();
@@ -104,11 +104,7 @@ class Mqtt {
#endif #endif
static bool connected() { static bool connected() {
#if defined(EMSESP_STANDALONE)
return true;
#else
return mqttClient_->connected(); return mqttClient_->connected();
#endif
} }
static MqttClient * client() { static MqttClient * client() {

View File

@@ -153,7 +153,7 @@ void Shower::set_shower_state(bool state, bool force) {
doc["name"] = "Shower Active"; doc["name"] = "Shower Active";
char str[70]; char str[70];
if (Mqtt::entity_format() == Mqtt::entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str()); snprintf(str, sizeof(str), "%s_shower_active", Mqtt::basename().c_str());
} else { } else {
snprintf(str, sizeof(str), "shower_active"); // v3.4 compatible snprintf(str, sizeof(str), "shower_active"); // v3.4 compatible

View File

@@ -548,7 +548,7 @@ void System::loop() {
// send MQTT info topic appended with the version information as JSON, as a retained flag // send MQTT info topic appended with the version information as JSON, as a retained flag
void System::send_info_mqtt(const char * event_str, bool send_ntp) { void System::send_info_mqtt(const char * event_str, bool send_ntp) {
// use dynamic json becaues it is called from NTP-callback from lwip task with small stack // use dynamic json because it is called from NTP-callback from lwip task with small stack
DynamicJsonDocument doc = DynamicJsonDocument(EMSESP_JSON_SIZE_MEDIUM); DynamicJsonDocument doc = DynamicJsonDocument(EMSESP_JSON_SIZE_MEDIUM);
doc["event"] = event_str; doc["event"] = event_str;
doc["version"] = EMSESP_APP_VERSION; doc["version"] = EMSESP_APP_VERSION;
@@ -1516,7 +1516,7 @@ std::string System::reset_reason(uint8_t cpu) const {
break; break;
} }
#endif #endif
return ("Unkonwn"); return ("Unknown");
} }
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@@ -528,7 +528,7 @@ void TemperatureSensor::publish_values(const bool force) {
config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}"; config["val_tpl"] = (std::string) "{{" + val_obj + " if " + val_cond + " else -55}}";
char uniq_s[70]; char uniq_s[70];
if (Mqtt::entity_format() == Mqtt::entitiyFormat::MULTI_SHORT) { if (Mqtt::entity_format() == Mqtt::entityFormat::MULTI_SHORT) {
snprintf(uniq_s, sizeof(uniq_s), "%s_temperaturesensor_%s", Mqtt::basename().c_str(), sensor.id().c_str()); snprintf(uniq_s, sizeof(uniq_s), "%s_temperaturesensor_%s", Mqtt::basename().c_str(), sensor.id().c_str());
} else { } else {
snprintf(uniq_s, sizeof(uniq_s), "temperaturesensor_%s", sensor.id().c_str()); snprintf(uniq_s, sizeof(uniq_s), "temperaturesensor_%s", sensor.id().c_str());

View File

@@ -1001,14 +1001,14 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
EMSESP::mqtt_.incoming("ems-esp/thermostat/hc2/mode", "auto"); EMSESP::mqtt_.incoming("ems-esp/thermostat/hc2/mode", "auto");
EMSESP::mqtt_.incoming("ems-esp/thermostat/wwc3/mode", "auto"); EMSESP::mqtt_.incoming("ems-esp/thermostat/wwc3/mode", "auto");
EMSESP::mqtt_.incoming("ems-esp/boiler/wwcircpump", "off"); EMSESP::mqtt_.incoming("ems-esp/boiler/wwcircpump", "off");
EMSESP::mqtt_.incoming("ems-esp/thermostat/seltemp"); // empty payload, sends reponse EMSESP::mqtt_.incoming("ems-esp/thermostat/seltemp"); // empty payload
EMSESP::mqtt_.incoming("ems-esp/thermostat_hc1", "22"); // HA only EMSESP::mqtt_.incoming("ems-esp/thermostat_hc1", "22"); // HA only
EMSESP::mqtt_.incoming("ems-esp/thermostat_hc1", "off"); // HA only EMSESP::mqtt_.incoming("ems-esp/thermostat_hc1", "off"); // HA only
EMSESP::mqtt_.incoming("ems-esp/system/send", "11 12 13"); EMSESP::mqtt_.incoming("ems-esp/system/send", "11 12 13");
EMSESP::mqtt_.incoming("ems-esp/boiler/syspress"); // empty payload, sends reponse EMSESP::mqtt_.incoming("ems-esp/boiler/syspress"); // empty payload
EMSESP::mqtt_.incoming("ems-esp/thermostat/mode"); // empty payload, sends reponse EMSESP::mqtt_.incoming("ems-esp/thermostat/mode"); // empty payload
EMSESP::mqtt_.incoming("ems-esp/system/publish"); EMSESP::mqtt_.incoming("ems-esp/system/publish");
EMSESP::mqtt_.incoming("ems-esp/thermostat/seltemp"); // empty payload, sends reponse EMSESP::mqtt_.incoming("ems-esp/thermostat/seltemp"); // empty payload
EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59"); EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp", "59");
EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp"); EMSESP::mqtt_.incoming("ems-esp/boiler/wwseltemp");
@@ -1022,7 +1022,7 @@ void Test::run_test(uuid::console::Shell & shell, const std::string & cmd, const
// check extended MQTT base // check extended MQTT base
Mqtt::base("home/cellar/heating"); Mqtt::base("home/cellar/heating");
EMSESP::mqtt_.incoming("home/cellar/heating/thermostat/mode"); // empty payload, sends reponse EMSESP::mqtt_.incoming("home/cellar/heating/thermostat/mode"); // empty payload
// Web API TESTS // Web API TESTS
AsyncWebServerRequest request; AsyncWebServerRequest request;

View File

@@ -1 +1 @@
#define EMSESP_APP_VERSION "3.6.0-dev.13c" #define EMSESP_APP_VERSION "3.6.0-dev.13d"

View File

@@ -30,7 +30,7 @@ WebEntityService::WebEntityService(AsyncWebServer * server, FS * fs, SecurityMan
// load the settings when the service starts // load the settings when the service starts
void WebEntityService::begin() { void WebEntityService::begin() {
_fsPersistence.readFromFS(); _fsPersistence.readFromFS();
EMSESP::logger().info("Starting custom entity service"); EMSESP::logger().info("Starting Custom entity service");
} }
// this creates the entity file, saving it to the FS // this creates the entity file, saving it to the FS

View File

@@ -50,7 +50,7 @@ void WebScheduler::read(WebScheduler & webScheduler, JsonObject & root) {
} }
} }
// call on initialization and also when the Scheduile web page is saved // call on initialization and also when the Schedule web page is saved
// this loads the data into the internal class // this loads the data into the internal class
StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webScheduler) { StateUpdateResult WebScheduler::update(JsonObject & root, WebScheduler & webScheduler) {
#ifdef EMSESP_STANDALONE #ifdef EMSESP_STANDALONE

View File

@@ -229,7 +229,7 @@ const char * WebStatusService::disconnectReason(uint8_t code) {
#ifndef EMSESP_STANDALONE #ifndef EMSESP_STANDALONE
switch (code) { switch (code) {
case WIFI_REASON_UNSPECIFIED: // = 1, case WIFI_REASON_UNSPECIFIED: // = 1,
return "unspecifiied"; return "unspecified";
case WIFI_REASON_AUTH_EXPIRE: // = 2, case WIFI_REASON_AUTH_EXPIRE: // = 2,
return "auth expire"; return "auth expire";
case WIFI_REASON_AUTH_LEAVE: // = 3, case WIFI_REASON_AUTH_LEAVE: // = 3,
@@ -239,9 +239,9 @@ const char * WebStatusService::disconnectReason(uint8_t code) {
case WIFI_REASON_ASSOC_TOOMANY: // = 5, case WIFI_REASON_ASSOC_TOOMANY: // = 5,
return "assoc too many"; return "assoc too many";
case WIFI_REASON_NOT_AUTHED: // = 6, case WIFI_REASON_NOT_AUTHED: // = 6,
return "not authed"; return "not authenticated";
case WIFI_REASON_NOT_ASSOCED: // = 7, case WIFI_REASON_NOT_ASSOCED: // = 7,
return "not assoced"; return "not assoc";
case WIFI_REASON_ASSOC_LEAVE: // = 8, case WIFI_REASON_ASSOC_LEAVE: // = 8,
return "assoc leave"; return "assoc leave";
case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9, case WIFI_REASON_ASSOC_NOT_AUTHED: // = 9,