[codex] add web controls for wifi reconnect espnow on off and mqtt publish #8

Merged
electron-rare merged 2 commits from codex/web-network-controls-latest into audit/telephony-webserver 2026-02-20 22:58:43 +00:00
3 changed files with 57 additions and 2 deletions
+6
View File
@@ -46,6 +46,7 @@
</form>
<div class="inline-actions">
<button id="wifiDisconnectBtn">Déconnecter WiFi</button>
<button id="wifiReconnectBtn">Reconnecter WiFi</button>
<button id="wifiScanBtn">Scanner WiFi</button>
</div>
<pre id="wifiJson"></pre>
@@ -57,6 +58,11 @@
<button id="mqttConnectBtn">Connecter MQTT</button>
<button id="mqttDisconnectBtn">Déconnecter MQTT</button>
</div>
<form id="mqttPublishForm">
<input type="text" id="mqttTopic" placeholder="Topic (ex: rtc_bl_phone/a252/test)" required>
<textarea id="mqttPayload" rows="3" placeholder='Payload JSON ou texte'>{"ping":true}</textarea>
<button type="submit">Publier MQTT</button>
</form>
<pre id="mqttJson"></pre>
</div>
+45 -2
View File
@@ -169,6 +169,20 @@ function bindEvents() {
}
});
document.getElementById("wifiReconnectBtn").addEventListener("click", async () => {
try {
const result = await requestJson("/api/network/wifi/reconnect", {
method: "POST",
headers: jsonHeaders(),
body: "{}",
});
setJson("actionResult", result);
await Promise.all([refreshStatus(), refreshNetwork()]);
} catch (error) {
setJson("actionResult", { error: error.message });
}
});
document.getElementById("wifiScanBtn").addEventListener("click", async () => {
try {
const result = await requestJson("/api/network/wifi/scan", {
@@ -211,9 +225,32 @@ function bindEvents() {
}
chatgpt-codex-connector[bot] commented 2026-02-20 22:51:08 +00:00 (Migrated from github.com)
Review

P2 Badge Keep MQTT publish payload as raw text

When the payload starts with { or [, parsePayloadValue turns it into an object/array, but the server-side /api/network/mqtt/publish handler reads doc["payload"] into a String (const String payload = doc["payload"] | ""), which falls back to an empty string for non-string JSON values. In practice, submitting JSON payloads (including the default {"ping":true} shown in the new form) publishes an empty payload instead of the intended message.

Useful? React with 👍 / 👎.

**<sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> Keep MQTT publish payload as raw text** When the payload starts with `{` or `[`, `parsePayloadValue` turns it into an object/array, but the server-side `/api/network/mqtt/publish` handler reads `doc["payload"]` into a `String` (`const String payload = doc["payload"] | ""`), which falls back to an empty string for non-string JSON values. In practice, submitting JSON payloads (including the default `{"ping":true}` shown in the new form) publishes an empty payload instead of the intended message. Useful? React with 👍 / 👎.
});
document.getElementById("mqttPublishForm").addEventListener("submit", async (event) => {
event.preventDefault();
const topic = document.getElementById("mqttTopic").value.trim();
const payload = document.getElementById("mqttPayload").value;
try {
const result = await requestJson("/api/network/mqtt/publish", {
method: "POST",
headers: jsonHeaders(),
body: JSON.stringify({ topic, payload }),
});
setJson("actionResult", result);
await Promise.all([refreshStatus(), refreshNetwork()]);
} catch (error) {
setJson("actionResult", { error: error.message });
}
});
document.getElementById("espnowOnBtn").addEventListener("click", async () => {
try {
await sendControl("ESPNOW_ON");
const result = await requestJson("/api/network/espnow/on", {
method: "POST",
headers: jsonHeaders(),
body: "{}",
});
setJson("actionResult", result);
await Promise.all([refreshStatus(), refreshNetwork()]);
} catch (error) {
setJson("actionResult", { error: error.message });
}
@@ -221,7 +258,13 @@ function bindEvents() {
document.getElementById("espnowOffBtn").addEventListener("click", async () => {
try {
await sendControl("ESPNOW_OFF");
const result = await requestJson("/api/network/espnow/off", {
method: "POST",
headers: jsonHeaders(),
body: "{}",
});
setJson("actionResult", result);
await Promise.all([refreshStatus(), refreshNetwork()]);
} catch (error) {
setJson("actionResult", { error: error.message });
}
+6
View File
@@ -148,6 +148,8 @@ void WebServerManager::registerRoutes() {
});
server_.on("/api/network/wifi/disconnect", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "WIFI_DISCONNECT"); });
server_.on("/api/network/wifi/reconnect", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "WIFI_RECONNECT"); });
server_.on("/api/network/wifi/scan", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "WIFI_SCAN"); });
@@ -176,6 +178,10 @@ void WebServerManager::registerRoutes() {
// ESP-NOW.
server_.on("/api/network/espnow", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "ESPNOW_STATUS"); });
server_.on("/api/network/espnow/on", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "ESPNOW_ON"); });
server_.on("/api/network/espnow/off", HTTP_POST,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "ESPNOW_OFF"); });
server_.on("/api/network/espnow/peer", HTTP_GET,
[this](AsyncWebServerRequest* request) { handleDispatch(request, "ESPNOW_PEER_LIST"); });
server_.on("/api/network/espnow/peer", HTTP_POST, [this](AsyncWebServerRequest* request) {