
//  -------------------------------------------------------------------------------------------------------------------------
//  |*                                                                                                                     *|
//  |                /////////////////////////////** CHYTRA ZASUVKA BY TOMAS CHALUPA **\\\\\\\\\\\\\\\\\\\\\\\\\\\\         | 
//  |                 ////////////////////////////////// * BAKALARSKA PRACE * \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\          |
//  |                  ///////////////////////////////// * VUT FSI 2020/21 * \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\           |
//  |*                                                                                                                     *|
//  -------------------------------------------------------------------------------------------------------------------------


// ** Seznam pouzitych knihoven s popisem jejich funkcnosti ** 
     
#include <MySQL_Generic_WiFi.h>       // Umoznuje primou komunikaci s MySQL databazi prostrednictvym SQL prikazu.
                                      // Vychazi z knihovny "MySQL Connector" od autora Dr. Charles Bell, ale je upravena 
                                      // tak, aby pracovala na vice platformach (hlavne ESP32). Tuto upravu provedl autor Khoi Hoang.
#include "Chytra_zasuvka_Pristup.h"   // V tomto hlavickovem souboru jsou ulozeny pristupove udaje k databazi 
                                      // a k lokalni WiFi siti, pres kterou se pripojuje.
                                      
#include <PZEM004Tv30.h>              // Zajistuje komunikaci mezi mikrokontrolerem a mericim modulem PZEM-004T v.3, umoznuje
                                      // cist informace o napeti, proudu, spotrebe elektricke energie atd.
                                      // Autor: Jakub Mandula
                                      
#include <SPI.h>                      // SPI - seriove periferni rozhrani, pro RFID ctecku, puvodni Arduino knihovna.
#include <MFRC522.h>                  // Zajistuje cteni dat z RFID prvku, na jejim vyvoji se podilelo vice autoru - 
                                      // Dr.Leong, Miguel Balboa, Søren Thing Andersen, Tom Clement ...
#include <Wire.h>                     // I2C - zajistuje komunikaci pres tento typ sbernice, jedna se o puvodni Arduino knihovnu


#include "timer.h"                    // Knihovna, ktera nabizi nekolik uzitecnych casovacu, ktere jsou realizovany softwarove.
                                      // Z techto casovacu jsou nasledne volany funkce, ktere se v nastaveny cas provedou.
                                      // Autor: Bruno Calou Alves
#include <Tone32.h>                   // Umoznuje generovani tonu se zadanymi vlastnostmi

// ** Definice dulezitych pinu pro ESP32 **  

#define SS_PIN 21                     // Slave Select pin, slouzi pro ctecku MFRC522
#define RST_PIN 22                    // Reset pin, slouzi pro ctecku MFRC522
#define RELE_PIN 13                   // Pin pro ovladani rele modulu, ma opacnou logiku: HIGH = rozepnuto, LOW = sepnuto 
#define modra  25                     // Piny
#define zelena  26                    // pro ovladani
#define cervena  27                   // RGB modulu


// ** Deklarace globalnich prommennych **  

String Kredit;                        // Do teto promenne se ulozi hodnota kreditu z databaze
String UID_karty = "";                // Unique IDentifier, obsahuje unikatni kod, nacteny z RFID prvku
String Pristup = "ZAMITNUT";          // Informace o pristupu ziskana z databaze, pri spusteni programu je pristup zamitnut
bool Karta_nactena = false;           // Dvoustavova promena, zamezuje vycenasobnemu nacteni UID z karty v okamziku cteni dat
float Napeti;                         // Hodnota napeti ve Voltech s presnosti na 1 desetinu
float Proud;                          // Hodnota proudu v Amperech s presnosti na 3 setiny
float Prikon;                         // Hodnota prikonu ve Watech s presnosti na 1 desetinu
float Ucinik;                         // Hodnota uciniku (bezrozmerne) s presnosti na 2 desetiny
float Frekvence;                      // Hodnota frekvence v Hertzich s presnosti na 1 desetinu
float Spotreba;                       // Hodnota spotreby el. energie v kiloWatt hodinach s presnosti na 1 desetinu
int Citac = 0;                        // Hodnota pomocneho citace, ktery pocita pocet provedenych iteraci


// ** Vytvoreni instanci pro jednotlive tridy **  

