// 1-channel LoRa Gateway for ESP8266 // Copyright (c) 2016, 2017, 2018 Maarten Westenberg version for ESP8266 // Version 5.3.2 // Date: 2018-07-07 // // based on work done by many people and making use of several libraries. // // 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 webserver code for the ESP Single Channel Gateway. // Note: // The ESP Webserver works with Strings to display html content. // Care must be taken that not all data is output to the webserver in one string // as this will use a LOT of memory and possibly kill the heap (cause system // crash or other unreliable behaviour. // Instead, output of the various tables on the webpage should be displayed in // chucks so that strings are limited in size. // Be aware that using no strings but only sendContent() calls has its own // disadvantage that these calls take a lot of time and cause the page to be // displayed like an old typewriter. // So, the trick is to make chucks that are sent to the website by using // a response String but not make those Strings too big. // // Also, selecting too many options for Statistics, display, Hopping channels // etc makes the gateway more sluggish and may impact the availabile memory and // thus its performance and reliability. It's up to the uer to select wisely! // // ---------------------------------------------------------------------------- // PRINT IP // Output the 4-byte IP address for easy printing. // As this function is also used by _otaServer.ino do not put in #define // ---------------------------------------------------------------------------- static void printIP(IPAddress ipa, const char sep, String& response) { response+=(IPAddress)ipa[0]; response+=sep; response+=(IPAddress)ipa[1]; response+=sep; response+=(IPAddress)ipa[2]; response+=sep; response+=(IPAddress)ipa[3]; } // // The remainder of the file ONLY works is A_SERVER=1 is set. // #if A_SERVER==1 // ================================================================================ // WEBSERVER DECLARATIONS // ================================================================================ // None at the moment // ================================================================================ // WEBSERVER FUNCTIONS // ================================================================================ // ---------------------------------------------------------------------------- // Used by all functions requiring user confirmation // Displays a menu by user and two buttons "YES" and "CANCEL" // The function returns true for YES and false for CANCEL // ---------------------------------------------------------------------------- boolean YesNo(String s) { boolean ret = false; //Serial.println(F("Renew Web Page")); //sendWebPage("",""); return(ret); } // ---------------------------------------------------------------------------- // WWWFILE // This function will open a pop-up in the browser and then // display the contents of a file in that window // Output is sent to server.sendContent() // Parameters: // fn; String with filename // Returns: // // ---------------------------------------------------------------------------- void wwwFile(String fn) { if (!SPIFFS.exists(fn)) { #if DUSB>=1 Serial.print(F("wwwButtons:: ERROR: file not found=")); Serial.println(fn); #endif return; } #if DUSB>=2 else { Serial.print(F("wwwButtons:: File existist= ")); Serial.println(fn); } #endif #if DUSB>=1 File f = SPIFFS.open(fn, "r"); // Open the file for reading int j; for (j=0; j // ---------------------------------------------------------------------------- static void wwwButtons() { String response = ""; response += ""; response += ""; server.sendContent(response); // Send to the screen } // ---------------------------------------------------------------------------- // SET ESP8266 WEB SERVER VARIABLES // // This funtion implements the WiFI Webserver (very simple one). The purpose // of this server is to receive simple admin commands, and execute these // results are sent back to the web client. // Commands: DEBUG, ADDRESS, IP, CONFIG, GETTIME, SETTIME // The webpage is completely built response and then printed on screen. // Parameters: // cmd: Contains a character array with the command to execute // arg: Contains the parameter value of that command // Returns: // // ---------------------------------------------------------------------------- static void setVariables(const char *cmd, const char *arg) { // DEBUG settings; These can be used as a single argument if (strcmp(cmd, "DEBUG")==0) { // Set debug level 0-2 if (atoi(arg) == 1) { debug = (debug+1)%4; } else if (atoi(arg) == -1) { debug = (debug+3)%4; } writeGwayCfg(CONFIGFILE); // Save configuration to file } if (strcmp(cmd, "CAD")==0) { // Set -cad on=1 or off=0 _cad=(bool)atoi(arg); writeGwayCfg(CONFIGFILE); // Save configuration to file } if (strcmp(cmd, "HOP")==0) { // Set -hop on=1 or off=0 _hop=(bool)atoi(arg); if (! _hop) { ifreq=0; freq=freqs[ifreq]; rxLoraModem(); sf = SF7; cadScanner(); } writeGwayCfg(CONFIGFILE); // Save configuration to file } if (strcmp(cmd, "DELAY")==0) { // Set delay usecs txDelay+=atoi(arg)*1000; } // SF; Handle Spreading Factor Settings if (strcmp(cmd, "SF")==0) { uint8_t sfi = sf; if (atoi(arg) == 1) { if (sf>=SF12) sf=SF7; else sf= (sf_t)((int)sf+1); } else if (atoi(arg) == -1) { if (sf<=SF7) sf=SF12; else sf= (sf_t)((int)sf-1); } rxLoraModem(); // Reset the radion with the new spreading factor writeGwayCfg(CONFIGFILE); // Save configuration to file } // FREQ; Handle Frequency Settings if (strcmp(cmd, "FREQ")==0) { uint8_t nf = sizeof(freqs)/sizeof(int); // Number of elements in array // Compute frequency index if (atoi(arg) == 1) { if (ifreq==(nf-1)) ifreq=0; else ifreq++; } else if (atoi(arg) == -1) { Serial.println("down"); if (ifreq==0) ifreq=(nf-1); else ifreq--; } freq = freqs[ifreq]; rxLoraModem(); // Reset the radion with the new frequency writeGwayCfg(CONFIGFILE); // Save configuration to file } //if (strcmp(cmd, "GETTIME")==0) { Serial.println(F("gettime tbd")); } // Get the local time //if (strcmp(cmd, "SETTIME")==0) { Serial.println(F("settime tbd")); } // Set the local time if (strcmp(cmd, "HELP")==0) { Serial.println(F("Display Help Topics")); } #if GATEWAYNODE==1 if (strcmp(cmd, "NODE")==0) { // Set node on=1 or off=0 gwayConfig.isNode =(bool)atoi(arg); writeGwayCfg(CONFIGFILE); // Save configuration to file } if (strcmp(cmd, "FCNT")==0) { frameCount=0; rxLoraModem(); // Reset the radion with the new frequency writeGwayCfg(CONFIGFILE); } #endif #if WIFIMANAGER==1 if (strcmp(cmd, "NEWSSID")==0) { WiFiManager wifiManager; strcpy(wpa[0].login,""); strcpy(wpa[0].passw,""); WiFi.disconnect(); wifiManager.autoConnect(AP_NAME, AP_PASSWD ); } #endif #if A_OTA==1 if (strcmp(cmd, "UPDATE")==0) { if (atoi(arg) == 1) { updateOtaa(); } } #endif #if A_REFRESH==1 if (strcmp(cmd, "REFR")==0) { // Set refresh on=1 or off=0 gwayConfig.refresh =(bool)atoi(arg); writeGwayCfg(CONFIGFILE); // Save configuration to file } #endif } // ---------------------------------------------------------------------------- // OPEN WEB PAGE // This is the init function for opening the webpage // // ---------------------------------------------------------------------------- static void openWebPage() { ++gwayConfig.views; // increment number of views #if A_REFRESH==1 //server.client().stop(); // Experimental, stop webserver in case something is still running! #endif String response=""; server.sendHeader("Cache-Control", "no-cache, no-store, must-revalidate"); server.sendHeader("Pragma", "no-cache"); server.sendHeader("Expires", "-1"); // init webserver, fill the webpage // NOTE: The page is renewed every _WWW_INTERVAL seconds, please adjust in ESP-sc-gway.h // server.setContentLength(CONTENT_LENGTH_UNKNOWN); server.send(200, "text/html", ""); #if A_REFRESH==1 if (gwayConfig.refresh) { response += String() + "ESP8266 1ch Gateway"; } #else response += String() + "ESP8266 1ch Gateway"; #endif response += ""; response += ""; response += ""; response +="

