/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // // "Debug_2Hawk_GPS_Time.ino" as of 12/27/2018 @ 20:25 EST // // Arduino.cc topic: "NTP --ESP8266 Time-Synced, Data Logging and Web Server" 10/21/2018 @ 16:42 EDT --techno500 // // "NTP_Time-synced_with_RTC_Web_Interface.ino" developed by William Lucid // // Portion of NTP time code here were developed from code provided by schufti --of ESP8266Community // // https://forum.arduino.cc/index.php?topic=543468.0 //Project discussion at arduino.cc // // Supports WeMos D1 R2 Revison 2.1.0 and RobotDyn WiFi D1 R2 32 MB --ESP8266EX Baseds Developement Board // // https://wiki.wemos.cc/products:d1:d1 // // http://robotdyn.com/wifi-d1-r2-esp8266-dev-board-32m-flash.html // // listFiles and readFile functions by martinayotte of ESP8266 Community Forum. // // Time keeping using rtc and NTP developed from code provided by rudy of ESP8266 Community Forum. // // GPS and rain gauge code developed by haroon552 of Arduino.cc Community Forum // // Previous project: "SdWebBrowse_CC3000_HTTPServer.ino" by tech500" on https://github.com/tech500 // // Project is Open-Source, requires one Barometric Pressure sensor, BME280 and RobotDyn, ESP8266 based developement board. // // https://tinyurl.com/500-weather Project web page --Servered from ESP8266, RobotDyn WiFi D1 development board // // https://tinyurl.com/Indpls-weather Domain, Hosted web page // // // Debug Note: Must use esp8266 by ESP8266 Community version 2.4.2 from "Arduino IDE,Board Manager" // /////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Some lines require editing with your data; such as YourSSID, YourPassword, Your ThinkSpeak ChannelNumber, Your Thinkspeak API Key, Public IP, Forwarded Port, // Your filename for restricted access to "ACCESS.TXT." ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ******************************************************************************** // ******************************************************************************** // // See invidual library downloads for each library license. // // Following code was developed using the Adafruit CC300 library, "HTTPServer" example. // and by merging library examples, adding logic for Sketch flow. // // ********************************************************************************* // ********************************************************************************* #include #include #include #include #include #include // time() ctime() //Part of version 2.4.2 ESP8266 Board Manager install #include // struct timeval //Part of version 2.4.2 ESP8266 Board Manager install #include // settimeofday_cb() //Part of version 2.4.2 ESP8266 Board Manager install #include //Part of version 2.4.2 ESP8266 Board Manager install #include //Part of ESP8266-Arduino Core ----> Used for SPIFFS (file system) //#include //Part of version 2.4.2 ESP8266 Board Manager install ----> Used for NTP part of timekeeping #include //Part of version 2.4.2 ESP8266 Board Manager install #include //Part of version 2.4.2 ESP8266 Board Manager install #include //Part of ESP8266 Board Manager install #include //Part of version 2.4.2 ESP8266 Board Manager install ----> Used for Domain Web Interace #include //Part of the Arduino IDE software download -----> Used for I2C protocol #include "DS3231.h" //Used for time keeping rtc, DS3231 #include //https://github.com/mathworks/thingspeak-arduino . Get it using the Library Manager #include //https://github.com/plerup/espsoftwareserial ----> Used for GPS -->Special version for ESP8266! //#include "GSM_Module.h" // Source maybe part of Arduino IDE (?) --->Needed for SMS/Server upload #include //http://arduiniana.org/libraries/tinygpsplus/ Used for GPS parsing, NEO m8n #include //Use the Arduino Library Manager, get BME280 by Tyler Glenn //#include //https://github.com/esp8266/Basic/tree/master/libraries/LiquidCrystal Not used anymore //For FTP /////////// bool upload; //////////////////// SoftwareSerial swSer(12,13, false, 256); //D6,D7 Ublox 6m GPS module to pins 12 and 13 static const uint32_t GPSBaud = 9600; // Ublox GPS default Baud Rate is 9600 const double Home_LAT = 88.888888; // Your Home Latitude --edit with your data const double Home_LNG = 88.888888; // Your Home Longitude --edit with your data const char* WiFi_hostname = "DS3231-NTP"; //unsigned int localPort = 5000; // local port to listen for UDP packets //unsigned int timezone = 4.0; //unsigned int dst = 4; TinyGPSPlus gps; // Create an Instance of the TinyGPS++ object called gps // The serial connection to the GPS device //const int led15 = 15; DS3231 Clock; RTCDateTime dt; extern "C" { #include "user_interface.h" } // Replace with your network details const char* ssid = "R2D3"; const char* password = "sissy4357"; #define NTP0 "us.pool.ntp.org" #define NTP1 "time.nist.gov" #define TZ "Asia/Dubai" char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; //year, month, date, hour, min, sec and week-day(starts from 0 and goes to 6) //writing any non-existent time-data may interfere with normal operation of the RTC. //Take care of week-day also. //DateTime dt(2011, 11, 10, 15, 18, 0, 5); //uint32_t ts = 1510592825; // 1510592825 = Monday 13 November 2017 17:07:05 UTC //const int SW4 = 4; ESP8266WebServer httpServer(80); ESP8266HTTPUpdateServer httpUpdater; WiFiClient client; // A UDP instance to let us send and receive packets over UDP //WiFiUDP Udp; //-------------------------------------------------- //timeval cbtime; // time set in callback //bool cbtime_set = false; int DOW, MONTH, DATE, YEAR, HOUR, MINUTE, SECOND; String SMonth, SDay, SYear, SHour, SMin, SSec; char strftime_buf[64]; String dtStamp(strftime_buf); String lastUpdate; int lc = 0; time_t tnow = 0; float temp(NAN), hum(NAN), pres(NAN), millibars, fahrenheit, RHx, T, heat_index, dew, dew_point, atm; float HeatIndex, DewPoint, temperature, humidity, TempUnit_Fahrenheit; int count = 0; int error = 0; BME280I2C bme; // Default : forced mode, standby time = 1000 ms // Oversampling = pressure ×1, temperature ×1, humidity ×1, filter off, //#define BME_ADDRESS 0x76 // Note Adafruit module I2C adress is 0x77 my module (eBay) uses 0x76 unsigned long delayTime; //#define SEALEVELPRESSURE_HPA (1013.25) // Average millbars at Sea Level. Check local weather service office. bool AcquisitionDone = false; int started; //Used to tell if Server has started //use I2Cscanner to find LCD display address, in this case 3F //https://github.com/todbot/arduino-i2c-scanner/ //LiquidCrystal_I2C lcd(0x3F,16,2); // set the LCD address to 0x3F for a 16 chars and 2 line display //#define sonalert 9 // pin for Piezo buzzer //#define online D5 //pin for online LED indicator #define BUFSIZE 64 //Size of read buffer for file download -optimized for CC3000. float currentPressure; //Present pressure reading used to find pressure change difference. float pastPressure; //Previous pressure reading used to find pressure change difference. float milliBars; //Barometric pressure in millibars float difference; //change in barometric pressure drop; greater than .020 inches of mercury. //long int id = 1; //Increments record number char *filename; char str[] = {0}; String fileRead; char MyBuffer[13]; char buf[1024]; String publicIP = "10.0.0.201"; //in-place of xxx.xxx.xxx.xxx put your Public IP address inside quotes #define LISTEN_PORT 8020 // in-place of yyyy put your listening port number // The HTTP protocol uses port 80 by default. #define MAX_ACTION 10 // Maximum length of the HTTP action that can be parsed. #define MAX_PATH 64 // Maximum length of the HTTP request path that can be parsed. // There isn't much memory available so keep this short! #define BUFFER_SIZE MAX_ACTION + MAX_PATH + 20 // Size of buffer for incoming request data. // Since only the first line is parsed this // needs to be as large as the maximum action // and path plus a little for whitespace and // HTTP version. #define TIMEOUT_MS 500 // Amount of time in milliseconds to wait for /////////default 500///// // an incoming request to finish. Don't set this // too high or your server could be slow to respond. uint8_t buffer[BUFFER_SIZE + 1]; int bufindex = 0; char action[MAX_ACTION + 1]; char path[MAX_PATH + 1]; ////////////////////////// // Web Server on port LISTEN_PORT ///////////////////////// WiFiServer server(LISTEN_PORT); /* This is the ThingSpeak channel number for the MathwWorks weather station https://thingspeak.com/channels/YourChannelNumber. It senses a number of things and puts them in the eight field of the channel: Field 1 - Temperature (Degrees C ) Field 2 - Humidity (%RH) Field 3 - Barometric Pressure (hpa) Field 4 - Rain Last 5 Minutes (mm) */ //edit ThingSpeak.com data here... //unsigned long myChannelNumber = yourchannelnumber; //const char * myWriteAPIKey = "yourwriteapikey"; //Hardware pin definitions //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= // digital I/O pins const byte RAIN = D5; ///D5 on NODEMCU For Rain Collector ***************************************** May need to change to a different pin! ************************** //Global Variables //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= long lastMSecond = 0; //The millis counter to see when a second rolls by long loopMSecond = 0; //time it took to loop once in millis long loopMSecond_Rem = 0; //Remining millis of Second calcultion. int seconds = 0; //When it hits 60, increase the current minute byte loop_seconds = 0; byte last_10_seconds = 0; byte ten_sec_count = 0; byte ten_second_5m = 0; //Keeps track of the "wind speed/dir avg" over last 5 minutes array of data int minutes = 0; //Keeps track of where we are in various arrays of data byte minutes_5m = 0; //Keeps track of where we are in rain5min over last 5 minutes array of data int hours = 0; byte last_hour = 0; float gpslng = 0.0, gpslat = 0.0, gpsalt = 0.0; int gpssat = 0; //Rain over the past hour (store 1 per minute) //Total rain over date (store one per day) volatile float rainHour = 0.0; //60 floating numbers to keep track of 60 minutes of rain volatile float rainDay = 0.0; //24 floating numbers to keep track of 24 hours of rain volatile float rain5min = 0.0; //5 floating numbers to keep track of 5 minutes of rain //float batt_lvl = 11.8; //[analog value from 0 to 1023] //#define DHTPIN 4 // what digital pin we're connected to //#define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 //DHT dht(DHTPIN, DHTTYPE); //float h = dht.readHumidity(); //float t = dht.readTemperature(); //Rain time stamp int Rainindi=0; //Variables used for GPS //unsigned long age; int gps_year, gps_month, gps_day; int seconds_new, minutes_new, hours_new, gps_year_new, gps_month_new, gps_day_new; //Calibrate rain bucket here //Rectangle raingauge from Sparkfun.com weather sensors float rain_bucket_mm = 0.011*25.4;//Each dump is 0.011" of water //DAVISNET Rain Collector 2 //float rain_bucket_mm = 0.01*25.4;//Each dump is 0.01" of water // volatiles are subject to modification by IRQs volatile unsigned long raintime, rainlast, raininterval, rain, Rainindtime, Rainindlast; // For Rain int addr=0; String eepromstring = "0.00"; //for loop int i; //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= //Interrupt routines (these are called by the hardware interrupts, not by the main code) //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= int magnet; //define interrupt_handler ISR void ISR(void) { magnet = 1; } void rainCounter() // Count rain gauge bucket tips as they occur // Activated by the magnet and reed switch in the rain gauge, attached to input D2 { raintime = millis(); // grab current time raininterval = raintime - rainlast; // calculate interval between this and last event if (raininterval > 100) // ignore switch-bounce glitches less than 10mS after initial edge { rainDay += rain_bucket_mm; rainHour += rain_bucket_mm; //Increase this minute's amount of rain rain5min += rain_bucket_mm; // increase this 5 mnts amout of rain rainlast = raintime; // set up for next event Serial.print(F("RainIRQ! ")); Serial.print(F("Rain(5m) : ")); Serial.println(rain5min); Serial.print(F("RainHour) : ")); Serial.println(rainHour); Serial.print(F("RainDay) : ")); Serial.println(rainDay); //STORE RAINCOUNT IN EEPROM Serial.println("SET EEPROM"); eepromstring = String(rainDay,2); eepromSet("rainDay", eepromstring); eepromstring = String(rainHour,2); eepromSet("rainHour", eepromstring); eepromstring = String(rain5min,2); eepromSet("rain5min", eepromstring); //END - STORE RAINCOUNT IN EEPROM } } //Funtions that need declared before setup bool doFTP(); void eepromDelete(); void eepromSet(); void fileStore(); void FTP_UPLOAD(); String getDateTime(); void listen(); void logtoSD(); void parseFirstLine(); void parseRequest(); void printGPS(); void readFile(); void RTC_UPDATE(); void smartDelay(); void speak(); float updateDifference(); void webInterface(); void wifiStart(); //////////////////////////////////////////////////////////////////////////////////////////////////////////////// void setup(void) { Serial.begin(115200); swSer.begin (GPSBaud); if (gps.charsProcessed() < 10) { Serial.println(F("No GPS detected: check wiring.")); } while(!Serial) {} Serial.print("Sentences that failed checksum = "); Serial.println(gps.failedChecksum()); wifiStart(); //Serial.println(TinyGPSPlus::libraryVersion()); pinMode(RAIN, INPUT_PULLUP); // input from wind meters rain gauge sensor attachInterrupt(digitalPinToInterrupt(RAIN), ISR, FALLING); //pinMode(REFERENCE_3V3, INPUT); //turn on interrupts interrupts(); EEPROM.begin(512); // pinMode(online, OUTPUT); //Set pinMode to OUTPUT for online LED pinMode(4, INPUT_PULLUP); //Set input (SDA) pull-up resistor on GPIO_0 // Change this *! if you don't use a Wemos Wire.setClock(2000000); Wire.begin(4,5); //Wire.begin(0, 2); configTime(4 * 3600, 0, NTP0, NTP1); setenv("TZ", "Asia/Dubai", 3); // this sets TZ to Indianapolis, Indiana tzset(); /***************************************************************************** Serial.println("Initialize DS3231"); Clock.begin(); Clock.enableOutput(false); //Unsupported by DS3231.h library //tnow = time(nullptr) + 1; // Disarm alarms and clear alarms for this example, because alarms is battery backed. // Under normal conditions, the settings should be reset after power and restart microcontroller. Clock.armAlarm1(false); Clock.armAlarm2(false); Clock.clearAlarm1(); Clock.clearAlarm2(); while(!bme.begin()) { Serial.println("Could not find BME280 sensor!"); delay(1000); } *********************************************************************/ //digitalWrite(led15, 0); //pinMode(led15, OUTPUT); //pinMode(SW4, INPUT_PULLUP); getDateTime(); Serial.println("Day of the Week: " + (String)DOW); //day of the week Sunday = 0 ---> Saturday = 6 Serial.print(dtStamp + "\n"); SPIFFS.begin(); //SPIFFS.format(); //SPIFFS.remove("/SERVER.TXT"); //SPIFFS.remove("/WIFI.TXT"); //SPIFFS.remove("/LOG421.TXT"); //SPIFFS.rename("/LOG715 TXT", "/LOG715.TXT"); //lcdDisplay(); // LCD 1602 Display function --used for inital display ThingSpeak.begin(client); //WiFi.disconnect(); //For testing wifiStart function in setup and listen functions. minutes_5m = (MINUTE)%5; /////Should this be % 12? lastMSecond = millis(); printGPS(); gpslat = gps.location.lat(); gpslng = gps.location.lng(); gpsalt = gps.altitude.feet(); Serial.println(" *** Ready *** "); } // How big our line buffer should be. 100 is plenty! #define BUFFER 100 //////////////////////////////////////////////////////////////////////////////////////////////////// void loop() { wdt_reset(); listen(); int flag; if(WiFi.status() != WL_CONNECTED) { wifiStart(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); //Open a "WIFI.TXT" for appended writing. Client access ip address logged. File logFile = SPIFFS.open("/WIFI.TXT", "a"); if (!logFile) { Serial.println("File failed to open"); } else { logFile.print("Connected WiFi: "); logFile.println(dtStamp); } } while( magnet == 1 ) { /* Wait for the ISR to set the * flag; reset it before * taking any action. */ if (magnet) { if ((MINUTE % 15 == 0) && (SECOND == 0)) { listen(); } else { magnet = 0; rainCounter(); } } } getDateTime(); //added 11/14/2018 William --needed to evaluate if statements //Resets every 5 Minutes and 11 Seconds. if ((MINUTE % 12 == 0) && (SECOND == 20)) //Reset rain5min variable every 5 MINUTES 11 SECOND. { if (flag == 0) { rainHour = 0; //STORE RAINCOUNT IN EEPROM Serial.println("SET EEPROM"); eepromstring = String(rainHour,2); eepromSet("rainHour", eepromstring); //END - STORE RAINCOUNT IN EEPROM //RTC_UPDATE(); rainDay = 0; //STORE RAINCOUNT IN EEPROM Serial.println("SET EEPROM"); eepromstring = String(rainDay,2); eepromSet("rainDay",eepromString); //END - STORE RAINCOUNT IN EEPROM } flag = 1; listen(); } if ((MINUTE % 15 == 0) && (SECOND == 40)) //Write Data to "LOG.TXT" every 15 MINUTES. { if (flag == 1) { fileStore(); FTP_UPLOAD(); delay(100); rain5min = 0; //STORE RAINCOUNT IN EEPROM Serial.println("SET EEPROM"); eepromstring = String(rain5min,2); eepromSet("rain5min", eepromstring); //END - STORE RAINCOUNT IN EEPROM //pastPressure = currentPressure; RTC_UPDATE(); //printGPS(); } flag = 0; listen(); } wifi_set_sleep_type(NONE_SLEEP_T); delay(100); if (started == 1) { // Open a "log.txt" for appended writing File log = SPIFFS.open("/SERVER.TXT", "a"); if (!log) { Serial.println("file open failed"); } log.print("Started Server: "); log.println(dtStamp) + " "; log.close(); } started = 0; //only time started = 1 is when Server starts in setup smartDelay(50); gpslat = gps.location.lat(); gpslng = gps.location.lng(); gpsalt = gps.altitude.feet(); flag = 1; //done with the flag; set flag to 1. listen(); } ///////////////// void accessLog() { getDateTime(); String ip1String = "192.168.0.130"; //Host ip address String ip2String = client.remoteIP().toString(); //client remote IP address //Open a "access.txt" for appended writing. Client access ip address logged. File logFile = SPIFFS.open("/ACCESS.TXT", "a"); if (!logFile) { Serial.println("File failed to open"); } if ((ip1String == ip2String) || (ip2String == "0.0.0.0")) { //Serial.println("IP Address match"); logFile.close(); } else { //Serial.println("IP address that do not match ->log client ip address"); logFile.print("Accessed: "); logFile.print(dtStamp + " -- "); logFile.print("Client IP: "); logFile.print(client.remoteIP()); logFile.print(" -- "); logFile.print("Action: "); logFile.print(action); logFile.print(" -- "); logFile.print("Path: "); logFile.print(path); //Serial.println("Error = " + (String)error); if ((error == 1) || (error == 2)) { if(error == 1) { Serial.println("Error 404"); logFile.print(" Error 404"); error = 0; } if(error == 2) { Serial.println("Error 405"); logFile.print(" Error 405"); } } error = 0; logFile.println(""); logFile.close(); } } //////////////////////////////// void beep(unsigned char delayms) { // wait for a delayms ms // digitalWrite(sonalert, HIGH); // delay(3000); // digitalWrite(sonalert, LOW); } //---------------------------------------------------------EEPROM---------------------------------------------- void eepromSet(String name, String value) { Serial.println("eepromSet"); String list=eepromDelete(name); String nameValue="&" + name + "=" + value; //Serial.println(list); //Serial.println(nameValue); list+=nameValue; for (int i = 0; i < list.length(); ++i) { EEPROM.write(i,list.charAt(i)); } EEPROM.commit(); Serial.print(name); Serial.print(":"); Serial.println(value); } String eepromDelete(String name) { Serial.println("eepromDelete"); int nameOfValue; String currentName=""; String currentValue=""; int foundIt=0; char letter; String newList=""; for (int i = 0; i < 512; ++i) { letter= char(EEPROM.read(i)); if (letter=='\n') { if (foundIt==1) { } else if (newList.length()>0) { newList+="=" + currentValue; } break; } else if (letter=='&') { nameOfValue=0; currentName=""; if (foundIt==1) { foundIt=0; } else if (newList.length()>0) { newList+="=" + currentValue; } } else if (letter=='=') { if (currentName==name) { foundIt=1; } else { foundIt=0; newList+="&" + currentName; } nameOfValue=1; currentValue=""; } else { if (nameOfValue==0) { currentName+=letter; } else { currentValue+=letter; } } } for (int i = 0; i < 512; ++i) { EEPROM.write(i,'\n'); } EEPROM.commit(); for (int i = 0; i < newList.length(); ++i) { EEPROM.write(i,newList.charAt(i)); } EEPROM.commit(); Serial.println(name); Serial.println(newList); return newList; } void eepromClear() { Serial.println("eepromClear"); for (int i = 0; i < 512; ++i) { EEPROM.write(i,'\n'); } } String eepromList() { Serial.println("eepromList"); char letter; String list=""; for (int i = 0; i < 512; ++i) { letter= char(EEPROM.read(i)); if (letter=='\n') { break; } else { list+=letter; } } Serial.println(list); return list; } String eepromGet(String name) { Serial.println("eepromGet"); int nameOfValue; String currentName=""; String currentValue=""; int foundIt=0; String value=""; char letter; for (int i = 0; i < 512; ++i) { letter= char(EEPROM.read(i)); if (letter=='\n') { if (foundIt==1) { value=currentValue; } break; } else if (letter=='&') { nameOfValue=0; currentName=""; if (foundIt==1) { value=currentValue; break; } } else if (letter=='=') { if (currentName==name) { foundIt=1; } else { nameOfValue=1; currentValue=""; } } else { if (nameOfValue==0) { currentName+=letter; } else { currentValue+=letter; } } } Serial.print(name); Serial.print(":"); Serial.println(value); return value; } ////////// void end() { accessLog(); // Wait a short period to make sure the response had time to send before // the connection is closed . delay(100); //Client flush buffers client.flush(); // Close the connection when done. client.stop(); // digitalWrite(online, LOW); //turn-off online LED indicator getDateTime(); Serial.println("Client closed: " + dtStamp); delay(100); //Delay for changing too quickly to new browser tab. } //////////////// void fileStore() //If 6th day of week, rename "log.txt" to ("log" + month + day + ".txt") and create new, empty "log.txt" { String logname; logname = "/LOG"; logname += DATE; ////logname += Clock.getMonth(Century); logname += MONTH; ///logname += Clock.getDate(); logname += YEAR; logname += ".TXT"; // Open file for appended writing File log = SPIFFS.open(logname.c_str(), "a"); // Open file for appended writing //File log = SPIFFS.open("/LOG.TXT", "a"); if (!log) { Serial.println("file open failed"); } // rename the file "LOG.TXT" /* String logname; logname = "/LOG"; logname += MONTH; ////logname += Clock.getMonth(Century); logname += DATE; ///logname += Clock.getDate(); logname += ".TXT"; SPIFFS.rename("/LOG.TXT", logname.c_str()); log.close(); //For troubleshooting //Serial.println(logname.c_str()); */ } void FTP_UPLOAD() { upload = true; if (doFTP(upload)) Serial.println(F("FTP OK")); else Serial.println(F("FTP FAIL")); // delay(10); // give time to the WiFi handling in the background } #define FTPWRITE boolean debug = true; unsigned long startTime = millis(); // change to your server IPAddress ftserver( 10,0,0,201 ); //WiFiClient client; char outBuf[128]; char outCount; // change fileName to your file (8.3 format!) ////String fileName = logname; //String fpath = logname; // SPIFFS file handle File fh; //format bytes String formatBytes(size_t bytes) { if (bytes < 1024) { return String(bytes) + "B"; } else if (bytes < (1024 * 1024)) { return String(bytes / 1024.0) + "KB"; } else if (bytes < (1024 * 1024 * 1024)) { return String(bytes / 1024.0 / 1024.0) + "MB"; } else { return String(bytes / 1024.0 / 1024.0 / 1024.0) + "GB"; } } //----------------- FTP fail void efail() { byte thisByte = 0; client.println(F("QUIT")); while (!client.available()) delay(1); while (client.available()) { thisByte = client.read(); Serial.write(thisByte); } client.stop(); Serial.println(F("Command disconnected")); //fh.close(); Serial.println(F("SD closed")); } // efail //-------------- FTP receive byte eRcv() { byte respCode; byte thisByte; while (!client.available()) delay(1); respCode = client.peek(); outCount = 0; while (client.available()) { thisByte = client.read(); Serial.write(thisByte); if (outCount < 127) { outBuf[outCount] = thisByte; outCount++; outBuf[outCount] = 0; } } if (respCode >= '4') { efail(); return 0; } return 1; } // eRcv() //--------------- FTP handling byte doFTP(boolean upload) { String logname; logname = "/LOG"; logname += DATE; ////logname += Clock.getMonth(Century); logname += MONTH; ///logname += Clock.getDate(); logname += YEAR; logname += ".TXT"; if (upload) { fh = SPIFFS.open(logname.c_str(), "a+"); } // else // { // SPIFFS.remove(path); // fh = SPIFFS.open(path, "w"); // } if (!fh) { Serial.println(F("SPIFFS open fail")); return 0; } if (upload) { if (!fh.seek((uint32_t)0, SeekSet)) { Serial.println(F("Rewind fail")); //fh.close(); return 0; } } if (debug) Serial.println(F("SPIFFS opened")); if (client.connect(ftserver, 21)) // 21 = FTP server { Serial.println(F("Command connected")); } else { //fh.close(); Serial.println(F("Command connection failed")); return 0; } if (!eRcv()) return 0; if (debug) Serial.println("Send USER"); client.println(F("USER admin")); if (!eRcv()) return 0; if (debug) Serial.println("Send PASSWORD"); client.println(F("PASS admin")); if (!eRcv()) return 0; if (debug) Serial.println("Send SYST"); client.println(F("SYST")); if (!eRcv()) return 0; if (debug) Serial.println("Send Type I"); client.println(F("Type I")); if (!eRcv()) return 0; if (debug) Serial.println("Send PASV"); client.println(F("PASV")); if (!eRcv()) return 0; char *tStr = strtok(outBuf, "(,"); int array_pasv[6]; for ( int i = 0; i < 6; i++) { tStr = strtok(NULL, "(,"); array_pasv[i] = atoi(tStr); if (tStr == NULL) { Serial.println(F("Bad PASV Answer")); } } unsigned int hiPort, loPort; hiPort = array_pasv[4] << 8; loPort = array_pasv[5] & 255; if (debug) Serial.print(F("Data port: ")); hiPort = hiPort | loPort; if (debug) Serial.println(hiPort); if (client.connect(ftserver, hiPort)) { Serial.println(F("Data connected")); } else { Serial.println(F("Data connection failed")); client.stop(); //fh.close(); return 0; } if (upload) { if (debug) Serial.println("Send STOR filename"); client.print(F("STOR ")); client.println(logname.c_str()); } else { if (debug) Serial.println("Send RETR filename"); client.print(F("RETR ")); client.println(logname.c_str()); } if (!eRcv()) { client.stop(); return 0; } if (upload) { if (debug) Serial.println(F("Writing")); // for faster upload increase buffer size to 1460 //#define bufSizeFTP 64 #define bufSizeFTP 1460 uint8_t clientBuf[bufSizeFTP]; //unsigned int clientCount = 0; size_t clientCount = 0; while (fh.available()) { clientBuf[clientCount] = fh.read(); clientCount++; if (clientCount > (bufSizeFTP - 1)) { client.write((const uint8_t *) &clientBuf[0], bufSizeFTP); clientCount = 0; delay(1); } } if (clientCount > 0) client.write((const uint8_t *) &clientBuf[0], clientCount); } else { while (client.connected()) { while (client.available()) { char c = client.read(); fh.write(c); if (debug) Serial.write(c); } } } client.stop(); Serial.println(F("Data disconnected")); if (!eRcv()) return 0; client.println(F("QUIT")); if (!eRcv()) return 0; client.stop(); Serial.println(F("Command disconnected")); //fh.close(); //if (debug) Serial.println(F("SPIFS closed")); return 1; } // doFTP() void getEeprom() { //RESET EEPROM CONTENT - ONLY EXECUTE ONE TIME - AFTER COMMENT /*Serial.println("CLEAR "); eepromClear(); Serial.println("SET "); eepromSet("rain5min", "0.00"); eepromSet("rainDay", "9.00"); eepromSet("rainHour", "0.00"); Serial.println("LIST "); Serial.println(eepromList());*/ //END - RESET EEPROM CONTENT - ONLY EXECUTE ONE TIME - AFTER COMMENT //eepromClear(); //GET STORED RAINCOUNT IN EEPROM Serial.println("GET EEPROM"); eepromstring=eepromGet("rainDay"); rainDay=eepromstring.toFloat(); Serial.print("RAINDAY VALUE FROM EEPROM: "); Serial.println(rainDay); eepromstring=eepromGet("rainHour"); rainHour=eepromstring.toFloat(); Serial.print("RAINHOUR VALUE FROM EEPROM: "); Serial.println(rainHour); eepromstring=eepromGet("rain5min"); rain5min=eepromstring.toFloat(); Serial.print("rain5min VALUE FROM EEPROM: "); Serial.println(rain5min); //END - GET STORED RAINCOUNT IN EEPROM } ////////////////////////////////// //rtc and NTPtime keeping function ////////////////////////////////// String readDateTime() //Read time from Real Time Clock { dt = Clock.getDateTime(); SECOND = dt.second; MINUTE = dt.minute; HOUR = dt.hour; DATE = dt.day; MONTH = dt.month; YEAR = dt.year; DOW = dt.dayOfWeek; int temp; temp = (DATE); if (temp < 10) { SDay = ("0" + (String)temp); } else { SDay = (String)temp; } temp = (MONTH); if (temp < 10) { SMonth = ("0" + (String)temp); } else { SMonth = (String)temp; } SYear = (String)(YEAR); temp = (HOUR); if (temp < 10) { SHour = ("0" + (String)temp); } else { SHour = (String)temp; } temp = (MINUTE); if (temp < 10) { SMin = ("0" + (String)temp); } else { SMin = (String)temp; } temp = (SECOND); if (temp < 10) { SSec = ("0" + (String)temp); } else { SSec = (String)temp; } dtStamp = SDay + '/' + SMonth + '/' + SYear + " , " + SHour + ':' + SMin + ':' + SSec; return (dtStamp); } String getDateTime() //Get time from GPS Time to set RTC { struct tm *ti; tnow = time(nullptr) + 1; ti = localtime(&tnow); DOW = ti->tm_wday; while (swSer.available() > 0) { gps.encode(swSer.read()); SECOND = gps.time.second(); MINUTE = gps.time.minute(); // HOUR = gps.time.hour(); DATE = gps.date.day(); MONTH = gps.date.month(); YEAR = gps.date.year(); } strftime(strftime_buf, sizeof(strftime_buf), "%a , %m/%d/%Y , %H:%M:%S GST", localtime(&tnow)); dtStamp = strftime_buf; return (dtStamp); RTC_UPDATE(); } ///////////////////// void getWeatherData() { BME280::TempUnit tempUnit(BME280::TempUnit_Celsius); BME280::PresUnit presUnit(BME280::PresUnit_hPa); bme.read(pres, temp, hum, tempUnit, presUnit); } ///////////// void listen() // Listen for client connection { if(WiFi.status() != WL_CONNECTED) { wifiStart(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.begin(ssid, password); //Open a "WIFI.TXT" for appended writing. Client access ip address logged. File logFile = SPIFFS.open("/WIFI.TXT", "a"); if (!logFile) { Serial.println("File failed to open"); } else { logFile.print("Connected WiFi: "); logFile.println(dtStamp); } } getDateTime(); if ((MINUTE % 15 == 0) && (SECOND == 0)) //Write Data to "LOG.TXT" every 15 MINUTES. { getEeprom(); getWeatherData(); lastUpdate = dtStamp; //store dtstamp for use on dynamic web page updateDifference(); //Get Barometric Pressure difference logtoSD(); //Output to SPIFFS --Log to SPIFFS on 15 minute interval. delay(10); //Be sure there is enough SPIFFS write time webInterface(); speak(); } // Check if a client has connected WiFiClient client = server.available(); if (client) { // Process this request until it completes or times out. // Note that this is explicitly limited to handling one request at a time! // Clear the incoming data buffer and point to the beginning of it. bufindex = 0; memset(&buffer, 0, sizeof(buffer)); // Clear action and path strings. memset(&action, 0, sizeof(action)); memset(&path, 0, sizeof(path)); // Set a timeout for reading all the incoming data. unsigned long endtime = millis() + TIMEOUT_MS; // Read all the incoming data until it can be parsed or the timeout expires. bool parsed = false; while (!parsed && (millis() < endtime) && (bufindex < BUFFER_SIZE)) { if (client.available()) { buffer[bufindex++] = client.read(); } parsed = parseRequest(buffer, bufindex, action, path); } if(parsed) { error = 0; // Check the action to see if it was a GET request. if (strcmp(action, "GET") == 0) { //digitalWrite(online,HIGH); //turn on online LED indicator String ip1String = "192.168.0.130"; //Host ip address //String ip1String = "172.18.0.124"; //Host ip address String ip2String = client.remoteIP().toString(); //client remote IP address Serial.print("\n"); Serial.println("Client connected: " + dtStamp); Serial.print("Client IP: "); Serial.println(ip2String); Serial.println(F("Processing request")); Serial.print(F("Action: ")); Serial.println(action); Serial.print(F("Path: ")); Serial.println(path); //accessLog(); // Check the action to see if it was a GET request. if (strncmp(path, "/favicon.ico", 12) == 0) // Respond with the path that was accessed. { char *filename = "/FAVICON.ICO"; strcpy(MyBuffer, filename); Serial.println(filename); // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: image/x-icon"); client.println(); error = 0; readFile(); } // Check the action to see if it was a GET request. if ((strcmp(path, "/Weather") == 0) || (strcmp(path, "/") == 0)) // Respond with the path that was accessed. { getWeatherData(); if(!(isnan(dew))) { delay(200); // First send the success response code. client.println("HTTP/1.1 200 OK"); client.println("Content-Type: html"); client.println("Connnection: close"); client.println("Server: Robotdyn WiFi D1 R2"); // Send an empty line to signal start of body. client.println(""); // Now send the response data. // output dynamic webpage client.println(""); client.println(""); client.println("Weather Observations"); client.println(""); // add a meta refresh tag, so the browser pulls again every 15 seconds: //client.println(""); client.println("

