/* 
// Sakul http://wwww.sakul.cz SakulRaider@seznam.cz
// 2014 Program Odectu z elektromeru
// verze programu 1.0

// Dořešit: 

*/

#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <EtherCard.h>

// Inicializace displeje a nastaveni (RS-4, E-5, D4-9, D5-6, D6-17, D7-7)
 LiquidCrystal lcd(4, 5, 9, 6, 17, 7);

// ---------------------------------------------------------------------------------------------------------
 
// Nezapomeň zadat unikátní MAC adresu pro Ethernetový modul !!!
static byte mymac[] = { 0x00,0x0c,0x55,0x55,0xdb,0x2c };         // (MAC až db:32)
byte Ethernet::buffer[600];
char website[] PROGMEM = "www.arduino.sakul.cz";                     // Adresa kam se data odesílají

// ---------------------------------------------------------------------------------------------------------

int analogPin = 0;                         
int ADrd;                                  
int ADrdMin = 500;                         
int ADrdMax = 1000;                        
int elektromerH = 0;                       
int elektromerL = 0;                       
int pulzy;                                 
int delicka;                               
int chyby = 0;                             
int chybyBUF;                              
char KWh[10];                              
char mekovka[16];                          
unsigned long timer1;                      
unsigned long time;                        
unsigned long time1;                       
unsigned long  interval = 3600000;         // Interval zasílání hodnot do databáze na webu (1 za hodinu = 3 600 000) (20000=20sekund)
boolean Podpeti = false;                   
boolean NazElektComplete = false;          

String NazElekt = "Elektomer-001";         // Název elektromeru NUTNO ZADAT JESTE DALE V PROGRAMU !!!
String firmware = " firmware 1.0";         
String web = "www.sakul.cz";               // Info o mé webové stránce

// Registry pro práci s EEPROM
byte byte1H=0;                             
byte byte2H=0;
byte byte1L=0;
byte byte2L=0;
byte byte1pulzy=0;
byte byte2pulzy=0;
int adresa=0;                              

// Definice Vstupů
const int Tlac = 3;                        
const int Jumper1 = 18;                    
const int Jumper2 = 19;                    
const int InEther = 16;                    
const int LED3 = 15;                       
int TlacState = 0;                         
int Jumper1State = 0;                      
int Jumper2State = 0;                      
int InEtherState = 0;                      