ESP Gateway Config

"; response +="

"; response +="Version: "; response+=VERSION; response +="
ESP alive since "; // STARTED ON stringTime(startTime, response); response +=", Uptime: "; // UPTIME uint32_t secs = millis()/1000; uint16_t days = secs / 86400; // Determine number of days uint8_t _hour = hour(secs); uint8_t _minute = minute(secs); uint8_t _second = second(secs); response += String() + days + "-"; if (_hour < 10) response += "0"; response += String() + _hour + ":"; if (_minute < 10) response += "0"; response += String() + _minute + ":"; if (_second < 10) response += "0"; response += String() + _second; response +="
Current time "; // CURRENT TIME stringTime(now(), response); response +="
"; response +="

"; server.sendContent(response); } // ---------------------------------------------------------------------------- // CONFIG AND SETTINGS DATA // // // ---------------------------------------------------------------------------- static void settingsData() { String response=""; String bg=""; response +="

Gateway Settings

"; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; bg = " background-color: "; bg += ( _cad ? "LightGreen" : "orange" ); response +=""; response +=""; response +=""; response +=""; bg = " background-color: "; bg += ( _hop ? "LightGreen" : "orange" ); response +=""; response +=""; response +=""; response +=""; response +=""; } else { response += sf; response +=""; response +=""; } response +=""; // Channel response +=""; response +=""; } else { response += String() + ifreq; response +=""; response +=""; response +=""; } response +=""; // Debugging options, only when DUSB is set, otherwise no // serial activity #if DUSB>=1 response +=""; response +=""; response +=""; response +=""; response +=""; bg = ( (pdebug & P_SCAN) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_CAD) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_RX) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_TX) ? "LightGreen" : "orange" ); response +=""; response += ""; // Use a second Line response +=""; bg = ( (pdebug & P_PRE) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_MAIN) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_GUI) ? "LightGreen" : "orange" ); response +=""; bg = ( (pdebug & P_RADIO) ? "LightGreen" : "orange" ); response +=""; response +=""; #endif // Serial Debugging response +=""; //response +=""; //response +=""; response +=""; #if GATEWAYNODE==1 response +=""; response +=""; response +=""; bg = " background-color: "; bg += ( (gwayConfig.isNode == 1) ? "LightGreen" : "orange" ); response +=""; response +=""; response +=""; response +=""; #endif #if A_REFRESH==1 bg = " background-color: "; bg += ( (gwayConfig.refresh == 1) ? "LightGreen" : "orange" ); response +=""; response +=""; response +=""; response +=""; #endif // Reset Accesspoint #if WIFIMANAGER==1 response +=""; #endif // Update Firmware all statistics response +=""; response +=""; // Format the Filesystem response +=""; response +=String() + ""; response +=""; // Reset all statistics #if STATISTICS >= 1 response +=""; response +=String() + ""; response +=""; // Reset response +=""; response +=String() + ""; response +=""; #endif response +="
SettingValueSet
CAD"; response += ( _cad ? "ON" : "OFF" ); response +="
HOP"; response += ( _hop ? "ON" : "OFF" ); response +="
SF Setting"; if (_cad) { response += "AUTO
Channel"; if (_hop) { response += "AUTO
Debug level"; response +=debug; response +="
Debug pattern"; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +="
"; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +="
Usb Debug"; response +=DUSB; response +="
Framecounter Internal Sensor"; response +=frameCount; response +=""; response +="
Gateway Node"; response += ( (gwayConfig.isNode == true) ? "ON" : "OFF" ); response +="
WWW Refresh"; response += ( (gwayConfig.refresh == 1) ? "ON" : "OFF" ); response +="
"; response +="Click here to reset accesspoint
"; response +="
Update Firmware
Format SPIFFS"+""+"
Statistics"+statc.resets+"
Boots and Resets"+gwayConfig.boots+"
"; server.sendContent(response); } // ---------------------------------------------------------------------------- // INTERRUPT DATA // Display interrupt data, but only for debug >= 2 // // ---------------------------------------------------------------------------- static void interruptData() { uint8_t flags = readRegister(REG_IRQ_FLAGS); uint8_t mask = readRegister(REG_IRQ_FLAGS_MASK); if (debug >= 2) { String response=""; response +="

