Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ He is making great Arduino libraries.
- **Ethernet support**
- **Ready for Arduino 3 (ESP-IDF 5.1)**
- **ESP8266 support** (except for Ethernet)
- **Supports Static IP configuration**

## Usage

Expand Down Expand Up @@ -92,6 +93,19 @@ void loop() {
}
```

### Set static IP

```cpp
Mycila::ESPConnect::IPConfig ipConfig;

ipConfig.ip.fromString("192.168.125.99");
ipConfig.gateway.fromString("192.168.125.1");
ipConfig.subnet.fromString("255.255.255.0");
ipConfig.dns.fromString("192.168.125.1");

espConnect.setIPConfig(ipConfig);
```

### Use an external configuration system

```cpp
Expand Down
14 changes: 14 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ He is making great Arduino libraries.
- **Ethernet support**
- **Ready for Arduino 3 (ESP-IDF 5.1)**
- **ESP8266 support** (except for Ethernet)
- **Supports Static IP configuration**

## Usage

Expand Down Expand Up @@ -92,6 +93,19 @@ void loop() {
}
```

### Set static IP

```cpp
Mycila::ESPConnect::IPConfig ipConfig;

ipConfig.ip.fromString("192.168.125.99");
ipConfig.gateway.fromString("192.168.125.1");
ipConfig.subnet.fromString("255.255.255.0");
ipConfig.dns.fromString("192.168.125.1");