Rain Station
"); client.println("Abu Dhabi Test


"); if(lastUpdate != NULL) { client.println("Last Update: "); client.println(lastUpdate); client.println("
"); } client.println("Latitude : " ); client.print(gpslat,5); client.print("
"); client.println("Longitude : " ); client.print(gpslng,5); client.print("
"); client.println("Elevation"); client.print(gpsalt,0); client.print(" Feet.
"); client.println("Temperature: "); client.print(temp, 1); client.print(" C.
"); client.println("Humidity: "); client.print(hum, 1); client.print(" %
"); //client.println("Dew point: "); //client.print(DewPoint, 1); //client.print(" F.
"); //client.println("Heat Index: "); //client.print(HeatIndex, 1); //client.print(" F.
"); client.println("Barometric Pressure: "); client.print(pres, 1); //Inches of Mercury client.print(" hpa.
"); client.println("Rain Day : "); client.print(rainDay, 1); //Inches of Mercury client.print(" Day/mm
"); /* if (pastPressure == currentPressure) { client.println(0.000); client.print(" inHg --Difference since last update
"); } else { client.println(difference, 3); client.print(" inHg --Difference since last update
"); } */ client.println("Rain Hour: "); client.println(rainHour, 1); //Convert hPA to millbars client.println(" Hour/mm
"); client.println("Rain5min : "); client.print(rain5min, 1); client.print(" 5min/mm
"); //client.println("Elevation: 824 Feet
"); client.println("