System State and Interrupt

"; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +="
ParameterValueSet
_state"; switch (_state) { // See loraModem.h case S_INIT: response +="INIT"; break; case S_SCAN: response +="SCAN"; break; case S_CAD: response +="CAD"; break; case S_RX: response +="RX"; break; case S_TX: response +="TX"; break; default: response +="unknown"; break; } response +="
flags (8 bits)0x"; if (flags <16) response += "0"; response +=String(flags,HEX); response+="
mask (8 bits)0x"; if (mask <16) response += "0"; response +=String(mask,HEX); response+="
Re-entrant cntr"; response += String() + gwayConfig.reents; response +="
ntp call cntr"; response += String() + gwayConfig.ntps; response+="
ntpErr cntr"; response += String() + gwayConfig.ntpErr; response +=""; stringTime(gwayConfig.ntpErrTime, response); response +="
Time Correction (uSec)"; response += txDelay; response +="
"; server.sendContent(response); }// if debug>=2 } // ---------------------------------------------------------------------------- // STATISTICS DATA // // ---------------------------------------------------------------------------- static void statisticsData() { String response=""; // Header response +="

Package Statistics

"; response +=""; response +=""; #if STATISTICS == 3 response +=""; response +=""; response +=""; #endif response +=""; response +=""; response +=""; // Table rows response +=""; #if STATISTICS == 3 response +=""; response +=""; response +=""; #endif response += ""; response +=""; response +=""; #if STATISTICS == 3 response +=""; response +=""; response +=""; #endif response +=""; response +=""; response +=""; #if STATISTICS == 3 response +=""; response +=""; response +=""; #endif response +=""; response +=""; // Provide a table with all the SF data including percentage of messsages #if STATISTICS == 2 response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; #endif #if STATISTICS == 3 response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; #endif response +="
CounterC 0C 1C 2PkgsPkgs/hr
Packages Downlink" + String(cp_up_pkt_fwd) + "
Packages Uplink Total" + String(cp_nb_rx_rcv) + "" + String((cp_nb_rx_rcv*3600)/(now() - startTime)) + "
Packages Uplink OK " + String(cp_nb_rx_ok) + "
SF7 rcvd"; response +=statc.sf7; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf7/cp_nb_rx_rcv : 0)+" %"; response +="
SF8 rcvd"; response +=statc.sf8; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf8/cp_nb_rx_rcv : 0)+" %"; response +="
SF9 rcvd"; response +=statc.sf9; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf9/cp_nb_rx_rcv : 0)+" %"; response +="
SF10 rcvd"; response +=statc.sf10; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf10/cp_nb_rx_rcv : 0)+" %"; response +="
SF11 rcvd"; response +=statc.sf11; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf11/cp_nb_rx_rcv : 0)+" %"; response +="
SF12 rcvd"; response +=statc.sf12; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf12/cp_nb_rx_rcv : 0)+" %"; response +="
SF7 rcvd"; response +=statc.sf7_0; response +=""; response +=statc.sf7_1; response +=""; response +=statc.sf7_2; response +=""; response +=statc.sf7; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf7/cp_nb_rx_rcv : 0)+" %"; response +="
SF8 rcvd"; response +=statc.sf8_0; response +=""; response +=statc.sf8_1; response +=""; response +=statc.sf8_2; response +=""; response +=statc.sf8; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf8/cp_nb_rx_rcv : 0)+" %"; response +="
SF9 rcvd"; response +=statc.sf9_0; response +=""; response +=statc.sf9_1; response +=""; response +=statc.sf9_2; response +=""; response +=statc.sf9; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf9/cp_nb_rx_rcv : 0)+" %"; response +="
SF10 rcvd"; response +=statc.sf10_0; response +=""; response +=statc.sf10_1; response +=""; response +=statc.sf10_2; response +=""; response +=statc.sf10; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf10/cp_nb_rx_rcv : 0)+" %"; response +="
SF11 rcvd"; response +=statc.sf11_0; response +=""; response +=statc.sf11_1; response +=""; response +=statc.sf11_2; response +=""; response +=statc.sf11; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf11/cp_nb_rx_rcv : 0)+" %"; response +="
SF12 rcvd"; response +=statc.sf12_0; response +=""; response +=statc.sf12_1; response +=""; response +=statc.sf12_1; response +=""; response +=statc.sf12; response +=""; response += String(cp_nb_rx_rcv>0 ? 100*statc.sf12/cp_nb_rx_rcv : 0)+" %"; response +="
"; server.sendContent(response); } // ---------------------------------------------------------------------------- // SENSORDATA // If enabled, display the sensorHistory on the current webserver Page. // In this GUI section a number of statr[x] records are displayed such as: // // Time, The time the sensor message was received // Node, the DevAddr or even Node name for Trusted nodes, // Data (Localserver), when _LOCALSERVER is enabled contains decoded data // C, Channel frequency on which the sensor was received // Freq, The frequency of the channel // SF, Spreading Factor // pRSSI, Packet RSSI // // Parameters: // - // Returns: // - // ---------------------------------------------------------------------------- static void sensorData() { #if STATISTICS >= 1 String response=""; response += "

