initial w5500 support

This commit is contained in:
technyon
2022-04-26 22:12:52 +02:00
parent 2a1f5facf9
commit 677f7e56c8
11 changed files with 314 additions and 71 deletions

View File

@@ -17,7 +17,11 @@ include_directories(${PROJECT_NAME}
file(GLOB SRCFILES file(GLOB SRCFILES
# "Lib/FreeRTOS/src/*.c" # "Lib/FreeRTOS/src/*.c"
# "Lib/FreeRTOS/src/*.cpp" # "Lib/FreeRTOS/src/*.cpp"
Pins.h
Network.cpp Network.cpp
networkDevices/NetworkDevice.h
networkDevices/WifiDevice.cpp
networkDevices/W5500Device.cpp
NukiWrapper.cpp NukiWrapper.cpp
MqttTopics.h MqttTopics.h
WebCfgServer.cpp WebCfgServer.cpp
@@ -59,6 +63,7 @@ target_link_arduino_libraries(${PROJECT_NAME}
DNSServer DNSServer
Preferences Preferences
SPIFFS SPIFFS
Ethernet
# esp32 # esp32
# Wire # Wire
# FS # FS

View File

@@ -1,18 +1,21 @@
#include "Network.h" #include "Network.h"
#include "WiFi.h"
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager #include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#include "Arduino.h" #include "Arduino.h"
#include "MqttTopics.h" #include "MqttTopics.h"
#include "PreferencesKeys.h" #include "PreferencesKeys.h"
#include "Pins.h"
Network* nwInst; Network* nwInst;
Network::Network(Preferences* preferences) Network::Network(const NetworkDeviceType networkDevice, Preferences* preferences)
: _mqttClient(_wifiClient), : _preferences(preferences),
_preferences(preferences) _networkDeviceType(networkDevice)
{ {
nwInst = this; nwInst = this;
_hostname = _preferences->getString(preference_hostname);
setupDevice(networkDevice);
_configTopics.reserve(5); _configTopics.reserve(5);
_configTopics.push_back(mqtt_topic_config_button_enabled); _configTopics.push_back(mqtt_topic_config_button_enabled);
_configTopics.push_back(mqtt_topic_config_led_enabled); _configTopics.push_back(mqtt_topic_config_led_enabled);
@@ -21,53 +24,46 @@ Network::Network(Preferences* preferences)
_configTopics.push_back(mqtt_topic_config_auto_lock); _configTopics.push_back(mqtt_topic_config_auto_lock);
} }
Network::~Network()
{
if(_device != nullptr)
{
delete _device;
_device = nullptr;
}
}
void Network::setupDevice(const NetworkDeviceType hardware)
{
switch(hardware)
{
case NetworkDeviceType::W5500:
Serial.println(F("Network device: W5500"));
_device = new W5500Device(_hostname);
break;
case NetworkDeviceType::WiFi:
Serial.println(F("Network device: Builtin WiFi"));
_device = new WifiDevice(_hostname);
break;
default:
Serial.println(F("Unknown network device type, defaulting to WiFi"));
_device = new WifiDevice(_hostname);
break;
}
}
void Network::initialize() void Network::initialize()
{ {
String hostname = _preferences->getString(preference_hostname); if(_hostname == "")
if(hostname == "")
{ {
hostname = "nukihub"; _hostname = "nukihub";
_preferences->putString(preference_hostname, hostname); _preferences->putString(preference_hostname, _hostname);
} }
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP _device->initialize();
// it is a good practice to make sure your code sets wifi mode how you want it.
//WiFiManager, Local intialization. Once its business is done, there is no need to keep it around
WiFiManager wm;
std::vector<const char *> wm_menu;
wm_menu.push_back("wifi");
wm_menu.push_back("exit");
wm.setShowInfoUpdate(false);
wm.setMenu(wm_menu);
wm.setHostname(hostname);
bool res = false;
if(_cookie.isSet())
{
Serial.println(F("Opening WiFi configuration portal."));
_cookie.clear();
res = wm.startConfigPortal();
}
else
{
res = wm.autoConnect(); // password protected ap
}
if(!res) {
Serial.println(F("Failed to connect. Wait for ESP restart."));
delay(10000);
ESP.restart();
}
else {
Serial.print(F("WiFi connected."));
Serial.println(WiFi.localIP().toString());
}
Serial.print(F("Host name: ")); Serial.print(F("Host name: "));
Serial.println(hostname); Serial.println(_hostname);
const char* brokerAddr = _preferences->getString(preference_mqtt_broker).c_str(); const char* brokerAddr = _preferences->getString(preference_mqtt_broker).c_str();
strcpy(_mqttBrokerAddr, brokerAddr); strcpy(_mqttBrokerAddr, brokerAddr);
@@ -119,14 +115,13 @@ void Network::initialize()
Serial.print(F(":")); Serial.print(F(":"));
Serial.println(port); Serial.println(port);
_mqttClient.setServer(_mqttBrokerAddr, port); _device->mqttClient()->setServer(_mqttBrokerAddr, port);
_mqttClient.setCallback(Network::onMqttDataReceivedCallback); _device->mqttClient()->setCallback(Network::onMqttDataReceivedCallback);
} }
bool Network::reconnect() bool Network::reconnect()
{ {
while (!_mqttClient.connected() && millis() > _nextReconnect) while (!_device->mqttClient()->connected() && millis() > _nextReconnect)
{ {
Serial.println(F("Attempting MQTT connection")); Serial.println(F("Attempting MQTT connection"));
bool success = false; bool success = false;
@@ -134,12 +129,12 @@ bool Network::reconnect()
if(strlen(_mqttUser) == 0) if(strlen(_mqttUser) == 0)
{ {
Serial.println(F("MQTT: Connecting without credentials")); Serial.println(F("MQTT: Connecting without credentials"));
success = _mqttClient.connect(_preferences->getString(preference_hostname).c_str()); success = _device->mqttClient()->connect(_preferences->getString(preference_hostname).c_str());
} }
else else
{ {
Serial.print(F("MQTT: Connecting with user: ")); Serial.println(_mqttUser); Serial.print(F("MQTT: Connecting with user: ")); Serial.println(_mqttUser);
success = _mqttClient.connect(_preferences->getString(preference_hostname).c_str(), _mqttUser, _mqttPass); success = _device->mqttClient()->connect(_preferences->getString(preference_hostname).c_str(), _mqttUser, _mqttPass);
} }
@@ -157,7 +152,7 @@ bool Network::reconnect()
else else
{ {
Serial.print(F("MQTT connect failed, rc=")); Serial.print(F("MQTT connect failed, rc="));
Serial.println(_mqttClient.state()); Serial.println(_device->mqttClient()->state());
_mqttConnected = false; _mqttConnected = false;
_nextReconnect = millis() + 5000; _nextReconnect = millis() + 5000;
} }
@@ -167,13 +162,13 @@ bool Network::reconnect()
void Network::update() void Network::update()
{ {
if(!WiFi.isConnected()) if(!_device->isConnected())
{ {
Serial.println(F("WiFi not connected")); Serial.println(F("Network not connected"));
vTaskDelay( 1000 / portTICK_PERIOD_MS); vTaskDelay( 1000 / portTICK_PERIOD_MS);
} }
if(!_mqttClient.connected()) if(!_device->mqttClient()->connected())
{ {
bool success = reconnect(); bool success = reconnect();
if(!success) if(!success)
@@ -188,7 +183,7 @@ void Network::update()
_presenceCsv = nullptr; _presenceCsv = nullptr;
} }
_mqttClient.loop(); _device->mqttClient()->loop();
} }
void Network::onMqttDataReceivedCallback(char *topic, byte *payload, unsigned int length) void Network::onMqttDataReceivedCallback(char *topic, byte *payload, unsigned int length)
@@ -323,7 +318,7 @@ void Network::publishFloat(const char* topic, const float value, const uint8_t p
dtostrf(value, 0, precision, str); dtostrf(value, 0, precision, str);
char path[200] = {0}; char path[200] = {0};
buildMqttPath(topic, path); buildMqttPath(topic, path);
_mqttClient.publish(path, str); _device->mqttClient()->publish(path, str);
} }
void Network::publishInt(const char *topic, const int value) void Network::publishInt(const char *topic, const int value)
@@ -333,7 +328,7 @@ void Network::publishInt(const char *topic, const int value)
itoa(value, str, 10); itoa(value, str, 10);
char path[200] = {0}; char path[200] = {0};
buildMqttPath(topic, path); buildMqttPath(topic, path);
_mqttClient.publish(path, str); _device->mqttClient()->publish(path, str);
} }
void Network::publishBool(const char *topic, const bool value) void Network::publishBool(const char *topic, const bool value)
@@ -342,14 +337,14 @@ void Network::publishBool(const char *topic, const bool value)
str[0] = value ? '1' : '0'; str[0] = value ? '1' : '0';
char path[200] = {0}; char path[200] = {0};
buildMqttPath(topic, path); buildMqttPath(topic, path);
_mqttClient.publish(path, str); _device->mqttClient()->publish(path, str);
} }
void Network::publishString(const char *topic, const char *value) void Network::publishString(const char *topic, const char *value)
{ {
char path[200] = {0}; char path[200] = {0};
buildMqttPath(topic, path); buildMqttPath(topic, path);
_mqttClient.publish(path, value); _device->mqttClient()->publish(path, value);
} }
@@ -384,14 +379,12 @@ void Network::subscribe(const char *path)
{ {
char prefixedPath[500]; char prefixedPath[500];
buildMqttPath(path, prefixedPath); buildMqttPath(path, prefixedPath);
_mqttClient.subscribe(prefixedPath); _device->mqttClient()->subscribe(prefixedPath);
} }
void Network::restartAndConfigureWifi() void Network::restartAndConfigureWifi()
{ {
_cookie.set(); _device->reconfigure();
delay(200);
ESP.restart();
} }
bool Network::comparePrefixedPath(const char *fullPath, const char *subPath) bool Network::comparePrefixedPath(const char *fullPath, const char *subPath)

View File

@@ -1,20 +1,30 @@
#pragma once #pragma once
#include <PubSubClient.h> #include <PubSubClient.h>
#include <WiFiClient.h> #include "networkDevices/NetworkDevice.h"
#include "networkDevices/WifiDevice.h"
#include "networkDevices/W5500Device.h"
#include <Preferences.h> #include <Preferences.h>
#include <vector> #include <vector>
#include "NukiConstants.h" #include "NukiConstants.h"
#include "SpiffsCookie.h" #include "SpiffsCookie.h"
enum class NetworkDeviceType
{
WiFi,
W5500
};
class Network class Network
{ {
public: public:
explicit Network(Preferences* preferences); explicit Network(const NetworkDeviceType networkDevice, Preferences* preferences);
virtual ~Network() = default; virtual ~Network();
void initialize(); void initialize();
void update(); void update();
void setupDevice(const NetworkDeviceType hardware);
void initializeW5500();
bool isMqttConnected(); bool isMqttConnected();
@@ -45,10 +55,10 @@ private:
bool reconnect(); bool reconnect();
PubSubClient _mqttClient; NetworkDevice* _device = nullptr;
WiFiClient _wifiClient;
Preferences* _preferences; Preferences* _preferences;
SpiffsCookie _cookie; String _hostname;
NetworkDeviceType _networkDeviceType;
bool _mqttConnected = false; bool _mqttConnected = false;

5
Pins.h Normal file
View File

@@ -0,0 +1,5 @@
#pragma once
#define NETWORK_SELECT 26
#define ETHERNET_CS_PIN 5
#define ETHERNET_RESET_PIN 33

View File

@@ -1,5 +1,4 @@
#include "WebCfgServer.h" #include "WebCfgServer.h"
#include <WiFiClient.h>
#include "PreferencesKeys.h" #include "PreferencesKeys.h"
#include "Version.h" #include "Version.h"

View File

@@ -1,4 +1,5 @@
#include "Arduino.h" #include "Arduino.h"
#include "Pins.h"
#include "NukiWrapper.h" #include "NukiWrapper.h"
#include "Network.h" #include "Network.h"
#include "WebCfgServer.h" #include "WebCfgServer.h"
@@ -80,11 +81,16 @@ uint32_t getRandomId()
void setup() void setup()
{ {
pinMode(NETWORK_SELECT, INPUT_PULLUP);
Serial.begin(115200); Serial.begin(115200);
const NetworkDeviceType networkDevice = NetworkDeviceType::WiFi;
// const NetworkDeviceType networkDevice = digitalRead(NETWORK_SELECT) == HIGH ? NetworkDeviceType::WiFi : NetworkDeviceType::W5500;
preferences = new Preferences(); preferences = new Preferences();
preferences->begin("nukihub", false); preferences->begin("nukihub", false);
network = new Network(preferences); network = new Network(networkDevice, preferences);
network->initialize(); network->initialize();
uint32_t deviceId = preferences->getUInt(preference_deviceId); uint32_t deviceId = preferences->getUInt(preference_deviceId);

View File

@@ -0,0 +1,21 @@
#pragma once
#include "PubSubClient.h"
class NetworkDevice
{
public:
explicit NetworkDevice(const String& hostname)
: _hostname(hostname)
{}
virtual PubSubClient* mqttClient() = 0;
virtual void initialize() = 0;
virtual void reconfigure() = 0;
virtual bool isConnected() = 0;
protected:
const String _hostname;
};

View File

@@ -0,0 +1,95 @@
#include "W5500Device.h"
#include "../Pins.h"
W5500Device::W5500Device(const String &hostname)
: NetworkDevice(hostname)
{
}
W5500Device::~W5500Device()
{}
void W5500Device::initialize()
{
resetDevice();
Ethernet.init(ETHERNET_CS_PIN);
_ethClient = new EthernetClient();
_mqttClient = new PubSubClient(*_ethClient);
// start the Ethernet connection:
Serial.println(F("Initialize Ethernet with DHCP:"));
int dhcpRetryCnt = 0;
while(dhcpRetryCnt < 3)
{
Serial.print(F("DHCP connect try #"));
Serial.print(dhcpRetryCnt);
Serial.println();
dhcpRetryCnt++;
byte mac[] = {0xB0,0xCD,0xAE,0x0F,0xDE,0x10};
if (Ethernet.begin(mac, 1000, 1000) == 0)
{
Serial.println(F("Failed to configure Ethernet using DHCP"));
// Check for Ethernet hardware present
if (Ethernet.hardwareStatus() == EthernetNoHardware)
{
Serial.println(F("Ethernet module not found"));
delay(10000);
ESP.restart();
}
if (Ethernet.linkStatus() == LinkOFF)
{
Serial.println(F("Ethernet cable is not connected."));
}
IPAddress ip;
ip.fromString("192.168.4.1");
IPAddress subnet;
subnet.fromString("255.255.255.0");
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
Ethernet.setSubnetMask(subnet);
delay(2000);
}
else
{
dhcpRetryCnt = 1000;
Serial.print(F(" DHCP assigned IP "));
Serial.println(Ethernet.localIP());
}
}
}
void W5500Device::reconfigure()
{
Serial.println(F("Reconfigure W5500 not implemented."));
}
void W5500Device::resetDevice()
{
Serial.println(F("Resetting network hardware."));
pinMode(ETHERNET_RESET_PIN, OUTPUT);
digitalWrite(ETHERNET_RESET_PIN, HIGH);
delay(250);
digitalWrite(ETHERNET_RESET_PIN, LOW);
delay(50);
digitalWrite(ETHERNET_RESET_PIN, HIGH);
delay(1500);
}
PubSubClient *W5500Device::mqttClient()
{
return _mqttClient;
}
bool W5500Device::isConnected()
{
return _ethClient->connected();
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include "NetworkDevice.h"
#include <Ethernet.h>
class W5500Device : public NetworkDevice
{
public:
explicit W5500Device(const String& hostname);
~W5500Device();
virtual void initialize();
virtual void reconfigure();
virtual bool isConnected();
virtual PubSubClient *mqttClient();
private:
void resetDevice();
EthernetClient* _ethClient = nullptr;
PubSubClient* _mqttClient = nullptr;
};

View File

@@ -0,0 +1,62 @@
#include <WiFi.h>
#include "WifiDevice.h"
#include "WiFiManager.h"
WifiDevice::WifiDevice(const String& hostname)
: NetworkDevice(hostname),
_mqttClient(_wifiClient)
{}
PubSubClient *WifiDevice::mqttClient()
{
return &_mqttClient;
}
void WifiDevice::initialize()
{
WiFi.mode(WIFI_STA); // explicitly set mode, esp defaults to STA+AP
WiFiManager wm;
std::vector<const char *> wm_menu;
wm_menu.push_back("wifi");
wm_menu.push_back("exit");
wm.setShowInfoUpdate(false);
wm.setMenu(wm_menu);
wm.setHostname(_hostname);
bool res = false;
if(_cookie.isSet())
{
Serial.println(F("Opening WiFi configuration portal."));
_cookie.clear();
res = wm.startConfigPortal();
}
else
{
res = wm.autoConnect(); // password protected ap
}
if(!res) {
Serial.println(F("Failed to connect. Wait for ESP restart."));
delay(10000);
ESP.restart();
}
else {
Serial.print(F("WiFi connected: "));
Serial.println(WiFi.localIP().toString());
}
}
void WifiDevice::reconfigure()
{
_cookie.set();
delay(200);
ESP.restart();
}
bool WifiDevice::isConnected()
{
return WiFi.isConnected();
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <WiFiClient.h>
#include "NetworkDevice.h"
#include "../SpiffsCookie.h"
class WifiDevice : public NetworkDevice
{
public:
WifiDevice(const String& hostname);
virtual void initialize();
virtual void reconfigure();
virtual bool isConnected();
virtual PubSubClient *mqttClient();
private:
WiFiClient _wifiClient;
PubSubClient _mqttClient;
SpiffsCookie _cookie;
};