@alteriom/painlessmesh 1.9.6 → 1.9.8
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 +55 -0
- package/README.md +42 -175
- package/docs/troubleshooting/common-issues.md +26 -0
- package/docs/troubleshooting/external-device-connection.md +283 -0
- package/examples/bridge/bridge.ino +23 -0
- package/examples/bridge_failover/bridge_failover.ino +24 -0
- package/library.json +1 -1
- package/library.properties +1 -1
- package/package.json +4 -4
- package/src/AlteriomPainlessMesh.h +3 -3
- package/src/arduino/wifi.hpp +850 -547
- package/src/painlessMesh.h +2 -2
- package/src/painlessMeshSTA.cpp +11 -2
- package/src/painlessmesh/mesh.hpp +34 -29
- package/src/painlessmesh/tcp.hpp +34 -8
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,61 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- TBD
|
|
13
|
+
|
|
14
|
+
### Changed
|
|
15
|
+
|
|
16
|
+
- TBD
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- TBD
|
|
21
|
+
|
|
22
|
+
## [1.9.8] - 2025-12-14
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
|
|
26
|
+
- **Heap Corruption on TCP Connection Errors** (#254) - Fixed ESP32 heap corruption crashes during AsyncClient deletion
|
|
27
|
+
- **Root Cause**: AsyncClient objects were being deleted synchronously from within their own error callback handlers, causing heap corruption and use-after-free crashes
|
|
28
|
+
- **Symptom**: ESP32 devices crash with "CORRUPT HEAP: Bad head at 0x4083a398. Expected 0xabba1234 got 0xfefefefe" during TCP connection error handling
|
|
29
|
+
- **Solution**: Deferred AsyncClient deletion using task scheduler to execute after error handler completes
|
|
30
|
+
- Changed from synchronous `delete client` to deferred deletion via `mesh.addTask([client]() { delete client; }, 0)`
|
|
31
|
+
- Deletion now occurs microseconds after error handler returns, preventing use-after-free
|
|
32
|
+
- Added logging for cleanup operations to aid debugging
|
|
33
|
+
- **Impact**: Eliminates heap corruption crashes on ESP32 during TCP connection retries and error conditions
|
|
34
|
+
- **Files Modified**: `src/painlessmesh/tcp.hpp` (lines 138, 149)
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- **README Version Reference** - Updated version banner to 1.9.7 for consistency with release history
|
|
39
|
+
|
|
40
|
+
## [1.9.7] - 2025-12-13
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- **External Device WiFi AP Connection** (#231) - Fixed DHCP and AP initialization issues preventing phones and computers from connecting to bridge
|
|
45
|
+
- **Root Cause**: When AP was restarted during channel changes, DHCP server was not properly reinitialized due to incomplete WiFi stack reset
|
|
46
|
+
- **Symptom**: External devices (Android phones, Windows 11 computers) cannot connect to mesh WiFi AP or fail to receive IP addresses via DHCP
|
|
47
|
+
- **Solution**: Improved AP restart sequence and DHCP initialization:
|
|
48
|
+
- Added explicit `WiFi.enableAP(true)` for ESP32 to ensure DHCP server starts
|
|
49
|
+
- Changed `softAPdisconnect(false)` to `softAPdisconnect(true)` for proper DHCP shutdown
|
|
50
|
+
- Increased timing delays: 200ms before AP restart + 100ms stabilization after
|
|
51
|
+
- Added logging for AP configuration to aid debugging
|
|
52
|
+
- **Impact**: External devices can now reliably connect to bridge AP for debugging and testing
|
|
53
|
+
|
|
54
|
+
### Documentation
|
|
55
|
+
|
|
56
|
+
- **External Device Connection Guide** - New comprehensive guide for connecting phones/computers to mesh AP
|
|
57
|
+
- Complete connection instructions for Android, Windows, macOS, Linux
|
|
58
|
+
- Troubleshooting section for common connection issues
|
|
59
|
+
- Security best practices and warnings
|
|
60
|
+
- Example debug sessions with network tools
|
|
61
|
+
- Added to bridge examples with detailed setup notes
|
|
62
|
+
|
|
8
63
|
## [1.9.6] - 2025-12-10
|
|
9
64
|
|
|
10
65
|
### Fixed
|
package/README.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
<div align="center">
|
|
6
6
|
|
|
7
|
-
**Version 1.9.
|
|
7
|
+
**Version 1.9.8** - Latest release with ESP32 heap corruption fix and improved TCP error handling
|
|
8
8
|
|
|
9
9
|
[](https://github.com/Alteriom/painlessMesh/actions/workflows/ci.yml)
|
|
10
10
|
[](https://github.com/Alteriom/painlessMesh/actions/workflows/docs.yml)
|
|
@@ -647,199 +647,66 @@ If you like the library please consider supporting its development. Your contrib
|
|
|
647
647
|
|
|
648
648
|
**[Donate via PayPal](https://www.paypal.com/paypalme/domlavoie)** • [dominic.lavoie@gmail.com](mailto:dominic.lavoie@gmail.com)
|
|
649
649
|
|
|
650
|
-
## 📚
|
|
650
|
+
## 📚 Documentation
|
|
651
651
|
|
|
652
|
-
|
|
652
|
+
### 📖 Essential Guides
|
|
653
653
|
|
|
654
|
-
|
|
654
|
+
| Document | Description |
|
|
655
|
+
|----------|-------------|
|
|
656
|
+
| **[📘 User Guide](USER_GUIDE.md)** | **Complete comprehensive guide** - Everything you need to know |
|
|
657
|
+
| **[🌉 Bridge Guide](BRIDGE_TO_INTERNET.md)** | Connect mesh to Internet, MQTT, and cloud services |
|
|
658
|
+
| **[📋 Documentation Hub](.github/DOCUMENTATION.md)** | Central navigation for all documentation resources |
|
|
659
|
+
| **[🌐 Online Docs](https://alteriom.github.io/painlessMesh/)** | Interactive documentation website with API reference |
|
|
655
660
|
|
|
656
|
-
|
|
661
|
+
### 🚀 Quick Links
|
|
657
662
|
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
| **🌐 First Mesh** | Build a real multi-node network | [📖 Build Now](https://alteriom.github.io/painlessMesh/#/getting-started/first-mesh) |
|
|
663
|
+
**New to AlteriomPainlessMesh?**
|
|
664
|
+
- [Quick Start](docs/getting-started/quickstart.md) - Get your first mesh running in 5 minutes
|
|
665
|
+
- [Installation](docs/getting-started/installation.md) - Arduino IDE and PlatformIO setup
|
|
666
|
+
- [First Mesh](docs/getting-started/first-mesh.md) - Build a multi-node network
|
|
663
667
|
|
|
664
|
-
|
|
668
|
+
**Reference Documentation:**
|
|
669
|
+
- [Core API](docs/api/core-api.md) - painlessMesh class methods
|
|
670
|
+
- [Alteriom Extensions](docs/alteriom/overview.md) - SensorPackage, CommandPackage, StatusPackage
|
|
671
|
+
- [Examples](examples/) - 16 working examples for common scenarios
|
|
665
672
|
|
|
666
|
-
**
|
|
673
|
+
**Need Help?**
|
|
674
|
+
- [FAQ](docs/troubleshooting/faq.md) - Frequently asked questions
|
|
675
|
+
- [Common Issues](docs/troubleshooting/common-issues.md) - Troubleshooting guide
|
|
676
|
+
- [GitHub Issues](https://github.com/Alteriom/painlessMesh/issues) - Bug reports and support
|
|
667
677
|
|
|
668
|
-
|
|
669
|
-
|---------|-------------|------|
|
|
670
|
-
| **🔧 Core API** | painlessMesh class reference and methods | [📖 Core API](https://alteriom.github.io/painlessMesh/#/api/core-api) |
|
|
671
|
-
| **📦 Doxygen API** | Auto-generated complete API documentation | [📖 Browse API](https://alteriom.github.io/painlessMesh/#/api/doxygen) |
|
|
672
|
-
| **⚙️ Configuration** | All mesh configuration options | [📖 Configure](https://alteriom.github.io/painlessMesh/#/api/configuration) |
|
|
673
|
-
| **🔄 Callbacks** | Event handling and callback patterns | [📖 Events](https://alteriom.github.io/painlessMesh/#/api/callbacks) |
|
|
674
|
-
|
|
675
|
-
### 🎯 Alteriom Extensions
|
|
676
|
-
|
|
677
|
-
**IoT-ready packages for production applications:**
|
|
678
|
-
|
|
679
|
-
| Package | Purpose | Documentation |
|
|
680
|
-
|---------|---------|---------------|
|
|
681
|
-
| **📊 SensorPackage** | Environmental data collection | [📖 Sensor Docs](https://alteriom.github.io/painlessMesh/#/alteriom/overview) |
|
|
682
|
-
| **⚡ CommandPackage** | Device control and automation | [📖 Command Docs](https://alteriom.github.io/painlessMesh/#/alteriom/overview) |
|
|
683
|
-
| **📈 StatusPackage** | Health monitoring and diagnostics | [📖 Status Docs](https://alteriom.github.io/painlessMesh/#/alteriom/overview) |
|
|
684
|
-
|
|
685
|
-
### 🏗️ Advanced Topics
|
|
686
|
-
|
|
687
|
-
**Deep dive into architecture and advanced usage:**
|
|
688
|
-
|
|
689
|
-
| Topic | Description | Link |
|
|
690
|
-
|-------|-------------|------|
|
|
691
|
-
| **🌳 Architecture** | How painlessMesh works internally | [📖 Architecture](https://alteriom.github.io/painlessMesh/#/architecture/mesh-architecture) |
|
|
692
|
-
| **🌉 Bridge to Internet** | Connect mesh to WiFi/Internet/MQTT | [📖 Bridge Guide](BRIDGE_TO_INTERNET.md) |
|
|
693
|
-
| **🔌 Plugin System** | Create custom message packages | [📖 Plugins](https://alteriom.github.io/painlessMesh/#/architecture/plugin-system) |
|
|
694
|
-
| **🎓 Tutorials** | Step-by-step examples and patterns | [📖 Tutorials](https://alteriom.github.io/painlessMesh/#/tutorials/basic-examples) |
|
|
695
|
-
| **🛠️ Troubleshooting** | Common issues and solutions | [📖 Help](https://alteriom.github.io/painlessMesh/#/troubleshooting/common-issues) |
|
|
696
|
-
|
|
697
|
-
### 📝 Quick Reference
|
|
698
|
-
|
|
699
|
-
**Bookmark these for daily development:**
|
|
700
|
-
|
|
701
|
-
- **[📋 Class Index](https://alteriom.github.io/painlessMesh/#/api/doxygen/classes)** - All classes with methods
|
|
702
|
-
- **[⚙️ Function Index](https://alteriom.github.io/painlessMesh/#/api/doxygen/functions)** - All functions and globals
|
|
703
|
-
- **[📁 File Structure](https://alteriom.github.io/painlessMesh/#/api/doxygen/files)** - Source code organization
|
|
704
|
-
- **[❓ FAQ](https://alteriom.github.io/painlessMesh/#/troubleshooting/faq)** - Frequently asked questions
|
|
705
|
-
|
|
706
|
-
**📖 Examples:**
|
|
707
|
-
|
|
708
|
-
- **[Basic Example](examples/basic/basic.ino)** - Essential patterns and techniques
|
|
709
|
-
- **[Alteriom Sensor Node](examples/alteriom/alteriom.ino)** - IoT sensor packages
|
|
710
|
-
- **[Bridge Example](examples/bridge/bridge.ino)** - Connect mesh to Internet
|
|
711
|
-
|
|
712
|
-
**📋 Complete Documentation Index:** [docs/README.md](docs/README.md)
|
|
713
|
-
|
|
714
|
-
## painlessMesh API Summary
|
|
715
|
-
|
|
716
|
-
Here's a quick API overview.
|
|
678
|
+
## 🔧 Quick API Reference
|
|
717
679
|
|
|
680
|
+
**Core Methods:**
|
|
718
681
|
```cpp
|
|
719
682
|
#include "painlessMesh.h"
|
|
720
683
|
|
|
721
684
|
painlessMesh mesh;
|
|
722
|
-
```
|
|
723
|
-
|
|
724
|
-
### Member Functions
|
|
725
|
-
|
|
726
|
-
#### void painlessMesh::init(String ssid, String password, uint16_t port = 5555, WiFiMode_t connectMode = WIFI_AP_STA, _auth_mode authmode = AUTH_WPA2_PSK, uint8_t channel = 1, phy_mode_t phymode = PHY_MODE_11G, uint8_t maxtpw = 82, uint8_t hidden = 0, uint8_t maxconn = 4)
|
|
727
|
-
|
|
728
|
-
Add this to your setup() function.
|
|
729
|
-
Initialize the mesh network. This routine does the following things.
|
|
730
|
-
|
|
731
|
-
- Starts a wifi network
|
|
732
|
-
- Begins searching for other wifi networks that are part of the mesh
|
|
733
|
-
- Logs on to the best mesh network node it finds… if it doesn’t find anything, it starts a new search in 5 seconds.
|
|
734
|
-
|
|
735
|
-
`ssid` = the name of your mesh. All nodes share same AP ssid. They are distinguished by BSSID.
|
|
736
|
-
`password` = wifi password to your mesh.
|
|
737
|
-
`port` = the TCP port that you want the mesh server to run on. Defaults to 5555 if not specified.
|
|
738
|
-
`connectMode` = switch between WIFI_AP, WIFI_STA and WIFI_AP_STA (default) mode
|
|
739
|
-
|
|
740
|
-
#### void painlessMesh::stop()
|
|
741
|
-
|
|
742
|
-
Stop the node. This will cause the node to disconnect from all other nodes and stop/sending messages.
|
|
743
|
-
|
|
744
|
-
#### void painlessMesh::update( void )
|
|
745
|
-
|
|
746
|
-
Add this to your loop() function
|
|
747
|
-
This routine runs various maintenance tasks... Not super interesting, but things don't work without it.
|
|
748
|
-
|
|
749
|
-
#### void painlessMesh::onReceive( &receivedCallback )
|
|
750
|
-
|
|
751
|
-
Set a callback routine for any messages that are addressed to this node. Callback routine has the following structure.
|
|
752
|
-
|
|
753
|
-
`void receivedCallback( uint32_t from, String &msg )`
|
|
754
|
-
|
|
755
|
-
Every time this node receives a message, this callback routine will the called. “from” is the id of the original sender of the message, and “msg” is a string that contains the message. The message can be anything. A JSON, some other text string, or binary data.
|
|
756
|
-
|
|
757
|
-
#### void painlessMesh::onNewConnection( &newConnectionCallback )
|
|
758
|
-
|
|
759
|
-
This fires every time the local node makes a new connection. The callback has the following structure.
|
|
760
|
-
|
|
761
|
-
`void newConnectionCallback( uint32_t nodeId )`
|
|
762
|
-
|
|
763
|
-
`nodeId` is new connected node ID in the mesh.
|
|
764
685
|
|
|
765
|
-
|
|
686
|
+
// Initialize mesh
|
|
687
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &userScheduler, MESH_PORT);
|
|
766
688
|
|
|
767
|
-
|
|
689
|
+
// Main loop - call this in loop()
|
|
690
|
+
mesh.update();
|
|
768
691
|
|
|
769
|
-
|
|
692
|
+
// Send messages
|
|
693
|
+
mesh.sendBroadcast("Hello everyone!");
|
|
694
|
+
mesh.sendSingle(nodeId, "Hello specific node");
|
|
770
695
|
|
|
771
|
-
|
|
696
|
+
// Get information
|
|
697
|
+
uint32_t myId = mesh.getNodeId();
|
|
698
|
+
std::list<uint32_t> nodes = mesh.getNodeList();
|
|
772
699
|
|
|
773
|
-
|
|
700
|
+
// Register callbacks
|
|
701
|
+
mesh.onReceive(&receivedCallback);
|
|
702
|
+
mesh.onNewConnection(&newConnectionCallback);
|
|
703
|
+
mesh.onChangedConnections(&changedConnectionCallback);
|
|
774
704
|
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
#### void painlessMesh::onNodeTimeAdjusted( &nodeTimeAdjustedCallback )
|
|
780
|
-
|
|
781
|
-
This fires every time local time is adjusted to synchronize it with mesh time. Callback has the following structure.
|
|
782
|
-
|
|
783
|
-
`void onNodeTimeAdjusted(int32_t offset)`
|
|
784
|
-
|
|
785
|
-
`offset` is the adjustment delta that has been calculated and applied to local clock.
|
|
786
|
-
|
|
787
|
-
#### void onNodeDelayReceived(nodeDelayCallback_t onDelayReceived)
|
|
788
|
-
|
|
789
|
-
This fires when a time delay measurement response is received, after a request was sent. Callback has the following structure.
|
|
790
|
-
|
|
791
|
-
`void onNodeDelayReceived(uint32_t nodeId, int32_t delay)`
|
|
792
|
-
|
|
793
|
-
`nodeId` The node that originated response.
|
|
794
|
-
|
|
795
|
-
`delay` One way network trip delay in microseconds.
|
|
796
|
-
|
|
797
|
-
#### bool painlessMesh::sendBroadcast( String &msg, bool includeSelf = false)
|
|
798
|
-
|
|
799
|
-
Sends msg to every node on the entire mesh network. By default the current node is excluded from receiving the message (`includeSelf = false`). `includeSelf = true` overrides this behavior, causing the `receivedCallback` to be called when sending a broadcast message.
|
|
800
|
-
|
|
801
|
-
returns true if everything works, false if not. Prints an error message to Serial.print, if there is a failure.
|
|
802
|
-
|
|
803
|
-
#### bool painlessMesh::sendSingle(uint32_t dest, String &msg)
|
|
804
|
-
|
|
805
|
-
Sends msg to the node with Id == dest.
|
|
806
|
-
|
|
807
|
-
returns true if everything works, false if not. Prints an error message to Serial.print, if there is a failure.
|
|
808
|
-
|
|
809
|
-
#### String painlessMesh::subConnectionJson()
|
|
810
|
-
|
|
811
|
-
Returns mesh topology in JSON format.
|
|
812
|
-
|
|
813
|
-
#### std::list<uint32_t> painlessMesh::getNodeList()
|
|
814
|
-
|
|
815
|
-
Get a list of all known nodes. This includes nodes that are both directly and indirectly connected to the current node.
|
|
816
|
-
|
|
817
|
-
#### uint32_t painlessMesh::getNodeId( void )
|
|
818
|
-
|
|
819
|
-
Return the chipId of the node that we are running on.
|
|
820
|
-
|
|
821
|
-
#### uint32_t painlessMesh::getNodeTime( void )
|
|
822
|
-
|
|
823
|
-
Returns the mesh timebase microsecond counter. Rolls over 71 minutes from startup of the first node.
|
|
824
|
-
|
|
825
|
-
Nodes try to keep a common time base synchronizing to each other using an SNTP based protocol
|
|
826
|
-
|
|
827
|
-
#### bool painlessMesh::startDelayMeas(uint32_t nodeId)
|
|
828
|
-
|
|
829
|
-
Sends a node a packet to measure network trip delay to that node. Returns true if nodeId is connected to the mesh, false otherwise. After calling this function, user program have to wait to the response in the form of a callback specified by `void painlessMesh::onNodeDelayReceived(nodeDelayCallback_t onDelayReceived)`.
|
|
830
|
-
|
|
831
|
-
nodeDelayCallback_t is a function in the form of `void (uint32_t nodeId, int32_t delay)`.
|
|
832
|
-
|
|
833
|
-
#### void painlessMesh::stationManual( String ssid, String password, uint16_t port, uint8_t *remote_ip )
|
|
834
|
-
|
|
835
|
-
Connects the node to an AP outside the mesh. When specifying a `remote_ip` and `port`, the node opens a TCP connection after establishing the WiFi connection.
|
|
836
|
-
|
|
837
|
-
Note: The mesh must be on the same WiFi channel as the AP.
|
|
838
|
-
|
|
839
|
-
#### void painlessMesh::setDebugMsgTypes( uint16_t types )
|
|
705
|
+
// Debug configuration
|
|
706
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
707
|
+
```
|
|
840
708
|
|
|
841
|
-
|
|
842
|
-
ERROR | MESH_STATUS | CONNECTION | SYNC | COMMUNICATION | GENERAL | MSG_TYPES | REMOTE
|
|
709
|
+
**For complete API documentation, see [USER_GUIDE.md](USER_GUIDE.md#api-reference) or [online docs](https://alteriom.github.io/painlessMesh/#/api/core-api).**
|
|
843
710
|
|
|
844
711
|
# Funding
|
|
845
712
|
|
|
@@ -60,6 +60,32 @@ For Arduino IDE, download and install manually from: https://github.com/ESP32Asy
|
|
|
60
60
|
|
|
61
61
|
## Connection Issues
|
|
62
62
|
|
|
63
|
+
### External Devices Cannot Connect to Mesh AP
|
|
64
|
+
|
|
65
|
+
**Symptoms:**
|
|
66
|
+
- Phone or computer can't see the mesh WiFi network
|
|
67
|
+
- Can see network but can't connect
|
|
68
|
+
- Connected but no IP address assigned
|
|
69
|
+
- Connection drops frequently
|
|
70
|
+
|
|
71
|
+
**Solution:**
|
|
72
|
+
|
|
73
|
+
See the dedicated guide for connecting external devices:
|
|
74
|
+
|
|
75
|
+
📖 **[Connecting External Devices Guide](external-device-connection.md)**
|
|
76
|
+
|
|
77
|
+
**Quick Summary:**
|
|
78
|
+
|
|
79
|
+
External devices (phones, computers, test equipment) can connect to the bridge node's WiFi AP for debugging:
|
|
80
|
+
- **SSID**: Your MESH_PREFIX value
|
|
81
|
+
- **Password**: Your MESH_PASSWORD value
|
|
82
|
+
- **IP Range**: 10.x.x.x/24 (DHCP automatic)
|
|
83
|
+
- **Limits**: ESP32 supports 10 devices, ESP8266 supports 4
|
|
84
|
+
|
|
85
|
+
Common issues are DHCP timing, channel changes, and connection limits.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
63
89
|
### Nodes Not Connecting
|
|
64
90
|
|
|
65
91
|
**Symptoms:**
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# Connecting External Devices to painlessMesh Bridge
|
|
2
|
+
|
|
3
|
+
This guide explains how to connect external devices (phones, computers, test equipment) to a painlessMesh bridge node's WiFi Access Point for debugging and testing purposes.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Each painlessMesh node operates in AP+STA mode, broadcasting a WiFi Access Point (AP) with the mesh SSID. External devices can connect to this AP, though they typically don't get internet access (unless using shared gateway mode).
|
|
8
|
+
|
|
9
|
+
## When to Connect External Devices
|
|
10
|
+
|
|
11
|
+
You might want to connect external devices to the mesh AP when:
|
|
12
|
+
- Debugging mesh connectivity issues
|
|
13
|
+
- Running diagnostic tools (ping, network scanners)
|
|
14
|
+
- Testing DHCP configuration
|
|
15
|
+
- Monitoring mesh traffic
|
|
16
|
+
- Developing custom mesh applications
|
|
17
|
+
|
|
18
|
+
## Connection Details
|
|
19
|
+
|
|
20
|
+
### Basic Information
|
|
21
|
+
|
|
22
|
+
| Setting | Value |
|
|
23
|
+
|---------|-------|
|
|
24
|
+
| **SSID** | Your `MESH_PREFIX` value (e.g., "FishFarmMesh", "whateverYouLike") |
|
|
25
|
+
| **Password** | Your `MESH_PASSWORD` value (e.g., "securepass", "somethingSneaky") |
|
|
26
|
+
| **Security** | WPA2-PSK |
|
|
27
|
+
| **IP Range** | 10.x.x.x/24 (automatically assigned via DHCP) |
|
|
28
|
+
| **Gateway** | 10.x.x.1 (the bridge node itself) |
|
|
29
|
+
| **DNS** | 10.x.x.1 (the bridge node) |
|
|
30
|
+
|
|
31
|
+
### Node-Specific IP Addressing
|
|
32
|
+
|
|
33
|
+
Each mesh node gets a unique IP address based on its Node ID:
|
|
34
|
+
```
|
|
35
|
+
IP = 10.(NodeID >> 8).(NodeID & 0xFF).1
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Example: If Node ID is `0x1A2B`, the AP IP would be `10.26.43.1`
|
|
39
|
+
|
|
40
|
+
Connected clients receive IPs in the same subnet, typically starting from `.2`
|
|
41
|
+
|
|
42
|
+
## Connection Limits
|
|
43
|
+
|
|
44
|
+
The number of devices that can connect simultaneously depends on the platform:
|
|
45
|
+
|
|
46
|
+
| Platform | Max Connections | Notes |
|
|
47
|
+
|----------|----------------|-------|
|
|
48
|
+
| **ESP32** | 10 (default) | Configurable via `MAX_CONN` |
|
|
49
|
+
| **ESP8266** | 4 (default) | Configurable via `MAX_CONN` |
|
|
50
|
+
|
|
51
|
+
**Important**: Mesh nodes also count toward this limit! If 3 mesh nodes are connected to a bridge, only 7 slots remain for external devices on ESP32 (or 1 on ESP8266).
|
|
52
|
+
|
|
53
|
+
## Step-by-Step Connection Guide
|
|
54
|
+
|
|
55
|
+
### 1. Verify Bridge is Running
|
|
56
|
+
|
|
57
|
+
Check the serial output for these messages:
|
|
58
|
+
```
|
|
59
|
+
init(): Mesh channel set to X
|
|
60
|
+
apInit(): AP configured - SSID: YourMeshName, Channel: X, IP: 10.x.x.1
|
|
61
|
+
apInit(): AP active - Max connections: 10
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### 2. Connect Your Device
|
|
65
|
+
|
|
66
|
+
#### On Android:
|
|
67
|
+
1. Open WiFi settings
|
|
68
|
+
2. Look for network with your MESH_PREFIX name
|
|
69
|
+
3. Enter your MESH_PASSWORD
|
|
70
|
+
4. Wait for connection (may take 5-10 seconds)
|
|
71
|
+
5. Check IP address (should be 10.x.x.x)
|
|
72
|
+
|
|
73
|
+
#### On Windows 11:
|
|
74
|
+
1. Click WiFi icon in system tray
|
|
75
|
+
2. Find network with your MESH_PREFIX name
|
|
76
|
+
3. Click "Connect"
|
|
77
|
+
4. Enter your MESH_PASSWORD
|
|
78
|
+
5. Open Command Prompt and run `ipconfig` to verify IP
|
|
79
|
+
|
|
80
|
+
#### On macOS:
|
|
81
|
+
1. Click WiFi icon in menu bar
|
|
82
|
+
2. Select network with your MESH_PREFIX name
|
|
83
|
+
3. Enter your MESH_PASSWORD
|
|
84
|
+
4. Open Terminal and run `ifconfig` to verify IP
|
|
85
|
+
|
|
86
|
+
#### On Linux:
|
|
87
|
+
1. Use NetworkManager GUI or command line:
|
|
88
|
+
```bash
|
|
89
|
+
nmcli device wifi connect "FishFarmMesh" password "securepass"
|
|
90
|
+
```
|
|
91
|
+
2. Verify connection:
|
|
92
|
+
```bash
|
|
93
|
+
ip addr show
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### 3. Test Connectivity
|
|
97
|
+
|
|
98
|
+
Once connected, test basic connectivity:
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
# Ping the bridge/gateway
|
|
102
|
+
ping 10.x.x.1
|
|
103
|
+
|
|
104
|
+
# Check if you got an IP via DHCP
|
|
105
|
+
# Windows: ipconfig
|
|
106
|
+
# Linux/Mac: ifconfig or ip addr
|
|
107
|
+
|
|
108
|
+
# Try to reach other mesh nodes (if you know their IPs)
|
|
109
|
+
ping 10.y.y.1
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Troubleshooting
|
|
113
|
+
|
|
114
|
+
### Can't See the SSID
|
|
115
|
+
|
|
116
|
+
**Possible Causes:**
|
|
117
|
+
1. Bridge hasn't finished initializing (wait 10-15 seconds after boot)
|
|
118
|
+
2. Channel conflict with nearby WiFi networks
|
|
119
|
+
3. WiFi range issue
|
|
120
|
+
4. AP not properly started
|
|
121
|
+
|
|
122
|
+
**Solutions:**
|
|
123
|
+
1. Check serial output for "AP configured" message
|
|
124
|
+
2. Ensure `CONNECTION` debug level is enabled:
|
|
125
|
+
```cpp
|
|
126
|
+
mesh.setDebugMsgTypes(ERROR | STARTUP | CONNECTION);
|
|
127
|
+
```
|
|
128
|
+
3. Try power cycling the bridge
|
|
129
|
+
4. Check if the AP is hidden:
|
|
130
|
+
```cpp
|
|
131
|
+
// In your sketch, ensure:
|
|
132
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &scheduler, MESH_PORT,
|
|
133
|
+
WIFI_AP_STA, channel, 0); // 0 = not hidden
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Can Connect But Don't Get IP Address
|
|
137
|
+
|
|
138
|
+
**Possible Causes:**
|
|
139
|
+
1. DHCP server not initialized
|
|
140
|
+
2. Too many devices connected (limit reached)
|
|
141
|
+
3. IP conflict
|
|
142
|
+
4. WiFi stack timing issue
|
|
143
|
+
|
|
144
|
+
**Solutions:**
|
|
145
|
+
1. Disconnect and reconnect after 10 seconds
|
|
146
|
+
2. Check serial output for connection count
|
|
147
|
+
3. Try rebooting the bridge node
|
|
148
|
+
4. Ensure you're using the latest painlessMesh version with DHCP fixes
|
|
149
|
+
|
|
150
|
+
### Connection Drops Frequently
|
|
151
|
+
|
|
152
|
+
**Possible Causes:**
|
|
153
|
+
1. Channel change during mesh discovery
|
|
154
|
+
2. Weak signal strength
|
|
155
|
+
3. Network congestion
|
|
156
|
+
4. Too many mesh topology changes
|
|
157
|
+
|
|
158
|
+
**Solutions:**
|
|
159
|
+
1. This is normal during initial mesh formation when channels are being discovered
|
|
160
|
+
2. After 30-60 seconds, the mesh should stabilize on one channel
|
|
161
|
+
3. Move closer to the bridge node
|
|
162
|
+
4. Use a fixed channel if you know your router's channel:
|
|
163
|
+
```cpp
|
|
164
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &scheduler, MESH_PORT,
|
|
165
|
+
WIFI_AP_STA, 6); // Force channel 6
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Can't Access Internet
|
|
169
|
+
|
|
170
|
+
**This is expected behavior!** Regular mesh nodes don't provide internet routing by default.
|
|
171
|
+
|
|
172
|
+
**Options for Internet Access:**
|
|
173
|
+
|
|
174
|
+
1. **Use Shared Gateway Mode**: All nodes connect to router
|
|
175
|
+
```cpp
|
|
176
|
+
mesh.initAsSharedGateway(MESH_PREFIX, MESH_PASSWORD,
|
|
177
|
+
ROUTER_SSID, ROUTER_PASSWORD,
|
|
178
|
+
&scheduler, MESH_PORT);
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
2. **Connect to the Router**: Connect your device to the router WiFi instead, then communicate with mesh nodes via the bridge
|
|
182
|
+
|
|
183
|
+
3. **Custom Routing**: Implement custom NAT/routing on the bridge (advanced)
|
|
184
|
+
|
|
185
|
+
## Advanced: Using with Test Tools
|
|
186
|
+
|
|
187
|
+
### ESPping or Similar Tools
|
|
188
|
+
|
|
189
|
+
If you're using tools like ESPping (https://github.com/dvarrel/ESPping) to debug mesh connectivity:
|
|
190
|
+
|
|
191
|
+
1. Connect the test device to the mesh AP
|
|
192
|
+
2. You'll get an IP in the 10.x.x.x range
|
|
193
|
+
3. You can now ping mesh nodes directly:
|
|
194
|
+
```bash
|
|
195
|
+
ping 10.x.x.1 # The bridge you're connected to
|
|
196
|
+
```
|
|
197
|
+
4. To find other mesh nodes, check the bridge's serial output for their IPs
|
|
198
|
+
|
|
199
|
+
### Network Scanners
|
|
200
|
+
|
|
201
|
+
Tools like `nmap`, `arp-scan`, or Android apps like "Network Analyzer" can help:
|
|
202
|
+
|
|
203
|
+
```bash
|
|
204
|
+
# Scan the mesh network
|
|
205
|
+
sudo nmap -sn 10.x.x.0/24
|
|
206
|
+
|
|
207
|
+
# Or use arp-scan
|
|
208
|
+
sudo arp-scan --interface=wlan0 10.x.x.0/24
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Packet Analysis
|
|
212
|
+
|
|
213
|
+
If you need to capture mesh traffic:
|
|
214
|
+
|
|
215
|
+
1. Connect your computer to the mesh AP
|
|
216
|
+
2. Use Wireshark or tcpdump to capture packets
|
|
217
|
+
3. Filter for TCP port 5555 (default mesh port)
|
|
218
|
+
```
|
|
219
|
+
tcp.port == 5555
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## Example Debug Session
|
|
223
|
+
|
|
224
|
+
Here's a complete example of connecting and debugging:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
# 1. Connect to mesh AP
|
|
228
|
+
nmcli device wifi connect "FishFarmMesh" password "securepass"
|
|
229
|
+
|
|
230
|
+
# 2. Check your IP
|
|
231
|
+
ip addr show wlan0
|
|
232
|
+
# Should show: inet 10.26.43.2/24
|
|
233
|
+
|
|
234
|
+
# 3. Ping the gateway (bridge)
|
|
235
|
+
ping -c 3 10.26.43.1
|
|
236
|
+
# Should get replies
|
|
237
|
+
|
|
238
|
+
# 4. Check DHCP lease
|
|
239
|
+
cat /var/lib/NetworkManager/dhclient-*.lease
|
|
240
|
+
# Shows lease details from 10.26.43.1
|
|
241
|
+
|
|
242
|
+
# 5. Scan for other mesh nodes
|
|
243
|
+
sudo nmap -sn 10.0.0.0/8 --exclude 10.26.43.2
|
|
244
|
+
# May find other nodes on 10.x.x.1 addresses
|
|
245
|
+
|
|
246
|
+
# 6. Try connecting to mesh TCP port
|
|
247
|
+
nc -v 10.26.43.1 5555
|
|
248
|
+
# Should connect if node is accepting connections
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
## Security Considerations
|
|
252
|
+
|
|
253
|
+
### Important Warnings
|
|
254
|
+
|
|
255
|
+
1. **Don't use weak passwords**: The mesh password protects your entire network
|
|
256
|
+
2. **Change default credentials**: Always change from example values like "whateverYouLike"
|
|
257
|
+
3. **No internet isolation**: External devices on mesh AP can potentially communicate with all mesh nodes
|
|
258
|
+
4. **Production vs. Debug**: Consider disabling external connections in production:
|
|
259
|
+
```cpp
|
|
260
|
+
// Limit max connections to only mesh nodes
|
|
261
|
+
mesh.init(MESH_PREFIX, MESH_PASSWORD, &scheduler, MESH_PORT,
|
|
262
|
+
WIFI_AP_STA, channel, 0, 4); // Max 4 on ESP8266
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Best Practices
|
|
266
|
+
|
|
267
|
+
1. **Use strong passwords**: At least 8 characters, mixed case, numbers
|
|
268
|
+
2. **Monitor connections**: Log when devices connect/disconnect
|
|
269
|
+
3. **Implement timeouts**: Automatically disconnect idle external devices
|
|
270
|
+
4. **Network segmentation**: Use VLANs if possible for mesh vs. debug traffic
|
|
271
|
+
|
|
272
|
+
## Related Documentation
|
|
273
|
+
|
|
274
|
+
- [Bridge Setup Guide](../BRIDGE_TO_INTERNET.md)
|
|
275
|
+
- [Shared Gateway Mode](../api/shared-gateway.md)
|
|
276
|
+
- [Common Issues](common-issues.md)
|
|
277
|
+
- [ESP32-C6 Compatibility](ESP32_C6_COMPATIBILITY.md)
|
|
278
|
+
|
|
279
|
+
## Changelog
|
|
280
|
+
|
|
281
|
+
- **Unreleased**: Initial documentation for external device connections
|
|
282
|
+
- Added DHCP server initialization fixes for ESP32
|
|
283
|
+
- Improved AP restart timing for channel changes
|
|
@@ -16,6 +16,29 @@
|
|
|
16
16
|
// - Enables nodes to implement failover and queueing logic
|
|
17
17
|
//
|
|
18
18
|
// For more details, see BRIDGE_TO_INTERNET.md
|
|
19
|
+
//
|
|
20
|
+
// EXTERNAL DEVICE CONNECTIONS:
|
|
21
|
+
// ----------------------------
|
|
22
|
+
// External devices (phones, computers) can connect to the bridge's WiFi
|
|
23
|
+
// AP for debugging and testing purposes. The AP will broadcast the mesh
|
|
24
|
+
// SSID (e.g., "whateverYouLike") with the configured password.
|
|
25
|
+
//
|
|
26
|
+
// Connection details:
|
|
27
|
+
// - SSID: Your MESH_PREFIX value
|
|
28
|
+
// - Password: Your MESH_PASSWORD value
|
|
29
|
+
// - IP Range: 10.x.x.x (automatically assigned via DHCP)
|
|
30
|
+
// - Gateway: 10.x.x.1 (the bridge node itself)
|
|
31
|
+
//
|
|
32
|
+
// Note: ESP32 AP mode supports up to 10 concurrent connections by default,
|
|
33
|
+
// ESP8266 supports up to 4. If mesh nodes are already connected, fewer
|
|
34
|
+
// slots will be available for external devices.
|
|
35
|
+
//
|
|
36
|
+
// Troubleshooting external connections:
|
|
37
|
+
// 1. Ensure the bridge has successfully initialized (check serial output)
|
|
38
|
+
// 2. Wait a few seconds after boot for the AP to fully start
|
|
39
|
+
// 3. Check for channel conflicts with other WiFi networks
|
|
40
|
+
// 4. Try forgetting the network on your device and reconnecting
|
|
41
|
+
// 5. Monitor serial output with CONNECTION debug level enabled
|
|
19
42
|
//************************************************************
|
|
20
43
|
#include "painlessMesh.h"
|
|
21
44
|
|