Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WebUI] Add Configure MQTT and Logging #1592

Merged
merged 8 commits into from
Apr 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions main/User_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,11 @@ CRGB leds2[FASTLED_IND_NUM_LEDS];
char mqtt_topic[parameters_size + 1] = Base_Topic;
char gateway_name[parameters_size + 1] = Gateway_Name;

void connectMQTT();
#ifndef ESPWifiManualSetup
void saveMqttConfig();
#endif

unsigned long uptime();
bool cmpToMainTopic(const char*, const char*);
void pub(const char*, const char*, bool);
Expand Down
178 changes: 124 additions & 54 deletions main/ZwebUI.ino
Original file line number Diff line number Diff line change
Expand Up @@ -466,15 +466,48 @@ void handleWI() {

/**
* @brief /MQ - Configure MQTT Page
*
* T: handleMQ Arg: 0, mh=192.168.1.17
* T: handleMQ Arg: 1, ml=1883
* T: handleMQ Arg: 2, mu=your_username
* T: handleMQ Arg: 3, mp=your_password
* T: handleMQ Arg: 4, sc=on
* T: handleMQ Arg: 5, msc=suds
* T: handleMQ Arg: 6, mt=home/
* T: handleMQ Arg: 7, save=
*/
void handleMQ() {
WEBUI_TRACE_LOG(F("handleMQ: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
if (server.args()) {
for (uint8_t i = 0; i < server.args(); i++) {
WEBUI_TRACE_LOG(F("handleMQ Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
}
if (server.hasArg("save")) {
if (server.hasArg("mh")) {
strncpy(mqtt_server, server.arg("mh").c_str(), parameters_size);
}
if (server.hasArg("ml")) {
strncpy(mqtt_port, server.arg("ml").c_str(), 6);
}
if (server.hasArg("mu")) {
strncpy(mqtt_user, server.arg("mu").c_str(), parameters_size);
}
if (server.hasArg("mp")) {
strncpy(mqtt_pass, server.arg("mp").c_str(), parameters_size);
}
mqtt_secure = server.hasArg("sc");
if (server.hasArg("msc")) {
mqtt_cert = server.arg("msc"); // String
}
if (server.hasArg("mt")) {
strncpy(mqtt_topic, server.arg("mt").c_str(), parameters_size);
}
# ifndef ESPWifiManualSetup
saveMqttConfig();
connectMQTT();
# endif
}
}

char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1);

Expand All @@ -484,8 +517,42 @@ void handleMQ() {
String response = String(buffer);
response += String(script);
response += String(style);
// mqtt server, mqtt port, client id, mqtt username, mqtt password, topic, Full Topic
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, mqtt_server, mqtt_port, gateway_name, mqtt_user, mqtt_pass, mqtt_topic, "");
// mqtt server (mh), mqtt port (ml), mqtt username (mu), mqtt password (mp), secure connection (sc), server certificate (msc), topic (mt)
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_mqtt_body, jsonChar, gateway_name, mqtt_server, mqtt_port, mqtt_user, mqtt_pass, (mqtt_secure ? "checked" : ""), mqtt_cert, mqtt_topic);
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
server.send(200, "text/html", response);
}

/**
* @brief /LO - Configure Logging Page
* T: handleLO: uri: /lo, args: 2, method: 1
* T: handleLO Arg: 0, lo=5
* T: handleLO Arg: 1, save=
*/
void handleLO() {
WEBUI_TRACE_LOG(F("handleLO: uri: %s, args: %d, method: %d" CR), server.uri(), server.args(), server.method());
if (server.args()) {
for (uint8_t i = 0; i < server.args(); i++) {
WEBUI_TRACE_LOG(F("handleLO Arg: %d, %s=%s" CR), i, server.argName(i).c_str(), server.arg(i).c_str());
}
if (server.hasArg("save") && server.hasArg("lo")) {
Log.setLevel(server.arg("lo").toInt());
}
}

char jsonChar[100];
serializeJson(modules, jsonChar, measureJson(modules) + 1);

char buffer[WEB_TEMPLATE_BUFFER_MAX_SIZE];

snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, header_html, (String(gateway_name) + " - Configure Logging").c_str());
String response = String(buffer);
response += String(script);
response += String(style);
int logLevel = Log.getLevel();
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, config_logging_body, jsonChar, gateway_name, (logLevel == 0 ? "selected" : ""), (logLevel == 1 ? "selected" : ""), (logLevel == 2 ? "selected" : ""), (logLevel == 3 ? "selected" : ""), (logLevel == 4 ? "selected" : ""), (logLevel == 5 ? "selected" : ""), (logLevel == 6 ? "selected" : ""));
response += String(buffer);
snprintf(buffer, WEB_TEMPLATE_BUFFER_MAX_SIZE, footer, OMG_VERSION);
response += String(buffer);
Expand Down Expand Up @@ -837,12 +904,13 @@ void WebUISetup() {
server.on("/up", handleUP); // Firmware Upgrade

server.on("/cn", handleCN); // Configuration
server.on("/wi", handleWI); // Configuration Wifi
server.on("/mq", handleMQ); // Configuration MQTT
server.on("/wi", handleWI); // Configure Wifi
server.on("/mq", handleMQ); // Configure MQTT
# if defined(ZgatewayCloud)
server.on("/cl", handleCL); // Cloud configuration
server.on("/cl", handleCL); // Configure Cloud
server.on("/tk", handleTK); // Store Device Token
# endif
server.on("/lo", handleLO); // Configure Logging

server.on("/rt", handleRT); // Reset configuration ( Erase and Restart )
server.begin();
Expand Down Expand Up @@ -1043,72 +1111,74 @@ void webUIPubPrint(const char* topicori, JsonObject& data) {

# ifdef ZgatewayRTL_433
case webUIHash("RTL_433toMQTT"): {
// {"model":"Acurite-Tower","id":2043,"channel":"B","battery_ok":1,"temperature_C":5.3,"humidity":81,"mic":"CHECKSUM","protocol":"Acurite 592TXR Temp/Humidity, 5n1 Weather Station, 6045 Lightning, 3N1, Atlas","rssi":-81,"duration":121060}
if (!strncmp(data["model"], "status", 6) && data.containsKey("id")) {
// {"model":"Acurite-Tower","id":2043,"channel":"B","battery_ok":1,"temperature_C":5.3,"humidity":81,"mic":"CHECKSUM","protocol":"Acurite 592TXR Temp/Humidity, 5n1 Weather Station, 6045 Lightning, 3N1, Atlas","rssi":-81,"duration":121060}

// Line 1
// Line 1

strlcpy(message->line1, data["model"], WEBUI_TEXT_WIDTH);
strlcpy(message->line1, data["model"], WEBUI_TEXT_WIDTH);

// Line 2
// Line 2

String id = data["id"];
String channel = data["channel"];
String line2 = "id: " + id + " channel: " + channel;
line2.toCharArray(message->line2, WEBUI_TEXT_WIDTH);
String id = data["id"];
String channel = data["channel"];
String line2 = "id: " + id + " channel: " + channel;
line2.toCharArray(message->line2, WEBUI_TEXT_WIDTH);

// Line 3
// Line 3

String line3 = "";
String line3 = "";

if (data.containsKey("temperature_C")) {
float temperature_C = data["temperature_C"];
char temp[5];
if (data.containsKey("temperature_C")) {
float temperature_C = data["temperature_C"];
char temp[5];

if (displayMetric) {
dtostrf(temperature_C, 3, 1, temp);
line3 = "temp: " + (String)temp + "°C ";
} else {
dtostrf(convertTemp_CtoF(temperature_C), 3, 1, temp);
line3 = "temp: " + (String)temp + "°F ";
if (displayMetric) {
dtostrf(temperature_C, 3, 1, temp);
line3 = "temp: " + (String)temp + "°C ";
} else {
dtostrf(convertTemp_CtoF(temperature_C), 3, 1, temp);
line3 = "temp: " + (String)temp + "°F ";
}
}
}

float humidity = data["humidity"];
if (data.containsKey("humidity") && humidity <= 100 && humidity >= 0) {
char hum[5];
dtostrf(humidity, 3, 1, hum);
line3 += "hum: " + (String)hum + "% ";
}
if (data.containsKey("wind_avg_km_h")) {
float wind_avg_km_h = data["wind_avg_km_h"];
char wind[6];
float humidity = data["humidity"];
if (data.containsKey("humidity") && humidity <= 100 && humidity >= 0) {
char hum[5];
dtostrf(humidity, 3, 1, hum);
line3 += "hum: " + (String)hum + "% ";
}
if (data.containsKey("wind_avg_km_h")) {
float wind_avg_km_h = data["wind_avg_km_h"];
char wind[6];

if (displayMetric) {
dtostrf(wind_avg_km_h, 3, 1, wind);
line3 += "wind: " + (String)wind + "km/h ";
} else {
dtostrf(convert_kmph2mph(wind_avg_km_h), 3, 1, wind);
line3 += "wind: " + (String)wind + "mp/h ";
if (displayMetric) {
dtostrf(wind_avg_km_h, 3, 1, wind);
line3 += "wind: " + (String)wind + "km/h ";
} else {
dtostrf(convert_kmph2mph(wind_avg_km_h), 3, 1, wind);
line3 += "wind: " + (String)wind + "mp/h ";
}
}
}

line3.toCharArray(message->line3, WEBUI_TEXT_WIDTH);
line3.toCharArray(message->line3, WEBUI_TEXT_WIDTH);

// Line 4
// Line 4

String rssi = data["rssi"];
String battery_ok = data["battery_ok"];
String rssi = data["rssi"];
String battery_ok = data["battery_ok"];

String line4 = "batt: " + battery_ok + " rssi: " + rssi;
line4.toCharArray(message->line4, WEBUI_TEXT_WIDTH);
String line4 = "batt: " + battery_ok + " rssi: " + rssi;
line4.toCharArray(message->line4, WEBUI_TEXT_WIDTH);

// Queue completed message
// Queue completed message

if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message);
} else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
if (xQueueSend(webUIQueue, (void*)&message, 0) != pdTRUE) {
Log.error(F("[ WebUI ] webUIQueue full, discarding signal %s" CR), message->title);
free(message);
} else {
// Log.notice(F("[ WebUI ] Queued %s" CR), message->title);
}
}
break;
}
Expand Down
14 changes: 8 additions & 6 deletions main/config_WebContent.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
// TODO: Create a script to generate these from WebPack

#define body_footer_main_menu "<div id=but2d style=\"display: block;\"></div><p><form id=but2 style=\"display: block;\" action='.' method='get'><button>Main Menu</button></form></p>"
#define body_footer_config_menu "<div id=but3d style=\"display: block;\"></div><p><form id=but3 style=\"display: block;\" action='cn' method='get'><button>Configuration</button></form></p>";
#define body_footer_config_menu "<div id=but3d style=\"display: block;\"></div><p><form id=but3 style=\"display: block;\" action='cn' method='get'><button>Configuration</button></form></p>"
#define body_header "<body><div style='text-align:left;display:inline-block;min-width:340px;'><div style='text-align:center;'><noscript> To use, please enable JavaScript <br></noscript><h3>%s</h3><h2>%s</h2></div>"

#define button_upgrade "<p><form id=but5 style='display: block;' action='up' method='get'><button>Firmware Upgrade</button></form></p>"
Expand All @@ -45,7 +45,7 @@
#else
# define configure_3
#endif
#define configure_4
#define configure_4 "<p><form action='lo' method='get'><button>Configure Logging</button></form></p>"
#define configure_5
#define configure_6
#define configure_7
Expand Down Expand Up @@ -75,19 +75,21 @@ const char reset_body[] = body_header "<div style='text-align:center;'>%s</div><

const char config_cloud_body[] = body_header "<fieldset><legend><b>&nbsp;Cloud Configuration&nbsp;</b></legend><form method='get' action='cl'><p><label><input id='cl-en' type='checkbox' %s><b>Enable Cloud Connection</b></label></p><br><p><label><input id='cl-lk' type='checkbox' disabled><b>Cloud Account%s Linked</b></label></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset><p><form action='%s' method='get'><input type='hidden' name='macAddress' value='%s'/><input type='hidden' name='redirect_uri' value='%s'/><input type='hidden' name='gateway_name' value='%s'/><input type='hidden' name='uptime' value='%d'/><input type='hidden' name='RT' value='%d'/><button>Link Cloud Account</button></form></p>" body_footer_config_menu;

const char token_body[] = body_header "div style='text-align:center;'>Link Cloud Account</div><br><div style='text-align:center;'>Cloud was successfully linked</div><br><div id=but2d style=\"display: block;\"></div><p><form id=but2 style=\"display: block;\" action='cn' method='get'><button>Configuration</button></form></p>";
const char token_body[] = body_header "<div style='text-align:center;'>Link Cloud Account</div><br><div style='text-align:center;'>Cloud was successfully linked</div><br><div id=but2d style=\"display: block;\"></div><p><form id=but2 style=\"display: block;\" action='cn' method='get'><button>Configuration</button></form></p>";

const char console_body[] = body_header "<br><textarea readonly id='t1' cols='340' wrap='off'></textarea><br><br><form method='get' onsubmit='return l(1);'><input id='c1' placeholder='Enter topic and command' autofocus><br></form>" body_footer_main_menu;

const char information_body[] = body_header "<style>td {padding: 0px 5px;}</style><div id='i' name='i'></div>" body_footer_main_menu;

const char upgrade_body[] = body_header " <div id='f1' style='display:block;'><fieldset><legend><b>&nbsp;Upgrade by web server&nbsp;</b></legend><form method='get' action='u1'><br><b>OTA Url</b><br><input id='o' placeholder=\"OTA_URL\" value=\"%s\"><br><br><button type='submit'>Start upgrade</button></form></fieldset><br><br><fieldset><legend><b>&nbsp;Upgrade by file upload&nbsp;</b></legend><form method='post' action='u2' enctype='multipart/form-data'><br><input type='file' name='u2'><br><br><button type='submit' onclick='eb(\"f1\").style.display=\"none\";eb(\"f2\").style.display=\"block\";this.form.submit();'>Start upgrade</button></form></fieldset></div><div id='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div><div id=but2d style=\"display: block;\"></div><p>" body_footer_main_menu;
const char upgrade_body[] = body_header "<div id='f1' style='display:block;'><fieldset><legend><b>&nbsp;Upgrade by web server&nbsp;</b></legend><form method='get' action='u1'><br><b>OTA Url</b><br><input id='o' placeholder=\"OTA_URL\" value=\"%s\"><br><br><button type='submit'>Start upgrade</button></form></fieldset><br><br><fieldset><legend><b>&nbsp;Upgrade by file upload&nbsp;</b></legend><form method='post' action='u2' enctype='multipart/form-data'><br><input type='file' name='u2'><br><br><button type='submit' onclick='eb(\"f1\").style.display=\"none\";eb(\"f2\").style.display=\"block\";this.form.submit();'>Start upgrade</button></form></fieldset></div><div id='f2' style='display:none;text-align:center;'><b>Upload started ...</b></div><div id=but2d style=\"display: block;\"></div><p>" body_footer_main_menu;

const char config_wifi_body[] = body_header "<div title='-43 dBm (100%)'><a href='#p' onclick='c(this)'>%s</a><span class='q'><div class='si'><i class='b0'></i><i class='b1'></i><i class='b2'></i><i class='b3'></i></span></div></div><div title='-84 dBm (32%)'><a href='#p' onclick='c(this)'>BELL634</a><span class='q'><div class='si'><i class='b0'></i><i class='b1'></i><i class='b2 o30'></i><i class='b3 o30'></i></span></div></div><div title='-86 dBm (28%)'><a href='#p' onclick='c(this)'>MRC</a><span class='q'><div class='si'><i class='b0'></i><i class='b1'></i><i class='b2 o30'></i><i class='b3 o30'></i></span></div></div><br><div><a href='/wi?scan='>Scan for all WiFi Networks</a></div><br><fieldset><legend><b>&nbsp;Wifi parameters&nbsp;</b></legend><form method='get' action='wi'><p><b>WiFi Network</b> () <br><input id='s1' placeholder=\"Type or Select your WiFi Network\" value=\"%s\"></p><p><label><b>WiFi Password</b><input type='checkbox' onclick='sp(\"p1\")'></label><br><input id='p1' type='password' placeholder=\"Enter your WiFi Password\" value=\"****\"></p><p><b>WiFi Network 2</b> () <br><input id='s2' placeholder=\"Type your Alternative WiFi Network\" value=\"\"></p><p><label><b>WiFi Password</b><input type='checkbox' onclick='sp(\"p2\")'></label><br><input id='p2' type='password' placeholder=\"Enter your WiFi Password\" value=\"****\"></p><p><b>Hostname</b>%s<br><input id='h' placeholder=\"%s\" value=\"%s\"></p><p><b>CORS Domain</b><input id='c' placeholder=\"\" value=\"%s\"></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;

// mqtt server, mqtt port, client id, mqtt username, mqtt password, topic, Full Topic
// mqtt server (mh), mqtt port (ml), mqtt username (mu), mqtt password (mp), secure connection (sc), server certificate (msc), topic (mt)

const char config_mqtt_body[] = body_header "<fieldset><legend><b>&nbsp;MQTT parameters&nbsp;</b></legend><form method='get' action='mq'><p><b>Host</b> () <br><input id='mh' placeholder=" MQTT_SERVER " value='%s'></p><p><b>Port</b> (1883) <br><input id='ml' placeholder=" MQTT_PORT " value='%s'></p><p><b>Client</b> <br><input id='mc' placeholder='' value='%s'></p><p><b>User</b> " MQTT_USER " <br><input id='mu' placeholder=" MQTT_USER " value='%s'></p><p><label><b>Password</b><input type='checkbox' onclick='sp(\"mp\")'></label><br><input id='mp' type='password' placeholder=\"Password\" value='%s'></p><p><b>Topic</b> <br><input id='mt' placeholder='' value='%s'></p><p><b>Full Topic</b> <br><input id='mf' placeholder=\"\" value='%s'></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;
const char config_mqtt_body[] = body_header "<fieldset><legend><b>&nbsp;MQTT parameters&nbsp;</b></legend><form method='get' action='mq'><p><b>MQTT Server</b><br><input id='mh' placeholder=" MQTT_SERVER " value='%s'></p><p><b>MQTT Port</b><br><input id='ml' placeholder=" MQTT_PORT " value='%s'></p><p><b>MQTT Username</b><br><input id='mu' placeholder=" MQTT_USER " value='%s'></p><p><label><b>MQTT Password</b><input type='checkbox' onclick='sp(\"mp\")'></label><br><input id='mp' type='password' placeholder=\"Password\" value='%s'></p><p><b>MQTT Secure Connection</b><br><input id='sc' type='checkbox' %s></p><p><b>MQTT Server Certificate</b><br><textarea class='form-control' name='msc' id='field_msc' rows='10' cols='64'>%s</textarea></p><p><b>MQTT Base Topic</b><br><input id='mt' placeholder='' value='%s'></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;

const char config_logging_body[] = body_header "<fieldset><legend><b>OpenMQTTGateway Logging</b></legend><form method='get' action='lo'><p><b>log level</b><br><select id='lo'><option %s value='0'>Silent</option><option %s value='1'>Fatal</option><option %s value='2'>Error</option><option %s value='3'>Warning</option><option %s value='4'>Notice</option><option %s value='5'>Trace</option><option %s value='6'>Verbose</option></select></p><br><button name='save' type='submit' class='button bgrn'>Save</button></form></fieldset>" body_footer_config_menu;

const char footer[] = "<div style='text-align:right;font-size:11px;'><hr/><a href='https://community.openmqttgateway.com' target='_blank' style='color:#aaa;'>%s</a></div></div></body></html>";

Expand Down
10 changes: 7 additions & 3 deletions main/main.ino
Original file line number Diff line number Diff line change
Expand Up @@ -585,6 +585,9 @@ void delayWithOTA(long waitMillis) {
# endif
# endif
ArduinoOTA.handle();
# if defined(ZwebUI) && defined(ESP32)
WebUILoop();
# endif
delay(waitStep);
}
#else
Expand Down Expand Up @@ -1589,6 +1592,9 @@ void loop() {
if ((Ethernet.hardwareStatus() != EthernetW5100 && Ethernet.linkStatus() == LinkON) || (Ethernet.hardwareStatus() == EthernetW5100)) { //we are able to detect disconnection only on w5200 and w5500
#endif
failure_number_ntwk = 0;
#if defined(ZwebUI) && defined(ESP32)
WebUILoop();
#endif
if (client.loop()) { // MQTT client is still connected
InfoIndicatorON();
failure_number_ntwk = 0;
Expand Down Expand Up @@ -1743,9 +1749,7 @@ void loop() {
launchRTL_433Discovery(publishDiscovery);
# endif
#endif
#if defined(ZwebUI) && defined(ESP32)
WebUILoop();
#endif

} else {
// MQTT disconnected
connected = false;
Expand Down