diff --git a/.gitignore b/.gitignore index 699e94556..506d73ff0 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ .vscode/c_cpp_properties.json .vscode/launch.json .vscode/ipch +.vscode/settings.json platformio-device-monitor*.log \ No newline at end of file diff --git a/include/Configuration.h b/include/Configuration.h index 52eef24a4..b453e0667 100644 --- a/include/Configuration.h +++ b/include/Configuration.h @@ -4,7 +4,7 @@ #include #define CONFIG_FILENAME "/config.bin" -#define CONFIG_VERSION 0x00011200 // 0.1.18 // make sure to clean all after change +#define CONFIG_VERSION 0x00011300 // 0.1.19 // make sure to clean all after change #define WIFI_MAX_SSID_STRLEN 31 #define WIFI_MAX_PASSWORD_STRLEN 64 @@ -19,6 +19,7 @@ #define MQTT_MAX_PASSWORD_STRLEN 32 #define MQTT_MAX_TOPIC_STRLEN 32 #define MQTT_MAX_LWTVALUE_STRLEN 20 +#define MQTT_MAX_ROOT_CA_CERT_STRLEN 2048 #define INV_MAX_NAME_STRLEN 31 #define INV_MAX_COUNT 10 @@ -70,6 +71,8 @@ struct CONFIG_T { bool Mqtt_Hass_Retain; char Mqtt_Hass_Topic[MQTT_MAX_TOPIC_STRLEN + 1]; bool Mqtt_Hass_IndividualPanels; + bool Mqtt_Tls; + char Mqtt_RootCaCert[MQTT_MAX_ROOT_CA_CERT_STRLEN + 1]; }; class ConfigurationClass { diff --git a/include/MqttSettings.h b/include/MqttSettings.h index 5d17312b5..d4ab9fea2 100644 --- a/include/MqttSettings.h +++ b/include/MqttSettings.h @@ -3,8 +3,8 @@ #include "NetworkSettings.h" #include -#include #include +#include #include class MqttSettingsClass { @@ -21,13 +21,15 @@ class MqttSettingsClass { private: void NetworkEvent(network_event event); - void onMqttDisconnect(AsyncMqttClientDisconnectReason reason); + void onMqttDisconnect(espMqttClientTypes::DisconnectReason reason); void onMqttConnect(bool sessionPresent); void performConnect(); void performDisconnect(); - AsyncMqttClient mqttClient; + void createMqttClientObject(); + + MqttClient* mqttClient = nullptr; String clientId; String willTopic; Ticker mqttReconnectTimer; diff --git a/include/WebApi_mqtt.h b/include/WebApi_mqtt.h index 62d98b80d..56e265417 100644 --- a/include/WebApi_mqtt.h +++ b/include/WebApi_mqtt.h @@ -3,6 +3,8 @@ #include +#define MQTT_JSON_DOC_SIZE 3072 + class WebApiMqttClass { public: void init(AsyncWebServer* server); @@ -12,6 +14,7 @@ class WebApiMqttClass { void onMqttStatus(AsyncWebServerRequest* request); void onMqttAdminGet(AsyncWebServerRequest* request); void onMqttAdminPost(AsyncWebServerRequest* request); + String getRootCaCertInfo(char* cert); AsyncWebServer* _server; }; \ No newline at end of file diff --git a/include/defaults.h b/include/defaults.h index 1d091578d..fefd8606e 100644 --- a/include/defaults.h +++ b/include/defaults.h @@ -29,6 +29,39 @@ #define MQTT_PASSWORD "" #define MQTT_TOPIC "solar/" #define MQTT_RETAIN true +#define MQTT_TLS false +// ISRG_Root_X1.crt -- Root CA for Letsencrypt +#define MQTT_ROOT_CA_CERT "-----BEGIN CERTIFICATE-----\n" \ + "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\n" \ + "-----END CERTIFICATE-----\n" #define MQTT_LWT_TOPIC "dtu/status" #define MQTT_LWT_ONLINE "online" #define MQTT_LWT_OFFLINE "offline" diff --git a/platformio.ini b/platformio.ini index 8e6d93aec..e4bb2c3f0 100644 --- a/platformio.ini +++ b/platformio.ini @@ -22,7 +22,7 @@ build_flags = lib_deps = https://github.com/me-no-dev/ESPAsyncWebServer.git bblanchon/ArduinoJson @ ^6.19.4 - https://github.com/marvinroger/async-mqtt-client.git + https://github.com/bertmelis/espMqttClient.git nrf24/RF24 @ ^1.4.2 extra_scripts = @@ -37,7 +37,6 @@ upload_protocol = esptool [env:generic] board = esp32dev - monitor_port = COM4 upload_port = COM4 @@ -56,4 +55,19 @@ build_flags = ${env.build_flags} -DOPENDTU_ETHERNET monitor_port = COM3 -upload_port = COM3 \ No newline at end of file +upload_port = COM3 + + +[env:d1 mini esp32] +board = wemos_d1_mini32 +build_flags = + ${env.build_flags} + -DHOYMILES_PIN_MISO=19 + -DHOYMILES_PIN_MOSI=23 + -DHOYMILES_PIN_SCLK=18 + -DHOYMILES_PIN_IRQ=16 + -DHOYMILES_PIN_CE=17 + -DHOYMILES_PIN_CS=5 + +monitor_port = /dev/cu.usbserial-01E68DD0 +upload_port = /dev/cu.usbserial-01E68DD0 diff --git a/src/Configuration.cpp b/src/Configuration.cpp index cbe2d5481..095739134 100644 --- a/src/Configuration.cpp +++ b/src/Configuration.cpp @@ -33,6 +33,8 @@ void ConfigurationClass::init() strlcpy(config.Mqtt_Password, MQTT_PASSWORD, sizeof(config.Mqtt_Password)); strlcpy(config.Mqtt_Topic, MQTT_TOPIC, sizeof(config.Mqtt_Topic)); config.Mqtt_Retain = MQTT_RETAIN; + config.Mqtt_Tls = MQTT_TLS; + strlcpy(config.Mqtt_RootCaCert, MQTT_ROOT_CA_CERT, sizeof(config.Mqtt_RootCaCert)); strlcpy(config.Mqtt_LwtTopic, MQTT_LWT_TOPIC, sizeof(config.Mqtt_LwtTopic)); strlcpy(config.Mqtt_LwtValue_Online, MQTT_LWT_ONLINE, sizeof(config.Mqtt_LwtValue_Online)); strlcpy(config.Mqtt_LwtValue_Offline, MQTT_LWT_OFFLINE, sizeof(config.Mqtt_LwtValue_Offline)); @@ -140,6 +142,11 @@ void ConfigurationClass::migrate() config.Mqtt_Hass_IndividualPanels = MQTT_HASS_INDIVIDUALPANELS; } + if (config.Cfg_Version < 0x00011300) { + config.Mqtt_Tls = MQTT_TLS; + strlcpy(config.Mqtt_RootCaCert, MQTT_ROOT_CA_CERT, sizeof(config.Mqtt_RootCaCert)); + } + config.Cfg_Version = CONFIG_VERSION; write(); } diff --git a/src/MqttSettings.cpp b/src/MqttSettings.cpp index 242b068f4..049a11f3e 100644 --- a/src/MqttSettings.cpp +++ b/src/MqttSettings.cpp @@ -5,11 +5,11 @@ #include "MqttSettings.h" #include "Configuration.h" #include "NetworkSettings.h" -#include +#include #include +#include MqttSettingsClass::MqttSettingsClass() - : mqttClient() { } @@ -34,10 +34,33 @@ void MqttSettingsClass::onMqttConnect(bool sessionPresent) publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Online); } -void MqttSettingsClass::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) +void MqttSettingsClass::onMqttDisconnect(espMqttClientTypes::DisconnectReason reason) { Serial.println(F("Disconnected from MQTT.")); + Serial.print(F("Disconnect reason:")); + switch (reason) { + case espMqttClientTypes::DisconnectReason::TCP_DISCONNECTED: + Serial.println(F("TCP_DISCONNECTED")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_UNACCEPTABLE_PROTOCOL_VERSION: + Serial.println(F("MQTT_UNACCEPTABLE_PROTOCOL_VERSION")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_IDENTIFIER_REJECTED: + Serial.println(F("MQTT_IDENTIFIER_REJECTED")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_SERVER_UNAVAILABLE: + Serial.println(F("MQTT_SERVER_UNAVAILABLE")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_MALFORMED_CREDENTIALS: + Serial.println(F("MQTT_MALFORMED_CREDENTIALS")); + break; + case espMqttClientTypes::DisconnectReason::MQTT_NOT_AUTHORIZED: + Serial.println(F("MQTT_NOT_AUTHORIZED")); + break; + default: + Serial.println(F("Unknown")); + } mqttReconnectTimer.once( 2, +[](MqttSettingsClass* instance) { instance->performConnect(); }, this); } @@ -45,18 +68,28 @@ void MqttSettingsClass::onMqttDisconnect(AsyncMqttClientDisconnectReason reason) void MqttSettingsClass::performConnect() { if (NetworkSettings.isConnected() && Configuration.get().Mqtt_Enabled) { + using namespace std::placeholders; Serial.println(F("Connecting to MQTT...")); CONFIG_T& config = Configuration.get(); - mqttClient.setServer(config.Mqtt_Hostname, config.Mqtt_Port); - mqttClient.setCredentials(config.Mqtt_Username, config.Mqtt_Password); - willTopic = getPrefix() + config.Mqtt_LwtTopic; - mqttClient.setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline); - clientId = NetworkSettings.getApName(); - mqttClient.setClientId(clientId.c_str()); - - mqttClient.connect(); + if (config.Mqtt_Tls) { + static_cast(mqttClient)->setCACert(config.Mqtt_RootCaCert); + static_cast(mqttClient)->setServer(config.Mqtt_Hostname, config.Mqtt_Port); + static_cast(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password); + static_cast(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline); + static_cast(mqttClient)->setClientId(clientId.c_str()); + static_cast(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1)); + static_cast(mqttClient)->onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1)); + } else { + static_cast(mqttClient)->setServer(config.Mqtt_Hostname, config.Mqtt_Port); + static_cast(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password); + static_cast(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline); + static_cast(mqttClient)->setClientId(clientId.c_str()); + static_cast(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1)); + static_cast(mqttClient)->onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1)); + } + mqttClient->connect(); } } @@ -64,20 +97,22 @@ void MqttSettingsClass::performDisconnect() { CONFIG_T& config = Configuration.get(); publish(config.Mqtt_LwtTopic, config.Mqtt_LwtValue_Offline); - mqttClient.disconnect(); + mqttClient->disconnect(); } void MqttSettingsClass::performReconnect() { performDisconnect(); + createMqttClientObject(); + mqttReconnectTimer.once( 2, +[](MqttSettingsClass* instance) { instance->performConnect(); }, this); } bool MqttSettingsClass::getConnected() { - return mqttClient.connected(); + return mqttClient->connected(); } String MqttSettingsClass::getPrefix() @@ -89,14 +124,14 @@ void MqttSettingsClass::publish(String subtopic, String payload) { String topic = getPrefix(); topic += subtopic; - mqttClient.publish(topic.c_str(), 0, Configuration.get().Mqtt_Retain, payload.c_str()); + mqttClient->publish(topic.c_str(), 0, Configuration.get().Mqtt_Retain, payload.c_str()); } void MqttSettingsClass::publishHass(String subtopic, String payload) { String topic = Configuration.get().Mqtt_Hass_Topic; topic += subtopic; - mqttClient.publish(topic.c_str(), 0, Configuration.get().Mqtt_Hass_Retain, payload.c_str()); + mqttClient->publish(topic.c_str(), 0, Configuration.get().Mqtt_Hass_Retain, payload.c_str()); } void MqttSettingsClass::init() @@ -104,8 +139,19 @@ void MqttSettingsClass::init() using namespace std::placeholders; NetworkSettings.onEvent(std::bind(&MqttSettingsClass::NetworkEvent, this, _1)); - mqttClient.onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1)); - mqttClient.onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1)); + createMqttClientObject(); +} + +void MqttSettingsClass::createMqttClientObject() +{ + if (mqttClient != nullptr) + delete mqttClient; + CONFIG_T& config = Configuration.get(); + if (config.Mqtt_Tls) { + mqttClient = static_cast(new espMqttClientSecure); + } else { + mqttClient = static_cast(new espMqttClient); + } } MqttSettingsClass MqttSettings; \ No newline at end of file diff --git a/src/WebApi_mqtt.cpp b/src/WebApi_mqtt.cpp index 92eb78963..97d078e7d 100644 --- a/src/WebApi_mqtt.cpp +++ b/src/WebApi_mqtt.cpp @@ -27,7 +27,7 @@ void WebApiMqttClass::loop() void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); + AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); JsonObject root = response->getRoot(); CONFIG_T& config = Configuration.get(); @@ -38,6 +38,8 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) root[F("mqtt_topic")] = config.Mqtt_Topic; root[F("mqtt_connected")] = MqttSettings.getConnected(); root[F("mqtt_retain")] = config.Mqtt_Retain; + root[F("mqtt_tls")] = config.Mqtt_Tls; + root[F("mqtt_root_ca_cert_info")] = getRootCaCertInfo(config.Mqtt_RootCaCert); root[F("mqtt_lwt_topic")] = String(config.Mqtt_Topic) + config.Mqtt_LwtTopic; root[F("mqtt_publish_interval")] = config.Mqtt_PublishInterval; root[F("mqtt_hass_enabled")] = config.Mqtt_Hass_Enabled; @@ -51,7 +53,7 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request) void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); + AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); JsonObject root = response->getRoot(); CONFIG_T& config = Configuration.get(); @@ -62,6 +64,8 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request) root[F("mqtt_password")] = config.Mqtt_Password; root[F("mqtt_topic")] = config.Mqtt_Topic; root[F("mqtt_retain")] = config.Mqtt_Retain; + root[F("mqtt_tls")] = config.Mqtt_Tls; + root[F("mqtt_root_ca_cert")] = config.Mqtt_RootCaCert; root[F("mqtt_lwt_topic")] = config.Mqtt_LwtTopic; root[F("mqtt_lwt_online")] = config.Mqtt_LwtValue_Online; root[F("mqtt_lwt_offline")] = config.Mqtt_LwtValue_Offline; @@ -77,7 +81,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request) void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) { - AsyncJsonResponse* response = new AsyncJsonResponse(); + AsyncJsonResponse* response = new AsyncJsonResponse(false, MQTT_JSON_DOC_SIZE); JsonObject retMsg = response->getRoot(); retMsg[F("type")] = F("warning"); @@ -90,14 +94,14 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) String json = request->getParam("data", true)->value(); - if (json.length() > 1024) { + if (json.length() > MQTT_JSON_DOC_SIZE) { retMsg[F("message")] = F("Data too large!"); response->setLength(); request->send(response); return; } - DynamicJsonDocument root(1024); + DynamicJsonDocument root(MQTT_JSON_DOC_SIZE); DeserializationError error = deserializeJson(root, json); if (error) { @@ -107,7 +111,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) return; } - if (!(root.containsKey("mqtt_enabled") && root.containsKey("mqtt_hostname") && root.containsKey("mqtt_port") && root.containsKey("mqtt_username") && root.containsKey("mqtt_password") && root.containsKey("mqtt_topic") && root.containsKey("mqtt_retain") && root.containsKey("mqtt_lwt_topic") && root.containsKey("mqtt_lwt_online") && root.containsKey("mqtt_lwt_offline") && root.containsKey("mqtt_publish_interval") && root.containsKey("mqtt_hass_enabled") && root.containsKey("mqtt_hass_retain") && root.containsKey("mqtt_hass_topic") && root.containsKey("mqtt_hass_individualpanels"))) { + if (!(root.containsKey("mqtt_enabled") && root.containsKey("mqtt_hostname") && root.containsKey("mqtt_port") && root.containsKey("mqtt_username") && root.containsKey("mqtt_password") && root.containsKey("mqtt_topic") && root.containsKey("mqtt_retain") && root.containsKey("mqtt_tls") && root.containsKey("mqtt_lwt_topic") && root.containsKey("mqtt_lwt_online") && root.containsKey("mqtt_lwt_offline") && root.containsKey("mqtt_publish_interval") && root.containsKey("mqtt_hass_enabled") && root.containsKey("mqtt_hass_retain") && root.containsKey("mqtt_hass_topic") && root.containsKey("mqtt_hass_individualpanels"))) { retMsg[F("message")] = F("Values are missing!"); response->setLength(); request->send(response); @@ -155,6 +159,13 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) return; } + if (root[F("mqtt_root_ca_cert")].as().length() > MQTT_MAX_ROOT_CA_CERT_STRLEN) { + retMsg[F("message")] = F("Certificate must not longer then " STR(MQTT_MAX_ROOT_CA_CERT_STRLEN) " characters!"); + response->setLength(); + request->send(response); + return; + } + if (root[F("mqtt_lwt_topic")].as().length() > MQTT_MAX_TOPIC_STRLEN) { retMsg[F("message")] = F("LWT topic must not longer then " STR(MQTT_MAX_TOPIC_STRLEN) " characters!"); response->setLength(); @@ -210,6 +221,8 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) CONFIG_T& config = Configuration.get(); config.Mqtt_Enabled = root[F("mqtt_enabled")].as(); config.Mqtt_Retain = root[F("mqtt_retain")].as(); + config.Mqtt_Tls = root[F("mqtt_tls")].as(); + strcpy(config.Mqtt_RootCaCert, root[F("mqtt_root_ca_cert")].as().c_str()); config.Mqtt_Port = root[F("mqtt_port")].as(); strcpy(config.Mqtt_Hostname, root[F("mqtt_hostname")].as().c_str()); strcpy(config.Mqtt_Username, root[F("mqtt_username")].as().c_str()); @@ -233,4 +246,25 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request) MqttSettings.performReconnect(); MqttHassPublishing.forceUpdate(); -} \ No newline at end of file +} + +String WebApiMqttClass::getRootCaCertInfo(char* cert) +{ + char rootCaCertInfo[1024] = ""; + + mbedtls_x509_crt global_cacert; + + strcpy(rootCaCertInfo, "Can't parse root ca"); + + mbedtls_x509_crt_init(&global_cacert); + int ret = mbedtls_x509_crt_parse(&global_cacert, const_cast((unsigned char*)cert), 1 + strlen(cert)); + if (ret < 0) { + sprintf(rootCaCertInfo, "Can't parse root ca: mbedtls_x509_crt_parse returned -0x%x\n\n", -ret); + mbedtls_x509_crt_free(&global_cacert); + return ""; + } + mbedtls_x509_crt_info(rootCaCertInfo, sizeof(rootCaCertInfo) - 1, "", &global_cacert); + mbedtls_x509_crt_free(&global_cacert); + + return rootCaCertInfo; +} diff --git a/webapp/src/components/MqttAdminView.vue b/webapp/src/components/MqttAdminView.vue index fdc395c14..903448aca 100644 --- a/webapp/src/components/MqttAdminView.vue +++ b/webapp/src/components/MqttAdminView.vue @@ -30,7 +30,7 @@
+ Discovery
+ +
+ +
+
+ +
+
+
+ +
+ +
+ +
+
+
@@ -174,7 +196,8 @@
- +
disabled + + TLS + + enabled + disabled + + + + Root CA Certifcate Info + {{ mqttDataList.mqtt_root_ca_cert_info }} +
@@ -149,6 +163,8 @@ export default defineComponent({ mqtt_topic: "", mqtt_publish_interval: 0, mqtt_retain: false, + mqtt_tls: false, + mqtt_root_ca_cert_info: "", mqtt_connected: false, mqtt_hass_enabled: false, mqtt_hass_retain: false, diff --git a/webapp_dist/js/app.js.gz b/webapp_dist/js/app.js.gz index a82cf9007..f86ca47d7 100644 Binary files a/webapp_dist/js/app.js.gz and b/webapp_dist/js/app.js.gz differ