// Example Sketch For Huzzah32 with very simple NMEA sentence decode
// that will display the time on the Lumex LDM6432.
// TX pin of Huzzah32 goes to RX pin of LDM6432.
// RX pin of Huzzah32 goes to TX pin of LDM6432.
// GND pin of Huzzah32 goes to GND pin of LDM6432.
// Each are powered via USB cables.
/*
 *  This sketch sends data via HTTP GET requests to data.sparkfun.com service.
 *
 *  You need to get streamId and privateKey at data.sparkfun.com and paste them
 *  below. Or just customize this script to talk to other HTTP servers.
 *
 */

#include <WiFi.h>

#define UTC_OFFSET  7       // this is PDT, so -8 from UTC - except when it's daylight savings time
// Note - UTC offset during Daylight Savings Time
// There is a simple routine for daylight savings time correction - it
// is up to the programmer to implement a better algorithm.

unsigned char utc_hr_buff[10];   // small buffer for UTC hour conversion

const char* ssid     = "ThemisBooth2P4";	// change to your SSID
const char* password = "Themis69391!";		// change to your pass code

const char* host = "192.168.3.249";		// ip of NMEA sentence broadcaster - some GPS receivers have this capability 
const char* streamId   = "....................";
const char* privateKey = "....................";

bool newData = false;
// char ldmCmd[] = "AT81=(0,0,TEST9876)";
// char ldmCmd1[] = "AT80=(0,0,A)";

// char ldmCmdHdr[] = "AT81=(0,3,Time:)";
char ldmCmdHdr[] = "ATe1=(0,3,96,Time:)";
char ldmBrightness[] = "ATf2=(10)";            // brightness
char ldmCmdMsg1[] = "ATe1=(2,2,3,Have A)";
// char ldmCmdMsg5[] = "ATe1=(2,0,3,GPS Actual)";
char ldmCmdMsg5[] = "ATe1=(2,0,3,(GPS)Maker)";
char ldmCmdMsg3[] = "ATe1=(2,2,3,Happy )";
char ldmCmdMsg2[] = "ATe1=(3,1,3,Nice Day!)";
// char ldmCmdMsg6[] = "ATe1=(3,0,3,Real Time.)";
char ldmCmdMsg6[] = "ATe1=(3,0,3,Faire 2019)";
char ldmCmdMsg4[] = "ATe1=(3,1,3,New Year!)";
// char ldmCmd[] = "AT81=(1,0,  HH:MM:SS)";                    // right now - just this format - char line x char column - 7 tall 5 wide
char ldmCmd1[] = "AT80=(0,0,A)";
char ldmCmd[] = "ATe1=(1,0,111, HH:MM:SS)";
static void Write_AT_Command(char *string);
IPAddress server(192,168,2,196);
int keyIndex = 0; 
WiFiClient client;
HardwareSerial HuzzahSerial(1);
void setup()
{
    unsigned char i;
    Serial.begin(115200);
    delay(10);
    
    Serial.println();
    Serial.println(); 
#if 0      
 while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
#endif  
    Serial.println();
    Serial.println();
    
  // lumex display is connected to Serial1
  HuzzahSerial.begin(115200, SERIAL_8N1, 16, 17);
  
//  Serial1.flush();
 Serial.println();
 Serial.println(); 
  
// Serial1.begin(9600);
#if 0
  while (!Serial1) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
#endif  

    Write_AT_Command("ATd0=()");
    delay(10);
     
  
    // We start by connecting to a WiFi network

    Serial.println();
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);

    WiFi.begin(ssid, password);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());
    
   Write_AT_Command(ldmBrightness);
   delay(2);
   Write_AT_Command("AT83=(0,0,EFGH9876)");
    delay(1000);
    
   keyIndex = 0x30;
  // clear Lumex display
    Write_AT_Command("ATd0=()");
    delay(10);
    
    // Use WiFiClient class to create TCP connections
//    WiFiClient client;
    const int httpPort = 123;
    
    if (!client.connect(host, httpPort)) {
        Serial.println("connection failed");
 ///       return;
    } else {
      Serial.println("connected to server");
    }
       
 Write_AT_Command("ATd0=()");
  delay(100); 
 Write_AT_Command(ldmCmdHdr); 
  delay(100);  
 Write_AT_Command(ldmCmd); 
  delay(100);    
Write_AT_Command(ldmCmdMsg5);
  delay(100);
Write_AT_Command(ldmCmdMsg6); 

  delay(1000);  

// init utc hr buffer

      for ( i = 0; i < 9; i ++ ) {
        utc_hr_buff[i] = 0x00;
        
      }
     
}

int value = 0;