Timer casovac1;                                 // Pro prvni casovac
Timer casovac2;                                 // Pro druhy casovac
MySQL_Connection conn((Client *)&client);       // Pro pripojeni k databazi
MySQL_Query SQL_prikaz = MySQL_Query(&conn);    // Pro SQL prikazy
MFRC522 mfrc522(SS_PIN, RST_PIN);               // Pro RFID ctecku
PZEM004Tv30 pzem(&Serial2);                     // Pro merici modul PZEM-004T


// ** Deklarace funkci pouzitych v programu **  

void Vlozeni_do_Databaze(String Vlozit);
String Cteni_z_Databaze(String Cist);
void Mereni();
void Odeslani_namerenych_hodnot();
void Odeslani_spotreby();
void Vypadek_nabijeni();


//-----------------------------------------------------------------------------------------------------------------------------*

// ** Nasledujici funkce "setup" se provedou pouze jednou, a to pri kazdem novem spusteni programu **  

void setup() {

  // Nastaveni definovanych pinu jako vystupy
  pinMode(RELE_PIN, OUTPUT);
  pinMode(modra, OUTPUT);
  pinMode(zelena, OUTPUT);
  pinMode(cervena, OUTPUT); 

  // Pro jistotu se pri kazdem spusteni nastavi vsechny ovladane vystupy na logickou 0 (doje k jejich odpojeni od napajeni)
  digitalWrite(RELE_PIN, HIGH);
  digitalWrite(modra, LOW);
  digitalWrite(zelena, LOW);
  digitalWrite(cervena, LOW); 
  
  // Nasleduje nastaveni funkce SW casovace
  casovac1.setInterval(2000);           // Casovy interval (v ms), po jehoz uplynuti se provede nejaka akce
  casovac1.setCallback(Mereni);         // Touto akci je mereni hodnot z modulu PZEM-004T a to kazde 2 sekundy

  casovac2.setInterval(30000);
  casovac2.setCallback(Odeslani_namerenych_hodnot);   // Dalsi akci je odeslani namerenych hodnot do databaze a to kazdych 30 sekund


  Serial.begin(115200);               // Spusteni seriove komunikace mezi ESP32 a PC pres rozhrani USB, cislo oznacuje tzv. baudrate
                                      // Tato komunikace je vhodna hlavne pri ladeni programu, jelikoz umoznuje vypisovat aktualne provadene operace
                                      // Pri zavadeni do provozu se odstrani kvuli ulehceni pameti
  SPI.begin();                        // Inicializace SPI sbernice
  mfrc522.PCD_Init();                 // Inicializace RFID ctecky MFRC522 
   
  
  while (!Serial);                    // Jakmile je pripravena komunikace pres seriovou linku


  // ** Vytvoreni pripojeni ESP32 k siti WiFi **
  
  Serial.println(String("Pripojovani k siti ") + ssid);       // Informace o pripojeni
  digitalWrite(modra, HIGH);                                  // Rozsviceni modre indikacni LED
  WiFi.begin(ssid, pass);                                     // Zahajeni procesu pripojovani k siti
  
  while (WiFi.status() != WL_CONNECTED) {                     // Provadi se dokud se nepripoji
    delay(500);
    Serial.print(".");                                        // Vypise prubeh pripojovani (loading)
  }

  // Vypisou se informace o siti, ke ktere se ESP32 uspesne pripojilo
  Serial.print("Pripojeno k siti s IP adresou: ");
  Serial.println(WiFi.localIP());


  // ** Pripojeni ESP32 k MySQL databazi **
  conn.close();      // Vymaze se posledni pripojeni k databazi
  // Informace o databazi, ke ktere se chceme pripojit
  Serial.print("Pripojovani k databazi: ");                
  Serial.print(server_addr);
  Serial.println(String(", Port = ") + server_port);
  Serial.println(String("Uzivatel = ") + user + String(", Heslo = ") + password + String(", Databaze = ") + String("freedbtech_chytra_zasuvka"));

  // Nasledujici prikaz se vykonava opakovane, dokud nedojde k pripojeni k databazi
  while(conn.connectNonBlocking(server_addr, server_port, user, password) == RESULT_FAIL);
    
  Vypadek_nabijeni();                               // Zjisti se, zda pri poslednim pouziti chytre zasuvky nedoslo k vypadku el. proudu
  
  // Pripojeni k databazi bylo navazano
  digitalWrite(modra, LOW);                         // muzeme zhasnout modrou indikacni LED
  
  // Zobrazeni vyzvy k prilozeni karty
  Serial.println("Prilozte kartu ke ctecce...");
  Serial.println();

  
}

