Skip to content

Mqtt#135

Open
corrancho wants to merge 9 commits into
espressif:masterfrom
corrancho:mqtt
Open

Mqtt#135
corrancho wants to merge 9 commits into
espressif:masterfrom
corrancho:mqtt

Conversation

@corrancho

Copy link
Copy Markdown

Description

Related

Testing


Checklist

Before submitting a Pull Request, please ensure the following:

  • 🚨 This PR does not introduce breaking changes.
  • All CI checks (GH Actions) pass.
  • Documentation is updated as needed.
  • Tests are updated or added as necessary.
  • Code is well-commented, especially in complex areas.
  • Git history is clean — commits are squashed to the minimum necessary.

Wrap the ESP-IDF esp-mqtt client in a new lua_module_mqtt component, add the APP_CLAW_LUA_MODULE_MQTT Kconfig option and app_claw registration, enable it in the edge_agent defaults, and document the module in the EN/ZH lua-modules reference.
Store broker URL, username, password, and client id in settings_store
(NVS) and expose them through a dedicated MqttPage in the web config UI,
following the per-subsystem page pattern.

The values flow app_config -> app_claw_config -> the Lua mqtt module via
lua_module_mqtt_set_defaults(), so scripts can call mqtt.new() with no
arguments to reuse the configured broker, or override per call.
@CLAassistant

CLAassistant commented Jun 26, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Add MQTT JWT authentication (for brokers like EMQX) and protect the MQTT
settings behind a developer-mode switch, in the edge_agent app only
(mcp_server_point has no MQTT config).

JWT auth:
- New persisted field mqtt_jwt across the config chain: app_config
  struct/defaults/NVS field, app_claw config struct, config API field,
  and the frontend AppConfig + mqtt group. The lua_module_mqtt module is
  not touched.
- JWT gets its own 1024-byte buffer (APP_CONFIG_MQTT_JWT_LEN /
  APP_CLAW_MQTT_JWT_LEN) instead of reusing the 320-byte string length —
  EMQX JWTs with claims easily exceed 320 and would otherwise truncate.
- Auth selection lives where the broker defaults are seeded
  (app_lua_register_mqtt): when mqtt_jwt is set it is passed in the
  password slot and takes priority; otherwise the plain password is used,
  so username/password auth is unchanged when no JWT is configured.
- Frontend: a separate "JWT Token" password field on the MQTT page.

Developer mode (mirrors FilesPage):
- A dev-mode toggle that starts OFF and asks for confirmation when
  enabled. While OFF the MQTT fields are read-only and Save is disabled;
  enabling it unlocks editing and the destructive action.
- A "Clear credentials" button, enabled only in dev mode (with a confirm
  and a guard), wipes all MQTT credentials (uri, username, password, jwt)
  to empty in NVS.
- New i18n keys (en + zh-cn) for the JWT field, dev mode, and clearing.

Verified on hardware: a 441-char JWT persists intact (would truncate at
320), and clearing empties all four MQTT fields.
Add a "Test connection" button that probes the stored MQTT broker
credentials on demand. There is no persistent app-level MQTT connection
to read, so this is a one-shot probe, not a live monitor.

- New endpoint POST /api/mqtt/probe (in http_server_config_api.c): loads
  the saved config, spins up a throwaway esp-mqtt client using the same
  JWT-or-password auth logic as the runtime, waits up to 4s for it to
  connect or error, and reports {connected: bool}. An empty broker URL
  returns {connected:false, reason:"not configured"}. The probe client is
  always stopped and destroyed (success, failure or timeout) — no leaked
  connections. network.timeout_ms is bounded so an unreachable broker
  fails fast instead of blocking teardown. Adds the mqtt component to the
  http_server REQUIRES. lua_module_mqtt is not touched.
- Frontend: a read-only "Test connection" button (works without dev mode)
  and a badge showing only the LAST test result, not live status — grey
  "Not tested", green "Last test: OK", red "Last test: failed". New i18n
  keys in en + zh-cn.

Verified on hardware: valid creds connect, a wrong password and an
unreachable broker both report failed (the latter without hanging), and
an empty URL reports not configured.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds end-to-end MQTT support to ESP-Claw: a new Lua mqtt module backed by ESP-IDF’s esp-mqtt, plus device web configuration (including a one-shot connection probe) and docs updates so users can configure a default broker and use it from Lua scripts.

Changes:

  • Introduces lua_module_mqtt with publish/subscribe, poll-based receive, and callback/dispatch receive modes.
  • Extends app config + web UI with MQTT broker settings (URI/username/password/JWT/client ID) and adds /api/mqtt/probe.
  • Updates EN/ZH docs and Lua module reference list; enables the MQTT Lua module in sdkconfig.defaults.

Reviewed changes

