Implemented serveal global network functions which are independent of the medium (wifi / ethernet)
This commit is contained in:
parent
69959db93c
commit
c022b8696b
@ -1,10 +1,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
#pragma once
|
||||
|
||||
#include "NetworkSettings.h"
|
||||
#include <Arduino.h>
|
||||
#include <AsyncMqttClient.h>
|
||||
#include <Ticker.h>
|
||||
#include <WiFi.h>
|
||||
#include <memory>
|
||||
|
||||
class MqttSettingsClass {
|
||||
@ -19,7 +19,7 @@ public:
|
||||
String getPrefix();
|
||||
|
||||
private:
|
||||
void WiFiEvent(WiFiEvent_t event);
|
||||
void NetworkEvent(network_event event);
|
||||
|
||||
void onMqttDisconnect(AsyncMqttClientDisconnectReason reason);
|
||||
void onMqttConnect(bool sessionPresent);
|
||||
|
||||
@ -4,6 +4,37 @@
|
||||
#include <DNSServer.h>
|
||||
#include <WiFi.h>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
enum class network_mode {
|
||||
WiFi,
|
||||
Ethernet,
|
||||
Undefined
|
||||
};
|
||||
|
||||
enum class network_event {
|
||||
NETWORK_UNKNOWN,
|
||||
NETWORK_START,
|
||||
NETWORK_STOP,
|
||||
NETWORK_CONNECTED,
|
||||
NETWORK_DISCONNECTED,
|
||||
NETWORK_GOT_IP,
|
||||
NETWORK_LOST_IP,
|
||||
NETWORK_EVENT_MAX
|
||||
};
|
||||
|
||||
typedef std::function<void(network_event event)> NetworkEventCb;
|
||||
|
||||
typedef struct NetworkEventCbList {
|
||||
NetworkEventCb cb;
|
||||
network_event event;
|
||||
|
||||
NetworkEventCbList()
|
||||
: cb(NULL)
|
||||
, event(network_event::NETWORK_UNKNOWN)
|
||||
{
|
||||
}
|
||||
} NetworkEventCbList_t;
|
||||
|
||||
class NetworkSettingsClass {
|
||||
public:
|
||||
@ -14,6 +45,18 @@ public:
|
||||
void enableAdminMode();
|
||||
String getApName();
|
||||
|
||||
IPAddress localIP();
|
||||
IPAddress subnetMask();
|
||||
IPAddress gatewayIP();
|
||||
IPAddress dnsIP(uint8_t dns_no = 0);
|
||||
String macAddress();
|
||||
const char* getHostname();
|
||||
bool isConnected();
|
||||
network_mode NetworkMode();
|
||||
|
||||
bool onEvent(NetworkEventCb cbEvent, network_event event = network_event::NETWORK_EVENT_MAX);
|
||||
void raiseEvent(network_event event);
|
||||
|
||||
private:
|
||||
void setHostname();
|
||||
void setStaticIp();
|
||||
@ -30,6 +73,9 @@ private:
|
||||
IPAddress apNetmask;
|
||||
std::unique_ptr<DNSServer> dnsServer;
|
||||
bool dnsServerStatus = false;
|
||||
network_mode _networkMode = network_mode::Undefined;
|
||||
bool _ethConnected = false;
|
||||
std::vector<NetworkEventCbList_t> _cbEventList;
|
||||
};
|
||||
|
||||
extern NetworkSettingsClass NetworkSettings;
|
||||
@ -6,7 +6,7 @@
|
||||
#include "ArduinoJson.h"
|
||||
#include "MqttPublishing.h"
|
||||
#include "MqttSettings.h"
|
||||
#include "WiFiSettings.h"
|
||||
#include "NetworkSettings.h"
|
||||
|
||||
MqttHassPublishingClass MqttHassPublishing;
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include "MqttPublishing.h"
|
||||
#include "MqttSettings.h"
|
||||
#include "NetworkSettings.h"
|
||||
|
||||
MqttPublishingClass MqttPublishing;
|
||||
|
||||
@ -21,7 +22,7 @@ void MqttPublishingClass::loop()
|
||||
|
||||
if (millis() - _lastPublish > (config.Mqtt_PublishInterval * 1000)) {
|
||||
MqttSettings.publish("dtu/uptime", String(millis() / 1000));
|
||||
MqttSettings.publish("dtu/ip", WiFi.localIP().toString());
|
||||
MqttSettings.publish("dtu/ip", NetworkSettings.localIP().toString());
|
||||
|
||||
// Loop all inverters
|
||||
for (uint8_t i = 0; i < Hoymiles.getNumInverters(); i++) {
|
||||
|
||||
@ -7,22 +7,21 @@
|
||||
#include "NetworkSettings.h"
|
||||
#include <AsyncMqttClient.h>
|
||||
#include <Ticker.h>
|
||||
#include <WiFi.h>
|
||||
|
||||
MqttSettingsClass::MqttSettingsClass()
|
||||
: mqttClient()
|
||||
{
|
||||
}
|
||||
|
||||
void MqttSettingsClass::WiFiEvent(WiFiEvent_t event)
|
||||
void MqttSettingsClass::NetworkEvent(network_event event)
|
||||
{
|
||||
switch (event) {
|
||||
case SYSTEM_EVENT_STA_GOT_IP:
|
||||
Serial.println(F("WiFi connected"));
|
||||
case network_event::NETWORK_GOT_IP:
|
||||
Serial.println(F("Network connected"));
|
||||
performConnect();
|
||||
break;
|
||||
case SYSTEM_EVENT_STA_DISCONNECTED:
|
||||
Serial.println(F("WiFi lost connection"));
|
||||
case network_event::NETWORK_DISCONNECTED:
|
||||
Serial.println(F("Network lost connection"));
|
||||
mqttReconnectTimer.detach(); // ensure we don't reconnect to MQTT while reconnecting to Wi-Fi
|
||||
break;
|
||||
}
|
||||
@ -45,7 +44,7 @@ void MqttSettingsClass::onMqttDisconnect(AsyncMqttClientDisconnectReason reason)
|
||||
|
||||
void MqttSettingsClass::performConnect()
|
||||
{
|
||||
if (WiFi.isConnected() && Configuration.get().Mqtt_Enabled) {
|
||||
if (NetworkSettings.isConnected() && Configuration.get().Mqtt_Enabled) {
|
||||
Serial.println(F("Connecting to MQTT..."));
|
||||
CONFIG_T& config = Configuration.get();
|
||||
mqttClient.setServer(config.Mqtt_Hostname, config.Mqtt_Port);
|
||||
@ -103,7 +102,7 @@ void MqttSettingsClass::publishHass(String subtopic, String payload)
|
||||
void MqttSettingsClass::init()
|
||||
{
|
||||
using namespace std::placeholders;
|
||||
WiFi.onEvent(std::bind(&MqttSettingsClass::WiFiEvent, this, _1));
|
||||
NetworkSettings.onEvent(std::bind(&MqttSettingsClass::NetworkEvent, this, _1));
|
||||
|
||||
mqttClient.onConnect(std::bind(&MqttSettingsClass::onMqttConnect, this, _1));
|
||||
mqttClient.onDisconnect(std::bind(&MqttSettingsClass::onMqttDisconnect, this, _1));
|
||||
|
||||
@ -31,36 +31,83 @@ void NetworkSettingsClass::NetworkEvent(WiFiEvent_t event)
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case ARDUINO_EVENT_ETH_START:
|
||||
Serial.println("ETH start");
|
||||
ETH.setHostname("esp32-ethernet");
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_START);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_STOP:
|
||||
Serial.println("ETH stop");
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_STOP);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_CONNECTED:
|
||||
Serial.println("ETH connected");
|
||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
_ethConnected = true;
|
||||
raiseEvent(network_event::NETWORK_CONNECTED);
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_GOT_IP:
|
||||
Serial.printf("ETH got IP: %s\n", ETH.localIP().toString().c_str());
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_GOT_IP);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
||||
Serial.println("ETH disconnected");
|
||||
_ethConnected = false;
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
raiseEvent(network_event::NETWORK_DISCONNECTED);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case ARDUINO_EVENT_WIFI_STA_CONNECTED:
|
||||
Serial.println("WiFi connected");
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
raiseEvent(network_event::NETWORK_CONNECTED);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_DISCONNECTED:
|
||||
Serial.println("WiFi disconnected");
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
WiFi.reconnect();
|
||||
raiseEvent(network_event::NETWORK_DISCONNECTED);
|
||||
}
|
||||
break;
|
||||
case ARDUINO_EVENT_WIFI_STA_GOT_IP:
|
||||
Serial.printf("WiFi got ip: %s\n", WiFi.localIP().toString().c_str());
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
raiseEvent(network_event::NETWORK_GOT_IP);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Serial.printf("Event: %d\n", event);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetworkSettingsClass::onEvent(NetworkEventCb cbEvent, network_event event)
|
||||
{
|
||||
if (!cbEvent) {
|
||||
return pdFALSE;
|
||||
}
|
||||
NetworkEventCbList_t newEventHandler;
|
||||
newEventHandler.cb = cbEvent;
|
||||
newEventHandler.event = event;
|
||||
_cbEventList.push_back(newEventHandler);
|
||||
return true;
|
||||
}
|
||||
|
||||
void NetworkSettingsClass::raiseEvent(network_event event)
|
||||
{
|
||||
for (uint32_t i = 0; i < _cbEventList.size(); i++) {
|
||||
NetworkEventCbList_t entry = _cbEventList[i];
|
||||
if (entry.cb) {
|
||||
if (entry.event == event || entry.event == network_event::NETWORK_EVENT_MAX) {
|
||||
entry.cb(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NetworkSettingsClass::setupMode()
|
||||
{
|
||||
if (adminEnabled) {
|
||||
@ -74,7 +121,11 @@ void NetworkSettingsClass::setupMode()
|
||||
} else {
|
||||
dnsServer->stop();
|
||||
dnsServerStatus = false;
|
||||
WiFi.mode(WIFI_STA);
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
WiFi.mode(WIFI_STA);
|
||||
} else {
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
}
|
||||
}
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
ETH.begin();
|
||||
@ -99,6 +150,26 @@ String NetworkSettingsClass::getApName()
|
||||
|
||||
void NetworkSettingsClass::loop()
|
||||
{
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
if (_ethConnected) {
|
||||
if (_networkMode != network_mode::Ethernet) {
|
||||
// Do stuff when switching to Ethernet mode
|
||||
Serial.println(F("Switch to Ethernet mode"));
|
||||
_networkMode = network_mode::Ethernet;
|
||||
WiFi.mode(WIFI_MODE_NULL);
|
||||
setStaticIp();
|
||||
setHostname();
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
if (_networkMode != network_mode::WiFi) {
|
||||
// Do stuff when switching to Ethernet mode
|
||||
Serial.println(F("Switch to WiFi mode"));
|
||||
_networkMode = network_mode::WiFi;
|
||||
enableAdminMode();
|
||||
applyConfig();
|
||||
}
|
||||
|
||||
if (millis() - lastTimerCall > 1000) {
|
||||
adminTimeoutCounter++;
|
||||
connectTimeoutTimer++;
|
||||
@ -106,8 +177,8 @@ void NetworkSettingsClass::loop()
|
||||
lastTimerCall = millis();
|
||||
}
|
||||
if (adminEnabled) {
|
||||
// Don't disable the admin mode when WiFi is not available
|
||||
if (WiFi.status() != WL_CONNECTED) {
|
||||
// Don't disable the admin mode when network is not available
|
||||
if (!isConnected()) {
|
||||
adminTimeoutCounter = 0;
|
||||
}
|
||||
// If WiFi is connected to AP for more than ADMIN_TIMEOUT
|
||||
@ -120,7 +191,7 @@ void NetworkSettingsClass::loop()
|
||||
// It's nearly not possible to use the internal AP if the
|
||||
// WiFi is searching for an AP. So disable searching afer
|
||||
// WIFI_RECONNECT_TIMEOUT and repeat after WIFI_RECONNECT_REDO_TIMEOUT
|
||||
if (WiFi.status() == WL_CONNECTED) {
|
||||
if (isConnected()) {
|
||||
connectTimeoutTimer = 0;
|
||||
connectRedoTimer = 0;
|
||||
} else {
|
||||
@ -170,11 +241,22 @@ void NetworkSettingsClass::setHostname()
|
||||
{
|
||||
Serial.print(F("Setting Hostname... "));
|
||||
if (strcmp(Configuration.get().WiFi_Hostname, "")) {
|
||||
if (WiFi.hostname(Configuration.get().WiFi_Hostname)) {
|
||||
Serial.println(F("done"));
|
||||
} else {
|
||||
Serial.println(F("failed"));
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
if (WiFi.hostname(Configuration.get().WiFi_Hostname)) {
|
||||
Serial.println(F("done"));
|
||||
} else {
|
||||
Serial.println(F("failed"));
|
||||
}
|
||||
}
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
else if (_networkMode == network_mode::Ethernet) {
|
||||
if (ETH.setHostname(Configuration.get().WiFi_Hostname)) {
|
||||
Serial.println(F("done"));
|
||||
} else {
|
||||
Serial.println(F("failed"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
Serial.println(F("failed (Hostname empty)"));
|
||||
}
|
||||
@ -182,16 +264,138 @@ void NetworkSettingsClass::setHostname()
|
||||
|
||||
void NetworkSettingsClass::setStaticIp()
|
||||
{
|
||||
if (!Configuration.get().WiFi_Dhcp) {
|
||||
Serial.print(F("Configuring WiFi STA static IP... "));
|
||||
WiFi.config(
|
||||
IPAddress(Configuration.get().WiFi_Ip),
|
||||
IPAddress(Configuration.get().WiFi_Gateway),
|
||||
IPAddress(Configuration.get().WiFi_Netmask),
|
||||
IPAddress(Configuration.get().WiFi_Dns1),
|
||||
IPAddress(Configuration.get().WiFi_Dns2));
|
||||
Serial.println(F("done"));
|
||||
if (_networkMode == network_mode::WiFi) {
|
||||
if (!Configuration.get().WiFi_Dhcp) {
|
||||
Serial.print(F("Configuring WiFi STA static IP... "));
|
||||
WiFi.config(
|
||||
IPAddress(Configuration.get().WiFi_Ip),
|
||||
IPAddress(Configuration.get().WiFi_Gateway),
|
||||
IPAddress(Configuration.get().WiFi_Netmask),
|
||||
IPAddress(Configuration.get().WiFi_Dns1),
|
||||
IPAddress(Configuration.get().WiFi_Dns2));
|
||||
Serial.println(F("done"));
|
||||
}
|
||||
}
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
else if (_networkMode == network_mode::Ethernet) {
|
||||
if (Configuration.get().WiFi_Dhcp) {
|
||||
ETH.config(INADDR_NONE, INADDR_NONE, INADDR_NONE, INADDR_NONE);
|
||||
} else {
|
||||
Serial.print(F("Configuring Ethernet static IP... "));
|
||||
ETH.config(
|
||||
IPAddress(Configuration.get().WiFi_Ip),
|
||||
IPAddress(Configuration.get().WiFi_Gateway),
|
||||
IPAddress(Configuration.get().WiFi_Netmask),
|
||||
IPAddress(Configuration.get().WiFi_Dns1),
|
||||
IPAddress(Configuration.get().WiFi_Dns2));
|
||||
Serial.println(F("done"));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
IPAddress NetworkSettingsClass::localIP()
|
||||
{
|
||||
switch (_networkMode) {
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case network_mode::Ethernet:
|
||||
return ETH.localIP();
|
||||
break;
|
||||
#endif
|
||||
case network_mode::WiFi:
|
||||
return WiFi.localIP();
|
||||
break;
|
||||
default:
|
||||
return INADDR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress NetworkSettingsClass::subnetMask()
|
||||
{
|
||||
switch (_networkMode) {
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case network_mode::Ethernet:
|
||||
return ETH.subnetMask();
|
||||
break;
|
||||
#endif
|
||||
case network_mode::WiFi:
|
||||
return WiFi.subnetMask();
|
||||
break;
|
||||
default:
|
||||
return IPAddress(255, 255, 255, 0);
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress NetworkSettingsClass::gatewayIP()
|
||||
{
|
||||
switch (_networkMode) {
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case network_mode::Ethernet:
|
||||
return ETH.gatewayIP();
|
||||
break;
|
||||
#endif
|
||||
case network_mode::WiFi:
|
||||
return WiFi.gatewayIP();
|
||||
break;
|
||||
default:
|
||||
return INADDR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
IPAddress NetworkSettingsClass::dnsIP(uint8_t dns_no)
|
||||
{
|
||||
switch (_networkMode) {
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case network_mode::Ethernet:
|
||||
return ETH.dnsIP(dns_no);
|
||||
break;
|
||||
#endif
|
||||
case network_mode::WiFi:
|
||||
return WiFi.dnsIP(dns_no);
|
||||
break;
|
||||
default:
|
||||
return INADDR_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
String NetworkSettingsClass::macAddress()
|
||||
{
|
||||
switch (_networkMode) {
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
case network_mode::Ethernet:
|
||||
return ETH.macAddress();
|
||||
break;
|
||||
#endif
|
||||
case network_mode::WiFi:
|
||||
return WiFi.macAddress();
|
||||
break;
|
||||
default:
|
||||
return String("");
|
||||
}
|
||||
}
|
||||
|
||||
const char* NetworkSettingsClass::getHostname()
|
||||
{
|
||||
#ifdef OPENDTU_ETHERNET
|
||||
if (_networkMode == network_mode::Ethernet) {
|
||||
return ETH.getHostname();
|
||||
}
|
||||
#endif
|
||||
return WiFi.getHostname();
|
||||
}
|
||||
|
||||
bool NetworkSettingsClass::isConnected()
|
||||
{
|
||||
#ifndef OPENDTU_ETHERNET
|
||||
return WiFi.localIP()[0] != 0;
|
||||
#else
|
||||
return WiFi.localIP()[0] != 0 || ETH.localIP()[0] != 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
network_mode NetworkSettingsClass::NetworkMode()
|
||||
{
|
||||
return _networkMode;
|
||||
}
|
||||
|
||||
NetworkSettingsClass NetworkSettings;
|
||||
@ -31,12 +31,12 @@ void WebApiNetworkClass::onNetworkStatus(AsyncWebServerRequest* request)
|
||||
|
||||
root[F("sta_status")] = ((WiFi.getMode() & WIFI_STA) != 0);
|
||||
root[F("sta_ssid")] = WiFi.SSID();
|
||||
root[F("sta_ip")] = WiFi.localIP().toString();
|
||||
root[F("sta_netmask")] = WiFi.subnetMask().toString();
|
||||
root[F("sta_gateway")] = WiFi.gatewayIP().toString();
|
||||
root[F("sta_dns1")] = WiFi.dnsIP(0).toString();
|
||||
root[F("sta_dns2")] = WiFi.dnsIP(1).toString();
|
||||
root[F("sta_mac")] = WiFi.macAddress();
|
||||
root[F("sta_ip")] = NetworkSettings.localIP().toString();
|
||||
root[F("sta_netmask")] = NetworkSettings.subnetMask().toString();
|
||||
root[F("sta_gateway")] = NetworkSettings.gatewayIP().toString();
|
||||
root[F("sta_dns1")] = NetworkSettings.dnsIP(0).toString();
|
||||
root[F("sta_dns2")] = NetworkSettings.dnsIP(1).toString();
|
||||
root[F("sta_mac")] = NetworkSettings.macAddress();
|
||||
root[F("sta_rssi")] = WiFi.RSSI();
|
||||
root[F("ap_status")] = ((WiFi.getMode() & WIFI_AP) != 0);
|
||||
root[F("ap_ssid")] = NetworkSettings.getApName();
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "ArduinoJson.h"
|
||||
#include "AsyncJson.h"
|
||||
#include "Configuration.h"
|
||||
#include "NetworkSettings.h"
|
||||
#include <LittleFS.h>
|
||||
#include <ResetReason.h>
|
||||
|
||||
@ -31,7 +32,7 @@ void WebApiSysstatusClass::onSystemStatus(AsyncWebServerRequest* request)
|
||||
AsyncJsonResponse* response = new AsyncJsonResponse();
|
||||
JsonObject root = response->getRoot();
|
||||
|
||||
root[F("hostname")] = WiFi.getHostname();
|
||||
root[F("hostname")] = NetworkSettings.getHostname();
|
||||
|
||||
root[F("sdkversion")] = ESP.getSdkVersion();
|
||||
root[F("cpufreq")] = ESP.getCpuFreqMHz();
|
||||
|
||||
@ -54,7 +54,7 @@ void setup()
|
||||
Serial.println(F("done"));
|
||||
|
||||
// Initialize WiFi
|
||||
Serial.print(F("Initialize WiFi... "));
|
||||
Serial.print(F("Initialize Network... "));
|
||||
NetworkSettings.init();
|
||||
Serial.println(F("done"));
|
||||
NetworkSettings.applyConfig();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user