//-----------------------------------------------------------------------------------------------------------------------------*

// ** Nasledujici hlavni funkce "loop" se provadi jiz opakovane - v nekonecne smycce ** 

void loop() {

// ** Nasledujici cyklus se provadi opakovane, az to az do te doby, dokud uzivatel neprilozi ke ctecce spravny RFID prvek **

   
while(Pristup == "ZAMITNUT"){
  digitalWrite(zelena, HIGH);                       // Pokud neni prilozena karta, sviti zelena indikacni LED kontinualne
  
  //** Cteni RFID karty prilozene ke ctecce **
  // Nasledujici cyklus ceka, az se v dosahu anteny RFID ctecky neobjevi nejaky RFID prvek
  if ( ! mfrc522.PICC_IsNewCardPresent()){
    return;
  }

  // Pokud se objevil, nactou se jeho data
  if ( ! mfrc522.PICC_ReadCardSerial()){
       return;
  }

  // Tato podminka pres booleovskou promennou "Karta_nactena" zamezi nasobnemu precteni dat ze stejneho RFID prvku
  if(Karta_nactena==false){
     tone(14, 2500, 100, 0); 
     UID_karty = "";                                            // Vymaze predchozi ulozeny UID kod     
     for (int i = 0; i < mfrc522.uid.size; i++){                // Z nactenych dat se vybere pouze urcita cast,
     UID_karty.concat(String(mfrc522.uid.uidByte[i], HEX));     // ktera zavisi na jejich velikosti a ulozi do promenne
     }
     
     UID_karty.toUpperCase();                                   // Prevede text na velka pismena
     UID_karty = String(UID_karty);                             // a ulozi do stejne promenne
     Serial.print("UID karty: ");
     Serial.println(UID_karty);                                 // Vypise UID
     Karta_nactena = true;                                      // Touto zmenou stavu se zamezi opetovnemu cteni dat
     digitalWrite(zelena, LOW);                                 // Indikuje, ze prilozena karta byla nactena
  }

    
  digitalWrite(modra, HIGH);                // Indikuje, ze se ESP32 pripojuje k online databazi


  //** Nasleduje nahrani UID kodu z karty do databaze, ktera ho nasledne zpracuje
  // Jedna se o SQL prikaz v tomto zneni-> Vlozit do NAZEV_DATABAZE.NAZEV_TABULKY (NAZEV_SLOUPCE) hodnoty (UID prave nactene karty)
  Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Historie_pristupu (UID_karty) VALUES ('" + UID_karty + "')");

  
  //** Po zpracovani, se v poslednim radku tabulky objevi stav o pristupu, a to bud "POVOLEN" nebo "ZAMITNUT" a prave tento stav precte nasledujici funkce
  // Jedna se o SQL prikaz v tomto zneni-> Vybrat hodnotu (text) z NAZEV_DATABAZE.NAZEV_TABULKY seradit dle sloupce "Poradi" od nejvyssiho = nejnovejsiho
  Pristup = Cteni_z_Databaze("SELECT Pristup FROM freedbtech_chytra_zasuvka.Historie_pristupu ORDER BY Poradi DESC LIMIT 1");
  

  digitalWrite(modra, LOW);                   // Indikuje, ze uz ESP32 neni pripojen k online databazi
 
        
  if(Pristup == "POVOLEN"){                     // Pokud je text obdrzeny z databaze shodny, je uzivatel overen a muze zacit nabijet spotrebic
      Serial.println("Karta overena");        // Informativni hlaska
      digitalWrite(RELE_PIN, LOW);            // Sepnutim rele se privede napeti do zasuvky
      digitalWrite(zelena, HIGH);             // Oznacuje uspesne overeni uzivatele
      tone(14, 2000, 100, 0); 
      delay(100);
      tone(14, 1500, 100, 0);      
      Serial.println("Zasuvka je aktivni");   // Informativni hlaska
      pzem.resetEnergy(); 
      
  //** Stazeni kreditu z databaze **
  // Jedna se o SQL prikaz v tomto zneni -> Vyber hodnotu pole Kreditu z NAZEV_DATABAZE.NAZEV_TABULKY kde se Uzivatelske_cislo shoduje s poslednim zaznamenanym uzivatelskym cislem od posledniho uzivatele (ten ktery pred chvilkou prilozil kartu)
  Kredit = Cteni_z_Databaze("SELECT Kredit FROM freedbtech_chytra_zasuvka.Seznam_uzivatelu WHERE Uzivatelske_cislo = (SELECT Cislo_uzivatele FROM freedbtech_chytra_zasuvka.Historie_pristupu ORDER BY Poradi DESC LIMIT 1)");
  Serial.print("Aktualni kredit uzivatele: ");
  Serial.println(Kredit);
         
  casovac1.start();                     // Spusteni casovace cislo 1
  casovac2.start();                     // Spusteni casovace cislo 2
              
  }else{                                      // Pokud text obdrzeny z databaze neni shodny, neni zasuvka aktivni a nelze tedy spotrebice nabijet
      Serial.println("Neznama karta");        // Informativni hlaska
      digitalWrite(RELE_PIN, HIGH);           // Pro jistotu rozepne rele (melo by byt z predchoziho nastaveni)
      digitalWrite(cervena, HIGH);            // Informativni cervena LED oznacuje neznameho uzivatele nebo nedostatek kreditu
      tone(14, 2300, 100, 0); 
      delay(100);
      tone(14, 2000, 100, 0);      
      delay(3000);                            // Pauza 3 sekundy pred prilozenim dalsi karty
      digitalWrite(cervena, LOW);             // Zhasne cervenou LED, a opet se rozsviti zelena - chytra zasuvka je pripravena
      // Informativni hlaska pro seriovou komunikaci
      Serial.println("Prilozte kartu ke ctecce...");
      Serial.println();                  
  }
    
    // Tento prikaz umoznuje znovu nacist kartu
    Karta_nactena = false;                             
 
}   // Konec cyklu, ktery pracuje s RFID prvkem



  //** Zahajeni procesu nabijeni **
  // Nasledujici cyklus se provadi dokud jsou splneny podminky, pokud ne, nabijeni se ukonci a chytra zasuvka se uzamkne
  // Podminky: 1. Po dobu asi 6 sekund je proud tekouci zatezi nulovy - spotrebic odpojen nebo plne nabit, 2. Byla prekrocena hranice kreditu
  while(Pristup=="POVOLEN"){ 
             
      if(Citac==4 || String(Spotreba,3) == Kredit){  
      // Vypis informaci     
      Serial.println("Nabijeni dokonceno / spotrebic odpojen / Nedostatek kreditu");
      Serial.println("Zasuvka uzamcena");
      Serial.println();  
      // Zastaveni casovacu             
      casovac1.stop();                  
      casovac2.stop();  
      digitalWrite(RELE_PIN, HIGH);    // Rozepnuti rele = rozepnuti fazoveho vodice
      tone(14, 2200, 100, 0); 
      delay(100);
      tone(14, 2400, 100, 0);
      delay(100);
      tone(14, 2000, 100, 0);       
      Odeslani_spotreby();             // Odesle se namerna spotreba za toto nabijeni do online databaze
      Serial.println("Spotreba odeslana na server");
      delay(1000);                     // Kratka pauza
      digitalWrite(modra, LOW);        
      Citac=0;                         // Vynulovani citace
      pzem.resetEnergy();              // Resetovani pameti spotreby mericiho modulu
      Serial.println("Prilozte kartu ke ctecce...");
      Serial.println();       
      Pristup="ZAMITNUT";              // Timto prikazem dojde k ukonceni tohoto cyklu
      }else{                           // Pokud nejsou splneny vyse uvedene podminky, dojde k aktualizaci casovacu, ktera je nutna pro jejich provoz
      casovac1.update();
      casovac2.update();  
      }
          
  }
  // Opustenim predchoziho cyklu je chytra zasuvka opet pripravena k dalsimu pouziti
}