Copilot reviewed 27 out of 29 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
docs/src/content/docs/zh-cn/tutorial/web-config.mdx Documents MQTT settings in the web config tutorial (ZH).
docs/src/content/docs/zh-cn/reference-cap/lua-modules.mdx Adds mqtt to Lua modules list (ZH).
docs/src/content/docs/en/tutorial/web-config.mdx Documents MQTT settings in the web config tutorial (EN).
docs/src/content/docs/en/reference-cap/lua-modules.mdx Adds mqtt to Lua modules list (EN).
components/lua_modules/lua_module_mqtt/test/mqtt_pubsub.lua Adds a pub/sub polling example script for the MQTT Lua module.
components/lua_modules/lua_module_mqtt/test/mqtt_callbacks.lua Adds a callback/dispatch example script for the MQTT Lua module.
components/lua_modules/lua_module_mqtt/src/lua_module_mqtt.h Declares the Lua module entrypoints and defaults injection API.
components/lua_modules/lua_module_mqtt/src/lua_module_mqtt.c Implements the MQTT Lua binding, rx queue, and callback registry.
components/lua_modules/lua_module_mqtt/README.md Adds usage documentation for the Lua MQTT module.
components/lua_modules/lua_module_mqtt/idf_component.yml Declares the component manager manifest (no external deps).
components/lua_modules/lua_module_mqtt/CMakeLists.txt Registers the new component and its dependencies.
components/common/app_claw/Kconfig Adds a Kconfig option to enable the MQTT Lua module.
components/common/app_claw/include/app_claw.h Extends app_claw_config_t with MQTT fields (incl. JWT buffer).
components/common/app_claw/idf_component.yml Wires lua_module_mqtt into app_claw dependency rules.
components/common/app_claw/app_lua_modules.c Registers the MQTT Lua module and seeds broker defaults from config.
application/edge_agent/sdkconfig.defaults Enables CONFIG_APP_CLAW_LUA_MODULE_MQTT by default.
application/edge_agent/components/http_server/http_server_config_api.c Adds MQTT config fields and /api/mqtt/probe route/handler.
application/edge_agent/components/http_server/frontend_source/src/state/dirty.ts Adds mqtt as a tracked dirty tab.
application/edge_agent/components/http_server/frontend_source/src/pages/MqttPage.tsx Adds the MQTT settings page UI (edit, probe, clear).
application/edge_agent/components/http_server/frontend_source/src/i18n/zh-cn.ts Adds MQTT UI strings (ZH).
application/edge_agent/components/http_server/frontend_source/src/i18n/en.ts Adds MQTT UI strings (EN).
application/edge_agent/components/http_server/frontend_source/src/components/layout/Sidebar.tsx Adds MQTT navigation entry/icon.
application/edge_agent/components/http_server/frontend_source/src/App.tsx Adds the MQTT page route/tab rendering.
application/edge_agent/components/http_server/frontend_source/src/api/client.ts Adds MQTT config fields/groups and the probeMqtt() API client.
application/edge_agent/components/http_server/CMakeLists.txt Adds mqtt dependency for the server (probe implementation).
application/edge_agent/components/app_config/include/app_config.h Extends persisted config with MQTT fields and JWT buffer size.
application/edge_agent/components/app_config/app_config.c Adds MQTT fields to config storage + claw config projection.
.gitignore Ignores a local flash helper script.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +67 to +81
esp_err_t lua_module_mqtt_set_defaults(const char *uri,
const char *username,
const char *password,
const char *client_id)
{
free(s_default_uri);
free(s_default_username);
free(s_default_password);
free(s_default_client_id);
s_default_uri = lua_module_mqtt_dup_or_null(uri);
s_default_username = lua_module_mqtt_dup_or_null(username);
s_default_password = lua_module_mqtt_dup_or_null(password);
s_default_client_id = lua_module_mqtt_dup_or_null(client_id);
return ESP_OK;
}
Comment on lines +193 to +199
case MQTT_EVENT_DATA: {
/* Only the first fragment carries the topic. Larger-than-buffer
* payloads arrive fragmented; this binding keeps single-fragment
* messages and drops continuation fragments. */
if (event->topic_len <= 0 || event->current_data_offset != 0) {
break;
}
Comment on lines +101 to +118
const clearCredentials = async () => {
if (!devMode()) {
pushToast(t('mqttDevModeRequired') as string, 'error');
return;
}
if (clearing()) return;
if (!window.confirm(t('mqttClearConfirm') as string)) return;
setClearing(true);
try {
await saveConfigPatch({ mqtt_uri: '', mqtt_username: '', mqtt_password: '', mqtt_jwt: '' });
await tab.reload();
pushToast(t('mqttClearDone') as string, 'success');
} catch (err) {
pushToast((err as Error).message, 'error');
} finally {
setClearing(false);
}
};
@corrancho

Copy link
Copy Markdown
Author

Thanks for the review! I've addressed all three comments:

  • set_defaults is now allocation-safe with an atomic swap (returns ESP_ERR_NO_MEM on failure without dropping existing config).
  • Fragmented payloads are now dropped instead of enqueuing truncated data (checks data_len != total_data_len).
  • The probe badge resets to idle after clearing credentials.

@laride

laride commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the PR!

Would you mind updating the PR description to include the use case for this feature, as well as a brief explanation of how it is intended to be used? That would make it much easier for reviewers and future contributors to understand the motivation and usage of this feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants