@alteriom/painlessmesh 1.8.10 → 1.8.12

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 CHANGED
@@ -7,23 +7,82 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.8.12] - 2025-11-19
11
+
12
+ ### Changed
13
+
14
+ - **Documentation Updates** - Comprehensive documentation improvements
15
+ - Updated all documentation to reflect current library state
16
+ - Improved code examples and usage instructions
17
+ - Enhanced API reference documentation
18
+ - Verified all links and references
19
+ - Merged via PRs #152, #153
20
+
21
+ ### Fixed
22
+
23
+ - **Code Quality** - Resolved linting and formatting issues
24
+ - Fixed clang-format compliance across codebase
25
+ - Ensured prettier formatting consistency
26
+ - Improved code quality and maintainability
27
+
28
+ ## [1.8.11] - 2025-11-18
29
+
30
+ ### Fixed
31
+
32
+ - **Bridge Discovery Race Condition** - Fixed routing table timing issue that prevented reliable bridge status delivery
33
+ - **Root Cause**: Bridge was sending status messages before routing tables were fully established after connection
34
+ - Changed from `newConnectionCallback` to `changedConnectionCallbacks` for routing table readiness
35
+ - Ensures routing tables are properly configured before attempting to send bridge status
36
+ - Bridge now waits for routing table convergence before sending status messages to new nodes
37
+ - **Before Fix**: Messages sent too early could fail to reach destination due to incomplete routing
38
+ - **After Fix**: Bridge status reliably delivered once routing is properly established
39
+ - Core fix in `src/arduino/wifi.hpp` - uses connection change callbacks instead of new connection callbacks
40
+ - More robust than timing-based delays (previous 500ms approach)
41
+ - Resolves GitHub issue #142
42
+ - Merged via PR #142
43
+
44
+ - **Windows MSVC Compilation Compatibility** - Fixed access modifier issues for Windows builds
45
+ - MSVC compiler does not grant friend status to lambdas inside friend functions
46
+ - Changed semaphore methods (`semaphoreTake()`, `semaphoreGive()`) from protected to public
47
+ - Changed `droppedConnectionCallbacks` access for lambda compatibility
48
+ - **Impact**: Library now compiles successfully on Windows with MSVC compiler
49
+ - **Affected Platforms**: Windows desktop builds, Visual Studio projects
50
+ - Core fix in `src/painlessmesh/mesh.hpp` line ~2060
51
+ - Also updated access modifiers in `buffer.hpp`, `ntp.hpp`, and `router.hpp` for consistency
52
+ - No functional changes - purely compatibility improvements
53
+ - Maintains full compatibility with GCC/Clang compilers
54
+
55
+ - **Code Security Improvements** - Fixed multiple code scanning alerts
56
+ - Fixed wrong type of arguments to formatting functions (alerts #3, #5)
57
+ - Fixed potentially overrunning write with float to string conversion (alert #2)
58
+ - Fixed use of potentially dangerous function (alert #1)
59
+ - Improved type safety in string formatting operations
60
+ - Enhanced buffer safety for float conversions
61
+ - Merged via PRs #144, #145, #146, #147
62
+
63
+ ### Changed
64
+
65
+ - **CI/CD Reliability** - Added retry logic for Arduino package index updates
66
+ - Handles transient network failures during package publication
67
+ - Improves reliability of automated release workflow
68
+ - Reduces false failures in CI pipeline
69
+
10
70
  ## [1.8.10] - 2025-11-18
11
71
 
12
72
  ### Fixed
13
73
 
14
- - **Bridge Status Discovery - Direct Messaging** - Fixed newly connected nodes not receiving bridge status
15
- - **Root Cause**: Broadcast messages were not reaching newly connected nodes reliably
16
- - Time sync (NTP) was interfering with bridge discovery
17
- - Broadcast routing may not be fully established immediately after connection
18
- - **Solution**: Send bridge status directly to new node using `sendSingle()`
19
- - Changed from broadcast (`routing=2`) to single (`routing=1`)
20
- - Minimal 500ms delay (just for connection stability)
21
- - Direct targeted delivery ensures message reaches the new node
22
- - Time sync no longer affects bridge discovery
23
- - Location: `src/arduino/wifi.hpp` line ~809 in `initBridgeStatusBroadcast()`
24
- - Impact: Nodes discover bridges immediately (within 500ms) after connecting
25
- - Backward compatible: No API changes, internal delivery mechanism improved
74
+ - **Bridge Status Discovery - Direct Messaging** - Fixed newly connected nodes not receiving bridge status reliably
75
+ - Changed bridge status delivery mechanism from broadcast to direct single message
76
+ - Bridge now sends status directly to newly connected nodes using `sendSingle()` (routing=1)
77
+ - Added minimal 500ms delay for connection stability before sending status
78
+ - **Root Cause**: Broadcast routing may not be established immediately after connection; time sync (NTP) operations were interfering with bridge discovery
79
+ - **Before Fix**: Nodes could wait up to 30 seconds for bridge status via periodic broadcast; "No primary bridge available" errors
80
+ - **After Fix**: Nodes discover bridges within 500ms of connection; reliable bridge discovery regardless of NTP sync activity
81
+ - Direct targeted delivery ensures message reaches new node immediately
82
+ - Core fix in `src/arduino/wifi.hpp` line ~809 in `initBridgeStatusBroadcast()`
26
83
  - Resolves GitHub issue #135 "The latest fix does not work"
84
+ - 100% backward compatible - no API changes
85
+ - **Note**: Further improved in v1.8.11 with routing table readiness detection
27
86
 
28
87
  ## [1.8.9] - 2025-11-12
29
88
 
@@ -0,0 +1,146 @@
1
+ # AlteriomPainlessMesh Documentation Index
2
+
3
+ Complete guide to finding documentation in the AlteriomPainlessMesh library.
4
+
5
+ ## Quick Links
6
+
7
+ - 🌐 **[Online Documentation](https://alteriom.github.io/painlessMesh/)** - Interactive documentation website
8
+ - 📖 **[API Reference](https://alteriom.github.io/painlessMesh/#/api/doxygen)** - Complete API documentation
9
+ - 🎯 **[Examples](https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples)** - Code examples and tutorials
10
+
11
+ ## Core Documentation
12
+
13
+ ### Getting Started
14
+ - **[README.md](README.md)** - Project overview, features, and quick start
15
+ - **[docs/getting-started/quickstart.md](docs/getting-started/quickstart.md)** - Quick start guide
16
+ - **[docs/getting-started/installation.md](docs/getting-started/installation.md)** - Installation instructions
17
+ - **[docs/getting-started/first-mesh.md](docs/getting-started/first-mesh.md)** - Your first mesh network
18
+
19
+ ### Release Information
20
+ - **[CHANGELOG.md](CHANGELOG.md)** - Complete version history
21
+ - **[RELEASE_GUIDE.md](RELEASE_GUIDE.md)** - Release process for maintainers
22
+ - **[RELEASE_NOTES_1.8.12.md](RELEASE_NOTES_1.8.12.md)** - Latest release notes
23
+ - **[RELEASE_CHECKLIST_1.8.12.md](RELEASE_CHECKLIST_1.8.12.md)** - Release checklist
24
+
25
+ ### Contributing
26
+ - **[CONTRIBUTING.md](CONTRIBUTING.md)** - How to contribute to the project
27
+ - **[LICENSE](LICENSE)** - LGPL-3.0 license terms
28
+
29
+ ## Technical Documentation
30
+
31
+ ### Alteriom Extensions
32
+ - **[docs/alteriom/overview.md](docs/alteriom/overview.md)** - Alteriom extensions overview
33
+ - **[examples/alteriom/README.md](examples/alteriom/README.md)** - Alteriom package documentation
34
+ - **[examples/alteriom/alteriom_sensor_package.hpp](examples/alteriom/alteriom_sensor_package.hpp)** - Package definitions with extensive inline documentation
35
+
36
+ ### MQTT Integration
37
+ - **[docs/MQTT_BRIDGE_COMMANDS.md](docs/MQTT_BRIDGE_COMMANDS.md)** - MQTT command API
38
+ - **[docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md](docs/MQTT_BRIDGE_IMPLEMENTATION_SUMMARY.md)** - Implementation details
39
+ - **[docs/MQTT_SCHEMA_COMPLIANCE.md](docs/MQTT_SCHEMA_COMPLIANCE.md)** - Schema validation
40
+ - **[docs/OTA_COMMANDS_REFERENCE.md](docs/OTA_COMMANDS_REFERENCE.md)** - OTA update commands
41
+
42
+ ### Advanced Features
43
+ - **[docs/MESH_TOPOLOGY_GUIDE.md](docs/MESH_TOPOLOGY_GUIDE.md)** - Network topology reporting
44
+ - **[docs/BRIDGE_FAILOVER.md](docs/BRIDGE_FAILOVER.md)** - Bridge failover documentation
45
+ - **[docs/BRIDGE_HEALTH_MONITORING.md](docs/BRIDGE_HEALTH_MONITORING.md)** - Bridge health monitoring
46
+ - **[BRIDGE_TO_INTERNET.md](BRIDGE_TO_INTERNET.md)** - Connecting mesh to internet
47
+
48
+ ### Development
49
+ - **[docs/API_DESIGN_GUIDELINES.md](docs/API_DESIGN_GUIDELINES.md)** - API design patterns
50
+ - **[docs/VERSION_MANAGEMENT.md](docs/VERSION_MANAGEMENT.md)** - Version management guide
51
+ - **[docs/development/DOCKER_TESTING.md](docs/development/DOCKER_TESTING.md)** - Docker testing guide
52
+ - **[docs/development/TESTING_SUMMARY.md](docs/development/TESTING_SUMMARY.md)** - Test suite overview
53
+ - **[docs/development/ARDUINO_COMPLIANCE_SUMMARY.md](docs/development/ARDUINO_COMPLIANCE_SUMMARY.md)** - Arduino standards
54
+
55
+ ### Phase Documentation
56
+ - **[docs/PHASE1_GUIDE.md](docs/PHASE1_GUIDE.md)** - Phase 1 features (v1.6.x)
57
+ - **[docs/PHASE2_GUIDE.md](docs/PHASE2_GUIDE.md)** - Phase 2 features (v1.7.x+)
58
+ - **[docs/releases/FEATURE_HISTORY.md](docs/releases/FEATURE_HISTORY.md)** - Consolidated feature history
59
+
60
+ ## Example Code
61
+
62
+ ### Basic Examples
63
+ - **[examples/basic/](examples/basic/)** - Basic mesh networking
64
+ - **[examples/startHere/](examples/startHere/)** - Simple starting point
65
+
66
+ ### Alteriom Examples
67
+ - **[examples/alteriom/](examples/alteriom/)** - Core Alteriom package examples
68
+ - **[examples/alteriomSensorNode/](examples/alteriomSensorNode/)** - Sensor node implementation
69
+ - **[examples/alteriomImproved/](examples/alteriomImproved/)** - Enhanced sensor node
70
+ - **[examples/alteriomMetricsHealth/](examples/alteriomMetricsHealth/)** - Metrics and health monitoring
71
+ - **[examples/alteriomPhase1/](examples/alteriomPhase1/)** - Phase 1 features demo
72
+ - **[examples/alteriomPhase2/](examples/alteriomPhase2/)** - Phase 2 features demo
73
+
74
+ ### Bridge Examples
75
+ - **[examples/bridge/](examples/bridge/)** - Basic bridge examples
76
+ - **[examples/bridge_failover/](examples/bridge_failover/)** - Bridge failover implementation
77
+ - **[examples/multi_bridge/](examples/multi_bridge/)** - Multiple bridge setup
78
+ - **[examples/bridgeAwareSensorNode/](examples/bridgeAwareSensorNode/)** - Bridge-aware nodes
79
+
80
+ ### MQTT Examples
81
+ - **[examples/mqttBridge/](examples/mqttBridge/)** - MQTT bridge
82
+ - **[examples/mqttCommandBridge/](examples/mqttCommandBridge/)** - Command bridge
83
+ - **[examples/mqttStatusBridge/](examples/mqttStatusBridge/)** - Status reporting bridge
84
+ - **[examples/mqttTopologyTest/](examples/mqttTopologyTest/)** - Topology testing
85
+
86
+ ### Advanced Examples
87
+ - **[examples/otaReceiver/](examples/otaReceiver/)** - OTA update receiver
88
+ - **[examples/otaSender/](examples/otaSender/)** - OTA update sender
89
+ - **[examples/ntpTimeSyncBridge/](examples/ntpTimeSyncBridge/)** - NTP time sync bridge
90
+ - **[examples/ntpTimeSyncNode/](examples/ntpTimeSyncNode/)** - NTP time sync node
91
+ - **[examples/webServer/](examples/webServer/)** - Mesh web server
92
+ - **[examples/diagnosticsExample/](examples/diagnosticsExample/)** - Diagnostics tools
93
+
94
+ ## Troubleshooting
95
+
96
+ - **[docs/troubleshooting/common-issues.md](docs/troubleshooting/common-issues.md)** - Common problems and solutions
97
+ - **[docs/troubleshooting/ESP32_C6_COMPATIBILITY.md](docs/troubleshooting/ESP32_C6_COMPATIBILITY.md)** - ESP32-C6 issues
98
+ - **[docs/troubleshooting/debugging.md](docs/troubleshooting/debugging.md)** - Debugging techniques
99
+ - **[docs/troubleshooting/faq.md](docs/troubleshooting/faq.md)** - Frequently asked questions
100
+
101
+ ## Architecture Documentation
102
+
103
+ - **[docs/architecture/mesh-architecture.md](docs/architecture/mesh-architecture.md)** - Mesh architecture overview
104
+ - **[docs/architecture/plugin-system.md](docs/architecture/plugin-system.md)** - Plugin architecture
105
+ - **[docs/architecture/routing.md](docs/architecture/routing.md)** - Message routing
106
+ - **[docs/architecture/time-sync.md](docs/architecture/time-sync.md)** - Time synchronization
107
+
108
+ ## Support & Community
109
+
110
+ ### Getting Help
111
+ - **GitHub Issues**: https://github.com/Alteriom/painlessMesh/issues
112
+ - **GitHub Discussions**: https://github.com/Alteriom/painlessMesh/discussions
113
+
114
+ ### Package Registries
115
+ - **NPM**: https://www.npmjs.com/package/@alteriom/painlessmesh
116
+ - **PlatformIO**: https://registry.platformio.org/libraries/alteriom/painlessMesh
117
+ - **Arduino Library Manager**: Search for "AlteriomPainlessMesh"
118
+
119
+ ## Version-Specific Documentation
120
+
121
+ ### Current Version (1.8.12)
122
+ - Focus on documentation improvements and code quality
123
+ - Added prettier configuration for consistent formatting
124
+ - Enhanced inline documentation
125
+ - See [RELEASE_NOTES_1.8.12.md](RELEASE_NOTES_1.8.12.md) for details
126
+
127
+ ### Previous Versions
128
+ - **v1.8.11** - Bridge discovery and Windows MSVC compatibility fixes
129
+ - **v1.8.10** - Bridge status direct messaging improvements
130
+ - **v1.8.9** - Bridge self-registration fixes
131
+ - **v1.8.0** - Bridge failover introduction
132
+ - **v1.7.0** - Phase 2 features (broadcast OTA, MQTT status bridge)
133
+ - **v1.6.0** - Phase 1 features (Alteriom packages)
134
+
135
+ See [CHANGELOG.md](CHANGELOG.md) for complete version history.
136
+
137
+ ## Contributing to Documentation
138
+
139
+ To contribute to documentation:
140
+ 1. Follow the style guide in existing documentation
141
+ 2. Update this index when adding new documentation files
142
+ 3. Ensure all links are functional
143
+ 4. Use Markdown for all documentation
144
+ 5. Include code examples where appropriate
145
+
146
+ For detailed contribution guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md).
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AlteriomPainlessMesh
2
2
 
3
- > **📚 [Complete Documentation](https://alteriom.github.io/painlessMesh/)** | **📖 [API Reference](https://alteriom.github.io/painlessMesh/#/api/doxygen)** | **🎯 [Examples](https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples)**
3
+ > **📚 [Complete Documentation](https://alteriom.github.io/painlessMesh/)** | **📖 [API Reference](https://alteriom.github.io/painlessMesh/#/api/doxygen)** | **🎯 [Examples](https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples)** | **🗂️ [Documentation Index](DOCUMENTATION_INDEX.md)**
4
4
 
5
5
  <div align="center">
6
6
 
@@ -0,0 +1,96 @@
1
+ # Release Notes - Version 1.8.12
2
+
3
+ **Release Date:** 2025-11-19
4
+
5
+ ## Overview
6
+
7
+ Version 1.8.12 is a maintenance release focused on documentation improvements and code quality enhancements. This release includes changes from PRs #152 and #153, ensuring comprehensive documentation coverage and adherence to code formatting standards.
8
+
9
+ ## What's New
10
+
11
+ ### Documentation Enhancements
12
+
13
+ - **Comprehensive Documentation Review** - All documentation has been reviewed and updated to reflect the current state of the library
14
+ - **API Reference Updates** - Improved clarity and completeness in API documentation
15
+ - **Example Code Documentation** - Enhanced inline documentation for example projects
16
+ - **Package Documentation** - Updated documentation for all Alteriom custom packages
17
+
18
+ ### Code Quality Improvements
19
+
20
+ - **Prettier Configuration** - Added prettier configuration for consistent JSON and Markdown formatting
21
+ - New `.prettierrc` configuration file
22
+ - New `.prettierignore` file to exclude build artifacts and dependencies
23
+ - Added `npm run format` and `npm run format:check` scripts
24
+ - **Clang-Format Compliance** - Ensured all C++ code follows established formatting standards
25
+ - **Code Organization** - Improved code structure and maintainability
26
+
27
+ ### Version Updates
28
+
29
+ - Updated all version references across:
30
+ - `package.json` - NPM package version
31
+ - `library.json` - PlatformIO library version
32
+ - `library.properties` - Arduino library version
33
+ - `src/painlessMesh.h` - Header file version comments
34
+ - `src/AlteriomPainlessMesh.h` - Version defines and comments
35
+
36
+ ## Installation
37
+
38
+ ### Arduino Library Manager
39
+ ```
40
+ Sketch → Include Library → Manage Libraries → Search "AlteriomPainlessMesh" → Install
41
+ ```
42
+
43
+ ### PlatformIO
44
+ ```ini
45
+ [env:myenv]
46
+ lib_deps =
47
+ alteriom/AlteriomPainlessMesh @ ^1.8.12
48
+ ```
49
+
50
+ ### NPM
51
+ ```bash
52
+ npm install @alteriom/painlessmesh@1.8.12
53
+ ```
54
+
55
+ ## Compatibility
56
+
57
+ - **ESP32** - All variants supported
58
+ - **ESP8266** - All variants supported
59
+ - **Arduino IDE** - Version 1.8.0 or higher
60
+ - **PlatformIO** - Latest version
61
+ - **ArduinoJson** - Version 7.4.2 or higher
62
+ - **TaskScheduler** - Version 4.0.0 or higher
63
+
64
+ ## Migration Guide
65
+
66
+ This is a patch release with no breaking changes. Users can upgrade from any 1.8.x version without code modifications.
67
+
68
+ ## Known Issues
69
+
70
+ None identified in this release.
71
+
72
+ ## Pull Requests Included
73
+
74
+ - PR #152 - Documentation improvements
75
+ - PR #153 - Code quality enhancements
76
+
77
+ ## Contributors
78
+
79
+ Special thanks to all contributors who helped make this release possible!
80
+
81
+ ## Documentation
82
+
83
+ - **Main Documentation**: https://alteriom.github.io/painlessMesh/
84
+ - **API Reference**: https://alteriom.github.io/painlessMesh/#/api/doxygen
85
+ - **Examples**: https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples
86
+ - **GitHub Repository**: https://github.com/Alteriom/painlessMesh
87
+
88
+ ## Support
89
+
90
+ For questions, issues, or feature requests:
91
+ - **GitHub Issues**: https://github.com/Alteriom/painlessMesh/issues
92
+ - **Documentation**: https://alteriom.github.io/painlessMesh/
93
+
94
+ ## License
95
+
96
+ This project is licensed under LGPL-3.0. See the LICENSE file for details.
@@ -0,0 +1,209 @@
1
+ # Channel Synchronization in painlessMesh
2
+
3
+ ## Problem Statement
4
+
5
+ When a mesh network operates on one channel and a node promotes to bridge via election, it may connect to a router operating on a different channel. This creates a channel mismatch where:
6
+
7
+ 1. Bridge node switches to router's channel (e.g., channel 6)
8
+ 2. Other mesh nodes remain on original channel (e.g., channel 1)
9
+ 3. Bridge takeover announcements sent on new channel are not heard by nodes on old channel
10
+ 4. Nodes cannot find the mesh network and become isolated
11
+
12
+ ## Solution Overview
13
+
14
+ The solution has two complementary parts:
15
+
16
+ ### Part 1: Automatic Channel Re-detection
17
+
18
+ Nodes automatically detect when they can't find the mesh on their current channel and trigger a full channel scan to locate it.
19
+
20
+ **Implementation:** `src/painlessMeshSTA.cpp` and `src/painlessMeshSTA.h`
21
+
22
+ **Key Components:**
23
+ - `consecutiveEmptyScans` counter tracks scans with no mesh nodes found
24
+ - `EMPTY_SCAN_THRESHOLD` constant (6 scans) determines when to trigger re-scan
25
+ - Full channel scan using `scanForMeshChannel()` when threshold reached
26
+ - Automatic channel update and AP restart when mesh found on different channel
27
+
28
+ **Flow:**
29
+ ```
30
+ 1. Node scans on current channel (e.g., channel 1)
31
+ 2. Finds no mesh nodes → increment consecutiveEmptyScans
32
+ 3. Repeat for EMPTY_SCAN_THRESHOLD scans (~30 seconds with fast scanning)
33
+ 4. Trigger scanForMeshChannel() to scan ALL channels (1-13)
34
+ 5. If mesh found on different channel:
35
+ a. Update mesh->_meshChannel to detected channel
36
+ b. Restart AP on new channel
37
+ c. Reset consecutiveEmptyScans counter
38
+ 6. Continue normal scanning on new channel
39
+ ```
40
+
41
+ **Safeguards:**
42
+ - Only triggers when WiFi.status() != WL_CONNECTED (not when stably connected)
43
+ - Only triggers when channel > 0 (channel 0 already means auto-detect)
44
+ - Resets counter when mesh nodes are found (prevents false triggers)
45
+
46
+ ### Part 2: Dual-Channel Takeover Announcements
47
+
48
+ Bridge promotion sends takeover announcements on both the old and new channels to ensure all nodes are notified.
49
+
50
+ **Implementation:** `src/arduino/wifi.hpp` in `promoteToBridge()` method
51
+
52
+ **Flow:**
53
+ ```
54
+ 1. Node wins bridge election
55
+ 2. Send takeover announcement on CURRENT channel (e.g., channel 1)
56
+ → Nodes still on channel 1 receive this announcement
57
+ 3. Wait 1 second for announcement to propagate
58
+ 4. Stop mesh and reinitialize as bridge via initAsBridge()
59
+ → Connects to router, detects router's channel (e.g., channel 6)
60
+ → Initializes mesh on channel 6
61
+ 5. Schedule follow-up takeover announcement on NEW channel (channel 6)
62
+ → Sent 3 seconds after initialization
63
+ → Nodes that switched to channel 6 receive this announcement
64
+ ```
65
+
66
+ **Benefits:**
67
+ - Early announcement notifies nodes on old channel before bridge switches
68
+ - Delayed announcement notifies nodes that switched early or quickly found new channel
69
+ - Ensures complete mesh awareness regardless of node timing
70
+
71
+ ## Expected Behavior
72
+
73
+ ### Scenario: Bridge Promotion with Channel Change
74
+
75
+ **Setup:**
76
+ - Node1: Regular mesh node on channel 1
77
+ - Node2: Regular mesh node on channel 1 (weak router signal)
78
+ - Router: Operating on channel 6
79
+
80
+ **Sequence:**
81
+ 1. Node2 starts mesh on channel 1 (default, no router connection)
82
+ 2. Node1 joins mesh on channel 1
83
+ 3. Node1 wins bridge election (better router signal)
84
+ 4. Node1 sends "Becoming bridge" announcement on channel 1
85
+ 5. Node2 receives announcement
86
+ 6. Node1 connects to router on channel 6, initializes mesh on channel 6
87
+ 7. Node1 sends follow-up "I'm the bridge" announcement on channel 6
88
+ 8. Node2 can't find mesh on channel 1 for 6 consecutive scans
89
+ 9. Node2 triggers full channel scan, finds mesh on channel 6
90
+ 10. Node2 updates to channel 6, restarts AP on channel 6
91
+ 11. Node2 reconnects to Node1 on channel 6
92
+ 12. Mesh network is now unified on channel 6
93
+
94
+ **Timeline:**
95
+ - T+0s: Node1 wins election, sends announcement on channel 1
96
+ - T+1s: Node1 stops mesh on channel 1
97
+ - T+2s: Node1 initializes mesh on channel 6
98
+ - T+5s: Node1 sends follow-up announcement on channel 6
99
+ - T+30s: Node2 can't find mesh on channel 1 (fast scanning)
100
+ - T+30s: Node2 triggers channel re-scan
101
+ - T+31s: Node2 finds mesh on channel 6
102
+ - T+32s: Node2 restarts AP on channel 6
103
+ - T+35s: Node2 reconnects to mesh on channel 6
104
+
105
+ ## Configuration
106
+
107
+ ### Adjusting Re-scan Threshold
108
+
109
+ The `EMPTY_SCAN_THRESHOLD` is defined in `src/painlessMeshSTA.h`:
110
+
111
+ ```cpp
112
+ static const uint16_t EMPTY_SCAN_THRESHOLD = 6; // ~30 seconds at default SCAN_INTERVAL
113
+ ```
114
+
115
+ **Trade-offs:**
116
+ - **Lower value** (e.g., 3): Faster channel detection, but more susceptible to false triggers
117
+ - **Higher value** (e.g., 10): More stable, but slower response to channel changes
118
+
119
+ ### Scan Timing
120
+
121
+ Default scan intervals defined in `src/painlessmesh/configuration.hpp`:
122
+
123
+ ```cpp
124
+ #define SCAN_INTERVAL 30 * TASK_SECOND // AP scan period in ms
125
+ ```
126
+
127
+ When no mesh nodes found, scanning switches to fast mode:
128
+ ```cpp
129
+ task.setInterval(0.5 * SCAN_INTERVAL); // 15 seconds
130
+ ```
131
+
132
+ With EMPTY_SCAN_THRESHOLD=6 and fast scanning:
133
+ - Time to trigger re-scan: 6 × 15s = 90 seconds (~1.5 minutes)
134
+
135
+ ## Debugging
136
+
137
+ ### Log Messages
138
+
139
+ **Channel Re-detection:**
140
+ ```
141
+ CONNECTION: connectToAP(): No mesh nodes found for 6 scans, triggering channel re-detection
142
+ CONNECTION: scanForMeshChannel(): Scanning all channels for mesh 'YourMesh'...
143
+ CONNECTION: scanForMeshChannel(): Found mesh on channel 6 (RSSI: -45)
144
+ CONNECTION: connectToAP(): Mesh found on different channel 6 (was 1), updating...
145
+ CONNECTION: connectToAP(): Restarting AP from channel 1 to channel 6
146
+ CONNECTION: connectToAP(): AP restarted on channel 6
147
+ ```
148
+
149
+ **Bridge Promotion:**
150
+ ```
151
+ STARTUP: === Becoming Bridge Node ===
152
+ STARTUP: Sending takeover announcement on current channel before switching...
153
+ STARTUP: ✓ Takeover announcement sent on channel 1
154
+ STARTUP: Step 1: Connecting to router YourRouter...
155
+ STARTUP: ✓ Router connected on channel 6
156
+ STARTUP: Step 2: Initializing mesh on channel 6...
157
+ STARTUP: ✓ Bridge promotion complete on channel 6
158
+ STARTUP: Sending follow-up takeover announcement on new channel 6
159
+ STARTUP: ✓ Follow-up takeover announcement sent
160
+ ```
161
+
162
+ ### Common Issues
163
+
164
+ **Issue:** Nodes don't switch channels
165
+ - **Check:** Ensure `channel=0` in init() for auto-detection
166
+ - **Check:** Verify nodes are not connected via stationManual() to router
167
+ - **Check:** Increase log level to see scanning activity
168
+
169
+ **Issue:** Channel switching takes too long
170
+ - **Solution:** Reduce EMPTY_SCAN_THRESHOLD in painlessMeshSTA.h
171
+ - **Trade-off:** May increase false triggers during temporary network instability
172
+
173
+ **Issue:** Bridge promotion doesn't work
174
+ - **Check:** Verify router credentials are configured
175
+ - **Check:** Ensure router has good signal strength (> -80 dBm)
176
+ - **Check:** Confirm router is on a valid channel (1-13 for 2.4GHz)
177
+
178
+ ## Testing
179
+
180
+ ### Manual Testing Procedure
181
+
182
+ 1. Setup two ESP32/ESP8266 nodes with painlessMesh
183
+ 2. Configure router on channel 6
184
+ 3. Start both nodes without router credentials (will use channel 1)
185
+ 4. Configure one node with router credentials and trigger election
186
+ 5. Monitor serial output for channel switching messages
187
+ 6. Verify both nodes eventually operate on channel 6
188
+ 7. Verify mesh connectivity is maintained
189
+
190
+ ### Expected Results
191
+
192
+ - Bridge node switches to router channel within 5 seconds
193
+ - Non-bridge nodes detect channel change within 90 seconds
194
+ - All nodes reconnect on new channel
195
+ - No loss of mesh connectivity (except during transition)
196
+
197
+ ## Related Files
198
+
199
+ - `src/painlessMeshSTA.h` - StationScan class definition with channel re-detection
200
+ - `src/painlessMeshSTA.cpp` - Channel re-detection implementation
201
+ - `src/arduino/wifi.hpp` - Bridge promotion with dual announcements
202
+ - `test/catch/catch_channel_resync.cpp` - Unit tests for channel synchronization
203
+ - `BRIDGE_TO_INTERNET.md` - Bridge setup documentation
204
+
205
+ ## References
206
+
207
+ - Issue #137: Bridge takeover announcements not heard across channels
208
+ - WiFi channels: 1-13 for 2.4GHz (channels 12-13 restricted in some regions)
209
+ - ESP32/ESP8266 can only operate on one channel at a time in AP+STA mode