@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
@@ -1,118 +1,118 @@
1
- //************************************************************
2
- // this is a simple example that uses the painlessMesh library to
3
- // connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
4
- // To send a message to a mesh node, you can publish it to "painlessMesh/to/12345678" where 12345678 equals the nodeId.
5
- // To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
6
- // When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
7
- // Every message from the mesh which is send to the gateway node will be published to "painlessMesh/from/12345678" where 12345678
8
- // is the nodeId from which the packet was send.
9
- //************************************************************
10
-
11
- #include <Arduino.h>
12
- #include <painlessMesh.h>
13
- #include <PubSubClient.h>
14
- #include <WiFiClient.h>
15
-
16
- #define MESH_PREFIX "whateverYouLike"
17
- #define MESH_PASSWORD "somethingSneaky"
18
- #define MESH_PORT 5555
19
-
20
- #define STATION_SSID "YourAP_SSID"
21
- #define STATION_PASSWORD "YourAP_PWD"
22
-
23
- #define HOSTNAME "MQTT_Bridge"
24
-
25
- // Prototypes
26
- void receivedCallback( const uint32_t &from, const String &msg );
27
- void mqttCallback(char* topic, byte* payload, unsigned int length);
28
-
29
- IPAddress getlocalIP();
30
-
31
- IPAddress myIP(0,0,0,0);
32
- IPAddress mqttBroker(192, 168, 1, 1);
33
-
34
- painlessMesh mesh;
35
- WiFiClient wifiClient;
36
- PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient);
37
-
38
- void setup() {
39
- Serial.begin(115200);
40
-
41
- mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
42
-
43
- // Channel set to 6. Make sure to use the same channel for your mesh and for you other
44
- // network (STATION_SSID)
45
- mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
46
- mesh.onReceive(&receivedCallback);
47
-
48
- mesh.stationManual(STATION_SSID, STATION_PASSWORD);
49
- mesh.setHostname(HOSTNAME);
50
-
51
- // Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background
52
- mesh.setRoot(true);
53
- // This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
54
- mesh.setContainsRoot(true);
55
- }
56
-
57
- void loop() {
58
- mesh.update();
59
- mqttClient.loop();
60
-
61
- if(myIP != getlocalIP()){
62
- myIP = getlocalIP();
63
- Serial.println("My IP is " + myIP.toString());
64
-
65
- if (mqttClient.connect("painlessMeshClient")) {
66
- mqttClient.publish("painlessMesh/from/gateway","Ready!");
67
- mqttClient.subscribe("painlessMesh/to/#");
68
- }
69
- }
70
- }
71
-
72
- void receivedCallback( const uint32_t &from, const String &msg ) {
73
- Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
74
- String topic = "painlessMesh/from/" + String(from);
75
- mqttClient.publish(topic.c_str(), msg.c_str());
76
- }
77
-
78
- void mqttCallback(char* topic, uint8_t* payload, unsigned int length) {
79
- char* cleanPayload = (char*)malloc(length+1);
80
- memcpy(cleanPayload, payload, length);
81
- cleanPayload[length] = '\0';
82
- String msg = String(cleanPayload);
83
- free(cleanPayload);
84
-
85
- String targetStr = String(topic).substring(16);
86
-
87
- if(targetStr == "gateway")
88
- {
89
- if(msg == "getNodes")
90
- {
91
- auto nodes = mesh.getNodeList(true);
92
- String str;
93
- for (auto &&id : nodes)
94
- str += String(id) + String(" ");
95
- mqttClient.publish("painlessMesh/from/gateway", str.c_str());
96
- }
97
- }
98
- else if(targetStr == "broadcast")
99
- {
100
- mesh.sendBroadcast(msg);
101
- }
102
- else
103
- {
104
- uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
105
- if(mesh.isConnected(target))
106
- {
107
- mesh.sendSingle(target, msg);
108
- }
109
- else
110
- {
111
- mqttClient.publish("painlessMesh/from/gateway", "Client not connected!");
112
- }
113
- }
114
- }
115
-
116
- IPAddress getlocalIP() {
117
- return IPAddress(mesh.getStationIP());
118
- }
1
+ //************************************************************
2
+ // this is a simple example that uses the painlessMesh library to
3
+ // connect to a another network and relay messages from a MQTT broker to the nodes of the mesh network.
4
+ // To send a message to a mesh node, you can publish it to "painlessMesh/to/12345678" where 12345678 equals the nodeId.
5
+ // To broadcast a message to all nodes in the mesh you can publish it to "painlessMesh/to/broadcast".
6
+ // When you publish "getNodes" to "painlessMesh/to/gateway" you receive the mesh topology as JSON
7
+ // Every message from the mesh which is send to the gateway node will be published to "painlessMesh/from/12345678" where 12345678
8
+ // is the nodeId from which the packet was send.
9
+ //************************************************************
10
+
11
+ #include <Arduino.h>
12
+ #include <painlessMesh.h>
13
+ #include <PubSubClient.h>
14
+ #include <WiFiClient.h>
15
+
16
+ #define MESH_PREFIX "whateverYouLike"
17
+ #define MESH_PASSWORD "somethingSneaky"
18
+ #define MESH_PORT 5555
19
+
20
+ #define STATION_SSID "YourAP_SSID"
21
+ #define STATION_PASSWORD "YourAP_PWD"
22
+
23
+ #define HOSTNAME "MQTT_Bridge"
24
+
25
+ // Prototypes
26
+ void receivedCallback( const uint32_t &from, const String &msg );
27
+ void mqttCallback(char* topic, byte* payload, unsigned int length);
28
+
29
+ IPAddress getlocalIP();
30
+
31
+ IPAddress myIP(0,0,0,0);
32
+ IPAddress mqttBroker(192, 168, 1, 1);
33
+
34
+ painlessMesh mesh;
35
+ WiFiClient wifiClient;
36
+ PubSubClient mqttClient(mqttBroker, 1883, mqttCallback, wifiClient);
37
+
38
+ void setup() {
39
+ Serial.begin(115200);
40
+
41
+ mesh.setDebugMsgTypes( ERROR | STARTUP | CONNECTION ); // set before init() so that you can see startup messages
42
+
43
+ // Channel set to 6. Make sure to use the same channel for your mesh and for you other
44
+ // network (STATION_SSID)
45
+ mesh.init( MESH_PREFIX, MESH_PASSWORD, MESH_PORT, WIFI_AP_STA, 6 );
46
+ mesh.onReceive(&receivedCallback);
47
+
48
+ mesh.stationManual(STATION_SSID, STATION_PASSWORD);
49
+ mesh.setHostname(HOSTNAME);
50
+
51
+ // Bridge node, should (in most cases) be a root node. See [the wiki](https://gitlab.com/painlessMesh/painlessMesh/wikis/Possible-challenges-in-mesh-formation) for some background
52
+ mesh.setRoot(true);
53
+ // This node and all other nodes should ideally know the mesh contains a root, so call this on all nodes
54
+ mesh.setContainsRoot(true);
55
+ }
56
+
57
+ void loop() {
58
+ mesh.update();
59
+ mqttClient.loop();
60
+
61
+ if(myIP != getlocalIP()){
62
+ myIP = getlocalIP();
63
+ Serial.println("My IP is " + myIP.toString());
64
+
65
+ if (mqttClient.connect("painlessMeshClient")) {
66
+ mqttClient.publish("painlessMesh/from/gateway","Ready!");
67
+ mqttClient.subscribe("painlessMesh/to/#");
68
+ }
69
+ }
70
+ }
71
+
72
+ void receivedCallback( const uint32_t &from, const String &msg ) {
73
+ Serial.printf("bridge: Received from %u msg=%s\n", from, msg.c_str());
74
+ String topic = "painlessMesh/from/" + String(from);
75
+ mqttClient.publish(topic.c_str(), msg.c_str());
76
+ }
77
+
78
+ void mqttCallback(char* topic, uint8_t* payload, unsigned int length) {
79
+ char* cleanPayload = (char*)malloc(length+1);
80
+ memcpy(cleanPayload, payload, length);
81
+ cleanPayload[length] = '\0';
82
+ String msg = String(cleanPayload);
83
+ free(cleanPayload);
84
+
85
+ String targetStr = String(topic).substring(16);
86
+
87
+ if(targetStr == "gateway")
88
+ {
89
+ if(msg == "getNodes")
90
+ {
91
+ auto nodes = mesh.getNodeList(true);
92
+ String str;
93
+ for (auto &&id : nodes)
94
+ str += String(id) + String(" ");
95
+ mqttClient.publish("painlessMesh/from/gateway", str.c_str());
96
+ }
97
+ }
98
+ else if(targetStr == "broadcast")
99
+ {
100
+ mesh.sendBroadcast(msg);
101
+ }
102
+ else
103
+ {
104
+ uint32_t target = strtoul(targetStr.c_str(), NULL, 10);
105
+ if(mesh.isConnected(target))
106
+ {
107
+ mesh.sendSingle(target, msg);
108
+ }
109
+ else
110
+ {
111
+ mqttClient.publish("painlessMesh/from/gateway", "Client not connected!");
112
+ }
113
+ }
114
+ }
115
+
116
+ IPAddress getlocalIP() {
117
+ return IPAddress(mesh.getStationIP());
118
+ }
@@ -1,26 +1,26 @@
1
- [platformio]
2
- src_dir = .
3
-
4
- [env]
5
- lib_deps =
6
- bblanchon/ArduinoJson
7
- arkhipenko/TaskScheduler
8
- PubSubClient
9
-
10
- [env:esp8266]
11
- platform = espressif8266
12
- board = nodemcuv2
13
- framework = arduino
14
- lib_extra_dirs = ../../
15
- lib_deps =
16
- ${env.lib_deps} ; Inherit common dependencies
17
- esp32async/ESPAsyncTCP@^2.0.0 ; Only for ESP8266
18
-
19
- [env:esp32]
20
- platform = espressif32
21
- board = esp32dev
22
- framework = arduino
23
- lib_extra_dirs = ../../
24
- lib_deps =
25
- ${env.lib_deps} ; Inherit common dependencies
26
- esp32async/AsyncTCP
1
+ [platformio]
2
+ src_dir = .
3
+
4
+ [env]
5
+ lib_deps =
6
+ bblanchon/ArduinoJson
7
+ arkhipenko/TaskScheduler
8
+ PubSubClient
9
+
10
+ [env:esp8266]
11
+ platform = espressif8266
12
+ board = nodemcuv2
13
+ framework = arduino
14
+ lib_extra_dirs = ../../
15
+ lib_deps =
16
+ ${env.lib_deps} ; Inherit common dependencies
17
+ esp32async/ESPAsyncTCP@^2.0.0 ; Only for ESP8266
18
+
19
+ [env:esp32]
20
+ platform = espressif32
21
+ board = esp32dev
22
+ framework = arduino
23
+ lib_extra_dirs = ../../
24
+ lib_deps =
25
+ ${env.lib_deps} ; Inherit common dependencies
26
+ esp32async/AsyncTCP
@@ -0,0 +1,235 @@
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
+ // Command response fields (for MQTT bridge)
100
+ uint32_t responseToCommand = 0; // CommandId this is responding to
101
+ TSTRING responseMessage = ""; // Success/error message
102
+
103
+ StatusPackage() : BroadcastPackage(202) {} // Type ID 202 for Alteriom status
104
+
105
+ StatusPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
106
+ deviceStatus = jsonObj["status"];
107
+ uptime = jsonObj["uptime"];
108
+ freeMemory = jsonObj["mem"];
109
+ wifiStrength = jsonObj["wifi"];
110
+ firmwareVersion = jsonObj["fw"].as<TSTRING>();
111
+ responseToCommand = jsonObj["respTo"] | 0;
112
+ responseMessage = jsonObj["respMsg"].as<TSTRING>();
113
+ }
114
+
115
+ JsonObject addTo(JsonObject&& jsonObj) const {
116
+ jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
117
+ jsonObj["status"] = deviceStatus;
118
+ jsonObj["uptime"] = uptime;
119
+ jsonObj["mem"] = freeMemory;
120
+ jsonObj["wifi"] = wifiStrength;
121
+ jsonObj["fw"] = firmwareVersion;
122
+ if (responseToCommand > 0) {
123
+ jsonObj["respTo"] = responseToCommand;
124
+ jsonObj["respMsg"] = responseMessage;
125
+ }
126
+ return jsonObj;
127
+ }
128
+
129
+ #if ARDUINOJSON_VERSION_MAJOR < 7
130
+ size_t jsonObjectSize() const {
131
+ return JSON_OBJECT_SIZE(noJsonFields + 7) + firmwareVersion.length() +
132
+ responseMessage.length();
133
+ }
134
+ #endif
135
+ };
136
+
137
+ /**
138
+ * @brief Enhanced status package with comprehensive health metrics (Phase 1)
139
+ *
140
+ * This is an extended version of StatusPackage that includes additional
141
+ * mesh statistics, performance metrics, and alerting capabilities.
142
+ * Type ID 203 is used to distinguish from the basic StatusPackage (202).
143
+ */
144
+ class EnhancedStatusPackage : public painlessmesh::plugin::BroadcastPackage {
145
+ public:
146
+ // Device Health (from original StatusPackage)
147
+ uint8_t deviceStatus = 0; // Device status flags
148
+ uint32_t uptime = 0; // Device uptime in seconds
149
+ uint16_t freeMemory = 0; // Free memory in KB
150
+ uint8_t wifiStrength = 0; // WiFi signal strength
151
+ TSTRING firmwareVersion = ""; // Current firmware version
152
+ TSTRING firmwareMD5 = ""; // Firmware hash for OTA verification
153
+
154
+ // Mesh Statistics
155
+ uint16_t nodeCount = 0; // Number of known nodes in mesh
156
+ uint8_t connectionCount = 0; // Number of direct connections
157
+ uint32_t messagesReceived = 0; // Total messages received
158
+ uint32_t messagesSent = 0; // Total messages sent
159
+ uint32_t messagesDropped = 0; // Total messages dropped/failed
160
+
161
+ // Performance Metrics
162
+ uint16_t avgLatency = 0; // Average message latency in ms
163
+ uint8_t packetLossRate = 0; // Packet loss rate percentage (0-100)
164
+ uint16_t throughput = 0; // Network throughput in bytes/sec
165
+
166
+ // Warnings/Alerts
167
+ uint8_t alertFlags = 0; // Bit flags for various alert conditions
168
+ TSTRING lastError = ""; // Last error message for diagnostics
169
+
170
+ EnhancedStatusPackage()
171
+ : BroadcastPackage(203) {} // Type ID 203 for enhanced status
172
+
173
+ EnhancedStatusPackage(JsonObject jsonObj) : BroadcastPackage(jsonObj) {
174
+ deviceStatus = jsonObj["status"];
175
+ uptime = jsonObj["uptime"];
176
+ freeMemory = jsonObj["mem"];
177
+ wifiStrength = jsonObj["wifi"];
178
+ firmwareVersion = jsonObj["fw"].as<TSTRING>();
179
+ firmwareMD5 = jsonObj["fwMD5"].as<TSTRING>();
180
+
181
+ nodeCount = jsonObj["nodes"];
182
+ connectionCount = jsonObj["conns"];
183
+ messagesReceived = jsonObj["msgRx"];
184
+ messagesSent = jsonObj["msgTx"];
185
+ messagesDropped = jsonObj["msgDrop"];
186
+
187
+ avgLatency = jsonObj["latency"];
188
+ packetLossRate = jsonObj["loss"];
189
+ throughput = jsonObj["throughput"];
190
+
191
+ alertFlags = jsonObj["alerts"];
192
+ lastError = jsonObj["lastErr"].as<TSTRING>();
193
+ }
194
+
195
+ JsonObject addTo(JsonObject&& jsonObj) const {
196
+ jsonObj = BroadcastPackage::addTo(std::move(jsonObj));
197
+
198
+ // Device Health
199
+ jsonObj["status"] = deviceStatus;
200
+ jsonObj["uptime"] = uptime;
201
+ jsonObj["mem"] = freeMemory;
202
+ jsonObj["wifi"] = wifiStrength;
203
+ jsonObj["fw"] = firmwareVersion;
204
+ jsonObj["fwMD5"] = firmwareMD5;
205
+
206
+ // Mesh Statistics
207
+ jsonObj["nodes"] = nodeCount;
208
+ jsonObj["conns"] = connectionCount;
209
+ jsonObj["msgRx"] = messagesReceived;
210
+ jsonObj["msgTx"] = messagesSent;
211
+ jsonObj["msgDrop"] = messagesDropped;
212
+
213
+ // Performance Metrics
214
+ jsonObj["latency"] = avgLatency;
215
+ jsonObj["loss"] = packetLossRate;
216
+ jsonObj["throughput"] = throughput;
217
+
218
+ // Alerts
219
+ jsonObj["alerts"] = alertFlags;
220
+ jsonObj["lastErr"] = lastError;
221
+
222
+ return jsonObj;
223
+ }
224
+
225
+ #if ARDUINOJSON_VERSION_MAJOR < 7
226
+ size_t jsonObjectSize() const {
227
+ return JSON_OBJECT_SIZE(noJsonFields + 18) + firmwareVersion.length() +
228
+ firmwareMD5.length() + lastError.length();
229
+ }
230
+ #endif
231
+ };
232
+
233
+ } // namespace alteriom
234
+
235
+ #endif // ALTERIOM_SENSOR_PACKAGE_HPP