 #include <ESP8266mDNS.h>        // Required for OTA
 #include <WiFiUdp.h>            // Required for OTA
 #include <ArduinoOTA.h>         // Required for OTA
-#include <BlynkSimpleEsp8266.h> // 6/22/16 Rev: Includes edit of this file to expand virtual pins
+#include <BlynkSimpleEsp8266.h>
 #include <TimeLib.h>            // Used by WidgetRTC.h
 #include <WidgetRTC.h>          // Blynk's RTC
-
 #include <OneWire.h>            // Temperature sensor library
 #include <DallasTemperature.h>  // Temperature sensor library
-#define ONE_WIRE_BUS 12         // WeMos pin D6
+#define ONE_WIRE_BUS 12         // WeMos pin D6. RA/SA temp sensor array.
 OneWire oneWire(ONE_WIRE_BUS);
 DallasTemperature sensors(&oneWire);
 


char auth[] = "fromBlynkApp";
char ssid[] = "ssid";
char pass[] = "pw";

char myEmail[] = "email";

char* hostSF = "192.168.0.168";
char* streamId   = "publicKey";
char* privateKey = "privateKey";

SimpleTimer timer;

WidgetRTC rtc;
WidgetTerminal terminal(V26);

const int blowerPin = 13;  // WeMos pin D7.
const int fanPin = 14;     // Future fan only pin.
bool daySet = FALSE;       // Sets the day once after reset and RTC is set correctly.

bool runOnce = TRUE;
bool resetFlag = TRUE;        // TRUE when the hardware has been reset.
bool startFlag = FALSE;       // TRUE when the A/C has started.
bool stopFlag = FALSE;        // TRUE when the A/C has stopped.
bool sensorFailFlag = FALSE;  // TRUE when RA or SA temp sensor are returning bad values.

int offHour, offHour24,  // All used to send an HVAC run status string to Blynk's app.
    onHour, onHour24, offMinute, onMinute, offMonth, onMonth, offDay, onDay;

int tempSplit;                    // Difference between return and supply air.
const int tempSplitSetpoint = 20; // Split lower than this value will send alarm notification.
int alarmFor = 0;                 // Provides "latching" for high split alarm counting & functionality. 0 is normal. 1 is prealarm. 5 is alarmed and lockout.
const int splitAlarmTime = 180;   // If a high split persists for this duration (in seconds), notification is sent.
int alarmTime;                    // Seconds that high split alarm has been active.

long todaysAccumRuntimeSec;           // Today's accumulated runtime in seconds - displayed in app as minutes.
int currentCycleSec, currentCycleMin; // If HVAC is running, the duration of the current cycle (non-accumulating).
int yesterdayRuntime;                 // Sum of yesterday's runtime in minutes - displays in app.
int hvacTodaysStartCount;             // Records how many times the unit has started today.
int todaysDate;                       // Sets today's date related to things that reset at EOD.
String currentTimeDate;               // Time formatted as "0:00AM on 0/0"
String startTimeDate, stopTimeDate, resetTimeDate;
int runStatus;                        // Used for graphing. 40 == running. NULL == off.
String currentStatus;                 // What displays in app. Used solely for sync and recover purposes.

long currentFilterSec;                // Filter age based on unit runtime in seconds (stored in vPin). Seconds used for finer resolution.
long currentFilterHours;              // Filter age based on unit runtime in hours.
long timeFilterChanged;               // Unix time that filter was last changed.
bool filterConfirmFlag = FALSE;       // Used to enter/exit the filter change mode.
const int filterChangeHours = 300L;   // Duration in hours between filter changes. Up for debate and experimentation!
bool changeFilterAlarm = FALSE;       // TRUE if filter needs to be changed, until reset.

long todaysAccumRuntimeSecCooling;    // Seconds that system has been cooling.
long todaysAccumRuntimeSecHeating;    // Seconds that system has been heating.
bool heatingMode;                     // FALSE = Cooling. TRUE = Heating.
bool hvacMode;                        // FALSE = Cooling. TRUE = Heating.

double tempRA, tempSA;                // Return and supply air temperatures

// HVAC control pins
int coolingRelay = 5;   // WeMos pin D1.
int heatingRelay = 4;   // WeMos pin D2.
int fanRelay = 16;      // WeMos pin D0.
int bypassRelay = 0;    // WeMos pin D3.

int controlSplit = 2;   // Predefined value of how much I want to heat or cool above/below setpoint.
int controllingTemp;
int setpointTemp;
String controllingSpace;
bool coolingMode;       // 1 = cooling. 0 = heating.
bool controlMode;
int tempKK, tempLK, tempAT;

long controlStart;
long controlRuntime;
long heatControlTimeout = 600000; // 600000 millis = 10 minutes
long coolControlTimeout = 120000000; // 120000000 millis = 20 minutes
bool controlLatch = FALSE;

bool blynkFlag;
int blynkDisconnectCount;
bool ranOnce;

void setup()
{
  Serial.begin(9600);
  WiFi.mode(WIFI_STA);

  //WiFi.softAPdisconnect(true); // Per https://github.com/esp8266/Arduino/issues/676 this turns off AP
  Blynk.begin(auth, ssid, pass);

  sensors.begin();
  sensors.setResolution(ds18b20RA, 10);
  sensors.setResolution(ds18b20SA, 10);

  while (Blynk.connect() == false) {
    // Wait until connected
  }

  pinMode(coolingRelay, OUTPUT);
  pinMode(heatingRelay, OUTPUT);
  pinMode(fanRelay, OUTPUT);

  // END OTA ROUTINE

  rtc.begin();

  fanStatusTimer = timer.setInterval(1000, fanStatus);
  setClockTimeTimer = timer.setInterval(1000, setClockTime);
  tempDisplayTimer = timer.setInterval(3210, tempDisplay);
  statusDisplayTimer = timer.setInterval(3543, statusDisplay);
  tempWatcherTimer = timer.setInterval(5000, tempWatcher);
  longStatusDisplayTimer = timer.setInterval(600000, longStatusDisplay);  // 10 minutes
  timer.setInterval(65432, updateVpinData1);

  timer.disable(fanStatusTimer);
  timer.disable(tempDisplayTimer);
  timer.disable(statusDisplayTimer);
  timer.disable(tempWatcherTimer);
}

void loop()  // To keep Blynk happy, keep most tasks out of the loop.
