///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// "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("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("");
}