void loop()
{
//    delay(5000);
//    ++value;

//    Serial.print("connecting to ");
 //   Serial.println(host);
 
  float flat, flon;
  int temp;
  unsigned char ones, tens, resultant;
  char c, d;
  unsigned long age, date, time, chars = 0;
  unsigned short sentences = 0, failed = 0;
  static const double LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
  static unsigned char counter = 0;
   static unsigned char arrayIndex = 0;
  static bool start_counter = false;
  static bool new_data = false;
  static bool switch_msg = false;
  
  newData = false;
  counter = 0;
  
  // if there are incoming bytes available
  // from the server, read them and print them:
  while (client.available()) {
    c = client.read();
//    d = c;
//    gps.encode(c);   

//    if ( c == '$' )
//       if ( c == 0x24 || c == 0x5A )
//       if ( c == 0x5A )
//       {
 ///      ldmCmd1[10] = c;
//       Serial.write(c);      // print vs. write here...
//       newData = true;
 //      }
 //      if (newData) {

 //       if (counter < 10 && c != 0x5A )
 //       Serial.write(c);   

 //       counter++;
 //      }
   
//    if (gps.encode(c))
//    {
//      newData = true;
//    }
       if ( c == 'A' )
        {
          start_counter = true;
          new_data = true;
        }
        if ( start_counter )
        {
          counter++;          

             switch ( counter )
             {
                  case 3:
                  arrayIndex = 14;
                  ldmCmd[arrayIndex] = 0x20; 
                  arrayIndex = 15;
                  ldmCmd[arrayIndex] = c;               // correctiom here
                  utc_hr_buff[7] = c;
//                  tens = c - 0x30;
                  tens = c;
                  break;
              
                  case 4:
                  arrayIndex = 16;
                  ldmCmd[arrayIndex] = c;               // correction here
                  // utc_hr_buff[8] = c;
                  // utc_hr_buff[9] = 0x00;
                  ones = c - 0x30;
//                  ones = c - 0x37;

                  switch ( tens )                     // needs to be fast and easily computed - maybe a LUT type of fix also...
                  {
                      case 0x30:

                                switch ( ldmCmd[16] )
                                {

                                     case 0x30:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x37; 
                                     break;

                                     case 0x31:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x38; 
                                     break;  
                                                                        
                                     case 0x32:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x39; 
                                     break;   
                                                                       
                                     case 0x33:
                                     ldmCmd[15] = 0x32;
                                     ldmCmd[16] = 0x30; 
                                     break;  
                                                                        
                                     case 0x34:                                   
                                     ldmCmd[15] = 0x32;
                                     ldmCmd[16] = 0x31; 
                                     break;   
                                                                       
                                     case 0x35:
                                     ldmCmd[15] = 0x32;
                                     ldmCmd[16] = 0x32; 
                                     break;

                                     case 0x36:
                                     ldmCmd[15] = 0x32;
                                     ldmCmd[16] = 0x33; 
                                     break;  
                                                                        
                                     case 0x37:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x30; 
                                     break;   
                                                                       
                                     case 0x38:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x31; 
                                     break;  
                                                                        
                                     case 0x39:                                   
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x32; 
                                     break;             
                                     
                                      default: 
                                      break;                                  
                                }
                      break;

                      case 0x31:
                                switch ( ldmCmd[16] )
                                {

                                     case 0x30:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x33; 
                                     break;

                                     case 0x31:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x34; 
                                     break;  
                                                                        
                                     case 0x32:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x35; 
                                     break;   
                                                                       
                                     case 0x33:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x36; 
                                     break;  
                                                                        
                                     case 0x34:                                   
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x37; 
                                     break;   
                                                                       
                                     case 0x35:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x38; 
                                     break;

                                     case 0x36:
                                     ldmCmd[15] = 0x30;
                                     ldmCmd[16] = 0x39; 
                                     break;  
                                                                        
                                     case 0x37:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x30; 
                                     break;   
                                                                       
                                     case 0x38:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x31; 
                                     break;  
                                                                        
                                     case 0x39:                                   
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x32; 
                                     break;             
                                     
                                      default: 
                                      break;                                  
                                }              
                      break;

                      case 0x32:
                                switch ( ldmCmd[16] )
                                {

                                     case 0x30:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x33; 
                                     break;

                                     case 0x31:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x34; 
                                     break;  
                                                                        
                                     case 0x32:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x35; 
                                     break;   
                                                                       
                                     case 0x33:
                                     ldmCmd[15] = 0x31;
                                     ldmCmd[16] = 0x36; 
                                     break;  

                                     default:
                                     break;

                                }                
                      break;              

                        default:
                        break;                    
                  }

                  break;
                  
                  case 5:
                  arrayIndex = 18;
                  ldmCmd[arrayIndex] = c;
                  break;
                  
                  case 6:
                  arrayIndex = 19;
                  ldmCmd[arrayIndex] = c;
                  break;
                  
                  case 7:
                  arrayIndex = 21;
                  ldmCmd[arrayIndex] = c;
                  break;
                  
                  case 8:
                  arrayIndex = 22;
                  ldmCmd[arrayIndex] = c;
                  start_counter = false;        // just doing seconds, not 1/10ths or 1/100rds... yet
                  if ( new_data ) {
#if 0                    
                  resultant = tens + ones;
                  // temp = atoi((const char*)utc_hr_buff);
                 
                  if ( resultant - UTC_OFFSET >= 0 ) {
                        resultant = resultant - UTC_OFFSET;
                  } else {
                    resultant = resultant - UTC_OFFSET + 24;                    
                  }
//                   Serial.print(resultant);
//                   delay(1);
                  itoa(resultant, (char *)utc_hr_buff, 10);
                  ldmCmd[15] = utc_hr_buff[7];
                  ldmCmd[16] = utc_hr_buff[8];
//                  Serial.write(ldmCmd[15]);
                  delay(1);
#endif                  
//                  Serial.write(ldmCmd[16]); 
//                  delay(1); 
                  Write_AT_Command(ldmCmd);
//                  delay(1);
                  new_data = false;
                  counter = 0;
 //                 if ( ldmCmd[14] = 0x38 )
 #if 0
                  if ( ldmCmd[17] = 0x39 )
                  {
                    Write_AT_Command(ldmCmdMsg3);
                    Write_AT_Command(ldmCmdMsg4);

                  }
#endif                  
                  }          
                  
                 
                  break;
                  
               default: 
                  arrayIndex = 14;
///               ldmCmd[arrayIndex] = 0x2a;               
                 break;              
             }      
    
        }
  
#if 0  
     if ( !start_counter )
      {
       if ( !switch_msg )
       {
      Write_AT_Command(ldmCmdMsg3);
      delay(1);
       Write_AT_Command(ldmCmdMsg4);
      delay(1); 
      switch_msg = true;
       }
       if ( switch_msg )
       {
     Write_AT_Command(ldmCmdMsg1);
      delay(1);
       Write_AT_Command(ldmCmdMsg2);
      delay(1); 
      switch_msg = true;

       }
       }
  
      
#endif      
 }
  
/*
  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting from server.");
    client.stop();

    // do nothing forevermore:
    while (true);
  }
  */
/*  
  if (gps.time.isUpdated())
  {
    Serial.print(F("TIME       Fix Age="));
    Serial.print(gps.time.age());
    Serial.print(F("ms Raw="));
    Serial.print(gps.time.value());
    Serial.print(F(" Hour="));
    Serial.print(gps.time.hour());
    Serial.print(F(" Minute="));
    Serial.print(gps.time.minute());
    Serial.print(F(" Second="));
    Serial.print(gps.time.second());
    Serial.print(F(" Hundredths="));
    Serial.println(gps.time.centisecond());
  }
  */
//  if (newData)
//  {
//    print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
//  print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
 //   gps.f_get_position(&flat, &flon, &age);
//  print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
//  print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
//  print_int(age, TinyGPS::GPS_INVALID_AGE, 5);

//    print_date(gps);
    
//gps.stats(&chars, &sentences, &failed);
//print_int(chars, 0xFFFFFFFF, 6);
//print_int(sentences, 0xFFFFFFFF, 10);
//print_int(failed, 0xFFFFFFFF, 9);

//  gps.stats(&chars, &sentences, &failed);
//  Serial.print(" CHARS=");
//  Serial.print(chars);
//  Serial.print(" SENTENCES=");
//  Serial.print(sentences);
//  Serial.print(" CSUM ERR=");
//  Serial.println(failed);
//  if (chars == 0)
//    Serial.println("** No characters received from GPS: check wiring **");
//   Serial.println();

//  if (gps.time.isUpdated())
//  Serial.println(gps.time.value()); 
//  delay(1);

//  }
 
// Serial.print(".");
// smartdelay(500);
// Serial.println("\n");
   delay(450);
   
}  // end main loop()

/*
    // We now create a URI for the request
    String url = "/input/";
    url += streamId;
    url += "?private_key=";
    url += privateKey;
    url += "&value=";
    url += value;

    Serial.print("Requesting URL: ");
    Serial.println(url);

    // This will send the request to the server
    client.print(String("GET ") + url + " HTTP/1.1\r\n" +
                 "Host: " + host + "\r\n" +
                 "Connection: close\r\n\r\n");
    unsigned long timeout = millis();
    while (client.available() == 0) {
        if (millis() - timeout > 5000) {
            Serial.println(">>> Client Timeout !");
            client.stop();
            return;
        }
    }

    // Read all the lines of the reply from server and print them to Serial
    while(client.available()) {
        String line = client.readStringUntil('\r');
        Serial.print(line);
    }

    Serial.println();
    Serial.println("closing connection");
}
*/

static void Write_AT_Command(char *string)
{
  HuzzahSerial.print(string);
  while (HuzzahSerial.read() != 'E') {}
  delay(2);
}
