@alteriom/painlessmesh 1.6.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +380 -143
- package/LICENSE +674 -674
- package/README.md +477 -434
- package/RELEASE_GUIDE.md +504 -418
- package/docs/DOCUMENTATION_MIGRATION_PLAN.md +175 -175
- package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +1062 -0
- package/docs/MESH_TOPOLOGY_GUIDE.md +992 -0
- package/docs/MESH_TOPOLOGY_PROGRESS.md +422 -0
- package/docs/MQTT_BRIDGE_COMMANDS.md +894 -0
- package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +324 -0
- package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +576 -0
- package/docs/MQTT_SCHEMA_COMPLIANCE.md +285 -0
- package/docs/MQTT_SCHEMA_PROPOSALS.md +446 -0
- package/docs/MQTT_SCHEMA_REVIEW.md +690 -0
- package/docs/OTA_COMMANDS_REFERENCE.md +554 -0
- package/docs/PHASE1_GUIDE.md +349 -0
- package/docs/PHASE2_GUIDE.md +543 -0
- package/docs/README.md +77 -70
- package/docs/SCHEMA_VALIDATION_CHECKLIST.md +222 -0
- package/docs/alteriom/overview.md +507 -507
- package/docs/api/core-api.md +606 -606
- package/docs/architecture/mesh-architecture.md +378 -378
- package/docs/architecture/plugin-system.md +516 -516
- package/docs/getting-started/first-mesh.md +409 -409
- package/docs/getting-started/installation.md +274 -274
- package/docs/getting-started/quickstart.md +157 -157
- package/docs/improvements/FEATURE_PROPOSALS.md +337 -0
- package/docs/improvements/PHASE1_IMPLEMENTATION.md +325 -0
- package/docs/improvements/PHASE2_IMPLEMENTATION.md +567 -0
- package/docs/improvements/README.md +86 -68
- package/docs/improvements/ota-and-status-enhancements.md +911 -0
- package/docs/improvements/ota-status-architecture-diagrams.md +658 -0
- package/docs/improvements/ota-status-quick-reference.md +284 -0
- package/docs/platformio-publishing.md +255 -0
- package/docs/platformio-setup-summary.md +121 -0
- package/docs/troubleshooting/common-issues.md +520 -520
- package/docs/troubleshooting/faq.md +472 -472
- package/docs/tutorials/basic-examples.md +717 -717
- package/docs/wiki/API-Reference.md +245 -245
- package/docs/wiki/Complete-Documentation.md +122 -122
- package/examples/alteriom/README.md +139 -81
- package/examples/alteriom/alteriom.ino +186 -185
- package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
- package/examples/alteriom/platformio.ini +24 -24
- package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
- package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
- package/examples/alteriomImproved/platformio.ini +25 -0
- package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomPhase1/phase1_features.ino +242 -0
- package/examples/alteriomPhase1/platformio.ini +25 -0
- package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomPhase2/phase2_features.ino +186 -0
- package/examples/alteriomPhase2/platformio.ini +25 -0
- package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomSensorNode/platformio.ini +25 -0
- package/examples/basic/basic.ino +66 -66
- package/examples/basic/platformio.ini +25 -25
- package/examples/bridge/bridge.ino +51 -51
- package/examples/bridge/mesh_event_publisher.hpp +253 -0
- package/examples/bridge/mesh_topology_reporter.hpp +303 -0
- package/examples/bridge/mqtt_command_bridge.hpp +459 -0
- package/examples/bridge/mqtt_status_bridge.hpp +519 -0
- package/examples/bridge/platformio.ini +25 -25
- package/examples/echoNode/echoNode.ino +33 -33
- package/examples/echoNode/platformio.ini +25 -25
- package/examples/logClient/logClient.ino +109 -109
- package/examples/logClient/platformio.ini +25 -25
- package/examples/logServer/logServer.ino +81 -81
- package/examples/logServer/platformio.ini +25 -25
- package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
- package/examples/meshCommandNode/meshCommandNode.ino +263 -0
- package/examples/meshCommandNode/platformio.ini +25 -0
- package/examples/mqttBridge/mqttBridge.ino +118 -118
- package/examples/mqttBridge/platformio.ini +26 -26
- package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
- package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
- package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
- package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
- package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
- package/examples/mqttCommandBridge/platformio.ini +26 -0
- package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
- package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
- package/examples/mqttStatusBridge/platformio.ini +26 -0
- package/examples/mqttTopologyTest/README.md +467 -0
- package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
- package/examples/mqttTopologyTest/platformio.ini +26 -0
- package/examples/namedMesh/namedMesh.ino +97 -97
- package/examples/namedMesh/platformio.ini +25 -25
- package/examples/otaReceiver/otaReceiver.ino +79 -79
- package/examples/otaReceiver/platformio.ini +25 -25
- package/examples/otaSender/otaSender.ino +160 -151
- package/examples/otaSender/platformio.ini +25 -25
- package/examples/startHere/platformio.ini +25 -25
- package/examples/startHere/startHere.ino +159 -159
- package/examples/webServer/platformio.ini +27 -27
- package/examples/webServer/webServer.ino +89 -89
- package/keywords.txt +48 -48
- package/library.json +55 -34
- package/library.properties +10 -10
- package/package.json +86 -78
- package/src/AlteriomPainlessMesh.h +97 -97
- package/src/arduino/wifi.hpp +365 -365
- package/src/boost/asynctcp.hpp +279 -279
- package/src/painlessMesh.h +70 -70
- package/src/painlessMeshSTA.cpp +236 -236
- package/src/painlessMeshSTA.h +58 -58
- package/src/painlessTaskOptions.h +4 -4
- package/src/painlessmesh/base64.hpp +111 -111
- package/src/painlessmesh/buffer.hpp +229 -229
- package/src/painlessmesh/callback.hpp +91 -91
- package/src/painlessmesh/configuration.hpp +77 -77
- package/src/painlessmesh/connection.hpp +192 -192
- package/src/painlessmesh/layout.hpp +188 -188
- package/src/painlessmesh/logger.hpp +158 -158
- package/src/painlessmesh/memory.hpp +119 -119
- package/src/painlessmesh/mesh.hpp +761 -560
- package/src/painlessmesh/metrics.hpp +322 -322
- package/src/painlessmesh/ntp.hpp +263 -263
- package/src/painlessmesh/ota.hpp +582 -553
- package/src/painlessmesh/plugin.hpp +188 -188
- package/src/painlessmesh/protocol.hpp +813 -813
- package/src/painlessmesh/router.hpp +322 -322
- package/src/painlessmesh/tcp.hpp +71 -71
- package/src/painlessmesh/validation.hpp +238 -238
- package/src/plugin/performance.hpp +214 -214
- package/src/plugin/remote.hpp +64 -64
- package/src/scheduler.cpp +10 -10
- package/src/wifi.cpp +2 -2
|
@@ -0,0 +1,894 @@
|
|
|
1
|
+
# MQTT Bridge Commands Reference
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document provides a complete reference for MQTT-to-mesh bridge commands in painlessMesh Alteriom fork. The MQTT bridge enables bidirectional communication between MQTT brokers and mesh networks, allowing web applications to control and monitor mesh nodes.
|
|
6
|
+
|
|
7
|
+
## Table of Contents
|
|
8
|
+
|
|
9
|
+
1. [Architecture Overview](#architecture-overview)
|
|
10
|
+
2. [Command Types](#command-types)
|
|
11
|
+
3. [MQTT Topic Structure](#mqtt-topic-structure)
|
|
12
|
+
4. [Command Definitions](#command-definitions)
|
|
13
|
+
5. [Implementation Guide](#implementation-guide)
|
|
14
|
+
6. [Complete Examples](#complete-examples)
|
|
15
|
+
7. [Troubleshooting](#troubleshooting)
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Architecture Overview
|
|
20
|
+
|
|
21
|
+
### Communication Flow
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Web Application → MQTT Broker → Gateway Bridge → Mesh Network → Target Node
|
|
25
|
+
Target Node → Mesh Network → Gateway Bridge → MQTT Broker → Web Application
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Components
|
|
29
|
+
|
|
30
|
+
1. **MQTT Broker** - Central message router (Mosquitto, HiveMQ, AWS IoT)
|
|
31
|
+
2. **Gateway Bridge** - ESP32/ESP8266 with WiFi + mesh capability
|
|
32
|
+
3. **Mesh Nodes** - ESP devices in mesh network
|
|
33
|
+
4. **Web Application** - Control interface publishing MQTT commands
|
|
34
|
+
|
|
35
|
+
### Message Types
|
|
36
|
+
|
|
37
|
+
| Direction | Package Type | Purpose |
|
|
38
|
+
|-----------|--------------|---------|
|
|
39
|
+
| MQTT → Mesh | CommandPackage (201) | Control device, request data |
|
|
40
|
+
| Mesh → MQTT | StatusPackage (202) | Report device status |
|
|
41
|
+
| Mesh → MQTT | SensorPackage (200) | Sensor data reports |
|
|
42
|
+
| Mesh → MQTT | EnhancedStatusPackage (203) | Detailed health metrics |
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Command Types
|
|
47
|
+
|
|
48
|
+
### Device Control Commands (1-99)
|
|
49
|
+
|
|
50
|
+
| Command ID | Name | Description | Parameters |
|
|
51
|
+
|------------|------|-------------|------------|
|
|
52
|
+
| 1 | RESET | Restart device | None |
|
|
53
|
+
| 2 | SLEEP | Enter deep sleep | `duration_ms` (uint32_t) |
|
|
54
|
+
| 3 | WAKE | Wake from sleep | None |
|
|
55
|
+
| 10 | LED_CONTROL | Control onboard LED | `state` (bool), `brightness` (uint8_t) |
|
|
56
|
+
| 11 | RELAY_SWITCH | Control relay output | `channel` (uint8_t), `state` (bool) |
|
|
57
|
+
| 12 | PWM_SET | Set PWM output | `pin` (uint8_t), `duty` (uint16_t) |
|
|
58
|
+
| 20 | SENSOR_ENABLE | Enable/disable sensor | `sensor_id` (uint8_t), `enabled` (bool) |
|
|
59
|
+
| 21 | SENSOR_CALIBRATE | Calibrate sensor | `sensor_id` (uint8_t) |
|
|
60
|
+
|
|
61
|
+
### Configuration Commands (100-199)
|
|
62
|
+
|
|
63
|
+
| Command ID | Name | Description | Parameters |
|
|
64
|
+
|------------|------|-------------|------------|
|
|
65
|
+
| 100 | GET_CONFIG | Request current configuration | None |
|
|
66
|
+
| 101 | SET_CONFIG | Update configuration | JSON config object |
|
|
67
|
+
| 102 | RESET_CONFIG | Reset to factory defaults | None |
|
|
68
|
+
| 103 | SAVE_CONFIG | Persist config to flash | None |
|
|
69
|
+
| 110 | SET_SAMPLE_RATE | Change sensor sample rate | `rate_ms` (uint32_t) |
|
|
70
|
+
| 111 | SET_DEVICE_NAME | Update device name | `name` (string) |
|
|
71
|
+
|
|
72
|
+
### Status Commands (200-255)
|
|
73
|
+
|
|
74
|
+
| Command ID | Name | Description | Parameters |
|
|
75
|
+
|------------|------|-------------|------------|
|
|
76
|
+
| 200 | GET_STATUS | Request basic status | None |
|
|
77
|
+
| 201 | GET_METRICS | Request performance metrics | None |
|
|
78
|
+
| 202 | GET_DIAGNOSTICS | Request detailed diagnostics | None |
|
|
79
|
+
| 210 | START_MONITORING | Begin continuous monitoring | `interval_ms` (uint32_t) |
|
|
80
|
+
| 211 | STOP_MONITORING | Stop continuous monitoring | None |
|
|
81
|
+
|
|
82
|
+
### Topology Commands (300-399) ✨ NEW in v0.5.0
|
|
83
|
+
|
|
84
|
+
| Command ID | Name | Description | Parameters |
|
|
85
|
+
|------------|------|-------------|------------|
|
|
86
|
+
| 300 | GET_TOPOLOGY | Request mesh network topology | `format` (optional): "full" or "summary" |
|
|
87
|
+
|
|
88
|
+
**Response:** Full mesh topology published to `alteriom/mesh/{mesh_id}/topology/response` with `correlation_id` field matching the command ID.
|
|
89
|
+
|
|
90
|
+
**Example Response:**
|
|
91
|
+
```json
|
|
92
|
+
{
|
|
93
|
+
"schema_version": 1,
|
|
94
|
+
"event": "mesh_topology",
|
|
95
|
+
"correlation_id": "12345",
|
|
96
|
+
"mesh_id": "MESH-001",
|
|
97
|
+
"nodes": [...],
|
|
98
|
+
"connections": [...],
|
|
99
|
+
"metrics": {...}
|
|
100
|
+
}
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## MQTT Topic Structure
|
|
106
|
+
|
|
107
|
+
### Command Topics (Published by Web App)
|
|
108
|
+
|
|
109
|
+
```
|
|
110
|
+
mesh/command/{nodeId} # Send command to specific node
|
|
111
|
+
mesh/command/broadcast # Broadcast command to all nodes
|
|
112
|
+
mesh/config/{nodeId}/get # Request configuration
|
|
113
|
+
mesh/config/{nodeId}/set # Update configuration
|
|
114
|
+
mesh/ota/{nodeId}/start # Initiate OTA update
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Response Topics (Published by Gateway Bridge)
|
|
118
|
+
|
|
119
|
+
```
|
|
120
|
+
mesh/response/{nodeId} # Command acknowledgments
|
|
121
|
+
mesh/status/{nodeId} # Status updates (Type 202)
|
|
122
|
+
mesh/sensor/{nodeId} # Sensor data (Type 200)
|
|
123
|
+
mesh/health/{nodeId} # Enhanced status (Type 203)
|
|
124
|
+
mesh/config/{nodeId} # Configuration data
|
|
125
|
+
mesh/error/{nodeId} # Error reports
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
### System Topics (Legacy - v0.4.0)
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
mesh/gateway/status # Gateway bridge health
|
|
132
|
+
mesh/topology # Mesh network topology (old format)
|
|
133
|
+
mesh/nodes # List of connected nodes
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Topology & Event Topics ✨ NEW (v0.5.0 - @alteriom/mqtt-schema compliant)
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
alteriom/mesh/{mesh_id}/topology # Full/incremental mesh topology
|
|
140
|
+
alteriom/mesh/{mesh_id}/topology/response # Topology responses to GET_TOPOLOGY command
|
|
141
|
+
alteriom/mesh/{mesh_id}/events # Real-time mesh state change events
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
**Schema Compliance:** All topology and event messages conform to **@alteriom/mqtt-schema v0.5.0** specification.
|
|
145
|
+
|
|
146
|
+
**Key Features:**
|
|
147
|
+
- **Device ID Format:** `ALT-XXXXXXXXXXXX` (12 hex digits)
|
|
148
|
+
- **Envelope Fields:** `schema_version`, `device_id`, `device_type`, `timestamp`, `firmware_version`
|
|
149
|
+
- **Connection Metrics:** RSSI, latency, quality (0-100), packet counts
|
|
150
|
+
- **Network Metrics:** Total nodes, network diameter, average quality
|
|
151
|
+
- **Update Types:** Full (every 60s), Incremental (every 5s if changed)
|
|
152
|
+
- **Event Types:** node_join, node_leave, connection_lost, connection_restored, network_split, network_merged
|
|
153
|
+
|
|
154
|
+
---
|
|
155
|
+
|
|
156
|
+
## Command Definitions
|
|
157
|
+
|
|
158
|
+
### CommandPackage Structure (Type 201)
|
|
159
|
+
|
|
160
|
+
Defined in `examples/alteriom/alteriom_sensor_package.hpp`:
|
|
161
|
+
|
|
162
|
+
```cpp
|
|
163
|
+
class CommandPackage : public painlessmesh::plugin::SinglePackage {
|
|
164
|
+
public:
|
|
165
|
+
uint8_t command = 0; // Command ID (1-255)
|
|
166
|
+
uint32_t targetDevice = 0; // Destination node ID
|
|
167
|
+
uint32_t commandId = 0; // Unique command tracking ID
|
|
168
|
+
TSTRING parameters = ""; // JSON-encoded parameters
|
|
169
|
+
|
|
170
|
+
CommandPackage() : SinglePackage(201) {}
|
|
171
|
+
};
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Command Parameter Encoding
|
|
175
|
+
|
|
176
|
+
Parameters are JSON-encoded strings:
|
|
177
|
+
|
|
178
|
+
```json
|
|
179
|
+
{
|
|
180
|
+
"state": "ON",
|
|
181
|
+
"brightness": 75,
|
|
182
|
+
"duration_ms": 5000
|
|
183
|
+
}
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### Command Response Structure
|
|
187
|
+
|
|
188
|
+
Responses use StatusPackage (Type 202) with enhanced fields:
|
|
189
|
+
|
|
190
|
+
```cpp
|
|
191
|
+
class StatusPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
192
|
+
public:
|
|
193
|
+
uint8_t deviceStatus = 0; // 0=OK, 1=Warning, 2=Error
|
|
194
|
+
uint32_t uptime = 0; // Seconds since boot
|
|
195
|
+
uint16_t freeMemory = 0; // Free heap in KB
|
|
196
|
+
TSTRING firmwareVersion = ""; // Current firmware version
|
|
197
|
+
|
|
198
|
+
// Response fields
|
|
199
|
+
uint32_t responseToCommand = 0; // Original commandId
|
|
200
|
+
TSTRING responseMessage = ""; // Success/error message
|
|
201
|
+
|
|
202
|
+
StatusPackage() : BroadcastPackage(202) {}
|
|
203
|
+
};
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
---
|
|
207
|
+
|
|
208
|
+
## Implementation Guide
|
|
209
|
+
|
|
210
|
+
### Gateway Bridge Implementation
|
|
211
|
+
|
|
212
|
+
The gateway bridge is implemented in `examples/bridge/mqtt_command_bridge.hpp` and provides:
|
|
213
|
+
|
|
214
|
+
1. **MQTT → Mesh Command Forwarding**
|
|
215
|
+
- Subscribes to command topics
|
|
216
|
+
- Parses JSON payloads
|
|
217
|
+
- Routes commands to target nodes
|
|
218
|
+
|
|
219
|
+
2. **Mesh → MQTT Response Forwarding**
|
|
220
|
+
- Receives mesh messages
|
|
221
|
+
- Publishes to appropriate MQTT topics
|
|
222
|
+
- Maintains message routing
|
|
223
|
+
|
|
224
|
+
3. **Configuration Management**
|
|
225
|
+
- Handles config requests
|
|
226
|
+
- Applies config updates
|
|
227
|
+
- Sends acknowledgments
|
|
228
|
+
|
|
229
|
+
4. **Local Command Execution**
|
|
230
|
+
- Executes commands targeted at gateway
|
|
231
|
+
- Sends responses via MQTT
|
|
232
|
+
|
|
233
|
+
### Mesh Node Implementation
|
|
234
|
+
|
|
235
|
+
Mesh nodes implement command handlers in `examples/alteriom/mesh_command_node.ino`:
|
|
236
|
+
|
|
237
|
+
1. **Command Reception**
|
|
238
|
+
- Listen for CommandPackage (Type 201)
|
|
239
|
+
- Parse command and parameters
|
|
240
|
+
- Execute appropriate action
|
|
241
|
+
|
|
242
|
+
2. **Response Generation**
|
|
243
|
+
- Create StatusPackage response
|
|
244
|
+
- Include commandId for tracking
|
|
245
|
+
- Broadcast back to mesh
|
|
246
|
+
|
|
247
|
+
3. **Status Reporting**
|
|
248
|
+
- Send periodic status updates
|
|
249
|
+
- Report errors and warnings
|
|
250
|
+
- Include relevant metrics
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
254
|
+
## Mesh Topology Reporting ✨ NEW in v0.5.0
|
|
255
|
+
|
|
256
|
+
### Overview
|
|
257
|
+
|
|
258
|
+
The mesh topology system provides real-time visibility into the structure and health of your mesh network. It publishes detailed information about nodes, connections, and network metrics in a standardized format that complies with **@alteriom/mqtt-schema v0.5.0**.
|
|
259
|
+
|
|
260
|
+
**Implementation:** `examples/bridge/mesh_topology_reporter.hpp`
|
|
261
|
+
|
|
262
|
+
### Topology Message Structure
|
|
263
|
+
|
|
264
|
+
#### Envelope Fields (Required by @alteriom/mqtt-schema)
|
|
265
|
+
|
|
266
|
+
```json
|
|
267
|
+
{
|
|
268
|
+
"schema_version": 1,
|
|
269
|
+
"device_id": "ALT-6825DD341CA4",
|
|
270
|
+
"device_type": "gateway",
|
|
271
|
+
"timestamp": "2025-01-12T15:00:00Z",
|
|
272
|
+
"firmware_version": "GW 2.3.4"
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
#### Topology Payload
|
|
277
|
+
|
|
278
|
+
```json
|
|
279
|
+
{
|
|
280
|
+
"event": "mesh_topology",
|
|
281
|
+
"mesh_id": "MESH-001",
|
|
282
|
+
"gateway_node_id": "ALT-6825DD341CA4",
|
|
283
|
+
"nodes": [
|
|
284
|
+
{
|
|
285
|
+
"node_id": "ALT-6825DD341CA4",
|
|
286
|
+
"role": "gateway",
|
|
287
|
+
"status": "online",
|
|
288
|
+
"last_seen": "2025-01-12T15:00:00Z",
|
|
289
|
+
"firmware_version": "GW 2.3.4",
|
|
290
|
+
"uptime_seconds": 86400,
|
|
291
|
+
"free_memory_kb": 128,
|
|
292
|
+
"connection_count": 3
|
|
293
|
+
}
|
|
294
|
+
],
|
|
295
|
+
"connections": [
|
|
296
|
+
{
|
|
297
|
+
"from_node": "ALT-6825DD341CA4",
|
|
298
|
+
"to_node": "ALT-441D64F804A0",
|
|
299
|
+
"quality": 95,
|
|
300
|
+
"latency_ms": 12,
|
|
301
|
+
"rssi": -42,
|
|
302
|
+
"hop_count": 1
|
|
303
|
+
}
|
|
304
|
+
],
|
|
305
|
+
"metrics": {
|
|
306
|
+
"total_nodes": 4,
|
|
307
|
+
"online_nodes": 4,
|
|
308
|
+
"network_diameter": 2,
|
|
309
|
+
"avg_connection_quality": 85,
|
|
310
|
+
"messages_per_second": 12.4
|
|
311
|
+
},
|
|
312
|
+
"update_type": "full"
|
|
313
|
+
}
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### Publishing Schedule
|
|
317
|
+
|
|
318
|
+
| Update Type | Frequency | Trigger | Topic |
|
|
319
|
+
|-------------|-----------|---------|-------|
|
|
320
|
+
| Full Topology | Every 60 seconds | Timer | `alteriom/mesh/MESH-001/topology` |
|
|
321
|
+
| Incremental | Every 5 seconds | Change detection | `alteriom/mesh/MESH-001/topology` |
|
|
322
|
+
| On-Demand | Immediate | GET_TOPOLOGY command | `alteriom/mesh/MESH-001/topology/response` |
|
|
323
|
+
|
|
324
|
+
### Node Roles
|
|
325
|
+
|
|
326
|
+
| Role | Description | Typical Use |
|
|
327
|
+
|------|-------------|-------------|
|
|
328
|
+
| gateway | MQTT bridge with WiFi | Root node, MQTT publisher |
|
|
329
|
+
| sensor | Sensor measurement node | Data collection |
|
|
330
|
+
| repeater | Range extender | Network coverage |
|
|
331
|
+
|
|
332
|
+
### Connection Quality Metrics
|
|
333
|
+
|
|
334
|
+
**Quality Score (0-100):** Calculated from latency, packet loss, and RSSI
|
|
335
|
+
|
|
336
|
+
- **90-100:** Excellent - Low latency (<50ms), strong signal (>-50 dBm)
|
|
337
|
+
- **70-89:** Good - Moderate latency (<100ms), good signal (>-70 dBm)
|
|
338
|
+
- **50-69:** Fair - Higher latency (<200ms), weaker signal (>-80 dBm)
|
|
339
|
+
- **0-49:** Poor - High latency (>200ms), weak signal (<-80 dBm)
|
|
340
|
+
|
|
341
|
+
**RSSI (Received Signal Strength Indicator):**
|
|
342
|
+
- Values in dBm (negative numbers)
|
|
343
|
+
- Stronger signal = higher (less negative) value
|
|
344
|
+
- Example: -42 dBm is better than -75 dBm
|
|
345
|
+
|
|
346
|
+
**Latency:**
|
|
347
|
+
- Round-trip time in milliseconds
|
|
348
|
+
- Calculated from message exchange timing
|
|
349
|
+
- Lower is better
|
|
350
|
+
|
|
351
|
+
### GET_TOPOLOGY Command (300)
|
|
352
|
+
|
|
353
|
+
**Request:** Publish to `mesh/command/{gateway_id}` or `mesh/command/broadcast`
|
|
354
|
+
|
|
355
|
+
```json
|
|
356
|
+
{
|
|
357
|
+
"type": 201,
|
|
358
|
+
"command": 300,
|
|
359
|
+
"targetDevice": 0,
|
|
360
|
+
"commandId": 12345,
|
|
361
|
+
"parameters": "{}"
|
|
362
|
+
}
|
|
363
|
+
```
|
|
364
|
+
|
|
365
|
+
**Response:** Published to `alteriom/mesh/MESH-001/topology/response`
|
|
366
|
+
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"schema_version": 1,
|
|
370
|
+
"device_id": "ALT-6825DD341CA4",
|
|
371
|
+
"event": "mesh_topology",
|
|
372
|
+
"correlation_id": "12345",
|
|
373
|
+
"mesh_id": "MESH-001",
|
|
374
|
+
... full topology ...
|
|
375
|
+
}
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
**Key Feature:** The `correlation_id` field matches the command's `commandId` for request tracking.
|
|
379
|
+
|
|
380
|
+
---
|
|
381
|
+
|
|
382
|
+
## Mesh Events ✨ NEW in v0.5.0
|
|
383
|
+
|
|
384
|
+
### Overview
|
|
385
|
+
|
|
386
|
+
Real-time notifications of mesh network state changes. Published immediately when events occur.
|
|
387
|
+
|
|
388
|
+
**Implementation:** `examples/bridge/mesh_event_publisher.hpp`
|
|
389
|
+
**Topic:** `alteriom/mesh/MESH-001/events`
|
|
390
|
+
|
|
391
|
+
### Event Types
|
|
392
|
+
|
|
393
|
+
| Event Type | Description | When Triggered |
|
|
394
|
+
|------------|-------------|----------------|
|
|
395
|
+
| node_join | New node connected | onNewConnection() callback |
|
|
396
|
+
| node_leave | Node disconnected | onDroppedConnection() callback |
|
|
397
|
+
| connection_lost | Direct connection failed | Connection timeout |
|
|
398
|
+
| connection_restored | Connection recovered | After connection_lost |
|
|
399
|
+
| network_split | Mesh partitioned | Network segmentation detected |
|
|
400
|
+
| network_merged | Partitions rejoined | Segments reconnected |
|
|
401
|
+
|
|
402
|
+
### Event Message Structure
|
|
403
|
+
|
|
404
|
+
#### Node Join Event
|
|
405
|
+
|
|
406
|
+
```json
|
|
407
|
+
{
|
|
408
|
+
"schema_version": 1,
|
|
409
|
+
"device_id": "ALT-6825DD341CA4",
|
|
410
|
+
"device_type": "gateway",
|
|
411
|
+
"timestamp": "2025-01-12T15:05:00Z",
|
|
412
|
+
"firmware_version": "GW 2.3.4",
|
|
413
|
+
"event": "mesh_event",
|
|
414
|
+
"event_type": "node_join",
|
|
415
|
+
"mesh_id": "MESH-001",
|
|
416
|
+
"affected_nodes": ["ALT-441D64F804A0"],
|
|
417
|
+
"details": {
|
|
418
|
+
"total_nodes": 4,
|
|
419
|
+
"timestamp": "2025-01-12T15:05:00Z"
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
#### Node Leave Event
|
|
425
|
+
|
|
426
|
+
```json
|
|
427
|
+
{
|
|
428
|
+
"schema_version": 1,
|
|
429
|
+
"device_id": "ALT-6825DD341CA4",
|
|
430
|
+
"device_type": "gateway",
|
|
431
|
+
"timestamp": "2025-01-12T15:10:00Z",
|
|
432
|
+
"firmware_version": "GW 2.3.4",
|
|
433
|
+
"event": "mesh_event",
|
|
434
|
+
"event_type": "node_leave",
|
|
435
|
+
"mesh_id": "MESH-001",
|
|
436
|
+
"affected_nodes": ["ALT-441D64F804A0"],
|
|
437
|
+
"details": {
|
|
438
|
+
"reason": "connection_lost",
|
|
439
|
+
"last_seen": "2025-01-12T15:08:45Z",
|
|
440
|
+
"total_nodes": 3
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
#### Connection Lost Event
|
|
446
|
+
|
|
447
|
+
```json
|
|
448
|
+
{
|
|
449
|
+
"event": "mesh_event",
|
|
450
|
+
"event_type": "connection_lost",
|
|
451
|
+
"affected_nodes": ["ALT-441D64F804A0"],
|
|
452
|
+
"details": {
|
|
453
|
+
"reason": "timeout",
|
|
454
|
+
"timestamp": "2025-01-12T15:10:00Z"
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Integration with Web Dashboards
|
|
460
|
+
|
|
461
|
+
**Subscribe to events:**
|
|
462
|
+
|
|
463
|
+
```javascript
|
|
464
|
+
const mqtt = require('mqtt');
|
|
465
|
+
const client = mqtt.connect('mqtt://broker.local:1883');
|
|
466
|
+
|
|
467
|
+
client.subscribe('alteriom/mesh/+/events');
|
|
468
|
+
client.subscribe('alteriom/mesh/+/topology');
|
|
469
|
+
|
|
470
|
+
client.on('message', (topic, message) => {
|
|
471
|
+
const data = JSON.parse(message.toString());
|
|
472
|
+
|
|
473
|
+
if (data.event === 'mesh_event') {
|
|
474
|
+
switch (data.event_type) {
|
|
475
|
+
case 'node_join':
|
|
476
|
+
console.log(`✅ Node joined: ${data.affected_nodes[0]}`);
|
|
477
|
+
break;
|
|
478
|
+
case 'node_leave':
|
|
479
|
+
console.log(`⚠️ Node left: ${data.affected_nodes[0]}`);
|
|
480
|
+
break;
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
if (data.event === 'mesh_topology') {
|
|
485
|
+
console.log(`📊 Topology update: ${data.nodes.length} nodes`);
|
|
486
|
+
// Render network graph with D3.js or similar
|
|
487
|
+
}
|
|
488
|
+
});
|
|
489
|
+
```
|
|
490
|
+
|
|
491
|
+
**Python example:**
|
|
492
|
+
|
|
493
|
+
```python
|
|
494
|
+
import paho.mqtt.client as mqtt
|
|
495
|
+
import json
|
|
496
|
+
|
|
497
|
+
def on_message(client, userdata, msg):
|
|
498
|
+
data = json.loads(msg.payload.decode())
|
|
499
|
+
|
|
500
|
+
if data['event'] == 'mesh_event':
|
|
501
|
+
event_type = data['event_type']
|
|
502
|
+
nodes = data['affected_nodes']
|
|
503
|
+
print(f"Event: {event_type} - Nodes: {nodes}")
|
|
504
|
+
|
|
505
|
+
elif data['event'] == 'mesh_topology':
|
|
506
|
+
total_nodes = data['metrics']['total_nodes']
|
|
507
|
+
quality = data['metrics']['avg_connection_quality']
|
|
508
|
+
print(f"Topology: {total_nodes} nodes, quality: {quality}%")
|
|
509
|
+
|
|
510
|
+
client = mqtt.Client()
|
|
511
|
+
client.on_message = on_message
|
|
512
|
+
client.connect("broker.local", 1883)
|
|
513
|
+
client.subscribe("alteriom/mesh/+/events")
|
|
514
|
+
client.subscribe("alteriom/mesh/+/topology")
|
|
515
|
+
client.loop_forever()
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
---
|
|
519
|
+
|
|
520
|
+
## Complete Examples
|
|
521
|
+
|
|
522
|
+
### Example 1: Send LED Control Command via MQTT
|
|
523
|
+
|
|
524
|
+
**Publish to:** `mesh/command/123456`
|
|
525
|
+
|
|
526
|
+
```json
|
|
527
|
+
{
|
|
528
|
+
"type": 201,
|
|
529
|
+
"command": 10,
|
|
530
|
+
"targetDevice": 123456,
|
|
531
|
+
"commandId": 1001,
|
|
532
|
+
"parameters": "{\"state\":true,\"brightness\":75}"
|
|
533
|
+
}
|
|
534
|
+
```
|
|
535
|
+
|
|
536
|
+
**Expected Response on:** `mesh/response/123456`
|
|
537
|
+
|
|
538
|
+
```json
|
|
539
|
+
{
|
|
540
|
+
"type": 202,
|
|
541
|
+
"from": 123456,
|
|
542
|
+
"deviceStatus": 0,
|
|
543
|
+
"uptime": 3600,
|
|
544
|
+
"freeMemory": 45,
|
|
545
|
+
"firmwareVersion": "1.0.0",
|
|
546
|
+
"responseToCommand": 1001,
|
|
547
|
+
"responseMessage": "LED ON"
|
|
548
|
+
}
|
|
549
|
+
```
|
|
550
|
+
|
|
551
|
+
### Example 2: Broadcast Configuration Request
|
|
552
|
+
|
|
553
|
+
**Publish to:** `mesh/command/broadcast`
|
|
554
|
+
|
|
555
|
+
```json
|
|
556
|
+
{
|
|
557
|
+
"type": 201,
|
|
558
|
+
"command": 100,
|
|
559
|
+
"targetDevice": 0,
|
|
560
|
+
"commandId": 2001,
|
|
561
|
+
"parameters": "{}"
|
|
562
|
+
}
|
|
563
|
+
```
|
|
564
|
+
|
|
565
|
+
All nodes respond with their configuration on respective `mesh/config/<nodeId>` topics.
|
|
566
|
+
|
|
567
|
+
### Example 3: Update Node Configuration
|
|
568
|
+
|
|
569
|
+
**Publish to:** `mesh/config/123456/set`
|
|
570
|
+
|
|
571
|
+
```json
|
|
572
|
+
{
|
|
573
|
+
"config": {
|
|
574
|
+
"deviceName": "Sensor-Living-Room",
|
|
575
|
+
"sampleRate": 30000,
|
|
576
|
+
"ledEnabled": false
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
**Expected Response on:** `mesh/response/123456`
|
|
582
|
+
|
|
583
|
+
```json
|
|
584
|
+
{
|
|
585
|
+
"status": "success",
|
|
586
|
+
"device_id": "123456",
|
|
587
|
+
"message": "Configuration updated"
|
|
588
|
+
}
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
### Example 4: Request Device Status
|
|
592
|
+
|
|
593
|
+
**Publish to:** `mesh/command/123456`
|
|
594
|
+
|
|
595
|
+
```json
|
|
596
|
+
{
|
|
597
|
+
"type": 201,
|
|
598
|
+
"command": 200,
|
|
599
|
+
"targetDevice": 123456,
|
|
600
|
+
"commandId": 3001,
|
|
601
|
+
"parameters": "{}"
|
|
602
|
+
}
|
|
603
|
+
```
|
|
604
|
+
|
|
605
|
+
**Expected Response on:** `mesh/status/123456`
|
|
606
|
+
|
|
607
|
+
```json
|
|
608
|
+
{
|
|
609
|
+
"type": 202,
|
|
610
|
+
"from": 123456,
|
|
611
|
+
"deviceStatus": 0,
|
|
612
|
+
"uptime": 7200,
|
|
613
|
+
"freeMemory": 42,
|
|
614
|
+
"firmwareVersion": "1.0.0",
|
|
615
|
+
"responseToCommand": 3001,
|
|
616
|
+
"responseMessage": "OK"
|
|
617
|
+
}
|
|
618
|
+
```
|
|
619
|
+
|
|
620
|
+
---
|
|
621
|
+
|
|
622
|
+
## Using with Web Applications
|
|
623
|
+
|
|
624
|
+
### JavaScript/Node.js Example
|
|
625
|
+
|
|
626
|
+
```javascript
|
|
627
|
+
const mqtt = require('mqtt');
|
|
628
|
+
const client = mqtt.connect('mqtt://192.168.1.100:1883');
|
|
629
|
+
|
|
630
|
+
client.on('connect', () => {
|
|
631
|
+
console.log('Connected to MQTT broker');
|
|
632
|
+
|
|
633
|
+
// Subscribe to response topics
|
|
634
|
+
client.subscribe('mesh/response/#');
|
|
635
|
+
client.subscribe('mesh/status/#');
|
|
636
|
+
|
|
637
|
+
// Send LED control command
|
|
638
|
+
const command = {
|
|
639
|
+
type: 201,
|
|
640
|
+
command: 10,
|
|
641
|
+
targetDevice: 123456,
|
|
642
|
+
commandId: Date.now(),
|
|
643
|
+
parameters: JSON.stringify({
|
|
644
|
+
state: true,
|
|
645
|
+
brightness: 75
|
|
646
|
+
})
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
client.publish('mesh/command/123456', JSON.stringify(command));
|
|
650
|
+
});
|
|
651
|
+
|
|
652
|
+
client.on('message', (topic, message) => {
|
|
653
|
+
console.log(`Received on ${topic}:`, message.toString());
|
|
654
|
+
const response = JSON.parse(message.toString());
|
|
655
|
+
|
|
656
|
+
if (response.responseToCommand) {
|
|
657
|
+
console.log(`Command ${response.responseToCommand} result: ${response.responseMessage}`);
|
|
658
|
+
}
|
|
659
|
+
});
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Python Example
|
|
663
|
+
|
|
664
|
+
```python
|
|
665
|
+
import paho.mqtt.client as mqtt
|
|
666
|
+
import json
|
|
667
|
+
import time
|
|
668
|
+
|
|
669
|
+
def on_connect(client, userdata, flags, rc):
|
|
670
|
+
print(f"Connected with result code {rc}")
|
|
671
|
+
client.subscribe("mesh/response/#")
|
|
672
|
+
client.subscribe("mesh/status/#")
|
|
673
|
+
|
|
674
|
+
# Send LED control command
|
|
675
|
+
command = {
|
|
676
|
+
"type": 201,
|
|
677
|
+
"command": 10,
|
|
678
|
+
"targetDevice": 123456,
|
|
679
|
+
"commandId": int(time.time() * 1000),
|
|
680
|
+
"parameters": json.dumps({
|
|
681
|
+
"state": True,
|
|
682
|
+
"brightness": 75
|
|
683
|
+
})
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
client.publish("mesh/command/123456", json.dumps(command))
|
|
687
|
+
|
|
688
|
+
def on_message(client, userdata, msg):
|
|
689
|
+
print(f"Received on {msg.topic}: {msg.payload.decode()}")
|
|
690
|
+
response = json.loads(msg.payload.decode())
|
|
691
|
+
|
|
692
|
+
if "responseToCommand" in response:
|
|
693
|
+
print(f"Command {response['responseToCommand']} result: {response['responseMessage']}")
|
|
694
|
+
|
|
695
|
+
client = mqtt.Client()
|
|
696
|
+
client.on_connect = on_connect
|
|
697
|
+
client.on_message = on_message
|
|
698
|
+
|
|
699
|
+
client.connect("192.168.1.100", 1883, 60)
|
|
700
|
+
client.loop_forever()
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
---
|
|
704
|
+
|
|
705
|
+
## Troubleshooting
|
|
706
|
+
|
|
707
|
+
### Commands Not Reaching Nodes
|
|
708
|
+
|
|
709
|
+
**Symptoms:**
|
|
710
|
+
- Commands published to MQTT but nodes don't respond
|
|
711
|
+
- No error messages in gateway logs
|
|
712
|
+
|
|
713
|
+
**Solutions:**
|
|
714
|
+
1. **Check MQTT Connection**: Verify bridge is connected to broker
|
|
715
|
+
```cpp
|
|
716
|
+
if (mqttClient.connected()) {
|
|
717
|
+
Serial.println("MQTT connected");
|
|
718
|
+
}
|
|
719
|
+
```
|
|
720
|
+
|
|
721
|
+
2. **Verify Topic Format**: Ensure exact topic structure with nodeId
|
|
722
|
+
```
|
|
723
|
+
Correct: mesh/command/123456
|
|
724
|
+
Wrong: mesh/commands/123456
|
|
725
|
+
Wrong: mesh/command/0x1E240
|
|
726
|
+
```
|
|
727
|
+
|
|
728
|
+
3. **Check JSON Format**: Validate command payload structure
|
|
729
|
+
```bash
|
|
730
|
+
# Use mosquitto_pub to test
|
|
731
|
+
mosquitto_pub -h 192.168.1.100 -t "mesh/command/123456" -m '{"type":201,"command":10,"targetDevice":123456,"commandId":1001,"parameters":"{}"}'
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
4. **Inspect Mesh Connectivity**: Use `mesh.getNodeList()` to verify nodes
|
|
735
|
+
```cpp
|
|
736
|
+
auto nodes = mesh.getNodeList();
|
|
737
|
+
Serial.printf("Connected nodes: %d\n", nodes.size());
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
5. **Enable Debug Logging**:
|
|
741
|
+
```cpp
|
|
742
|
+
mesh.setDebugMsgTypes(ERROR | CONNECTION | COMMUNICATION);
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
### No Response from Nodes
|
|
746
|
+
|
|
747
|
+
**Symptoms:**
|
|
748
|
+
- Commands reach nodes but no response received
|
|
749
|
+
- Node serial shows command execution but no MQTT response
|
|
750
|
+
|
|
751
|
+
**Solutions:**
|
|
752
|
+
1. **Verify Command Handler**: Ensure nodes have command handler implemented
|
|
753
|
+
2. **Check Command ID**: Confirm command ID is supported by node
|
|
754
|
+
3. **Monitor Serial Output**: Check node serial for command reception
|
|
755
|
+
4. **Validate Parameters**: Ensure parameter JSON is valid
|
|
756
|
+
5. **Check Response Routing**: Verify responses are reaching gateway
|
|
757
|
+
|
|
758
|
+
### MQTT Broker Issues
|
|
759
|
+
|
|
760
|
+
**Symptoms:**
|
|
761
|
+
- Gateway can't connect to broker
|
|
762
|
+
- Messages not being delivered
|
|
763
|
+
|
|
764
|
+
**Solutions:**
|
|
765
|
+
1. **Connection Refused**: Check broker IP, port, credentials
|
|
766
|
+
```cpp
|
|
767
|
+
mqttClient.setServer(MQTT_BROKER_IP, MQTT_BROKER_PORT);
|
|
768
|
+
if (!mqttClient.connect("painlessMesh-gateway")) {
|
|
769
|
+
Serial.printf("MQTT error: %d\n", mqttClient.state());
|
|
770
|
+
}
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
2. **Topic Not Found**: Verify subscription before publishing
|
|
774
|
+
```cpp
|
|
775
|
+
// Subscribe first
|
|
776
|
+
mqtt.subscribe("mesh/command/#");
|
|
777
|
+
delay(100);
|
|
778
|
+
// Then publish
|
|
779
|
+
mqtt.publish("mesh/response/123", "test");
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
3. **QoS Issues**: Use QoS 1 for reliable delivery
|
|
783
|
+
```cpp
|
|
784
|
+
mqtt.publish(topic, payload, true); // retained = true
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
4. **Retained Messages**: Clear retained messages if needed
|
|
788
|
+
```bash
|
|
789
|
+
mosquitto_pub -h 192.168.1.100 -t "mesh/command/123456" -n -r
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### Memory Issues
|
|
793
|
+
|
|
794
|
+
**Symptoms:**
|
|
795
|
+
- Gateway crashes or reboots unexpectedly
|
|
796
|
+
- Commands work initially but fail after time
|
|
797
|
+
|
|
798
|
+
**Solutions:**
|
|
799
|
+
1. **Monitor Heap**: Check free memory regularly
|
|
800
|
+
```cpp
|
|
801
|
+
Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
2. **Optimize JSON Buffer Size**: Use appropriate buffer sizes
|
|
805
|
+
```cpp
|
|
806
|
+
// Too large wastes memory
|
|
807
|
+
DynamicJsonDocument doc(1024); // Adjust based on needs
|
|
808
|
+
```
|
|
809
|
+
|
|
810
|
+
3. **Clean Up Objects**: Delete unused objects
|
|
811
|
+
```cpp
|
|
812
|
+
delete commandBridge; // If recreating
|
|
813
|
+
```
|
|
814
|
+
|
|
815
|
+
4. **Reduce Debug Output**: Disable verbose logging in production
|
|
816
|
+
|
|
817
|
+
### Network Stability
|
|
818
|
+
|
|
819
|
+
**Symptoms:**
|
|
820
|
+
- Intermittent command delivery
|
|
821
|
+
- Nodes dropping from mesh
|
|
822
|
+
|
|
823
|
+
**Solutions:**
|
|
824
|
+
1. **Check WiFi Signal**: Ensure strong WiFi for gateway
|
|
825
|
+
2. **Reduce Mesh Traffic**: Space out command sends
|
|
826
|
+
3. **Use Exponential Backoff**: Retry failed commands with delay
|
|
827
|
+
4. **Monitor Mesh Health**: Track connection changes
|
|
828
|
+
|
|
829
|
+
---
|
|
830
|
+
|
|
831
|
+
## Best Practices
|
|
832
|
+
|
|
833
|
+
### Command Design
|
|
834
|
+
|
|
835
|
+
1. **Use Unique Command IDs**: Generate unique IDs for tracking
|
|
836
|
+
```cpp
|
|
837
|
+
cmd.commandId = millis() | (nodeId << 16);
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
2. **Keep Parameters Small**: Minimize JSON parameter size
|
|
841
|
+
```json
|
|
842
|
+
Good: {"s":1,"b":75}
|
|
843
|
+
Avoid: {"state":"enabled","brightness_level":75,"extra_field":"unused"}
|
|
844
|
+
```
|
|
845
|
+
|
|
846
|
+
3. **Implement Timeouts**: Don't wait indefinitely for responses
|
|
847
|
+
```javascript
|
|
848
|
+
const timeout = setTimeout(() => {
|
|
849
|
+
console.log('Command timeout');
|
|
850
|
+
}, 5000);
|
|
851
|
+
```
|
|
852
|
+
|
|
853
|
+
4. **Handle Failures Gracefully**: Retry important commands
|
|
854
|
+
```javascript
|
|
855
|
+
let retries = 3;
|
|
856
|
+
function sendCommand() {
|
|
857
|
+
client.publish(topic, command);
|
|
858
|
+
setTimeout(() => {
|
|
859
|
+
if (!responseReceived && retries-- > 0) {
|
|
860
|
+
sendCommand();
|
|
861
|
+
}
|
|
862
|
+
}, 2000);
|
|
863
|
+
}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Security Considerations
|
|
867
|
+
|
|
868
|
+
1. **Use Authentication**: Enable MQTT broker authentication
|
|
869
|
+
2. **Validate Commands**: Check command bounds and parameters
|
|
870
|
+
3. **Rate Limiting**: Limit command frequency per client
|
|
871
|
+
4. **Access Control**: Restrict sensitive commands
|
|
872
|
+
5. **Encryption**: Use TLS for production MQTT connections
|
|
873
|
+
|
|
874
|
+
### Performance Optimization
|
|
875
|
+
|
|
876
|
+
1. **Batch Commands**: Group related commands when possible
|
|
877
|
+
2. **Cache Configuration**: Avoid repeated config requests
|
|
878
|
+
3. **Use Broadcast Sparingly**: Unicast when targeting specific nodes
|
|
879
|
+
4. **Monitor Latency**: Track command response times
|
|
880
|
+
|
|
881
|
+
---
|
|
882
|
+
|
|
883
|
+
## Related Documentation
|
|
884
|
+
|
|
885
|
+
- [OTA Commands Reference](OTA_COMMANDS_REFERENCE.md) - Firmware update commands
|
|
886
|
+
- [API Reference](api/core-api.md) - Core painlessMesh API
|
|
887
|
+
- [Plugin System](architecture/plugin-system.md) - Custom package development
|
|
888
|
+
- [Alteriom Overview](alteriom/overview.md) - Alteriom package types
|
|
889
|
+
|
|
890
|
+
---
|
|
891
|
+
|
|
892
|
+
**Last Updated:** October 2025
|
|
893
|
+
**painlessMesh Version:** 1.7.0+ Alteriom Fork
|
|
894
|
+
**Author:** Alteriom Development Team
|