@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.
Files changed (129) hide show
  1. package/CHANGELOG.md +380 -143
  2. package/LICENSE +674 -674
  3. package/README.md +477 -434
  4. package/RELEASE_GUIDE.md +504 -418
  5. package/docs/DOCUMENTATION_MIGRATION_PLAN.md +175 -175
  6. package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +1062 -0
  7. package/docs/MESH_TOPOLOGY_GUIDE.md +992 -0
  8. package/docs/MESH_TOPOLOGY_PROGRESS.md +422 -0
  9. package/docs/MQTT_BRIDGE_COMMANDS.md +894 -0
  10. package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +324 -0
  11. package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +576 -0
  12. package/docs/MQTT_SCHEMA_COMPLIANCE.md +285 -0
  13. package/docs/MQTT_SCHEMA_PROPOSALS.md +446 -0
  14. package/docs/MQTT_SCHEMA_REVIEW.md +690 -0
  15. package/docs/OTA_COMMANDS_REFERENCE.md +554 -0
  16. package/docs/PHASE1_GUIDE.md +349 -0
  17. package/docs/PHASE2_GUIDE.md +543 -0
  18. package/docs/README.md +77 -70
  19. package/docs/SCHEMA_VALIDATION_CHECKLIST.md +222 -0
  20. package/docs/alteriom/overview.md +507 -507
  21. package/docs/api/core-api.md +606 -606
  22. package/docs/architecture/mesh-architecture.md +378 -378
  23. package/docs/architecture/plugin-system.md +516 -516
  24. package/docs/getting-started/first-mesh.md +409 -409
  25. package/docs/getting-started/installation.md +274 -274
  26. package/docs/getting-started/quickstart.md +157 -157
  27. package/docs/improvements/FEATURE_PROPOSALS.md +337 -0
  28. package/docs/improvements/PHASE1_IMPLEMENTATION.md +325 -0
  29. package/docs/improvements/PHASE2_IMPLEMENTATION.md +567 -0
  30. package/docs/improvements/README.md +86 -68
  31. package/docs/improvements/ota-and-status-enhancements.md +911 -0
  32. package/docs/improvements/ota-status-architecture-diagrams.md +658 -0
  33. package/docs/improvements/ota-status-quick-reference.md +284 -0
  34. package/docs/platformio-publishing.md +255 -0
  35. package/docs/platformio-setup-summary.md +121 -0
  36. package/docs/troubleshooting/common-issues.md +520 -520
  37. package/docs/troubleshooting/faq.md +472 -472
  38. package/docs/tutorials/basic-examples.md +717 -717
  39. package/docs/wiki/API-Reference.md +245 -245
  40. package/docs/wiki/Complete-Documentation.md +122 -122
  41. package/examples/alteriom/README.md +139 -81
  42. package/examples/alteriom/alteriom.ino +186 -185
  43. package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
  44. package/examples/alteriom/platformio.ini +24 -24
  45. package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
  46. package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
  47. package/examples/alteriomImproved/platformio.ini +25 -0
  48. package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
  49. package/examples/alteriomPhase1/phase1_features.ino +242 -0
  50. package/examples/alteriomPhase1/platformio.ini +25 -0
  51. package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
  52. package/examples/alteriomPhase2/phase2_features.ino +186 -0
  53. package/examples/alteriomPhase2/platformio.ini +25 -0
  54. package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
  55. package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
  56. package/examples/alteriomSensorNode/platformio.ini +25 -0
  57. package/examples/basic/basic.ino +66 -66
  58. package/examples/basic/platformio.ini +25 -25
  59. package/examples/bridge/bridge.ino +51 -51
  60. package/examples/bridge/mesh_event_publisher.hpp +253 -0
  61. package/examples/bridge/mesh_topology_reporter.hpp +303 -0
  62. package/examples/bridge/mqtt_command_bridge.hpp +459 -0
  63. package/examples/bridge/mqtt_status_bridge.hpp +519 -0
  64. package/examples/bridge/platformio.ini +25 -25
  65. package/examples/echoNode/echoNode.ino +33 -33
  66. package/examples/echoNode/platformio.ini +25 -25
  67. package/examples/logClient/logClient.ino +109 -109
  68. package/examples/logClient/platformio.ini +25 -25
  69. package/examples/logServer/logServer.ino +81 -81
  70. package/examples/logServer/platformio.ini +25 -25
  71. package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
  72. package/examples/meshCommandNode/meshCommandNode.ino +263 -0
  73. package/examples/meshCommandNode/platformio.ini +25 -0
  74. package/examples/mqttBridge/mqttBridge.ino +118 -118
  75. package/examples/mqttBridge/platformio.ini +26 -26
  76. package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
  77. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
  78. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
  79. package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
  80. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
  81. package/examples/mqttCommandBridge/platformio.ini +26 -0
  82. package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
  83. package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
  84. package/examples/mqttStatusBridge/platformio.ini +26 -0
  85. package/examples/mqttTopologyTest/README.md +467 -0
  86. package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
  87. package/examples/mqttTopologyTest/platformio.ini +26 -0
  88. package/examples/namedMesh/namedMesh.ino +97 -97
  89. package/examples/namedMesh/platformio.ini +25 -25
  90. package/examples/otaReceiver/otaReceiver.ino +79 -79
  91. package/examples/otaReceiver/platformio.ini +25 -25
  92. package/examples/otaSender/otaSender.ino +160 -151
  93. package/examples/otaSender/platformio.ini +25 -25
  94. package/examples/startHere/platformio.ini +25 -25
  95. package/examples/startHere/startHere.ino +159 -159
  96. package/examples/webServer/platformio.ini +27 -27
  97. package/examples/webServer/webServer.ino +89 -89
  98. package/keywords.txt +48 -48
  99. package/library.json +55 -34
  100. package/library.properties +10 -10
  101. package/package.json +86 -78
  102. package/src/AlteriomPainlessMesh.h +97 -97
  103. package/src/arduino/wifi.hpp +365 -365
  104. package/src/boost/asynctcp.hpp +279 -279
  105. package/src/painlessMesh.h +70 -70
  106. package/src/painlessMeshSTA.cpp +236 -236
  107. package/src/painlessMeshSTA.h +58 -58
  108. package/src/painlessTaskOptions.h +4 -4
  109. package/src/painlessmesh/base64.hpp +111 -111
  110. package/src/painlessmesh/buffer.hpp +229 -229
  111. package/src/painlessmesh/callback.hpp +91 -91
  112. package/src/painlessmesh/configuration.hpp +77 -77
  113. package/src/painlessmesh/connection.hpp +192 -192
  114. package/src/painlessmesh/layout.hpp +188 -188
  115. package/src/painlessmesh/logger.hpp +158 -158
  116. package/src/painlessmesh/memory.hpp +119 -119
  117. package/src/painlessmesh/mesh.hpp +761 -560
  118. package/src/painlessmesh/metrics.hpp +322 -322
  119. package/src/painlessmesh/ntp.hpp +263 -263
  120. package/src/painlessmesh/ota.hpp +582 -553
  121. package/src/painlessmesh/plugin.hpp +188 -188
  122. package/src/painlessmesh/protocol.hpp +813 -813
  123. package/src/painlessmesh/router.hpp +322 -322
  124. package/src/painlessmesh/tcp.hpp +71 -71
  125. package/src/painlessmesh/validation.hpp +238 -238
  126. package/src/plugin/performance.hpp +214 -214
  127. package/src/plugin/remote.hpp +64 -64
  128. package/src/scheduler.cpp +10 -10
  129. 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,242 @@
