378 lines
11 KiB
C++
378 lines
11 KiB
C++
// 1-channel LoRa Gateway for ESP8266 and ESP32
|
|
// Copyright (c) 2016-2020 Maarten Westenberg version for ESP8266
|
|
//
|
|
// based on work done by Thomas Telkamp for Raspberry PI 1ch gateway
|
|
// and many others.
|
|
//
|
|
// All rights reserved. This program and the accompanying materials
|
|
// are made available under the terms of the MIT License
|
|
// which accompanies this distribution, and is available at
|
|
// https://opensource.org/licenses/mit-license.php
|
|
//
|
|
// NO WARRANTY OF ANY KIND IS PROVIDED
|
|
//
|
|
// Author: Maarten Westenberg (mw12554@hotmail.com)
|
|
//
|
|
// This file contains the LoRa filesystem specific code
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// WLANSTATUS prints the status of the Wlan.
|
|
// The status of the Wlan "connection" can change if we have no relation
|
|
// with the well known router anymore. Normally this relation is preserved
|
|
// but sometimes we have to reconfirm to the router again and we get the same
|
|
// address too.
|
|
// So, if the router is still in range we can "survive" with the same address
|
|
// and we may have to renew the "connection" from time to time.
|
|
// But when we loose the SSID connection, we may have to look for another router.
|
|
//
|
|
// Parameters: <none>
|
|
// Return value: Returns 1 when still WL_CONNETED, otherwise returns 0
|
|
// ----------------------------------------------------------------------------
|
|
int WlanStatus() {
|
|
|
|
switch (WiFi.status()) {
|
|
case WL_CONNECTED:
|
|
# if _MONITOR>=1
|
|
if ( debug>=1 ) {
|
|
mPrint("WlanStatus:: CONNECTED ssid=" + String(WiFi.SSID())); // 3
|
|
}
|
|
# endif //_MONITOR
|
|
WiFi.setAutoReconnect(true); // Reconect to this AP if DISCONNECTED
|
|
return(1);
|
|
break;
|
|
|
|
// In case we get disconnected from the AP we lose the IP address.
|
|
// The ESP is configured to reconnect to the last router in memory.
|
|
case WL_DISCONNECTED:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 ) {
|
|
mPrint("WlanStatus:: DISCONNECTED, IP=" + String(WiFi.localIP().toString())); // 6
|
|
}
|
|
# endif
|
|
//while (! WiFi.isConnected() ) {
|
|
delay(100);
|
|
//}
|
|
return(0);
|
|
break;
|
|
|
|
// When still pocessing
|
|
case WL_IDLE_STATUS:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 ) {
|
|
mPrint("WlanStatus:: IDLE"); // 0
|
|
}
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
// This code is generated as soonas the AP is out of range
|
|
// Whene detected, the program will search for a better AP in range
|
|
case WL_NO_SSID_AVAIL:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 )
|
|
mPrint("WlanStatus:: NO SSID"); // 1
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
case WL_CONNECT_FAILED:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 )
|
|
mPrint("WlanStatus:: Connect FAILED"); // 4
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
// Never seen this code
|
|
case WL_SCAN_COMPLETED:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 )
|
|
mPrint("WlanStatus:: SCAN COMPLETE"); // 2
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
// Never seen this code
|
|
case WL_CONNECTION_LOST:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 )
|
|
mPrint("WlanStatus:: Connection LOST"); // 5
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
// This code is generated for example when WiFi.begin() has not been called
|
|
// before accessing WiFi functions
|
|
case WL_NO_SHIELD:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 )
|
|
mPrint("WlanStatus:: WL_NO_SHIELD"); //
|
|
# endif //_MONITOR
|
|
break;
|
|
|
|
default:
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 ) {
|
|
mPrint("WlanStatus Error:: code=" + String(WiFi.status())); // 255 means ERROR
|
|
}
|
|
# endif //_MONITOR
|
|
break;
|
|
}
|
|
return(-1);
|
|
|
|
} // WlanStatus
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// When ESP WiFi Manager, do this
|
|
// ----------------------------------------------------------------------------
|
|
int wifiMgr()
|
|
{
|
|
#if _WIFIMANAGER==1
|
|
|
|
WiFiManager wifiManager;
|
|
|
|
# if _MONITOR>=1
|
|
if (debug>=1) {
|
|
mPrint("Starting Access Point Mode");
|
|
mPrint("Connect Wifi to accesspoint: "+String(AP_NAME)+" and connect to IP: 192.168.4.1");
|
|
}
|
|
# endif //_MONITOR
|
|
|
|
// Add the ID to the SSID of the WiFiManager
|
|
String ssid = String(AP_NAME) + "-" + String(ESP_getChipId(), HEX);
|
|
char s [ssid.length() + 1];
|
|
strncpy(s, ssid.c_str(), ssid.length());
|
|
s[ssid.length()]= 0;
|
|
|
|
wifiManager.setDebugOutput(false);
|
|
wifiManager.setConfigPortalTimeout(120);
|
|
wifiManager.startConfigPortal(s, AP_PASSWD );
|
|
wifiManager.setAPCallback(configModeCallback);
|
|
|
|
if (!wifiManager.autoConnect()) {
|
|
# if _MONITOR>=1
|
|
Serial.println("wifiMgr:: failed to connect and hit timeout");
|
|
# endif
|
|
ESP.restart();
|
|
delay(1000);
|
|
}
|
|
|
|
# if _MONITOR>=1
|
|
if ((debug>=1) && (pdebug & P_MAIN)) {
|
|
mPrint("WlanConnect:: Now starting WlanStatus");
|
|
delay(1);
|
|
int i = WlanStatus();
|
|
switch (i) {
|
|
case 1: mPrint("WlanConnect:: WlanStatus Connected"); break;
|
|
case 0: mPrint("WlanConnect:: WlanStatus Disconnected"); break;
|
|
default: mPrint("WlatConnect:: WlanStatus other");
|
|
}
|
|
}
|
|
# endif //_MONITOR
|
|
|
|
// At this point, there IS a Wifi Access Point found and connected
|
|
// We must connect to the local SPIFFS storage to store the access point
|
|
//String s = WiFi.SSID();
|
|
|
|
# if defined(ARDUINO_ARCH_ESP8266)
|
|
// Now look for the password
|
|
struct station_config sta_conf;
|
|
wifi_station_get_config(&sta_conf);
|
|
# else
|
|
mPrint("wifiMgr:: define arch specific");
|
|
# endif
|
|
|
|
#endif //_WIFIMANAGER
|
|
return 1;
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Callback Function for MiFiManager
|
|
// ----------------------------------------------------------------------------
|
|
//gets called when WiFiManager enters configuration mode
|
|
|
|
#if _WIFIMANAGER==1
|
|
void configModeCallback (WiFiManager *myWiFiManager)
|
|
{
|
|
|
|
Serial.println("Entered config mode");
|
|
Serial.println(WiFi.softAPIP());
|
|
//if you used auto generated SSID, print it
|
|
Serial.println(myWiFiManager->getConfigPortalSSID());
|
|
|
|
}
|
|
#endif //_WIFIMANAGER
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Function to join the Wifi Network (as defined in sta array
|
|
// It is a matter of returning to the main loop() asap and make sure in next loop
|
|
// the reconnect is done first thing. By default the system will reconnect to the
|
|
// samen SSID as it was connected to before.
|
|
// Parameters:
|
|
// int maxTry: Number of retries we do:
|
|
// 0: Used during Setup first CONNECT
|
|
// 1: Try once and if unsuccessful return(1);
|
|
// x: Try x times
|
|
//
|
|
// Returns:
|
|
// On failure: Return -1
|
|
// On connect: return 1
|
|
// On Disconnect state: return 0
|
|
//
|
|
// XXX After a few retries, the ESP should be reset. Note: Switching between
|
|
// two SSID's does the trick. Retrying the same SSID does not.
|
|
// Workaround is found below: Let the ESP forget the SSID
|
|
//
|
|
// NOTE: The Serial works only on debug setting and not on pdebug. This is
|
|
// because WiFi problems would make webserver (which works on WiFi) useless.
|
|
// ----------------------------------------------------------------------------
|
|
int WlanConnect(int maxTry) {
|
|
|
|
unsigned char agains = 0;
|
|
unsigned char wpa_index = 0;
|
|
|
|
// WiFi.persistent(false);
|
|
// WiFi.mode(WIFI_OFF); // this is a temporary line, to be removed after SDK update to 1.5.4
|
|
|
|
// Else: try to connect to WLAN as long as we are not connected.
|
|
// The try parameters tells us how many times we try before giving up
|
|
// Value 0 is reserved for setup() first time connect
|
|
int i=0;
|
|
|
|
while ((WiFi.status() != WL_CONNECTED) && (( i<= maxTry ) || (maxTry==0)) )
|
|
{
|
|
// We try every SSID in wpa array until success
|
|
for (unsigned int j=wpa_index; (j<(sizeof(wpa)/sizeof(wpa[0]))) && (WiFi.status() != WL_CONNECTED ); j++)
|
|
{
|
|
// Start with well-known access points in the list
|
|
char *ssid = wpa[j].login;
|
|
char *password = wpa[j].passw;
|
|
|
|
# if _MONITOR>=1
|
|
if ((debug>=1) && (pdebug & P_MAIN)) {
|
|
Serial.print(i);
|
|
Serial.print(':');
|
|
Serial.print(j);
|
|
Serial.print(':');
|
|
Serial.print(sizeof(wpa)/sizeof(wpa[0]));
|
|
Serial.print(F(". WlanConnect SSID="));
|
|
Serial.print(ssid);
|
|
if ( debug>=2 ) {
|
|
Serial.print(F(", pass="));
|
|
Serial.print(password);
|
|
}
|
|
Serial.println();
|
|
}
|
|
# endif //_MONITOR
|
|
|
|
// Count the number of times we call WiFi.begin
|
|
gwayConfig.wifis++;
|
|
|
|
WiFi.mode(WIFI_STA);
|
|
delay(1000);
|
|
WiFi.begin(ssid, password);
|
|
delay(8000);
|
|
|
|
// Check the connection status again, return values
|
|
// 1 = CONNECTED
|
|
// 0 = DISCONNECTED (will reconnect)
|
|
// -1 = No SSID or other cause
|
|
int stat = WlanStatus();
|
|
if ( stat == 1) {
|
|
writeGwayCfg(CONFIGFILE, &gwayConfig ); // Write configuration to SPIFFS
|
|
return(1);
|
|
}
|
|
|
|
// We increase the time for connect but try the same SSID
|
|
// We try for several times
|
|
agains=1;
|
|
while ((WiFi.status() != WL_CONNECTED) && (agains < 8)) {
|
|
agains++;
|
|
delay(8000); // delay(agains*500);
|
|
# if _MONITOR>=1
|
|
if ( debug>=0 ) {
|
|
Serial.print("."); // Serial only
|
|
}
|
|
# endif //_MONITOR
|
|
}
|
|
|
|
// Make sure that we can connect to different AP's than 1
|
|
// this is a patch. Normally we connect to previous one.
|
|
WiFi.persistent(false);
|
|
WiFi.mode(WIFI_OFF); // this is a temporary line, to be removed after SDK update to 1.5.4
|
|
|
|
} //for next WPA defined AP
|
|
|
|
i++; // Number of times we try to connect
|
|
} //while
|
|
|
|
yield();
|
|
return(1);
|
|
|
|
} //WlanConnect
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// resolveHost
|
|
// This function will use MDNS or DNS to resolve a hostname.
|
|
// So it may be .local or a normal hostname.
|
|
// Parameters:
|
|
// svrName: Name of the server we want the IP address from
|
|
// maxTry: The number we triue to get the value. 0 means: wait forever.
|
|
// Return:
|
|
// svrIP: 4 byte IP address of machine resolved
|
|
// ----------------------------------------------------------------------------
|
|
IPAddress resolveHost(String svrName, int maxTry)
|
|
{
|
|
IPAddress svrIP;
|
|
|
|
if (svrName.endsWith(".local")) {
|
|
# if defined(ESP32_ARCH)
|
|
svrName=svrName.substring(0,svrName.length()-6);
|
|
svrIP = MDNS.queryHost(svrName);
|
|
for (byte i=0; i<maxTry; i++) { // Try 5 times MDNS
|
|
svrIP = MDNS.queryHost(svrName);
|
|
if (svrIP.toString() != "0.0.0.0") break;
|
|
# if (_MONITOR>=1)
|
|
mPrint("ReTrying to resolve with mDNS");
|
|
# endif //_MONITOR
|
|
delay(12000);
|
|
}
|
|
# else
|
|
char cc[svrName.length() +1 ];
|
|
strncpy(cc, svrName.c_str(),svrName.length());
|
|
cc[svrName.length()]=0;
|
|
|
|
for (byte i=0; i<maxTry; i++) {
|
|
if (!WiFi.hostByName(cc, svrIP)) // Use DNS to get server IP once
|
|
{
|
|
mPrint("resolveHost:: ERROR hostByName="+ String(cc)+", len=" + String(sizeof(cc)));
|
|
};
|
|
delay(1000);
|
|
}
|
|
# if _MONITOR>=1
|
|
if ((debug>=1) && (pdebug & P_MAIN)) {
|
|
mPrint("resolveHost:: "+ String(cc) +" IP=" + String(svrIP.toString()) );
|
|
}
|
|
# endif //_MONITOR
|
|
# endif
|
|
}
|
|
else // Non LOCAL
|
|
{
|
|
char cc[svrName.length() +1 ]; // Assume whole array initially 0
|
|
strncpy(cc, svrName.c_str(),svrName.length());
|
|
cc[svrName.length()]=0;
|
|
|
|
for (byte i=0; i<maxTry; i++) {
|
|
if (WiFi.hostByName(cc, svrIP)) // Use DNS to get server IP once
|
|
{
|
|
# if _MONITOR>=1
|
|
mPrint("resolveHost:: OK="+ String(cc) +" IP=" + String(svrIP.toString()) );
|
|
# endif //_MONITOR
|
|
return svrIP; // If connected
|
|
}
|
|
else // Else not connected
|
|
{
|
|
mPrint("resolveHost:: ERROR hostByName="+ String(cc)+", len=" + String(sizeof(cc)));
|
|
};
|
|
delay(1000);
|
|
}
|
|
}
|
|
return svrIP;
|
|
} |