# net-switcher
Simple WiFi/Ethernet network switcher for ESP-IDF with automatic failover.
## Features
- **Simple API** - Arduino-style, easy to use
- **Automatic Failover** - Switch to backup when preferred network fails
- **Preference-based** - Choose Ethernet or WiFi as primary
- **Event Hooks** - Pre/post switch callbacks for your app logic
- **DNS Handling** - Automatic DNS server switching with fallbacks
- **Pure ESP-IDF** - No Arduino dependencies
## Installation
```bash
idf.py add-dependency "drfhaust/net-switcher"
```
## Quick Start
```c
#include "net_switcher.h"
void on_switch(bool is_eth, void *ctx) {
printf("Now on: %s\n", is_eth ? "Ethernet" : "WiFi");
}
void app_main() {
// Initialize
net_switcher_begin();
// Register your network interfaces
net_switcher_setWiFi(wifi_netif);
net_switcher_setEthernet(eth_netif);
// Set preference (Ethernet by default)
net_switcher_preferEthernet();
// Optional: get notified on switch
net_switcher_onPostSwitch(on_switch, NULL);
}
// In your event handlers:
void eth_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data) {
switch (id) {
case ETHERNET_EVENT_CONNECTED:
// Wait for IP...
break;
case ETHERNET_EVENT_DISCONNECTED:
net_switcher_setEthernetConnected(false);
net_switcher_update();
break;
}
}
void ip_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data) {
switch (id) {
case IP_EVENT_ETH_GOT_IP:
net_switcher_setEthernetConnected(true);
net_switcher_update();
break;
case IP_EVENT_STA_GOT_IP:
net_switcher_setWiFiConnected(true);
net_switcher_update();
break;
case IP_EVENT_STA_LOST_IP:
net_switcher_setWiFiConnected(false);
net_switcher_update();
break;
}
}
```
## API Reference
### Setup
```c
void net_switcher_begin(void); // Initialize
void net_switcher_setWiFi(esp_netif_t *netif); // Register WiFi interface
void net_switcher_setEthernet(esp_netif_t *netif); // Register Ethernet interface
```
### Preference
```c
void net_switcher_preferEthernet(void); // Ethernet when available
void net_switcher_preferWiFi(void); // WiFi when available
net_switcher_preference_t net_switcher_getPreference(void);
```
### Event Handlers
```c
// Called before switching (disconnect services here)
void net_switcher_onPreSwitch(net_switcher_callback_t cb, void *ctx);
// Called after switching (reconnect services here)
void net_switcher_onPostSwitch(net_switcher_callback_t cb, void *ctx);
// Callback signature:
typedef void (*net_switcher_callback_t)(bool is_ethernet, void *user_ctx);
```
### Control
```c
void net_switcher_update(void); // Auto-switch based on preference
void net_switcher_switchTo(bool ethernet); // Force switch
// Tell switcher about connection state
void net_switcher_setEthernetConnected(bool connected);
void net_switcher_setWiFiConnected(bool connected);
```
### State
```c
bool net_switcher_isEthernet(void); // Currently on Ethernet?
bool net_switcher_isWiFi(void); // Currently on WiFi?
bool net_switcher_isConnected(void); // Any network connected?
bool net_switcher_ethernetAvailable(void); // Ethernet link up?
bool net_switcher_wifiAvailable(void); // WiFi connected?
esp_netif_t *net_switcher_activeNetif(void); // Get active interface
```
## Switching Logic
| Preference | ETH Available | WiFi Available | Active |
|------------|---------------|----------------|--------|
| Ethernet | Yes | Yes | Ethernet |
| Ethernet | Yes | No | Ethernet |
| Ethernet | No | Yes | WiFi |
| WiFi | Yes | Yes | WiFi |
| WiFi | No | Yes | WiFi |
| WiFi | Yes | No | Ethernet |
## Example: With MQTT
```c
#include "net_switcher.h"
#include "mqtt_client.h"
static esp_mqtt_client_handle_t mqtt;
void pre_switch(bool to_eth, void *ctx) {
// Disconnect before switch
esp_mqtt_client_disconnect(mqtt);
}
void post_switch(bool is_eth, void *ctx) {
// Reconnect after switch
esp_mqtt_client_reconnect(mqtt);
}
void app_main() {
net_switcher_begin();
net_switcher_onPreSwitch(pre_switch, NULL);
net_switcher_onPostSwitch(post_switch, NULL);
// ...
}
```
## License
MIT License - see [LICENSE](LICENSE)
idf.py add-dependency "drfhaust/net-switcher^1.0.0"