Weather Observations

"); client.println("

" + dtStamp + "


"); client.println("
"); client.println("Current Week Observations
"); client.println("
"); client.println("File Browser
"); client.println("
"); client.println("Graphed Weather Observations
"); client.println("
"); client.println("Server: README
"); client.println("
"); //Show IP Adress on client screen client.print("Client IP: "); client.print(client.remoteIP().toString().c_str()); client.println(""); client.println(""); end(); } else { // First send the success response code. client.println("HTTP/1.1 200 OK"); client.println("Content-Type: html"); client.println("Connnection: close"); client.println("Server: Robotdyn WiFi D1 R2"); // Send an empty line to signal start of body. client.println(""); // Now send the response data. // output dynamic webpage client.println(""); client.println(""); client.println("Weather Observations"); client.println(""); // add a meta refresh tag, so the browser pulls again every 15 seconds: //client.println(""); client.println("

Rain Station
"); client.println("Test/h2>
"); if(lastUpdate != NULL) { //client.println("Last Update: "); client.println(lastUpdate); client.println("
"); } client.println("

Invalid Data --Sensor Failure"); client.println("Current Week Observations
"); client.println("
"); client.println("File Browser
"); client.println("
"); client.println("Graphed Weather Observations
"); client.println("
"); client.println("Server: README
"); client.println("
"); //Show IP Adress on client screen client.print("Client IP: "); client.print(client.remoteIP().toString().c_str()); client.println(""); client.println(""); end(); } } // Check the action to see if it was a GET request. else if (strcmp(path, "/SdBrowse") == 0) // Respond with the path that was accessed. { // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/html"); client.println(); client.println(""); client.println(""); client.println(""); client.println("SDBrowse"); // print all the files, use a helper to keep it clean client.println("

