@alteriom/painlessmesh 1.8.13 → 1.8.15
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 +43 -0
- package/README.md +2 -0
- package/RELEASE_NOTES_1.8.15.md +160 -0
- package/RELEASE_READINESS_PLAN.md +323 -0
- package/TESTING_WITH_SIMULATOR.md +259 -0
- package/docs/BRIDGE_INITIALIZATION_FALLBACK.md +357 -0
- package/docs/SIMULATOR_TESTING.md +408 -0
- package/docs/troubleshooting/common-architecture-mistakes.md +438 -0
- package/docs/troubleshooting/common-issues.md +28 -0
- package/docs/troubleshooting/faq.md +113 -12
- package/docs/troubleshooting/internet-access-faq.md +299 -0
- package/examples/basic/test/simulator/CMakeLists.txt +40 -0
- package/examples/basic/test/simulator/README.md +149 -0
- package/examples/basic/test/simulator/firmware/basic_firmware.hpp +117 -0
- package/examples/basic/test/simulator/scenarios/basic_mesh_test.yaml +81 -0
- package/examples/bridge/bridge.ino +17 -4
- package/examples/bridge_failover/bridge_failover.ino +17 -3
- package/examples/multi_bridge/primary_bridge.ino +15 -3
- package/examples/multi_bridge/secondary_bridge.ino +15 -3
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +5 -2
- package/src/arduino/wifi.hpp +60 -9
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
# Simulator-Based Testing for painlessMesh
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
painlessMesh includes integration with the [painlessMesh-simulator](https://github.com/Alteriom/painlessMesh-simulator) to enable large-scale testing of examples and firmware without physical hardware.
|
|
6
|
+
|
|
7
|
+
The simulator allows you to:
|
|
8
|
+
- 🚀 Test with 100+ virtual nodes simultaneously
|
|
9
|
+
- 🔧 Validate actual firmware code in a controlled environment
|
|
10
|
+
- 📋 Configure test scenarios with YAML files
|
|
11
|
+
- 🌐 Simulate realistic network conditions (latency, packet loss, partitions)
|
|
12
|
+
- 📊 Collect metrics and analyze performance
|
|
13
|
+
- 🔄 Integrate with CI/CD pipelines
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
painlessMesh Repository
|
|
19
|
+
├── src/ # Library code
|
|
20
|
+
├── examples/ # Example sketches
|
|
21
|
+
│ ├── basic/
|
|
22
|
+
│ │ ├── basic.ino # Original Arduino sketch
|
|
23
|
+
│ │ └── test/simulator/ # Simulator tests
|
|
24
|
+
│ │ ├── firmware/ # Firmware adapter
|
|
25
|
+
│ │ ├── scenarios/ # YAML test scenarios
|
|
26
|
+
│ │ └── CMakeLists.txt # Build configuration
|
|
27
|
+
│ └── [other examples]/
|
|
28
|
+
└── test/
|
|
29
|
+
└── simulator/ # painlessMesh-simulator (submodule)
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### 1. Initialize Simulator Submodule
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
cd test
|
|
38
|
+
git submodule update --init simulator
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### 2. Install Dependencies
|
|
42
|
+
|
|
43
|
+
**Ubuntu/Debian:**
|
|
44
|
+
```bash
|
|
45
|
+
sudo apt-get install cmake ninja-build libboost-dev libboost-program-options-dev libyaml-cpp-dev
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**macOS:**
|
|
49
|
+
```bash
|
|
50
|
+
brew install cmake ninja boost yaml-cpp
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Windows:**
|
|
54
|
+
See [test/simulator/BUILD_WINDOWS_STATUS.md](../test/simulator/BUILD_WINDOWS_STATUS.md)
|
|
55
|
+
|
|
56
|
+
### 3. Run a Test
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd test/simulator
|
|
60
|
+
mkdir build && cd build
|
|
61
|
+
cmake -G Ninja ..
|
|
62
|
+
ninja
|
|
63
|
+
|
|
64
|
+
# Run basic example test
|
|
65
|
+
bin/painlessmesh-simulator --config ../../../examples/basic/test/simulator/scenarios/basic_mesh_test.yaml
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Example Test Structure
|
|
69
|
+
|
|
70
|
+
### Basic Example
|
|
71
|
+
|
|
72
|
+
The `examples/basic/` example includes complete simulator tests:
|
|
73
|
+
|
|
74
|
+
**Files:**
|
|
75
|
+
- `test/simulator/firmware/basic_firmware.hpp` - Firmware adapter
|
|
76
|
+
- `test/simulator/scenarios/basic_mesh_test.yaml` - Test configuration
|
|
77
|
+
- `test/simulator/README.md` - Detailed instructions
|
|
78
|
+
|
|
79
|
+
**Test Scenario (basic_mesh_test.yaml):**
|
|
80
|
+
```yaml
|
|
81
|
+
simulation:
|
|
82
|
+
name: "Basic Example Test"
|
|
83
|
+
duration: 60
|
|
84
|
+
|
|
85
|
+
nodes:
|
|
86
|
+
- template: "basic_example"
|
|
87
|
+
count: 10
|
|
88
|
+
config:
|
|
89
|
+
mesh_prefix: "whateverYouLike"
|
|
90
|
+
mesh_password: "somethingSneaky"
|
|
91
|
+
|
|
92
|
+
validation:
|
|
93
|
+
- check: "all_nodes_connected"
|
|
94
|
+
timeout: 30
|
|
95
|
+
- check: "messages_delivered"
|
|
96
|
+
min_messages_per_node: 5
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Run it:**
|
|
100
|
+
```bash
|
|
101
|
+
cd examples/basic/test/simulator
|
|
102
|
+
mkdir build && cd build
|
|
103
|
+
cmake -G Ninja .. && ninja
|
|
104
|
+
bin/painlessmesh-simulator --config ../scenarios/basic_mesh_test.yaml
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Creating Tests for Your Example
|
|
108
|
+
|
|
109
|
+
### Step 1: Create Directory Structure
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
cd examples/your_example
|
|
113
|
+
mkdir -p test/simulator/firmware test/simulator/scenarios
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Step 2: Create Firmware Adapter
|
|
117
|
+
|
|
118
|
+
Create `test/simulator/firmware/your_firmware.hpp`:
|
|
119
|
+
|
|
120
|
+
```cpp
|
|
121
|
+
#pragma once
|
|
122
|
+
#include "simulator/firmware/firmware_base.hpp"
|
|
123
|
+
#include <painlessMesh.h>
|
|
124
|
+
|
|
125
|
+
class YourFirmware : public FirmwareBase {
|
|
126
|
+
public:
|
|
127
|
+
void setup(painlessMesh* mesh, Scheduler* userScheduler) override {
|
|
128
|
+
mesh_ = mesh;
|
|
129
|
+
|
|
130
|
+
// Copy your setup() logic from the .ino file
|
|
131
|
+
mesh_->init("YourPrefix", "password", userScheduler, 5555);
|
|
132
|
+
mesh_->onReceive([this](uint32_t from, String& msg) {
|
|
133
|
+
// Your receive callback
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
// Add your tasks, etc.
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
void loop() override {
|
|
140
|
+
// Copy your loop() logic
|
|
141
|
+
if (mesh_) mesh_->update();
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const char* getName() const override {
|
|
145
|
+
return "YourExample";
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
private:
|
|
149
|
+
painlessMesh* mesh_;
|
|
150
|
+
};
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### Step 3: Create Test Scenario
|
|
154
|
+
|
|
155
|
+
Create `test/simulator/scenarios/your_test.yaml`:
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
simulation:
|
|
159
|
+
name: "Your Example Test"
|
|
160
|
+
duration: 60
|
|
161
|
+
|
|
162
|
+
nodes:
|
|
163
|
+
- template: "your_firmware"
|
|
164
|
+
count: 10
|
|
165
|
+
|
|
166
|
+
validation:
|
|
167
|
+
- check: "all_nodes_connected"
|
|
168
|
+
timeout: 30
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Step 4: Create CMakeLists.txt
|
|
172
|
+
|
|
173
|
+
Copy from `examples/basic/test/simulator/CMakeLists.txt` and adapt paths.
|
|
174
|
+
|
|
175
|
+
### Step 5: Run Test
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
cd test/simulator/build
|
|
179
|
+
bin/painlessmesh-simulator --config ../../../examples/your_example/test/simulator/scenarios/your_test.yaml
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Test Scenarios
|
|
183
|
+
|
|
184
|
+
### Available Validations
|
|
185
|
+
|
|
186
|
+
```yaml
|
|
187
|
+
validation:
|
|
188
|
+
# Mesh formation
|
|
189
|
+
- check: "all_nodes_connected"
|
|
190
|
+
timeout: 30
|
|
191
|
+
|
|
192
|
+
# Message delivery
|
|
193
|
+
- check: "messages_delivered"
|
|
194
|
+
min_messages_per_node: 5
|
|
195
|
+
timeout: 60
|
|
196
|
+
|
|
197
|
+
# Time synchronization
|
|
198
|
+
- check: "time_synchronized"
|
|
199
|
+
max_time_diff_ms: 10000
|
|
200
|
+
timeout: 45
|
|
201
|
+
|
|
202
|
+
# Custom metrics
|
|
203
|
+
- check: "custom_metric"
|
|
204
|
+
metric_name: "your_metric"
|
|
205
|
+
min_value: 100
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Network Conditions
|
|
209
|
+
|
|
210
|
+
```yaml
|
|
211
|
+
network:
|
|
212
|
+
latency:
|
|
213
|
+
min_ms: 10
|
|
214
|
+
max_ms: 100
|
|
215
|
+
bandwidth_kbps: 256
|
|
216
|
+
packet_loss_percent: 5
|
|
217
|
+
|
|
218
|
+
events:
|
|
219
|
+
# Network partition
|
|
220
|
+
- type: "network_partition"
|
|
221
|
+
time: 30
|
|
222
|
+
duration: 15
|
|
223
|
+
groups: [[0,1,2], [3,4,5]]
|
|
224
|
+
|
|
225
|
+
# Node failures
|
|
226
|
+
- type: "node_crash"
|
|
227
|
+
time: 45
|
|
228
|
+
nodes: [2, 5]
|
|
229
|
+
|
|
230
|
+
# Node recovery
|
|
231
|
+
- type: "node_restart"
|
|
232
|
+
time: 50
|
|
233
|
+
nodes: [2, 5]
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### Topology Options
|
|
237
|
+
|
|
238
|
+
```yaml
|
|
239
|
+
topology:
|
|
240
|
+
type: "random" # Random connections
|
|
241
|
+
# OR
|
|
242
|
+
type: "ring" # Ring topology
|
|
243
|
+
# OR
|
|
244
|
+
type: "star" # Star topology
|
|
245
|
+
# OR
|
|
246
|
+
type: "mesh" # Full mesh
|
|
247
|
+
# OR
|
|
248
|
+
type: "tree" # Tree topology
|
|
249
|
+
|
|
250
|
+
connectivity: 0.7 # For random: 70% connectivity
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
## Metrics and Analysis
|
|
254
|
+
|
|
255
|
+
### Collected Metrics
|
|
256
|
+
|
|
257
|
+
The simulator automatically collects:
|
|
258
|
+
- Messages sent/received per node
|
|
259
|
+
- Topology changes
|
|
260
|
+
- Connection count
|
|
261
|
+
- Time synchronization drift
|
|
262
|
+
- Custom application metrics
|
|
263
|
+
|
|
264
|
+
### Output Format
|
|
265
|
+
|
|
266
|
+
Results are saved as CSV:
|
|
267
|
+
|
|
268
|
+
```csv
|
|
269
|
+
timestamp,node_id,messages_sent,messages_received,connections,time_drift_ms
|
|
270
|
+
0,6481,0,0,0,150000
|
|
271
|
+
1,6481,1,0,2,145000
|
|
272
|
+
2,6481,1,3,2,140000
|
|
273
|
+
...
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### Analysis
|
|
277
|
+
|
|
278
|
+
```python
|
|
279
|
+
import pandas as pd
|
|
280
|
+
|
|
281
|
+
df = pd.read_csv('results/test_results.csv')
|
|
282
|
+
|
|
283
|
+
# Messages per node
|
|
284
|
+
print(df.groupby('node_id')['messages_received'].sum())
|
|
285
|
+
|
|
286
|
+
# Average connections
|
|
287
|
+
print(df.groupby('timestamp')['connections'].mean())
|
|
288
|
+
|
|
289
|
+
# Time sync performance
|
|
290
|
+
print(df.groupby('timestamp')['time_drift_ms'].max())
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
## CI/CD Integration
|
|
294
|
+
|
|
295
|
+
### GitHub Actions Integration
|
|
296
|
+
|
|
297
|
+
Simulator tests are integrated into the CI/CD pipeline in `.github/workflows/ci.yml`:
|
|
298
|
+
|
|
299
|
+
**The `simulator-tests` job:**
|
|
300
|
+
- Runs on every push and pull request
|
|
301
|
+
- Builds the simulator from the submodule
|
|
302
|
+
- Executes example test scenarios
|
|
303
|
+
- Uploads results as artifacts
|
|
304
|
+
|
|
305
|
+
**Configuration:**
|
|
306
|
+
```yaml
|
|
307
|
+
simulator-tests:
|
|
308
|
+
name: Simulator Integration Tests
|
|
309
|
+
runs-on: ubuntu-latest
|
|
310
|
+
steps:
|
|
311
|
+
- uses: actions/checkout@v4
|
|
312
|
+
with:
|
|
313
|
+
submodules: recursive
|
|
314
|
+
|
|
315
|
+
- name: Install dependencies
|
|
316
|
+
run: |
|
|
317
|
+
sudo apt-get install cmake ninja-build libboost-dev libboost-program-options-dev libyaml-cpp-dev
|
|
318
|
+
|
|
319
|
+
- name: Build simulator
|
|
320
|
+
run: |
|
|
321
|
+
cd test/simulator
|
|
322
|
+
mkdir build && cd build
|
|
323
|
+
cmake -G Ninja .. && ninja
|
|
324
|
+
|
|
325
|
+
- name: Run tests
|
|
326
|
+
run: |
|
|
327
|
+
cd test/simulator/build
|
|
328
|
+
bin/painlessmesh-simulator --config \
|
|
329
|
+
../../../examples/basic/test/simulator/scenarios/basic_mesh_test.yaml
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
This ensures example sketches are validated on every code change.
|
|
333
|
+
|
|
334
|
+
## Examples with Simulator Tests
|
|
335
|
+
|
|
336
|
+
### Currently Available
|
|
337
|
+
|
|
338
|
+
- ✅ `examples/basic/` - Basic mesh formation and broadcasting
|
|
339
|
+
|
|
340
|
+
### Coming Soon
|
|
341
|
+
|
|
342
|
+
- ⏳ `examples/startHere/` - Getting started example
|
|
343
|
+
- ⏳ `examples/echoNode/` - Echo server/client
|
|
344
|
+
- ⏳ `examples/bridge/` - Internet bridge functionality
|
|
345
|
+
- ⏳ `examples/mqttBridge/` - MQTT integration
|
|
346
|
+
|
|
347
|
+
## Documentation
|
|
348
|
+
|
|
349
|
+
- **Simulator Repository**: https://github.com/Alteriom/painlessMesh-simulator
|
|
350
|
+
- **Getting Started**: [test/simulator/GETTING_STARTED.md](../test/simulator/GETTING_STARTED.md)
|
|
351
|
+
- **Integration Guide**: [test/simulator/docs/INTEGRATING_INTO_YOUR_PROJECT.md](../test/simulator/docs/INTEGRATING_INTO_YOUR_PROJECT.md)
|
|
352
|
+
- **Configuration Reference**: [test/simulator/docs/CONFIGURATION_GUIDE.md](../test/simulator/docs/CONFIGURATION_GUIDE.md)
|
|
353
|
+
|
|
354
|
+
## Troubleshooting
|
|
355
|
+
|
|
356
|
+
### Submodule not initialized
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
cd test
|
|
360
|
+
git submodule update --init simulator
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
### Build errors
|
|
364
|
+
|
|
365
|
+
```bash
|
|
366
|
+
# Check dependencies
|
|
367
|
+
sudo apt-get install cmake ninja-build libboost-dev libyaml-cpp-dev
|
|
368
|
+
|
|
369
|
+
# Clean rebuild
|
|
370
|
+
cd test/simulator
|
|
371
|
+
rm -rf build
|
|
372
|
+
mkdir build && cd build
|
|
373
|
+
cmake -G Ninja ..
|
|
374
|
+
ninja
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
### Simulation timeouts
|
|
378
|
+
|
|
379
|
+
Increase timeout in YAML:
|
|
380
|
+
```yaml
|
|
381
|
+
simulation:
|
|
382
|
+
duration: 120 # Increase from 60
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
### Memory issues with large meshes
|
|
386
|
+
|
|
387
|
+
Reduce node count or increase system resources.
|
|
388
|
+
|
|
389
|
+
## Benefits
|
|
390
|
+
|
|
391
|
+
✅ **Fast iteration** - Test in seconds vs hours of hardware testing
|
|
392
|
+
✅ **Reproducible** - Same scenario always produces same results
|
|
393
|
+
✅ **Scalable** - Test with 100+ nodes on a laptop
|
|
394
|
+
✅ **Automated** - Integrate with CI/CD
|
|
395
|
+
✅ **Cost-effective** - No hardware required
|
|
396
|
+
✅ **Realistic** - Same code runs on hardware and simulator
|
|
397
|
+
|
|
398
|
+
## Contributing
|
|
399
|
+
|
|
400
|
+
To add simulator tests for more examples:
|
|
401
|
+
|
|
402
|
+
1. Create test structure in `examples/your_example/test/simulator/`
|
|
403
|
+
2. Adapt the .ino logic into a firmware adapter
|
|
404
|
+
3. Create test scenarios with validation criteria
|
|
405
|
+
4. Document in README.md
|
|
406
|
+
5. Submit pull request
|
|
407
|
+
|
|
408
|
+
See existing examples for patterns to follow.
|