Message History

"; response += ""; response += ""; response += ""; response += ""; #if _LOCALSERVER==1 response += ""; #endif response += ""; response += ""; response += ""; response += ""; #if RSSI==1 if (debug > 1) { response += ""; } #endif response += ""; server.sendContent(response); for (int i=0; i"; response += String() + ""; #if _LOCALSERVER==1 response += String() + ""; response += String() + ""; response += String() + ""; response += String() + ""; #if RSSI==1 if (debug > 1) { response += String() + ""; } #endif response += ""; server.sendContent(response); } server.sendContent("
TimeNodeDataCFreqSFpRSSIRSSI
"; // Tmst stringTime((statr[i].tmst), response); // XXX Change tmst not to be millis() dependent response += ""; // Node if (SerialName((char *)(& (statr[i].node)), response) < 0) { // works with TRUSTED_NODES >= 1 printHEX((char *)(& (statr[i].node)),' ',response); // else } response += ""; // Data for (int j=0; j" + statr[i].ch + "" + freqs[statr[i].ch] + "" + statr[i].sf + "" + statr[i].prssi + "" + statr[i].rssi + "
"); #endif } // ---------------------------------------------------------------------------- // SYSTEMDATA // // ---------------------------------------------------------------------------- static void systemData() { String response=""; response +="