espConnect.setIPConfig(ipConfig);
```

### Use an external configuration system

```cpp
Expand Down
1 change: 0 additions & 1 deletion examples/AdvancedCaptivePortal/AdvancedCaptivePortal.ino
Original file line number Diff line number Diff line change
Expand Up @@ -94,5 +94,4 @@ void setup() {

void loop() {
espConnect.loop();
delay(100);
}
84 changes: 84 additions & 0 deletions examples/WiFiStaticIP/WiFiStaticIP.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <MycilaESPConnect.h>

AsyncWebServer server(80);
Mycila::ESPConnect espConnect(server);
uint32_t lastLog = 0;
uint32_t lastChange = 0;
String hostname = "arduino-1";

void setup() {
Serial.begin(115200);
while (!Serial)
continue;

server.on("/clear", HTTP_GET, [&](AsyncWebServerRequest* request) {
Serial.println("Clearing configuration...");
espConnect.clearConfiguration();
request->send(200);
ESP.restart();
});

// network state listener is required here in async mode
espConnect.listen([](__unused Mycila::ESPConnect::State previous, Mycila::ESPConnect::State state) {
JsonDocument doc;
espConnect.toJson(doc.to<JsonObject>());
serializeJson(doc, Serial);
Serial.println();

switch (state) {
case Mycila::ESPConnect::State::NETWORK_CONNECTED:
case Mycila::ESPConnect::State::AP_STARTED:
// serve your home page here
server.on("/", HTTP_GET, [&](AsyncWebServerRequest* request) {
return request->send(200, "text/plain", "Hello World!");
})
.setFilter([](__unused AsyncWebServerRequest* request) { return espConnect.getState() != Mycila::ESPConnect::State::PORTAL_STARTED; });
server.begin();
break;

case Mycila::ESPConnect::State::NETWORK_DISCONNECTED:
server.end();
break;

default:
break;
}
});

espConnect.setAutoRestart(true);
espConnect.setBlocking(false);

Serial.println("====> Trying to connect to saved WiFi or will start portal in the background...");

espConnect.begin(hostname.c_str(), "Captive Portal SSID");

Serial.println("====> setup() completed...");
}

void loop() {
espConnect.loop();

uint32_t now = millis();

if (now - lastLog > 3000) {
JsonDocument doc;
espConnect.toJson(doc.to<JsonObject>());
serializeJson(doc, Serial);
Serial.println();
lastLog = millis();
}

if (now - lastChange > 10000) {
if (espConnect.getIPConfig().ip == INADDR_NONE) {
Mycila::ESPConnect::IPConfig ipConfig;
ipConfig.ip.fromString("192.168.125.99");
ipConfig.gateway.fromString("192.168.125.1");
ipConfig.subnet.fromString("255.255.255.0");
ipConfig.dns.fromString("192.168.125.1");
espConnect.setIPConfig(ipConfig);
} else {
espConnect.setIPConfig(Mycila::ESPConnect::IPConfig());
}
lastChange = millis();
}
}
3 changes: 2 additions & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ monitor_filters = esp32_exception_decoder, log2file
[platformio]
lib_dir = .
; src_dir = examples/BlockingCaptivePortal
src_dir = examples/NonBlockingCaptivePortal
; src_dir = examples/NonBlockingCaptivePortal
; src_dir = examples/AdvancedCaptivePortal
; src_dir = examples/TestWiFi8266
src_dir = examples/WiFiStaticIP

; esp8266

Expand Down
43 changes: 30 additions & 13 deletions src/MycilaESPConnect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,9 +219,9 @@ const String Mycila::ESPConnect::getWiFiSSID() const {
switch (WiFi.getMode()) {
case WIFI_MODE_AP:
case WIFI_MODE_APSTA:
return WiFi.softAPSSID();
return _apSSID;
case WIFI_MODE_STA:
return WiFi.SSID();
return _config.wifiSSID;
default:
return emptyString;
}
Expand Down Expand Up @@ -386,6 +386,18 @@ void Mycila::ESPConnect::loop() {
}
}

void Mycila::ESPConnect::setIPConfig(const IPConfig& ipConfig) {
_ipConfig = ipConfig;

#ifdef ESPCONNECT_ETH_SUPPORT
LOGI(TAG, "Changing Ethernet IP Configuration...");
ETH.config(_ipConfig.ip, _ipConfig.gateway, _ipConfig.subnet, _ipConfig.dns);
#else
LOGI(TAG, "Changing WiFi IP Configuration...");
WiFi.config(_ipConfig.ip, _ipConfig.gateway, _ipConfig.subnet, _ipConfig.dns);
#endif
}

void Mycila::ESPConnect::clearConfiguration() {
Preferences preferences;
preferences.begin("espconnect", false);
Expand Down Expand Up @@ -454,27 +466,28 @@ void Mycila::ESPConnect::_startEthernet() {
#endif

LOGI(TAG, "Starting Ethernet...");
bool success = true;

#if defined(ESPCONNECT_ETH_SPI_SUPPORT)
#if ESP_IDF_VERSION_MAJOR >= 5
// https://github.com/espressif/arduino-esp32/tree/master/libraries/Ethernet/examples
SPI.begin(ETH_PHY_SPI_SCK, ETH_PHY_SPI_MISO, ETH_PHY_SPI_MOSI);
if (!ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI)) {
LOGE(TAG, "ETH failed to start!");
}
success = ETH.begin(ETH_PHY_TYPE, ETH_PHY_ADDR, ETH_PHY_CS, ETH_PHY_IRQ, ETH_PHY_RST, SPI);
#else
if (!ETH.beginSPI(ETH_PHY_SPI_MISO, ETH_PHY_SPI_MOSI, ETH_PHY_SPI_SCK, ETH_PHY_CS, ETH_PHY_RST, ETH_PHY_IRQ)) {
LOGE(TAG, "ETH failed to start!");
}
success = ETH.beginSPI(ETH_PHY_SPI_MISO, ETH_PHY_SPI_MOSI, ETH_PHY_SPI_SCK, ETH_PHY_CS, ETH_PHY_RST, ETH_PHY_IRQ);
#endif
#else
if (!ETH.begin()) {
success = ETH.begin();
#endif

if (success) {
LOGD(TAG, "ETH started.");
ETH.config(_ipConfig.ip, _ipConfig.gateway, _ipConfig.subnet, _ipConfig.dns);
} else {
LOGE(TAG, "ETH failed to start!");
}
#endif

_lastTime = millis();

LOGD(TAG, "ETH started.");
}
#endif

Expand All @@ -489,6 +502,10 @@ void Mycila::ESPConnect::_startSTA() {
WiFi.setAutoReconnect(true);
WiFi.mode(WIFI_STA);

#ifndef ESPCONNECT_ETH_SUPPORT
WiFi.config(_ipConfig.ip, _ipConfig.gateway, _ipConfig.subnet, _ipConfig.dns);
#endif

LOGD(TAG, "Connecting to SSID: %s...", _config.wifiSSID.c_str());
WiFi.begin(_config.wifiSSID, _config.wifiPassword);

Expand Down Expand Up @@ -633,7 +650,7 @@ void Mycila::ESPConnect::_enableCaptivePortal() {

if (_homeHandler == nullptr) {
_homeHandler = &_httpd->on("/", HTTP_GET, [](AsyncWebServerRequest* request) {
AsyncWebServerResponse *response = request->beginResponse(200, "text/html", ESPCONNECT_HTML, sizeof(ESPCONNECT_HTML));
AsyncWebServerResponse* response = request->beginResponse(200, "text/html", ESPCONNECT_HTML, sizeof(ESPCONNECT_HTML));
response->addHeader("Content-Encoding", "gzip");
return request->send(response);
});
Expand Down
17 changes: 17 additions & 0 deletions src/MycilaESPConnect.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,16 @@ namespace Mycila {

typedef std::function<void(State previous, State state)> StateCallback;

typedef struct {
// Static IP address to use when connecting to WiFi (STA mode) or Ethernet
// If not set, DHCP will be used
IPAddress ip = INADDR_NONE;
// Subnet mask: 255.255.255.0
IPAddress subnet = INADDR_NONE;
IPAddress gateway = INADDR_NONE;
IPAddress dns = INADDR_NONE;
} IPConfig;

typedef struct {
// SSID name to connect to, loaded from config or set from begin(), or from the captive portal
String wifiSSID;
Expand Down Expand Up @@ -166,6 +176,12 @@ namespace Mycila {
// whether we need to set the ESP to stay in AP mode or not, loaded from config, begin(), or from captive portal
bool hasConfiguredAPMode() const { return _config.apMode; }

// IP configuration used for WiFi or ETH
const IPConfig& getIPConfig() const { return _ipConfig; }
// Static IP configuration: by default, DHCP is used
// The static IP configuration applies to the WiFi STA connection, except if ETH is used for ETH board, then it applies only to the Ethernet connection.
void setIPConfig(const IPConfig& ipConfig);

// Maximum duration that the captive portal will be active before closing
uint32_t getCaptivePortalTimeout() const { return _portalTimeout; }
// Maximum duration that the captive portal will be active before closing
Expand Down Expand Up @@ -205,6 +221,7 @@ namespace Mycila {
uint32_t _scanStart = 0;
uint32_t _scanTimeout = ESPCONNECT_PORTAL_SCAN_TIMEOUT;
Config _config;
IPConfig _ipConfig;
#ifndef ESP8266
WiFiEventId_t _wifiEventListenerId = 0;
#endif
Expand Down