mirror of https://github.com/lumapu/ahoy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
194 lines
6.3 KiB
194 lines
6.3 KiB
//-----------------------------------------------------------------------------
|
|
// 2024 Ahoy, https://ahoydtu.de
|
|
// Creative Commons - https://creativecommons.org/licenses/by-nc-sa/4.0/deed
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#ifndef __AHOY_NETWORK_H__
|
|
#define __AHOY_NETWORK_H__
|
|
|
|
#include "AhoyNetworkHelper.h"
|
|
#include <WiFiUdp.h>
|
|
#include "../config/settings.h"
|
|
#include "../utils/helper.h"
|
|
|
|
#if defined(ESP32)
|
|
#include <ESPmDNS.h>
|
|
#else
|
|
#include <ESP8266mDNS.h>
|
|
#endif
|
|
|
|
#define NTP_PACKET_SIZE 48
|
|
|
|
class AhoyNetwork {
|
|
public:
|
|
typedef std::function<void(bool)> OnNetworkCB;
|
|
typedef std::function<void(bool)> OnTimeCB;
|
|
|
|
public:
|
|
void setup(settings_t *config, uint32_t *utcTimestamp, OnNetworkCB onNetworkCB, OnTimeCB onTimeCB) {
|
|
mConfig = config;
|
|
mUtcTimestamp = utcTimestamp;
|
|
mOnNetworkCB = onNetworkCB;
|
|
mOnTimeCB = onTimeCB;
|
|
|
|
#if defined(ESP32)
|
|
WiFi.onEvent([this](WiFiEvent_t event) -> void {
|
|
this->OnEvent(event);
|
|
});
|
|
#else
|
|
wifiConnectHandler = WiFi.onStationModeConnected(
|
|
[this](const WiFiEventStationModeConnected& event) -> void {
|
|
OnEvent(SYSTEM_EVENT_STA_CONNECTED);
|
|
});
|
|
wifiGotIPHandler = WiFi.onStationModeGotIP(
|
|
[this](const WiFiEventStationModeGotIP& event) -> void {
|
|
OnEvent(SYSTEM_EVENT_STA_GOT_IP);
|
|
});
|
|
wifiDisconnectHandler = WiFi.onStationModeDisconnected(
|
|
[this](const WiFiEventStationModeDisconnected& event) -> void {
|
|
OnEvent(SYSTEM_EVENT_STA_DISCONNECTED);
|
|
});
|
|
#endif
|
|
}
|
|
|
|
bool isConnected() const {
|
|
return (mStatus == NetworkState.CONNECTED);
|
|
}
|
|
|
|
bool updateNtpTime(void) {
|
|
if(CONNECTED != mStatus)
|
|
return;
|
|
|
|
if (!mUdp.connected()) {
|
|
IPAddress timeServer;
|
|
if (!WiFi.hostByName(mConfig->ntp.addr, timeServer))
|
|
return false;
|
|
if (!mUdp.connect(timeServer, mConfig->ntp.port))
|
|
return false;
|
|
}
|
|
|
|
mUdp.onPacket([this](AsyncUDPPacket packet) {
|
|
this->handleNTPPacket(packet);
|
|
});
|
|
sendNTPpacket(timeServer);
|
|
|
|
return true;
|
|
}
|
|
|
|
public:
|
|
virtual void begin() = 0;
|
|
virtual void tickNetworkLoop() = 0;
|
|
virtual void connectionEvent(WiFiStatus_t status) = 0;
|
|
|
|
protected:
|
|
void setupIp(void) {
|
|
if(mConfig->sys.ip.ip[0] != 0) {
|
|
IPAddress ip(mConfig->sys.ip.ip);
|
|
IPAddress mask(mConfig->sys.ip.mask);
|
|
IPAddress dns1(mConfig->sys.ip.dns1);
|
|
IPAddress dns2(mConfig->sys.ip.dns2);
|
|
IPAddress gateway(mConfig->sys.ip.gateway);
|
|
if(!ETH.config(ip, gateway, mask, dns1, dns2))
|
|
DPRINTLN(DBG_ERROR, F("failed to set static IP!"));
|
|
}
|
|
}
|
|
|
|
void OnEvent(WiFiEvent_t event) {
|
|
switch(event) {
|
|
case SYSTEM_EVENT_STA_CONNECTED:
|
|
[[fallthrough]];
|
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
|
if(NetworkState::CONNECTED != mStatus) {
|
|
mStatus = NetworkState::CONNECTED;
|
|
DPRINTLN(DBG_INFO, F("Network connected"));
|
|
}
|
|
break;
|
|
|
|
case SYSTEM_EVENT_STA_GOT_IP:
|
|
[[fallthrough]];
|
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
|
mStatus = NetworkState::GOT_IP;
|
|
break;
|
|
|
|
case ARDUINO_EVENT_WIFI_STA_LOST_IP:
|
|
[[fallthrough]];
|
|
case ARDUINO_EVENT_WIFI_STA_STOP:
|
|
[[fallthrough]];
|
|
case SYSTEM_EVENT_STA_DISCONNECTED:
|
|
[[fallthrough]];
|
|
case ARDUINO_EVENT_ETH_STOP:
|
|
[[fallthrough]];
|
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
|
mStatus = NetworkState::DISCONNECTED;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
private:
|
|
void sendNTPpacket(IPAddress& address) {
|
|
//DPRINTLN(DBG_VERBOSE, F("wifi::sendNTPpacket"));
|
|
uint8_t buf[NTP_PACKET_SIZE];
|
|
memset(buf, 0, NTP_PACKET_SIZE);
|
|
|
|
buf[0] = 0b11100011; // LI, Version, Mode
|
|
buf[1] = 0; // Stratum
|
|
buf[2] = 6; // Max Interval between messages in seconds
|
|
buf[3] = 0xEC; // Clock Precision
|
|
// bytes 4 - 11 are for Root Delay and Dispersion and were set to 0 by memset
|
|
buf[12] = 49; // four-byte reference ID identifying
|
|
buf[13] = 0x4E;
|
|
buf[14] = 49;
|
|
buf[15] = 52;
|
|
|
|
//mUdp.beginPacket(address, 123); // NTP request, port 123
|
|
mUdp.write(buf, NTP_PACKET_SIZE);
|
|
//mUdp.endPacket();
|
|
}
|
|
|
|
void handleNTPPacket(AsyncUDPPacket packet) {
|
|
char buf[80];
|
|
|
|
memcpy(buf, packet.data(), sizeof(buf));
|
|
|
|
unsigned long highWord = word(buf[40], buf[41]);
|
|
unsigned long lowWord = word(buf[42], buf[43]);
|
|
|
|
// combine the four bytes (two words) into a long integer
|
|
// this is NTP time (seconds since Jan 1 1900):
|
|
unsigned long secsSince1900 = highWord << 16 | lowWord;
|
|
|
|
*mUtcTimestamp = secsSince1900 - 2208988800UL; // UTC time
|
|
DPRINTLN(DBG_INFO, "[NTP]: " + ah::getDateTimeStr(*mUtcTimestamp) + " UTC");
|
|
mOnTimeCB(true);
|
|
mUdp.close();
|
|
}
|
|
|
|
protected:
|
|
enum class NetworkState : uint8_t {
|
|
DISCONNECTED,
|
|
CONNECTING,
|
|
CONNECTED,
|
|
IN_AP_MODE,
|
|
GOT_IP,
|
|
IN_STA_MODE,
|
|
RESET,
|
|
SCAN_READY
|
|
};
|
|
|
|
protected:
|
|
settings_t *mConfig = nullptr;
|
|
uint32_t *mUtcTimestamp = nullptr;
|
|
|
|
OnNetworkCB mOnNetworkCB;
|
|
OnTimeCB mOnTimeCB;
|
|
|
|
NetworkState mStatus = NetworkState.DISCONNECTED;
|
|
|
|
WiFiUDP mUdp; // for time server
|
|
DNSServer mDns;
|
|
};
|
|
|
|
#endif /*__AHOY_NETWORK_H__*/
|
|
|