void setup () {
  chybyBUF = 0;                             
  chyby = 0;                                
  NazElekt.reserve(16);                     
  Serial.begin(38400);                      
  pinMode(LED3, OUTPUT);                    
  pinMode(InEther, OUTPUT);                 
  digitalWrite(LED3,LOW);                   
  pinMode(Tlac, INPUT_PULLUP);              
  pinMode(Jumper1, INPUT_PULLUP);           
  pinMode(Jumper2, INPUT_PULLUP);           
  attachInterrupt(0,preruseni, FALLING);    
//  attachInterrupt(1,ResetEther, FALLING);    
 
  lcd.begin(16, 2);                           
  lcd.clear();  
  // Vymazání všech uložených hodnot
  TlacState = digitalRead(Tlac);              
  if (TlacState == false){
    lcd.clear();                              
    lcd.setCursor (0,0);                       
    lcd.print("Podrz tlacitko:");
    lcd.setCursor (0,1);
    lcd.print ("MAZU hodnoty !!!");
    delay(5000);
  }
  TlacState = digitalRead(Tlac);
  if (TlacState == false){
     EEPROM.write(adresa, byte1H);              
     EEPROM.write(adresa + 1, byte2H);
     EEPROM.write(adresa + 2, byte1L);
     EEPROM.write(adresa + 3, byte2L);
     EEPROM.write(adresa + 4, byte1pulzy);
     EEPROM.write(adresa + 5, byte2pulzy);
     adresa = 0;
     lcd.clear();                              
     lcd.setCursor (0,0);                       
     lcd.print("Hodnoty smazany");
     lcd.setCursor (0,1);
     lcd.print ("Uvolni tlacitko");
     delay (5000);
     }
     
  lcd.clear();                              
  lcd.setCursor (2,0);                          
  lcd.print("Cekam na DHCP");
  lcd.setCursor (3,2);
  lcd.print ("CEKEJTE...");
     
  // Načtení všech hodnot z EEPROM 
  byte1H = EEPROM.read(adresa);                
  byte2H = EEPROM.read(adresa + 1);
  byte1L = EEPROM.read(adresa + 2);
  byte2L = EEPROM.read(adresa + 3);
  byte1pulzy = EEPROM.read(adresa + 4);
  byte2pulzy = EEPROM.read(adresa + 5);
  adresa = 0;                                           
  elektromerH = byte1H + (byte2H << 8);                 
  elektromerL = byte1L + (byte2L << 8);
  pulzy = byte1pulzy + (byte2pulzy << 8);
  
  // Zjištění a nastavení dělícího poměru
  Jumper1State = digitalRead(Jumper1);
  Jumper2State = digitalRead(Jumper2);
   if (Jumper1State == false){delicka = 2000;}         
   else if (Jumper2State == false){delicka = 1000;}      
     else {delicka = 800;}                             

// ----------------------------------------------------------------------------------------------------------------------- 

 // Konfigurace Ethernetu
  Serial.println("\n[webClient]");

  if (ether.begin(sizeof Ethernet::buffer, mymac) == 0){
     delay (5);
  Serial.println( "Failed to access Ethernet controller");
  lcd.clear();                                         
  lcd.setCursor (0,0);                   
  lcd.print("CHYBA na Modulu:");
  lcd.setCursor (2,2);
  lcd.print ("Ethernetu !!");
  delay (5000);
   }
  if (!ether.dhcpSetup()){
     digitalWrite(InEther,HIGH);                       
     Serial.println("DHCP failed");
     lcd.clear();                                     
     lcd.setCursor (2,0);                   
     lcd.print("ERROR DHCP !!");
     lcd.setCursor (4,2);
     lcd.print ("Zadna IP");
     delay (5000);
   }

  ether.printIp("IP:  ", ether.myip);
  ether.printIp("GW:  ", ether.gwip);  
  ether.printIp("DNS: ", ether.dnsip);
  sprintf(mekovka, "%02X%02X%02X%02X%02X%02X", mymac[0],mymac[1],mymac[2],mymac[3],mymac[4],mymac[5]); 
  Serial.print ("MAC: ");
  Serial.println (mekovka);

  if (!ether.dnsLookup(website))
    delay (5);
    Serial.println("DNS failed");
    
  ether.printIp("SRV: ", ether.hisip);
// ----------------------------------------------------------------------------------------------------------------------- 
}

//::::::::::::::::::::::: Konec SETUPU ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

void loop () {
 
   if (chyby >= 2){                                 
       lcd.clear();                                 
       lcd.setCursor (1,0);                   
       lcd.print("Data Odeslana:");
       lcd.setCursor (2,1);
       lcd.print ("NEUSPESNE!!!");
       digitalWrite(LED3,HIGH);                     
       delay(6000);
       chyby = 0;      
   }
   
   if (chybyBUF >= 3){                              
      setup();
     
   }

 // ---------------------------------------------------------------------------------------------------------------------- 
   ether.packetLoop(ether.packetReceive());
 
   char queryString[128] = {0};
    sprintf(queryString, "&kwh=%05d%04d", elektromerH, elektromerL);      
    
   if (millis() > timer1) {                                               
     timer1 = millis() + interval;
     Serial.println();
     Serial.print("<<< ZACATEK PRENOSU ");
     ether.browseUrl(PSTR("/add_data.php?elektromer=Elektromer-001"), queryString, website, my_callback); 
     lcd.clear(); 
     lcd.setCursor (0,0);                                                 
     lcd.print("Odesilam data...");
     lcd.setCursor (3,1);
     lcd.print ("CEKEJTE...");
     delay(3000);
     chyby ++;
     chybyBUF ++;     
  }
 // ---------------------------------------------------------------------------------------------------------------------- 
 
 ADrd = analogRead (analogPin);              

 if (micros() - time >= 1000000) {            
  lcd.clear();                                
  lcd.setCursor (0,0);                        
  lcd.print("U=");
  if (ADrd <= ADrdMin){lcd.print ("Min");}             
    else if (ADrd >= ADrdMax){lcd.print ("Max");}      
       else {lcd.print (ADrd);};                       
  lcd.print("P=");
  lcd.print (pulzy);
  lcd.print("/");
  lcd.print (delicka);
  sprintf(KWh, "%05d%04d", elektromerH, elektromerL);    
  lcd.setCursor (0,2);
  lcd.print("KWh = ");
  lcd.print (KWh);
  time = micros();  
  }

  if (ADrd <= ADrdMin){                     
     if (Podpeti == false){                 
     byte1H = elektromerH;                  
     byte2H = elektromerH >> 8;
     byte1L = elektromerL;                   
     byte2L = elektromerL >> 8;
     byte1pulzy = pulzy;                     
     byte2pulzy = pulzy >> 8;   
     EEPROM.write(adresa, byte1H);
     EEPROM.write(adresa + 1, byte2H);
     EEPROM.write(adresa + 2, byte1L);
     EEPROM.write(adresa + 3, byte2L);
     EEPROM.write(adresa + 4, byte1pulzy);
     EEPROM.write(adresa + 5, byte2pulzy);
     adresa = 0;
     Podpeti = true;                         
    }
  }      
  
  TlacState = digitalRead(Tlac);            
  if (TlacState == false){
     info();
     }
    
 // Ukládání dat do EEPROM každý den
 if (millis() - time1 >= 86400000) {          // Uložit stav elektroměru každých 24hodin (86400000)
    ulozData();
    setup();                                 
    }  
  
}