1
+ /**
2
+ * Phase 1 OTA Features Example - Compressed OTA & Enhanced Status
3
+ *
4
+ * This example demonstrates the Phase 1 enhancements to painlessMesh:
5
+ * - Option 1E: Compressed OTA Transfer for 40-60% bandwidth reduction
6
+ * - Option 2A: Enhanced StatusPackage with comprehensive metrics
7
+ *
8
+ * Features:
9
+ * - Compressed firmware updates reduce network bandwidth
10
+ * - Enhanced status reporting with mesh statistics and performance metrics
11
+ * - Backward compatible with existing nodes
12
+ */
13
+
14
+ #include "alteriom_sensor_package.hpp"
15
+ #include "painlessMesh.h"
16
+
17
+ #define MESH_PREFIX "AlteriomPhase1Mesh"
18
+ #define MESH_PASSWORD "phase1Features"
19
+ #define MESH_PORT 5555
20
+
21
+ #define STATUS_INTERVAL 30000 // Send enhanced status every 30 seconds
22
+
23
+ Scheduler userScheduler;
24
+ painlessMesh mesh;
25
+
26
+ // Task declarations
27
+ Task statusTask(STATUS_INTERVAL, TASK_FOREVER, &sendEnhancedStatus);
28
+
29
+ // Metrics tracking
30
+ unsigned long lastRebootTime = 0;
31
+ uint32_t totalMessagesReceived = 0;
32
+ uint32_t totalMessagesSent = 0;
33
+
34
+ void setup() {
35
+ Serial.begin(115200);
36
+
37
+ lastRebootTime = millis();
38
+
39
+ mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
40
+ mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
41
+
42
+ mesh.onReceive(&receivedCallback);
43
+ mesh.onNewConnection(&newConnectionCallback);
44
+ mesh.onChangedConnections(&changedConnectionCallback);
45
+
46
+ // Add the enhanced status reporting task
47
+ userScheduler.addTask(statusTask);
48
+ statusTask.enable();
49
+
50
+ Serial.println("Phase 1 Features Example Started");
51
+ Serial.println("- Compressed OTA enabled");
52
+ Serial.println("- Enhanced Status reporting active");
53
+ }
54
+
55
+ void loop() {
56
+ mesh.update();
57
+ }
58
+
59
+ /**
60
+ * Send Enhanced Status Package with comprehensive metrics
61
+ */
62
+ void sendEnhancedStatus() {
63
+ alteriom::EnhancedStatusPackage status;
64
+
65
+ // Device Health
66
+ status.deviceStatus = 0x01; // 0x01 = Online and healthy
67
+ status.uptime = (millis() - lastRebootTime) / 1000; // Uptime in seconds
68
+
69
+ #ifdef ESP32
70
+ status.freeMemory = ESP.getFreeHeap() / 1024; // Free heap in KB
71
+ status.firmwareVersion = "1.0.0-phase1";
72
+ status.wifiStrength = constrain(map(WiFi.RSSI(), -100, -50, 0, 100), 0, 100);
73
+ #elif defined(ESP8266)
74
+ status.freeMemory = ESP.getFreeHeap() / 1024;
75
+ status.firmwareVersion = "1.0.0-phase1";
76
+ status.wifiStrength = constrain(map(WiFi.RSSI(), -100, -50, 0, 100), 0, 100);
77
+ #else
78
+ status.freeMemory = 128; // Default for testing
79
+ status.firmwareVersion = "1.0.0-test";
80
+ status.wifiStrength = 75;
81
+ #endif
82
+
83
+ // For demonstration, use a placeholder MD5
84
+ status.firmwareMD5 = "abc123def456";
85
+
86
+ // Mesh Statistics
87
+ auto nodeList = mesh.getNodeList();
88
+ status.nodeCount = nodeList.size();
89
+ status.connectionCount = nodeList.size(); // Use node count as connection count
90
+ status.messagesReceived = totalMessagesReceived;
91
+ status.messagesSent = totalMessagesSent;
92
+ status.messagesDropped = 0; // Would need tracking in real implementation
93
+
94
+ // Performance Metrics
95
+ // In a real implementation, these would be calculated from actual metrics
96
+ status.avgLatency = 50; // Average message latency in ms
97
+ status.packetLossRate = 1; // 1% packet loss
98
+ status.throughput = 512; // Bytes per second
99
+
100
+ // Alerts - check for various conditions
101
+ status.alertFlags = 0;
102
+ if (status.freeMemory < 32) {
103
+ status.alertFlags |= 0x01; // Low memory alert
104
+ }
105
+ if (status.wifiStrength < 30) {
106
+ status.alertFlags |= 0x02; // Weak signal alert
107
+ }
108
+ if (status.connectionCount == 0 && status.nodeCount == 0) {
109
+ status.alertFlags |= 0x04; // Isolated node alert
110
+ }
111
+
112
+ status.lastError = (status.alertFlags == 0) ? "" : "See alert flags";
113
+
114
+ // Convert to JSON and send
115
+ String msg;
116
+ DynamicJsonDocument doc(status.jsonObjectSize());
117
+ JsonObject obj = doc.to<JsonObject>();
118
+ status.addTo(std::move(obj));
119
+ serializeJson(doc, msg);
120
+
121
+ mesh.sendBroadcast(msg);
122
+ totalMessagesSent++;
123
+
124
+ Serial.printf("Enhanced Status sent - Nodes: %d, Mem: %dKB, Uptime: %ds\n",
125
+ status.nodeCount, status.freeMemory, status.uptime);
126
+ }
127
+
128
+ /**
129
+ * Callback when messages are received
130
+ */
131
+ void receivedCallback(uint32_t from, String& msg) {
132
+ totalMessagesReceived++;
133
+
134
+ // Parse the message to identify the type
135
+ DynamicJsonDocument doc(2048);
136
+ DeserializationError error = deserializeJson(doc, msg);
137
+
138
+ if (error) {
139
+ Serial.printf("JSON parse error from %u: %s\n", from, error.c_str());
140
+ return;
141
+ }
142
+
143
+ JsonObject obj = doc.as<JsonObject>();
144
+ int msgType = obj["type"];
145
+
146
+ switch (msgType) {
147
+ case 203: { // Enhanced Status Package
148
+ alteriom::EnhancedStatusPackage status(obj);
149
+
150
+ Serial.printf("Enhanced Status from %u: v%s, Nodes: %d, Mem: %dKB, Msgs: %d/%d\n",
151
+ from,
152
+ status.firmwareVersion.c_str(),
153
+ status.nodeCount,
154
+ status.freeMemory,
155
+ status.messagesReceived,
156
+ status.messagesSent);
157
+
158
+ if (status.alertFlags != 0) {
159
+ Serial.printf(" ALERTS (0x%02X): %s\n", status.alertFlags, status.lastError.c_str());
160
+ }
161
+ break;
162
+ }
163
+
164
+ case 202: { // Basic Status Package (backward compatible)
165
+ alteriom::StatusPackage status(obj);
166
+ Serial.printf("Basic Status from %u: v%s, Mem: %dKB\n",
167
+ from, status.firmwareVersion.c_str(), status.freeMemory);
168
+ break;
169
+ }
170
+
171
+ default:
172
+ Serial.printf("Message type %d from %u (not a status package)\n", msgType, from);
173
+ break;
174
+ }
175
+ }
176
+
177
+ void newConnectionCallback(uint32_t nodeId) {
178
+ Serial.printf("New Connection: %u\n", nodeId);
179
+ Serial.printf("Total nodes in mesh: %d\n", mesh.getNodeList().size());
180
+ }
181
+
182
+ void changedConnectionCallback() {
183
+ Serial.printf("Connections changed. Nodes: %d\n", mesh.getNodeList().size());
184
+ }
185
+
186
+ /**
187
+ * Example: How to use Compressed OTA (sender side)
188
+ *
189
+ * This function shows how to enable compressed OTA transfers.
190
+ * In a real implementation, this would be called from an OTA sender node.
191
+ */
192
+ void setupCompressedOTA() {
193
+ #ifdef PAINLESSMESH_ENABLE_OTA
194
+
195
+ // Example firmware info
196
+ String firmwareMD5 = "abc123def456789"; // MD5 of firmware
197
+ size_t numParts = 100; // Number of firmware chunks
198
+
199
+ // Offer OTA update with compression enabled
200
+ // Parameters: role, hardware, md5, numParts, forced, broadcasted, compressed
201
+ auto otaTask = mesh.offerOTA(
202
+ "sensor", // Role this firmware is for
203
+ "ESP32", // Hardware type
204
+ firmwareMD5, // MD5 hash of firmware
205
+ numParts, // Number of data chunks
206
+ false, // Not forced (only update if different)
207
+ false, // Not using broadcast mode (yet - Phase 2)
208
+ true // COMPRESSED! 40-60% bandwidth savings
209
+ );
210
+
211
+ Serial.println("Compressed OTA announced!");
212
+ Serial.println("Expected bandwidth savings: 40-60%");
213
+ Serial.println("Nodes will receive and decompress firmware automatically");
214
+
215
+ #else
216
+ Serial.println("OTA not enabled. Define PAINLESSMESH_ENABLE_OTA");
217
+ #endif
218
+ }
219
+
220
+ /**
221
+ * Benefits of Phase 1 Features:
222
+ *
223
+ * 1. Compressed OTA (Option 1E):
224
+ * - 40-60% reduction in network bandwidth
225
+ * - Faster firmware distribution across mesh
226
+ * - Lower energy consumption
227
+ * - Backward compatible with uncompressed OTA
228
+ * - Works with all future OTA options (broadcast, progressive, etc.)
229
+ *
230
+ * 2. Enhanced Status Package (Option 2A):
231
+ * - Comprehensive device health monitoring
232
+ * - Mesh network statistics (nodes, connections, messages)
233
+ * - Performance metrics (latency, packet loss, throughput)
234
+ * - Alert system for proactive issue detection
235
+ * - Standardized format across all Alteriom nodes
236
+ * - Easy integration with monitoring dashboards
237
+ *
238
+ * Next Steps (Phase 2):
239
+ * - Broadcast OTA for even faster updates in large meshes
240
+ * - MQTT bridge for cloud monitoring integration
241
+ * - Professional monitoring tools (Grafana, InfluxDB)
242
+ */
@@ -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