System Status

"; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; // XXX We Shoudl find an ESP32 alternative #if !defined ESP32_ARCH response +=""; response +=""; response+=""; response +=""; #endif response +=""; #if STATISTICS>=1 response +=""; response +=""; #endif response +="
ParameterValueSet
Gateway ID"; if (MAC_array[0]< 0x10) response +='0'; response +=String(MAC_array[0],HEX); // The MAC array is always returned in lowercase if (MAC_array[1]< 0x10) response +='0'; response +=String(MAC_array[1],HEX); if (MAC_array[2]< 0x10) response +='0'; response +=String(MAC_array[2],HEX); response +="FFFF"; if (MAC_array[3]< 0x10) response +='0'; response +=String(MAC_array[3],HEX); if (MAC_array[4]< 0x10) response +='0'; response +=String(MAC_array[4],HEX); if (MAC_array[5]< 0x10) response +='0'; response +=String(MAC_array[5],HEX); response+="
Free heap"; response+=ESP.getFreeHeap(); response+="
ESP speed"; response+=ESP.getCpuFreqMHz(); response +="
ESP Chip ID"; response+=ESP.getChipId(); response+="
OLED"; response+=OLED; response+="
WiFi Setups"; response+=gwayConfig.wifis; response+="
WWW Views"; response+=gwayConfig.views; response+="
"; server.sendContent(response); } // ---------------------------------------------------------------------------- // WIFIDATA // Display the most important Wifi parameters gathered // // ---------------------------------------------------------------------------- static void wifiData() { String response=""; response +="

WiFi Config

