 //initialize state machine, start in state: Idle
 FSM thermostatStateMachine = FSM(initState);
 
-String VERSION = "Version 0.07";
+//milliseconds for the init cycle, so temperature samples get stabilized
+//this should be in the order of the 5 minutes: 5*60*1000==300000
+#define INIT_TIMEOUT 30000
+elapsedMillis initTimer;
+
+//milliseconds to leave the fan on when the target temp has been reached
+//this evacuates the heat or the cold air from vents
+#define END_OF_CYCLE_TIMEOUT 15000
+elapsedMillis endOfCycleTimer;
+
+//minimum number of milliseconds to leave the heating element on
+// to protect on-off on the fan and the heating element
+#define MINIMUM_ON_TIMEOUT 5000
+elapsedMillis minimumOnTimer;
+
+/*******************************************************************************
+ IO mapping
+*******************************************************************************/
+// D0 : relay: fan
+// D1 : relay: heat
+// D2 : relay: cold
+// D4 : DHT22
+// D3, D5~D7 : unused
+// A0~A7 : unused
 int fan = D0;
 int heat = D1;
 int cold = D2;
+//TESTING_HACK
 int fanTesting;
 int heatTesting;
 int coldTesting;
 
-// system defines
+/*******************************************************************************
+ DHT sensor
+*******************************************************************************/
 #define DHTTYPE  DHT22                // Sensor type DHT11/21/22/AM2301/AM2302
 #define DHTPIN   4                    // Digital pin for communications
 #define DHT_SAMPLE_INTERVAL   30000   // Sample room temperature every 30 seconds

  }
}

void myDigitalWrite( int input, int status){
  digitalWrite(input, status);
  if (input == fan){

String currentTempString = String(currentTemp); //String to store the sensor's temp so it can be exposed
String currentHumidityString = String(currentHumidity); //String to store the sensor's humidity so it can be exposed

//TESTING_HACK
// this allows me to system test the project
bool testing = false;


/*******************************************************************************
 * Function Name  : setup
 * Description    : this function runs once at system boot
 *******************************************************************************/
void setup() {

  //pulish startup message with firmware version
  Particle.publish(APP_NAME, VERSION, 60, PRIVATE);

  //declare and init pins
  pinMode(fan, OUTPUT);
  pinMode(heat, OUTPUT);
  pinMode(cold, OUTPUT);
  myDigitalWrite(fan, LOW);
  myDigitalWrite(heat, LOW);
  myDigitalWrite(cold, LOW);

  //declare cloud variables
  //https://docs.particle.io/reference/firmware/photon/#particle-variable-
  //Currently, up to 10 cloud variables may be defined and each variable name is limited to a maximum of 12 characters
  if (Particle.variable("targetTemp", targetTempString)==false) {
    Particle.publish(APP_NAME, "ERROR: Failed to register variable targetTemp", 60, PRIVATE);
  }
  if (Particle.variable("currentTemp", currentTempString)==false) {
    Particle.publish(APP_NAME, "ERROR: Failed to register variable currentTemp", 60, PRIVATE);
  }
  if (Particle.variable("humidity", currentHumidityString)==false) {
    Particle.publish(APP_NAME, "ERROR: Failed to register variable humidity", 60, PRIVATE);
  }

  //declare cloud functions
  //https://docs.particle.io/reference/firmware/photon/#particle-function-
  //Currently the application supports the creation of up to 4 different cloud functions.
  //The length of the funcKey is limited to a max of 12 characters.
  // If you declare a function name longer than 12 characters the function will not be registered.
  //user functions
  if (Particle.function("setTargetTmp", setTargetTemp)==false) {
     Particle.publish(APP_NAME, "ERROR: Failed to register function setTargetTemp", 60, PRIVATE);
  }
  //TESTING_HACK
  if (Particle.function("setTesting", setTesting)==false) {
     Particle.publish(APP_NAME, "ERROR: Failed to register function setTesting", 60, PRIVATE);
  }
  //TESTING_HACK
  if (Particle.function("setCurrTmp", setCurrentTemp)==false) {
     Particle.publish(APP_NAME, "ERROR: Failed to register function setCurrentTemp", 60, PRIVATE);
  }
  //TESTING_HACK
  if (Particle.function("getOutputs", getOutputs)==false) {
     Particle.publish(APP_NAME, "ERROR: Failed to register function getOutputs", 60, PRIVATE);
  }

}