Collected Observations

"); //////////////// Code to listFiles from martinayotte of the "ESP8266 Community Forum" /////////////// String str = String(""); if (!SPIFFS.begin()) { Serial.println("SPIFFS failed to mount !"); } Dir dir = SPIFFS.openDir("/"); while (dir.next()) { str += ""; str += dir.fileName(); str += ""; str += " "; str += dir.fileSize(); str += "
\r\n"; } str += "\r\n"; client.print(str); ////////////////// End code by martinayotte ////////////////////////////////////////////////////// client.println("

"); client.println("Current Observations
"); client.println(""); client.println(""); end(); } // Check the action to see if it was a GET request. else if (strcmp(path, "/Graphs") == 0) // Respond with the path that was accessed. { //delayTime =1000; // First send the success response code. client.println("HTTP/1.1 200 OK"); client.println("Content-Type: html"); client.println("Connnection: close"); client.println("Server: Robotdyn D1 R2"); // Send an empty line to signal start of body. client.println(""); // Now send the response data. // output dynamic webpage client.println(""); client.println(""); client.println(""); client.println("Graphed Weather Observations"); // add a meta refresh tag, so the browser pulls again every 15 seconds: //client.println(""); client.println("
"); client.println("

Graphed Weather Observations


"); client.println("

"); client.println(""); client.println(""); client.println(""); client.println("
"); client.println("
"); delay(200); //client.println(""); //client.println(""); client.println(""); client.println(""); client.println(""); client.println("

