You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
277 lines
8.5 KiB
C
277 lines
8.5 KiB
C
#include <WiFiUdp.h>
|
|
#ifdef ESP8266
|
|
#include <ESP8266WiFi.h>
|
|
#elif defined(ESP32)
|
|
#include <WiFi.h>
|
|
#include <esp_wifi.h>
|
|
#elif defined(ARDUINO_ARCH_RP2040)
|
|
#include <WiFi.h>
|
|
#endif
|
|
#ifdef USE_ETHERNET
|
|
#include <ETH.h>
|
|
#endif
|
|
|
|
// select WiFi SSID configuration
|
|
#if defined(WIFI_SSID)
|
|
#define FDRS_WIFI_SSID WIFI_SSID
|
|
#elif defined(GLOBAL_WIFI_SSID)
|
|
#define FDRS_WIFI_SSID GLOBAL_WIFI_SSID
|
|
#else
|
|
// ASSERT("NO WiFi SSID defined! Please define in fdrs_globals.h (recommended) or in fdrs_node_config.h");
|
|
#endif // WIFI_SSID
|
|
|
|
// select WiFi password
|
|
#if defined(WIFI_PASS)
|
|
#define FDRS_WIFI_PASS WIFI_PASS
|
|
#elif defined(GLOBAL_WIFI_PASS)
|
|
#define FDRS_WIFI_PASS GLOBAL_WIFI_PASS
|
|
#else
|
|
// ASSERT("NO WiFi password defined! Please define in fdrs_globals.h (recommended) or in fdrs_node_config.h");
|
|
#endif // WIFI_PASS
|
|
|
|
// select Host IP Address
|
|
#if defined(HOST_IPADDRESS)
|
|
#define FDRS_HOST_IPADDRESS HOST_IPADDRESS
|
|
#elif defined(GLOBAL_HOST_IPADDRESS)
|
|
#define FDRS_HOST_IPADDRESS GLOBAL_HOST_IPADDRESS
|
|
#else
|
|
#endif // HOST_IPADDRESS
|
|
|
|
// select Gateway IP Address
|
|
#if defined(GW_IPADDRESS)
|
|
#define FDRS_GW_IPADDRESS GW_IPADDRESS
|
|
#elif defined(GLOBAL_GW_IPADDRESS)
|
|
#define FDRS_GW_IPADDRESS GLOBAL_GW_IPADDRESS
|
|
#else
|
|
#endif // GW_IPADDRESS
|
|
|
|
// select Subnet Address
|
|
#if defined(SUBNET_ADDRESS)
|
|
#define FDRS_SUBNET_ADDRESS SUBNET_ADDRESS
|
|
#elif defined(GLOBAL_SUBNET_ADDRESS)
|
|
#define FDRS_SUBNET_ADDRESS GLOBAL_SUBNET_ADDRESS
|
|
#else
|
|
#endif // SUBNET_ADDRESS
|
|
|
|
// select DNS1 IP Address configuration
|
|
#if defined(DNS1_IPADDRESS)
|
|
#define FDRS_DNS1_IPADDRESS DNS1_IPADDRESS
|
|
#elif defined(GLOBAL_DNS1_IPADDRESS)
|
|
#define FDRS_DNS1_IPADDRESS GLOBAL_DNS1_IPADDRESS
|
|
#else
|
|
// ASSERT("NO DNS1 IP Address defined! Please define in fdrs_globals.h (recommended) or in fdrs_gateway_config.h");
|
|
#endif // DNS1_IPADDRESS
|
|
|
|
// select DNS2 IP Address configuration
|
|
#if defined(DNS2_IPADDRESS)
|
|
#define FDRS_DNS2_IPADDRESS DNS2_IPADDRESS
|
|
#elif defined(GLOBAL_DNS2_IPADDRESS)
|
|
#define FDRS_DNS2_IPADDRESS GLOBAL_DNS2_IPADDRESS
|
|
#else
|
|
#endif // DNS2_IPADDRESS
|
|
|
|
// select NTP Time Server configuration
|
|
#if defined(TIME_SERVER)
|
|
#define FDRS_TIME_SERVER TIME_SERVER
|
|
#else
|
|
#define FDRS_TIME_SERVER GLOBAL_TIME_SERVER
|
|
#endif // TIME_SERVER
|
|
|
|
// select Time, in minutes, between NTP time server queries configuration
|
|
#if defined(TIME_FETCHNTP)
|
|
#define FDRS_TIME_FETCHNTP TIME_FETCHNTP
|
|
#else
|
|
#define FDRS_TIME_FETCHNTP GLOBAL_TIME_FETCHNTP
|
|
#endif // TIME_FETCHNTP
|
|
|
|
|
|
WiFiUDP FDRSNtp;
|
|
unsigned int localPort = 8888; // local port to listen for UDP packets
|
|
const char timeServer[] = FDRS_TIME_SERVER; // NTP server
|
|
const int NTP_PACKET_SIZE = 48; // NTP time stamp is in the first 48 bytes of the message
|
|
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming and outgoing packets
|
|
uint NTPFetchFail = 0; // consecutive NTP fetch failures
|
|
extern time_t now;
|
|
|
|
const char *ssid = FDRS_WIFI_SSID;
|
|
const char *password = FDRS_WIFI_PASS;
|
|
#ifdef USE_STATIC_IPADDRESS
|
|
uint8_t hostIpAddress[4], gatewayAddress[4], subnetAddress[4], dns1Address[4], dns2Address[4];
|
|
#endif
|
|
|
|
#ifdef USE_ETHERNET
|
|
static bool eth_connected = false;
|
|
|
|
void WiFiEvent(WiFiEvent_t event)
|
|
{
|
|
switch (event) {
|
|
case ARDUINO_EVENT_ETH_START:
|
|
Serial.println("ETH Started");
|
|
//set eth hostname here
|
|
ETH.setHostname("esp32-ethernet");
|
|
break;
|
|
case ARDUINO_EVENT_ETH_CONNECTED:
|
|
Serial.println("ETH Connected");
|
|
break;
|
|
case ARDUINO_EVENT_ETH_GOT_IP:
|
|
Serial.print("ETH MAC: ");
|
|
Serial.print(ETH.macAddress());
|
|
Serial.print(", IPv4: ");
|
|
Serial.print(ETH.localIP());
|
|
if (ETH.fullDuplex()) {
|
|
Serial.print(", FULL_DUPLEX");
|
|
}
|
|
Serial.print(", ");
|
|
Serial.print(ETH.linkSpeed());
|
|
Serial.println("Mbps");
|
|
eth_connected = true;
|
|
break;
|
|
case ARDUINO_EVENT_ETH_DISCONNECTED:
|
|
Serial.println("ETH Disconnected");
|
|
eth_connected = false;
|
|
break;
|
|
case ARDUINO_EVENT_ETH_STOP:
|
|
Serial.println("ETH Stopped");
|
|
eth_connected = false;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
#endif // USE_ETHERNET
|
|
|
|
// Convert IP Addresses from strings to byte arrays of 4 bytes
|
|
void stringToByteArray(const char* str, char sep, byte* bytes, int maxBytes, int base) {
|
|
for (int i = 0; i < maxBytes; i++) {
|
|
bytes[i] = strtoul(str, NULL, base); // Convert byte
|
|
str = strchr(str, sep); // Find next separator
|
|
if (str == NULL || *str == '\0') {
|
|
break; // No more separators, exit
|
|
}
|
|
str++; // Point to next character after separator
|
|
}
|
|
}
|
|
|
|
void begin_wifi()
|
|
{
|
|
delay(10);
|
|
#ifdef USE_ETHERNET
|
|
WiFi.onEvent(WiFiEvent);
|
|
ETH.begin();
|
|
while (!eth_connected)
|
|
{
|
|
DBG("Connecting ethernet...");
|
|
delay(500);
|
|
}
|
|
#else
|
|
#ifdef USE_STATIC_IPADDRESS
|
|
// Convert from String to byte array
|
|
stringToByteArray(FDRS_HOST_IPADDRESS, '.', hostIpAddress, 4, 10);
|
|
stringToByteArray(FDRS_GW_IPADDRESS, '.', gatewayAddress, 4, 10);
|
|
stringToByteArray(FDRS_SUBNET_ADDRESS, '.', subnetAddress, 4, 10);
|
|
stringToByteArray(FDRS_DNS1_IPADDRESS, '.', dns1Address, 4, 10);
|
|
stringToByteArray(FDRS_DNS2_IPADDRESS, '.', dns2Address, 4, 10);
|
|
WiFi.config(hostIpAddress, gatewayAddress, subnetAddress, dns1Address, dns2Address);
|
|
#endif
|
|
WiFi.begin(ssid, password);
|
|
int connectTries = 0;
|
|
while (WiFi.status() != WL_CONNECTED)
|
|
{
|
|
connectTries++;
|
|
DBG("Connecting to WiFi SSID: " + String(FDRS_WIFI_SSID) + " try number " + String(connectTries));
|
|
delay(1000);
|
|
WiFi.reconnect();
|
|
if(connectTries >= 15) {
|
|
DBG("Restarting ESP32: WiFi issues\n");
|
|
delay(5000);
|
|
ESP.restart();
|
|
}
|
|
}
|
|
#endif // USE_ETHERNET
|
|
}
|
|
|
|
// send an NTP request to the time server at the given address
|
|
void sendNTPpacket(const char * address) {
|
|
// set all bytes in the buffer to 0
|
|
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
|
// Initialize values needed to form NTP request
|
|
// (see URL above for details on the packets)
|
|
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
|
packetBuffer[1] = 0; // Stratum, or type of clock
|
|
packetBuffer[2] = 6; // Polling Interval
|
|
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
|
// 8 bytes of zero for Root Delay & Root Dispersion
|
|
packetBuffer[12] = 49;
|
|
packetBuffer[13] = 0x4E;
|
|
packetBuffer[14] = 49;
|
|
packetBuffer[15] = 52;
|
|
|
|
// all NTP fields have been given values, now
|
|
// you can send a packet requesting a timestamp:
|
|
FDRSNtp.beginPacket(address, 123); // NTP requests are to port 123
|
|
FDRSNtp.write(packetBuffer, NTP_PACKET_SIZE);
|
|
FDRSNtp.endPacket();
|
|
}
|
|
|
|
void fetchNtpTime() {
|
|
//DBG("GetTime Function");
|
|
if(timeSource.tmSource <= TMS_NTP) {
|
|
#ifdef USE_ETHERNET
|
|
if(eth_connected) {
|
|
#elif defined(USE_WIFI)
|
|
if(WiFi.status() == WL_CONNECTED) {
|
|
#endif
|
|
//DBG("Calling .begin function");
|
|
FDRSNtp.begin(localPort);
|
|
|
|
sendNTPpacket(timeServer); // send an NTP packet to a time server
|
|
uint i = 0;
|
|
for(i = 0; i < 800; i++) {
|
|
if(FDRSNtp.parsePacket())
|
|
break;
|
|
delay(10);
|
|
}
|
|
if(i < 800) {
|
|
DBG2("Took " + String(i * 10) + "ms to get NTP response from " + String(timeServer) + ".");
|
|
NTPFetchFail = 0;
|
|
// We've received a packet, read the data from it
|
|
FDRSNtp.read(packetBuffer, NTP_PACKET_SIZE); // read the packet into the buffer
|
|
|
|
// the timestamp starts at byte 40 of the received packet and is four bytes,
|
|
// or two words, long. First, extract the two words:
|
|
|
|
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
|
|
unsigned long lowWord = word(packetBuffer[42], packetBuffer[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;
|
|
//DBG("Seconds since Jan 1 1900 = " + String(secsSince1900));
|
|
|
|
// now convert NTP time into everyday time:
|
|
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
|
|
const unsigned long seventyYears = 2208988800UL;
|
|
// subtract seventy years:
|
|
// now is epoch format - seconds since Jan 1 1970
|
|
now = secsSince1900 - seventyYears;
|
|
if(setTime(now)) {
|
|
timeSource.tmNetIf = TMIF_LOCAL;
|
|
timeSource.tmAddress = 0xFFFF;
|
|
timeSource.tmSource = TMS_NTP;
|
|
timeSource.tmLastTimeSet = millis();
|
|
DBG1("Time source is now local NTP");
|
|
} // UTC time
|
|
}
|
|
else {
|
|
DBG1("Timeout getting a NTP response.");
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
void begin_ntp() {
|
|
fetchNtpTime();
|
|
handleTime();
|
|
printTime();
|
|
} |