@alteriom/painlessmesh 1.7.3 → 1.7.5
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 +84 -0
- package/docs/releases/PATCH_v1.7.2.md +262 -0
- package/docs/releases/PATCH_v1.7.4.md +219 -0
- package/docs/releases/RELEASE_CHECKLIST_v1.7.4.md +253 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.4.md +276 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.5.md +322 -0
- package/docs/troubleshooting/CRASH_QUICK_REF.md +93 -0
- package/docs/troubleshooting/FREERTOS_ASSERTION_FAILURE.md +288 -0
- package/docs/troubleshooting/FREERTOS_FIX_IMPLEMENTATION.md +267 -0
- package/docs/troubleshooting/QUICK_FIX_FREERTOS.md +164 -0
- package/docs/troubleshooting/SENSOR_NODE_CONNECTION_CRASH.md +264 -0
- package/examples/alteriom/platformio.ini +1 -0
- package/examples/alteriomImproved/improved_sensor_node.ino +2 -0
- package/examples/alteriomImproved/platformio.ini +7 -0
- package/examples/alteriomPhase1/platformio.ini +1 -0
- package/examples/alteriomPhase2/platformio.ini +1 -0
- package/examples/alteriomSensorNode/alteriom_sensor_node.ino +2 -0
- package/examples/alteriomSensorNode/platformio.ini +1 -0
- package/examples/basic/platformio.ini +1 -0
- package/examples/bridge/platformio.ini +1 -0
- package/examples/echoNode/platformio.ini +1 -0
- package/examples/logClient/platformio.ini +1 -0
- package/examples/logServer/platformio.ini +1 -0
- package/examples/meshCommandNode/meshCommandNode.ino +2 -0
- package/examples/meshCommandNode/platformio.ini +1 -0
- package/examples/mqttBridge/platformio.ini +1 -0
- package/examples/mqttCommandBridge/mesh_event_publisher.hpp +19 -19
- package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +18 -18
- package/examples/mqttCommandBridge/mqttCommandBridge.ino +3 -1
- package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +9 -6
- package/examples/mqttCommandBridge/platformio.ini +1 -0
- package/examples/mqttStatusBridge/mqttStatusBridge.ino +2 -0
- package/examples/mqttStatusBridge/platformio.ini +1 -0
- package/examples/mqttTopologyTest/mqttTopologyTest.ino +2 -0
- package/examples/mqttTopologyTest/platformio.ini +1 -0
- package/examples/namedMesh/platformio.ini +1 -0
- package/examples/otaReceiver/platformio.ini +1 -0
- package/examples/otaSender/platformio.ini +1 -0
- package/examples/startHere/platformio.ini +1 -0
- package/examples/webServer/platformio.ini +1 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/painlessTaskOptions.h +18 -3
- package/src/painlessmesh/mesh.hpp +12 -1
- package/src/painlessmesh/scheduler_queue.cpp +77 -0
- package/src/painlessmesh/scheduler_queue.hpp +34 -0
|
@@ -6,6 +6,13 @@ lib_deps =
|
|
|
6
6
|
bblanchon/ArduinoJson
|
|
7
7
|
arkhipenko/TaskScheduler
|
|
8
8
|
|
|
9
|
+
lib_ldf_mode = deep+
|
|
10
|
+
|
|
11
|
+
; Enable painlessMesh improvement features
|
|
12
|
+
build_flags =
|
|
13
|
+
-DPAINLESSMESH_ENABLE_VALIDATION
|
|
14
|
+
-DPAINLESSMESH_ENABLE_METRICS
|
|
15
|
+
-DPAINLESSMESH_ENABLE_MEMORY_OPTIMIZATION
|
|
9
16
|
[env:esp8266]
|
|
10
17
|
platform = espressif8266
|
|
11
18
|
board = nodemcuv2
|
|
@@ -5,6 +5,8 @@
|
|
|
5
5
|
// sensor node using custom packages with painlessMesh
|
|
6
6
|
//************************************************************
|
|
7
7
|
|
|
8
|
+
#include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
|
|
9
|
+
#include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
|
|
8
10
|
#include "alteriom_sensor_package.hpp"
|
|
9
11
|
#include "painlessMesh.h"
|
|
10
12
|
|
|
@@ -40,7 +40,7 @@ public:
|
|
|
40
40
|
* Called when a new node connects to the mesh
|
|
41
41
|
*/
|
|
42
42
|
void publishNodeJoin(uint32_t nodeId) {
|
|
43
|
-
|
|
43
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
44
44
|
|
|
45
45
|
// Envelope
|
|
46
46
|
doc["schema_version"] = 1;
|
|
@@ -54,10 +54,10 @@ public:
|
|
|
54
54
|
doc["event_type"] = "node_join";
|
|
55
55
|
doc["mesh_id"] = meshId;
|
|
56
56
|
|
|
57
|
-
JsonArray affected = doc
|
|
57
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
58
58
|
affected.add(generateDeviceId(nodeId));
|
|
59
59
|
|
|
60
|
-
JsonObject details = doc
|
|
60
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
61
61
|
details["total_nodes"] = mesh.getNodeList().size() + 1;
|
|
62
62
|
details["timestamp"] = getISO8601Timestamp();
|
|
63
63
|
|
|
@@ -69,7 +69,7 @@ public:
|
|
|
69
69
|
* Called when a node disconnects from the mesh
|
|
70
70
|
*/
|
|
71
71
|
void publishNodeLeave(uint32_t nodeId) {
|
|
72
|
-
|
|
72
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
73
73
|
|
|
74
74
|
// Envelope
|
|
75
75
|
doc["schema_version"] = 1;
|
|
@@ -83,10 +83,10 @@ public:
|
|
|
83
83
|
doc["event_type"] = "node_leave";
|
|
84
84
|
doc["mesh_id"] = meshId;
|
|
85
85
|
|
|
86
|
-
JsonArray affected = doc
|
|
86
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
87
87
|
affected.add(generateDeviceId(nodeId));
|
|
88
88
|
|
|
89
|
-
JsonObject details = doc
|
|
89
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
90
90
|
details["reason"] = "connection_lost";
|
|
91
91
|
details["last_seen"] = getISO8601Timestamp();
|
|
92
92
|
details["total_nodes"] = mesh.getNodeList().size() + 1;
|
|
@@ -99,7 +99,7 @@ public:
|
|
|
99
99
|
* Called when a direct connection fails
|
|
100
100
|
*/
|
|
101
101
|
void publishConnectionLost(uint32_t nodeId) {
|
|
102
|
-
|
|
102
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
103
103
|
|
|
104
104
|
doc["schema_version"] = 1;
|
|
105
105
|
doc["device_id"] = generateDeviceId(mesh.getNodeId());
|
|
@@ -111,10 +111,10 @@ public:
|
|
|
111
111
|
doc["event_type"] = "connection_lost";
|
|
112
112
|
doc["mesh_id"] = meshId;
|
|
113
113
|
|
|
114
|
-
JsonArray affected = doc
|
|
114
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
115
115
|
affected.add(generateDeviceId(nodeId));
|
|
116
116
|
|
|
117
|
-
JsonObject details = doc
|
|
117
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
118
118
|
details["reason"] = "timeout";
|
|
119
119
|
details["timestamp"] = getISO8601Timestamp();
|
|
120
120
|
|
|
@@ -126,7 +126,7 @@ public:
|
|
|
126
126
|
* Called when a connection is re-established
|
|
127
127
|
*/
|
|
128
128
|
void publishConnectionRestored(uint32_t nodeId) {
|
|
129
|
-
|
|
129
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
130
130
|
|
|
131
131
|
doc["schema_version"] = 1;
|
|
132
132
|
doc["device_id"] = generateDeviceId(mesh.getNodeId());
|
|
@@ -138,10 +138,10 @@ public:
|
|
|
138
138
|
doc["event_type"] = "connection_restored";
|
|
139
139
|
doc["mesh_id"] = meshId;
|
|
140
140
|
|
|
141
|
-
JsonArray affected = doc
|
|
141
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
142
142
|
affected.add(generateDeviceId(nodeId));
|
|
143
143
|
|
|
144
|
-
JsonObject details = doc
|
|
144
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
145
145
|
details["timestamp"] = getISO8601Timestamp();
|
|
146
146
|
|
|
147
147
|
publishEvent(doc, "Connection Restored");
|
|
@@ -152,7 +152,7 @@ public:
|
|
|
152
152
|
* Called when mesh partitions into separate segments
|
|
153
153
|
*/
|
|
154
154
|
void publishNetworkSplit() {
|
|
155
|
-
|
|
155
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
156
156
|
|
|
157
157
|
doc["schema_version"] = 1;
|
|
158
158
|
doc["device_id"] = generateDeviceId(mesh.getNodeId());
|
|
@@ -164,10 +164,10 @@ public:
|
|
|
164
164
|
doc["event_type"] = "network_split";
|
|
165
165
|
doc["mesh_id"] = meshId;
|
|
166
166
|
|
|
167
|
-
JsonArray affected = doc
|
|
167
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
168
168
|
// TODO: Detect which nodes are in different partitions
|
|
169
169
|
|
|
170
|
-
JsonObject details = doc
|
|
170
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
171
171
|
details["timestamp"] = getISO8601Timestamp();
|
|
172
172
|
details["partition_count"] = 2; // TODO: Calculate actual partitions
|
|
173
173
|
|
|
@@ -179,7 +179,7 @@ public:
|
|
|
179
179
|
* Called when mesh partitions rejoin
|
|
180
180
|
*/
|
|
181
181
|
void publishNetworkMerged() {
|
|
182
|
-
|
|
182
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
183
183
|
|
|
184
184
|
doc["schema_version"] = 1;
|
|
185
185
|
doc["device_id"] = generateDeviceId(mesh.getNodeId());
|
|
@@ -191,10 +191,10 @@ public:
|
|
|
191
191
|
doc["event_type"] = "network_merged";
|
|
192
192
|
doc["mesh_id"] = meshId;
|
|
193
193
|
|
|
194
|
-
JsonArray affected = doc
|
|
194
|
+
JsonArray affected = doc["affected_nodes"].to<JsonArray>();
|
|
195
195
|
// TODO: List nodes that rejoined
|
|
196
196
|
|
|
197
|
-
JsonObject details = doc
|
|
197
|
+
JsonObject details = doc["details"].to<JsonObject>();
|
|
198
198
|
details["timestamp"] = getISO8601Timestamp();
|
|
199
199
|
|
|
200
200
|
publishEvent(doc, "Network Merged");
|
|
@@ -204,7 +204,7 @@ private:
|
|
|
204
204
|
/**
|
|
205
205
|
* Internal method to publish event to MQTT
|
|
206
206
|
*/
|
|
207
|
-
void publishEvent(const
|
|
207
|
+
void publishEvent(const JsonDocument& doc, const char* eventName) {
|
|
208
208
|
if (!mqttClient.connected()) {
|
|
209
209
|
Serial.printf("[Event] ⚠️ MQTT not connected, cannot publish %s\n", eventName);
|
|
210
210
|
return;
|
|
@@ -37,7 +37,7 @@ public:
|
|
|
37
37
|
* alteriom/mesh/{mesh_id}/topology
|
|
38
38
|
*/
|
|
39
39
|
String generateFullTopology() {
|
|
40
|
-
|
|
40
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
41
41
|
|
|
42
42
|
// Envelope fields (from @alteriom/mqtt-schema)
|
|
43
43
|
doc["schema_version"] = 1;
|
|
@@ -53,8 +53,8 @@ public:
|
|
|
53
53
|
doc["mesh_id"] = meshId;
|
|
54
54
|
doc["gateway_node_id"] = generateDeviceId(mesh.getNodeId());
|
|
55
55
|
|
|
56
|
-
// Nodes array
|
|
57
|
-
JsonArray nodes = doc
|
|
56
|
+
// Nodes array - ArduinoJson v7 syntax
|
|
57
|
+
JsonArray nodes = doc["nodes"].to<JsonArray>();
|
|
58
58
|
addNodeInfo(nodes, mesh.getNodeId(), "gateway"); // Self
|
|
59
59
|
|
|
60
60
|
auto nodeList = mesh.getNodeList(false);
|
|
@@ -62,12 +62,12 @@ public:
|
|
|
62
62
|
addNodeInfo(nodes, nodeId, "sensor"); // Assume sensor role
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
// Connections array
|
|
66
|
-
JsonArray connections = doc
|
|
65
|
+
// Connections array - ArduinoJson v7 syntax
|
|
66
|
+
JsonArray connections = doc["connections"].to<JsonArray>();
|
|
67
67
|
addConnectionInfo(connections);
|
|
68
68
|
|
|
69
|
-
// Network metrics
|
|
70
|
-
JsonObject metrics = doc
|
|
69
|
+
// Network metrics - ArduinoJson v7 syntax
|
|
70
|
+
JsonObject metrics = doc["metrics"].to<JsonObject>();
|
|
71
71
|
metrics["total_nodes"] = nodeList.size() + 1; // +1 for gateway
|
|
72
72
|
metrics["online_nodes"] = nodeList.size() + 1;
|
|
73
73
|
metrics["network_diameter"] = calculateNetworkDiameter();
|
|
@@ -88,7 +88,7 @@ public:
|
|
|
88
88
|
* @param joined true if node joined, false if left
|
|
89
89
|
*/
|
|
90
90
|
String generateIncrementalUpdate(uint32_t nodeId, bool joined) {
|
|
91
|
-
|
|
91
|
+
JsonDocument doc; // ArduinoJson v7: automatic sizing
|
|
92
92
|
|
|
93
93
|
// Envelope fields
|
|
94
94
|
doc["schema_version"] = 1;
|
|
@@ -101,25 +101,25 @@ public:
|
|
|
101
101
|
doc["mesh_id"] = meshId;
|
|
102
102
|
doc["gateway_node_id"] = generateDeviceId(mesh.getNodeId());
|
|
103
103
|
|
|
104
|
-
// Node that changed
|
|
105
|
-
JsonArray nodes = doc
|
|
104
|
+
// Node that changed - ArduinoJson v7 syntax
|
|
105
|
+
JsonArray nodes = doc["nodes"].to<JsonArray>();
|
|
106
106
|
if (joined) {
|
|
107
107
|
addNodeInfo(nodes, nodeId, "sensor");
|
|
108
108
|
} else {
|
|
109
109
|
// For node leaving, mark as offline
|
|
110
|
-
JsonObject node = nodes.
|
|
110
|
+
JsonObject node = nodes.add<JsonObject>();
|
|
111
111
|
node["node_id"] = generateDeviceId(nodeId);
|
|
112
112
|
node["status"] = "offline";
|
|
113
113
|
}
|
|
114
114
|
|
|
115
|
-
// Update connections
|
|
116
|
-
JsonArray connections = doc
|
|
115
|
+
// Update connections - ArduinoJson v7 syntax
|
|
116
|
+
JsonArray connections = doc["connections"].to<JsonArray>();
|
|
117
117
|
// Add connections related to this node
|
|
118
118
|
addConnectionInfoForNode(connections, nodeId);
|
|
119
119
|
|
|
120
|
-
// Updated metrics
|
|
120
|
+
// Updated metrics - ArduinoJson v7 syntax
|
|
121
121
|
auto nodeList = mesh.getNodeList(false);
|
|
122
|
-
JsonObject metrics = doc
|
|
122
|
+
JsonObject metrics = doc["metrics"].to<JsonObject>();
|
|
123
123
|
metrics["total_nodes"] = nodeList.size() + 1;
|
|
124
124
|
metrics["online_nodes"] = nodeList.size() + 1;
|
|
125
125
|
|
|
@@ -148,7 +148,7 @@ private:
|
|
|
148
148
|
* Add node information to JSON array
|
|
149
149
|
*/
|
|
150
150
|
void addNodeInfo(JsonArray& nodes, uint32_t nodeId, const char* role) {
|
|
151
|
-
JsonObject node = nodes.
|
|
151
|
+
JsonObject node = nodes.add<JsonObject>(); // ArduinoJson v7 syntax
|
|
152
152
|
node["node_id"] = generateDeviceId(nodeId);
|
|
153
153
|
node["role"] = role;
|
|
154
154
|
node["status"] = "online";
|
|
@@ -184,7 +184,7 @@ private:
|
|
|
184
184
|
String gatewayId = generateDeviceId(mesh.getNodeId());
|
|
185
185
|
|
|
186
186
|
for (auto& conn : connDetails) {
|
|
187
|
-
JsonObject connObj = connections.
|
|
187
|
+
JsonObject connObj = connections.add<JsonObject>(); // ArduinoJson v7 syntax
|
|
188
188
|
connObj["from_node"] = gatewayId;
|
|
189
189
|
connObj["to_node"] = generateDeviceId(conn.nodeId);
|
|
190
190
|
connObj["quality"] = conn.quality;
|
|
@@ -207,7 +207,7 @@ private:
|
|
|
207
207
|
|
|
208
208
|
for (auto& conn : connDetails) {
|
|
209
209
|
if (conn.nodeId == nodeId) {
|
|
210
|
-
JsonObject connObj = connections.
|
|
210
|
+
JsonObject connObj = connections.add<JsonObject>(); // ArduinoJson v7 syntax
|
|
211
211
|
connObj["from_node"] = gatewayId;
|
|
212
212
|
connObj["to_node"] = targetId;
|
|
213
213
|
connObj["quality"] = conn.quality;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
#include <Arduino.h>
|
|
2
|
+
#include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
|
|
3
|
+
#include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
|
|
2
4
|
#include "painlessMesh.h"
|
|
3
5
|
#include <PubSubClient.h>
|
|
4
6
|
#include "mqtt_command_bridge.hpp"
|
|
@@ -43,7 +45,7 @@ Task taskMqttReconnect(TASK_SECOND * 5, TASK_FOREVER, []() {
|
|
|
43
45
|
// Task for periodic gateway status
|
|
44
46
|
Task taskGatewayStatus(TASK_MINUTE, TASK_FOREVER, []() {
|
|
45
47
|
if (mqttClient.connected()) {
|
|
46
|
-
|
|
48
|
+
JsonDocument status; // ArduinoJson v7: automatic sizing
|
|
47
49
|
status["gateway_id"] = mesh.getNodeId();
|
|
48
50
|
status["status"] = "online";
|
|
49
51
|
status["uptime"] = millis() / 1000;
|
|
@@ -203,7 +203,10 @@ public:
|
|
|
203
203
|
bool state = params["state"];
|
|
204
204
|
uint8_t brightness = params["brightness"] | 255;
|
|
205
205
|
|
|
206
|
-
// Control LED
|
|
206
|
+
// Control LED (use GPIO2 if LED_BUILTIN not defined on ESP32)
|
|
207
|
+
#ifndef LED_BUILTIN
|
|
208
|
+
#define LED_BUILTIN 2
|
|
209
|
+
#endif
|
|
207
210
|
digitalWrite(LED_BUILTIN, state ? LOW : HIGH);
|
|
208
211
|
|
|
209
212
|
response.responseMessage = "LED " + String(state ? "ON" : "OFF");
|
|
@@ -253,8 +256,8 @@ public:
|
|
|
253
256
|
break;
|
|
254
257
|
|
|
255
258
|
case 202: // StatusPackage
|
|
256
|
-
// Check if it's a command response
|
|
257
|
-
if (doc
|
|
259
|
+
// Check if it's a command response (ArduinoJson v7 compatible)
|
|
260
|
+
if (doc["respTo"].is<uint32_t>() && doc["respTo"].as<uint32_t>() > 0) {
|
|
258
261
|
publishToMqtt("mesh/response/" + String(from), msg);
|
|
259
262
|
} else {
|
|
260
263
|
publishToMqtt("mesh/status/" + String(from), msg);
|
|
@@ -397,14 +400,14 @@ public:
|
|
|
397
400
|
void handleConfigUpdate(JsonDocument& doc) {
|
|
398
401
|
JsonObject config = doc["config"];
|
|
399
402
|
|
|
400
|
-
// Apply configuration updates
|
|
401
|
-
if (config
|
|
403
|
+
// Apply configuration updates (ArduinoJson v7 compatible)
|
|
404
|
+
if (config["deviceName"].is<const char*>()) {
|
|
402
405
|
String newName = config["deviceName"];
|
|
403
406
|
Serial.printf("Config update: deviceName=%s\n", newName.c_str());
|
|
404
407
|
// Store to preferences/EEPROM in production
|
|
405
408
|
}
|
|
406
409
|
|
|
407
|
-
if (config
|
|
410
|
+
if (config["meshPrefix"].is<const char*>()) {
|
|
408
411
|
String newPrefix = config["meshPrefix"];
|
|
409
412
|
Serial.printf("Config update: meshPrefix=%s (requires restart)\n", newPrefix.c_str());
|
|
410
413
|
}
|
|
@@ -24,6 +24,8 @@
|
|
|
24
24
|
//************************************************************
|
|
25
25
|
|
|
26
26
|
#include <Arduino.h>
|
|
27
|
+
#include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
|
|
28
|
+
#include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
|
|
27
29
|
#include <painlessMesh.h>
|
|
28
30
|
#include <PubSubClient.h>
|
|
29
31
|
#include <WiFiClient.h>
|
|
@@ -51,6 +51,8 @@
|
|
|
51
51
|
* @version 1.0.0
|
|
52
52
|
*/
|
|
53
53
|
|
|
54
|
+
#include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
|
|
55
|
+
#include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
|
|
54
56
|
#include "painlessMesh.h"
|
|
55
57
|
#ifdef ESP8266
|
|
56
58
|
#include <ESP8266WiFi.h>
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name=AlteriomPainlessMesh
|
|
2
|
-
version=1.7.
|
|
2
|
+
version=1.7.5
|
|
3
3
|
author=Coopdis,Scotty Franzyshen,Edwin van Leeuwen,Germán Martín,Maximilian Schwarz,Doanh Doanh,Alteriom
|
|
4
4
|
maintainer=Alteriom
|
|
5
5
|
sentence=A painless way to setup a mesh with ESP8266 and ESP32 devices with Alteriom extensions
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alteriom/painlessmesh",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.5",
|
|
4
4
|
"description": "painlessMesh is a user-friendly library for creating mesh networks with ESP8266 and ESP32 devices. This Alteriom fork includes additional packages for sensor data (SensorPackage), device commands (CommandPackage), and status monitoring (StatusPackage). It handles routing and network management automatically, so you can focus on your application. The library uses JSON-based messaging and syncs time across all nodes, making it ideal for coordinated behaviour like synchronized light displays or sensor networks reporting to a central node.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"arduino",
|
|
@@ -1,4 +1,19 @@
|
|
|
1
|
-
// The following
|
|
1
|
+
// The following compile options are required for painlessMesh
|
|
2
2
|
#define _TASK_PRIORITY // Support for layered scheduling priority
|
|
3
|
-
#define _TASK_STD_FUNCTION // Support for std::function (ESP8266 and ESP32
|
|
4
|
-
//
|
|
3
|
+
#define _TASK_STD_FUNCTION // Support for std::function (ESP8266 and ESP32)
|
|
4
|
+
// Required for painlessMesh lambda callbacks
|
|
5
|
+
|
|
6
|
+
// NOTE: _TASK_THREAD_SAFE is currently DISABLED due to incompatibility
|
|
7
|
+
// with _TASK_STD_FUNCTION in TaskScheduler v4.0.x
|
|
8
|
+
//
|
|
9
|
+
// The thread-safe mode would prevent FreeRTOS assertion failures on ESP32,
|
|
10
|
+
// but TaskScheduler's implementation has bugs when trying to cast function
|
|
11
|
+
// pointers to std::function objects in processRequests().
|
|
12
|
+
//
|
|
13
|
+
// Workaround: Use semaphore timeout increase (mesh.hpp line 544: 10ms -> 100ms)
|
|
14
|
+
// See: docs/troubleshooting/SENSOR_NODE_CONNECTION_CRASH.md
|
|
15
|
+
//
|
|
16
|
+
// #ifdef ESP32
|
|
17
|
+
// #define _TASK_THREAD_SAFE // DISABLED - Incompatible with _TASK_STD_FUNCTION
|
|
18
|
+
// #endif
|
|
19
|
+
|
|
@@ -16,6 +16,10 @@
|
|
|
16
16
|
#include "painlessmesh/ota.hpp"
|
|
17
17
|
#endif
|
|
18
18
|
|
|
19
|
+
#if defined(ESP32) && defined(_TASK_THREAD_SAFE)
|
|
20
|
+
#include "painlessmesh/scheduler_queue.hpp"
|
|
21
|
+
#endif
|
|
22
|
+
|
|
19
23
|
namespace painlessmesh {
|
|
20
24
|
typedef std::function<void(uint32_t nodeId)> newConnectionCallback_t;
|
|
21
25
|
typedef std::function<void(uint32_t nodeId)> droppedConnectionCallback_t;
|
|
@@ -41,6 +45,13 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
41
45
|
|
|
42
46
|
#ifdef ESP32
|
|
43
47
|
xSemaphore = xSemaphoreCreateMutex();
|
|
48
|
+
|
|
49
|
+
#ifdef _TASK_THREAD_SAFE
|
|
50
|
+
// Initialize the TaskScheduler request queue for thread-safe operations
|
|
51
|
+
if (!scheduler::initQueue()) {
|
|
52
|
+
Log(ERROR, "Failed to create TaskScheduler request queue\n");
|
|
53
|
+
}
|
|
54
|
+
#endif
|
|
44
55
|
#endif
|
|
45
56
|
|
|
46
57
|
// Add package handlers
|
|
@@ -541,7 +552,7 @@ class Mesh : public ntp::MeshTime, public plugin::PackageHandler<T> {
|
|
|
541
552
|
*/
|
|
542
553
|
bool semaphoreTake() {
|
|
543
554
|
#ifdef ESP32
|
|
544
|
-
return xSemaphoreTake(xSemaphore, (TickType_t)
|
|
555
|
+
return xSemaphoreTake(xSemaphore, (TickType_t)100) == pdTRUE; // Was 10
|
|
545
556
|
#else
|
|
546
557
|
return true;
|
|
547
558
|
#endif
|