"; response +=""; response +=""; response +=""; #else response +=wifi_station_get_hostname(); response+=""; #endif response +=""; response +=""; response +=""; response +=""; response +=""; response +=""; #ifdef _THINGSERVER response +=""; response +=""; #endif response +="
ParameterValue
WiFi host"; #if ESP32_ARCH==1 response +=WiFi.getHostname(); response+="
WiFi SSID"; response +=WiFi.SSID(); response+="
IP Address"; printIP((IPAddress)WiFi.localIP(),'.',response); response +="
IP Gateway"; printIP((IPAddress)WiFi.gatewayIP(),'.',response); response +="
NTP Server"; response+=NTP_TIMESERVER; response+="
LoRa Router"; response+=_TTNSERVER; response+="
LoRa Router IP"; printIP((IPAddress)ttnServer,'.',response); response +="
LoRa Router 2"; response+=_THINGSERVER; response += String() + ":" + _THINGPORT + "
LoRa Router 2 IP"; printIP((IPAddress)thingServer,'.',response); response +="
"; server.sendContent(response); } // ---------------------------------------------------------------------------- // SEND WEB PAGE() // Call the webserver and send the standard content and the content that is // passed by the parameter. // // NOTE: This is the only place where yield() or delay() calls are used. // // ---------------------------------------------------------------------------- void sendWebPage(const char *cmd, const char *arg) { openWebPage(); yield(); wwwButtons(); setVariables(cmd,arg); yield(); statisticsData(); yield(); // Node statistics sensorData(); yield(); // Display the sensor history, message statistics settingsData(); yield(); // Display web configuration wifiData(); yield(); // WiFI specific parameters systemData(); yield(); // System statistics such as heap etc. interruptData(); yield(); // Display interrupts only when debug >= 2 // Close the client connection to server server.sendContent(String() + "

Click here to explain Help and REST options