//-----------------------------------------------------------------------------------------------------------------------------*

                          //** Definice jednotlivych funkci pouzitych v tomto programu **

//** Funkce pro spusteni SQL prikazu pro vlozeni dat do databaze **  
void Vlozeni_do_Databaze(String Vlozit){
  
   if ( !SQL_prikaz.execute(Vlozit.c_str()) ){        // Pokud nedoslo k vlozeni, vypise chybove hlaseni
      Serial.println("Chyba pri vkladani dat");
      digitalWrite(modra, LOW);
      digitalWrite(cervena, HIGH);                    // Rozsviti varovnou LED
      tone(14, 1500, 2000, 0);                        // Varovny ton bzucaku a zaroven 2 vterinova pauza
      
      if ( !SQL_prikaz.execute(Vlozit.c_str()) ){     // Zkusi se po kratke pauze znovu odeslat data
         delay(1000);                                 // Pokud se i na podruhe nepodari dojde k restartu programu 
         ESP.restart();                               // a znovu navazani spojeni s WiFi siti nebo  databazi 
      }else{
         Serial.println("Data vlozena");              // Pokud se komunikace napodruhe podarila, pokracuje se dale
      }
      
   }else{    
      Serial.println("Data vlozena");                 // V opacnem pripade doslo k uspesnemu nahrani dat do databaze
   }
   
}

