@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.
@@ -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.