@alteriom/painlessmesh 1.7.6 → 1.7.7
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 +107 -0
- package/README.md +81 -6
- package/RELEASE_GUIDE.md +36 -0
- package/docs/MQTT_BRIDGE_COMMANDS.md +10 -10
- package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +1 -1
- package/docs/MQTT_SCHEMA_COMPLIANCE.md +57 -2
- package/docs/PHASE1_GUIDE.md +1 -1
- package/docs/alteriom/overview.md +2 -2
- package/docs/architecture/plugin-system.md +1 -1
- package/docs/archive/RELEASE_SUMMARY.md +1 -1
- package/docs/releases/RELEASE_CHECKLIST_v1.7.6.md +389 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.7.md +391 -0
- package/docs/v1.7.7_MQTT_IMPROVEMENTS.md +776 -0
- package/docs/wiki/API-Reference.md +2 -2
- package/docs/wiki/Complete-Documentation.md +1 -1
- package/examples/alteriom/README.md +137 -3
- package/examples/alteriom/alteriom.ino +1 -1
- package/examples/alteriom/alteriom_sensor_package.hpp +557 -2
- package/examples/alteriomImproved/alteriom_sensor_package.hpp +1 -1
- package/examples/alteriomImproved/improved_sensor_node.ino +1 -1
- package/examples/alteriomMetricsHealth/alteriom_sensor_package.hpp +796 -0
- package/examples/alteriomMetricsHealth/metrics_health_node.ino +418 -0
- package/examples/alteriomMetricsHealth/platformio.ini +26 -0
- package/examples/alteriomPhase1/alteriom_sensor_package.hpp +1 -1
- package/examples/alteriomPhase1/phase1_features.ino +2 -2
- package/examples/alteriomPhase2/alteriom_sensor_package.hpp +1 -1
- package/examples/alteriomSensorNode/alteriom_sensor_node.ino +1 -1
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +1 -1
- package/examples/bridge/enhanced_mqtt_bridge.hpp +610 -0
- package/examples/bridge/enhanced_mqtt_bridge_example.ino +226 -0
- package/examples/meshCommandNode/alteriom_sensor_package.hpp +1 -1
- package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +1 -1
- package/examples/mqttTopologyTest/mqttTopologyTest.ino +5 -1
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enhanced MQTT Bridge Example - painlessMesh v1.7.7
|
|
3
|
+
*
|
|
4
|
+
* Demonstrates the enhanced MQTT bridge with:
|
|
5
|
+
* - Command handlers for requesting metrics and health checks
|
|
6
|
+
* - Aggregated network statistics
|
|
7
|
+
* - Real-time metric collection from mesh nodes
|
|
8
|
+
* - Health monitoring with alerting
|
|
9
|
+
*
|
|
10
|
+
* This gateway node bridges between MQTT and the mesh network,
|
|
11
|
+
* enabling remote monitoring and control.
|
|
12
|
+
*
|
|
13
|
+
* Hardware: ESP32 with WiFi (ESP8266 also supported)
|
|
14
|
+
*
|
|
15
|
+
* MQTT Topics:
|
|
16
|
+
* Subscribe (Commands):
|
|
17
|
+
* - mesh/command/request_metrics {"node_id": 0} // 0 = all nodes
|
|
18
|
+
* - mesh/command/request_health {"node_id": 12345}
|
|
19
|
+
* - mesh/command/get_aggregated {}
|
|
20
|
+
*
|
|
21
|
+
* Publish (Data):
|
|
22
|
+
* - mesh/metrics/{node_id} // Individual node metrics
|
|
23
|
+
* - mesh/health/{node_id} // Individual node health
|
|
24
|
+
* - mesh/aggregated/metrics // Aggregated mesh-wide metrics
|
|
25
|
+
* - mesh/aggregated/health // Aggregated mesh health summary
|
|
26
|
+
* - mesh/alerts/critical // Critical health alerts
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
#include "painlessMesh.h"
|
|
30
|
+
#include <WiFi.h>
|
|
31
|
+
#include <PubSubClient.h>
|
|
32
|
+
#include "enhanced_mqtt_bridge.hpp"
|
|
33
|
+
|
|
34
|
+
// Mesh Configuration
|
|
35
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
36
|
+
#define MESH_PASSWORD "your_password"
|
|
37
|
+
#define MESH_PORT 5555
|
|
38
|
+
|
|
39
|
+
// WiFi Station Configuration (for MQTT connection)
|
|
40
|
+
#define STATION_SSID "your_wifi_ssid"
|
|
41
|
+
#define STATION_PASSWORD "your_wifi_password"
|
|
42
|
+
|
|
43
|
+
// MQTT Configuration
|
|
44
|
+
#define MQTT_BROKER "192.168.1.100" // Your MQTT broker IP
|
|
45
|
+
#define MQTT_PORT 1883
|
|
46
|
+
#define MQTT_USER "mqtt_user" // Leave empty if no auth
|
|
47
|
+
#define MQTT_PASSWORD "mqtt_password" // Leave empty if no auth
|
|
48
|
+
|
|
49
|
+
Scheduler userScheduler;
|
|
50
|
+
painlessMesh mesh;
|
|
51
|
+
WiFiClient espClient;
|
|
52
|
+
PubSubClient mqttClient(espClient);
|
|
53
|
+
EnhancedMqttBridge* bridge = nullptr;
|
|
54
|
+
|
|
55
|
+
// Task for reconnecting to MQTT
|
|
56
|
+
Task taskReconnectMQTT(5000, TASK_FOREVER, &reconnectMQTT);
|
|
57
|
+
|
|
58
|
+
void setup() {
|
|
59
|
+
Serial.begin(115200);
|
|
60
|
+
Serial.println("\n\n=== Enhanced MQTT Bridge for painlessMesh v1.7.7 ===");
|
|
61
|
+
|
|
62
|
+
// Initialize mesh
|
|
63
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
64
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
65
|
+
|
|
66
|
+
// Configure mesh callbacks
|
|
67
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
68
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
69
|
+
mesh.onDroppedConnection(&droppedConnectionCallback);
|
|
70
|
+
|
|
71
|
+
// Connect to WiFi for MQTT
|
|
72
|
+
WiFi.mode(WIFI_AP_STA);
|
|
73
|
+
WiFi.begin(STATION_SSID, STATION_PASSWORD);
|
|
74
|
+
|
|
75
|
+
Serial.print("Connecting to WiFi");
|
|
76
|
+
while (WiFi.status() != WL_CONNECTED) {
|
|
77
|
+
delay(500);
|
|
78
|
+
Serial.print(".");
|
|
79
|
+
}
|
|
80
|
+
Serial.println(" Connected!");
|
|
81
|
+
Serial.printf("IP Address: %s\n", WiFi.localIP().toString().c_str());
|
|
82
|
+
|
|
83
|
+
// Configure MQTT
|
|
84
|
+
mqttClient.setServer(MQTT_BROKER, MQTT_PORT);
|
|
85
|
+
mqttClient.setCallback(mqttCallback);
|
|
86
|
+
mqttClient.setBufferSize(2048); // Increase buffer for large messages
|
|
87
|
+
|
|
88
|
+
// Connect to MQTT
|
|
89
|
+
connectMQTT();
|
|
90
|
+
|
|
91
|
+
// Create and initialize enhanced bridge
|
|
92
|
+
bridge = new EnhancedMqttBridge(mesh, mqttClient);
|
|
93
|
+
bridge->setTopicPrefix("mesh/");
|
|
94
|
+
bridge->setDeviceId("GATEWAY-" + String(mesh.getNodeId(), HEX));
|
|
95
|
+
bridge->enableAggregation(true);
|
|
96
|
+
bridge->setAggregationInterval(60000); // 60 seconds
|
|
97
|
+
bridge->begin();
|
|
98
|
+
|
|
99
|
+
// Add MQTT reconnect task
|
|
100
|
+
userScheduler.addTask(taskReconnectMQTT);
|
|
101
|
+
taskReconnectMQTT.enable();
|
|
102
|
+
|
|
103
|
+
Serial.printf("Gateway Node ID: %u\n", mesh.getNodeId());
|
|
104
|
+
Serial.println("Enhanced MQTT Bridge ready!");
|
|
105
|
+
Serial.println("\nAvailable MQTT commands:");
|
|
106
|
+
Serial.println(" mesh/command/request_metrics {\"node_id\": 0}");
|
|
107
|
+
Serial.println(" mesh/command/request_health {\"node_id\": 12345}");
|
|
108
|
+
Serial.println(" mesh/command/get_aggregated {}");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
void loop() {
|
|
112
|
+
mesh.update();
|
|
113
|
+
|
|
114
|
+
// Handle MQTT
|
|
115
|
+
if (mqttClient.connected()) {
|
|
116
|
+
mqttClient.loop();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Update bridge (handles aggregation)
|
|
120
|
+
if (bridge) {
|
|
121
|
+
bridge->update();
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* MQTT callback - receives commands from MQTT
|
|
127
|
+
*/
|
|
128
|
+
void mqttCallback(char* topic, byte* payload, unsigned int length) {
|
|
129
|
+
// Convert to String
|
|
130
|
+
String topicStr = String(topic);
|
|
131
|
+
String payloadStr = "";
|
|
132
|
+
for (unsigned int i = 0; i < length; i++) {
|
|
133
|
+
payloadStr += (char)payload[i];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Serial.printf("\n[MQTT] Message on topic: %s\n", topic);
|
|
137
|
+
Serial.printf("Payload: %s\n", payloadStr.c_str());
|
|
138
|
+
|
|
139
|
+
// Forward to bridge for handling
|
|
140
|
+
if (bridge) {
|
|
141
|
+
bridge->handleMQTTMessage(topicStr, payloadStr);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Connect to MQTT broker
|
|
147
|
+
*/
|
|
148
|
+
void connectMQTT() {
|
|
149
|
+
Serial.print("Connecting to MQTT broker...");
|
|
150
|
+
|
|
151
|
+
String clientId = "painlessMesh-" + String(mesh.getNodeId());
|
|
152
|
+
|
|
153
|
+
bool connected = false;
|
|
154
|
+
if (strlen(MQTT_USER) > 0) {
|
|
155
|
+
connected = mqttClient.connect(clientId.c_str(), MQTT_USER, MQTT_PASSWORD);
|
|
156
|
+
} else {
|
|
157
|
+
connected = mqttClient.connect(clientId.c_str());
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
if (connected) {
|
|
161
|
+
Serial.println(" Connected!");
|
|
162
|
+
|
|
163
|
+
// Subscribe to command topics
|
|
164
|
+
mqttClient.subscribe("mesh/command/request_metrics");
|
|
165
|
+
mqttClient.subscribe("mesh/command/request_health");
|
|
166
|
+
mqttClient.subscribe("mesh/command/get_aggregated");
|
|
167
|
+
|
|
168
|
+
Serial.println("Subscribed to command topics");
|
|
169
|
+
|
|
170
|
+
// Publish connection announcement
|
|
171
|
+
String topic = "mesh/gateway/status";
|
|
172
|
+
String payload = "{\"status\":\"connected\",\"node_id\":" + String(mesh.getNodeId()) + "}";
|
|
173
|
+
mqttClient.publish(topic.c_str(), payload.c_str());
|
|
174
|
+
} else {
|
|
175
|
+
Serial.printf(" Failed! (rc=%d)\n", mqttClient.state());
|
|
176
|
+
Serial.println("Will retry in 5 seconds...");
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Reconnect to MQTT if disconnected
|
|
182
|
+
*/
|
|
183
|
+
void reconnectMQTT() {
|
|
184
|
+
if (!mqttClient.connected() && WiFi.status() == WL_CONNECTED) {
|
|
185
|
+
Serial.println("\nMQTT disconnected, attempting to reconnect...");
|
|
186
|
+
connectMQTT();
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Mesh callbacks
|
|
191
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
192
|
+
Serial.printf("\n[Mesh] New connection: %u\n", nodeId);
|
|
193
|
+
Serial.printf("Total nodes in mesh: %d\n", mesh.getNodeList().size() + 1);
|
|
194
|
+
|
|
195
|
+
// Publish to MQTT
|
|
196
|
+
if (mqttClient.connected()) {
|
|
197
|
+
String topic = "mesh/events/connection";
|
|
198
|
+
String payload = "{\"event\":\"new_connection\",\"node_id\":" + String(nodeId) +
|
|
199
|
+
",\"total_nodes\":" + String(mesh.getNodeList().size() + 1) + "}";
|
|
200
|
+
mqttClient.publish(topic.c_str(), payload.c_str());
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
void changedConnectionCallback() {
|
|
205
|
+
Serial.println("\n[Mesh] Topology changed");
|
|
206
|
+
|
|
207
|
+
// Publish to MQTT
|
|
208
|
+
if (mqttClient.connected()) {
|
|
209
|
+
auto nodes = mesh.getNodeList();
|
|
210
|
+
String topic = "mesh/events/topology_change";
|
|
211
|
+
String payload = "{\"event\":\"topology_changed\",\"node_count\":" +
|
|
212
|
+
String(nodes.size() + 1) + "}";
|
|
213
|
+
mqttClient.publish(topic.c_str(), payload.c_str());
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
void droppedConnectionCallback(uint32_t nodeId) {
|
|
218
|
+
Serial.printf("\n[Mesh] Connection dropped: %u\n", nodeId);
|
|
219
|
+
|
|
220
|
+
// Publish to MQTT
|
|
221
|
+
if (mqttClient.connected()) {
|
|
222
|
+
String topic = "mesh/events/disconnection";
|
|
223
|
+
String payload = "{\"event\":\"connection_dropped\",\"node_id\":" + String(nodeId) + "}";
|
|
224
|
+
mqttClient.publish(topic.c_str(), payload.c_str());
|
|
225
|
+
}
|
|
226
|
+
}
|
|
@@ -60,7 +60,7 @@ class CommandPackage : public painlessmesh::plugin::SinglePackage {
|
|
|
60
60
|
TSTRING parameters = ""; // Command parameters as JSON string
|
|
61
61
|
uint32_t commandId = 0; // Unique command identifier for tracking
|
|
62
62
|
|
|
63
|
-
CommandPackage() : SinglePackage(
|
|
63
|
+
CommandPackage() : SinglePackage(400) {} // Type ID 201 for Alteriom commands
|
|
64
64
|
|
|
65
65
|
CommandPackage(JsonObject jsonObj) : SinglePackage(jsonObj) {
|
|
66
66
|
command = jsonObj["cmd"];
|
|
@@ -60,7 +60,7 @@ class CommandPackage : public painlessmesh::plugin::SinglePackage {
|
|
|
60
60
|
TSTRING parameters = ""; // Command parameters as JSON string
|
|
61
61
|
uint32_t commandId = 0; // Unique command identifier for tracking
|
|
62
62
|
|
|
63
|
-
CommandPackage() : SinglePackage(
|
|
63
|
+
CommandPackage() : SinglePackage(400) {} // Type ID 201 for Alteriom commands
|
|
64
64
|
|
|
65
65
|
CommandPackage(JsonObject jsonObj) : SinglePackage(jsonObj) {
|
|
66
66
|
command = jsonObj["cmd"];
|
|
@@ -130,9 +130,13 @@ unsigned long lastTopologyUpdate = 0;
|
|
|
130
130
|
* Format: ALT-XXXXXXXXXXXX (uppercase hex)
|
|
131
131
|
*/
|
|
132
132
|
String getDeviceId() {
|
|
133
|
+
#ifdef ESP32
|
|
133
134
|
uint64_t chipid = ESP.getEfuseMac(); // ESP32 unique ID
|
|
135
|
+
#else
|
|
136
|
+
uint32_t chipid = ESP.getChipId(); // ESP8266 chip ID
|
|
137
|
+
#endif
|
|
134
138
|
char deviceId[17];
|
|
135
|
-
snprintf(deviceId, sizeof(deviceId), "ALT-%012llX", chipid);
|
|
139
|
+
snprintf(deviceId, sizeof(deviceId), "ALT-%012llX", (uint64_t)chipid);
|
|
136
140
|
return String(deviceId);
|
|
137
141
|
}
|
|
138
142
|
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name=AlteriomPainlessMesh
|
|
2
|
-
version=1.7.
|
|
2
|
+
version=1.7.7
|
|
3
3
|
author=Coopdis,Scotty Franzyshen,Edwin van Leeuwen,Germán Martín,Maximilian Schwarz,Doanh Doanh,Alteriom
|
|
4
4
|
maintainer=Alteriom
|
|
5
5
|
sentence=A painless way to setup a mesh with ESP8266 and ESP32 devices with Alteriom extensions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alteriom/painlessmesh",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.7",
|
|
4
4
|
"description": "painlessMesh is a user-friendly library for creating mesh networks with ESP8266 and ESP32 devices. This Alteriom fork includes additional packages for sensor data (SensorPackage), device commands (CommandPackage), and status monitoring (StatusPackage). It handles routing and network management automatically, so you can focus on your application. The library uses JSON-based messaging and syncs time across all nodes, making it ideal for coordinated behaviour like synchronized light displays or sensor networks reporting to a central node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arduino",
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"url": "https://github.com/Alteriom/painlessMesh/issues"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@alteriom/mqtt-schema": "^0.
|
|
42
|
+
"@alteriom/mqtt-schema": "^0.7.2",
|
|
43
43
|
"@eslint/js": "^9.0.0",
|
|
44
44
|
"ajv": "^8.17.1",
|
|
45
45
|
"ajv-formats": "^3.0.1",
|