@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,224 @@
|
|
|
1
|
+
#ifndef ALTERIOM_SENSOR_PACKAGE_HPP
|
|
2
|
+
#define ALTERIOM_SENSOR_PACKAGE_HPP
|
|
3
|
+
|
|
4
|
+
#include "painlessmesh/plugin.hpp"
|
|
5
|
+
|
|
6
|
+
namespace alteriom {
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @brief Sensor data package for broadcasting environmental measurements
|
|
10
|
+
*
|
|
11
|
+
* This package is designed for Alteriom's IoT sensor network requirements,
|
|
12
|
+
* allowing nodes to share environmental data across the mesh.
|
|
13
|
+
*/
|
|
14
|
+
class SensorPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
15
|
+
public:
|
|
16
|
+
double temperature = 0.0; // Temperature in Celsius
|
|
17
|
+
double humidity = 0.0; // Relative humidity percentage
|
|
18
|
+
double pressure = 0.0; // Atmospheric pressure in hPa
|
|
19
|
+
uint32_t sensorId = 0; // Unique sensor identifier
|
|
20
|
+
uint32_t timestamp = 0; // Unix timestamp of measurement
|
|
21
|
+
uint8_t batteryLevel = 0; // Battery level percentage
|
|
22
|
+
|
|
23
|
+
SensorPackage()
|
|
24
|
+
: BroadcastPackage(200) {} // Type ID 200 for Alteriom sensors
|
|
25
|
+
|
|
26
|
+
SensorPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
27
|
+
temperature = jsonObj["temp"];
|
|
28
|
+
humidity = jsonObj["hum"];
|
|
29
|
+
pressure = jsonObj["press"];
|
|
30
|
+
sensorId = jsonObj["sid"];
|
|
31
|
+
timestamp = jsonObj["ts"];
|
|
32
|
+
batteryLevel = jsonObj["bat"];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
36
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
37
|
+
jsonObj["temp"] = temperature;
|
|
38
|
+
jsonObj["hum"] = humidity;
|
|
39
|
+
jsonObj["press"] = pressure;
|
|
40
|
+
jsonObj["sid"] = sensorId;
|
|
41
|
+
jsonObj["ts"] = timestamp;
|
|
42
|
+
jsonObj["bat"] = batteryLevel;
|
|
43
|
+
return jsonObj;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
47
|
+
size_t jsonObjectSize() const { return JSON_OBJECT_SIZE(noJsonFields + 6); }
|
|
48
|
+
#endif
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @brief Command package for controlling Alteriom devices
|
|
53
|
+
*
|
|
54
|
+
* Single-destination package for sending specific commands to individual nodes.
|
|
55
|
+
*/
|
|
56
|
+
class CommandPackage : public painlessmesh::plugin::SinglePackage {
|
|
57
|
+
public:
|
|
58
|
+
uint8_t command = 0; // Command type
|
|
59
|
+
uint32_t targetDevice = 0; // Target device ID
|
|
60
|
+
TSTRING parameters = ""; // Command parameters as JSON string
|
|
61
|
+
uint32_t commandId = 0; // Unique command identifier for tracking
|
|
62
|
+
|
|
63
|
+
CommandPackage() : SinglePackage(201) {} // Type ID 201 for Alteriom commands
|
|
64
|
+
|
|
65
|
+
CommandPackage(JsonObject jsonObj) : SinglePackage(jsonObj) {
|
|
66
|
+
command = jsonObj["cmd"];
|
|
67
|
+
targetDevice = jsonObj["target"];
|
|
68
|
+
parameters = jsonObj["params"].as<TSTRING>();
|
|
69
|
+
commandId = jsonObj["cid"];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
73
|
+
jsonObj = SinglePackage::addTo(std::move(jsonObj));
|
|
74
|
+
jsonObj["cmd"] = command;
|
|
75
|
+
jsonObj["target"] = targetDevice;
|
|
76
|
+
jsonObj["params"] = parameters;
|
|
77
|
+
jsonObj["cid"] = commandId;
|
|
78
|
+
return jsonObj;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
82
|
+
size_t jsonObjectSize() const {
|
|
83
|
+
return JSON_OBJECT_SIZE(noJsonFields + 4) + parameters.length();
|
|
84
|
+
}
|
|
85
|
+
#endif
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @brief Status report package for device health monitoring
|
|
90
|
+
*/
|
|
91
|
+
class StatusPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
92
|
+
public:
|
|
93
|
+
uint8_t deviceStatus = 0; // Device status flags
|
|
94
|
+
uint32_t uptime = 0; // Device uptime in seconds
|
|
95
|
+
uint16_t freeMemory = 0; // Free memory in KB
|
|
96
|
+
uint8_t wifiStrength = 0; // WiFi signal strength
|
|
97
|
+
TSTRING firmwareVersion = ""; // Current firmware version
|
|
98
|
+
|
|
99
|
+
StatusPackage() : BroadcastPackage(202) {} // Type ID 202 for Alteriom status
|
|
100
|
+
|
|
101
|
+
StatusPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
102
|
+
deviceStatus = jsonObj["status"];
|
|
103
|
+
uptime = jsonObj["uptime"];
|
|
104
|
+
freeMemory = jsonObj["mem"];
|
|
105
|
+
wifiStrength = jsonObj["wifi"];
|
|
106
|
+
firmwareVersion = jsonObj["fw"].as<TSTRING>();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
110
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
111
|
+
jsonObj["status"] = deviceStatus;
|
|
112
|
+
jsonObj["uptime"] = uptime;
|
|
113
|
+
jsonObj["mem"] = freeMemory;
|
|
114
|
+
jsonObj["wifi"] = wifiStrength;
|
|
115
|
+
jsonObj["fw"] = firmwareVersion;
|
|
116
|
+
return jsonObj;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
120
|
+
size_t jsonObjectSize() const {
|
|
121
|
+
return JSON_OBJECT_SIZE(noJsonFields + 5) + firmwareVersion.length();
|
|
122
|
+
}
|
|
123
|
+
#endif
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* @brief Enhanced status package with comprehensive health metrics (Phase 1)
|
|
128
|
+
*
|
|
129
|
+
* This is an extended version of StatusPackage that includes additional
|
|
130
|
+
* mesh statistics, performance metrics, and alerting capabilities.
|
|
131
|
+
* Type ID 203 is used to distinguish from the basic StatusPackage (202).
|
|
132
|
+
*/
|
|
133
|
+
class EnhancedStatusPackage : public painlessmesh::plugin::BroadcastPackage {
|
|
134
|
+
public:
|
|
135
|
+
// Device Health (from original StatusPackage)
|
|
136
|
+
uint8_t deviceStatus = 0; // Device status flags
|
|
137
|
+
uint32_t uptime = 0; // Device uptime in seconds
|
|
138
|
+
uint16_t freeMemory = 0; // Free memory in KB
|
|
139
|
+
uint8_t wifiStrength = 0; // WiFi signal strength
|
|
140
|
+
TSTRING firmwareVersion = ""; // Current firmware version
|
|
141
|
+
TSTRING firmwareMD5 = ""; // Firmware hash for OTA verification
|
|
142
|
+
|
|
143
|
+
// Mesh Statistics
|
|
144
|
+
uint16_t nodeCount = 0; // Number of known nodes in mesh
|
|
145
|
+
uint8_t connectionCount = 0; // Number of direct connections
|
|
146
|
+
uint32_t messagesReceived = 0; // Total messages received
|
|
147
|
+
uint32_t messagesSent = 0; // Total messages sent
|
|
148
|
+
uint32_t messagesDropped = 0; // Total messages dropped/failed
|
|
149
|
+
|
|
150
|
+
// Performance Metrics
|
|
151
|
+
uint16_t avgLatency = 0; // Average message latency in ms
|
|
152
|
+
uint8_t packetLossRate = 0; // Packet loss rate percentage (0-100)
|
|
153
|
+
uint16_t throughput = 0; // Network throughput in bytes/sec
|
|
154
|
+
|
|
155
|
+
// Warnings/Alerts
|
|
156
|
+
uint8_t alertFlags = 0; // Bit flags for various alert conditions
|
|
157
|
+
TSTRING lastError = ""; // Last error message for diagnostics
|
|
158
|
+
|
|
159
|
+
EnhancedStatusPackage()
|
|
160
|
+
: BroadcastPackage(203) {} // Type ID 203 for enhanced status
|
|
161
|
+
|
|
162
|
+
EnhancedStatusPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
|
|
163
|
+
deviceStatus = jsonObj["status"];
|
|
164
|
+
uptime = jsonObj["uptime"];
|
|
165
|
+
freeMemory = jsonObj["mem"];
|
|
166
|
+
wifiStrength = jsonObj["wifi"];
|
|
167
|
+
firmwareVersion = jsonObj["fw"].as<TSTRING>();
|
|
168
|
+
firmwareMD5 = jsonObj["fwMD5"].as<TSTRING>();
|
|
169
|
+
|
|
170
|
+
nodeCount = jsonObj["nodes"];
|
|
171
|
+
connectionCount = jsonObj["conns"];
|
|
172
|
+
messagesReceived = jsonObj["msgRx"];
|
|
173
|
+
messagesSent = jsonObj["msgTx"];
|
|
174
|
+
messagesDropped = jsonObj["msgDrop"];
|
|
175
|
+
|
|
176
|
+
avgLatency = jsonObj["latency"];
|
|
177
|
+
packetLossRate = jsonObj["loss"];
|
|
178
|
+
throughput = jsonObj["throughput"];
|
|
179
|
+
|
|
180
|
+
alertFlags = jsonObj["alerts"];
|
|
181
|
+
lastError = jsonObj["lastErr"].as<TSTRING>();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
JsonObject addTo(JsonObject&& jsonObj) const {
|
|
185
|
+
jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
|
|
186
|
+
|
|
187
|
+
// Device Health
|
|
188
|
+
jsonObj["status"] = deviceStatus;
|
|
189
|
+
jsonObj["uptime"] = uptime;
|
|
190
|
+
jsonObj["mem"] = freeMemory;
|
|
191
|
+
jsonObj["wifi"] = wifiStrength;
|
|
192
|
+
jsonObj["fw"] = firmwareVersion;
|
|
193
|
+
jsonObj["fwMD5"] = firmwareMD5;
|
|
194
|
+
|
|
195
|
+
// Mesh Statistics
|
|
196
|
+
jsonObj["nodes"] = nodeCount;
|
|
197
|
+
jsonObj["conns"] = connectionCount;
|
|
198
|
+
jsonObj["msgRx"] = messagesReceived;
|
|
199
|
+
jsonObj["msgTx"] = messagesSent;
|
|
200
|
+
jsonObj["msgDrop"] = messagesDropped;
|
|
201
|
+
|
|
202
|
+
// Performance Metrics
|
|
203
|
+
jsonObj["latency"] = avgLatency;
|
|
204
|
+
jsonObj["loss"] = packetLossRate;
|
|
205
|
+
jsonObj["throughput"] = throughput;
|
|
206
|
+
|
|
207
|
+
// Alerts
|
|
208
|
+
jsonObj["alerts"] = alertFlags;
|
|
209
|
+
jsonObj["lastErr"] = lastError;
|
|
210
|
+
|
|
211
|
+
return jsonObj;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#if ARDUINOJSON_VERSION_MAJOR < 7
|
|
215
|
+
size_t jsonObjectSize() const {
|
|
216
|
+
return JSON_OBJECT_SIZE(noJsonFields + 18) + firmwareVersion.length() +
|
|
217
|
+
firmwareMD5.length() + lastError.length();
|
|
218
|
+
}
|
|
219
|
+
#endif
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
} // namespace alteriom
|
|
223
|
+
|
|
224
|
+
#endif // ALTERIOM_SENSOR_PACKAGE_HPP
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// Phase 2 Features Example
|
|
3
|
+
//
|
|
4
|
+
// This example demonstrates the two major Phase 2 features:
|
|
5
|
+
// 1. Broadcast OTA (Option 1A) - True mesh-wide firmware distribution
|
|
6
|
+
// 2. MQTT Status Bridge (Option 2E) - Professional monitoring
|
|
7
|
+
//
|
|
8
|
+
// Phase 2 builds on Phase 1's foundation:
|
|
9
|
+
// - Phase 1: Compressed OTA + Enhanced Status
|
|
10
|
+
// - Phase 2: Broadcast OTA + MQTT Status Bridge
|
|
11
|
+
//
|
|
12
|
+
// Broadcast OTA Benefits:
|
|
13
|
+
// - Dramatically reduces network traffic (1 broadcast vs N unicasts)
|
|
14
|
+
// - Faster distribution to large meshes (parallel vs sequential)
|
|
15
|
+
// - Scales to 50+ nodes efficiently
|
|
16
|
+
// - Backward compatible with Phase 1
|
|
17
|
+
//
|
|
18
|
+
// MQTT Status Bridge Benefits:
|
|
19
|
+
// - Professional monitoring tools (Grafana, InfluxDB, Prometheus)
|
|
20
|
+
// - Cloud integration via MQTT
|
|
21
|
+
// - Real-time mesh visibility
|
|
22
|
+
// - Automated alerting
|
|
23
|
+
//************************************************************
|
|
24
|
+
|
|
25
|
+
#include "painlessMesh.h"
|
|
26
|
+
|
|
27
|
+
// Mesh configuration
|
|
28
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
29
|
+
#define MESH_PASSWORD "meshPassword123"
|
|
30
|
+
#define MESH_PORT 5555
|
|
31
|
+
|
|
32
|
+
// OTA configuration
|
|
33
|
+
#define OTA_PART_SIZE 1024 // Chunk size for OTA transfers
|
|
34
|
+
|
|
35
|
+
Scheduler userScheduler;
|
|
36
|
+
painlessMesh mesh;
|
|
37
|
+
|
|
38
|
+
// Prototypes
|
|
39
|
+
void sendBroadcastOTA();
|
|
40
|
+
void receivedCallback(uint32_t from, String& msg);
|
|
41
|
+
void newConnectionCallback(uint32_t nodeId);
|
|
42
|
+
void changedConnectionCallback();
|
|
43
|
+
|
|
44
|
+
void setup() {
|
|
45
|
+
Serial.begin(115200);
|
|
46
|
+
Serial.println("\n\n=== Phase 2 Features Demo ===\n");
|
|
47
|
+
|
|
48
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
49
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
50
|
+
mesh.onReceive(&receivedCallback);
|
|
51
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
52
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
53
|
+
|
|
54
|
+
Serial.println("Mesh initialized");
|
|
55
|
+
Serial.println("Phase 2 features:");
|
|
56
|
+
Serial.println(" 1. Broadcast OTA - scales to 50+ nodes");
|
|
57
|
+
Serial.println(" 2. MQTT Status Bridge - professional monitoring");
|
|
58
|
+
Serial.println();
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
void loop() {
|
|
62
|
+
mesh.update();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Phase 2 Feature 1: Broadcast OTA
|
|
67
|
+
*
|
|
68
|
+
* True mesh-wide broadcast distribution where firmware chunks
|
|
69
|
+
* are broadcast to all nodes simultaneously, dramatically reducing
|
|
70
|
+
* network traffic and improving update speed.
|
|
71
|
+
*
|
|
72
|
+
* Key differences from Phase 1:
|
|
73
|
+
* - Phase 1: Each node requests chunks individually (N unicasts)
|
|
74
|
+
* - Phase 2: Root broadcasts chunks once to all nodes (1 broadcast)
|
|
75
|
+
*
|
|
76
|
+
* Memory impact: +2-5KB per node for chunk tracking
|
|
77
|
+
*/
|
|
78
|
+
void sendBroadcastOTA() {
|
|
79
|
+
#ifdef PAINLESSMESH_ENABLE_OTA
|
|
80
|
+
|
|
81
|
+
Serial.println("\n=== Phase 2: Broadcast OTA ===");
|
|
82
|
+
|
|
83
|
+
// Example firmware info
|
|
84
|
+
String firmwareMD5 = "phase2_broadcast_example_md5";
|
|
85
|
+
size_t numParts = 150; // Number of firmware chunks
|
|
86
|
+
|
|
87
|
+
// Phase 2: Enable both compression (Phase 1) AND broadcast (Phase 2)
|
|
88
|
+
// This is the most efficient combination for large meshes
|
|
89
|
+
auto otaTask = mesh.offerOTA(
|
|
90
|
+
"sensor", // Role this firmware is for
|
|
91
|
+
"ESP32", // Hardware type (ESP32 or ESP8266)
|
|
92
|
+
firmwareMD5, // MD5 hash of firmware
|
|
93
|
+
numParts, // Number of data chunks
|
|
94
|
+
false, // Not forced (only update if different MD5)
|
|
95
|
+
true, // *** BROADCAST MODE (Phase 2 feature) ***
|
|
96
|
+
true // Compressed (Phase 1 feature for additional savings)
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
Serial.println("Broadcast OTA announced!");
|
|
100
|
+
Serial.println();
|
|
101
|
+
Serial.println("Phase 2 Broadcast Mode:");
|
|
102
|
+
Serial.println(" - Root node broadcasts each chunk ONCE");
|
|
103
|
+
Serial.println(" - All nodes receive chunks simultaneously");
|
|
104
|
+
Serial.println(" - Dramatically reduced network traffic");
|
|
105
|
+
Serial.println(" - Scales efficiently to 50+ nodes");
|
|
106
|
+
Serial.println();
|
|
107
|
+
Serial.println("Combined with Phase 1 Compression:");
|
|
108
|
+
Serial.println(" - 40-60% bandwidth reduction per chunk");
|
|
109
|
+
Serial.println(" - Faster distribution across large meshes");
|
|
110
|
+
Serial.println(" - Lower energy consumption");
|
|
111
|
+
Serial.println();
|
|
112
|
+
Serial.println("Expected performance for 50-node mesh:");
|
|
113
|
+
Serial.println(" - Without broadcast: 50 unicast transmissions per chunk");
|
|
114
|
+
Serial.println(" - With broadcast: 1 broadcast per chunk");
|
|
115
|
+
Serial.println(" - Network load reduction: ~98%");
|
|
116
|
+
Serial.println();
|
|
117
|
+
Serial.println("Architecture:");
|
|
118
|
+
Serial.println(" Root Node:");
|
|
119
|
+
Serial.println(" ├─> Broadcast: Announce(firmware_info)");
|
|
120
|
+
Serial.println(" ├─> Broadcast: Data(chunk_0)");
|
|
121
|
+
Serial.println(" ├─> Broadcast: Data(chunk_1)");
|
|
122
|
+
Serial.println(" └─> ... continues for all chunks");
|
|
123
|
+
Serial.println(" ");
|
|
124
|
+
Serial.println(" All Nodes:");
|
|
125
|
+
Serial.println(" ├─> Listen for broadcast announcements");
|
|
126
|
+
Serial.println(" ├─> Receive and cache chunks as they arrive");
|
|
127
|
+
Serial.println(" ├─> Assemble firmware from cached chunks");
|
|
128
|
+
Serial.println(" └─> Reboot into new firmware when complete");
|
|
129
|
+
|
|
130
|
+
#else
|
|
131
|
+
Serial.println("OTA not enabled. Define PAINLESSMESH_ENABLE_OTA");
|
|
132
|
+
#endif
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Callback when messages are received
|
|
137
|
+
*/
|
|
138
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
139
|
+
Serial.printf("Received from %u: %s\n", from, msg.c_str());
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
143
|
+
Serial.printf("New connection: %u\n", nodeId);
|
|
144
|
+
Serial.printf("Total nodes in mesh: %d\n", mesh.getNodeList().size() + 1);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
void changedConnectionCallback() {
|
|
148
|
+
Serial.println("Connections changed");
|
|
149
|
+
Serial.printf("Total nodes: %d\n", mesh.getNodeList().size() + 1);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Phase 2 Benefits Summary:
|
|
154
|
+
*
|
|
155
|
+
* 1. Broadcast OTA (Option 1A):
|
|
156
|
+
* - Scales to 50-100 node meshes
|
|
157
|
+
* - ~98% reduction in network traffic vs unicast
|
|
158
|
+
* - Parallel distribution to all nodes
|
|
159
|
+
* - Maintains backward compatibility
|
|
160
|
+
* - Memory overhead: +2-5KB per node
|
|
161
|
+
*
|
|
162
|
+
* 2. MQTT Status Bridge (Option 2E):
|
|
163
|
+
* - Professional monitoring tools integration
|
|
164
|
+
* - Real-time mesh visibility via MQTT topics
|
|
165
|
+
* - Grafana/InfluxDB dashboards
|
|
166
|
+
* - Prometheus metrics collection
|
|
167
|
+
* - Home Assistant automation
|
|
168
|
+
* - Cloud-ready architecture
|
|
169
|
+
* - Configurable publish intervals
|
|
170
|
+
* - Multiple topic streams (nodes, topology, metrics, alerts)
|
|
171
|
+
*
|
|
172
|
+
* When to use Phase 2:
|
|
173
|
+
* - Meshes with 10+ nodes (broadcast efficiency kicks in)
|
|
174
|
+
* - Production deployments requiring monitoring
|
|
175
|
+
* - Systems needing cloud integration
|
|
176
|
+
* - Enterprise environments with existing monitoring tools
|
|
177
|
+
* - Large-scale deployments (50+ nodes)
|
|
178
|
+
*
|
|
179
|
+
* Migration from Phase 1:
|
|
180
|
+
* - Broadcast OTA: Just set broadcasted=true in offerOTA()
|
|
181
|
+
* - MQTT Bridge: Include mqtt_status_bridge.hpp and configure
|
|
182
|
+
* - Both features are fully backward compatible
|
|
183
|
+
* - Can be deployed incrementally
|
|
184
|
+
*
|
|
185
|
+
* Next: Phase 3 features (progressive rollout + telemetry streams)
|
|
186
|
+
*/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
16
|
+
esp32async/ESPAsyncTCP ; Only for ESP8266
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../ ; Load the local copy of painlessmesh. For your own example add painlessmesh to the lib_deps
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps} ; Inherit common dependencies
|
|
25
|
+
esp32async/AsyncTCP
|