// James Ferguson
// CE351
// Temperature Slave

#include <SPI.h>
volatile boolean processTemperature;
volatile boolean processAccesPoint;
volatile boolean processPassword;
volatile boolean processConnection;
volatile float temperature;
char buff [50];

// commands
const byte SIMO_TEMPERATURE = B00000001;
const byte SIMO_CONNECT_WIFI = B00000010;
const byte SIMO_ACCESS_POINT = B00000011;
const byte SIMO_PASSWORD = B00000100;

// WIFI data
String accessPoint = "Guest";       // AP NAME. Change it to the AP you are using. You can even use the your smartphone's hotspot. 
String password = ""; // AP PASSWORD. At FLC, the Guest AP doesn't need a password
String API = "GVDN5WA12ZF3ZCU3"; // Must be your ThingSpeak channel's API. 
String Host = "api.thingspeak.com";
String Port = "80";
int countTrueCommand;
int countTimeCommand; 
boolean found = false

void setup (void) {
  Serial.begin(115200); // ESP setup 
  
  connectWIFI();

  pinMode(MISO, OUTPUT); // have to send on master in so it set as output
  SPCR |= _BV(SPE); // turn on SPI in slave mode
  processTemperature = false;
  processAccesPoint = false;
  processPassword = false;
  processConnection = false;
  SPI.attachInterrupt(); // turn on interrupt
}

void connectWIFI () { // ESP8266 setup
  sendCommand("AT+RST",5,"OK");
  sendCommand("AT",5,"OK");
  sendCommand("AT+CWMODE=1",5,"OK");
  String cmd = F("AT+CWJAP=\"");
  cmd += accessPoint;
  cmd += F("\",\"");
  cmd += password;
  cmd += F("\"");
  sendCommand(cmd,20,"OK");
}
 
ISR (SPI_STC_vect) { // SPI interrupt routine
  static byte indx;
  
  static byte curentCommand;
  byte recivedByte = SPDR; // read byte from SPI Data Register
  
  if (curentCommand == SIMO_TEMPERATURE) {
    if (indx < sizeof buff) {
      if (recivedByte == '\r') { //check for the end of the word
        processTemperature = true;
        indx = 0;
        curentCommand = B00000000;
      } else {
        buff [indx++= recivedByte; // save data in the next index in the array buff
      }
    }
  } else if (curentCommand == SIMO_CONNECT_WIFI) {
    curentCommand = B00000000;
    processConnection = true;
  } else if (curentCommand ==  SIMO_ACCESS_POINT) {
    if (indx < sizeof buff) {
      if (recivedByte == '\r') { //check for the end of the word
        processAccesPoint = true;
        indx = 0;
        curentCommand = B00000000;
      } else {
        buff [indx++= recivedByte; // save data in the next index in the array buff
      }
    }
  } else if (curentCommand ==  SIMO_PASSWORD) {
    if (indx < sizeof buff) {
      if (recivedByte == '\r') { //check for the end of the word
        processPassword = true;
        indx = 0;
        curentCommand = B00000000;
      } else {
        buff [indx++= recivedByte; // save data in the next index in the array buff
      }
    }
  } else { // we dont have a curent command, the recived byte is the command
    curentCommand = recivedByte;
    for (int i = 0; i < 50; i++) { // clear buffer
      buff[i] = '\0'
    }
  }
}
 
void loop (void) {
  if (processTemperature) {
    temperature = atof(buff);
    processTemperature = false; //reset the process

    String sensorByteStr = String(temperature);  
    String getData = "GET /update?api_key="+ API +"&field1="+sensorByteStr; // send to ThingSpeak, needs to be a string
    sendCommand("AT+CIPMUX=1",5,"OK");
    sendCommand("AT+CIPSTART=0,\"TCP\",\""+ Host +"\","+ Port,15,"OK");
    sendCommand("AT+CIPSEND=0," + String(getData.length()+4),4,">");
    Serial.println(getData);
    sendCommand("AT+CIPCLOSE=0",5,"OK");

  } else if (processAccesPoint) {
    processAccesPoint = false;
    accessPoint = String(buff);
    
  } else if (processPassword) {
    processPassword = false;
    password = String(buff);
    
  } else if (processConnection) {
    processConnection = false;
    //sendCommand("AT+RESTORE", 5, "OK");
    sendCommand("AT+CWQAP"5"OK");
    connectWIFI();
  }
}

void sendCommand(String command, int maxTime, char readReplay[]){ // send data to ESP8266
  while(countTimeCommand < (maxTime*1)) {
    Serial.println(command); //at+cipsend
    if(Serial.find(readReplay)) { //ok
      found = true;
      break;
    }  
    countTimeCommand++;
  }  
  if(found == true) {
    countTrueCommand++;
    countTimeCommand = 0;
  }  
  if(found == false) {
    countTrueCommand = 0;
    countTimeCommand = 0;
  }  
  found = false;
}