@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.
Files changed (47) hide show
  1. package/CHANGELOG.md +84 -0
  2. package/docs/releases/PATCH_v1.7.2.md +262 -0
  3. package/docs/releases/PATCH_v1.7.4.md +219 -0
  4. package/docs/releases/RELEASE_CHECKLIST_v1.7.4.md +253 -0
  5. package/docs/releases/RELEASE_SUMMARY_v1.7.4.md +276 -0
  6. package/docs/releases/RELEASE_SUMMARY_v1.7.5.md +322 -0
  7. package/docs/troubleshooting/CRASH_QUICK_REF.md +93 -0
  8. package/docs/troubleshooting/FREERTOS_ASSERTION_FAILURE.md +288 -0
  9. package/docs/troubleshooting/FREERTOS_FIX_IMPLEMENTATION.md +267 -0
  10. package/docs/troubleshooting/QUICK_FIX_FREERTOS.md +164 -0
  11. package/docs/troubleshooting/SENSOR_NODE_CONNECTION_CRASH.md +264 -0
  12. package/examples/alteriom/platformio.ini +1 -0
  13. package/examples/alteriomImproved/improved_sensor_node.ino +2 -0
  14. package/examples/alteriomImproved/platformio.ini +7 -0
  15. package/examples/alteriomPhase1/platformio.ini +1 -0
  16. package/examples/alteriomPhase2/platformio.ini +1 -0
  17. package/examples/alteriomSensorNode/alteriom_sensor_node.ino +2 -0
  18. package/examples/alteriomSensorNode/platformio.ini +1 -0
  19. package/examples/basic/platformio.ini +1 -0
  20. package/examples/bridge/platformio.ini +1 -0
  21. package/examples/echoNode/platformio.ini +1 -0
  22. package/examples/logClient/platformio.ini +1 -0
  23. package/examples/logServer/platformio.ini +1 -0
  24. package/examples/meshCommandNode/meshCommandNode.ino +2 -0
  25. package/examples/meshCommandNode/platformio.ini +1 -0
  26. package/examples/mqttBridge/platformio.ini +1 -0
  27. package/examples/mqttCommandBridge/mesh_event_publisher.hpp +19 -19
  28. package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +18 -18
  29. package/examples/mqttCommandBridge/mqttCommandBridge.ino +3 -1
  30. package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +9 -6
  31. package/examples/mqttCommandBridge/platformio.ini +1 -0
  32. package/examples/mqttStatusBridge/mqttStatusBridge.ino +2 -0
  33. package/examples/mqttStatusBridge/platformio.ini +1 -0
  34. package/examples/mqttTopologyTest/mqttTopologyTest.ino +2 -0
  35. package/examples/mqttTopologyTest/platformio.ini +1 -0
  36. package/examples/namedMesh/platformio.ini +1 -0
  37. package/examples/otaReceiver/platformio.ini +1 -0
  38. package/examples/otaSender/platformio.ini +1 -0
  39. package/examples/startHere/platformio.ini +1 -0
  40. package/examples/webServer/platformio.ini +1 -0
  41. package/library.json +1 -1
  42. package/library.properties +1 -1
  43. package/package.json +1 -1
  44. package/src/painlessTaskOptions.h +18 -3
  45. package/src/painlessmesh/mesh.hpp +12 -1
  46. package/src/painlessmesh/scheduler_queue.cpp +77 -0
  47. 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
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  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
 
@@ -2,6 +2,7 @@
2
2
  src_dir = .
3
3
 
4
4
  [env]
5
+ lib_ldf_mode = deep+
5
6
  lib_deps =
6
7
  bblanchon/ArduinoJson
7
8
  arkhipenko/TaskScheduler
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -1,3 +1,5 @@
1
+ #include "painlessTaskOptions.h" // Must be first to configure TaskScheduler
2
+ #include <TaskScheduler.h> // Required for LDF to find TaskScheduler dependency
1
3
  #include "painlessMesh.h"
2
4
  #include "alteriom_sensor_package.hpp"
3
5
 
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -7,6 +7,7 @@ lib_deps =
7
7
  arkhipenko/TaskScheduler
8
8
  PubSubClient
9
9
 
10
+ lib_ldf_mode = deep+
10
11
  [env:esp8266]
