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:
parent
6c088a9898
commit
4435fbcdad
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,4 +3,5 @@
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
.vscode/settings.json
|
||||
platformio-device-monitor*.log
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
};
|
||||
@ -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"
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
<div class="row mb-3" v-show="mqttConfigList.mqtt_enabled">
|
||||
<label class="col-sm-4 form-check-label" for="inputMqttHass">Enable Home Assistant MQTT Auto
|
||||
Discovery</label>
|
||||
Discovery</label>
|
||||
<div class="col-sm-8">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" id="inputMqttHass"
|
||||
@ -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: "",
|
||||
|
||||
@ -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.
Loading…
Reference in New Issue
Block a user