@alteriom/painlessmesh 1.6.1 → 1.7.3

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 (152) hide show
  1. package/CHANGELOG.md +435 -144
  2. package/LICENSE +674 -674
  3. package/README.md +491 -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 +130 -71
  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/archive/DOCUSAURUS_DEPLOYMENT.md +166 -0
  25. package/docs/archive/FEATURE_PROPOSALS.md +337 -0
  26. package/docs/archive/LIBRARY_JSON_FIX.md +98 -0
  27. package/docs/archive/LIBRARY_STRUCTURE_FIX.md +215 -0
  28. package/docs/archive/PHASE1_IMPLEMENTATION.md +325 -0
  29. package/docs/archive/PHASE2_IMPLEMENTATION.md +567 -0
  30. package/docs/archive/RELEASE_SUMMARY.md +173 -0
  31. package/docs/archive/SCONS_BUILD_FIX.md +313 -0
  32. package/docs/archive/TRIGGER_RELEASE.md +280 -0
  33. package/docs/archive/VECTOR_INCLUDE_FIX.md +129 -0
  34. package/docs/archive/ota-and-status-enhancements.md +911 -0
  35. package/docs/archive/ota-status-architecture-diagrams.md +658 -0
  36. package/docs/archive/ota-status-quick-reference.md +284 -0
  37. package/docs/development/ARDUINO_COMPLIANCE_SUMMARY.md +71 -0
  38. package/docs/development/CODE_REFACTORING_RECOMMENDATIONS.md +1011 -0
  39. package/docs/development/DOCKER_TESTING.md +196 -0
  40. package/docs/development/PLATFORMIO_USAGE.md +180 -0
  41. package/docs/development/TESTING_SUMMARY.md +126 -0
  42. package/docs/development/contributing.md +301 -0
  43. package/docs/development/documentation.md +583 -0
  44. package/docs/getting-started/first-mesh.md +409 -409
  45. package/docs/getting-started/installation.md +274 -274
  46. package/docs/getting-started/quickstart.md +157 -157
  47. package/docs/improvements/FUTURE_PROPOSALS.md +1016 -0
  48. package/docs/improvements/IMPLEMENTATION_HISTORY.md +1091 -0
  49. package/docs/improvements/OTA_STATUS_ENHANCEMENTS.md +709 -0
  50. package/docs/improvements/README.md +212 -69
  51. package/docs/platformio-publishing.md +255 -0
  52. package/docs/platformio-setup-summary.md +121 -0
  53. package/docs/releases/FEATURE_HISTORY.md +543 -0
  54. package/docs/releases/PATCH_v1.7.3.md +262 -0
  55. package/docs/releases/PHASE1_SUMMARY.md +246 -0
  56. package/docs/releases/PHASE2_SUMMARY.md +499 -0
  57. package/docs/releases/RELEASE_NOTES_1.7.0.md +539 -0
  58. package/docs/troubleshooting/common-issues.md +520 -520
  59. package/docs/troubleshooting/debugging.md +455 -0
  60. package/docs/troubleshooting/faq.md +472 -472
  61. package/docs/tutorials/basic-examples.md +717 -717
  62. package/docs/wiki/API-Reference.md +245 -245
  63. package/docs/wiki/Complete-Documentation.md +122 -122
  64. package/examples/alteriom/README.md +139 -81
  65. package/examples/alteriom/alteriom.ino +186 -185
  66. package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
  67. package/examples/alteriom/platformio.ini +24 -24
  68. package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
  69. package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
  70. package/examples/alteriomImproved/platformio.ini +25 -0
  71. package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
  72. package/examples/alteriomPhase1/phase1_features.ino +242 -0
  73. package/examples/alteriomPhase1/platformio.ini +25 -0
  74. package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
  75. package/examples/alteriomPhase2/phase2_features.ino +186 -0
  76. package/examples/alteriomPhase2/platformio.ini +25 -0
  77. package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
  78. package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
  79. package/examples/alteriomSensorNode/platformio.ini +25 -0
  80. package/examples/basic/basic.ino +66 -66
  81. package/examples/basic/platformio.ini +25 -25
  82. package/examples/bridge/bridge.ino +51 -51
  83. package/examples/bridge/mesh_event_publisher.hpp +253 -0
  84. package/examples/bridge/mesh_topology_reporter.hpp +303 -0
  85. package/examples/bridge/mqtt_command_bridge.hpp +459 -0
  86. package/examples/bridge/mqtt_status_bridge.hpp +519 -0
  87. package/examples/bridge/platformio.ini +25 -25
  88. package/examples/echoNode/echoNode.ino +33 -33
  89. package/examples/echoNode/platformio.ini +25 -25
  90. package/examples/logClient/logClient.ino +109 -109
  91. package/examples/logClient/platformio.ini +25 -25
  92. package/examples/logServer/logServer.ino +81 -81
  93. package/examples/logServer/platformio.ini +25 -25
  94. package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
  95. package/examples/meshCommandNode/meshCommandNode.ino +263 -0
  96. package/examples/meshCommandNode/platformio.ini +25 -0
  97. package/examples/mqttBridge/mqttBridge.ino +118 -118
  98. package/examples/mqttBridge/platformio.ini +26 -26
  99. package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
  100. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
  101. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
  102. package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
  103. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
  104. package/examples/mqttCommandBridge/platformio.ini +26 -0
  105. package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
  106. package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
  107. package/examples/mqttStatusBridge/platformio.ini +26 -0
  108. package/examples/mqttTopologyTest/README.md +467 -0
  109. package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
  110. package/examples/mqttTopologyTest/platformio.ini +26 -0
  111. package/examples/namedMesh/namedMesh.ino +97 -97
  112. package/examples/namedMesh/platformio.ini +25 -25
  113. package/examples/otaReceiver/otaReceiver.ino +79 -79
  114. package/examples/otaReceiver/platformio.ini +25 -25
  115. package/examples/otaSender/otaSender.ino +160 -151
  116. package/examples/otaSender/platformio.ini +25 -25
  117. package/examples/startHere/platformio.ini +25 -25
  118. package/examples/startHere/startHere.ino +159 -159
  119. package/examples/webServer/platformio.ini +27 -27
  120. package/examples/webServer/webServer.ino +89 -89
  121. package/keywords.txt +48 -48
  122. package/library.json +55 -34
  123. package/library.properties +10 -10
  124. package/package.json +86 -78
  125. package/src/AlteriomPainlessMesh.h +97 -97
  126. package/src/arduino/wifi.hpp +365 -365
  127. package/src/boost/asynctcp.hpp +279 -279
  128. package/src/painlessMesh.h +70 -70
  129. package/src/painlessMeshSTA.cpp +236 -236
  130. package/src/painlessMeshSTA.h +58 -58
  131. package/src/painlessTaskOptions.h +4 -4
  132. package/src/painlessmesh/base64.hpp +111 -111
  133. package/src/painlessmesh/buffer.hpp +229 -229
  134. package/src/painlessmesh/callback.hpp +91 -91
  135. package/src/painlessmesh/configuration.hpp +77 -77
  136. package/src/painlessmesh/connection.hpp +192 -192
  137. package/src/painlessmesh/layout.hpp +188 -188
  138. package/src/painlessmesh/logger.hpp +158 -158
  139. package/src/painlessmesh/memory.hpp +119 -119
  140. package/src/painlessmesh/mesh.hpp +761 -560
  141. package/src/painlessmesh/metrics.hpp +322 -322
  142. package/src/painlessmesh/ntp.hpp +263 -263
  143. package/src/painlessmesh/ota.hpp +582 -553
  144. package/src/painlessmesh/plugin.hpp +188 -188
  145. package/src/painlessmesh/protocol.hpp +813 -813
  146. package/src/painlessmesh/router.hpp +338 -322
  147. package/src/painlessmesh/tcp.hpp +71 -71
  148. package/src/painlessmesh/validation.hpp +238 -238
  149. package/src/plugin/performance.hpp +214 -214
  150. package/src/plugin/remote.hpp +64 -64
  151. package/src/scheduler.cpp +10 -10
  152. 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