Serial.print(char) crashes Mega - Board Toasted?

*** RESOLVED ***
The reason it was crashing the Mega was the char html[550] was being overfilled. I put in a check to see when it got nearly full to dump it into another c string.

void handleSchedule() {
  char html0[550] = { 0 }, html0b[550] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[100] = { 0 }, html4[100] = { 0 };
  char scheduleHHA[4] = { 0 };
  char scheduleMMA[4] = { 0 };
  char scheduleTempA[4] = { 0 };
  int scheduleHHi, scheduleMMi, scheduleTempi;
  char buff[10] = { 0 };

  currentBlock = 'A';
  char *pCurrentBlock = &currentBlock;
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostat Schedule</title></head><body><hr>");
  strcpy(html1, "<table><tr><th> Time </th > <th> Temp. </th> <tr><td><a href=AHHUp> + </a>");


  strcat(html0, html1);
  for (int i = 0; i < 4; i++) {

    Serial.print("currentBlock:");
    Serial.println(currentBlock);

    scheduleHHi = scheduleArray(currentBlock, 'r', "timeHH", 0);
    scheduleMMi = scheduleArray(currentBlock, 'r', "timeMM", 0);
    scheduleTempi = scheduleArray(currentBlock, 'r', "temperature", 0);
    Serial.print("ScheduleTempi:"); Serial.println(scheduleTempi);
    itoa(scheduleHHi, buff, 10);
    strcpy(scheduleHHA, buff);
    itoa(scheduleMMi, buff, 10);
    strcpy(scheduleMMA, buff);
    itoa(scheduleTempi, buff, 10);
    strcpy(scheduleTempA, buff);

    Serial.print("ScheduleTempA:"); Serial.println(scheduleTempA);

    strcpy(html2, "<a href=");
    strcat(html2, pCurrentBlock);
    strcat(html2, "HHDown> - </a>");
    
    strcat(html2, scheduleHHA);
    
    strcat(html2, "<a href=");
    strcat(html2, pCurrentBlock);
    strcat(html2, "HHUp> + </a>");

    strcat(html2, ": <a href=");
    strcat(html2, pCurrentBlock);
    strcat(html2, "MMDown> - </a>");
    
    strcat(html2, scheduleMMA);

    strcat(html2,"<a href=");
    strcat(html2, pCurrentBlock);
    strcat(html2, "MMUp> + </a>");
    strcat(html2, " </td> <td>");

    strcat(html3, "<a href=");
    strcat(html3, pCurrentBlock);
    strcat(html3, "TempDown> - </a>");
    
    strcat(html3, scheduleTempA);
    
    strcat(html3, "<a href=");
    strcat(html3, pCurrentBlock);
    strcat(html3, "TempUp> + </a>");
    strcat(html3, " </td></tr><tr><td>");

    int len0 = strlen(html0);
    int len0b = strlen(html0b);
    if (len0 > 430) { //When html0 is near overflow, start on html0b
      strcat(html0b, html2);
      strcat(html0b, html3);
    } else {
      strcat(html0, html2);
      strcat(html0, html3);
    }
    Serial.print("html0 length: "); Serial.print(len0);
      Serial.print("html0b length: "); Serial.print(len0b);
    currentBlock++;
  }
  strcpy(html4, " </table> </body> </html> ");

  strcat(html0b, html4);
  Serial.println(html0);
  Serial.println(html0b);
}

For some reason this reboots the Mega. It compiles without warnings on More warnings setting. I do get quite a few ALL warnings, but nothing fatal to suggest it would crash the Mega. The line that crashes is the Serial.print(htmlAll);. If I comment it out, it runs ok.

I'm begining to think the board is toast. What do YOU think?

void handleSchedule() {
  //This prints to WWW the schedule
  char html0[82] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };

  currentBlock = 'A';
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostat Schedule</title></head><body><hr>");
  strcpy(html1, "<table><tr><th> Time </th > <th> Temp. </th> <tr><td>");
  for (int i = 0; i < 8; i++) {
    currentBlock = currentBlock + i;
    Serial.print("currentBlock:");
    Serial.println(currentBlock);
    scheduleHH =  scheduleArray(currentBlock, 'r', "timeHH", 0);
    scheduleMM =  scheduleArray(currentBlock, 'r', "timeMM", 0);
    scheduleTemp =  scheduleArray(currentBlock, 'r', "temperature", 0);
    strcpy(html2, scheduleHH);
    strcat(html2, ':');
    strcat(html2, scheduleMM);
    strcat(html2, " < / td > <td>");
    strcpy(html3, scheduleTemp);
    strcat(html3, " </td> <tr>");
  }
  strcpy(html4, " </table> </body> < / html > ");
  strcat(html0, html1);
  strcat(html0, html2);
  strcat(html0, html3);
  strcat(html0, html4);
  Serial.println(html0);
}
char html0 = { 0 }

That is a single char variable. It holds one character. We don't use the braces when we initialize it. That's for arrays.

html0 = "<!DOCTYPE html><html><head><title>Thermostatv00</title></head><body><hr> System: ";

All that crap isn't going to fit into a single character. You need an array large enough to hold it.

Now that works because the compiler will just grab the first (or last I cant remember) character and stick it in there. But then you use strcat which really does try to cram all that stuff into a 1 character box. Once you start overstepping memory like that, all bets are off and you can get any kind of random weird results.

Moral of the story, go learn how to handle strings in C. You're not doing it right.

Delta_G, I fixxed that part. I am dumb. It's doing it on a much smaller scale function now. It will either lock up, (no indication of looping, no typical sketched response from serial) or reset (the LCD goes dark and thing reinits).

Could you post your revised code? Make sure we're all on the same page.

DKWatson, sure.

Also... I learned somewhere here if you have a char 'A' and you + 1, you get 'B', is that true?

This will produce this on SerialMon:

currentBlock:A
scheduleMM:0
after hours
just past the colon
on our way
:A <<== Missing "currentBlock"
scheduleMM:0
after hours
just past the <<== cut off string 
Connected to JMR <<== INIT string, after reboot.
void handleSchedule() {
  //This prints to WWW the schedule
  char html0[150] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };

  currentBlock = 'A';
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostat Schedule</title></head><body><hr>");
  strcpy(html1, "<table><tr><th> Time </th > <th> Temp. </th> <tr><td>");
  for (int i = 0; i < 8; i++) {
    currentBlock = currentBlock + i;
    Serial.print("currentBlock:");
    Serial.println(currentBlock);
    scheduleHH =  scheduleArray(currentBlock, 'r', "timeHH", 0);
    scheduleMM =  scheduleArray(currentBlock, 'r', "timeMM", 0);
    scheduleTemp =  scheduleArray(currentBlock, 'r', "temperature", 0);
    Serial.print("scheduleMM:");
    Serial.println(scheduleMM);
    strcpy(html2, scheduleHH);
    Serial.println("after hours");
   // strcat(html2, ':');
    Serial.println("just past the colon");
    strcat(html2, scheduleMM);
    Serial.println("on our way");
    strcat(html2, " < / td > <td>");
    Serial.println("half-way there");
    strcpy(html3, scheduleTemp);
    Serial.println("nearly done");
    strcat(html3, " </td> <tr>");
    Serial.println("end");
  }
  strcpy(html4, " </table> </body> < / html > ");
  strcat(html0, html1);
  strcat(html0, html2);
  strcat(html0, html3);
  strcat(html0, html4);
  Serial.println(html0);
}

