@alteriom/painlessmesh 1.6.1 → 1.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +380 -143
- package/LICENSE +674 -674
- package/README.md +477 -434
- package/RELEASE_GUIDE.md +504 -418
- package/docs/DOCUMENTATION_MIGRATION_PLAN.md +175 -175
- package/docs/IMPLEMENTATION_PLAN_MESH_TOPOLOGY.md +1062 -0
- package/docs/MESH_TOPOLOGY_GUIDE.md +992 -0
- package/docs/MESH_TOPOLOGY_PROGRESS.md +422 -0
- package/docs/MQTT_BRIDGE_COMMANDS.md +894 -0
- package/docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md +324 -0
- package/docs/MQTT_COMMAND_SCHEMA_PROPOSAL.md +576 -0
- package/docs/MQTT_SCHEMA_COMPLIANCE.md +285 -0
- package/docs/MQTT_SCHEMA_PROPOSALS.md +446 -0
- package/docs/MQTT_SCHEMA_REVIEW.md +690 -0
- package/docs/OTA_COMMANDS_REFERENCE.md +554 -0
- package/docs/PHASE1_GUIDE.md +349 -0
- package/docs/PHASE2_GUIDE.md +543 -0
- package/docs/README.md +77 -70
- package/docs/SCHEMA_VALIDATION_CHECKLIST.md +222 -0
- package/docs/alteriom/overview.md +507 -507
- package/docs/api/core-api.md +606 -606
- package/docs/architecture/mesh-architecture.md +378 -378
- package/docs/architecture/plugin-system.md +516 -516
- package/docs/getting-started/first-mesh.md +409 -409
- package/docs/getting-started/installation.md +274 -274
- package/docs/getting-started/quickstart.md +157 -157
- package/docs/improvements/FEATURE_PROPOSALS.md +337 -0
- package/docs/improvements/PHASE1_IMPLEMENTATION.md +325 -0
- package/docs/improvements/PHASE2_IMPLEMENTATION.md +567 -0
- package/docs/improvements/README.md +86 -68
- package/docs/improvements/ota-and-status-enhancements.md +911 -0
- package/docs/improvements/ota-status-architecture-diagrams.md +658 -0
- package/docs/improvements/ota-status-quick-reference.md +284 -0
- package/docs/platformio-publishing.md +255 -0
- package/docs/platformio-setup-summary.md +121 -0
- package/docs/troubleshooting/common-issues.md +520 -520
- package/docs/troubleshooting/faq.md +472 -472
- package/docs/tutorials/basic-examples.md +717 -717
- package/docs/wiki/API-Reference.md +245 -245
- package/docs/wiki/Complete-Documentation.md +122 -122
- package/examples/alteriom/README.md +139 -81
- package/examples/alteriom/alteriom.ino +186 -185
- package/examples/alteriom/alteriom_sensor_package.hpp +240 -127
- package/examples/alteriom/platformio.ini +24 -24
- package/examples/alteriomImproved/alteriom_sensor_package.hpp +224 -0
- package/examples/{alteriom → alteriomImproved}/improved_sensor_node.ino +245 -245
- package/examples/alteriomImproved/platformio.ini +25 -0
- package/examples/alteriomPhase1/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomPhase1/phase1_features.ino +242 -0
- package/examples/alteriomPhase1/platformio.ini +25 -0
- package/examples/alteriomPhase2/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomPhase2/phase2_features.ino +186 -0
- package/examples/alteriomPhase2/platformio.ini +25 -0
- package/examples/{alteriom → alteriomSensorNode}/alteriom_sensor_node.ino +183 -183
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +224 -0
- package/examples/alteriomSensorNode/platformio.ini +25 -0
- package/examples/basic/basic.ino +66 -66
- package/examples/basic/platformio.ini +25 -25
- package/examples/bridge/bridge.ino +51 -51
- package/examples/bridge/mesh_event_publisher.hpp +253 -0
- package/examples/bridge/mesh_topology_reporter.hpp +303 -0
- package/examples/bridge/mqtt_command_bridge.hpp +459 -0
- package/examples/bridge/mqtt_status_bridge.hpp +519 -0
- package/examples/bridge/platformio.ini +25 -25
- package/examples/echoNode/echoNode.ino +33 -33
- package/examples/echoNode/platformio.ini +25 -25
- package/examples/logClient/logClient.ino +109 -109
- package/examples/logClient/platformio.ini +25 -25
- package/examples/logServer/logServer.ino +81 -81
- package/examples/logServer/platformio.ini +25 -25
- package/examples/meshCommandNode/alteriom_sensor_package.hpp +235 -0
- package/examples/meshCommandNode/meshCommandNode.ino +263 -0
- package/examples/meshCommandNode/platformio.ini +25 -0
- package/examples/mqttBridge/mqttBridge.ino +118 -118
- package/examples/mqttBridge/platformio.ini +26 -26
- package/examples/mqttCommandBridge/alteriom_sensor_package.hpp +235 -0
- package/examples/mqttCommandBridge/mesh_event_publisher.hpp +253 -0
- package/examples/mqttCommandBridge/mesh_topology_reporter.hpp +303 -0
- package/examples/mqttCommandBridge/mqttCommandBridge.ino +252 -0
- package/examples/mqttCommandBridge/mqtt_command_bridge.hpp +459 -0
- package/examples/mqttCommandBridge/platformio.ini +26 -0
- package/examples/mqttStatusBridge/mqttStatusBridge.ino +216 -0
- package/examples/mqttStatusBridge/mqtt_status_bridge.hpp +522 -0
- package/examples/mqttStatusBridge/platformio.ini +26 -0
- package/examples/mqttTopologyTest/README.md +467 -0
- package/examples/mqttTopologyTest/mqttTopologyTest.ino +748 -0
- package/examples/mqttTopologyTest/platformio.ini +26 -0
- package/examples/namedMesh/namedMesh.ino +97 -97
- package/examples/namedMesh/platformio.ini +25 -25
- package/examples/otaReceiver/otaReceiver.ino +79 -79
- package/examples/otaReceiver/platformio.ini +25 -25
- package/examples/otaSender/otaSender.ino +160 -151
- package/examples/otaSender/platformio.ini +25 -25
- package/examples/startHere/platformio.ini +25 -25
- package/examples/startHere/startHere.ino +159 -159
- package/examples/webServer/platformio.ini +27 -27
- package/examples/webServer/webServer.ino +89 -89
- package/keywords.txt +48 -48
- package/library.json +55 -34
- package/library.properties +10 -10
- package/package.json +86 -78
- package/src/AlteriomPainlessMesh.h +97 -97
- package/src/arduino/wifi.hpp +365 -365
- package/src/boost/asynctcp.hpp +279 -279
- package/src/painlessMesh.h +70 -70
- package/src/painlessMeshSTA.cpp +236 -236
- package/src/painlessMeshSTA.h +58 -58
- package/src/painlessTaskOptions.h +4 -4
- package/src/painlessmesh/base64.hpp +111 -111
- package/src/painlessmesh/buffer.hpp +229 -229
- package/src/painlessmesh/callback.hpp +91 -91
- package/src/painlessmesh/configuration.hpp +77 -77
- package/src/painlessmesh/connection.hpp +192 -192
- package/src/painlessmesh/layout.hpp +188 -188
- package/src/painlessmesh/logger.hpp +158 -158
- package/src/painlessmesh/memory.hpp +119 -119
- package/src/painlessmesh/mesh.hpp +761 -560
- package/src/painlessmesh/metrics.hpp +322 -322
- package/src/painlessmesh/ntp.hpp +263 -263
- package/src/painlessmesh/ota.hpp +582 -553
- package/src/painlessmesh/plugin.hpp +188 -188
- package/src/painlessmesh/protocol.hpp +813 -813
- package/src/painlessmesh/router.hpp +322 -322
- package/src/painlessmesh/tcp.hpp +71 -71
- package/src/painlessmesh/validation.hpp +238 -238
- package/src/plugin/performance.hpp +214 -214
- package/src/plugin/remote.hpp +64 -64
- package/src/scheduler.cpp +10 -10
- package/src/wifi.cpp +2 -2
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
#ifndef _PAINLESS_MESH_CONFIGURATION_HPP_
|
|
2
|
-
#define _PAINLESS_MESH_CONFIGURATION_HPP_
|
|
3
|
-
|
|
4
|
-
// Include Arduino.h in test environment to ensure TSTRING is defined
|
|
5
|
-
#if defined(PAINLESSMESH_BOOST) || defined(ARDUINO_ARCH_ESP8266) || \
|
|
6
|
-
defined(ARDUINO_ARCH_ESP32)
|
|
7
|
-
#ifndef ARDUINO
|
|
8
|
-
#include "Arduino.h"
|
|
9
|
-
#endif
|
|
10
|
-
#endif
|
|
11
|
-
|
|
12
|
-
#include <list>
|
|
13
|
-
|
|
14
|
-
#include "painlessTaskOptions.h"
|
|
15
|
-
|
|
16
|
-
#include <TaskSchedulerDeclarations.h>
|
|
17
|
-
|
|
18
|
-
#define ARDUINOJSON_USE_LONG_LONG 1
|
|
19
|
-
#undef ARDUINOJSON_ENABLE_STD_STRING
|
|
20
|
-
#include <ArduinoJson.h>
|
|
21
|
-
#undef ARDUINOJSON_ENABLE_STD_STRING
|
|
22
|
-
|
|
23
|
-
// Enable (arduino) wifi support
|
|
24
|
-
#define PAINLESSMESH_ENABLE_ARDUINO_WIFI
|
|
25
|
-
|
|
26
|
-
// Enable OTA support
|
|
27
|
-
#define PAINLESSMESH_ENABLE_OTA
|
|
28
|
-
|
|
29
|
-
// Minimum free memory, besides here all packets in queue are discarded.
|
|
30
|
-
#define MIN_FREE_MEMORY 4000
|
|
31
|
-
// MAX number of unsent messages in queue. Newer messages are discarded
|
|
32
|
-
#define MAX_MESSAGE_QUEUE 50
|
|
33
|
-
|
|
34
|
-
#define NODE_TIMEOUT 10 * TASK_SECOND
|
|
35
|
-
#define SCAN_INTERVAL 30 * TASK_SECOND // AP scan period in ms
|
|
36
|
-
|
|
37
|
-
#ifdef ESP32
|
|
38
|
-
#include <AsyncTCP.h>
|
|
39
|
-
#include <WiFi.h>
|
|
40
|
-
#if ESP_ARDUINO_VERSION_MAJOR >= 3
|
|
41
|
-
#include "esp_mac.h" // required for core 3.x - exposes esp_mac_type_t values
|
|
42
|
-
#endif
|
|
43
|
-
#elif defined(ESP8266)
|
|
44
|
-
#include <ESP8266WiFi.h>
|
|
45
|
-
#include <ESPAsyncTCP.h>
|
|
46
|
-
#endif // ESP32
|
|
47
|
-
|
|
48
|
-
// Define TSTRING - use std::string in test environment, Arduino String
|
|
49
|
-
// otherwise
|
|
50
|
-
#if defined(PAINLESSMESH_BOOST)
|
|
51
|
-
// Test environment - TSTRING already defined in test Arduino.h as std::string
|
|
52
|
-
#else
|
|
53
|
-
typedef String TSTRING;
|
|
54
|
-
#endif
|
|
55
|
-
|
|
56
|
-
// backward compatibility
|
|
57
|
-
template <typename T>
|
|
58
|
-
using SimpleList = std::list<T>;
|
|
59
|
-
|
|
60
|
-
namespace painlessmesh {
|
|
61
|
-
namespace wifi {
|
|
62
|
-
class Mesh;
|
|
63
|
-
};
|
|
64
|
-
}; // namespace painlessmesh
|
|
65
|
-
|
|
66
|
-
/** A convenience typedef to access the mesh class*/
|
|
67
|
-
#ifdef PAINLESSMESH_ENABLE_ARDUINO_WIFI
|
|
68
|
-
using painlessMesh = painlessmesh::wifi::Mesh;
|
|
69
|
-
#endif
|
|
70
|
-
|
|
71
|
-
#ifdef ESP32
|
|
72
|
-
#define MAX_CONN 10
|
|
73
|
-
#else
|
|
74
|
-
#define MAX_CONN 4
|
|
75
|
-
#endif // DEBUG
|
|
76
|
-
|
|
77
|
-
#endif
|
|
1
|
+
#ifndef _PAINLESS_MESH_CONFIGURATION_HPP_
|
|
2
|
+
#define _PAINLESS_MESH_CONFIGURATION_HPP_
|
|
3
|
+
|
|
4
|
+
// Include Arduino.h in test environment to ensure TSTRING is defined
|
|
5
|
+
#if defined(PAINLESSMESH_BOOST) || defined(ARDUINO_ARCH_ESP8266) || \
|
|
6
|
+
defined(ARDUINO_ARCH_ESP32)
|
|
7
|
+
#ifndef ARDUINO
|
|
8
|
+
#include "Arduino.h"
|
|
9
|
+
#endif
|
|
10
|
+
#endif
|
|
11
|
+
|
|
12
|
+
#include <list>
|
|
13
|
+
|
|
14
|
+
#include "painlessTaskOptions.h"
|
|
15
|
+
|
|
16
|
+
#include <TaskSchedulerDeclarations.h>
|
|
17
|
+
|
|
18
|
+
#define ARDUINOJSON_USE_LONG_LONG 1
|
|
19
|
+
#undef ARDUINOJSON_ENABLE_STD_STRING
|
|
20
|
+
#include <ArduinoJson.h>
|
|
21
|
+
#undef ARDUINOJSON_ENABLE_STD_STRING
|
|
22
|
+
|
|
23
|
+
// Enable (arduino) wifi support
|
|
24
|
+
#define PAINLESSMESH_ENABLE_ARDUINO_WIFI
|
|
25
|
+
|
|
26
|
+
// Enable OTA support
|
|
27
|
+
#define PAINLESSMESH_ENABLE_OTA
|
|
28
|
+
|
|
29
|
+
// Minimum free memory, besides here all packets in queue are discarded.
|
|
30
|
+
#define MIN_FREE_MEMORY 4000
|
|
31
|
+
// MAX number of unsent messages in queue. Newer messages are discarded
|
|
32
|
+
#define MAX_MESSAGE_QUEUE 50
|
|
33
|
+
|
|
34
|
+
#define NODE_TIMEOUT 10 * TASK_SECOND
|
|
35
|
+
#define SCAN_INTERVAL 30 * TASK_SECOND // AP scan period in ms
|
|
36
|
+
|
|
37
|
+
#ifdef ESP32
|
|
38
|
+
#include <AsyncTCP.h>
|
|
39
|
+
#include <WiFi.h>
|
|
40
|
+
#if ESP_ARDUINO_VERSION_MAJOR >= 3
|
|
41
|
+
#include "esp_mac.h" // required for core 3.x - exposes esp_mac_type_t values
|
|
42
|
+
#endif
|
|
43
|
+
#elif defined(ESP8266)
|
|
44
|
+
#include <ESP8266WiFi.h>
|
|
45
|
+
#include <ESPAsyncTCP.h>
|
|
46
|
+
#endif // ESP32
|
|
47
|
+
|
|
48
|
+
// Define TSTRING - use std::string in test environment, Arduino String
|
|
49
|
+
// otherwise
|
|
50
|
+
#if defined(PAINLESSMESH_BOOST)
|
|
51
|
+
// Test environment - TSTRING already defined in test Arduino.h as std::string
|
|
52
|
+
#else
|
|
53
|
+
typedef String TSTRING;
|
|
54
|
+
#endif
|
|
55
|
+
|
|
56
|
+
// backward compatibility
|
|
57
|
+
template <typename T>
|
|
58
|
+
using SimpleList = std::list<T>;
|
|
59
|
+
|
|
60
|
+
namespace painlessmesh {
|
|
61
|
+
namespace wifi {
|
|
62
|
+
class Mesh;
|
|
63
|
+
};
|
|
64
|
+
}; // namespace painlessmesh
|
|
65
|
+
|
|
66
|
+
/** A convenience typedef to access the mesh class*/
|
|
67
|
+
#ifdef PAINLESSMESH_ENABLE_ARDUINO_WIFI
|
|
68
|
+
using painlessMesh = painlessmesh::wifi::Mesh;
|
|
69
|
+
#endif
|
|
70
|
+
|
|
71
|
+
#ifdef ESP32
|
|
72
|
+
#define MAX_CONN 10
|
|
73
|
+
#else
|
|
74
|
+
#define MAX_CONN 4
|
|
75
|
+
#endif // DEBUG
|
|
76
|
+
|
|
77
|
+
#endif
|
|
@@ -1,192 +1,192 @@
|
|
|
1
|
-
#ifndef _PAINLESS_MESH_CONNECTION_HPP_
|
|
2
|
-
#define _PAINLESS_MESH_CONNECTION_HPP_
|
|
3
|
-
|
|
4
|
-
#include <memory>
|
|
5
|
-
|
|
6
|
-
#include "Arduino.h"
|
|
7
|
-
#include "painlessmesh/configuration.hpp"
|
|
8
|
-
|
|
9
|
-
#include "painlessmesh/buffer.hpp"
|
|
10
|
-
#include "painlessmesh/logger.hpp"
|
|
11
|
-
|
|
12
|
-
extern painlessmesh::logger::LogClass Log;
|
|
13
|
-
|
|
14
|
-
namespace painlessmesh {
|
|
15
|
-
namespace tcp {
|
|
16
|
-
|
|
17
|
-
// Shared buffer for reading/writing to the buffer
|
|
18
|
-
static painlessmesh::buffer::temp_buffer_t shared_buffer;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Class that performs buffered read and write to the tcp connection
|
|
22
|
-
* (asyncclient)
|
|
23
|
-
*
|
|
24
|
-
* Note that the class expects to be wrapped in a shared_ptr to ensure proper
|
|
25
|
-
* lifetime management. Objects generally will only be destroyed after close is
|
|
26
|
-
* called (and the reading and writing tasks are stopped).
|
|
27
|
-
*/
|
|
28
|
-
class BufferedConnection
|
|
29
|
-
: public std::enable_shared_from_this<BufferedConnection> {
|
|
30
|
-
public:
|
|
31
|
-
/**
|
|
32
|
-
* Create a buffered connection around the client
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* BufferedConnection takes ownership of the client and will delete the
|
|
36
|
-
* pointer at the end.
|
|
37
|
-
*
|
|
38
|
-
* One should always call initialize after construction
|
|
39
|
-
*/
|
|
40
|
-
BufferedConnection(AsyncClient *client) : client(client) {}
|
|
41
|
-
|
|
42
|
-
~BufferedConnection() {
|
|
43
|
-
Log.remote("~BufferedConnection");
|
|
44
|
-
this->close();
|
|
45
|
-
if (!client->freeable()) {
|
|
46
|
-
client->close(true);
|
|
47
|
-
}
|
|
48
|
-
client->abort();
|
|
49
|
-
delete client;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
void initialize(Scheduler *scheduler) {
|
|
53
|
-
auto self = this->shared_from_this();
|
|
54
|
-
sentBufferTask.set(TASK_SECOND, TASK_FOREVER, [self]() {
|
|
55
|
-
if (!self->sentBuffer.empty() && self->client->canSend()) {
|
|
56
|
-
auto ret = self->writeNext();
|
|
57
|
-
if (ret)
|
|
58
|
-
self->sentBufferTask.forceNextIteration();
|
|
59
|
-
else
|
|
60
|
-
self->sentBufferTask.delay(100 * TASK_MILLISECOND);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
scheduler->addTask(sentBufferTask);
|
|
64
|
-
sentBufferTask.enableDelayed();
|
|
65
|
-
|
|
66
|
-
readBufferTask.set(TASK_SECOND, TASK_FOREVER, [self]() {
|
|
67
|
-
if (!self->receiveBuffer.empty()) {
|
|
68
|
-
TSTRING frnt = self->receiveBuffer.front();
|
|
69
|
-
self->receiveBuffer.pop_front();
|
|
70
|
-
if (!self->receiveBuffer.empty())
|
|
71
|
-
self->readBufferTask.forceNextIteration();
|
|
72
|
-
if (self->receiveCallback) self->receiveCallback(frnt);
|
|
73
|
-
}
|
|
74
|
-
});
|
|
75
|
-
scheduler->addTask(readBufferTask);
|
|
76
|
-
readBufferTask.enableDelayed();
|
|
77
|
-
|
|
78
|
-
client->onAck(
|
|
79
|
-
[self](void *arg, AsyncClient *client, size_t len, uint32_t time) {
|
|
80
|
-
self->sentBufferTask.forceNextIteration();
|
|
81
|
-
},
|
|
82
|
-
NULL);
|
|
83
|
-
|
|
84
|
-
client->onData(
|
|
85
|
-
[self](void *arg, AsyncClient *client, void *data, size_t len) {
|
|
86
|
-
self->receiveBuffer.push(static_cast<const char *>(data), len,
|
|
87
|
-
shared_buffer);
|
|
88
|
-
// Signal that we are done
|
|
89
|
-
self->client->ack(len);
|
|
90
|
-
self->readBufferTask.forceNextIteration();
|
|
91
|
-
},
|
|
92
|
-
NULL);
|
|
93
|
-
|
|
94
|
-
client->onDisconnect(
|
|
95
|
-
[self](void *arg, AsyncClient *client) { self->close(); }, NULL);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
void close() {
|
|
99
|
-
if (!mConnected) return;
|
|
100
|
-
|
|
101
|
-
// Disable tasks and callbacks
|
|
102
|
-
this->sentBufferTask.setCallback(NULL);
|
|
103
|
-
this->sentBufferTask.disable();
|
|
104
|
-
this->readBufferTask.setCallback(NULL);
|
|
105
|
-
this->readBufferTask.disable();
|
|
106
|
-
|
|
107
|
-
this->client->onData(NULL, NULL);
|
|
108
|
-
this->client->onAck(NULL, NULL);
|
|
109
|
-
this->client->onDisconnect(NULL, NULL);
|
|
110
|
-
this->client->onError(NULL, NULL);
|
|
111
|
-
|
|
112
|
-
if (client->connected()) {
|
|
113
|
-
client->close();
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
receiveBuffer.clear();
|
|
117
|
-
sentBuffer.clear();
|
|
118
|
-
|
|
119
|
-
if (disconnectCallback) disconnectCallback();
|
|
120
|
-
|
|
121
|
-
receiveCallback = NULL;
|
|
122
|
-
disconnectCallback = NULL;
|
|
123
|
-
|
|
124
|
-
mConnected = false;
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
bool write(const TSTRING &data, bool priority = false) {
|
|
128
|
-
sentBuffer.push(data, priority);
|
|
129
|
-
sentBufferTask.forceNextIteration();
|
|
130
|
-
return true;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
void onDisconnect(std::function<void()> callback) {
|
|
134
|
-
disconnectCallback = callback;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
void onReceive(std::function<void(TSTRING)> callback) {
|
|
138
|
-
receiveCallback = callback;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
bool connected() { return mConnected; }
|
|
142
|
-
|
|
143
|
-
protected:
|
|
144
|
-
bool mConnected = true;
|
|
145
|
-
|
|
146
|
-
AsyncClient *client;
|
|
147
|
-
|
|
148
|
-
std::function<void(TSTRING)> receiveCallback;
|
|
149
|
-
std::function<void()> disconnectCallback;
|
|
150
|
-
|
|
151
|
-
painlessmesh::buffer::ReceiveBuffer<TSTRING> receiveBuffer;
|
|
152
|
-
painlessmesh::buffer::SentBuffer<TSTRING> sentBuffer;
|
|
153
|
-
|
|
154
|
-
bool writeNext() {
|
|
155
|
-
if (sentBuffer.empty()) {
|
|
156
|
-
return false;
|
|
157
|
-
}
|
|
158
|
-
auto len = sentBuffer.requestLength(shared_buffer.length);
|
|
159
|
-
auto snd_len = client->space();
|
|
160
|
-
if (len > snd_len) len = snd_len;
|
|
161
|
-
if (len > 0) {
|
|
162
|
-
// sentBuffer.read(len, shared_buffer);
|
|
163
|
-
// auto written = client->write(shared_buffer.buffer, len, 1);
|
|
164
|
-
auto data_ptr = sentBuffer.readPtr(len);
|
|
165
|
-
auto written = client->write(data_ptr, len, 1);
|
|
166
|
-
if (written == len) {
|
|
167
|
-
client->send(); // TODO only do this for priority messages
|
|
168
|
-
sentBuffer.freeRead();
|
|
169
|
-
sentBufferTask.forceNextIteration();
|
|
170
|
-
return true;
|
|
171
|
-
} else if (written == 0) {
|
|
172
|
-
return false;
|
|
173
|
-
} else {
|
|
174
|
-
return false;
|
|
175
|
-
}
|
|
176
|
-
} else {
|
|
177
|
-
return false;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
Task sentBufferTask;
|
|
182
|
-
Task readBufferTask;
|
|
183
|
-
|
|
184
|
-
template <typename T>
|
|
185
|
-
std::shared_ptr<T> shared_from(T *derived) {
|
|
186
|
-
return std::static_pointer_cast<T>(shared_from_this());
|
|
187
|
-
}
|
|
188
|
-
}; // namespace tcp
|
|
189
|
-
}; // namespace tcp
|
|
190
|
-
}; // namespace painlessmesh
|
|
191
|
-
|
|
192
|
-
#endif
|
|
1
|
+
#ifndef _PAINLESS_MESH_CONNECTION_HPP_
|
|
2
|
+
#define _PAINLESS_MESH_CONNECTION_HPP_
|
|
3
|
+
|
|
4
|
+
#include <memory>
|
|
5
|
+
|
|
6
|
+
#include "Arduino.h"
|
|
7
|
+
#include "painlessmesh/configuration.hpp"
|
|
8
|
+
|
|
9
|
+
#include "painlessmesh/buffer.hpp"
|
|
10
|
+
#include "painlessmesh/logger.hpp"
|
|
11
|
+
|
|
12
|
+
extern painlessmesh::logger::LogClass Log;
|
|
13
|
+
|
|
14
|
+
namespace painlessmesh {
|
|
15
|
+
namespace tcp {
|
|
16
|
+
|
|
17
|
+
// Shared buffer for reading/writing to the buffer
|
|
18
|
+
static painlessmesh::buffer::temp_buffer_t shared_buffer;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Class that performs buffered read and write to the tcp connection
|
|
22
|
+
* (asyncclient)
|
|
23
|
+
*
|
|
24
|
+
* Note that the class expects to be wrapped in a shared_ptr to ensure proper
|
|
25
|
+
* lifetime management. Objects generally will only be destroyed after close is
|
|
26
|
+
* called (and the reading and writing tasks are stopped).
|
|
27
|
+
*/
|
|
28
|
+
class BufferedConnection
|
|
29
|
+
: public std::enable_shared_from_this<BufferedConnection> {
|
|
30
|
+
public:
|
|
31
|
+
/**
|
|
32
|
+
* Create a buffered connection around the client
|
|
33
|
+
*
|
|
34
|
+
*
|
|
35
|
+
* BufferedConnection takes ownership of the client and will delete the
|
|
36
|
+
* pointer at the end.
|
|
37
|
+
*
|
|
38
|
+
* One should always call initialize after construction
|
|
39
|
+
*/
|
|
40
|
+
BufferedConnection(AsyncClient *client) : client(client) {}
|
|
41
|
+
|
|
42
|
+
~BufferedConnection() {
|
|
43
|
+
Log.remote("~BufferedConnection");
|
|
44
|
+
this->close();
|
|
45
|
+
if (!client->freeable()) {
|
|
46
|
+
client->close(true);
|
|
47
|
+
}
|
|
48
|
+
client->abort();
|
|
49
|
+
delete client;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
void initialize(Scheduler *scheduler) {
|
|
53
|
+
auto self = this->shared_from_this();
|
|
54
|
+
sentBufferTask.set(TASK_SECOND, TASK_FOREVER, [self]() {
|
|
55
|
+
if (!self->sentBuffer.empty() && self->client->canSend()) {
|
|
56
|
+
auto ret = self->writeNext();
|
|
57
|
+
if (ret)
|
|
58
|
+
self->sentBufferTask.forceNextIteration();
|
|
59
|
+
else
|
|
60
|
+
self->sentBufferTask.delay(100 * TASK_MILLISECOND);
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
scheduler->addTask(sentBufferTask);
|
|
64
|
+
sentBufferTask.enableDelayed();
|
|
65
|
+
|
|
66
|
+
readBufferTask.set(TASK_SECOND, TASK_FOREVER, [self]() {
|
|
67
|
+
if (!self->receiveBuffer.empty()) {
|
|
68
|
+
TSTRING frnt = self->receiveBuffer.front();
|
|
69
|
+
self->receiveBuffer.pop_front();
|
|
70
|
+
if (!self->receiveBuffer.empty())
|
|
71
|
+
self->readBufferTask.forceNextIteration();
|
|
72
|
+
if (self->receiveCallback) self->receiveCallback(frnt);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
scheduler->addTask(readBufferTask);
|
|
76
|
+
readBufferTask.enableDelayed();
|
|
77
|
+
|
|
78
|
+
client->onAck(
|
|
79
|
+
[self](void *arg, AsyncClient *client, size_t len, uint32_t time) {
|
|
80
|
+
self->sentBufferTask.forceNextIteration();
|
|
81
|
+
},
|
|
82
|
+
NULL);
|
|
83
|
+
|
|
84
|
+
client->onData(
|
|
85
|
+
[self](void *arg, AsyncClient *client, void *data, size_t len) {
|
|
86
|
+
self->receiveBuffer.push(static_cast<const char *>(data), len,
|
|
87
|
+
shared_buffer);
|
|
88
|
+
// Signal that we are done
|
|
89
|
+
self->client->ack(len);
|
|
90
|
+
self->readBufferTask.forceNextIteration();
|
|
91
|
+
},
|
|
92
|
+
NULL);
|
|
93
|
+
|
|
94
|
+
client->onDisconnect(
|
|
95
|
+
[self](void *arg, AsyncClient *client) { self->close(); }, NULL);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
void close() {
|
|
99
|
+
if (!mConnected) return;
|
|
100
|
+
|
|
101
|
+
// Disable tasks and callbacks
|
|
102
|
+
this->sentBufferTask.setCallback(NULL);
|
|
103
|
+
this->sentBufferTask.disable();
|
|
104
|
+
this->readBufferTask.setCallback(NULL);
|
|
105
|
+
this->readBufferTask.disable();
|
|
106
|
+
|
|
107
|
+
this->client->onData(NULL, NULL);
|
|
108
|
+
this->client->onAck(NULL, NULL);
|
|
109
|
+
this->client->onDisconnect(NULL, NULL);
|
|
110
|
+
this->client->onError(NULL, NULL);
|
|
111
|
+
|
|
112
|
+
if (client->connected()) {
|
|
113
|
+
client->close();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
receiveBuffer.clear();
|
|
117
|
+
sentBuffer.clear();
|
|
118
|
+
|
|
119
|
+
if (disconnectCallback) disconnectCallback();
|
|
120
|
+
|
|
121
|
+
receiveCallback = NULL;
|
|
122
|
+
disconnectCallback = NULL;
|
|
123
|
+
|
|
124
|
+
mConnected = false;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
bool write(const TSTRING &data, bool priority = false) {
|
|
128
|
+
sentBuffer.push(data, priority);
|
|
129
|
+
sentBufferTask.forceNextIteration();
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
void onDisconnect(std::function<void()> callback) {
|
|
134
|
+
disconnectCallback = callback;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
void onReceive(std::function<void(TSTRING)> callback) {
|
|
138
|
+
receiveCallback = callback;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
bool connected() { return mConnected; }
|
|
142
|
+
|
|
143
|
+
protected:
|
|
144
|
+
bool mConnected = true;
|
|
145
|
+
|
|
146
|
+
AsyncClient *client;
|
|
147
|
+
|
|
148
|
+
std::function<void(TSTRING)> receiveCallback;
|
|
149
|
+
std::function<void()> disconnectCallback;
|
|
150
|
+
|
|
151
|
+
painlessmesh::buffer::ReceiveBuffer<TSTRING> receiveBuffer;
|
|
152
|
+
painlessmesh::buffer::SentBuffer<TSTRING> sentBuffer;
|
|
153
|
+
|
|
154
|
+
bool writeNext() {
|
|
155
|
+
if (sentBuffer.empty()) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
auto len = sentBuffer.requestLength(shared_buffer.length);
|
|
159
|
+
auto snd_len = client->space();
|
|
160
|
+
if (len > snd_len) len = snd_len;
|
|
161
|
+
if (len > 0) {
|
|
162
|
+
// sentBuffer.read(len, shared_buffer);
|
|
163
|
+
// auto written = client->write(shared_buffer.buffer, len, 1);
|
|
164
|
+
auto data_ptr = sentBuffer.readPtr(len);
|
|
165
|
+
auto written = client->write(data_ptr, len, 1);
|
|
166
|
+
if (written == len) {
|
|
167
|
+
client->send(); // TODO only do this for priority messages
|
|
168
|
+
sentBuffer.freeRead();
|
|
169
|
+
sentBufferTask.forceNextIteration();
|
|
170
|
+
return true;
|
|
171
|
+
} else if (written == 0) {
|
|
172
|
+
return false;
|
|
173
|
+
} else {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
} else {
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
Task sentBufferTask;
|
|
182
|
+
Task readBufferTask;
|
|
183
|
+
|
|
184
|
+
template <typename T>
|
|
185
|
+
std::shared_ptr<T> shared_from(T *derived) {
|
|
186
|
+
return std::static_pointer_cast<T>(shared_from_this());
|
|
187
|
+
}
|
|
188
|
+
}; // namespace tcp
|
|
189
|
+
}; // namespace tcp
|
|
190
|
+
}; // namespace painlessmesh
|
|
191
|
+
|
|
192
|
+
#endif
|