/*
    VUT FEKT UTKO
    ID 173711
    xmozny03
    Radek Možný 
    Bakalářská práce - IR senzor pro detekci pohybu

    Program PIR2_16MHz_externi_krystal

    Všechny příkazy  Serial.print() slouží k testovacím účelům a nemusí být implementovány.
    Část pr odesílání odezvy senzoru taktéž slouží pro testování funkčnosti programu.
*/


//definice knihoven
#include <SPI.h>
#include <RH_RF22.h>
#include <OneWire.h>
#include <LowPower.h>
#include <DallasTemperature.h>
#include <PinChangeInt.h>

// nastavení čísla vstupního pinu
const int pinCidlaDS = 9;
// vytvoření instance oneWireDS z knihovny OneWire
OneWire oneWireDS(pinCidlaDS);
// vytvoření instance senzoryDS z knihovny DallasTemperature
DallasTemperature senzoryDS(&oneWireDS);


RH_RF22 rf22;                  //jméno pro driver z knihovny RH_RF22
#define LED 4
const int PIR_Pin = 3;          // pin 3 pro PIR
int pirState = LOW;             
int buttonState = HIGH;
int val = 0;                    // variable for reading the pin status
int state_number =0;            // proměnná pro učení stavu senzoru a násleného vyslání stavu ústředně, 0 = ok, 1 = breach(sabotážní kontakt), 2 = Alarm (PIR detekce) 

#define interrupt_button 8      //pin 8 pro sabotážní kontakt
#define PINBAT A1               //definice pinu A1 pro měření napětí baterie
static char dash[2] = ";"; 
static char procenta_char[5];
static char temperature_char[5];


void setup()
{
  pinMode(interrupt_button, INPUT_PULLUP);     //nastavení pinu pro tlařítko přerušení jako vstup s aktivním pullup rezistorem
  pinMode(PIR_Pin, INPUT);                    //nastavení pinu pro PIR jako vstup
  attachPinChangeInterrupt(interrupt_button, breach, RISING);//aktivace přerušení pro tlačítko reagující na nástupnou hranu a následně vykonávající funkci breach
  attachPinChangeInterrupt(PIR_Pin, PIR_alarm, RISING);//aktivace přerušení pro PIR reagující na nástupnou hranu a následně vykonávající funkci breach
  pinMode (LED, OUTPUT);
  pinMode (PINBAT, INPUT);

  // zapnutí komunikace knihovny s teplotním čidlem
  senzoryDS.begin();
  
  rf22.init();                                         //inicializace komunikačního modulu DrF4432F20 
      Serial.begin(9600);                               //aktivace sériové komunikace o rychlosti 9600 baud
  if (!rf22.init())                                     //při nezdařilé inicializaci se ohlásí chyba
    Serial.println("init failed");
   // Defaultní nastavení po inicializaci: 434.0MHz, 0.05MHz AFC pull-in, modulace FSK_Rb2_4Fd36
 delay(30000); //Dobaa čekání na inicialzaci PIR
}  



void breach() {
    state_number = 1;    //funkce po přeručení sabotážním kontaktem 
};

void PIR_alarm()       //funkce po přeručení PIR
{         
    state_number = 2;
};




void loop()
{
  // awake
  
  //--------------------měření baterie------------
  delay(400);
  int sensorValue=analogRead(PINBAT);
  // na regulátoru je úbitek napeti 0.190V takze pod 3.490V na baterii uz procesor a ADC bude napajen mene jak 3.3V
  // pro 3.3V arduino a delic 1:1 bude cislo odpovidat napeti na baterii:
  // 528 - 3.40V
  //-------------------měření teploty-----------------------
  senzoryDS.requestTemperatures();                        //vyžádání digitální hodnoty teploty ze senzoru DS
  int temperature = senzoryDS.getTempCByIndex(0);        //určení teploty dle knihovyn DallasTemperature.h
  double d =3.3/1024*sensorValue*2;                     // výpočet napětí ve voltech
  double percentage = ((d -3.3)/0.9)*100;               //výpočet procet baterie v rozmezí 4,2V až 3,3V
  byte bat=0;                                           //stav baterie 1 = vyměnit 0 = ok
 digitalWrite (LED, HIGH);
  
  if (  sensorValue>558) {   //stav baterie 0 = vyměnit 1 = ok
    bat=1;  
  }
  
  Serial.print("PIR2,battery:");                              //výpis informací z PIR1 - slouží jen pro testovací účely
  Serial.println(bat);
  Serial.print("- value: ");
  Serial.print(sensorValue);
  Serial.print(" = ");
  Serial.print(d,4);
  Serial.println(" V");
  Serial.print("- Battery level: ");
  Serial.print(percentage,0);
  Serial.print(" %");
  Serial.println();
  Serial.print("- Temperature: ");
  Serial.print(senzoryDS.getTempCByIndex(0));
  Serial.println(" C");

 //--------------formování vysílané zprávy-----
  char Celek[30] = "PIR1;";
  dtostrf(percentage,4, 0, procenta_char);                           // příkla transformace int na char
  strcat(Celek, procenta_char);                          // přiklad připojení zprávy1 typu char na konec zprávy 2 typu char
  
  strcat(Celek, dash); 
  dtostrf(temperature,4, 0, temperature_char);
  strcat(Celek, temperature_char);
  strcat(Celek, dash);

  if(state_number == 1){                               //výběr stavu PIR
  char state[10] = "breach";
  strcat(Celek, state);
  state_number = 0;
  }
  else if(state_number == 2){
  char state[10] = "Alarm";
   strcat(Celek, state);
  state_number = 0;
  }
  else if(bat == 0){
  char state[10] = "Batt!";
   strcat(Celek, state);
  state_number = 0;
  }
  else{
    char state[10] = "ok";
    strcat(Celek, state);
    }


 //----------------------Vyslání zprávy stanici EZS-------
Serial.println("Sending to rf22_server:");
Serial.println(Celek);
//Serial.println(state_number);
rf22.send((uint8_t *)Celek, sizeof(Celek));
rf22.waitPacketSent(); 


  //-------------------- čekání na odezvu - tato část slouží pro testovací účely - zvyšuje spotřebu-------------
  
  int8_t buf[RH_RF22_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

  if (rf22.waitAvailableTimeout(500))
  {   
    if (rf22.recv(buf, &len))
    {
      Serial.print("got reply: ");
      Serial.println((char*)buf);
      Serial.println();
    }
    else
    {
      Serial.println("recv failed");
      Serial.println();
    }
  }
  else
  {
    Serial.println("No reply, is rf22_server running?");
    Serial.println();
  }
  delay (200);
  digitalWrite (LED, LOW); 

 //spánek SI4432
  rf22.sleep();
  
  //Vstup do PowerDown módu knihovny LowPower.h - vypnutí AD převodníků a BOD.
  // cyklus for pro zvýšení doby spánku pro watchdog timer, násobky 8, zde 8*7=56s
  for (int i = 0; i < 7; i++) {
  LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
  } 
  
}  





