Configurable MQTT Topic #428

This commit is contained in:
fvanroie 2023-02-15 20:09:13 +01:00
parent 59bc01be04
commit c296a5e568
3 changed files with 264 additions and 134 deletions

View File

@ -22,16 +22,21 @@ bool nvs_user_begin(Preferences& preferences, const char* key, bool readonly)
bool nvs_clear_user_config()
{
const char* name[8] = {FP_TIME, FP_OTA, FP_HTTP, FP_FTP, FP_MQTT, FP_WIFI};
const char* name[] = {FP_TIME, FP_OTA, FP_HTTP, FP_FTP, FP_MQTT, FP_WIFI};
Preferences preferences;
bool state = true;
for(int i = 0; i < 6; i++) {
if(!preferences.begin(name[i], false)) return false;
if(!preferences.clear()) return false;
for(int i = 0; i < sizeof(name) / sizeof(name[0]); i++) {
if(preferences.begin(name[i], false) && !preferences.clear()) state = false;
preferences.end();
}
return true;
for(int i = 0; i < sizeof(name) / sizeof(name[0]); i++) {
if(preferences.begin(name[i], false, "config") && !preferences.clear()) state = false;
preferences.end();
}
return state;
}
bool nvsUpdateString(Preferences& preferences, const char* key, JsonVariant value)

View File

@ -1,4 +1,4 @@
/* MIT License - Copyright (c) 2019-2022 Francis Van Roie
/* MIT License - Copyright (c) 2019-2023 Francis Van Roie
For full license information read the LICENSE file in the project folder */
#include "hasp_conf.h"
@ -22,6 +22,14 @@
#include "../hasp/hasp_dispatch.h"
#include "freertos/queue.h"
#include "esp_http_server.h"
#include "esp_tls.h"
#define MQTT_DEFAULT_NODE_TOPIC MQTT_PREFIX "/%hostname%/%topic%"
#define MQTT_DEFAULT_GROUP_TOPIC MQTT_PREFIX "/plates/%topic%"
#define MQTT_DEFAULT_BROADCAST_TOPIC MQTT_PREFIX "/" MQTT_TOPIC_BROADCAST "/%topic%"
#define MQTT_DEFAULT_HASS_TOPIC "homeassistant/status"
QueueHandle_t queue;
typedef struct
{
@ -29,22 +37,30 @@ typedef struct
char* payload; //[512];
} mqtt_message_t;
char mqttLwtTopic[28];
char mqttNodeTopic[24];
char mqttClientId[64];
char mqttGroupTopic[24];
String mqttNodeLwtTopic;
String mqttHassLwtTopic;
String mqttNodeStateTopic;
String mqttNodeCommandTopic;
String mqttGroupCommandTopic;
String mqttBroadcastCommandTopic;
bool mqttEnabled = false;
bool mqttHAautodiscover = true;
uint32_t mqttPublishCount;
uint32_t mqttReceiveCount;
uint32_t mqttFailedCount;
char mqttServer[MAX_HOSTNAME_LENGTH] = MQTT_HOSTNAME;
char mqttUsername[MAX_USERNAME_LENGTH] = MQTT_USERNAME;
char mqttPassword[MAX_PASSWORD_LENGTH] = MQTT_PASSWORD;
String mqttServer = MQTT_HOSTNAME;
String mqttUsername = MQTT_USERNAME;
String mqttPassword = MQTT_PASSWORD;
// char mqttServer[MAX_HOSTNAME_LENGTH] = MQTT_HOSTNAME;
// char mqttUsername[MAX_USERNAME_LENGTH] = MQTT_USERNAME;
// char mqttPassword[MAX_PASSWORD_LENGTH] = MQTT_PASSWORD;
// char mqttNodeName[16] = MQTT_NODENAME;
char mqttGroupName[16] = MQTT_GROUPNAME;
uint16_t mqttPort = MQTT_PORT;
// char mqttGroupName[16] = MQTT_GROUPNAME;
uint16_t mqttPort = MQTT_PORT;
int mqttQos = 0;
esp_mqtt_client_handle_t mqttClient;
static esp_mqtt_client_config_t mqtt_cfg;
@ -107,7 +123,7 @@ int mqttPublish(const char* topic, const char* payload, size_t len, bool retain)
if(!mqttEnabled) return MQTT_ERR_DISABLED;
// Write directly to the client, don't use the buffer
if(current_mqtt_state && esp_mqtt_client_publish(mqttClient, topic, payload, len, 0, retain) != ESP_FAIL) {
if(current_mqtt_state && esp_mqtt_client_publish(mqttClient, topic, payload, len, mqttQos, retain) != ESP_FAIL) {
// Enqueue a message to the outbox, to be sent later
// if(current_mqtt_state && esp_mqtt_client_enqueue(mqttClient, topic, payload, len, 0, retain, true) !=
@ -136,29 +152,29 @@ bool mqttIsConnected()
bool mqtt_send_lwt(bool online)
{
char tmp_payload[8];
// char tmp_topic[strlen(mqttNodeTopic) + 4];
// strncpy(tmp_topic, mqttNodeTopic, sizeof(tmp_topic));
// strncat_P(tmp_topic, PSTR(MQTT_TOPIC_LWT), sizeof(tmp_topic));
size_t len = snprintf_P(tmp_payload, sizeof(tmp_payload), online ? PSTR("online") : PSTR("offline"));
bool res = mqttPublish(mqttLwtTopic, tmp_payload, len, true);
bool res = mqttPublish(mqttNodeLwtTopic.c_str(), tmp_payload, len, true);
return res;
}
int mqtt_send_object_state(uint8_t pageid, uint8_t btnid, const char* payload)
{
char tmp_topic[strlen(mqttNodeTopic) + 16];
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" MQTT_TOPIC_STATE "/" HASP_OBJECT_NOTATION), mqttNodeTopic,
pageid, btnid);
return mqttPublish(tmp_topic, payload, false);
}
// int mqtt_send_object_state(uint8_t pageid, uint8_t btnid, const char* payload)
// {
// char tmp_topic[strlen(mqttNodeTopic) + 16];
// snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" MQTT_TOPIC_STATE "/" HASP_OBJECT_NOTATION), mqttNodeTopic,
// pageid, btnid);
// return mqttPublish(tmp_topic, payload, false);
// }
int mqtt_send_state(const char* subtopic, const char* payload)
{
char tmp_topic[strlen(mqttNodeTopic) + strlen(subtopic) + 16];
snprintf_P(tmp_topic, sizeof(tmp_topic), PSTR("%s" MQTT_TOPIC_STATE "/%s"), mqttNodeTopic, subtopic);
return mqttPublish(tmp_topic, payload, false);
String tmp_topic((char*)0);
tmp_topic.reserve(128);
tmp_topic = mqttNodeStateTopic;
// tmp_topic += MQTT_TOPIC_STATE;
// tmp_topic += "/";
tmp_topic += subtopic;
return mqttPublish(tmp_topic.c_str(), payload, false);
}
int mqtt_send_discovery(const char* payload, size_t len)
@ -216,21 +232,15 @@ static void mqtt_message_cb(const char* topic, byte* payload, unsigned int lengt
mqttReceiveCount++;
// LOG_TRACE(TAG_MQTT_RCV, F("%s = %s"), topic, (char*)payload);
if(topic == strstr(topic, mqttNodeTopic)) { // startsWith mqttNodeTopic
if(topic == strstr(topic, mqttNodeCommandTopic.c_str())) { // startsWith mqttNodeCommandTopic
topic += strlen(mqttNodeCommandTopic.c_str()); // shorten Node topic
// Node topic
topic += strlen(mqttNodeTopic); // shorten topic
} else if(topic == strstr(topic, mqttGroupTopic)) { // startsWith mqttGroupTopic
// Group topic
topic += strlen(mqttGroupTopic); // shorten topic
} else if(topic == strstr(topic, mqttGroupCommandTopic.c_str())) { // startsWith mqttGroupCommandTopic
topic += strlen(mqttGroupCommandTopic.c_str()); // shorten Group topic
#ifdef HASP_USE_BROADCAST
} else if(topic == strstr_P(topic, PSTR(MQTT_PREFIX "/" MQTT_TOPIC_BROADCAST "/"))) { // broadcast topic
// Broadcast topic
topic += strlen_P(PSTR(MQTT_PREFIX "/" MQTT_TOPIC_BROADCAST "/")); // shorten topic
} else if(topic == strstr_P(topic, mqttBroadcastCommandTopic.c_str())) { // broadcast topic
topic += strlen_P(mqttBroadcastCommandTopic.c_str()); // shorten Broadcast topic
#endif
#ifdef HASP_USE_HA
@ -241,10 +251,14 @@ static void mqtt_message_cb(const char* topic, byte* payload, unsigned int lengt
}
return;
#endif
} else if(topic == strstr(topic, mqttHassLwtTopic.c_str())) { // startsWith mqttGroupCommandTopic
String state = String((const char*)payload);
state.toLowerCase();
LOG_VERBOSE(TAG_MQTT, "Home Automation System: %s", state);
return;
} else {
// Other topic
LOG_ERROR(TAG_MQTT, F(D_MQTT_INVALID_TOPIC));
LOG_ERROR(TAG_MQTT, F(D_MQTT_INVALID_TOPIC ": %s"), topic); // Other topic
return;
}
@ -270,6 +284,7 @@ static void mqtt_message_cb(const char* topic, byte* payload, unsigned int lengt
else */
{
if(topic[0] == '/') topic++;
mqtt_process_topic_payload(topic, (const char*)payload, length);
}
@ -286,41 +301,58 @@ static void mqtt_message_cb(const char* topic, byte* payload, unsigned int lengt
} */
}
static void mqttSubscribeTo(const char* topic)
static int mqttSubscribeTo(String topic)
{
if(esp_mqtt_client_subscribe(mqttClient, topic, 0) == ESP_FAIL) {
LOG_ERROR(TAG_MQTT, F(D_MQTT_NOT_SUBSCRIBED), topic);
int err = esp_mqtt_client_subscribe(mqttClient, topic.c_str(), mqttQos);
if(err == ESP_FAIL) {
LOG_ERROR(TAG_MQTT, F(D_MQTT_NOT_SUBSCRIBED), topic.c_str());
mqttFailedCount++;
} else {
LOG_VERBOSE(TAG_MQTT, F(D_BULLET D_MQTT_SUBSCRIBED), topic);
LOG_VERBOSE(TAG_MQTT, F(D_BULLET D_MQTT_SUBSCRIBED), topic.c_str());
}
return err;
}
String mqttGetTopic(Preferences preferences, String subtopic, String key, String value, bool add_slash)
{
String topic = preferences.getString(key.c_str(), value);
topic.replace(F("%hostname%"), haspDevice.get_hostname());
topic.replace(F("%hwid%"), haspDevice.get_hardware_id());
topic.replace(F("%topic%"), subtopic);
topic.replace(F("%prefix%"), MQTT_PREFIX);
if(add_slash && !topic.endsWith("/")) {
topic += "/";
}
return topic;
}
void onMqttConnect(esp_mqtt_client_handle_t client)
{
LOG_INFO(TAG_MQTT, F(D_MQTT_CONNECTED), mqttServer, mqttClientId);
// Subscribe to our incoming topics
char topic[64];
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_COMMAND "/#"), mqttGroupTopic);
mqttSubscribeTo(topic);
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_COMMAND "/#"), mqttNodeTopic);
mqttSubscribeTo(topic);
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_CONFIG "/#"), mqttGroupTopic);
mqttSubscribeTo(topic);
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_CONFIG "/#"), mqttNodeTopic);
mqttSubscribeTo(topic);
LOG_DEBUG(TAG_MQTT, F(D_BULLET "%s"), mqttNodeCommandTopic.c_str());
LOG_DEBUG(TAG_MQTT, F(D_BULLET "%s"), mqttGroupCommandTopic.c_str());
LOG_DEBUG(TAG_MQTT, F(D_BULLET "%s"), mqttBroadcastCommandTopic.c_str());
LOG_DEBUG(TAG_MQTT, F(D_BULLET "%s"), mqttHassLwtTopic.c_str());
#if defined(HASP_USE_CUSTOM)
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_CUSTOM "/#"), mqttGroupTopic);
mqttSubscribeTo(topic);
snprintf_P(topic, sizeof(topic), PSTR("%s" MQTT_TOPIC_CUSTOM "/#"), mqttNodeTopic);
mqttSubscribeTo(topic);
#endif
// Subscribe to our incoming topics
mqttSubscribeTo(mqttGroupCommandTopic + "/#");
mqttSubscribeTo(mqttNodeCommandTopic + "/#");
#ifdef HASP_USE_BROADCAST
snprintf_P(topic, sizeof(topic), PSTR(MQTT_PREFIX "/" MQTT_TOPIC_BROADCAST "/" MQTT_TOPIC_COMMAND "/#"));
mqttSubscribeTo(topic);
mqttSubscribeTo(mqttBroadcastCommandTopic + "/#");
#endif
// subtopic = F(MQTT_TOPIC_CONFIG "/#");
// mqttSubscribeTo(mqttGroupTopic + subtopic);
// mqttSubscribeTo(mqttNodeTopic + subtopic);
#if defined(HASP_USE_CUSTOM)
subtopic = F(MQTT_TOPIC_CUSTOM "/#");
mqttSubscribeTo(mqttGroupTopic + subtopic);
mqttSubscribeTo(mqttNodeTopic + subtopic);
#endif
/* Home Assistant auto-configuration */
@ -334,6 +366,8 @@ void onMqttConnect(esp_mqtt_client_handle_t client)
}
#endif
mqttSubscribeTo(mqttHassLwtTopic);
// Force any subscribed clients to toggle offline/online when we first connect to
// make sure we get a full panel refresh at power on. Sending offline,
// "online" will be sent by the mqttStatusTopic subscription action.
@ -358,10 +392,10 @@ static void onMqttData(esp_mqtt_event_handle_t event)
static void onMqttSubscribed(esp_mqtt_event_handle_t event)
{
String topic = String(event->topic).substring(0, event->topic_len);
String msg = String(event->data).substring(0, event->data_len);
LOG_VERBOSE(TAG_MQTT, F(D_BULLET D_MQTT_SUBSCRIBED " %d %s %d"), topic.c_str(), event->topic_len, msg.c_str(),
event->data_len);
// String topic = String(event->topic).substring(0, event->topic_len);
String msg = String(event->data).substring(0, event->data_len);
const char* topic = "topic";
LOG_VERBOSE(TAG_MQTT, F(D_BULLET D_MQTT_SUBSCRIBED "(%d)"), topic, event->msg_id);
}
static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
@ -410,8 +444,8 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
case MQTT_CONNECTION_REFUSE_BAD_USERNAME: /*!< MQTT connection refused reason: Wrong user */
LOG_WARNING(TAG_MQTT, "Connection refused: Wrong user");
break;
case MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED: /*!< MQTT connection refused reason: Wrong username
or password */
case MQTT_CONNECTION_REFUSE_NOT_AUTHORIZED: /*!< MQTT connection refused reason: Wrong
username or password */
LOG_WARNING(TAG_MQTT, "Connection refused: Authentication error");
break;
default:;
@ -430,12 +464,6 @@ static esp_err_t mqtt_event_handler(esp_mqtt_event_handle_t event)
void mqttSetup()
{
Preferences preferences;
preferences.begin("mqtt", true);
String password = preferences.getString(FP_CONFIG_PASS, MQTT_PASSWORD);
strncpy(mqttPassword, password.c_str(), sizeof(mqttPassword));
LOG_DEBUG(TAG_MQTT, F(D_BULLET "Read %s => %s (%d bytes)"), FP_CONFIG_PASS, password.c_str(), password.length());
queue = xQueueCreate(64, sizeof(mqtt_message_t));
esp_crt_bundle_set(rootca_crt_bundle_start);
mqttStart();
@ -468,10 +496,45 @@ void mqttEvery5Seconds(bool networkIsConnected)
void mqttStart()
{
char buffer[64];
char lastWillPayload[8];
{
Preferences preferences;
nvs_user_begin(preferences, FP_MQTT, true);
mqttServer = preferences.getString(FP_CONFIG_HOST, mqttServer); // Update from NVS if it exists
mqttUsername = preferences.getString(FP_CONFIG_USER, mqttUsername); // Update from NVS if it exists
mqttPassword = preferences.getString(FP_CONFIG_PASS, mqttPassword); // Update from NVS if it exists
mqttPort = preferences.getUShort(FP_CONFIG_PORT, mqttPort); // Update from NVS if it exists
mqttEnabled = strlen(mqttServer) > 0 && mqttPort > 0;
String subtopic((char*)0);
subtopic.reserve(64);
String nvsOldGroup = MQTT_PREFIX "/"; // recover group setting
nvsOldGroup += preferences.getString(FP_CONFIG_GROUP, "plates");
nvsOldGroup += "/%topic%";
subtopic = F(MQTT_TOPIC_COMMAND);
mqttNodeCommandTopic =
mqttGetTopic(preferences, subtopic, FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC, false);
mqttGroupCommandTopic = mqttGetTopic(preferences, subtopic, FP_CONFIG_GROUP_TOPIC, nvsOldGroup.c_str(), false);
#ifdef HASP_USE_BROADCAST
mqttBroadcastCommandTopic =
mqttGetTopic(preferences, subtopic, FP_CONFIG_BROADCAST_TOPIC, MQTT_DEFAULT_BROADCAST_TOPIC, false);
#endif
subtopic = F(MQTT_TOPIC_STATE);
mqttNodeStateTopic = mqttGetTopic(preferences, subtopic, FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC, true);
subtopic = F(MQTT_TOPIC_LWT);
mqttNodeLwtTopic = mqttGetTopic(preferences, subtopic, FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC, false);
LOG_WARNING(TAG_MQTT, mqttNodeLwtTopic.c_str());
subtopic = F(MQTT_TOPIC_LWT);
mqttHassLwtTopic = mqttGetTopic(preferences, subtopic, FP_CONFIG_HASS_TOPIC, MQTT_DEFAULT_HASS_TOPIC, false);
LOG_WARNING(TAG_MQTT, mqttNodeLwtTopic.c_str());
preferences.end();
}
mqttEnabled = mqttServer.length() > 0 && mqttPort > 0;
if(!mqttEnabled) {
LOG_WARNING(TAG_MQTT, F(D_MQTT_NOT_CONFIGURED));
return;
@ -488,10 +551,6 @@ void mqttStart()
LOG_INFO(TAG_MQTT, mqttClientId);
}
strncpy(mqttLwtTopic, mqttNodeTopic, sizeof(mqttLwtTopic));
strncat_P(mqttLwtTopic, PSTR(MQTT_TOPIC_LWT), sizeof(mqttLwtTopic));
LOG_WARNING(TAG_MQTT, mqttLwtTopic);
mqtt_cfg.event_handle = mqtt_event_handler;
mqtt_cfg.buffer_size = MQTT_MAX_PACKET_SIZE;
mqtt_cfg.out_buffer_size = 512;
@ -502,15 +561,15 @@ void mqttStart()
mqtt_cfg.protocol_ver = MQTT_PROTOCOL_V_3_1_1;
mqtt_cfg.transport = MQTT_TRANSPORT_OVER_TCP;
mqtt_cfg.host = mqttServer;
mqtt_cfg.host = mqttServer.c_str();
mqtt_cfg.port = mqttPort;
mqtt_cfg.username = mqttUsername;
mqtt_cfg.password = mqttPassword;
mqtt_cfg.username = mqttUsername.c_str();
mqtt_cfg.password = mqttPassword.c_str();
mqtt_cfg.client_id = mqttClientId;
mqtt_cfg.lwt_msg = "offline";
mqtt_cfg.lwt_retain = true;
mqtt_cfg.lwt_topic = mqttLwtTopic;
mqtt_cfg.lwt_topic = mqttNodeLwtTopic.c_str();
mqtt_cfg.lwt_qos = 1;
mqtt_cfg.task_prio = 1;
@ -610,27 +669,73 @@ void mqtt_get_info(JsonDocument& doc)
bool mqttGetConfig(const JsonObject& settings)
{
bool changed = false;
Preferences preferences;
nvs_user_begin(preferences, FP_MQTT, false);
if(strcmp(haspDevice.get_hostname(), settings[FPSTR(FP_CONFIG_NAME)].as<String>().c_str()) != 0) changed = true;
settings[FPSTR(FP_CONFIG_NAME)] = haspDevice.get_hostname();
{
String nvsServer = preferences.getString(FP_CONFIG_HOST, mqttServer); // Read from NVS if it exists
if(strcmp(nvsServer.c_str(), settings[FP_CONFIG_HOST].as<String>().c_str()) != 0) changed = true;
settings[FP_CONFIG_HOST] = nvsServer;
}
if(strcmp(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)].as<String>().c_str()) != 0) changed = true;
settings[FPSTR(FP_CONFIG_GROUP)] = mqttGroupName;
{
String nvsUsername = preferences.getString(FP_CONFIG_USER, mqttUsername); // Read from NVS if it exists
if(strcmp(nvsUsername.c_str(), settings[FP_CONFIG_USER].as<String>().c_str()) != 0) changed = true;
settings[FP_CONFIG_USER] = nvsUsername;
}
if(strcmp(mqttServer, settings[FPSTR(FP_CONFIG_HOST)].as<String>().c_str()) != 0) changed = true;
settings[FPSTR(FP_CONFIG_HOST)] = mqttServer;
{
String nvsPassword = preferences.getString(FP_CONFIG_PASS, mqttPassword); // Read from NVS if it exists
if(strcmp(D_PASSWORD_MASK, settings[FP_CONFIG_PASS].as<String>().c_str()) != 0) changed = true;
settings[FP_CONFIG_PASS] = D_PASSWORD_MASK;
}
if(mqttPort != settings[FPSTR(FP_CONFIG_PORT)].as<uint16_t>()) changed = true;
settings[FPSTR(FP_CONFIG_PORT)] = mqttPort;
{
String nvsNodeTopic =
preferences.getString(FP_CONFIG_NODE_TOPIC, MQTT_DEFAULT_NODE_TOPIC); // Read from NVS if it exists
if(strcmp(nvsNodeTopic.c_str(), settings["topic"][FP_CONFIG_NODE].as<String>().c_str()) != 0) changed = true;
settings["topic"][FP_CONFIG_NODE] = nvsNodeTopic;
}
if(strcmp(mqttUsername, settings[FPSTR(FP_CONFIG_USER)].as<String>().c_str()) != 0) changed = true;
settings[FPSTR(FP_CONFIG_USER)] = mqttUsername;
{
String nvsOldGroup = MQTT_PREFIX "/"; // recover group setting
nvsOldGroup += preferences.getString(FP_CONFIG_GROUP, "plates");
nvsOldGroup += "/%topic%";
String nvsGroupTopic =
preferences.getString(FP_CONFIG_GROUP_TOPIC, nvsOldGroup.c_str()); // Read from NVS if it exists
if(strcmp(nvsGroupTopic.c_str(), settings["topic"][FP_CONFIG_GROUP].as<String>().c_str()) != 0) changed = true;
settings["topic"][FP_CONFIG_GROUP] = nvsGroupTopic;
}
// if(strcmp(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)].as<String>().c_str()) != 0) changed = true;
// settings[FPSTR(FP_CONFIG_PASS)] = mqttPassword;
if(strcmp(D_PASSWORD_MASK, settings[FPSTR(FP_CONFIG_PASS)].as<String>().c_str()) != 0) changed = true;
settings[FPSTR(FP_CONFIG_PASS)] = D_PASSWORD_MASK;
{
String nvsBroadcastTopic = preferences.getString(FP_CONFIG_BROADCAST_TOPIC,
MQTT_DEFAULT_BROADCAST_TOPIC); // Read from NVS if it exists
if(strcmp(nvsBroadcastTopic.c_str(), settings["topic"][FP_CONFIG_BROADCAST].as<String>().c_str()) != 0)
changed = true;
settings["topic"][FP_CONFIG_BROADCAST] = nvsBroadcastTopic;
}
{
String nvsHassTopic =
preferences.getString(FP_CONFIG_HASS_TOPIC, MQTT_DEFAULT_HASS_TOPIC); // Read from NVS if it exists
if(strcmp(nvsHassTopic.c_str(), settings["topic"][FP_CONFIG_HASS].as<String>().c_str()) != 0) changed = true;
settings["topic"][FP_CONFIG_HASS] = nvsHassTopic;
}
{
uint16_t nvsPort = preferences.getUShort(FP_CONFIG_PORT, mqttPort); // Read from NVS if it exists
if(nvsPort != settings[FP_CONFIG_PORT].as<uint16_t>()) changed = true;
settings[FP_CONFIG_PORT] = nvsPort;
}
if(strcmp(haspDevice.get_hostname(), settings[FP_CONFIG_NAME].as<String>().c_str()) != 0) changed = true;
settings[FP_CONFIG_NAME] = haspDevice.get_hostname();
// if(strcmp(mqttGroupName, settings[FP_CONFIG_GROUP].as<String>().c_str()) != 0) changed = true;
// settings[FP_CONFIG_GROUP] = mqttGroupName;
preferences.end();
if(changed) configOutput(settings, TAG_MQTT);
return changed;
}
@ -646,17 +751,20 @@ bool mqttGetConfig(const JsonObject& settings)
bool mqttSetConfig(const JsonObject& settings)
{
Preferences preferences;
preferences.begin("mqtt", false);
nvs_user_begin(preferences, FP_MQTT, false);
configOutput(settings, TAG_MQTT);
bool changed = false;
changed |= configSet(mqttPort, settings[FPSTR(FP_CONFIG_PORT)], F("mqttPort"));
if(!settings[FP_CONFIG_PORT].isNull()) {
// changed |= configSet(mqttPort, settings[FP_CONFIG_PORT], F("mqttPort"));
changed |= nvsUpdateString(preferences, FP_CONFIG_PORT, settings[FP_CONFIG_PORT]);
}
if(!settings[FPSTR(FP_CONFIG_NAME)].isNull()) {
changed |= strcmp(haspDevice.get_hostname(), settings[FPSTR(FP_CONFIG_NAME)]) != 0;
// strncpy(mqttNodeName, settings[FPSTR(FP_CONFIG_NAME)], sizeof(mqttNodeName));
haspDevice.set_hostname(settings[FPSTR(FP_CONFIG_NAME)].as<const char*>());
if(!settings[FP_CONFIG_NAME].isNull()) {
changed |= strcmp(haspDevice.get_hostname(), settings[FP_CONFIG_NAME]) != 0;
// strncpy(mqttNodeName, settings[FP_CONFIG_NAME], sizeof(mqttNodeName));
haspDevice.set_hostname(settings[FP_CONFIG_NAME].as<const char*>());
}
// Prefill node name
if(strlen(haspDevice.get_hostname()) == 0) {
@ -668,36 +776,57 @@ bool mqttSetConfig(const JsonObject& settings)
changed = true;
}
if(!settings[FPSTR(FP_CONFIG_GROUP)].isNull()) {
changed |= strcmp(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)]) != 0;
strncpy(mqttGroupName, settings[FPSTR(FP_CONFIG_GROUP)], sizeof(mqttGroupName));
if(!settings[FP_CONFIG_GROUP].isNull()) {
// changed |= strcmp(mqttGroupName, settings[FP_CONFIG_GROUP]) != 0;
// strncpy(mqttGroupName, settings[FP_CONFIG_GROUP], sizeof(mqttGroupName));
changed |= nvsUpdateString(preferences, FP_CONFIG_GROUP, settings[FP_CONFIG_GROUP]);
}
if(strlen(mqttGroupName) == 0) {
strcpy_P(mqttGroupName, PSTR("plates"));
changed = true;
// if(strlen(mqttGroupName) == 0) {
// strcpy_P(mqttGroupName, PSTR("plates"));
// changed = true;
// }
if(!settings[FP_CONFIG_HOST].isNull()) {
// changed |= strcmp(mqttServer, settings[FP_CONFIG_HOST]) != 0;
// strncpy(mqttServer, settings[FP_CONFIG_HOST], sizeof(mqttServer));
changed |= nvsUpdateString(preferences, FP_CONFIG_HOST, settings[FP_CONFIG_HOST]);
}
if(!settings[FPSTR(FP_CONFIG_HOST)].isNull()) {
changed |= strcmp(mqttServer, settings[FPSTR(FP_CONFIG_HOST)]) != 0;
strncpy(mqttServer, settings[FPSTR(FP_CONFIG_HOST)], sizeof(mqttServer));
if(!settings[FP_CONFIG_USER].isNull()) {
// changed |= strcmp(mqttUsername, settings[FP_CONFIG_USER]) != 0;
// strncpy(mqttUsername, settings[FP_CONFIG_USER], sizeof(mqttUsername));
changed |= nvsUpdateString(preferences, FP_CONFIG_USER, settings[FP_CONFIG_USER]);
}
if(!settings[FPSTR(FP_CONFIG_USER)].isNull()) {
changed |= strcmp(mqttUsername, settings[FPSTR(FP_CONFIG_USER)]) != 0;
strncpy(mqttUsername, settings[FPSTR(FP_CONFIG_USER)], sizeof(mqttUsername));
if(!settings[FP_CONFIG_PASS].isNull() && settings[FP_CONFIG_PASS].as<String>() != String(D_PASSWORD_MASK)) {
// changed |= strcmp(mqttPassword, settings[FP_CONFIG_PASS]) != 0;
// strncpy(mqttPassword, settings[FP_CONFIG_PASS], sizeof(mqttPassword));
changed |= nvsUpdateString(preferences, FP_CONFIG_PASS, settings[FP_CONFIG_PASS]);
}
if(!settings[FPSTR(FP_CONFIG_PASS)].isNull() &&
settings[FPSTR(FP_CONFIG_PASS)].as<String>() != String(FPSTR(D_PASSWORD_MASK))) {
changed |= strcmp(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)]) != 0;
strncpy(mqttPassword, settings[FPSTR(FP_CONFIG_PASS)], sizeof(mqttPassword));
nvsUpdateString(preferences, FP_CONFIG_PASS, settings[FPSTR(FP_CONFIG_PASS)]);
JsonVariant topic;
topic = settings["topic"][FP_CONFIG_NODE];
if(topic.is<const char*>()) {
changed |= nvsUpdateString(preferences, FP_CONFIG_NODE_TOPIC, topic);
}
topic = settings["topic"][FP_CONFIG_GROUP];
if(topic.is<const char*>()) {
changed |= nvsUpdateString(preferences, FP_CONFIG_GROUP_TOPIC, topic);
}
topic = settings["topic"][FP_CONFIG_BROADCAST];
if(topic.is<const char*>()) {
changed |= nvsUpdateString(preferences, FP_CONFIG_BROADCAST_TOPIC, topic);
}
topic = settings["topic"][FP_CONFIG_HASS];
if(topic.is<const char*>()) {
changed |= nvsUpdateString(preferences, FP_CONFIG_HASS_TOPIC, topic);
}
snprintf_P(mqttNodeTopic, sizeof(mqttNodeTopic), PSTR(MQTT_PREFIX "/%s/"), haspDevice.get_hostname());
snprintf_P(mqttGroupTopic, sizeof(mqttGroupTopic), PSTR(MQTT_PREFIX "/%s/"), mqttGroupName);
// snprintf_P(mqttNodeTopic, sizeof(mqttNodeTopic), PSTR(MQTT_PREFIX "/%s/"), haspDevice.get_hostname());
// snprintf_P(mqttGroupTopic, sizeof(mqttGroupTopic), PSTR(MQTT_PREFIX "/%s/"), mqttGroupName);
preferences.end();
return changed;
}
#endif // HASP_USE_CONFIG

View File

@ -1413,14 +1413,10 @@ static void http_handle_mqtt()
<h2 v-t="'mqtt.title'"></h2>
<div class="container" v-cloak v-if="config.mqtt">
<form @submit.prevent="submitOldConfig('mqtt') ">
<div class="row">
<div class="row gap">
<div class="col-25"><label class="required" for="name" v-t="'mqtt.name'"></label></div>
<div class="col-75"><input required="" type="text" id="name" maxlength="63" pattern="[a-z0-9_]*" placeholder="Plate Name" v-model="config.mqtt.name"></div>
</div>
<div class="row gap">
<div class="col-25"><label for="group" v-t="'mqtt.group'"></label></div>
<div class="col-75"><input type="text" id="group" maxlength="15" pattern="[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9]" placeholder="Group Name" v-model="config.mqtt.group"></div>
</div>
<div class="row">
<div class="col-25"><label for="host" v-t="'mqtt.host'"></label></div>
<div class="col-75"><input type="text" id="host" maxlength="127" placeholder="Server Name" v-model="config.mqtt.host"></div>