 #include <RTC_DS1307.h>
 
 #include <LCD03.h>
- 
-#define BATT_PIN A3 
+
+#define BATT_PIN A3
 
 #define LED_13_PIN 13
 
 #define LDR_PIN A1
 
-#define DHTPIN A0 
-#define DHTTYPE DHT22 
+#define DHTPIN A0
+#define DHTTYPE DHT22
 
 #define LCD_CHAR_LENGTH 16
 

  return result;
}

void printThisOnLCDLine(String text, int line){

  //Clear current line only if the new line cannot occupy the old line
  if(text.length() < LCD_CHAR_LENGTH){
    lcd.setCursor (0, line);  
    lcd.print("                "); 
  }

  lcd.setCursor (0, line);  
  lcd.print(text);
}

String generateDateTimeString(int year, int month, int day, int hour, int minute, int second){
  char buff[3];

  sprintf(buff, "%02d", hour);

  // the compilation time.  If necessary, the RTC is updated.
  DateTime now = RTC.now();
  DateTime compiled = DateTime(__DATE__, __TIME__);

  if (now.unixtime() < compiled.unixtime()) {
    Serial.println("RTC is older than compile time! Updating");
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }

  //Start LCD
  lcd.begin(LCD_CHAR_LENGTH, 2);


  lcd.createChar(THERM_ICON_REP, thermIcon);
  lcd.createChar(HUM_ICON_REP, humIcon);

  changeBacklightStatus(false);

  printThisOnLCDLine("By: YKM", 1);


  //Start DTT
  dht.begin();


}

void loop() {
  DateTime now = RTC.now();


  int second = now.second();
  int minute = now.minute();
  int hour = now.hour();

  int lightValue = analogRead(LDR_PIN);
  Serial.println("LDR");
  Serial.println(lightValue);

  if (currentlyOn) {

    //Update time only if second changes. Prevent needless requests to LCD
    if (second != prevUpdateTimeSecond) {
      prevUpdateTimeSecond = second;
      String dateString = generateDateTimeString(now.year(), now.month(), now.day(), now.hour(), now.minute(), now.second());
      printThisOnLCDLine(dateString, 0);



      if (lightValue < LIGHT_THRESHOLD_ON && !isLcdBacklightOn) {
        int battMilliVolt = getBatteryMilliVoltage();

        if (battMilliVolt > BATT_MILLIVOLT_NOT_TURN_ON_LIGHT_THRESHOLD) {
          changeBacklightStatus(true);
          isLcdBacklightOn = true;
        }

      }

      if (lightValue > LIGHT_THRESHOLD_OFF && isLcdBacklightOn) {
        changeBacklightStatus(false);
        isLcdBacklightOn = false;
      }
    }

    //Every refresh interval
    if ((second % REFRESH_INTERVAL) == 0 && second != prevIntervalReadingSecond) {
      //Prevent multiple readings every interval
      prevIntervalReadingSecond = second;
      Serial.println();
      Serial.print("Take DHT22 Readings: ");


      float DHTTemp = dht.readTemperature();
      float DHTHum = dht.readHumidity();


      Serial.print(DHTHum);
      Serial.print("\t");
      Serial.println(DHTTemp);





      generateAndPrintTempHumString(DHTTemp, DHTHum);




    }
  }




  //Prevent too many execution since only need to check once a minute
  if (TURN_OFF_AT_TIMES && prevUpdateTurnOnAndOffMinute != minute) {
    prevUpdateTurnOnAndOffMinute = minute;

    Serial.println("Checking time");
    if (currentlyOn) {

      if (((hour == OFF_HOUR && minute >= OFF_MIN)
           || (hour > OFF_HOUR && hour < ON_HOUR)) //Exceeded OFF time. The moment display turns on to indicate lights out, go to sleep.
          && isLcdBacklightOn) { //Don't enter sleep mode if background is still bright enough

        currentlyOn = false;
        lcd.clear();
        changeBacklightStatus(false);
        isLcdBacklightOn = false;
        longSleep();
      }

    } else {

      if ((lightValue > LIGHT_THRESHOLD_OFF) //If background bright enough during off hour, turns thing back on
          || (hour == ON_HOUR && minute == ON_MIN)) {
        currentlyOn = true;
      } else {
        longSleep();
      }

    }
  }


  shortSleep();
  //delay(250);

}

void changeBacklightStatus(bool on) {
  if (on) {
    lcd.backlight();
  } else {
    lcd.noBacklight();
  }


}

void shortSleep() {
  Sleepy::loseSomeTime(SLEEP_INTERVAL);

}


void longSleep() {
  Sleepy::loseSomeTime(SLEEP_LONG_INTERVAL);
}

int getBatteryMilliVoltage() {
  int battValue = analogRead(BATT_PIN);
  int battMilliVoltage = (((float) battValue) / 1024) * 5000;
  Serial.print("Batt: ");
  Serial.println(battMilliVoltage);

  return battMilliVoltage;

}


void generateAndPrintTempHumString(float temp, float hum) {

  String tempString = ftoa(temp, 1);
  String humString = ftoa(hum, 1);

  String intermediate1 = " " + tempString + LCD_DEGREES_SYMBOL + "C ";
  String intermediate2 = " " + humString + "%";

  lcd.setCursor (0, 1);
  lcd.write((byte) THERM_ICON_REP);
  lcd.print(intermediate1);
  lcd.write((byte) HUM_ICON_REP);
  lcd.print(intermediate2);

}


String generateTempHumString(float temp, float hum) {
  String tempString = ftoa(temp, 1);
  String humString = ftoa(hum, 1);
  String result = "P:" + tempString + LCD_DEGREES_SYMBOL + "C H:" + humString + "%";
  return result;

}


//Convert float/double to String as ardiuno sprintf does not support float/double
String ftoa(double f, int precision)
{
  long p[] = {0, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000};

  char temp[5];
  char * a = temp;
  long heiltal = (long)f;