11
12
  platform = espressif8266
12
13
  board = nodemcuv2
@@ -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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
57
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
58
58
  affected.add(generateDeviceId(nodeId));
59
59
 
60
- JsonObject details = doc.createNestedObject("details");
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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
86
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
87
87
  affected.add(generateDeviceId(nodeId));
88
88
 
89
- JsonObject details = doc.createNestedObject("details");
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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
114
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
115
115
  affected.add(generateDeviceId(nodeId));
116
116
 
117
- JsonObject details = doc.createNestedObject("details");
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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
141
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
142
142
  affected.add(generateDeviceId(nodeId));
143
143
 
144
- JsonObject details = doc.createNestedObject("details");
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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
167
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
168
168
  // TODO: Detect which nodes are in different partitions
169
169
 
170
- JsonObject details = doc.createNestedObject("details");
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
- DynamicJsonDocument doc(1024);
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.createNestedArray("affected_nodes");
194
+ JsonArray affected = doc["affected_nodes"].to<JsonArray>();
195
195
  // TODO: List nodes that rejoined
196
196
 
197
- JsonObject details = doc.createNestedObject("details");
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 DynamicJsonDocument& doc, const char* eventName) {
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
- DynamicJsonDocument doc(8192); // Large buffer for full topology
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.createNestedArray("nodes");
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.createNestedArray("connections");
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.createNestedObject("metrics");
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
- DynamicJsonDocument doc(2048);
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.createNestedArray("nodes");
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.createNestedObject();
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.createNestedArray("connections");
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.createNestedObject("metrics");
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.createNestedObject();
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.createNestedObject();
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.createNestedObject();
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
- DynamicJsonDocument status(512);
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.containsKey("respTo") && doc["respTo"] > 0) {
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.containsKey("deviceName")) {
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.containsKey("meshPrefix")) {
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
  }
@@ -7,6 +7,7 @@ lib_deps =
7
7
  arkhipenko/TaskScheduler
8
8
  knolleary/PubSubClient
9
9
 
10
+ lib_ldf_mode = deep+
10
11
  [env:esp8266]
11
12
  platform = espressif8266
12
13
  board = nodemcuv2
@@ -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>
@@ -7,6 +7,7 @@ lib_deps =
7
7
  arkhipenko/TaskScheduler
8
8
  knolleary/PubSubClient
9
9
 
10
+ lib_ldf_mode = deep+
10
11
  [env:esp8266]
11
12
  platform = espressif8266
12
13
  board = nodemcuv2
@@ -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>
@@ -7,6 +7,7 @@ lib_deps =
7
7
  arkhipenko/TaskScheduler
8
8
  knolleary/PubSubClient
9
9
 
10
+ lib_ldf_mode = deep+
10
11
  [env:esp8266]
11
12
  platform = espressif8266
12
13
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -6,6 +6,7 @@ lib_deps =
6
6
  bblanchon/ArduinoJson
7
7
  arkhipenko/TaskScheduler
8
8
 
9
+ lib_ldf_mode = deep+
9
10
  [env:esp8266]
10
11
  platform = espressif8266
11
12
  board = nodemcuv2
@@ -7,6 +7,7 @@ lib_deps =
7
7
  arkhipenko/TaskScheduler
8
8
  esp32async/ESPAsyncWebServer
9
9
 
10
+ lib_ldf_mode = deep+
10
11
  [env:esp8266]
11
12
  platform = espressif8266
12
13
  board = nodemcuv2
package/library.json CHANGED
@@ -6,7 +6,7 @@
6
6
  "type": "git",
7
7
  "url": "https://github.com/Alteriom/painlessMesh"
8
8
  },
9
- "version": "1.7.3",
9
+ "version": "1.7.5",
10
10
  "frameworks": ["arduino"],
11
11
  "platforms": ["espressif8266", "espressif32"],
12
12
  "srcDir": "src",
@@ -1,5 +1,5 @@
1
1
  name=AlteriomPainlessMesh
2
- version=1.7.3
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",
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 two complie options are required for painlessMesh
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
- // ONLY)
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)10) == pdTRUE;
555
+ return xSemaphoreTake(xSemaphore, (TickType_t)100) == pdTRUE; // Was 10
545
556
  #else
546
557
  return true;
547
558
  #endif