"); client.println("Current Observations
"); client.println("
"); client.println("

"); client.println(""); client.println(""); end(); } else if ((strncmp(path, "/LOG", 4) == 0) || (strcmp(path, "/WIFI.TXT") == 0) || (strcmp(path, "/DIFFER.TXT") == 0) || (strcmp(path, "/SERVER.TXT") == 0) || (strcmp(path, "/README.TXT") == 0)) // Respond with the path that was accessed. { char *filename; char name; strcpy( MyBuffer, path ); filename = &MyBuffer[1]; if ((strncmp(path, "/SYSTEM~1", 9) == 0) || (strncmp(path, "/ACCESS", 7) == 0)) { client.println("HTTP/1.1 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("

404

"); delay(250); client.println("

File Not Found!

"); client.println("

"); client.println("Return to File Browser
"); Serial.println("Http 404 issued"); error = 1; end(); } else { client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/plain"); client.println("Content-Disposition: attachment"); client.println("Content-Length:"); client.println("Connnection: close"); client.println(); readFile(); end(); } } // Check the action to see if it was a GET request. else if(strncmp(path, "/zzzzz.zzz", 7) == 0) //replace "/zzzzzzz" with your choice. Makes "ACCESS.TXT" a restricted file. Use this for private access to remote IP file. { //Restricted file: "ACCESS.TXT." Attempted access from "Server Files:" results in //404 File not Found! char *filename = "/ACCESS.TXT"; strcpy(MyBuffer, filename); // send a standard http response header client.println("HTTP/1.1 200 OK"); client.println("Content-Type: text/plain"); client.println("Content-Disposition: attachment"); //client.println("Content-Length:"); client.println(); readFile(); end(); } else { delay(1000); // everything else is a 404 client.println("HTTP 404 Not Found"); client.println("Content-Type: text/html"); client.println(); client.println("

