@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,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
|