//** Funkce pro spusteni SQL prikazu pro ziskani dat z databaze **  
String Cteni_z_Databaze(String Cist){

  String Data = "";                                   // Promenna, do ktere jsou ulozena ziskana data
  
  row_values *row = NULL;                     

  if ( !SQL_prikaz.execute(Cist.c_str()) ){           // Spusteni samotneho prikazu a kontrola jeho provedeni
      Serial.println("Chyba pri cteni dat");
      digitalWrite(modra, LOW);
      digitalWrite(cervena, HIGH);                    // Rozsviti varovnou LED
      tone(14, 1500, 2000, 0);                        // Varovny ton bzucaku a zaroven 2 vterinova pauza
      if ( !SQL_prikaz.execute(Cist.c_str()) ){       // Zkusi se po kratke pauze znovu odeslat data
         delay(1000);                                 // Pokud se i na podruhe nepodari dojde k restartu programu 
         ESP.restart();                               // a znovu navazani spojeni s WiFi siti nebo  databazi                           
      }else{
         Serial.println("Data nactena");              // Pokud se komunikace napodruhe podarila, pokracuje se dale
      }  
  }else{
  Serial.println("Data nactena");
  
  // Nasledujici cast kodu upravi ziskana data z databaze
  
  column_names *columns = SQL_prikaz.get_columns();

  // Tento cyklus precte data z radku tabulky, v tomto programu se vzdy jedna pouze o jeden radek a jeden sloupec
  do {
    row = SQL_prikaz.get_next_row();
    
    if (row != NULL){
      Data = (row->values[0]);
    }
  }while (row != NULL);

  return Data;                                 // Navratovou hodnotou teto funkce jsou ziskana data z databaze

  SQL_prikaz.close();                          // Vymaze prikaz z pameti
  }
}


//** Funkce pro mereni hodnot pomoci modulu PZEM-004T v.3 **  
void Mereni() {

  digitalWrite(zelena, !digitalRead(zelena));                                   // Tato LEDka indikuje nabijeni, kazde 2 sekundy zmeni svuj stav

  Napeti = pzem.voltage();                                                      // Mereni napeti
  if(!isnan(Napeti)){
      Serial.print("Napeti: "); Serial.print(Napeti,1); Serial.println("V");
  } else {
      Serial.println("Chyba pri cteni napeti");
  }  
  if(Napeti>250){
  Citac++;  
  Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Chybovy_protokol (Popis, Druh) VALUES ('Prepeti v elektricke siti', 'Upozorneni')");    
  }
  if(Napeti<210){
  Citac++;  
  Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Chybovy_protokol (Popis, Druh) VALUES ('Podpeti v elektricke siti', 'Upozorneni')");    
  }

  Proud = pzem.current();                                                       // Mereni proudu
  if(!isnan(Proud)){
      Serial.print("Proud: "); Serial.print(Proud,3); Serial.println("A");
      if (Proud == 0){            // Pokud je hodnota proudu tekouciho zatezi nulova, inkrementuje se citac
      Citac++;
      }else{
      Citac=0;
      }
  } else {
      Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Chybovy_protokol (Popis, Druh) VALUES ('Chyba pri mereni pomoci modulu PZEM-004T', 'Chyba')");
      Serial.println("Chyba pri cteni proudu");
      Citac++;                    // Citac se inkrementuje i kdyz nebyla namerena zadna hodnota
  }  
  if(Proud>9){
      Citac++;
      Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Chybovy_protokol (Popis, Druh) VALUES ('Namereny proud se blizi maximalni hodnote', 'Upozorneni')");
  }
  
  Prikon = pzem.power();                                                         // Mereni Prikonu
  if(!isnan(Prikon)){
      Serial.print("Prikon: "); Serial.print(Prikon,1); Serial.println("W");
  } else {
      Serial.println("Chyba pri cteni prikonu");
  }

  Frekvence = pzem.frequency();                                                 // Mereni pfrekvence
  if(!isnan(Frekvence)){
      Serial.print("Frekvence: "); Serial.print(Frekvence, 1); Serial.println("Hz");
  } else {
      Serial.println("Chyba pri cteni frekvence");
  }

  Ucinik = pzem.pf();                                                            // Mereni uciniku
    if(!isnan(Ucinik)){
        Serial.print("Ucinik: "); Serial.println(Ucinik,2);
    } else {
      Serial.println("Chyba pri cteni uciniku");
    }  


  Spotreba = pzem.energy();                                                      // Mereni spotreby                                                       
   if(!isnan(Spotreba)){
        Serial.print("Spotreba el. energie: "); Serial.print(Spotreba,3); Serial.println("kWh");
    } else {
      Serial.println("Chyba pri cteni spotreby");
    }

}

