@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
|
@@ -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
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
#include "painlessMesh.h"
|
|
2
|
+
#include "alteriom_sensor_package.hpp"
|
|
3
|
+
|
|
4
|
+
// Define LED_BUILTIN for ESP32 boards that don't have it predefined
|
|
5
|
+
#ifndef LED_BUILTIN
|
|
6
|
+
#define LED_BUILTIN 2
|
|
7
|
+
#endif
|
|
8
|
+
|
|
9
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
10
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
11
|
+
#define MESH_PORT 5555
|
|
12
|
+
|
|
13
|
+
using namespace alteriom;
|
|
14
|
+
|
|
15
|
+
Scheduler userScheduler;
|
|
16
|
+
painlessMesh mesh;
|
|
17
|
+
|
|
18
|
+
// Command handlers
|
|
19
|
+
void handleCommand(const CommandPackage& cmd);
|
|
20
|
+
void sendStatusResponse(uint32_t commandId, String message, uint8_t status = 0);
|
|
21
|
+
void sendConfiguration();
|
|
22
|
+
void sendStatus();
|
|
23
|
+
|
|
24
|
+
// Command definitions (matching mqtt_command_bridge.hpp)
|
|
25
|
+
enum Commands {
|
|
26
|
+
RESET = 1,
|
|
27
|
+
SLEEP = 2,
|
|
28
|
+
WAKE = 3,
|
|
29
|
+
LED_CONTROL = 10,
|
|
30
|
+
RELAY_SWITCH = 11,
|
|
31
|
+
PWM_SET = 12,
|
|
32
|
+
GET_CONFIG = 100,
|
|
33
|
+
SET_CONFIG = 101,
|
|
34
|
+
GET_STATUS = 200,
|
|
35
|
+
GET_METRICS = 201
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
void setup() {
|
|
39
|
+
Serial.begin(115200);
|
|
40
|
+
|
|
41
|
+
pinMode(LED_BUILTIN, OUTPUT);
|
|
42
|
+
|
|
43
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
44
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
45
|
+
|
|
46
|
+
mesh.onReceive([](uint32_t from, String& msg) {
|
|
47
|
+
Serial.printf("Received from %u\n", from);
|
|
48
|
+
|
|
49
|
+
// Parse message
|
|
50
|
+
JsonDocument doc;
|
|
51
|
+
DeserializationError error = deserializeJson(doc, msg);
|
|
52
|
+
|
|
53
|
+
if (error) {
|
|
54
|
+
Serial.printf("JSON parse error: %s\n", error.c_str());
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
uint8_t msgType = doc["type"];
|
|
59
|
+
|
|
60
|
+
if (msgType == 201) {
|
|
61
|
+
// CommandPackage
|
|
62
|
+
JsonObject obj = doc.as<JsonObject>();
|
|
63
|
+
CommandPackage cmd(obj);
|
|
64
|
+
|
|
65
|
+
// Check if command is for this node
|
|
66
|
+
if (cmd.targetDevice == 0 || cmd.targetDevice == mesh.getNodeId()) {
|
|
67
|
+
handleCommand(cmd);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
mesh.onNewConnection([](uint32_t nodeId) {
|
|
73
|
+
Serial.printf("New connection: %u\n", nodeId);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
mesh.onChangedConnections([]() {
|
|
77
|
+
Serial.printf("Connections changed - nodes: %d\n", mesh.getNodeList().size());
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
Serial.printf("Mesh node initialized: %u\n", mesh.getNodeId());
|
|
81
|
+
Serial.println("Ready to receive commands");
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
void loop() {
|
|
85
|
+
mesh.update();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* @brief Handle incoming command
|
|
90
|
+
*/
|
|
91
|
+
void handleCommand(const CommandPackage& cmd) {
|
|
92
|
+
Serial.printf("Command received: cmd=%d, id=%u\n", cmd.command, cmd.commandId);
|
|
93
|
+
|
|
94
|
+
switch(cmd.command) {
|
|
95
|
+
case RESET:
|
|
96
|
+
sendStatusResponse(cmd.commandId, "Rebooting...");
|
|
97
|
+
delay(1000);
|
|
98
|
+
ESP.restart();
|
|
99
|
+
break;
|
|
100
|
+
|
|
101
|
+
case SLEEP: {
|
|
102
|
+
JsonDocument params;
|
|
103
|
+
deserializeJson(params, cmd.parameters);
|
|
104
|
+
uint32_t duration = params["duration_ms"];
|
|
105
|
+
|
|
106
|
+
sendStatusResponse(cmd.commandId, "Entering sleep for " + String(duration) + "ms");
|
|
107
|
+
delay(100);
|
|
108
|
+
|
|
109
|
+
ESP.deepSleep(duration * 1000);
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
case LED_CONTROL: {
|
|
114
|
+
JsonDocument params;
|
|
115
|
+
deserializeJson(params, cmd.parameters);
|
|
116
|
+
|
|
117
|
+
bool state = params["state"];
|
|
118
|
+
uint8_t brightness = params["brightness"] | 255;
|
|
119
|
+
|
|
120
|
+
digitalWrite(LED_BUILTIN, state ? LOW : HIGH);
|
|
121
|
+
|
|
122
|
+
String msg = "LED " + String(state ? "ON" : "OFF");
|
|
123
|
+
if (brightness < 255) {
|
|
124
|
+
msg += " (brightness: " + String(brightness) + ")";
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
sendStatusResponse(cmd.commandId, msg);
|
|
128
|
+
Serial.println(msg);
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
case RELAY_SWITCH: {
|
|
133
|
+
JsonDocument params;
|
|
134
|
+
deserializeJson(params, cmd.parameters);
|
|
135
|
+
|
|
136
|
+
uint8_t channel = params["channel"];
|
|
137
|
+
bool state = params["state"];
|
|
138
|
+
|
|
139
|
+
// Control relay (GPIO configuration needed)
|
|
140
|
+
String msg = "Relay " + String(channel) + " " + String(state ? "ON" : "OFF");
|
|
141
|
+
sendStatusResponse(cmd.commandId, msg);
|
|
142
|
+
Serial.println(msg);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
case PWM_SET: {
|
|
147
|
+
JsonDocument params;
|
|
148
|
+
deserializeJson(params, cmd.parameters);
|
|
149
|
+
|
|
150
|
+
uint8_t pin = params["pin"];
|
|
151
|
+
uint16_t duty = params["duty"];
|
|
152
|
+
|
|
153
|
+
// Set PWM (example - adjust for your hardware)
|
|
154
|
+
String msg = "PWM pin " + String(pin) + " set to " + String(duty);
|
|
155
|
+
sendStatusResponse(cmd.commandId, msg);
|
|
156
|
+
Serial.println(msg);
|
|
157
|
+
break;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
case GET_CONFIG:
|
|
161
|
+
sendConfiguration();
|
|
162
|
+
break;
|
|
163
|
+
|
|
164
|
+
case GET_STATUS:
|
|
165
|
+
sendStatus();
|
|
166
|
+
break;
|
|
167
|
+
|
|
168
|
+
case GET_METRICS: {
|
|
169
|
+
// Send enhanced status
|
|
170
|
+
EnhancedStatusPackage metrics;
|
|
171
|
+
metrics.from = mesh.getNodeId();
|
|
172
|
+
metrics.deviceStatus = 0;
|
|
173
|
+
metrics.uptime = millis() / 1000;
|
|
174
|
+
metrics.freeMemory = ESP.getFreeHeap() / 1024;
|
|
175
|
+
metrics.wifiStrength = WiFi.RSSI();
|
|
176
|
+
metrics.firmwareVersion = "1.0.0";
|
|
177
|
+
|
|
178
|
+
auto nodeList = mesh.getNodeList();
|
|
179
|
+
metrics.nodeCount = nodeList.size();
|
|
180
|
+
metrics.connectionCount = nodeList.size();
|
|
181
|
+
|
|
182
|
+
auto variant = painlessmesh::protocol::Variant(&metrics);
|
|
183
|
+
String msg;
|
|
184
|
+
variant.printTo(msg);
|
|
185
|
+
|
|
186
|
+
mesh.sendBroadcast(msg);
|
|
187
|
+
Serial.println("Metrics sent");
|
|
188
|
+
break;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
case SET_CONFIG: {
|
|
192
|
+
JsonDocument params;
|
|
193
|
+
deserializeJson(params, cmd.parameters);
|
|
194
|
+
|
|
195
|
+
JsonObject config = params.as<JsonObject>();
|
|
196
|
+
|
|
197
|
+
if (config["deviceName"].is<String>()) {
|
|
198
|
+
String name = config["deviceName"];
|
|
199
|
+
Serial.printf("Config: deviceName=%s\n", name.c_str());
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (config["sampleRate"].is<uint32_t>()) {
|
|
203
|
+
uint32_t rate = config["sampleRate"];
|
|
204
|
+
Serial.printf("Config: sampleRate=%u\n", rate);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
sendStatusResponse(cmd.commandId, "Configuration updated");
|
|
208
|
+
break;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
default:
|
|
212
|
+
sendStatusResponse(cmd.commandId, "Unknown command: " + String(cmd.command), 2);
|
|
213
|
+
Serial.printf("Unknown command: %d\n", cmd.command);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* @brief Send status response
|
|
219
|
+
*/
|
|
220
|
+
void sendStatusResponse(uint32_t commandId, String message, uint8_t status) {
|
|
221
|
+
StatusPackage response;
|
|
222
|
+
response.from = mesh.getNodeId();
|
|
223
|
+
response.deviceStatus = status;
|
|
224
|
+
response.uptime = millis() / 1000;
|
|
225
|
+
response.freeMemory = ESP.getFreeHeap() / 1024;
|
|
226
|
+
response.wifiStrength = WiFi.RSSI();
|
|
227
|
+
response.firmwareVersion = "1.0.0";
|
|
228
|
+
response.responseToCommand = commandId;
|
|
229
|
+
response.responseMessage = message;
|
|
230
|
+
|
|
231
|
+
auto variant = painlessmesh::protocol::Variant(&response);
|
|
232
|
+
String msg;
|
|
233
|
+
variant.printTo(msg);
|
|
234
|
+
|
|
235
|
+
mesh.sendBroadcast(msg);
|
|
236
|
+
Serial.printf("Response sent: %s\n", message.c_str());
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* @brief Send configuration
|
|
241
|
+
*/
|
|
242
|
+
void sendConfiguration() {
|
|
243
|
+
JsonDocument config;
|
|
244
|
+
config["deviceName"] = "Sensor-" + String(mesh.getNodeId());
|
|
245
|
+
config["firmwareVersion"] = "1.0.0";
|
|
246
|
+
config["role"] = "sensor";
|
|
247
|
+
config["sampleRate"] = 60000;
|
|
248
|
+
config["ledEnabled"] = true;
|
|
249
|
+
|
|
250
|
+
String configStr;
|
|
251
|
+
serializeJson(config, configStr);
|
|
252
|
+
|
|
253
|
+
sendStatusResponse(0, configStr);
|
|
254
|
+
Serial.println("Configuration sent");
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* @brief Send basic status
|
|
259
|
+
*/
|
|
260
|
+
void sendStatus() {
|
|
261
|
+
sendStatusResponse(0, "OK");
|
|
262
|
+
Serial.println("Status sent");
|
|
263
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[platformio]
|
|
2
|
+
src_dir = .
|
|
3
|
+
|
|
4
|
+
[env]
|
|
5
|
+
lib_deps =
|
|
6
|
+
bblanchon/ArduinoJson
|
|
7
|
+
arkhipenko/TaskScheduler
|
|
8
|
+
|
|
9
|
+
[env:esp8266]
|
|
10
|
+
platform = espressif8266
|
|
11
|
+
board = nodemcuv2
|
|
12
|
+
framework = arduino
|
|
13
|
+
lib_extra_dirs = ../../
|
|
14
|
+
lib_deps =
|
|
15
|
+
${env.lib_deps}
|
|
16
|
+
me-no-dev/ESPAsyncTCP
|
|
17
|
+
|
|
18
|
+
[env:esp32]
|
|
19
|
+
platform = espressif32
|
|
20
|
+
board = esp32dev
|
|
21
|
+
framework = arduino
|
|
22
|
+
lib_extra_dirs = ../../
|
|
23
|
+
lib_deps =
|
|
24
|
+
${env.lib_deps}
|
|
25
|
+
mathieucarbou/AsyncTCP
|