@alteriom/painlessmesh 1.7.9 → 1.8.0
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 +94 -2
- package/README.md +108 -1
- package/docs/BRIDGE_FAILOVER.md +512 -0
- package/docs/BRIDGE_HEALTH_MONITORING.md +293 -0
- package/docs/CREATE_MISSING_RELEASES.md +321 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.8.md +523 -0
- package/docs/releases/RELEASE_SUMMARY_v1.7.9.md +542 -0
- package/examples/alteriom/alteriom_sensor_package.hpp +213 -0
- package/examples/alteriomSensorNode/alteriom_sensor_package.hpp +1014 -11
- package/examples/basic/basic.ino +6 -2
- package/examples/bridge/bridge.ino +44 -23
- package/examples/bridge/bridge_health_monitoring_example.ino +188 -0
- package/examples/bridgeAwareSensorNode/alteriom_sensor_package.hpp +1227 -0
- package/examples/bridgeAwareSensorNode/bridgeAwareSensorNode.ino +343 -0
- package/examples/bridgeAwareSensorNode/platformio.ini +26 -0
- package/examples/bridge_failover/README.md +358 -0
- package/examples/bridge_failover/bridge_failover.ino +180 -0
- package/examples/bridge_failover/platformio.ini +27 -0
- package/examples/diagnosticsExample/diagnosticsExample.ino +171 -0
- package/examples/diagnosticsExample/platformio.ini +26 -0
- package/examples/ntpTimeSyncBridge/alteriom_sensor_package.hpp +1383 -0
- package/examples/ntpTimeSyncBridge/ntpTimeSyncBridge.ino +81 -0
- package/examples/ntpTimeSyncNode/alteriom_sensor_package.hpp +1383 -0
- package/examples/ntpTimeSyncNode/ntpTimeSyncNode.ino +109 -0
- package/examples/rtcIntegration/README.md +235 -0
- package/examples/rtcIntegration/rtcIntegration.ino +196 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +1 -1
- package/src/arduino/wifi.hpp +572 -0
- package/src/painlessMeshSTA.cpp +63 -0
- package/src/painlessMeshSTA.h +3 -0
- package/src/painlessmesh/mesh.hpp +1127 -4
- package/src/painlessmesh/rtc.hpp +203 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file ntpTimeSyncNode.ino
|
|
3
|
+
* @brief Example: Regular mesh node receiving NTP time from bridge
|
|
4
|
+
*
|
|
5
|
+
* This example demonstrates a regular mesh node that:
|
|
6
|
+
* 1. Connects to the mesh network
|
|
7
|
+
* 2. Listens for NTP time broadcasts from bridge nodes
|
|
8
|
+
* 3. Updates local time when NTP sync is received
|
|
9
|
+
* 4. Optionally syncs RTC module if available
|
|
10
|
+
*
|
|
11
|
+
* No Internet connection needed - time is received from bridge!
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
#include "painlessMesh.h"
|
|
15
|
+
#include "examples/alteriom/alteriom_sensor_package.hpp"
|
|
16
|
+
|
|
17
|
+
// Mesh configuration
|
|
18
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
19
|
+
#define MESH_PASSWORD "your_mesh_password"
|
|
20
|
+
#define MESH_PORT 5555
|
|
21
|
+
|
|
22
|
+
Scheduler userScheduler;
|
|
23
|
+
painlessMesh mesh;
|
|
24
|
+
|
|
25
|
+
using namespace alteriom;
|
|
26
|
+
|
|
27
|
+
// Track last time sync
|
|
28
|
+
uint32_t lastNTPSync = 0;
|
|
29
|
+
uint32_t ntpSyncCount = 0;
|
|
30
|
+
|
|
31
|
+
// Received callback - handle incoming messages
|
|
32
|
+
void receivedCallback(uint32_t from, String& msg) {
|
|
33
|
+
// Parse JSON message
|
|
34
|
+
DynamicJsonDocument doc(1024);
|
|
35
|
+
DeserializationError error = deserializeJson(doc, msg);
|
|
36
|
+
|
|
37
|
+
if (error) {
|
|
38
|
+
Serial.printf("JSON parse error: %s\n", error.c_str());
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
JsonObject obj = doc.as<JsonObject>();
|
|
43
|
+
uint16_t msgType = obj["type"];
|
|
44
|
+
|
|
45
|
+
// Check if this is an NTP time sync message
|
|
46
|
+
if (msgType == 614) {
|
|
47
|
+
// Deserialize NTP time sync package
|
|
48
|
+
auto pkg = NTPTimeSyncPackage(obj);
|
|
49
|
+
|
|
50
|
+
Serial.printf("\n=== NTP Time Sync Received ===\n");
|
|
51
|
+
Serial.printf("From: %u\n", from);
|
|
52
|
+
Serial.printf("NTP Time: %u\n", pkg.ntpTime);
|
|
53
|
+
Serial.printf("Accuracy: %ums\n", pkg.accuracy);
|
|
54
|
+
Serial.printf("Source: %s\n", pkg.source.c_str());
|
|
55
|
+
Serial.printf("Timestamp: %u\n", pkg.timestamp);
|
|
56
|
+
Serial.println("=============================\n");
|
|
57
|
+
|
|
58
|
+
// Update mesh time (this is application-specific)
|
|
59
|
+
// In a real implementation, you would:
|
|
60
|
+
// 1. Verify the sender is a bridge node
|
|
61
|
+
// 2. Apply the time with mesh.setTimeFromNTP(pkg.ntpTime)
|
|
62
|
+
// 3. Update RTC if available
|
|
63
|
+
|
|
64
|
+
lastNTPSync = millis();
|
|
65
|
+
ntpSyncCount++;
|
|
66
|
+
|
|
67
|
+
Serial.printf("Time sync applied! Total syncs: %u\n", ntpSyncCount);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Status task - periodic status updates
|
|
72
|
+
Task taskStatus(30000, TASK_FOREVER, [](){
|
|
73
|
+
uint32_t timeSinceSync = (millis() - lastNTPSync) / 1000;
|
|
74
|
+
|
|
75
|
+
Serial.printf("\n--- Node Status ---\n");
|
|
76
|
+
Serial.printf("Node ID: %u\n", mesh.getNodeId());
|
|
77
|
+
Serial.printf("Connections: %d\n", mesh.getNodeList().size());
|
|
78
|
+
Serial.printf("NTP Syncs: %u\n", ntpSyncCount);
|
|
79
|
+
|
|
80
|
+
if (ntpSyncCount > 0) {
|
|
81
|
+
Serial.printf("Last sync: %u seconds ago\n", timeSinceSync);
|
|
82
|
+
} else {
|
|
83
|
+
Serial.println("Waiting for first NTP sync...");
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
Serial.println("------------------\n");
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
void setup() {
|
|
90
|
+
Serial.begin(115200);
|
|
91
|
+
|
|
92
|
+
// Initialize mesh
|
|
93
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
94
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
95
|
+
|
|
96
|
+
// Set callbacks
|
|
97
|
+
mesh.onReceive(&receivedCallback);
|
|
98
|
+
|
|
99
|
+
// Add status task
|
|
100
|
+
userScheduler.addTask(taskStatus);
|
|
101
|
+
taskStatus.enable();
|
|
102
|
+
|
|
103
|
+
Serial.println("Regular mesh node initialized");
|
|
104
|
+
Serial.println("Listening for NTP time broadcasts...");
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
void loop() {
|
|
108
|
+
mesh.update();
|
|
109
|
+
}
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
# RTC Integration Example
|
|
2
|
+
|
|
3
|
+
This example demonstrates how to integrate Real-Time Clock (RTC) modules with painlessMesh for accurate offline timekeeping.
|
|
4
|
+
|
|
5
|
+
## Problem Statement
|
|
6
|
+
|
|
7
|
+
When Internet or bridge connectivity is unavailable, mesh nodes lose access to accurate time synchronization. This is problematic for applications that require valid timestamps, such as:
|
|
8
|
+
|
|
9
|
+
- Fish farm alarm systems (regulatory compliance)
|
|
10
|
+
- Environmental monitoring with offline data logging
|
|
11
|
+
- Industrial IoT with intermittent connectivity
|
|
12
|
+
- Remote sensor networks
|
|
13
|
+
|
|
14
|
+
## Solution
|
|
15
|
+
|
|
16
|
+
painlessMesh RTC integration provides:
|
|
17
|
+
|
|
18
|
+
✅ **Accurate timestamps during offline periods**
|
|
19
|
+
✅ **Automatic NTP sync when Internet available**
|
|
20
|
+
✅ **Graceful fallback to mesh time**
|
|
21
|
+
✅ **Support for common RTC modules**
|
|
22
|
+
|
|
23
|
+
## Supported RTC Modules
|
|
24
|
+
|
|
25
|
+
- **DS3231** - High accuracy I2C RTC with temperature compensation
|
|
26
|
+
- **DS1307** - Basic I2C RTC
|
|
27
|
+
- **PCF8523** - Low power I2C RTC
|
|
28
|
+
- **PCF8563** - Ultra-low power I2C RTC
|
|
29
|
+
- **ESP32 Internal RTC** - Built-in ESP32 RTC (requires external battery backup)
|
|
30
|
+
|
|
31
|
+
## Hardware Requirements
|
|
32
|
+
|
|
33
|
+
### For DS3231 (used in this example)
|
|
34
|
+
- ESP32 or ESP8266 board
|
|
35
|
+
- DS3231 RTC module
|
|
36
|
+
- Connections:
|
|
37
|
+
- SDA → GPIO 21 (ESP32) or GPIO 4 (ESP8266)
|
|
38
|
+
- SCL → GPIO 22 (ESP32) or GPIO 5 (ESP8266)
|
|
39
|
+
- VCC → 3.3V
|
|
40
|
+
- GND → GND
|
|
41
|
+
|
|
42
|
+
### Library Requirements
|
|
43
|
+
```
|
|
44
|
+
painlessMesh
|
|
45
|
+
RTClib (Adafruit)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Install via Arduino Library Manager:
|
|
49
|
+
- Tools → Manage Libraries
|
|
50
|
+
- Search for "RTClib" by Adafruit
|
|
51
|
+
- Click Install
|
|
52
|
+
|
|
53
|
+
## How It Works
|
|
54
|
+
|
|
55
|
+
### 1. RTC Interface Implementation
|
|
56
|
+
|
|
57
|
+
You implement the `RTCInterface` for your specific RTC hardware:
|
|
58
|
+
|
|
59
|
+
```cpp
|
|
60
|
+
class DS3231Interface : public painlessmesh::rtc::RTCInterface {
|
|
61
|
+
// Implement begin(), isAvailable(), getUnixTime(), setUnixTime(), getType()
|
|
62
|
+
};
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 2. Enable RTC
|
|
66
|
+
|
|
67
|
+
```cpp
|
|
68
|
+
DS3231Interface rtcInterface(&rtc);
|
|
69
|
+
mesh.enableRTC(&rtcInterface);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### 3. Automatic Time Management
|
|
73
|
+
|
|
74
|
+
```cpp
|
|
75
|
+
mesh.onBridgeStatusChanged([](uint32_t bridgeNodeId, bool hasInternet) {
|
|
76
|
+
if (hasInternet) {
|
|
77
|
+
// Sync RTC from NTP when Internet available
|
|
78
|
+
uint32_t ntpTime = getNTPTime();
|
|
79
|
+
mesh.syncRTCFromNTP(ntpTime);
|
|
80
|
+
}
|
|
81
|
+
// Offline: RTC maintains accurate time
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### 4. Get Accurate Time
|
|
86
|
+
|
|
87
|
+
```cpp
|
|
88
|
+
// Prefers RTC, falls back to mesh time
|
|
89
|
+
uint32_t timestamp = mesh.getAccurateTime();
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## API Reference
|
|
93
|
+
|
|
94
|
+
### Mesh Methods
|
|
95
|
+
|
|
96
|
+
#### `bool enableRTC(rtc::RTCInterface* rtcInterface)`
|
|
97
|
+
Enable RTC integration with a user-provided interface.
|
|
98
|
+
|
|
99
|
+
**Returns:** `true` if RTC initialized successfully, `false` otherwise
|
|
100
|
+
|
|
101
|
+
#### `void disableRTC()`
|
|
102
|
+
Disable RTC integration.
|
|
103
|
+
|
|
104
|
+
#### `bool syncRTCFromNTP(uint32_t ntpTimestamp)`
|
|
105
|
+
Sync RTC from NTP/Internet time source.
|
|
106
|
+
|
|
107
|
+
**Parameters:**
|
|
108
|
+
- `ntpTimestamp` - Unix timestamp from NTP
|
|
109
|
+
|
|
110
|
+
**Returns:** `true` if sync successful, `false` otherwise
|
|
111
|
+
|
|
112
|
+
#### `uint32_t getAccurateTime()`
|
|
113
|
+
Get accurate time with RTC fallback.
|
|
114
|
+
|
|
115
|
+
**Returns:** Unix timestamp (seconds) from RTC, or mesh time (microseconds) if RTC unavailable
|
|
116
|
+
|
|
117
|
+
#### `bool hasRTC()`
|
|
118
|
+
Check if RTC is enabled and available.
|
|
119
|
+
|
|
120
|
+
**Returns:** `true` if RTC can be used, `false` otherwise
|
|
121
|
+
|
|
122
|
+
#### `rtc::RTCType getRTCType()`
|
|
123
|
+
Get RTC module type.
|
|
124
|
+
|
|
125
|
+
**Returns:** `RTCType` enum value
|
|
126
|
+
|
|
127
|
+
#### `uint32_t getTimeSinceRTCSync()`
|
|
128
|
+
Get time since last RTC sync.
|
|
129
|
+
|
|
130
|
+
**Returns:** Milliseconds since last sync, or 0 if never synced
|
|
131
|
+
|
|
132
|
+
#### `void onRTCSyncComplete(rtcSyncCompleteCallback_t callback)`
|
|
133
|
+
Set callback for RTC sync completion.
|
|
134
|
+
|
|
135
|
+
### RTC Types
|
|
136
|
+
|
|
137
|
+
```cpp
|
|
138
|
+
enum RTCType {
|
|
139
|
+
RTC_NONE = 0,
|
|
140
|
+
RTC_DS3231 = 1,
|
|
141
|
+
RTC_DS1307 = 2,
|
|
142
|
+
RTC_PCF8523 = 3,
|
|
143
|
+
RTC_PCF8563 = 4,
|
|
144
|
+
RTC_ESP32_INTERNAL = 5
|
|
145
|
+
};
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Usage Example
|
|
149
|
+
|
|
150
|
+
```cpp
|
|
151
|
+
#include "painlessMesh.h"
|
|
152
|
+
#include <RTClib.h>
|
|
153
|
+
|
|
154
|
+
painlessMesh mesh;
|
|
155
|
+
RTC_DS3231 rtc;
|
|
156
|
+
DS3231Interface rtcInterface(&rtc);
|
|
157
|
+
|
|
158
|
+
void setup() {
|
|
159
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
160
|
+
mesh.onBridgeStatusChanged(&bridgeStatusCallback);
|
|
161
|
+
mesh.onRTCSyncComplete(&rtcSyncCompleteCallback);
|
|
162
|
+
|
|
163
|
+
if (mesh.enableRTC(&rtcInterface)) {
|
|
164
|
+
Serial.println("RTC enabled!");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet) {
|
|
169
|
+
if (hasInternet && mesh.hasRTC()) {
|
|
170
|
+
uint32_t ntpTime = getNTPTime(); // Your implementation
|
|
171
|
+
mesh.syncRTCFromNTP(ntpTime);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
void rtcSyncCompleteCallback(uint32_t timestamp) {
|
|
176
|
+
Serial.printf("RTC synced to: %u\n", timestamp);
|
|
177
|
+
}
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Testing
|
|
181
|
+
|
|
182
|
+
### Verify RTC Time Persistence
|
|
183
|
+
1. Upload sketch to node
|
|
184
|
+
2. Disconnect Internet/bridge
|
|
185
|
+
3. Power cycle the node
|
|
186
|
+
4. Verify timestamps remain accurate (±2 seconds)
|
|
187
|
+
|
|
188
|
+
### Verify NTP Sync
|
|
189
|
+
1. Connect bridge to Internet
|
|
190
|
+
2. Monitor serial output for sync messages
|
|
191
|
+
3. Verify RTC time updated correctly
|
|
192
|
+
|
|
193
|
+
### Verify Offline Operation
|
|
194
|
+
1. Disconnect Internet
|
|
195
|
+
2. Wait several hours
|
|
196
|
+
3. Verify timestamps continue to increment accurately
|
|
197
|
+
|
|
198
|
+
## Troubleshooting
|
|
199
|
+
|
|
200
|
+
### "Couldn't find RTC"
|
|
201
|
+
- Check I2C connections (SDA/SCL)
|
|
202
|
+
- Verify RTC module has power
|
|
203
|
+
- Try I2C scanner sketch to detect device
|
|
204
|
+
|
|
205
|
+
### "RTC lost power"
|
|
206
|
+
- RTC battery needs replacement
|
|
207
|
+
- Time will be synced from NTP when available
|
|
208
|
+
|
|
209
|
+
### Time Not Syncing
|
|
210
|
+
- Verify bridge has Internet connectivity
|
|
211
|
+
- Check NTP server is accessible
|
|
212
|
+
- Ensure `syncRTCFromNTP()` called with valid timestamp
|
|
213
|
+
|
|
214
|
+
## Best Practices
|
|
215
|
+
|
|
216
|
+
1. **Always check RTC availability** before relying on timestamps
|
|
217
|
+
2. **Sync regularly** when Internet available (recommended: every 24 hours)
|
|
218
|
+
3. **Monitor battery** on RTC modules for continuous operation
|
|
219
|
+
4. **Implement fallback** to mesh time if RTC fails
|
|
220
|
+
5. **Log sync events** for debugging and maintenance
|
|
221
|
+
|
|
222
|
+
## Regulatory Compliance
|
|
223
|
+
|
|
224
|
+
For systems requiring timestamp accuracy (e.g., fish farm alarms):
|
|
225
|
+
|
|
226
|
+
- RTC provides ±2 second accuracy during offline periods
|
|
227
|
+
- Timestamps remain valid for alarm reporting
|
|
228
|
+
- Sync logs provide audit trail
|
|
229
|
+
- Battery backup ensures continuous operation
|
|
230
|
+
|
|
231
|
+
## See Also
|
|
232
|
+
|
|
233
|
+
- [Bridge Status Feature](../../BRIDGE_STATUS_FEATURE.md) - Internet connectivity detection
|
|
234
|
+
- [Bridge Architecture](../../BRIDGE_ARCHITECTURE_IMPLEMENTATION.md) - Mesh bridge setup
|
|
235
|
+
- [painlessMesh Documentation](https://gitlab.com/painlessMesh/painlessMesh) - Main library docs
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
//************************************************************
|
|
2
|
+
// RTC Integration Example
|
|
3
|
+
//
|
|
4
|
+
// This example demonstrates how to use RTC (Real-Time Clock)
|
|
5
|
+
// modules with painlessMesh for accurate offline timekeeping.
|
|
6
|
+
//
|
|
7
|
+
// When Internet/bridge is unavailable, nodes can still maintain
|
|
8
|
+
// accurate timestamps using a local RTC module.
|
|
9
|
+
//
|
|
10
|
+
// Supported RTC modules:
|
|
11
|
+
// - DS3231, DS1307 (I2C)
|
|
12
|
+
// - PCF8523, PCF8563 (I2C)
|
|
13
|
+
// - ESP32 internal RTC
|
|
14
|
+
//
|
|
15
|
+
// This example uses DS3231 with the RTClib library.
|
|
16
|
+
// Install: https://github.com/adafruit/RTClib
|
|
17
|
+
//************************************************************
|
|
18
|
+
|
|
19
|
+
#include "painlessMesh.h"
|
|
20
|
+
#include <RTClib.h> // Adafruit RTClib for DS3231
|
|
21
|
+
|
|
22
|
+
#define MESH_PREFIX "AlteriomMesh"
|
|
23
|
+
#define MESH_PASSWORD "somethingSneaky"
|
|
24
|
+
#define MESH_PORT 5555
|
|
25
|
+
|
|
26
|
+
Scheduler userScheduler;
|
|
27
|
+
painlessMesh mesh;
|
|
28
|
+
|
|
29
|
+
// DS3231 RTC instance
|
|
30
|
+
RTC_DS3231 rtc;
|
|
31
|
+
|
|
32
|
+
// RTC Interface implementation for DS3231
|
|
33
|
+
class DS3231Interface : public painlessmesh::rtc::RTCInterface {
|
|
34
|
+
private:
|
|
35
|
+
RTC_DS3231* rtcDevice;
|
|
36
|
+
|
|
37
|
+
public:
|
|
38
|
+
DS3231Interface(RTC_DS3231* device) : rtcDevice(device) {}
|
|
39
|
+
|
|
40
|
+
bool begin() override {
|
|
41
|
+
if (!rtcDevice->begin()) {
|
|
42
|
+
Serial.println("Couldn't find RTC");
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Check if RTC lost power and needs time set
|
|
47
|
+
if (rtcDevice->lostPower()) {
|
|
48
|
+
Serial.println("RTC lost power, time needs to be set!");
|
|
49
|
+
// Note: Time will be set via NTP when Internet available
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
bool isAvailable() override {
|
|
56
|
+
return !rtcDevice->lostPower();
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
uint32_t getUnixTime() override {
|
|
60
|
+
DateTime now = rtcDevice->now();
|
|
61
|
+
return now.unixtime();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
bool setUnixTime(uint32_t timestamp) override {
|
|
65
|
+
rtcDevice->adjust(DateTime(timestamp));
|
|
66
|
+
Serial.printf("RTC time set to: %u\n", timestamp);
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
painlessmesh::rtc::RTCType getType() override {
|
|
71
|
+
return painlessmesh::rtc::RTC_DS3231;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// Create RTC interface instance
|
|
76
|
+
DS3231Interface rtcInterface(&rtc);
|
|
77
|
+
|
|
78
|
+
// Task to send timestamped sensor data
|
|
79
|
+
void sendSensorData();
|
|
80
|
+
Task taskSendData(30000, TASK_FOREVER, &sendSensorData);
|
|
81
|
+
|
|
82
|
+
// Flag to track if we need NTP sync
|
|
83
|
+
bool needsNTPSync = true;
|
|
84
|
+
|
|
85
|
+
void setup() {
|
|
86
|
+
Serial.begin(115200);
|
|
87
|
+
|
|
88
|
+
// Initialize mesh
|
|
89
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
90
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
91
|
+
|
|
92
|
+
// Set up mesh callbacks
|
|
93
|
+
mesh.onReceive(&receivedCallback);
|
|
94
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
95
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
96
|
+
mesh.onBridgeStatusChanged(&bridgeStatusCallback);
|
|
97
|
+
mesh.onRTCSyncComplete(&rtcSyncCompleteCallback);
|
|
98
|
+
|
|
99
|
+
// Enable RTC
|
|
100
|
+
if (mesh.enableRTC(&rtcInterface)) {
|
|
101
|
+
Serial.println("RTC enabled successfully!");
|
|
102
|
+
Serial.printf("RTC Type: %d\n", mesh.getRTCType());
|
|
103
|
+
|
|
104
|
+
// Print current RTC time
|
|
105
|
+
uint32_t rtcTime = mesh.getAccurateTime();
|
|
106
|
+
Serial.printf("Current RTC time: %u\n", rtcTime);
|
|
107
|
+
} else {
|
|
108
|
+
Serial.println("Failed to enable RTC - will use mesh time only");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// Add sensor data task
|
|
112
|
+
userScheduler.addTask(taskSendData);
|
|
113
|
+
taskSendData.enable();
|
|
114
|
+
|
|
115
|
+
Serial.println("Setup complete");
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
void loop() {
|
|
119
|
+
mesh.update();
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
void sendSensorData() {
|
|
123
|
+
// Get accurate timestamp (RTC if available, mesh time otherwise)
|
|
124
|
+
uint32_t timestamp = mesh.getAccurateTime();
|
|
125
|
+
|
|
126
|
+
// Simulate sensor reading
|
|
127
|
+
float temperature = 25.5 + random(-50, 50) / 10.0;
|
|
128
|
+
float humidity = 60.0 + random(-100, 100) / 10.0;
|
|
129
|
+
|
|
130
|
+
// Create message with timestamp
|
|
131
|
+
String msg = "{\"type\":\"sensor\",";
|
|
132
|
+
msg += "\"nodeId\":" + String(mesh.getNodeId()) + ",";
|
|
133
|
+
msg += "\"timestamp\":" + String(timestamp) + ",";
|
|
134
|
+
msg += "\"temperature\":" + String(temperature, 1) + ",";
|
|
135
|
+
msg += "\"humidity\":" + String(humidity, 1) + ",";
|
|
136
|
+
msg += "\"hasRTC\":" + String(mesh.hasRTC() ? "true" : "false") + ",";
|
|
137
|
+
msg += "\"rtcType\":" + String(mesh.getRTCType());
|
|
138
|
+
msg += "}";
|
|
139
|
+
|
|
140
|
+
mesh.sendBroadcast(msg);
|
|
141
|
+
|
|
142
|
+
Serial.printf("Sent sensor data with timestamp: %u\n", timestamp);
|
|
143
|
+
Serial.printf("Time since last RTC sync: %u ms\n", mesh.getTimeSinceRTCSync());
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
void receivedCallback(uint32_t from, String &msg) {
|
|
147
|
+
Serial.printf("Received from %u: %s\n", from, msg.c_str());
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
void newConnectionCallback(uint32_t nodeId) {
|
|
151
|
+
Serial.printf("New Connection: %u\n", nodeId);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
void changedConnectionCallback() {
|
|
155
|
+
Serial.printf("Changed connections\n");
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
void bridgeStatusCallback(uint32_t bridgeNodeId, bool hasInternet) {
|
|
159
|
+
Serial.printf("Bridge %u - Internet: %s\n",
|
|
160
|
+
bridgeNodeId,
|
|
161
|
+
hasInternet ? "Connected" : "Disconnected");
|
|
162
|
+
|
|
163
|
+
if (hasInternet && needsNTPSync && mesh.hasRTC()) {
|
|
164
|
+
// Internet is available and we need to sync RTC
|
|
165
|
+
// In a real application, you would get NTP time here
|
|
166
|
+
// For this example, we'll use a placeholder
|
|
167
|
+
Serial.println("Internet available - would sync RTC from NTP now");
|
|
168
|
+
|
|
169
|
+
// Example: Get NTP time (you need to implement this)
|
|
170
|
+
// uint32_t ntpTime = getNTPTime();
|
|
171
|
+
// if (mesh.syncRTCFromNTP(ntpTime)) {
|
|
172
|
+
// Serial.println("RTC synced successfully!");
|
|
173
|
+
// needsNTPSync = false;
|
|
174
|
+
// }
|
|
175
|
+
|
|
176
|
+
// For demonstration purposes, let's sync to a known time
|
|
177
|
+
uint32_t demoTime = 1704067200; // 2024-01-01 00:00:00 UTC
|
|
178
|
+
if (mesh.syncRTCFromNTP(demoTime)) {
|
|
179
|
+
Serial.println("RTC synced to demo time!");
|
|
180
|
+
needsNTPSync = false;
|
|
181
|
+
}
|
|
182
|
+
} else if (!hasInternet) {
|
|
183
|
+
// Internet lost - RTC will keep accurate time offline
|
|
184
|
+
Serial.println("Internet offline - using RTC for timestamps");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
void rtcSyncCompleteCallback(uint32_t timestamp) {
|
|
189
|
+
Serial.printf("RTC sync completed! New time: %u\n", timestamp);
|
|
190
|
+
|
|
191
|
+
// Convert timestamp to human-readable format
|
|
192
|
+
DateTime dt(timestamp);
|
|
193
|
+
Serial.printf("Synced to: %d-%02d-%02d %02d:%02d:%02d\n",
|
|
194
|
+
dt.year(), dt.month(), dt.day(),
|
|
195
|
+
dt.hour(), dt.minute(), dt.second());
|
|
196
|
+
}
|
package/library.json
CHANGED
package/library.properties
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
name=AlteriomPainlessMesh
|
|
2
|
-
version=1.
|
|
2
|
+
version=1.8.0
|
|
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.
|
|
3
|
+
"version": "1.8.0",
|
|
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",
|