/*
  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.
  
  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.
  
  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>. 
*/

#include <SandS.h>
#include <Wire.h>
#include <EEPROM.h>
#include <SoftwareSerial.h>

void setup() {
  while(!SerialPort.begin(19200, SERIAL_8N1, SERIAL_RS485_FD));
  Serial.begin(115200);
}

#define MAX_RECIPE_SIZE 64

byte ovenLightStatus;
byte applicanceState;
char recipeName[MAX_RECIPE_SIZE];
word ovenTemperature;
word minutesElapsed;
word minutesRemaining;
word temperatureSetpoint;
byte activeHeaterSystem;
byte meatProbeTemperature;
byte childLockStatus;

// Waits for and reads status packet
// Very little error checking done, no time out
boolean readStatus() {
  byte state = 0;
  char in;
  char pkt[128]; // 128 bytes max
  byte pktix = 0;
  char *str[16] = {&pkt[0]};
  byte strix = 0;
  while(1) {
    while(!SerialPort.available());
    in = SerialPort.read();
    switch(state) {
      case 0:
        if(in == (char)0xFD) state = 1;
        break;
      case 1:
        if(in == (char)0x0A) state = 2;
        else return false;
        break;
      case 2:
        Serial.write(in);
        if(in == (char)0x0A || in == (char)0x7C) {; // end of data
          pkt[pktix++] = 0x00;
          str[++strix] = &pkt[pktix];
          if(in == 0x0A) state = 3;
        } else {
          pkt[pktix++] = in;
        }
        break;
      case 3:
        if(in == (char)0xFE) {
          // == FIXES A COMM BUG IN THE OVEN ==
          if(strix == 11) {
            for(byte n = 3; n < 10; n++) str[n] = str[n + 1];
            strix = 10;
          }
          // == END FIX =======================
          if(strix != 10) return false; // All packets should have 10 SUBSTR
          Serial.println("");
          Serial.println(strix);
          for(byte n = 0; n < strix; n++)
          Serial.println(str[n]);
          
          ovenLightStatus = strtoul(str[0], NULL, 10);
          applicanceState = strtoul(str[1], NULL, 10);
          strcpy(recipeName, str[2]);
          ovenTemperature = strtoul(str[3], NULL, 10);
          minutesElapsed = strtoul(str[4], NULL, 10);
          minutesRemaining = strtoul(str[5], NULL, 10);
          temperatureSetpoint = strtoul(str[6], NULL, 10);
          activeHeaterSystem = strtoul(str[7], NULL, 10);
          meatProbeTemperature = strtoul(str[8], NULL, 10);
          childLockStatus = strtoul(str[9], NULL, 10);
          return true;
        }
        return false;
    }
  }
}

void loop() {
  if(!readStatus()) {
    Serial.println("\n== STATUS READOUT FAILED =======");
  } else {
    Serial.println("\n== OVEN STATUS READOUT =========");
    Serial.print("Oven light status:      ");
    Serial.println(ovenLightStatus);
    Serial.print("Applicance state:       ");
    Serial.println(applicanceState);
    Serial.print("Recipe name:            ");
    Serial.println(recipeName);
    Serial.print("Oven temperature:       ");
    Serial.println(ovenTemperature);
    Serial.print("Minutes elapsed:        ");
    Serial.println(minutesElapsed);
    Serial.print("Minutes remaining:      ");
    Serial.println(minutesRemaining);
    Serial.print("Temperature setpoint:   ");
    Serial.println(temperatureSetpoint);
    Serial.print("Active heater system:   ");
    Serial.println(activeHeaterSystem);
    Serial.print("Meat probe temperature: ");
    Serial.println(meatProbeTemperature);
    Serial.print("Child lock status:      ");
    Serial.println(childLockStatus);
  }
}
