Feature: Allow custom MQTT Client ID

This commit is contained in:
Thomas Basler 2024-06-29 00:28:21 +02:00
parent e4bbf55ea5
commit ba95f99e03
12 changed files with 39 additions and 3 deletions

View File

@ -16,6 +16,7 @@
#define NTP_MAX_TIMEZONEDESCR_STRLEN 50
#define MQTT_MAX_HOSTNAME_STRLEN 128
#define MQTT_MAX_CLIENTID_STRLEN 64
#define MQTT_MAX_USERNAME_STRLEN 64
#define MQTT_MAX_PASSWORD_STRLEN 64
#define MQTT_MAX_TOPIC_STRLEN 32
@ -88,6 +89,7 @@ struct CONFIG_T {
bool Enabled;
char Hostname[MQTT_MAX_HOSTNAME_STRLEN + 1];
uint32_t Port;
char ClientId[MQTT_MAX_CLIENTID_STRLEN + 1];
char Username[MQTT_MAX_USERNAME_STRLEN + 1];
char Password[MQTT_MAX_PASSWORD_STRLEN + 1];
char Topic[MQTT_MAX_TOPIC_STRLEN + 1];

View File

@ -60,6 +60,7 @@ enum WebApiError {
MqttHassTopicLength,
MqttHassTopicCharacter,
MqttLwtQos,
MqttClientIdLength,
NetworkBase = 8000,
NetworkIpInvalid,

View File

@ -4,6 +4,7 @@
*/
#include "Configuration.h"
#include "MessageOutput.h"
#include "NetworkSettings.h"
#include "Utils.h"
#include "defaults.h"
#include <ArduinoJson.h>
@ -58,6 +59,7 @@ bool ConfigurationClass::write()
mqtt["enabled"] = config.Mqtt.Enabled;
mqtt["hostname"] = config.Mqtt.Hostname;
mqtt["port"] = config.Mqtt.Port;
mqtt["clientid"] = config.Mqtt.ClientId;
mqtt["username"] = config.Mqtt.Username;
mqtt["password"] = config.Mqtt.Password;
mqtt["topic"] = config.Mqtt.Topic;
@ -232,6 +234,7 @@ bool ConfigurationClass::read()
config.Mqtt.Enabled = mqtt["enabled"] | MQTT_ENABLED;
strlcpy(config.Mqtt.Hostname, mqtt["hostname"] | MQTT_HOST, sizeof(config.Mqtt.Hostname));
config.Mqtt.Port = mqtt["port"] | MQTT_PORT;
strlcpy(config.Mqtt.ClientId, mqtt["clientid"] | NetworkSettings.getApName().c_str(), sizeof(config.Mqtt.ClientId));
strlcpy(config.Mqtt.Username, mqtt["username"] | MQTT_USER, sizeof(config.Mqtt.Username));
strlcpy(config.Mqtt.Password, mqtt["password"] | MQTT_PASSWORD, sizeof(config.Mqtt.Password));
strlcpy(config.Mqtt.Topic, mqtt["topic"] | MQTT_TOPIC, sizeof(config.Mqtt.Topic));

View File

@ -115,7 +115,7 @@ void MqttSettingsClass::performConnect()
MessageOutput.println("Connecting to MQTT...");
const CONFIG_T& config = Configuration.get();
const String willTopic = getPrefix() + config.Mqtt.Lwt.Topic;
const String clientId = NetworkSettings.getApName();
const String clientId = config.Mqtt.ClientId;
if (config.Mqtt.Tls.Enabled) {
static_cast<espMqttClientSecure*>(_mqttClient)->setCACert(config.Mqtt.Tls.RootCaCert);
static_cast<espMqttClientSecure*>(_mqttClient)->setServer(config.Mqtt.Hostname, config.Mqtt.Port);

View File

@ -34,6 +34,7 @@ void WebApiMqttClass::onMqttStatus(AsyncWebServerRequest* request)
root["mqtt_enabled"] = config.Mqtt.Enabled;
root["mqtt_hostname"] = config.Mqtt.Hostname;
root["mqtt_port"] = config.Mqtt.Port;
root["mqtt_clientid"] = config.Mqtt.ClientId;
root["mqtt_username"] = config.Mqtt.Username;
root["mqtt_topic"] = config.Mqtt.Topic;
root["mqtt_connected"] = MqttSettings.getConnected();
@ -67,6 +68,7 @@ void WebApiMqttClass::onMqttAdminGet(AsyncWebServerRequest* request)
root["mqtt_enabled"] = config.Mqtt.Enabled;
root["mqtt_hostname"] = config.Mqtt.Hostname;
root["mqtt_port"] = config.Mqtt.Port;
root["mqtt_clientid"] = config.Mqtt.ClientId;
root["mqtt_username"] = config.Mqtt.Username;
root["mqtt_password"] = config.Mqtt.Password;
root["mqtt_topic"] = config.Mqtt.Topic;
@ -108,6 +110,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
if (!(root.containsKey("mqtt_enabled")
&& root.containsKey("mqtt_hostname")
&& root.containsKey("mqtt_port")
&& root.containsKey("mqtt_clientid")
&& root.containsKey("mqtt_username")
&& root.containsKey("mqtt_password")
&& root.containsKey("mqtt_topic")
@ -142,6 +145,13 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
return;
}
if (root["mqtt_clientid"].as<String>().length() > MQTT_MAX_CLIENTID_STRLEN) {
retMsg["message"] = "Client ID must not be longer than " STR(MQTT_MAX_CLIENTID_STRLEN) " characters!";
retMsg["code"] = WebApiError::MqttClientIdLength;
retMsg["param"]["max"] = MQTT_MAX_CLIENTID_STRLEN;
WebApi.sendJsonResponse(request, response, __FUNCTION__, __LINE__);
return;
}
if (root["mqtt_username"].as<String>().length() > MQTT_MAX_USERNAME_STRLEN) {
retMsg["message"] = "Username must not be longer than " STR(MQTT_MAX_USERNAME_STRLEN) " characters!";
retMsg["code"] = WebApiError::MqttUsernameLength;
@ -271,6 +281,7 @@ void WebApiMqttClass::onMqttAdminPost(AsyncWebServerRequest* request)
strlcpy(config.Mqtt.Tls.ClientKey, root["mqtt_client_key"].as<String>().c_str(), sizeof(config.Mqtt.Tls.ClientKey));
config.Mqtt.Port = root["mqtt_port"].as<uint>();
strlcpy(config.Mqtt.Hostname, root["mqtt_hostname"].as<String>().c_str(), sizeof(config.Mqtt.Hostname));
strlcpy(config.Mqtt.ClientId, root["mqtt_clientid"].as<String>().c_str(), sizeof(config.Mqtt.ClientId));
strlcpy(config.Mqtt.Username, root["mqtt_username"].as<String>().c_str(), sizeof(config.Mqtt.Username));
strlcpy(config.Mqtt.Password, root["mqtt_password"].as<String>().c_str(), sizeof(config.Mqtt.Password));
strlcpy(config.Mqtt.Lwt.Topic, root["mqtt_lwt_topic"].as<String>().c_str(), sizeof(config.Mqtt.Lwt.Topic));

View File

@ -85,6 +85,7 @@
"7014": "Hass-Topic darf nicht länger als {max} Zeichen sein!",
"7015": "Hass-Topic darf keine Leerzeichen enthalten!",
"7016": "LWT QOS darf icht größer als {max} sein!",
"7017": "Client ID darf nicht länger als {max} Zeichen sein!",
"8001": "IP-Adresse ist ungültig!",
"8002": "Netzmaske ist ungültig!",
"8003": "Standardgateway ist ungültig!",
@ -297,6 +298,7 @@
"Disabled": "nicht aktiv",
"Server": "@:ntpinfo.Server",
"Port": "Port",
"ClientId": "Client ID",
"Username": "Benutzername",
"BaseTopic": "Basis-Topic",
"PublishInterval": "Veröffentlichungsintervall",
@ -441,6 +443,7 @@
"Hostname": "Hostname:",
"HostnameHint": "Hostname oder IP-Adresse",
"Port": "Port:",
"ClientId": "Client ID:",
"Username": "Benutzername:",
"UsernameHint": "Benutzername, leer lassen für anonyme Verbindung",
"Password": "Passwort:",

View File

@ -85,6 +85,7 @@
"7014": "Hass topic must not longer then {max} characters!",
"7015": "Hass topic must not contain space characters!",
"7016": "LWT QOS must not greater then {max}!",
"7017": "Client ID must not longer then {max} characters!",
"8001": "IP address is invalid!",
"8002": "Netmask is invalid!",
"8003": "Gateway is invalid!",
@ -297,6 +298,7 @@
"Disabled": "Disabled",
"Server": "@:ntpinfo.Server",
"Port": "Port",
"ClientId": "Client ID",
"Username": "Username",
"BaseTopic": "Base Topic",
"PublishInterval": "Publish Interval",
@ -441,6 +443,7 @@
"Hostname": "Hostname:",
"HostnameHint": "Hostname or IP address",
"Port": "Port:",
"ClientId": "Client ID:",
"Username": "Username:",
"UsernameHint": "Username, leave empty for anonymous connection",
"Password": "Password:",

View File

@ -85,6 +85,7 @@
"7014": "Le sujet Hass ne doit pas dépasser {max} caractères !",
"7015": "Le sujet Hass ne doit pas contenir d'espace !",
"7016": "LWT QOS ne doit pas être supérieur à {max}!",
"7017": "Client ID must not longer then {max} characters!",
"8001": "L'adresse IP n'est pas valide !",
"8002": "Le masque de réseau n'est pas valide !",
"8003": "La passerelle n'est pas valide !",
@ -297,6 +298,7 @@
"Disabled": "Désactivé",
"Server": "@:ntpinfo.Server",
"Port": "Port",
"ClientId": "Client ID",
"Username": "Nom d'utilisateur",
"BaseTopic": "Sujet de base",
"PublishInterval": "Intervalle de publication",
@ -441,6 +443,7 @@
"Hostname": "Nom d'hôte",
"HostnameHint": "Nom d'hôte ou adresse IP",
"Port": "Port",
"ClientId": "Client ID:",
"Username": "Nom d'utilisateur",
"UsernameHint": "Nom d'utilisateur, laisser vide pour une connexion anonyme",
"Password": "Mot de passe:",

View File

@ -2,6 +2,7 @@ export interface MqttConfig {
mqtt_enabled: boolean;
mqtt_hostname: string;
mqtt_port: number;
mqtt_clientid: string;
mqtt_username: string;
mqtt_password: string;
mqtt_topic: string;

View File

@ -2,6 +2,7 @@ export interface MqttStatus {
mqtt_enabled: boolean;
mqtt_hostname: string;
mqtt_port: number;
mqtt_clientid: string;
mqtt_username: string;
mqtt_topic: string;
mqtt_publish_interval: number;

View File

@ -28,6 +28,10 @@
v-model="mqttConfigList.mqtt_port"
type="number" min="1" max="65535"/>
<InputElement :label="$t('mqttadmin.ClientId')"
v-model="mqttConfigList.mqtt_clientid"
type="text" maxlength="64"/>
<InputElement :label="$t('mqttadmin.Username')"
v-model="mqttConfigList.mqtt_username"
type="text" maxlength="64"

View File

@ -18,6 +18,10 @@
<th>{{ $t('mqttinfo.Port') }}</th>
<td>{{ mqttDataList.mqtt_port }}</td>
</tr>
<tr>
<th>{{ $t('mqttinfo.ClientId') }}</th>
<td>{{ mqttDataList.mqtt_clientid }}</td>
</tr>
<tr>
<th>{{ $t('mqttinfo.Username') }}</th>
<td>{{ mqttDataList.mqtt_username }}</td>