Will look at your code, but yes, A + 1 = B and A + 32 (0X20) = a.

html0 isn't big enough.

html0 at first is 78 characters, html1 is 53. After strcat(html0, html1); html0 is 131, leaving room for 18 more (one required for the NULL terminator)

Forget the others, html4 is 29 characters. Once you start writing beyond the end of your array, all bets are off.

Fixed that. Rushed coding. I can't figure it out. Still ... blink. It's resetting. Speaking of, blink works fine.

The bigger the sketch the more likely it has errors -- A.... and B: the more likely it is to predispose a bad chip to exhibit failure. The sketch is 1196 lines.

Funny thing is the first sketch/function I posted now will lock the board up, not reset it. Here IT is.

void handleRoot() { //Content of page is here.
  int fanMode = readEEprom("fanMode");
  int fanPostMixTime = readEEprom("fanPostMixTime");
  int fanFor = readEEprom("fanFor");
  int fanEvery = readEEprom("fanEvery");
  char html0[82] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };
  char html6[100] = { 0 }, html7[200] = { 0 },  html8[100] = { 0 }, html9[100] = { 0 };
  itoa(tempSetting, tempSetting, 10);
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostatv00</title></head><body><hr> System: ");
  modeName.toCharArray(html0b, 8);
  strcpy(html1, "<hr> <a href=035><font color=red> UP </font></a>
<font size=6>");
  strcpy(html2, tempSetting);
  if (fanMode == 0) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000><b> * Fan on With H/C * </b></a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020> Fan Post-mix </a>
 <a href=0290021> - </a>");
  if (fanMode == 1) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010><b> * Fan on All Time * </b> </a>
 <a href=0290020> Fan Post-mix </a>
 <a href=0290021> - </a>");
  if (fanMode == 2) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020><b> * Fan Post-mix * </b></a>
 <a href=0290021> - </a>");
  if (fanMode == 3) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020>Fan Post-mix</a>
 <a href=0290021> - </a>");
  itoa(fanPostMixTime, fanPostMixTime, 10);
  strcpy(html4, fanPostMixTime);
  if (fanMode < 3)   strcpy(html5, "Mins <a href=0290022> + </a>
 <a href=0290030> Fan on FOR... Every...  </a>
 <a href=0290031>  - </a>");
  if (fanMode == 3)  strcpy(html5, "Mins <a href=0290022> + </a>
 <a href=0290030><b> * Fan on FOR... Every... * </b> </a>
 <a href=0290031>  - </a>");
  itoa(fanFor, fanFor, 10);
  strcpy(html6, fanFor);
  strcpy(html7, "Mins <a href=0290032> + </a> <a href=0290033> &nbsp &nbsp &nbsp &nbsp - </a>");
  itoa(fanEvery, fanEvery, 10);
  strcpy(html8, fanEvery);
  strcpy(html9, "Mins <a href=0290034> + </a> </font><hr> <a href=schedule> Schedule </a></body></html>");
  char htmlAll[1000] = { 0 };
  strcpy(htmlAll, html0);
  strcat(htmlAll, html0b);
  strcat(htmlAll, html1);
  strcat(htmlAll, html2);//Glue it all together
  strcat(htmlAll, html3);
  strcat(htmlAll, html4);
  strcat(htmlAll, html5);
  strcat(htmlAll, html6);
  strcat(htmlAll, html7);
  strcat(htmlAll, html8);
  strcat(htmlAll, html9);
  // server.send(200, "HTML", htmlAll);
  Serial.println(htmlAll);
}

My point is that it will freeze and / or reboot in the middle of a Serial.print("Happy birthday to you") becomes "Happy birthda". REBOOT.

Another issue you need to deal with is the re-initializing of html2 and html3 inside your for() loop. When first you go through the loop, html2 = scheduleHH. So say html2 = HH\0. Then you cat scheduleMM. The cat function appends at the start of the NULL and then places a new NULL at the end of the new array so html2 becomes HHMM\0. Then you cat " < / td > " so html2 is now HHMM < / td > \0. Okay so far?

The next time through the loop, you make html2 = scheduleHH again, but the rest of the array is still there so the value of html4 is still HHMM < / td > \0. The next cat will place MM where?

Just checked, strcopy will place a NULL and the end of the new text, but the old text is still in the remaining part of the array.

You may be dealing with a buffer overflow in the Serial class having to deal with a 1000 byte array, even if it only holds about 600 bytes. Try chunking it down.

The bad news is, I've just run this through a Mega,

char html0[82] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };
char html6[100] = { 0 }, html7[200] = { 0 },  html8[100] = { 0 }, html9[100] = { 0 };

void setup()
{
    Serial.begin(38400);
    strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostatv00</title></head><body><hr> System: ");
    strcpy(html0b, "8");
    strcpy(html1, "<hr> <a href=035><font color=red> UP </font></a>
<font size=6>");
    strcpy(html2, "123");
    strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020><b> * Fan Post-mix * </b></a>
 <a href=0290021> - </a>");
    strcpy(html4, "55");
    strcpy(html5, "Mins <a href=0290022> + </a>
 <a href=0290030> Fan on FOR... Every...  </a>
 <a href=0290031>  - </a>");
    strcpy(html6, "22");
    strcpy(html7, "Mins <a href=0290032> + </a> <a href=0290033> &nbsp &nbsp &nbsp &nbsp - </a>");
    strcpy(html8, "33");
    strcpy(html9, "Mins <a href=0290034> + </a> </font><hr> <a href=schedule> Schedule </a></body></html>");
    Serial.println("Okay so far");
    char htmlAll[1000] = { 0 };
    strcpy(htmlAll, html0);
    strcat(htmlAll, html0b);
    strcat(htmlAll, html1);
    strcat(htmlAll, html2);
    strcat(htmlAll, html3);
    strcat(htmlAll, html4);
    strcat(htmlAll, html5);
    strcat(htmlAll, html6);
    strcat(htmlAll, html7);
    strcat(htmlAll, html8);
    strcat(htmlAll, html9);
    Serial.println("Okay here with no print");
    Serial.println(htmlAll);
}

void loop()
{

}

And it works fine.

Last question, for now, what release of the IDE are you using?

IDE 1.8.5

Could be still the fact it's part of a 1200 line sketch. I got one part down, the one with the table that is working half-way now. The first one still is locking up, the run you ran through. My best guess is some part of memory is frigged, higher than when you load one function. I did accidentally short some outputs.

Thanks for your fast help.

Matt

Tough to say without seeing all the code and possibly testing it on another unit. You're using a lot of RAM and not all of it shows up at compile time. For example, htmlAll[1000] is placed on the stack. You may have memory corruption issues elsewhere, but there's 8K to work with.

The IDE should be okay. There are known issues with 1.8.7 but 1.8.5 is quite stable. Can you get your hands on another Mega to test? For any more of an answer, you'll need to post your entire code. The two snippets you have posted don't reveal what's going on in the rest of the program, and like someone else has said, the problem is most likely in the code you didn't post.

Here is the code in situ. I have to place several posts as there is a lot of code with menus and whatnot. Strings are still in use in parts, so that could be a cause of the memory problems alone. Lines ~1-300

*/
//*** Includes **************************************
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <SPI.h>
#include <EEPROM.h>
#include <avr/pgmspace.h>
/*
  #include <ESP8266WiFi.h>
  #include <WiFiClient.h>
  #include <ESP8266WebServer.h>
  #include <ESP8266mDNS.h>
*/

//***  Inits  **************************************
LiquidCrystal_I2C lcd(0x27, 16, 2);
//ESP8266WebServer server(80);

//*** Declarations *********************************
const char* ssid = "JMR";
const char* password = "crystal....";

int currentMM, currentHH;
int fanMode, HHOffset, MMOffset, cursorPosition = 0, menuIndex = 0, menuIDc, menuDepth = 0;
int millisPrior, subLoop, tempReadI, locked, seed, scheduleHH, scheduleMM, scheduleTemp, tempSetting, tempTemp, currentTemp, systemOnMS, systemPrev = 0;
int ntpOn;
int flasherA[5][7] = { 0 };
unsigned long menuStartMS, flasherL[5], tempMS, fanMS;
char lcdMode;
char currentBlock;
char menuIDa = 0, menuIDb;
//float tempRounded = 70.5;
String currentTimeStr, modeName;


// PIN-MAP
//*****************************************************************************************************************************************************************
// -1: InputPullup, 0: Not installed, 1: Input Positive, 2: OUTPUT
int installed[20] = {   0,  0,   2,      2,    2,     0,    2,    0,    0,     2,     2,     2,    1,      0,    1,     0,      0,    0,     0,          0 };
//char* pinNames[20] = { '0', '1', '2',   '3',   '4',   '5', '6', '7',   '8',   '9',  "10",  "11", "12",  "13",  "A0",  "A1",  "A2",  "A3",  "A4",      "A5"  };
//char* ssNames[20] = {  "x", "x", "FN6", "HT6", "AC6", "x", "LB6", "x", "x", "LO6", "LR6", "LG6",  "tm6", "LED",   "sd6", "x", "x", "x", "x", "x" };
const int                       FN6 = 2,     AC6 = 4,     LB6 = 6,                         LG6 = 11,     LED = 13,       sd6 = A0     ;
const int                             HT6 = 3,                          LO6 = 9, LR6 = 10,      tm6 = 12      ;
// *****************************************************************************************************************************************************************

void setup() {
  lcd.init();
  lcd.backlight();
  lcd.print("Thermostat");
  Serial.begin(9600);
  esp8266HTTPDinit();
  for (int i = 0; i < 18; i++) {
    // Array init loop

    // Set pin-modes based on installed flags
    if (installed[i] == -1) {
      pinMode(i, INPUT_PULLUP);
    }
    if (installed[i] == 0) {
      pinMode(i, INPUT_PULLUP);
    }
    if (installed[i] == 1) {
      pinMode(i, INPUT);
    }
    if (installed[i] == 2) {
      pinMode(i, OUTPUT);
    }
  }
  int currentHH = 0;
  int currentMM = 0;
  //writeEEprom("hysteresis",3);
  millisPrior = readEEprom("longmillis");
  //writeEEprom("fanMode", 0); //TEMP - remove this soon.
  currentBlock = 'A';
  currentTemp = 58;
}
unsigned long currentTime() {
  currentHH = 4;
  currentMM = 15;
  return 0;
}

void loop() {
  //  server.handleClient();
  tempTempSet(0);
  int menuAddrI;
  char *menuAddr;
  unsigned long ms = currentTime();
  flasher(0, 0, 0, 0, 0, 0);
  subLoop++;
  if (subLoop > 120) {
    loop2();
    subLoop = 0;
  }
  String currentTimeStr;
  currentTimeStr = currentTime(); //Calc current time
  if ((millis() - menuStartMS > 5000) && (lcdMode = 'm')) {
    lcdMode = 'd';
    displayIt(); //Revert to standby display
  }
  locked = readEEprom("lock");
  int  i = Serial.read() - 48;
  if (i > -1) {
    //Removed lock-screen shit
    menuAddr = menuAddress();
    menuAddrI = atoi(menuAddr);
    switch (i) {
      case 8: //Up
        flasher(0, 0, 100, 0, 2000, 255);
        tempTempSet(1);
        menuIndex--;

        switch (menuAddrI) {
          case 88:
            timeSet(1);
            break;
          case 81:
            ntpToggle();
            break;
          case 82:
            tfTimeout(1);
            break;
          case 83:
            fanTimeout(1);
          case 11:
            block(1);
            break;
          case 12:
            scheduleTime(1);
            break;
          case 13:
            scheduleTempFx(1);
            break;
          case 28:
            fanHCConfirm();
          case 21:
            fanAllConfirm();
            break;
          case 22:
            fanPostMix(1);
            break;
          case 23:
            fanOnEvery(1);
        }                               // Up
        menuM();
        break;
      case 5: //Center/Menu/Enter/Select
        menuStartMS = millis(); // Track start of menu display to revert
        menuDepth = 0;
        menuIDa = -1;
        menuIDb = -1;
        menuIDc = -1;
        menuIndex = 0;

        switch (menuAddrI) {
          case 28:
            fanHCConfirm();
            break;
          case 21:
            fanAllConfirm();
            break;
        }

        menuM();
        break;
      case 2: //Down
        menuIndex++;
        currentTemp--;
        handleSchedule();
        Serial.print(menuIndex); Serial.print("Temp.: "); Serial.println(currentTemp);
        switch (menuAddrI) {
          case 88:
            timeSet(-1);
            break;
          case 81:
            ntpToggle();
            break;
          case 82:
            tfTimeout(-1);
            break;
          case 83:
            fanTimeout(-1);
          case 11:
            block(-1);
            break;
          case 12:
            scheduleTime(-1);
            break;
          case 13:
            scheduleTempFx(-1);
            break;
          case 28:
            fanHCConfirm();
            break;
          case 21:
            fanAllConfirm();
            break;
          case 22:
            fanPostMix(-1);
            break;
          case 23:
            fanOnEvery(-1);
        }
        menuM();
        break;
      case 4: //Back / Left
        handleRoot();
        menuIndex = 0;
        menuDepth--;
        if (menuDepth < 0) {
          displayIt();
        }
        menuIDc = -1;
        menuM();
        cursorPosition--;
        break;
      case 6: // Right / Enter Menu
        menuStartMS = millis();
        if (menuDepth == 0) {
          menuIDa = menuIndex; //Upon (right), menuID becomes menuIndex, root menu level
        }
        if (menuDepth == 1) {
          menuIDb = menuIndex; //Submenu Level
        }
        if (menuDepth == 2) {
          menuIDc = menuIndex; //Item Level
        }
        menuDepth++;
        menuDepth = constrain(menuDepth, 0, 2);
        cursorPosition++;
        if (menuAddrI == 81) ntpToggle();
        menuIndex = 0;
        menuM();
        break; // 6 / Right / Enter Menu

    }
    if (menuIndex < 0) menuIndex = 3;   //Keep from running outside array bounds
    if (menuIndex > 3) menuIndex = 0;   //Keep from running outside array bounds
    if (cursorPosition > 2) cursorPosition = 0; //Wrap cursor at 2
    if (cursorPosition < 0) cursorPosition = 2; //Wrap cursor at 2
  }
  delay(10);
}

void loop2() {
  //debugSA();
  tempReading();
  systemUse();
  systemAction();
  lcd.setCursor(15, 0);
  int fanMode = readEEprom("fanMode");
  lcd.print(fanMode);
  // Serial.print(currentTemp); Serial.print("\t["); Serial.print(systemUse()); Serial.print(']'); Serial.println(modeName);
  //digitalWrite(13, !digitalRead(13));

}
void debugSA() {
  int arrTimeHH[8] = { 0 };
  int arrTimeMM[8] = { 0 };
  int arrTemp[8] = { 0 };
  EEPROM.get(210, arrTimeHH);
  EEPROM.get(230, arrTimeMM);
  EEPROM.get(250, arrTemp);
  for (int i = 0; i < 9; i++) {

    Serial.print(arrTimeHH[i]);
    Serial.print("\t\t"); //print tabs
    Serial.print(arrTimeMM[i]);
    Serial.print("\t\t"); //print tabs
    Serial.print(arrTemp[i]);
    Serial.println("."); //print tabs
    arrTimeHH[i] = i * 2;
    arrTimeMM[i] = i * 3;
    arrTemp[i] = 60 + i * 2;
  }
  Serial.print("---------------------------");
  EEPROM.put(210, arrTimeHH);
  EEPROM.put(230, arrTimeMM);
  EEPROM.put(250, arrTemp);
}

Lines 301~600

void lockScreen() {
  return;
  String lcdOut0;
  String lcdOut1;
  if (readEEprom("lock") == 0) return;
  lcdOut0 = "***T-stat Locked!**";
  locked = 1;
  menuStartMS = millis();
  seed = (random(0, 5));
  switch (seed) {
    case 0:
      lcdOut1 = "Press In";
      break;
    case 1:
      lcdOut1 = "Push up!";
      break;
    case 2:
      lcdOut1 = "Push Down";
      break;
    case 3:
      lcdOut1 = "Push Left";
      break;
    case 4:
      lcdOut1 = "Push Right!";
      break;
  }
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");

  lcd.clear();
  lcd.print(lcdOut0);
  lcd.setCursor(0, 1);
  lcd.print(lcdOut1);
}
float tempReading() {
  float tempRead;
  int totalTemp;
  float tempArray[30];
  int divisor;
  divisor = 0;
  //Take Temp reading
  tempRead = random(0, 10) + 65; //Temp for testing
  tempArray[tempReadI] = tempRead;
  tempReadI++;
  if (tempReadI > 30) tempReadI = 0;
  for (int i = 0; i < 31; i++) { //Add up temps
    if (tempArray[i] > 0) {
      divisor++;
      totalTemp = totalTemp + int(tempArray[i]);
    }
  }
  totalTemp = totalTemp / divisor;
  return constrain(totalTemp, 50, 90);
}

void timeSet(int dirc) {
  if (cursorPosition == 0) {
    readEEprom("HHOffset");
    HHOffset = HHOffset + 1 * dirc;
    writeEEprom("HHOffset", HHOffset);
    if (HHOffset > 23) {
      HHOffset = 0;  // rollover hours
    }
  }
  if (cursorPosition > 0) {
    readEEprom("MMOffset");
    MMOffset = MMOffset + 1 * dirc;
    writeEEprom("MMOffset", MMOffset);
    if (MMOffset > 59) {
      MMOffset = 0;  // Rollover minutes
    }
  }
}
void ntpToggle() {
  int ntp = readEEprom("timeNTP"); //Get value
  ntp = !ntp; //toggle value
  writeEEprom("timeNTP", ntp); //Store value
}
void tfTimeout(int dirc) { //Actually the TEMPERATURE timeout change
  int data = readEEprom("tempTimeout");
  data = data + 15 * dirc;
  writeEEprom("tempTimeout", data);
}

void fanTimeout(int dirc) {
  int data = readEEprom("fanTimeout");
  data = data + 15 * dirc;
  writeEEprom("fanTimeout", data);
}

void scheduleTime(int dirc) {
  if (cursorPosition == 0) {
    scheduleHH =  scheduleArray(currentBlock, 'r', "timeHH", 0);
    scheduleHH = scheduleHH + 1 * dirc;
    scheduleArray(currentBlock, 'w', "timeHH", scheduleHH);
    if (scheduleHH < 0) {
      scheduleHH = 23;  // rollover hours
    }
  }
  if (cursorPosition > 0) {
    scheduleMM =  scheduleArray(currentBlock, 'r', "timeMM", 0);
    scheduleMM = - 15 * dirc;
    scheduleArray(currentBlock, 'w', "timeMM", scheduleMM);
    if (scheduleMM < 0) {
      scheduleMM = 59;  // Rollover minutes
    }
  }
}
void scheduleTempFx(int dirc) {
  scheduleTemp = scheduleArray(currentBlock, 'r', "temp", scheduleTemp);
  scheduleTemp = scheduleTemp + 1 * dirc;
  scheduleArray(currentBlock, 'w', "temp", scheduleTemp);
}
void fanHCConfirm() {
  writeEEprom("fanMode", 0);
}
void fanAllConfirm() {
  writeEEprom("fanMode", 1);
}
void fanPostMix(int dirc) {
  int data = readEEprom("fanPostMixTime");
  data = + 5 * dirc;
  writeEEprom("fanPostMixTime", data);
  handleRoot();
}

void tempTempSet(int dirc) {
  int data = scheduleArray(currentBlock, 'r', "temperature", 0);
  if (dirc == 1) data = data + 1;
  if (dirc == -1) data = data - 1;
  tempSetting = data;
  tempMS = millis();
  if (abs(dirc) == 1) {
    tempTemp = 1;
    handleRoot();
    tempMS = millis();
  }
}
void fanOnEvery(int dirc) {
  int data;
  writeEEprom("fanMode", 3);
  if (cursorPosition == 0) {
    data = readEEprom("fanFor");
    data + 15 * dirc;
    writeEEprom("fanFor", data);
  }
  if (cursorPosition > 0) {
    data = readEEprom("fanEvery");
    data = data + 15 * dirc;
    writeEEprom("fanEvery", data);
  }
  handleRoot();
}


char* menuAddress() { //returns a four digit number indcating menu address
  char *menuItem;
  char *AA, BB, CC, DD;
  AA = menuIDa;
  BB = menuIDb;
  if (AA == -1) strcpy(AA, '9');
  if (BB == -1) strcpy(BB, '9');
  if (AA == 0) strcpy(AA, '8');
  if (BB == 0) strcpy(BB, '8');
  itoa(atoi(AA) * 10, AA, 10);
  strcat(menuItem, AA);
  strcat(menuItem, BB);

  return menuItem;
}
void displayIt() {
  return;
  String lcdOut0 = String(currentTemp) + ' ' + currentTime();
  String lcdOut1 = String(tempReading());
  locked = readEEprom("lock");
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");

  lcd.clear();
  lcd.print(lcdOut0);
  lcd.setCursor(0, 1);
  lcd.print(lcdOut1);
}
void systemAction() {
  fanLED();
  //System Modes

  switch (systemPrev) {
    case 0:
      modeName = "Standby";
      flasher(0, 0, 0, 0, 100, 0); //Internal off
      flasher(0, 1, 0, 0, 100, 0); //Red off
      flasher(0, 2, 0, 0, 100, 0); //Orange off
      flasher(0, 4, 0, 0, 100, 0); //Blue off
      digitalWrite(HT6, LOW);
      digitalWrite(AC6, LOW);
      digitalWrite(FN6, LOW);

      break;
    case 1: //FAN
      modeName = "Fan";
      //See below for flashers
      flasher(0, 0, 0, 0, 100, 0); //Internal off
      flasher(0, 1, 0, 0, 100, 0); //Red off
      flasher(0, 2, 0, 0, 100, 0); //Orange off
      flasher(0, 4, 0, 0, 100, 0); //Blue off
      digitalWrite(HT6, LOW);
      digitalWrite(AC6, LOW);
      digitalWrite(FN6, HIGH);

      break;
    case 2: // HEAT
      modeName = "Heat";
      flasher(0, 0, 0, 0, 100, 0); //Internal off
      flasher(0, 1, 0, 0, 100, 0); //Red off
      flasher(0, 2, 1000, 1, 1, 0); //Orange off
      flasher(0, 4, 0, 0, 100, 0); //Blue ON
      digitalWrite(HT6, HIGH);
      digitalWrite(AC6, LOW);
      digitalWrite(FN6, HIGH);

      break;
    case 3: //Cool / AC
      modeName = "Cooling";
      flasher(0, 0, 0, 0, 100, 0); //Internal off
      flasher(0, 1, 0, 0, 100, 0); //Red off
      flasher(0, 2, 0, 0, 100, 0); //Orange off
      flasher(0, 4, 1000, 1, 0, 0); //Blue ON
      digitalWrite(HT6, HIGH);
      digitalWrite(AC6, LOW);
      digitalWrite(FN6, HIGH);

      break;
  }
  //Fan Modes
}
void fanLED() {
  int fanMode = readEEprom("fanMode");

  if (fanMode == 0) flasher(0, 3, 0, 0, 900, 0); //on with hc - green off
  if (fanMode == 1) flasher(0, 3, 1000, 0, 0, 0); //All time - green FULL
  if (fanMode == 2) flasher(0, 3, 50, 0, 800, 0); //Post-mix - green flicker
  if (fanMode == 3) flasher(0, 3, 100, 0, 200, 0); //On every - green fast blink
}
int systemUse() {
  systemPrev = systemUse2();
  Serial.print("SystemPrev:"); Serial.println(systemPrev);
  return systemPrev;
}
int systemUse2() {
  //Determines which system to use.
  //0 is none, 1 fan, 2 heat, 3 cool
  char currentBlockI = 'A' + currentBlockID();
  //Serial.print(currentBlockI);
  //tempSetting = scheduleArray(currentBlockI, 'r', "temperature", 0);
  //Serial.print('['); Serial.print(tempSetting); Serial.print(']');
  //It SHOULD be tempSetting, but it is currentTemp
  int fanMode = readEEprom("fanMode"); // 0 = default on w/ HC, 1 = On all time, 2 = post-mix, 3 = on every...
  //Serial.print(fanMode);

  int tempDiff = (currentTemp - tempSetting);
  int  hysteresis = readEEprom("hysteresis");
  //Proper hysteresis. Turn OFF (0/1) == setTemp. Turn ON when abs(current - set) >= hysteresis
  Serial.println(hysteresis);
  Serial.print("TempDiff: "); Serial.println(tempDiff);
  if (systemPrev == 0) {
    //Turning on!
    if (abs(tempDiff) > hysteresis) {
      systemOnMS = millis();
      if (tempDiff > 0) return 3; //COOL ON
      if (tempDiff < 0) return 2; //HEAT ON
    }
  }
  if (systemPrev > 0) {
    //running... otherwise turning off...
    if (tempDiff > 0) {
      return 3; //COOL
    }
    if (tempDiff < 0) {
      return 2;  //HEAT
    }
  }
  if (fanMode == 0) {
    return 0;
  }
  if (fanMode == 1) {
    return 1;
  }
  if (fanMode == 2) {
    //find out how long system has been off
    int systemOffMins = ((millis() - systemOnMS) / 60000);
    int fanPostMixTime = readEEprom("fanPostMixTime");
    if (systemOffMins <= fanPostMixTime) {
      return 1;
    }
    else {
      return 0;
    }
  }
  //
}

Lines 600~900

int currentBlockID() {
  //returns current block where 0 = A...
  int HH, MM, n;
  char block;
  for (n = 0; n < 9; n++) {
    block = 'A' + n;
    HH = scheduleArray(block, 'r', "timeHH", 0);
    MM = scheduleArray(block, 'r', "timeMM", 0);
    if ((currentHH >= HH) && (currentMM >= MM)) {
      break;
    }
  }
  return n;
}


//void displayIt() { } //dummy entry
void menuM() {
  char menuItem[3] =  { menuAddress() };
  Serial.print("MenuID: "); Serial.println(menuItem);
  if (menuDepth == 0) menuM0();
  if (menuDepth == 1) menuM1();
  if (menuDepth == 2) menuM2();
}
void menuM0() { // Have a timeout for menu display to revert back to normal display
  char lcdOut0[20];
  char lcdOut1[20];
  char mainM[5][20] = { "Time Settings", "Schedule", "Fan Settings", "Lock Settings", "Temperature Settings" };
  strncpy(lcdOut0, mainM[menuIndex], 20);
  strncpy(lcdOut1, mainM[menuIndex + 1], 20);
  Serial.print('*');
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");
  lcd.clear();
  lcd.print('*');
  lcd.setCursor(15, 0);
  lcd.print('*');
  lcd.setCursor(1, 0);
  lcd.print(lcdOut0);
  lcd.setCursor(0, 1);
  lcd.print(lcdOut1);
}

void menuM1() {
  String lcdOut0;
  String lcdOut1;
  const String timeM[4], scheduleM[4], fanM[4], tempM[4], lockM[4];
  timeM[0] = "Time Set";
  timeM[1] = "NTP Time Set";
  timeM[2] = "Temp. Timeout";
  timeM[3] = "Fan Timeout";
  scheduleM[0] = "Set # of Blocks";
  scheduleM[1] = "Select Block";
  scheduleM[2] = "Set Block Time";
  scheduleM[3] = "Set Block Temp.";
  fanM[0] = "On with H/C";
  fanM[1] = "On all Time";
  fanM[2] = "Post-mix...";
  fanM[3] = "On every...";
  tempM[0] = "Hysteresis";
  tempM[1] = "Temp Alerts";
  tempM[2] = '.';
  tempM[3] = '.';
  lockM[0] = "Lock on/off";
  lockM[1] = "Lock Timeout";
  lockM[2] = '.';
  lockM[3] = '.';
  switch (menuIDa) {
    case 0: //Time Menu
      lcdOut0 = timeM[menuIndex];
      lcdOut1 = timeM[menuIndex + 1];
      break;
    case 1: //Schedule Menu
      lcdOut0 = scheduleM[menuIndex];
      lcdOut1 = scheduleM[menuIndex + 1];
      break;
    case 2: //Fan Menu
      lcdOut0 = fanM[menuIndex];
      lcdOut1 = fanM[menuIndex + 1];
      break;
    case 3: //Lock Menu
      lcdOut0 = lockM[menuIndex];
      lcdOut1 = lockM[menuIndex + 1];
    case 4: //Temperature Menu
      lcdOut0 = tempM[menuIndex];
      lcdOut1 = tempM[menuIndex + 1];
      break;
  }
  Serial.print('*');
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");
  lcd.clear();
  lcd.print('*');
  lcd.setCursor(14, 0);
  lcd.print(menuIndex);
  lcd.setCursor(1, 0);
  lcd.print(lcdOut0);
  lcd.setCursor(0, 1);
  lcd.print(lcdOut1);
}

void menuM2() {
  String lcdOut0;
  String lcdOut1;
  int MM2, HH2;
  char currentHHchar[3] = { 0 };
  char currentMMchar[3] = { 0 };
  String currentHHStr, currentMMStr;
  if (menuIDa == 0) { //time menu
    switch (menuIDb) {
      case 0: //Set time
        //polls current time and displays it like "*22* : 34" with stars around which to change
        //An up cursor will increment hour
        //A left cursor will select minutes to change
        lcdOut0 = "Set time.";
        HHOffset = readEEprom("HHOffset");
        MMOffset = readEEprom("MMOffset");
        HH2 = currentHH + HHOffset;
        MM2 = currentMM + MMOffset;

        itoa(HH2, currentHHchar, 10);
        itoa(MM2, currentMMchar, 10);
        currentHHStr = String(currentHHchar);
        currentMMStr = String(currentMMchar);

        if (cursorPosition == 0) lcdOut1 = "*" + currentHHStr + "*" + ":" + currentMMStr;
        if (cursorPosition > 0) lcdOut1 = currentHHStr + ":*" + currentMMStr + "*";
        break;
      case 1: //Auto/NTP Timeset
        lcdOut0 = "Auto/NTP Timeset";
        if (readEEprom("timeNTP") == 0) {
          lcdOut1 = "On / *OFF*";
        }
        else {
          lcdOut1 = "*ON* / Off";
        }
        //Select/left will change state of ntpOn
        break;
      case 2: //Temperature & Fan Change timeouts
        lcdOut0 = "Temp Timeout Mins";
        lcdOut1 = readEEprom("tempTimeout");
        break;
      case 3: // Fan Timeout
        lcdOut0 = "Fan Timeout Mins";
        lcdOut1 = readEEprom("fanTimeout");
    }
  }
  if (menuIDa == 1) { // Schedule Menu
    switch (menuIDb) {
      case 0:
        lcdOut0 = "# of blocks 2-8";
        lcdOut1 = readEEprom("timeBlocks");
        break;
      case 1:
        lcdOut0 = "Select Block";
        lcdOut1 = currentBlock;
        break;
      case 2:
        lcdOut0 = String("Set time for " + String(currentBlock));
        if (cursorPosition == 0) lcdOut1 = '*' + String(scheduleArray(currentBlock, 'r', "timeHH", 0)) + "*:" + String(scheduleArray(currentBlock, 'r', "timeMM", 0));
        if (cursorPosition > 0) lcdOut1 = String(scheduleArray(currentBlock, 'r', "timeHH", 0)) + ":*" + String(scheduleArray(currentBlock, 'r', "timeMM", 0)) + '*';
        break;
      case 3:
        lcdOut0 = String("Set temp for " + String(currentBlock));
        tempSetting = scheduleArray(currentBlock, 'r', "temperature", 0);
        lcdOut1 = tempSetting;
        break;
    }
  }
  if (menuIDa == 2) { //Fan Items
    switch (menuIDb) {
      case 0: //On with H/C
        writeEEprom("fanMode", 0);
        lcdOut0 = "Fan Mode 0 Set";
        lcdOut1 = "On with H/C";
        break;
      case 1: //All the time
        writeEEprom("fanMode", 1);
        lcdOut0 = "Fan Mode 1 Set";
        lcdOut1 = "On always";
        break;
      case 2: // Post-mix
        writeEEprom("fanMode", 2);
        lcdOut0 = "Specify post-mix mins";
        lcdOut1 = String(readEEprom("FanpostMixTime")) + "mins";
        break;
      case 3: //On Every
        writeEEprom("fanMode", 3);
        lcdOut0 = "On FOR  EVERY";
        lcdOut1 = "   " + String(readEEprom("fanFor")) + "  " + String(readEEprom("fanEvery")) + " mins";
        break;
    }
  }
  if (menuIDa == 3) { //Lock Items
    switch (menuIDb) {
      case 0: //Lock On/Off
        break;
      case 1: //Lock Timeout
        break;
    }
  }
  if (menuIDa == 4) { //Temperature items }
  }
  Serial.println(lcdOut0);
  Serial.println(lcdOut1);
  Serial.println("----------");
  lcd.clear();
  lcd.print(lcdOut0);
  lcd.setCursor(0, 1);
  lcd.print(lcdOut1);
}
int scheduleArray(char Block, char rw, char* item, int data) {
  int block;
  int out;
  int arrTimeHH[8], arrTimeMM[8], arrTemp[8];

  out = 0;

  if (Block == 'A') block = 0;
  if (Block == 'B') block = 1;
  if (Block == 'C') block = 2;
  if (Block == 'D') block = 3;
  if (Block == 'E') block = 4;
  if (Block == 'F') block = 5;
  if (Block == 'G') block = 6;
  if (Block == 'G') block = 7;
  //Serial.print('['); Serial.print(item); Serial.print(']');
  if (rw == 'r') { //Read data
    EEPROM.get(210, arrTimeHH);
    EEPROM.get(230, arrTimeMM);
    EEPROM.get(250, arrTemp);
    if (strcmp(item, "timeHH") == 0) {
      out = arrTimeHH[block];
    }
    if (strcmp(item, "timeMM") == 0) {
      out = arrTimeMM[block];
    }
    if (strcmp(item, "temperature") == 0) { //Do NOT use "temp" - for some reason doesn't work.
      out = arrTemp[block];
    }
  }
  if (rw == 'w') { //Write data
    if (strcmp(item, "timeHH") == 0) {
      arrTimeHH[block] = data;
      EEPROM.put(210, arrTimeHH);
    }
    if (strcmp(item, "timeMM") == 0) {
      arrTimeMM[block] = data;
      EEPROM.put(230, arrTimeMM);
    }
    if (strcmp(item, "temperature") == 0) {
      arrTemp[block] = data;
      EEPROM.put(250, arrTemp);
    }
  }
  return out;
}
void block(int dirc) {
  if (dirc == -1) {
    if (currentBlock == "") {
      currentBlock = 'H';
      return;
    }
    currentBlock = currentBlock + dirc;
    if (currentBlock == 'A') {
      currentBlock = 'H';
      return;
    }
  }

  if (dirc == 1) {
    if (currentBlock == "") {
      currentBlock = 'A';
      return;
    }
    currentBlock = currentBlock + dirc;
    if (currentBlock == 'H') {
      currentBlock = 'A';
      return;
    }
  }

}

Lines 900~1100

void flasher(int mode, int color, int intv1MS, int intv1Lev, int intv2MS, int intv2Lev) {
  int colorLED, colorL, state;
  //Serial.print(readEEprom("fanMode"));
  // flasher(0, 2, 200, 20, 500, 200)
  //first check if new flash request
  if ((intv1MS + intv2MS) > 0) { //new flash -- ** MUST NOT be called faster than interval total! **
    //Serial.println(intv1MS + intv2MS) ;
    //store vars into array
    flasherA[color][0] = mode;
    flasherA[color][1] = intv1MS;
    flasherA[color][2] = intv1Lev;
    flasherA[color][3] = intv2MS;
    flasherA[color][4] = intv2Lev;
    flasherL[color] = millis();
  }
  //cycle colors
  for (colorL = 0; colorL < 5; colorL++) {
    switch (colorL) {
      case 0:
        colorLED = LED;
        state = digitalRead(LED);
        break;
      case 1:
        colorLED = LR6;
        state = digitalRead(LR6);
        break;
      case 2:
        colorLED = LO6;
        state = digitalRead(LO6);
        break;
      case 3:
        colorLED = LG6;
        state = digitalRead(LG6);
        break;
      case 4:
        colorLED = LB6;
        state = digitalRead(LB6);
        break;
    }
    if (state == LOW) {
      if ((millis() - flasherL[colorL]) > flasherA[colorL][3]) {
        flasherL[colorL] = millis();
        flasherA[colorL][6] = HIGH; //flasherA[colorL][4];
        digitalWrite(colorLED, flasherA[colorL][6]);
      }
    }
    if (state == HIGH) {
      if (flasherA[colorL][3] == 0) {
        return;  //Keep on, ON!
      }
      if ((millis() - flasherL[colorL]) > flasherA[colorL][1]) {
        flasherL[colorL] = millis();
        flasherA[colorL][6] = LOW; //flasherA[colorL][2];
        digitalWrite(colorLED, flasherA[colorL][6]);
      }
    }
    if (flasherA[colorL][1] == 0) {
      digitalWrite(colorLED, LOW);
    }
  }
}

int readEEprom(String itemName) {
  unsigned long eAddr, outVar;
  eAddr = eAddrRef(itemName);
  if (eAddr == -1)  {
    outVar = -1;
    return;
  }
  EEPROM.get(eAddr, outVar);
  return outVar;
}
void writeEEprom(String itemName, unsigned long value) {
  int eAddr, valueInt;
  valueInt = int(value);
  if (itemName.substring(0, 4) == "long") {
    EEPROM.put(eAddr, value);
  }
  else {
    EEPROM.put(eAddr, valueInt);
  }
  eAddr = eAddrRef(itemName);
  EEPROM.put(eAddr, value);
}
int eAddrRef(String itemName) { //Looks up address from name. Provides a address and name cross-reference
  int eAddr;
  eAddr = -1; //If falls through without match, address -1
  if (itemName == "tempTimeout") { // Temperature change reverts in n minutes.
    eAddr = 0;
  }
  if (itemName == "temperature") { // Current read temp.
    eAddr = 2;
  }
  if (itemName == "temperatureSet") { //Current set temp.
    eAddr = 3;
  }
  if (itemName == "timeBlocks") { // Number of time slots to display & use
    eAddr = 4;
  }
  if (itemName == "tempX") { // temp setting at midnight. Rest stored in array.
    eAddr = 38;
  }
  if (itemName == "lock") { // To use lock, 0 for off.
    eAddr = 40;
  }
  if (itemName == "unlockTime") { //Time to stay unlocked
    eAddr = 42;
  }
  if (itemName == "timeNTP") { // Use NTP Server?
    eAddr = 44;
  }
  if (itemName == "fanTimeout") {
    eAddr = 46;
  }
  if (itemName == "hysteresis") {
    eAddr = 48;
  }
  if (itemName == "fanMode") { // 0 = default on w/ HC, 1 = On all time, 2 = post-mix, 3 = on every...
    eAddr = 50;
  }
  if (itemName == "fanPostMixTime") { // n of mins to post-mix (run fan after HC cycle)
    eAddr = 52;
  }
  if (itemName == "longmillis") {
    eAddr = 54;
  }
  if (itemName == "MMOffset") {
    eAddr = 60;
  }
  if (itemName == "HHOffset") {
    eAddr = 62;
  }
  if (itemName == "fanFor") {
    eAddr = 64;
  }
  if (itemName == "fanEvery") {
    eAddr = 66;
  }
  if (itemName == "tempTimeout") {
    eAddr = 68;
  }

  return eAddr;
  if (eAddr == -1) {
    Serial.println("No eAddr tag found!");
  }
}

void esp8266HTTPDinit() {
  pinMode(13, OUTPUT);
  digitalWrite(13, 0);
  // WiFi.mode(WIFI_STA);
  // WiFi.begin(ssid, password);

  // Wait for connection
  /* while (WiFi.status() != WL_CONNECTED) {
     delay(500);
     Serial.print(".");
    }
  */
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  // Serial.println(WiFi.localIP());

  //  if (MDNS.begin("esp8266")) {
  Serial.println("MDNS responder started");
  // }
  /*
    server.on("/", handleRoot);
    server.on("/35", wwwTemp(1));
    server.on("/36", wwwTemp(-1));
    server.on("/0290010", fanModeSet(1));
    server.on("/0290020", fanModeSet(2));
    server.on("/0290021", fanPostMix(1));
    server.on("/0290022", fanPostMix(-1));
    server.on("/0290030", fanModeSet(3));
    server.on("/0290031", fanOnEveryFor(1));
    server.on("/0290032", fanOnEveryFor(-1));
    server.on("/0290033", fanOnEveryE(1));
    server.on("/0290034", fanOnEveryE(-1));

    server.on("/inline", []() {
      server.send(200, "text/plain", "this works as well");
    });

    server.onNotFound(handleNotFound);

    server.begin();
  */
  Serial.println("HTTP server started");
}
void wwwTemp(int dirc) {
  tempTempSet(dirc);
  handleRoot();
}
void fanOnEveryFor(int dirc) {
  cursorPosition = 0;
  fanOnEvery(dirc);
  handleRoot();

}
void fanOnEveryE(int dirc) {
  cursorPosition = 1;
  fanOnEvery(dirc);
  handleRoot();

}

Lines 1100-EOF

void fanModeSet(int fanModeS) {
  fanMode = fanModeS;
  handleRoot();
}
void handleRoot() { //Content of page is here.
  int fanMode = readEEprom("fanMode");
  int fanPostMixTime = readEEprom("fanPostMixTime");
  int fanFor = readEEprom("fanFor");
  int fanEvery = readEEprom("fanEvery");
  char html0[82] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };
  char html6[100] = { 0 }, html7[200] = { 0 },  html8[100] = { 0 }, html9[100] = { 0 };
  itoa(tempSetting, tempSetting, 10);
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostatv00</title></head><body><hr> System: ");
  modeName.toCharArray(html0b, 8);
  strcpy(html1, "<hr> <a href=035><font color=red> UP </font></a>
<font size=6>");
  strcpy(html2, tempSetting);
  if (fanMode == 0) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000><b> * Fan on With H/C * </b></a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020> Fan Post-mix </a>
 <a href=0290021> - </a>");
  if (fanMode == 1) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010><b> * Fan on All Time * </b> </a>
 <a href=0290020> Fan Post-mix </a>
 <a href=0290021> - </a>");
  if (fanMode == 2) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020><b> * Fan Post-mix * </b></a>
 <a href=0290021> - </a>");
  if (fanMode == 3) strcpy(html3, "
 </font><a href=036><font color=blue> DOWN</font></a>
<hr><font color = black><a href=0290000> Fan on With H/C </a>
 <a href=0290010> Fan on All Time </a>
 <a href=0290020>Fan Post-mix</a>
 <a href=0290021> - </a>");
  itoa(fanPostMixTime, fanPostMixTime, 10);
  strcpy(html4, fanPostMixTime);
  if (fanMode < 3)   strcpy(html5, "Mins <a href=0290022> + </a>
 <a href=0290030> Fan on FOR... Every...  </a>
 <a href=0290031>  - </a>");
  if (fanMode == 3)  strcpy(html5, "Mins <a href=0290022> + </a>
 <a href=0290030><b> * Fan on FOR... Every... * </b> </a>
 <a href=0290031>  - </a>");
  itoa(fanFor, fanFor, 10);
  strcpy(html6, fanFor);
  strcpy(html7, "Mins <a href=0290032> + </a> <a href=0290033> &nbsp &nbsp &nbsp &nbsp - </a>");
  itoa(fanEvery, fanEvery, 10);
  strcpy(html8, fanEvery);
  strcpy(html9, "Mins <a href=0290034> + </a> </font><hr> <a href=schedule> Schedule </a></body></html>");
  char htmlAll1[550] = { 0 };
  char htmlAll2[550] = { 0 };
  strcpy(htmlAll1, html0);
  strcat(htmlAll1, html0b);
  strcat(htmlAll1, html1);
  strcat(htmlAll1, html2);//Glue it all together
  strcat(htmlAll2, html3);
  strcat(htmlAll2, html4);
  strcat(htmlAll2, html5);
  strcat(htmlAll2, html6);
  strcat(htmlAll2, html7);
  strcat(htmlAll2, html8);
  strcat(htmlAll2, html9);
  // server.send(200, "HTML", htmlAll);
  Serial.println(htmlAll1);
  Serial.println(htmlAll2);
}
void handleSchedule() {
  char html0[550] = { 0 }, html0b[100] = { 0 }, html1[100] = { 0 }, html2[100] = { 0 }, html3[400] = { 0 }, html4[100] = { 0 }, html5[200] = { 0 };
  currentBlock = 'A';
  strcpy(html0, "<!DOCTYPE html><html><head><title>Thermostat Schedule</title></head><body><hr>");
  strcpy(html1, "<table><tr><th> Time </th > <th> Temp. </th> <tr><td>");
    char* scheduleHH;
    char* scheduleMM;
    char* scheduleTemp;
    strcat(html0, html1);
  for (int i = 0; i < 8; i++) {
  currentBlock++;
    Serial.print("currentBlock:");
    Serial.println(currentBlock);
//   return;
  
  itoa(scheduleArray(currentBlock,"scheduleHH",'r',0),scheduleHH,10);
itoa(scheduleArray(currentBlock,"scheduleMM",'r',0),scheduleMM,10);
itoa(scheduleArray(currentBlock,"scheduleTemp",'r',0),scheduleTemp,10);
Serial.println(scheduleHH);
   strcpy(html2, scheduleHH);
  strcat(html2, ':');
    strcat(html2, scheduleMM);
    strcat(html2, " </td> <td>");
    strcpy(html3, scheduleTemp);
    strcat(html3, " </td></tr><tr><td>");

  strcat(html0, html2);
  strcat(html0, html3);
  }
  strcpy(html4, " </table> </body> </html> ");

  strcat(html0, html4);
  Serial.println(html0);
}
void handleNotFound() {
  digitalWrite(13, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  //  message += server.uri();
  message += "\nMethod: ";
  //  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  // message += server.args();
  message += "\n";
  //for (uint8_t i = 0; i < server.args(); i++) {
  //   message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  //}
  //  server.send(404, "text / plain", message);
  digitalWrite(13, 0);
}