//** Funkce pro odeslani namerenych hodnot do databaze, provede se kazdych 30 sekund **  
void Odeslani_namerenych_hodnot() {
  
  digitalWrite(modra, HIGH);                  // Indikuje komunikaci se serverem

    // Vlozeni vsech namerenych hodbot do databaze pomoci nasledujiciho SQL prikazu
    Vlozeni_do_Databaze("INSERT INTO freedbtech_chytra_zasuvka.Zaznam_nabijeni (Napeti, Proud, Prikon, Spotreba, Frekvence, Ucinik) VALUES ('" + String(Napeti,1) + "', '" + String(Proud,3) + "', '" + String(Prikon,1) + "', '" + String(Spotreba,3) + "', '" + String(Frekvence,1) + "', '" + String(Ucinik,2) + "')");
  
  digitalWrite(modra, LOW);
}

//** Funkce pro aktualizaci hodnot spotreby elektricke energie, provede po skonceni procesu nabijeni **
void Odeslani_spotreby() {
  
  digitalWrite(modra, HIGH);

  if ((Spotreba!=0) && (!isnan(Spotreba))){
  // Nasledujici SQL prikaz provede toto -> aktualizuje se NAZEV_DATABAZE.NAZEV_TABULKY a pricte se k dosavadni spotrebe prave namerena hodnota a tato hodnota se take odecte z kreditu, to se provede u konkretniho uzivatele, tj. posledni uzivatel, ktery prilozil kartu.
  Vlozeni_do_Databaze("UPDATE freedbtech_chytra_zasuvka.Seznam_uzivatelu SET Spotreba = Spotreba + ('" + String(Spotreba,3) + "'), Kredit = Kredit - ('" + String(Spotreba,3) + "') WHERE Uzivatelske_cislo = (SELECT Cislo_uzivatele FROM freedbtech_chytra_zasuvka.Historie_pristupu ORDER BY Poradi DESC LIMIT 1)");
  }
  digitalWrite(modra, LOW);

}

void Vypadek_nabijeni() {

  Spotreba = pzem.energy();
  
  if ((!isnan(Spotreba))&&(Spotreba!=0)){
  tone(14, 2500, 100, 0);             // Akusticka signalizace predchoziho vypadku
  Serial.println("Predchozi nedokoncene nabijeni se spotrebou:");
  Serial.println(Spotreba,3);
  // Nasledujici SQL prikaz provede toto -> aktualizuje se NAZEV_DATABAZE.NAZEV_TABULKY a pricte se k dosavadni spotrebe prave namerena hodnota a tato hodnota se take odecte z kreditu, to se provede u konkretniho uzivatele, tj. posledni uzivatel, ktery prilozil kartu.  
  Vlozeni_do_Databaze("UPDATE freedbtech_chytra_zasuvka.Seznam_uzivatelu SET Spotreba = Spotreba + ('" + String(Spotreba,3) + "'), Kredit = Kredit - ('" + String(Spotreba,3) + "') WHERE Uzivatelske_cislo = (SELECT Cislo_uzivatele FROM freedbtech_chytra_zasuvka.Historie_pristupu ORDER BY Poradi DESC LIMIT 1)");  

  }
  pzem.resetEnergy();                 // Pri novem spusteni taktez resetujeme pamet spotreby energie v mericim modulu PZEM-004T 

  
}