"); server.sendContent(String() + ""); server.sendContent(""); yield(); server.client().stop(); } // ---------------------------------------------------------------------------- // SetupWWW function called by main setup() program to setup webserver // It does actually not much more than installing the callback handlers // for messages sent to the webserver // // Implemented is an interface like: // http:///= // // ---------------------------------------------------------------------------- void setupWWW() { server.begin(); // Start the webserver // ----------------- // BUTTONS, define what should happen with the buttons we press on the homepage server.on("/", []() { sendWebPage("",""); // Send the webPage string server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/HELP", []() { sendWebPage("HELP",""); // Send the webPage string server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Format the filesystem server.on("/FORMAT", []() { Serial.print(F("FORMAT ...")); SPIFFS.format(); // Normally disabled. Enable only when SPIFFS corrupt initConfig(&gwayConfig); Serial.println(F("DONE")); }); // Reset the statistics server.on("/RESET", []() { Serial.println(F("RESET")); startTime= now() - 1; // Reset all timers too cp_nb_rx_rcv = 0; // Reset package statistics cp_nb_rx_ok = 0; cp_up_pkt_fwd = 0; #if STATISTICS >= 1 for (int i=0; i= 2 statc.sf7 = 0; statc.sf8 = 0; statc.sf9 = 0; statc.sf10= 0; statc.sf11= 0; statc.sf12= 0; statc.resets= 0; writeGwayCfg(CONFIGFILE); #if STATISTICS >= 3 statc.sf7_0 = 0; statc.sf7_1 = 0; statc.sf7_2 = 0; statc.sf8_0 = 0; statc.sf8_1 = 0; statc.sf8_2 = 0; statc.sf9_0 = 0; statc.sf9_1 = 0; statc.sf9_2 = 0; statc.sf10_0= 0; statc.sf10_1= 0; statc.sf10_2= 0; statc.sf11_0= 0; statc.sf11_1= 0; statc.sf11_2= 0; statc.sf12_0= 0; statc.sf12_1= 0; statc.sf12_2= 0; #endif #endif #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Reset the boot counter server.on("/BOOT", []() { Serial.println(F("BOOT")); #if STATISTICS >= 2 gwayConfig.boots = 0; gwayConfig.wifis = 0; gwayConfig.views = 0; gwayConfig.ntpErr = 0; // NTP errors gwayConfig.ntpErrTime = 0; // NTP last error time gwayConfig.ntps = 0; // Number of NTP calls #endif gwayConfig.reents = 0; // Re-entrance writeGwayCfg(CONFIGFILE); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/NEWSSID", []() { sendWebPage("NEWSSID",""); // Send the webPage string server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Set debug parameter server.on("/DEBUG=-1", []() { // Set debug level 0-2 debug = (debug+3)%4; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/DEBUG=1", []() { debug = (debug+1)%4; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Set PDEBUG parameter // server.on("/PDEBUG=SCAN", []() { // Set debug level 0-2 pdebug ^= P_SCAN; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=CAD", []() { // Set debug level 0-2 pdebug ^= P_CAD; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=RX", []() { // Set debug level 0-2 pdebug ^= P_RX; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=TX", []() { // Set debug level 0-2 pdebug ^= P_TX; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=PRE", []() { // Set debug level 0-2 pdebug ^= P_PRE; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=MAIN", []() { // Set debug level 0-2 pdebug ^= P_MAIN; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=GUI", []() { // Set debug level 0-2 pdebug ^= P_GUI; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/PDEBUG=RADIO", []() { // Set debug level 0-2 pdebug ^= P_RADIO; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Set delay in microseconds server.on("/DELAY=1", []() { txDelay+=1000; server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/DELAY=-1", []() { txDelay-=1000; server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Spreading Factor setting server.on("/SF=1", []() { if (sf>=SF12) sf=SF7; else sf= (sf_t)((int)sf+1); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/SF=-1", []() { if (sf<=SF7) sf=SF12; else sf= (sf_t)((int)sf-1); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Frequency of the GateWay node server.on("/FREQ=1", []() { uint8_t nf = sizeof(freqs)/sizeof(int); // Number of elements in array if (ifreq==(nf-1)) ifreq=0; else ifreq++; server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/FREQ=-1", []() { uint8_t nf = sizeof(freqs)/sizeof(int); // Number of elements in array if (ifreq==0) ifreq=(nf-1); else ifreq--; server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Set CAD function off/on server.on("/CAD=1", []() { _cad=(bool)1; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/CAD=0", []() { _cad=(bool)0; writeGwayCfg(CONFIGFILE); // Save configuration to file server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // GatewayNode server.on("/NODE=1", []() { #if GATEWAYNODE==1 gwayConfig.isNode =(bool)1; writeGwayCfg(CONFIGFILE); // Save configuration to file #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/NODE=0", []() { #if GATEWAYNODE==1 gwayConfig.isNode =(bool)0; writeGwayCfg(CONFIGFILE); // Save configuration to file #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); #if GATEWAYNODE==1 // Framecounter of the Gateway node server.on("/FCNT", []() { frameCount=0; rxLoraModem(); // Reset the radion with the new frequency writeGwayCfg(CONFIGFILE); //sendWebPage("",""); // Send the webPage string server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); #endif // WWW Page refresh function server.on("/REFR=1", []() { // WWW page auto refresh ON #if A_REFRESH==1 gwayConfig.refresh =1; writeGwayCfg(CONFIGFILE); // Save configuration to file #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/REFR=0", []() { // WWW page auto refresh OFF #if A_REFRESH==1 gwayConfig.refresh =0; writeGwayCfg(CONFIGFILE); // Save configuration to file #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // Switch off/on the HOP functions server.on("/HOP=1", []() { _hop=true; server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/HOP=0", []() { _hop=false; ifreq=0; freq=freqs[0]; rxLoraModem(); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); #if !defined ESP32_ARCH // Change speed to 160 MHz server.on("/SPEED=80", []() { system_update_cpu_freq(80); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); server.on("/SPEED=160", []() { system_update_cpu_freq(160); server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); #endif // Display Statistics server.on("/STAT", []() { buttonStat(); //server.sendHeader("Location", String("/"), true); //server.send ( 302, "text/plain", ""); }); server.on("/LOG", []() { server.sendHeader("Location", String("/"), true); buttonLog(); server.send ( 302, "text/plain", ""); }); // Update the sketch. Not yet implemented server.on("/UPDATE=1", []() { #if A_OTA==1 updateOtaa(); #endif server.sendHeader("Location", String("/"), true); server.send ( 302, "text/plain", ""); }); // ----------- // This section from version 4.0.7 defines what PART of the // webpage is shown based on the buttons pressed by the user // Maybe not all information should be put on the screen since it // may take too much time to serve all information before a next // package interrupt arrives at the gateway Serial.print(F("WWW Server started on port ")); Serial.println(A_SERVERPORT); return; } #endif