404

"); delay(250); client.println("

File Not Found!

"); client.println("

"); client.println("Return to File Browser
"); Serial.println("Http 404 issued"); error = 1; end(); } } else { // Unsupported action, respond with an HTTP 405 method not allowed error. Serial.print(action); client.println("HTTP Method Not Allowed"); client.println(""); Serial.println(""); Serial.println("Http 405 issued"); Serial.println(""); //digitalWrite(online, HIGH); //turn-on online LED indicator error = 2; end(); } accessLog(); } } } //******************************************************************** ////////////////////////////////////////////////////////////////////// // Return true if the buffer contains an HTTP request. Also returns the request // path and action strings if the request was parsed. This does not attempt to // parse any HTTP headers because there really isn't enough memory to process // them all. // HTTP request looks like: // [method] [path] [version] \r\n // Header_key_1: Header_value_1 \r\n // ... // Header_key_n: Header_value_n \r\n // \r\n bool parseRequest(uint8_t* buf, int bufSize, char* action, char* path) { // Check if the request ends with \r\n to signal end of first line. if (bufSize < 2) return false; if (buf[bufSize - 2] == '\r' && buf[bufSize - 1] == '\n') { parseFirstLine((char*)buf, action, path); return true; } return false; } /////////////////////////////////////////////////////////////////// // Parse the action and path from the first line of an HTTP request. void parseFirstLine(char* line, char* action, char* path) { // Parse first word up to whitespace as action. char* lineaction = strtok(line, " "); if (lineaction != NULL) strncpy(action, lineaction, MAX_ACTION); // Parse second word up to whitespace as path. char* linepath = strtok(NULL, " "); if (linepath != NULL) strncpy(path, linepath, MAX_PATH); } void logtoSD() //Output to SPIFFS Card every fifthteen minutes { String logname; logname = "/LOG"; logname += DATE; ////logname += Clock.getMonth(Century); logname += MONTH; ///logname += Clock.getDate(); logname += YEAR; logname += ".TXT"; // Open a "log.txt" for appended writing File log = SPIFFS.open(logname.c_str(), "a"); // Open a "log.txt" for appended writing // File log = SPIFFS.open("/LOG.TXT", "a"); if (!log) { Serial.println("file open failed"); } //log.print(id); //log.print(" , "); log.print("Latitude : "); log.print(gpslat, 5); log.print(" , "); log.print("Longitude : "); log.print(gpslng, 5); log.print(" , "); log.print(lastUpdate); log.print(" , "); log.print("Humidity: "); log.print(hum, 1); log.print(" % , "); log.print("Temperature: "); log.print(temp, 1); log.print(" C. , "); log.print("Pressure: "); log.print(pres, 1); log.print(" hpa. "); log.print(" , "); log.print(" RainDay "); log.print(rainDay, 1); log.print(" ,"); log.print(" RainHour "); log.print(rainHour, 1); log.print(" , "); log.print(" Rain5min "); log.print(rain5min, 1); log.print(" mm. "); log.print(" , "); log.print("Elevation: "); log.print(gpsalt, 0); log.print(" feet. "); log.println(); //Increment Record ID number //id++; Serial.print("\n"); //Serial.println("Data written to 'LOG.TXT' " + dtStamp); Serial.println("Data written to " + logname + dtStamp); Serial.print("\n"); log.close(); } ///////////// void newDay() //Collect Data for twenty-four hours; then start a new day { //Do file maintence on 1st day of week at appointed time from RTC. Assign new name to "log.txt." Create new "log.txt." //if ((DOW) == 6) // if ((DOW) == 0) // { // fileStore(); // } //id = 1; //Reset id for start of new day //Write log Header // Open file for appended writing // File log = SPIFFS.open("/LOG.TXT", "a"); // if (!log) // { // Serial.println("file open failed"); // } // else // { // delay(1000); // log.println("......"); //Just a leading blank line, in case there was previous data // log.println("Date, Time, Humidity, Dew Point, Temperature, Heat Index, in. Hg., Difference, millibars, Atm, Elevation"); // log.close(); // Serial.println("......"); // Serial.println("Date, Time, Humidity, Dew Point, Temperature, Heat Index, in. Hg., Difference, millibars, Atm, Elevation"); // Serial.println(""); // } // Serial.println("\n"); } void printGPS() { smartDelay(500); // Run Procedure smartDelay if (millis() > 5000 && gps.charsProcessed() < 10) { Serial.println(F("No GPS data received: check wiring")); Serial.println(""); } } static void smartDelay(unsigned long ms) // This custom version of delay() ensures that the gps object is being "fed". { unsigned long start = millis(); do { while (swSer.available()) gps.encode(swSer.read()); } while (millis() - start < ms); } /////////////// void readFile() { //digitalWrite(online, HIGH); //turn-on online LED indicator String filename = (const char *)&MyBuffer; File webFile = SPIFFS.open(filename, "r"); if (!webFile) { Serial.println("File failed to open"); Serial.println("\n"); } else { int siz = webFile.size(); //.setContentLength(str.length() + siz); //webserver.send(200, "text/plain", str); while (siz > 0) { size_t len = std::min((int)(sizeof(buf) - 1), siz); webFile.read((uint8_t *)buf, len); client.write((const char*)buf, len); siz -= len; } webFile.close(); } error = 0; delayTime = 1000; MyBuffer[0] = '\0'; //digitalWrite(online, LOW); //turn-off online LED indicator listen(); } void RTC_UPDATE() { time_t tnow = time(nullptr)+1; Serial.println((uint32_t)tnow); //Clock.setDateTime(1397408400); if (time(nullptr) > 100000ul) { Clock.setDateTime((uint32_t)tnow); Serial.println("RTC updated"); Serial.println("."); delay(10); } delay(100); Serial.println(dtStamp + "\n"); listen(); } //////////// void speak() { char t_buffered1[14]; dtostrf(temp, 7, 1, t_buffered1); char t_buffered2[14]; dtostrf(hum, 7, 1, t_buffered2); char t_buffered3[14]; dtostrf(pres, 7, 1, t_buffered3); char t_buffered4[14]; dtostrf(rain5min, 7, 1, t_buffered4); // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different // pieces of information in a channel. Here, we write to field 1. // Write to ThingSpeak. There are up to 8 fields in a channel, allowing you to store up to 8 different // pieces of information in a channel. Here, we write to field 1. ThingSpeak.setField(1, t_buffered1); //Temperature ThingSpeak.setField(2, t_buffered2); //Humidity ThingSpeak.setField(3, t_buffered3); //Barometric Pressure ThingSpeak.setField(4, t_buffered4); //Dew Point F. // Write the fields that you've set all at once. //ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey); getDateTime(); Serial.println(""); Serial.println("Sent data to Thingspeak.com " + dtStamp + "\n"); listen(); } //////////////////////// float updateDifference() //Pressure difference for fifthteen minute interval { //Function to find difference in Barometric Pressure //First loop pass pastPressure and currentPressure are equal resulting in an incorrect difference result. //Future loop passes difference results are correct Serial.println("currentPressure: " + (String)currentPressure); difference = currentPressure - pastPressure; //This will be pressure from this pass thru loop, pressure1 will be new pressure reading next loop pass if (difference == currentPressure) { difference = 0; } return (difference); //Barometric pressure change in inches of Mecury } /////////////////// void webInterface() { char fahren[9];// Buffer big enough for 9-character float dtostrf(temp, 6, 1, fahren); // Leave room for too large numbers! char heat[9]; // Buffer big enough for 9-character float dtostrf(hum, 6, 1, heat); // Leave room for too large numbers! char humd[9]; // Buffer big enough for 9-character float dtostrf(pres, 6, 1, humd); // Leave room for too large numbers! char dewpt[9]; // Buffer big enough for 9-character float dtostrf(rain5min, 6, 1, dewpt); // Leave room for too large numbers! char cpressure[9]; // Buffer big enough for 9-character float dtostrf(currentPressure, 6, 3, cpressure); // Leave room for too large numbers! char gpslng[9]; // Buffer big enough for 9-character float dtostrf(millibars, 6, 2, gpslng); // Leave room for too large numbers! String data = "fahren=" + (String)fahren + "&heat=" + heat + "&humd=" + humd + "&dewpt=" + dewpt + "&cpressure=" + cpressure + "&gpslng=" + gpslng + "&last=" + lastUpdate; if(WiFi.status()== WL_CONNECTED) { //Check WiFi connection status HTTPClient http; //Declare object of class HTTPClient //http.begin("http://ncmrain.000webhostapp.com/dataCollector.php"); //Specify request destination --need to change url to yours http.addHeader("Content-Type", "application/x-www-form-urlencoded"); //Specify content-type header int httpCode = http.POST(data); //Send the request String payload = http.getString(); //Get the response payload if(httpCode == 200) { Serial.print(""); Serial.print("HttpCode: "); Serial.print(httpCode); //Print HTTP return code Serial.print(" Data echoed back from Hosted website " ); Serial.println(""); Serial.println(payload); //Print payload response http.end(); //Close HTTPClient http } else { Serial.print(""); Serial.print("HttpCode: "); Serial.print(httpCode); //Print HTTP return code Serial.print(" Domain website data update failed. "); Serial.println(""); http.end(); //Close HTTPClient http } end(); } else { Serial.println("Error in WiFi connection"); end(); } } void wifiReconnect() { while (WiFi.status() != WL_CONNECTED) { WiFi.begin(ssid, password); } } void wifiStart() { WiFi.disconnect(); WiFi.mode(WIFI_STA); //wifi_set_sleep_type(NONE_SLEEP_T); Serial.println(); Serial.print("MAC: "); Serial.println(WiFi.macAddress()); // We start by connecting to a WiFi network Serial.print("Connecting to "); Serial.println(ssid); //setting the addresses IPAddress ip(10,0,0,201); IPAddress gateway(10,0,0,1); IPAddress subnet(255, 255, 255, 0); IPAddress dns(10,0,0,1); WiFi.begin(ssid, password); WiFi.config(ip, gateway, subnet, dns); WiFi.waitForConnectResult(); Serial.printf("Connection result: %d\n", WiFi.waitForConnectResult()); // Starting the web server server.begin(); Serial.println("Web server running. Waiting for the ESP IP..."); delay(500); started = 1; //Server started // Printing the ESP IP address Serial.print("Server IP: "); Serial.println(WiFi.localIP()); Serial.print("Port: "); Serial.print(LISTEN_PORT); Serial.println("\n"); Serial.println("---------------------"); Serial.println(""); Serial.println(WiFi_hostname); //Udp.begin(localPort); //Serial.printf("UDP at IP %s, UDP port %d\n", WiFi.localIP().toString().c_str(), localPort); Serial.println("---------------------"); // Set up mDNS responder: // - first argument is the domain name, in this example domain name is "esp8266.local", // - second argument is the IP address to advertise if (!MDNS.begin(WiFi_hostname)) { Serial.println("Error setting up MDNS responder!"); while (1) { delay(1000); } } Serial.println("mDNS responder started"); // MDNS.begin(host); httpUpdater.setup(&httpServer); httpServer.begin(); MDNS.addService("http", "tcp", 80); Serial.printf("HTTPUpdateServer ready! Open http://%s.local/update in your browser\n", WiFi_hostname); MDNS.addService("esp", "udp", 8266); Serial.println("ESP UDP service added on port 8266"); Serial.println(""); }