@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,188 +1,188 @@
|
|
|
1
|
-
#ifndef _PAINLESS_MESH_LAYOUT_HPP_
|
|
2
|
-
#define _PAINLESS_MESH_LAYOUT_HPP_
|
|
3
|
-
|
|
4
|
-
#include <list>
|
|
5
|
-
#include <memory>
|
|
6
|
-
|
|
7
|
-
#include "painlessmesh/protocol.hpp"
|
|
8
|
-
|
|
9
|
-
namespace painlessmesh {
|
|
10
|
-
namespace layout {
|
|
11
|
-
|
|
12
|
-
#include <memory>
|
|
13
|
-
/**
|
|
14
|
-
* Whether the tree contains the given nodeId
|
|
15
|
-
*/
|
|
16
|
-
inline bool contains(protocol::NodeTree nodeTree, uint32_t nodeId) {
|
|
17
|
-
if (nodeTree.nodeId == nodeId) {
|
|
18
|
-
return true;
|
|
19
|
-
}
|
|
20
|
-
for (auto&& s : nodeTree.subs) {
|
|
21
|
-
if (contains(s, nodeId)) return true;
|
|
22
|
-
}
|
|
23
|
-
return false;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
inline protocol::NodeTree excludeRoute(protocol::NodeTree&& tree,
|
|
27
|
-
uint32_t exclude) {
|
|
28
|
-
// Make sure to exclude any subs with nodeId == 0,
|
|
29
|
-
// even if exlude is not set to zero
|
|
30
|
-
tree.subs.remove_if([exclude](protocol::NodeTree s) {
|
|
31
|
-
return s.nodeId == 0 || s.nodeId == exclude;
|
|
32
|
-
});
|
|
33
|
-
return tree;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
template <class T>
|
|
37
|
-
class Layout {
|
|
38
|
-
public:
|
|
39
|
-
size_t stability = 0;
|
|
40
|
-
std::list<std::shared_ptr<T> > subs;
|
|
41
|
-
|
|
42
|
-
/** Return the nodeId of the node that we are running on.
|
|
43
|
-
*
|
|
44
|
-
* On the ESP hardware nodeId is uniquely calculated from the MAC address of
|
|
45
|
-
* the node.
|
|
46
|
-
*/
|
|
47
|
-
uint32_t getNodeId() { return nodeId; }
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Check whether this node is a root node.
|
|
51
|
-
*/
|
|
52
|
-
bool isRoot() { return root; }
|
|
53
|
-
|
|
54
|
-
protocol::NodeTree asNodeTree() {
|
|
55
|
-
auto nt = protocol::NodeTree(nodeId, root);
|
|
56
|
-
for (auto&& s : subs) {
|
|
57
|
-
if (s->nodeId == 0) continue;
|
|
58
|
-
nt.subs.push_back(protocol::NodeTree(*s));
|
|
59
|
-
}
|
|
60
|
-
return nt;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
protected:
|
|
64
|
-
uint32_t nodeId = 0;
|
|
65
|
-
bool root = false;
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
template <class T>
|
|
69
|
-
void syncLayout(Layout<T>& layout, uint32_t changedId) {
|
|
70
|
-
// TODO: this should be called from changed connections and dropped
|
|
71
|
-
// connections events
|
|
72
|
-
for (auto&& sub : layout.subs) {
|
|
73
|
-
if (sub->connected() && !sub->newConnection && sub->nodeId != 0 &&
|
|
74
|
-
sub->nodeId != changedId) { // Exclude current
|
|
75
|
-
sub->nodeSyncTask.forceNextIteration();
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
layout.stability /= 2;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
class Neighbour : public protocol::NodeTree {
|
|
82
|
-
public:
|
|
83
|
-
// Inherit constructors
|
|
84
|
-
using protocol::NodeTree::NodeTree;
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Is the passed nodesync valid
|
|
88
|
-
*
|
|
89
|
-
* If not then the caller of this function should probably disconnect
|
|
90
|
-
* this neighbour.
|
|
91
|
-
*/
|
|
92
|
-
bool validSubs(protocol::NodeTree tree) {
|
|
93
|
-
if (nodeId == 0) // Cant really know, so valid as far as we know
|
|
94
|
-
return true;
|
|
95
|
-
if (nodeId != tree.nodeId) return false;
|
|
96
|
-
for (auto&& s : tree.subs) {
|
|
97
|
-
if (layout::contains(s, nodeId)) return false;
|
|
98
|
-
}
|
|
99
|
-
return true;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Update subs with the new subs
|
|
104
|
-
*
|
|
105
|
-
* \param tree The possible new tree with this node as base
|
|
106
|
-
*
|
|
107
|
-
* Generally one probably wants to call validSubs before calling this
|
|
108
|
-
* function.
|
|
109
|
-
*
|
|
110
|
-
* \return Whether we adopted the new tree
|
|
111
|
-
*/
|
|
112
|
-
bool updateSubs(protocol::NodeTree tree) {
|
|
113
|
-
if (nodeId == 0 || tree != (*this)) {
|
|
114
|
-
nodeId = tree.nodeId;
|
|
115
|
-
subs = tree.subs;
|
|
116
|
-
root = tree.root;
|
|
117
|
-
return true;
|
|
118
|
-
}
|
|
119
|
-
return false;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* Create a request
|
|
124
|
-
*/
|
|
125
|
-
protocol::NodeSyncRequest request(NodeTree&& layout) {
|
|
126
|
-
auto subTree = excludeRoute(std::move(layout), nodeId);
|
|
127
|
-
return protocol::NodeSyncRequest(subTree.nodeId, nodeId, subTree.subs,
|
|
128
|
-
subTree.root);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/**
|
|
132
|
-
* Create a reply
|
|
133
|
-
*/
|
|
134
|
-
protocol::NodeSyncReply reply(NodeTree&& layout) {
|
|
135
|
-
auto subTree = excludeRoute(std::move(layout), nodeId);
|
|
136
|
-
return protocol::NodeSyncReply(subTree.nodeId, nodeId, subTree.subs,
|
|
137
|
-
subTree.root);
|
|
138
|
-
}
|
|
139
|
-
};
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* The size of the mesh (the number of nodes)
|
|
143
|
-
*/
|
|
144
|
-
inline uint32_t size(protocol::NodeTree nodeTree) {
|
|
145
|
-
auto no = 1;
|
|
146
|
-
for (auto&& s : nodeTree.subs) {
|
|
147
|
-
no += size(s);
|
|
148
|
-
}
|
|
149
|
-
return no;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Whether the top node in the tree is also the root of the mesh
|
|
154
|
-
*/
|
|
155
|
-
inline bool isRoot(protocol::NodeTree nodeTree) {
|
|
156
|
-
if (nodeTree.root) return true;
|
|
157
|
-
return false;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
/**
|
|
161
|
-
* Whether any node in the tree is also root of the mesh
|
|
162
|
-
*/
|
|
163
|
-
inline bool isRooted(protocol::NodeTree nodeTree) {
|
|
164
|
-
if (isRoot(nodeTree)) return true;
|
|
165
|
-
for (auto&& s : nodeTree.subs) {
|
|
166
|
-
if (isRooted(s)) return true;
|
|
167
|
-
}
|
|
168
|
-
return false;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
/**
|
|
172
|
-
* Return all nodes in a list container
|
|
173
|
-
*/
|
|
174
|
-
inline std::list<uint32_t> asList(protocol::NodeTree nodeTree,
|
|
175
|
-
bool includeSelf = true) {
|
|
176
|
-
std::list<uint32_t> lst;
|
|
177
|
-
if (includeSelf) lst.push_back(nodeTree.nodeId);
|
|
178
|
-
for (auto&& s : nodeTree.subs) {
|
|
179
|
-
lst.splice(lst.end(), asList(s));
|
|
180
|
-
}
|
|
181
|
-
return lst;
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
} // namespace layout
|
|
185
|
-
} // namespace painlessmesh
|
|
186
|
-
|
|
187
|
-
#endif
|
|
188
|
-
|
|
1
|
+
#ifndef _PAINLESS_MESH_LAYOUT_HPP_
|
|
2
|
+
#define _PAINLESS_MESH_LAYOUT_HPP_
|
|
3
|
+
|
|
4
|
+
#include <list>
|
|
5
|
+
#include <memory>
|
|
6
|
+
|
|
7
|
+
#include "painlessmesh/protocol.hpp"
|
|
8
|
+
|
|
9
|
+
namespace painlessmesh {
|
|
10
|
+
namespace layout {
|
|
11
|
+
|
|
12
|
+
#include <memory>
|
|
13
|
+
/**
|
|
14
|
+
* Whether the tree contains the given nodeId
|
|
15
|
+
*/
|
|
16
|
+
inline bool contains(protocol::NodeTree nodeTree, uint32_t nodeId) {
|
|
17
|
+
if (nodeTree.nodeId == nodeId) {
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
for (auto&& s : nodeTree.subs) {
|
|
21
|
+
if (contains(s, nodeId)) return true;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
inline protocol::NodeTree excludeRoute(protocol::NodeTree&& tree,
|
|
27
|
+
uint32_t exclude) {
|
|
28
|
+
// Make sure to exclude any subs with nodeId == 0,
|
|
29
|
+
// even if exlude is not set to zero
|
|
30
|
+
tree.subs.remove_if([exclude](protocol::NodeTree s) {
|
|
31
|
+
return s.nodeId == 0 || s.nodeId == exclude;
|
|
32
|
+
});
|
|
33
|
+
return tree;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
template <class T>
|
|
37
|
+
class Layout {
|
|
38
|
+
public:
|
|
39
|
+
size_t stability = 0;
|
|
40
|
+
std::list<std::shared_ptr<T> > subs;
|
|
41
|
+
|
|
42
|
+
/** Return the nodeId of the node that we are running on.
|
|
43
|
+
*
|
|
44
|
+
* On the ESP hardware nodeId is uniquely calculated from the MAC address of
|
|
45
|
+
* the node.
|
|
46
|
+
*/
|
|
47
|
+
uint32_t getNodeId() { return nodeId; }
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Check whether this node is a root node.
|
|
51
|
+
*/
|
|
52
|
+
bool isRoot() { return root; }
|
|
53
|
+
|
|
54
|
+
protocol::NodeTree asNodeTree() {
|
|
55
|
+
auto nt = protocol::NodeTree(nodeId, root);
|
|
56
|
+
for (auto&& s : subs) {
|
|
57
|
+
if (s->nodeId == 0) continue;
|
|
58
|
+
nt.subs.push_back(protocol::NodeTree(*s));
|
|
59
|
+
}
|
|
60
|
+
return nt;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
protected:
|
|
64
|
+
uint32_t nodeId = 0;
|
|
65
|
+
bool root = false;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
template <class T>
|
|
69
|
+
void syncLayout(Layout<T>& layout, uint32_t changedId) {
|
|
70
|
+
// TODO: this should be called from changed connections and dropped
|
|
71
|
+
// connections events
|
|
72
|
+
for (auto&& sub : layout.subs) {
|
|
73
|
+
if (sub->connected() && !sub->newConnection && sub->nodeId != 0 &&
|
|
74
|
+
sub->nodeId != changedId) { // Exclude current
|
|
75
|
+
sub->nodeSyncTask.forceNextIteration();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
layout.stability /= 2;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
class Neighbour : public protocol::NodeTree {
|
|
82
|
+
public:
|
|
83
|
+
// Inherit constructors
|
|
84
|
+
using protocol::NodeTree::NodeTree;
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Is the passed nodesync valid
|
|
88
|
+
*
|
|
89
|
+
* If not then the caller of this function should probably disconnect
|
|
90
|
+
* this neighbour.
|
|
91
|
+
*/
|
|
92
|
+
bool validSubs(protocol::NodeTree tree) {
|
|
93
|
+
if (nodeId == 0) // Cant really know, so valid as far as we know
|
|
94
|
+
return true;
|
|
95
|
+
if (nodeId != tree.nodeId) return false;
|
|
96
|
+
for (auto&& s : tree.subs) {
|
|
97
|
+
if (layout::contains(s, nodeId)) return false;
|
|
98
|
+
}
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Update subs with the new subs
|
|
104
|
+
*
|
|
105
|
+
* \param tree The possible new tree with this node as base
|
|
106
|
+
*
|
|
107
|
+
* Generally one probably wants to call validSubs before calling this
|
|
108
|
+
* function.
|
|
109
|
+
*
|
|
110
|
+
* \return Whether we adopted the new tree
|
|
111
|
+
*/
|
|
112
|
+
bool updateSubs(protocol::NodeTree tree) {
|
|
113
|
+
if (nodeId == 0 || tree != (*this)) {
|
|
114
|
+
nodeId = tree.nodeId;
|
|
115
|
+
subs = tree.subs;
|
|
116
|
+
root = tree.root;
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Create a request
|
|
124
|
+
*/
|
|
125
|
+
protocol::NodeSyncRequest request(NodeTree&& layout) {
|
|
126
|
+
auto subTree = excludeRoute(std::move(layout), nodeId);
|
|
127
|
+
return protocol::NodeSyncRequest(subTree.nodeId, nodeId, subTree.subs,
|
|
128
|
+
subTree.root);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Create a reply
|
|
133
|
+
*/
|
|
134
|
+
protocol::NodeSyncReply reply(NodeTree&& layout) {
|
|
135
|
+
auto subTree = excludeRoute(std::move(layout), nodeId);
|
|
136
|
+
return protocol::NodeSyncReply(subTree.nodeId, nodeId, subTree.subs,
|
|
137
|
+
subTree.root);
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* The size of the mesh (the number of nodes)
|
|
143
|
+
*/
|
|
144
|
+
inline uint32_t size(protocol::NodeTree nodeTree) {
|
|
145
|
+
auto no = 1;
|
|
146
|
+
for (auto&& s : nodeTree.subs) {
|
|
147
|
+
no += size(s);
|
|
148
|
+
}
|
|
149
|
+
return no;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Whether the top node in the tree is also the root of the mesh
|
|
154
|
+
*/
|
|
155
|
+
inline bool isRoot(protocol::NodeTree nodeTree) {
|
|
156
|
+
if (nodeTree.root) return true;
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Whether any node in the tree is also root of the mesh
|
|
162
|
+
*/
|
|
163
|
+
inline bool isRooted(protocol::NodeTree nodeTree) {
|
|
164
|
+
if (isRoot(nodeTree)) return true;
|
|
165
|
+
for (auto&& s : nodeTree.subs) {
|
|
166
|
+
if (isRooted(s)) return true;
|
|
167
|
+
}
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Return all nodes in a list container
|
|
173
|
+
*/
|
|
174
|
+
inline std::list<uint32_t> asList(protocol::NodeTree nodeTree,
|
|
175
|
+
bool includeSelf = true) {
|
|
176
|
+
std::list<uint32_t> lst;
|
|
177
|
+
if (includeSelf) lst.push_back(nodeTree.nodeId);
|
|
178
|
+
for (auto&& s : nodeTree.subs) {
|
|
179
|
+
lst.splice(lst.end(), asList(s));
|
|
180
|
+
}
|
|
181
|
+
return lst;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
} // namespace layout
|
|
185
|
+
} // namespace painlessmesh
|
|
186
|
+
|
|
187
|
+
#endif
|
|
188
|
+
|