Add support for MQTT TLS

To support TLS its necessary to use another MQTT library.
The new lib is a drop-in replacement for the async-mqtt-client.
This commit is contained in:
helgeerbe 2022-07-26 16:08:45 +02:00 committed by Thomas Basler
parent 6c088a9898
commit 4435fbcdad
12 changed files with 217 additions and 33 deletions

1
.gitignore vendored
View File

@ -3,4 +3,5 @@
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch
.vscode/settings.json
platformio-device-monitor*.log

View File

@ -4,7 +4,7 @@
#include <Arduino.h>
#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 {

View File

@ -3,8 +3,8 @@
#include "NetworkSettings.h"
#include <Arduino.h>
#include <AsyncMqttClient.h>
#include <Ticker.h>
#include <espMqttClient.h>
#include <memory>
class MqttSettingsClass {
@ -21,13 +21,15 @@ public:
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;

View File

@ -3,6 +3,8 @@
#include <ESPAsyncWebServer.h>
#define MQTT_JSON_DOC_SIZE 3072
class WebApiMqttClass {
public:
void init(AsyncWebServer* server);
@ -12,6 +14,7 @@ private:
void onMqttStatus(AsyncWebServerRequest* request);
void onMqttAdminGet(AsyncWebServerRequest* request);
void onMqttAdminPost(AsyncWebServerRequest* request);
String getRootCaCertInfo(char* cert);
AsyncWebServer* _server;
};

View File

@ -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"

View File

@ -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
@ -57,3 +56,18 @@ build_flags = ${env.build_flags}
monitor_port = COM3
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

View File

@ -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();
}

View File

@ -5,11 +5,11 @@
#include "MqttSettings.h"
#include "Configuration.h"
#include "NetworkSettings.h"
#include <AsyncMqttClient.h>
#include <MqttClientSetup.h>
#include <Ticker.h>
#include <espMqttClient.h>
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<espMqttClientSecure*>(mqttClient)->setCACert(config.Mqtt_RootCaCert);
static_cast<espMqttClientSecure*>(mqttClient)->setServer(config.Mqtt_Hostname, config.Mqtt_Port);
static_cast<espMqttClientSecure*>(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password);
static_cast<espMqttClientSecure*>(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline);
static_cast<espMqttClientSecure*>(mqttClient)->setClientId(clientId.c_str());
static_cast<espMqttClientSecure*>(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1));
static_cast<espMqttClientSecure*>(mqttClient)->onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1));
} else {
static_cast<espMqttClient*>(mqttClient)->setServer(config.Mqtt_Hostname, config.Mqtt_Port);
static_cast<espMqttClient*>(mqttClient)->setCredentials(config.Mqtt_Username, config.Mqtt_Password);
static_cast<espMqttClient*>(mqttClient)->setWill(willTopic.c_str(), 2, config.Mqtt_Retain, config.Mqtt_LwtValue_Offline);
static_cast<espMqttClient*>(mqttClient)->setClientId(clientId.c_str());
static_cast<espMqttClient*>(mqttClient)->onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1));
static_cast<espMqttClient*>(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<MqttClient*>(new espMqttClientSecure);
} else {
mqttClient = static_cast<MqttClient*>(new espMqttClient);
}
}
MqttSettingsClass MqttSettings;

View File

@ -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<String>().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<String>().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<bool>();
config.Mqtt_Retain = root[F("mqtt_retain")].as<bool>();
config.Mqtt_Tls = root[F("mqtt_tls")].as<bool>();
strcpy(config.Mqtt_RootCaCert, root[F("mqtt_root_ca_cert")].as<String>().c_str());
config.Mqtt_Port = root[F("mqtt_port")].as<uint>();
strcpy(config.Mqtt_Hostname, root[F("mqtt_hostname")].as<String>().c_str());
strcpy(config.Mqtt_Username, root[F("mqtt_username")].as<String>().c_str());
@ -234,3 +247,24 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
MqttSettings.performReconnect();
MqttHassPublishing.forceUpdate();
}
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*>((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;
}

View File

@ -111,6 +111,28 @@
</div>
</div>
</div>
<div class="row mb-3">
<label class="col-sm-2 form-check-label" for="inputTls">Enable TLS</label>
<div class="col-sm-10">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="inputTls"
v-model="mqttConfigList.mqtt_tls" />
</div>
</div>
</div>
<div class="row mb-3" v-show="mqttConfigList.mqtt_tls">
<label for="inputCert" class="col-sm-2 col-form-label">CA-Root-Certificate (default
Letsencrypt):</label>
<div class="col-sm-10">
<textarea class="form-control" id="inputCert" maxlength="2048" rows="10"
placeholder="Root CA Certificate from Letsencrypt"
v-model="mqttConfigList.mqtt_root_ca_cert">
</textarea>
</div>
</div>
</div>
</div>
@ -174,7 +196,8 @@
</div>
<div class="row mb-3">
<label class="col-sm-2 form-check-label" for="inputIndividualPanels">Individual Panels:</label>
<label class="col-sm-2 form-check-label" for="inputIndividualPanels">Individual
Panels:</label>
<div class="col-sm-10">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" id="inputIndividualPanels"
@ -212,6 +235,8 @@ export default defineComponent({
mqtt_topic: "",
mqtt_publish_interval: 0,
mqtt_retain: false,
mqtt_tls: false,
mqtt_root_ca_cert: "",
mqtt_lwt_topic: "",
mqtt_lwt_online: "",
mqtt_lwt_offline: "",

View File

@ -57,6 +57,20 @@
<span v-else>disabled</span>
</td>
</tr>
<tr>
<th>TLS</th>
<td class="badge" :class="{
'bg-danger': !mqttDataList.mqtt_tls,
'bg-success': mqttDataList.mqtt_tls,
}">
<span v-if="mqttDataList.mqtt_tls">enabled</span>
<span v-else>disabled</span>
</td>
</tr>
<tr v-show="mqttDataList.mqtt_tls">
<th>Root CA Certifcate Info</th>
<td>{{ mqttDataList.mqtt_root_ca_cert_info }}</td>
</tr>
</tbody>
</table>
</div>
@ -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,

Binary file not shown.