//::::::::::::::::::::::::::: Konec Hlavního programu :::::::::::::::::::::::::::::::::::::::::::::::::::::::::

void preruseni(){                            
     pulzy ++;
     
   if (pulzy >= delicka){                    
     elektromerL ++;                         
     pulzy = 0;
     }
     if (elektromerL >= 10000){              
      elektromerH ++;
      elektromerL = 0;
      }   
        if (elektromerL >= 32760){          
        elektromerH = 0;
        }
 }

void info(){                                 
  lcd.begin(16, 2);                         
  lcd.clear(); 
  lcd.setCursor (2,0);                   
  lcd.print(web);
  lcd.setCursor (1,2);
  lcd.print (firmware);
  delay(5000);                               
  lcd.clear();                               
  lcd.setCursor (0,0);                   
  lcd.print("Naz. elektromeru");             
  lcd.setCursor (1,2);
  lcd.print (NazElekt);
  delay(5000);
  lcd.clear();                               
  lcd.setCursor (0,0);                   
  lcd.print(ether.myip[0]);                  
  lcd.print('.');
  lcd.print(ether.myip[1]);
  lcd.print('.');
  lcd.print(ether.myip[2]);
  lcd.print('.');
  lcd.print(ether.myip[3]); 
  lcd.setCursor (0,1);
  lcd.print("MAC:");
  lcd.setCursor (4,1);
  lcd.print (mekovka);                         
  delay(9000);
}

void ulozData(){                            
  lcd.begin(16, 2);                         
  lcd.clear(); 
  lcd.setCursor (0,0);                   
  lcd.print("UKLADAM DATA !!!");
  lcd.setCursor (3,2);
  lcd.print ("CEKEJTE...");
  delay(3000);
     byte1H = elektromerH;                  
     byte2H = elektromerH >> 8;
     byte1L = elektromerL;                   
     byte2L = elektromerL >> 8;
     byte1pulzy = pulzy;                     
     byte2pulzy = pulzy >> 8;   
     EEPROM.write(adresa, byte1H);
     EEPROM.write(adresa + 1, byte2H);
     EEPROM.write(adresa + 2, byte1L);
     EEPROM.write(adresa + 3, byte2L);
     EEPROM.write(adresa + 4, byte1pulzy);
     EEPROM.write(adresa + 5, byte2pulzy);
     adresa = 0;                              
  lcd.clear(); 
  lcd.setCursor (2,0);                   
  lcd.print("DATA ULOZENA");
  lcd.setCursor (0,2);
  lcd.print (" ");
  delay(3000);     
  Podpeti = false;                           
  time1 = millis(); 
}

// called when the client request is complete
static void my_callback (byte status, word off, word len) {
  Serial.println(">>>");
  Ethernet::buffer[off+300] = 0;
  Serial.println((const char*) Ethernet::buffer + off);
  Serial.println("<<< KONEC >>>");
  lcd.clear();                                 
  lcd.setCursor (1,0);                   
  lcd.print("Data Odeslana:");
  lcd.setCursor (4,1);
  lcd.print ("USPESNE");
  digitalWrite(LED3,LOW);                     
  digitalWrite(InEther,LOW);                  
  delay(3000);
  chyby = 0;
  chybyBUF = 0;
}
