@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,576 @@
|
|
|
1
|
+
# MQTT Command Schema Proposal for @alteriom/mqtt-schema v0.5.0
|
|
2
|
+
|
|
3
|
+
**Date:** October 12, 2025
|
|
4
|
+
**Proposed By:** Alteriom Firmware Team
|
|
5
|
+
**Target Version:** @alteriom/mqtt-schema v0.5.0
|
|
6
|
+
**Status:** PROPOSAL
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Executive Summary
|
|
11
|
+
|
|
12
|
+
This proposal adds standardized command and command response schemas to @alteriom/mqtt-schema to enable bidirectional control flow between MQTT clients (web apps, automation systems) and IoT devices (sensors, gateways).
|
|
13
|
+
|
|
14
|
+
**Current State (v0.4.0):**
|
|
15
|
+
- ✅ Sensor data telemetry (sensor_data.schema.json)
|
|
16
|
+
- ✅ Gateway metrics and status
|
|
17
|
+
- ✅ Control responses (control_response.schema.json) - **EXISTS BUT LIMITED**
|
|
18
|
+
- ❌ Device control commands - **MISSING**
|
|
19
|
+
|
|
20
|
+
**Proposed Addition:**
|
|
21
|
+
- New schema: `command.schema.json` - Standardized command structure
|
|
22
|
+
- Enhanced schema: `command_response.schema.json` - Extend control_response with correlation tracking
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Use Case
|
|
27
|
+
|
|
28
|
+
**Scenario**: Web dashboard needs to trigger immediate sensor reading
|
|
29
|
+
|
|
30
|
+
**Current Workaround**: Custom JSON format, no validation
|
|
31
|
+
```json
|
|
32
|
+
{
|
|
33
|
+
"type": "command",
|
|
34
|
+
"node_id": 1693975713,
|
|
35
|
+
"command": "read_sensors"
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
❌ Not schema-validated
|
|
39
|
+
❌ No timestamp
|
|
40
|
+
❌ No correlation tracking
|
|
41
|
+
❌ No response linking
|
|
42
|
+
|
|
43
|
+
**Proposed Standard**:
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"schema_version": 1,
|
|
47
|
+
"device_id": "ALT-441D64F804A0",
|
|
48
|
+
"device_type": "sensor",
|
|
49
|
+
"timestamp": "2025-10-12T14:30:00Z",
|
|
50
|
+
"firmware_version": "SN 2.3.4",
|
|
51
|
+
"event": "command",
|
|
52
|
+
"command": "read_sensors",
|
|
53
|
+
"correlation_id": "cmd-1728745800-001",
|
|
54
|
+
"parameters": {
|
|
55
|
+
"immediate": true,
|
|
56
|
+
"sensors": ["temperature", "humidity"]
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
✅ Schema-validated
|
|
61
|
+
✅ Envelope compliance
|
|
62
|
+
✅ Correlation tracking
|
|
63
|
+
✅ Typed parameters
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Proposed Schema: command.schema.json
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
72
|
+
"$id": "https://schemas.alteriom.io/mqtt/v1/command.schema.json",
|
|
73
|
+
"title": "Device Command v1",
|
|
74
|
+
"description": "Command message sent from MQTT client to IoT device for control operations",
|
|
75
|
+
"allOf": [{"$ref": "envelope.schema.json"}],
|
|
76
|
+
"type": "object",
|
|
77
|
+
"required": ["event", "command"],
|
|
78
|
+
"properties": {
|
|
79
|
+
"event": {
|
|
80
|
+
"type": "string",
|
|
81
|
+
"const": "command",
|
|
82
|
+
"description": "Event type discriminator"
|
|
83
|
+
},
|
|
84
|
+
"command": {
|
|
85
|
+
"type": "string",
|
|
86
|
+
"minLength": 1,
|
|
87
|
+
"maxLength": 64,
|
|
88
|
+
"pattern": "^[a-z][a-z0-9_]*$",
|
|
89
|
+
"description": "Command name in snake_case (e.g., read_sensors, set_interval, restart)",
|
|
90
|
+
"examples": [
|
|
91
|
+
"read_sensors",
|
|
92
|
+
"set_interval",
|
|
93
|
+
"enable_sensor",
|
|
94
|
+
"update_config",
|
|
95
|
+
"restart",
|
|
96
|
+
"get_status"
|
|
97
|
+
]
|
|
98
|
+
},
|
|
99
|
+
"correlation_id": {
|
|
100
|
+
"type": "string",
|
|
101
|
+
"minLength": 1,
|
|
102
|
+
"maxLength": 128,
|
|
103
|
+
"pattern": "^[A-Za-z0-9_-]+$",
|
|
104
|
+
"description": "Unique identifier for tracking command → response lifecycle"
|
|
105
|
+
},
|
|
106
|
+
"parameters": {
|
|
107
|
+
"type": "object",
|
|
108
|
+
"description": "Command-specific parameters (validated by device)",
|
|
109
|
+
"additionalProperties": true,
|
|
110
|
+
"examples": [
|
|
111
|
+
{"interval": 30000},
|
|
112
|
+
{"sensor": "temperature", "enabled": true},
|
|
113
|
+
{"immediate": true, "sensors": ["temperature", "humidity"]}
|
|
114
|
+
]
|
|
115
|
+
},
|
|
116
|
+
"timeout_ms": {
|
|
117
|
+
"type": "integer",
|
|
118
|
+
"minimum": 1000,
|
|
119
|
+
"maximum": 300000,
|
|
120
|
+
"default": 5000,
|
|
121
|
+
"description": "Command execution timeout in milliseconds"
|
|
122
|
+
},
|
|
123
|
+
"priority": {
|
|
124
|
+
"type": "string",
|
|
125
|
+
"enum": ["low", "normal", "high", "urgent"],
|
|
126
|
+
"default": "normal",
|
|
127
|
+
"description": "Command priority for queue management"
|
|
128
|
+
}
|
|
129
|
+
},
|
|
130
|
+
"additionalProperties": true
|
|
131
|
+
}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### Field Specifications
|
|
135
|
+
|
|
136
|
+
| Field | Type | Required | Description |
|
|
137
|
+
|-------|------|----------|-------------|
|
|
138
|
+
| `schema_version` | integer | ✅ | Always 1 (from envelope) |
|
|
139
|
+
| `device_id` | string | ✅ | Target device ID (from envelope) |
|
|
140
|
+
| `device_type` | string | ✅ | "sensor" or "gateway" (from envelope) |
|
|
141
|
+
| `timestamp` | string (ISO 8601) | ✅ | Command creation time (from envelope) |
|
|
142
|
+
| `firmware_version` | string | ✅ | Sender firmware version (from envelope) |
|
|
143
|
+
| `event` | "command" | ✅ | Event type discriminator |
|
|
144
|
+
| `command` | string | ✅ | Command name (snake_case) |
|
|
145
|
+
| `correlation_id` | string | ❌ | Unique tracking ID (recommended) |
|
|
146
|
+
| `parameters` | object | ❌ | Command-specific parameters |
|
|
147
|
+
| `timeout_ms` | integer | ❌ | Execution timeout (default: 5000ms) |
|
|
148
|
+
| `priority` | enum | ❌ | Queue priority (default: "normal") |
|
|
149
|
+
|
|
150
|
+
---
|
|
151
|
+
|
|
152
|
+
## Enhanced Schema: command_response.schema.json
|
|
153
|
+
|
|
154
|
+
**Note**: This extends/replaces the existing `control_response.schema.json`
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
159
|
+
"$id": "https://schemas.alteriom.io/mqtt/v1/command_response.schema.json",
|
|
160
|
+
"title": "Command Response v1",
|
|
161
|
+
"description": "Response message from IoT device after executing a command",
|
|
162
|
+
"allOf": [{"$ref": "envelope.schema.json"}],
|
|
163
|
+
"type": "object",
|
|
164
|
+
"required": ["event", "success"],
|
|
165
|
+
"properties": {
|
|
166
|
+
"event": {
|
|
167
|
+
"type": "string",
|
|
168
|
+
"const": "command_response",
|
|
169
|
+
"description": "Event type discriminator"
|
|
170
|
+
},
|
|
171
|
+
"command": {
|
|
172
|
+
"type": "string",
|
|
173
|
+
"minLength": 1,
|
|
174
|
+
"maxLength": 64,
|
|
175
|
+
"description": "Original command name that was executed"
|
|
176
|
+
},
|
|
177
|
+
"correlation_id": {
|
|
178
|
+
"type": "string",
|
|
179
|
+
"minLength": 1,
|
|
180
|
+
"maxLength": 128,
|
|
181
|
+
"pattern": "^[A-Za-z0-9_-]+$",
|
|
182
|
+
"description": "Matches correlation_id from original command"
|
|
183
|
+
},
|
|
184
|
+
"success": {
|
|
185
|
+
"type": "boolean",
|
|
186
|
+
"description": "Whether command execution succeeded"
|
|
187
|
+
},
|
|
188
|
+
"result": {
|
|
189
|
+
"type": ["object", "array", "string", "number", "boolean", "null"],
|
|
190
|
+
"description": "Command execution result data"
|
|
191
|
+
},
|
|
192
|
+
"message": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"maxLength": 256,
|
|
195
|
+
"description": "Human-readable status message"
|
|
196
|
+
},
|
|
197
|
+
"error_code": {
|
|
198
|
+
"type": "string",
|
|
199
|
+
"maxLength": 64,
|
|
200
|
+
"description": "Machine-readable error code (e.g., TIMEOUT, INVALID_PARAMS)"
|
|
201
|
+
},
|
|
202
|
+
"latency_ms": {
|
|
203
|
+
"type": "integer",
|
|
204
|
+
"minimum": 0,
|
|
205
|
+
"description": "Time taken to execute command in milliseconds"
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
"additionalProperties": true
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### Field Specifications
|
|
213
|
+
|
|
214
|
+
| Field | Type | Required | Description |
|
|
215
|
+
|-------|------|----------|-------------|
|
|
216
|
+
| `schema_version` | integer | ✅ | Always 1 (from envelope) |
|
|
217
|
+
| `device_id` | string | ✅ | Responding device ID (from envelope) |
|
|
218
|
+
| `device_type` | string | ✅ | "sensor" or "gateway" (from envelope) |
|
|
219
|
+
| `timestamp` | string (ISO 8601) | ✅ | Response creation time (from envelope) |
|
|
220
|
+
| `firmware_version` | string | ✅ | Device firmware version (from envelope) |
|
|
221
|
+
| `event` | "command_response" | ✅ | Event type discriminator |
|
|
222
|
+
| `command` | string | ❌ | Original command name |
|
|
223
|
+
| `correlation_id` | string | ❌ | Links to original command (strongly recommended) |
|
|
224
|
+
| `success` | boolean | ✅ | Execution success/failure |
|
|
225
|
+
| `result` | any | ❌ | Command result data |
|
|
226
|
+
| `message` | string | ❌ | Human-readable message |
|
|
227
|
+
| `error_code` | string | ❌ | Machine-readable error code |
|
|
228
|
+
| `latency_ms` | integer | ❌ | Execution time |
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Complete Examples
|
|
233
|
+
|
|
234
|
+
### Example 1: Read Sensors Command
|
|
235
|
+
|
|
236
|
+
**MQTT Topic**: `alteriom/nodes/ALT-441D64F804A0/commands`
|
|
237
|
+
|
|
238
|
+
**Command Payload**:
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"schema_version": 1,
|
|
242
|
+
"device_id": "ALT-441D64F804A0",
|
|
243
|
+
"device_type": "sensor",
|
|
244
|
+
"timestamp": "2025-10-12T14:30:00Z",
|
|
245
|
+
"firmware_version": "WEB 1.0.0",
|
|
246
|
+
"event": "command",
|
|
247
|
+
"command": "read_sensors",
|
|
248
|
+
"correlation_id": "cmd-1728745800-001",
|
|
249
|
+
"parameters": {
|
|
250
|
+
"immediate": true,
|
|
251
|
+
"sensors": ["temperature", "humidity", "pressure"]
|
|
252
|
+
},
|
|
253
|
+
"timeout_ms": 5000,
|
|
254
|
+
"priority": "high"
|
|
255
|
+
}
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
**Response Topic**: `alteriom/nodes/ALT-441D64F804A0/responses`
|
|
259
|
+
|
|
260
|
+
**Response Payload**:
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"schema_version": 1,
|
|
264
|
+
"device_id": "ALT-441D64F804A0",
|
|
265
|
+
"device_type": "sensor",
|
|
266
|
+
"timestamp": "2025-10-12T14:30:02Z",
|
|
267
|
+
"firmware_version": "SN 2.3.4",
|
|
268
|
+
"event": "command_response",
|
|
269
|
+
"command": "read_sensors",
|
|
270
|
+
"correlation_id": "cmd-1728745800-001",
|
|
271
|
+
"success": true,
|
|
272
|
+
"result": {
|
|
273
|
+
"sensors_read": ["temperature", "humidity", "pressure"],
|
|
274
|
+
"values": {
|
|
275
|
+
"temperature": 23.5,
|
|
276
|
+
"humidity": 45,
|
|
277
|
+
"pressure": 1013
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"message": "Sensors read successfully",
|
|
281
|
+
"latency_ms": 1250
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Example 2: Set Interval Command
|
|
286
|
+
|
|
287
|
+
**Command**:
|
|
288
|
+
```json
|
|
289
|
+
{
|
|
290
|
+
"schema_version": 1,
|
|
291
|
+
"device_id": "ALT-441D64F804A0",
|
|
292
|
+
"device_type": "sensor",
|
|
293
|
+
"timestamp": "2025-10-12T14:35:00Z",
|
|
294
|
+
"firmware_version": "WEB 1.0.0",
|
|
295
|
+
"event": "command",
|
|
296
|
+
"command": "set_interval",
|
|
297
|
+
"correlation_id": "cmd-1728746100-002",
|
|
298
|
+
"parameters": {
|
|
299
|
+
"interval": 60000
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
**Response**:
|
|
305
|
+
```json
|
|
306
|
+
{
|
|
307
|
+
"schema_version": 1,
|
|
308
|
+
"device_id": "ALT-441D64F804A0",
|
|
309
|
+
"device_type": "sensor",
|
|
310
|
+
"timestamp": "2025-10-12T14:35:01Z",
|
|
311
|
+
"firmware_version": "SN 2.3.4",
|
|
312
|
+
"event": "command_response",
|
|
313
|
+
"command": "set_interval",
|
|
314
|
+
"correlation_id": "cmd-1728746100-002",
|
|
315
|
+
"success": true,
|
|
316
|
+
"result": {
|
|
317
|
+
"old_interval": 30000,
|
|
318
|
+
"new_interval": 60000
|
|
319
|
+
},
|
|
320
|
+
"message": "Reading interval updated to 60s",
|
|
321
|
+
"latency_ms": 450
|
|
322
|
+
}
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### Example 3: Command Error
|
|
326
|
+
|
|
327
|
+
**Command**:
|
|
328
|
+
```json
|
|
329
|
+
{
|
|
330
|
+
"schema_version": 1,
|
|
331
|
+
"device_id": "ALT-441D64F804A0",
|
|
332
|
+
"device_type": "sensor",
|
|
333
|
+
"timestamp": "2025-10-12T14:40:00Z",
|
|
334
|
+
"firmware_version": "WEB 1.0.0",
|
|
335
|
+
"event": "command",
|
|
336
|
+
"command": "enable_sensor",
|
|
337
|
+
"correlation_id": "cmd-1728746400-003",
|
|
338
|
+
"parameters": {
|
|
339
|
+
"sensor": "gps",
|
|
340
|
+
"enabled": true
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
**Error Response**:
|
|
346
|
+
```json
|
|
347
|
+
{
|
|
348
|
+
"schema_version": 1,
|
|
349
|
+
"device_id": "ALT-441D64F804A0",
|
|
350
|
+
"device_type": "sensor",
|
|
351
|
+
"timestamp": "2025-10-12T14:40:01Z",
|
|
352
|
+
"firmware_version": "SN 2.3.4",
|
|
353
|
+
"event": "command_response",
|
|
354
|
+
"command": "enable_sensor",
|
|
355
|
+
"correlation_id": "cmd-1728746400-003",
|
|
356
|
+
"success": false,
|
|
357
|
+
"result": null,
|
|
358
|
+
"message": "GPS sensor not available on this device",
|
|
359
|
+
"error_code": "SENSOR_NOT_AVAILABLE",
|
|
360
|
+
"latency_ms": 120
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Example 4: Command Timeout
|
|
365
|
+
|
|
366
|
+
**Gateway-Generated Error Response** (when device doesn't respond):
|
|
367
|
+
```json
|
|
368
|
+
{
|
|
369
|
+
"schema_version": 1,
|
|
370
|
+
"device_id": "ALT-6825DD341CA4",
|
|
371
|
+
"device_type": "gateway",
|
|
372
|
+
"timestamp": "2025-10-12T14:45:05Z",
|
|
373
|
+
"firmware_version": "GW 2.3.4",
|
|
374
|
+
"event": "command_response",
|
|
375
|
+
"command": "restart",
|
|
376
|
+
"correlation_id": "cmd-1728746700-004",
|
|
377
|
+
"success": false,
|
|
378
|
+
"result": {
|
|
379
|
+
"target_device": "ALT-441D64F804A0",
|
|
380
|
+
"timeout_ms": 5000
|
|
381
|
+
},
|
|
382
|
+
"message": "Command timeout - device did not respond within 5000ms",
|
|
383
|
+
"error_code": "TIMEOUT",
|
|
384
|
+
"latency_ms": 5000
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
---
|
|
389
|
+
|
|
390
|
+
## Standard Command Names
|
|
391
|
+
|
|
392
|
+
To promote interoperability, we recommend these standard command names:
|
|
393
|
+
|
|
394
|
+
### Device Control
|
|
395
|
+
- `restart` - Reboot device
|
|
396
|
+
- `factory_reset` - Reset to factory defaults
|
|
397
|
+
- `sleep` - Enter low-power mode
|
|
398
|
+
- `wake` - Exit low-power mode
|
|
399
|
+
|
|
400
|
+
### Sensor Operations
|
|
401
|
+
- `read_sensors` - Trigger immediate sensor reading
|
|
402
|
+
- `enable_sensor` - Enable/disable specific sensor
|
|
403
|
+
- `calibrate_sensor` - Calibrate sensor
|
|
404
|
+
- `set_interval` - Update reading interval
|
|
405
|
+
|
|
406
|
+
### Configuration
|
|
407
|
+
- `get_config` - Request current configuration
|
|
408
|
+
- `set_config` - Update configuration
|
|
409
|
+
- `save_config` - Persist config to flash
|
|
410
|
+
- `get_status` - Request device status
|
|
411
|
+
|
|
412
|
+
### Network
|
|
413
|
+
- `scan_networks` - Scan WiFi/LoRa networks
|
|
414
|
+
- `connect` - Connect to network
|
|
415
|
+
- `disconnect` - Disconnect from network
|
|
416
|
+
|
|
417
|
+
### Firmware
|
|
418
|
+
- `start_ota` - Begin OTA update
|
|
419
|
+
- `cancel_ota` - Cancel OTA update
|
|
420
|
+
- `get_version` - Request firmware version
|
|
421
|
+
|
|
422
|
+
### Diagnostics
|
|
423
|
+
- `run_diagnostics` - Run self-test
|
|
424
|
+
- `get_logs` - Retrieve device logs
|
|
425
|
+
- `clear_logs` - Clear log storage
|
|
426
|
+
|
|
427
|
+
**Note**: Devices may implement custom commands with `custom_` prefix (e.g., `custom_led_pattern`)
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Error Codes Reference
|
|
432
|
+
|
|
433
|
+
Standard error codes for `error_code` field:
|
|
434
|
+
|
|
435
|
+
| Code | Description |
|
|
436
|
+
|------|-------------|
|
|
437
|
+
| `UNKNOWN_COMMAND` | Command name not recognized |
|
|
438
|
+
| `INVALID_PARAMS` | Invalid or missing parameters |
|
|
439
|
+
| `TIMEOUT` | Command execution timeout |
|
|
440
|
+
| `DEVICE_BUSY` | Device busy, cannot execute |
|
|
441
|
+
| `PERMISSION_DENIED` | Insufficient permissions |
|
|
442
|
+
| `SENSOR_NOT_AVAILABLE` | Sensor not present/enabled |
|
|
443
|
+
| `CONFIG_ERROR` | Configuration update failed |
|
|
444
|
+
| `NETWORK_ERROR` | Network operation failed |
|
|
445
|
+
| `FIRMWARE_ERROR` | Firmware operation failed |
|
|
446
|
+
| `STORAGE_ERROR` | Storage operation failed |
|
|
447
|
+
| `HARDWARE_ERROR` | Hardware failure detected |
|
|
448
|
+
| `RATE_LIMITED` | Too many commands |
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
452
|
+
## Migration Path
|
|
453
|
+
|
|
454
|
+
### From control_response.schema.json to command_response.schema.json
|
|
455
|
+
|
|
456
|
+
**Old Format** (control_response.schema.json):
|
|
457
|
+
```json
|
|
458
|
+
{
|
|
459
|
+
"schema_version": 1,
|
|
460
|
+
"device_id": "ALT-441D64F804A0",
|
|
461
|
+
"device_type": "sensor",
|
|
462
|
+
"timestamp": "2025-10-12T14:30:02Z",
|
|
463
|
+
"firmware_version": "SN 2.3.4",
|
|
464
|
+
"command": "read_sensors",
|
|
465
|
+
"status": "ok",
|
|
466
|
+
"message": "Sensors read successfully",
|
|
467
|
+
"result": {"temperature": 23.5}
|
|
468
|
+
}
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
**New Format** (command_response.schema.json):
|
|
472
|
+
```json
|
|
473
|
+
{
|
|
474
|
+
"schema_version": 1,
|
|
475
|
+
"device_id": "ALT-441D64F804A0",
|
|
476
|
+
"device_type": "sensor",
|
|
477
|
+
"timestamp": "2025-10-12T14:30:02Z",
|
|
478
|
+
"firmware_version": "SN 2.3.4",
|
|
479
|
+
"event": "command_response",
|
|
480
|
+
"command": "read_sensors",
|
|
481
|
+
"correlation_id": "cmd-1728745800-001",
|
|
482
|
+
"success": true,
|
|
483
|
+
"message": "Sensors read successfully",
|
|
484
|
+
"result": {"temperature": 23.5},
|
|
485
|
+
"latency_ms": 1250
|
|
486
|
+
}
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
**Key Changes**:
|
|
490
|
+
1. Added `event: "command_response"` discriminator
|
|
491
|
+
2. Replaced `status: "ok"|"error"` with `success: boolean`
|
|
492
|
+
3. Added `correlation_id` for request tracking
|
|
493
|
+
4. Added `latency_ms` for performance monitoring
|
|
494
|
+
5. Added `error_code` for machine-readable errors
|
|
495
|
+
|
|
496
|
+
**Backward Compatibility**:
|
|
497
|
+
- Old `control_response.schema.json` can coexist
|
|
498
|
+
- Validators can accept both formats during transition
|
|
499
|
+
- Recommend deprecating `control_response` in v0.6.0
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
## Implementation Checklist
|
|
504
|
+
|
|
505
|
+
### For @alteriom/mqtt-schema Repository
|
|
506
|
+
|
|
507
|
+
- [ ] Create `schemas/command.schema.json`
|
|
508
|
+
- [ ] Create `schemas/command_response.schema.json`
|
|
509
|
+
- [ ] Update `mqtt_v1_bundle.json` to include new schemas
|
|
510
|
+
- [ ] Generate TypeScript types from schemas
|
|
511
|
+
- [ ] Add Ajv validators for command and command_response
|
|
512
|
+
- [ ] Update `classifyAndValidate()` to recognize `event: "command"`
|
|
513
|
+
- [ ] Add type guards: `isCommandMessage()`, `isCommandResponseMessage()`
|
|
514
|
+
- [ ] Update README.md with command examples
|
|
515
|
+
- [ ] Add validation tests for command schemas
|
|
516
|
+
- [ ] Update CHANGELOG.md for v0.5.0
|
|
517
|
+
- [ ] Deprecation notice for `control_response.schema.json` (remove in v0.6.0)
|
|
518
|
+
|
|
519
|
+
### For alteriom-firmware Repository
|
|
520
|
+
|
|
521
|
+
- [ ] Update `package.json` to `@alteriom/mqtt-schema@^0.5.0`
|
|
522
|
+
- [ ] Implement `mqtt_command_bridge.cpp` with schema validation
|
|
523
|
+
- [ ] Update `mqtt_spec_builder.cpp` to support command messages
|
|
524
|
+
- [ ] Update `mqtt_spec_builder.cpp` to support command_response messages
|
|
525
|
+
- [ ] Add command name constants to `mqtt_spec_builder.h`
|
|
526
|
+
- [ ] Update documentation with command examples
|
|
527
|
+
- [ ] Add integration tests for command flow
|
|
528
|
+
- [ ] Update CHANGELOG.md
|
|
529
|
+
|
|
530
|
+
---
|
|
531
|
+
|
|
532
|
+
## Benefits
|
|
533
|
+
|
|
534
|
+
1. **Standardization**: All commands follow same structure
|
|
535
|
+
2. **Validation**: JSON schema validation catches errors early
|
|
536
|
+
3. **Traceability**: Correlation IDs link commands to responses
|
|
537
|
+
4. **Monitoring**: Latency tracking enables performance analysis
|
|
538
|
+
5. **Interoperability**: Standard command names work across vendors
|
|
539
|
+
6. **Error Handling**: Machine-readable error codes
|
|
540
|
+
7. **Type Safety**: TypeScript types generated from schemas
|
|
541
|
+
8. **Documentation**: Self-documenting via JSON schema
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## Questions for Schema Maintainers
|
|
546
|
+
|
|
547
|
+
1. **Naming Convention**: Should we use `command` or `control` for the event type?
|
|
548
|
+
- Proposal: `event: "command"` for requests, `event: "command_response"` for responses
|
|
549
|
+
- Alternative: `event: "control"` / `event: "control_response"`
|
|
550
|
+
|
|
551
|
+
2. **Priority Field**: Should priority be standardized or left to implementation?
|
|
552
|
+
- Current proposal: Standard enum with optional usage
|
|
553
|
+
|
|
554
|
+
3. **Timeout Field**: Should timeout be in command or handled by client?
|
|
555
|
+
- Current proposal: Optional field in command message
|
|
556
|
+
|
|
557
|
+
4. **Backward Compatibility**: Deprecate `control_response.schema.json` now or later?
|
|
558
|
+
- Current proposal: Deprecate in v0.5.0, remove in v0.6.0
|
|
559
|
+
|
|
560
|
+
5. **Custom Commands**: Should we enforce `custom_` prefix or allow any name?
|
|
561
|
+
- Current proposal: Recommend `custom_` prefix, but allow any valid snake_case
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## References
|
|
566
|
+
|
|
567
|
+
- [@alteriom/mqtt-schema v0.4.0](https://www.npmjs.com/package/@alteriom/mqtt-schema)
|
|
568
|
+
- [JSON Schema Draft 2020-12](https://json-schema.org/draft/2020-12/schema)
|
|
569
|
+
- [MQTT Topics Best Practices](https://www.hivemq.com/blog/mqtt-essentials-part-5-mqtt-topics-best-practices/)
|
|
570
|
+
- [alteriom-firmware MQTT_BRIDGE_IMPROVEMENTS.md](../analysis/MQTT_BRIDGE_IMPROVEMENTS.md)
|
|
571
|
+
|
|
572
|
+
---
|
|
573
|
+
|
|
574
|
+
**Submitted By**: Alteriom Firmware Development Team
|
|
575
|
+
**Contact**: [GitHub Issues](https://github.com/Alteriom/alteriom-mqtt-schema/issues)
|
|
576
|
+
**Date**: October 12, 2025
|