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

    Program PIR2_8MHz_RC_oscilator

    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 <Vcc.h>
#include <LowPower.h>
#include <PinChangeInt.h>

const float VccMin        = 2.8;  // Minimální předpokládané napětí
const float VccMax        = 4.2;  // Maximum expected Vcc level, in Volts. Example for 2xAA Alkaline.
const float VccCorrection = 1.0/1.0;  // Measured Vcc by multimeter divided by reported Vcc 1.0/1.0

Vcc vcc(VccCorrection);            //funkce pro úpravu dle korekce z knihovny Vcc.h


RH_RF22 rf22;                     //jméno pro driver z knihovny RH_RF22
#define LED 4
#define interrupt_button 8      //pin 8 pro sabotážní kontakt
const int PIR_Pin = 3;          // pin pro PIR
int pirState = LOW;             
int buttonState = HIGH;
int val = 0;                    // proměnná pr čtení stavu pir
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)

static char dash[5] = ";";        //definice částí zpráv pro vyslání a oddělovače ;
static char procenta_char[10];
static char temperature_char[10];




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
  //attachInterrupt(1, PIR_alarm, HIGH);
  pinMode (LED, OUTPUT);

  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(60000); //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
  byte bat=0;    //stav baterie 1 = vyměnit 0 = ok
  //--------------------měření baterie------------
  delay(200);
  double voltage = vcc.Read_Volts();                        //určení napětí baterie bez využití regulátoru napětí z knihovny Vcc.h
  double percentage = (voltage-VccMin)/(VccMax-VccMin)*100;
  //-------------------měření teploty-----------------------
  delay(200);
  int temperature_val = rf22.temperatureRead();             //čtení digitální hodnoty teploty z SI4432
  int temperature=temperature_val*0.5-64;                    //výpočet teploty dle datasheetu SI4432 str 60 range 1 ->ADC8value x ADC8LSB + lowest temp -> ADC8LSB = 0,5; Lowest temp = -64 C
   
  digitalWrite (LED, HIGH);                                  //výpis informací z PIR2 - slouží jen pro testovací účely
  Serial.print("PIR1,battery:");
  Serial.print("- value: ");
  Serial.print(voltage,4);
  Serial.println(" V");
  Serial.print("- Battery level: ");
  Serial.print(percentage,0);
  Serial.print(" %");
  Serial.println();
  
  Serial.print("- Temperature: ");
  Serial.print(temperature);
  Serial.println(" C");

digitalWrite (LED, HIGH);
if (percentage > 20) {        //baterie pod 20% zahlásí nutnost výměny
    bat=1;  
  }

//--------------formování vysílané zprávy-----
  char Celek[50] = "PIR2;";
  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);
rf22.send((uint8_t *)Celek, sizeof(Celek));            
  rf22.waitPacketSent();
  
  //-------------------- čekání na odezvu - tato část slouží pro testovací účely - zvyšuje spotřebu-------------
  uint8_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("Bez odezvy.");
    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);
  } 
}  





