/* 
#AUTHOR Дмитрий Витальевич Мельник
#MAIL i.x.c.o.n@yandex.ru 
#LICENSE Использование  только  для не коммерческих проектов, без упоминания автора. При использовании автор не несет ни какой отвественности, и не дает ни какой гарантии работы. Не ведет поддержку или исправление ошибок.  
*/
#include <SoftwareSerial.h>//библиотека  для  виртуального сериала
//внимание может быть только 1  вирутальный сериал
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define PINBUTTONSBROS A2 //пин для кнопки сброса
#define PINLED A0 //пин первого светодиода
#define PINLED2 A3//пин второго светодиода
#define PINZUMMER A1//пин для  зумера

uint32_t timer = 0;//таймер
uint32_t timer1 = 0;//таймер
uint32_t timer2 = 0;//таймер

// создаём объект mySerial и передаём номера управляющих пинов RX и  
SoftwareSerial SIM800(2, 3); 

char TextSendSIM800[255]; //массив для  приема данных от сим800
char TextResvSerial[255]; //массви для  приема данных от сериала

bool StatusAlert = false; //статус  тревоги

int TimerAlert = 0; // для  таймера рабы  тревоги
int TimerOFFAlert = 30; //Указываем сколько секунд держиться тревожное событие

void setup(){
  pinMode(PINBUTTONSBROS, INPUT_PULLUP);//Устанавливает режим работы как вход с подтяжкой
  pinMode(PINLED, OUTPUT);//Устанавливает режим работы  как выход
  pinMode(PINLED2, OUTPUT);//Устанавливает режим работы  как выход

  digitalWrite(PINLED, HIGH);//Устанавливает в состояние выкл
  digitalWrite(PINLED2, HIGH);//Устанавливает в состояние выкл

  Serial.begin(9600);//Иницилизация сериала
  Serial.setTimeout(100);//Устанавливаем время ожидания данных от сериала
  SIM800.begin(9600);//Иницилизация сериала  для СИМ800
  SIM800.setTimeout(100);//Устанавливаем время ожидания данных от сериала
  Serial.print("START OK\r\n");//Что модуль запустился
  delay(100);
  SIM800.println("AT");//Это нужно  для автонастройки
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 allocation failed"));
  }
  display.clearDisplay();
  display.setCursor(36, 12);
  display.setTextColor(WHITE);
  display.setTextSize(2);
  display.println("ESP32");
  display.setCursor(36, 32);
  display.println("START");
  display.display();
}
     
void loop(){


  if(millis() - timer >= 100){//первый таймер
    timer = millis();//обнуляем таймер

    ReadSerial();//проверяем есть ли  данные с сериала
    ReadSIM800();//проверяем есть ли данные с сим80
    

    if(!digitalRead(PINBUTTONSBROS)){// проверяем нажание кнопки
      if(StatusAlert){//если была включена тревога увидим сообщение
        Serial.println("ALERT OFF");
      }
      TimerAlert = 0;//обнуляем таймер тревоги
      StatusAlert = false;//выключаем тревогу
    }
  }

  if(millis() - timer1 >= 500){//второй таймер
    timer1 = millis();//обнуляем таймер
    if(StatusAlert){//если тревога включена
      tone(PINZUMMER, 1000, 250);//сигнал на зумер
      if(digitalRead(PINLED)){//если первый светодиод выкл
        digitalWrite(PINLED, LOW);//моргаем
        digitalWrite(PINLED2, HIGH);//моргаем     
      }else{// если первый светодиод вкл
        digitalWrite(PINLED, HIGH);//моргаем
        digitalWrite(PINLED2, LOW);//моргаем 
      }
    }
  }

  if(millis() - timer2 >= 1000){//третий таймер
    timer2 = millis();//обнуление таймера
    if(StatusAlert){//если статус тревоги вкл
      Serial.println("ALERT ON");//пишем что вкл тревога
      TimerAlert++;//счетчик таймера  тревоги
      if(TimerAlert > TimerOFFAlert){//проверяем время  работы
        TimerAlert = 0;//сброс счетчика
        StatusAlert = false;//отключение  тревоги
        digitalWrite(PINLED, HIGH);//вкл
        digitalWrite(PINLED2, HIGH);//вкл
        Serial.println("Таймер на  отключение тревоги отключен");
      }
    }

  }

}
//пошли функции работы
void ReadSIM800(){//обработка данных от сим модуля
  if(SIM800.available() > 0){// если есть  данные
    String TempSTRSIM800 = "";
    TempSTRSIM800 = SIM800.readString();//считываем все в строку
    //Serial.print(TempSTRSIM800);
    TempSTRSIM800.trim();// обрезаем пробелы
    int i = 0;
      for(i = 0; i < TempSTRSIM800.length(); i++){
        TextSendSIM800[i] = TempSTRSIM800[i];// копируем в си строку
      }
      TextSendSIM800[i] = 0x00;//закрываем си строку
      Serial.println(TextSendSIM800);

    if(strncmp(TextSendSIM800, "+CMTI:", 6) == 0){//проверяем пришла ли смс
        Serial.println("Пришло СМС");
        char GETSMS[12] = "AT+CMGR=";//создаем и отправляем смс чтения на смс
        for(i = 0; i < TempSTRSIM800.length(); i++){
          if(TextSendSIM800[i] == ','){
            break;
          }
        }
        i++;
        int j = 0;
        for(j = 0; j <3; j++){
          if(0x30 <= TextSendSIM800[i+j] && TextSendSIM800[i+j] <= 0x39){
            GETSMS[8+j] = TextSendSIM800[i+j];
          }
          else{
            GETSMS[8+j] = 0x00;
            break;
          }
        }
        SIM800.println(GETSMS);
    }
    else{//тут ищем в открытой смс есть ли сигнал на включение тревоги
      char Alert[] = "STATUS ALERT";
      int TempLen = TempSTRSIM800.indexOf(0x53);

      //Serial.println(TempLen);
      bool TempAlert = false;
      if(TempLen > 0){
        //Serial.println("Есть вхождение");
        for(int q = 0; q < 12; q++){
          if(TextSendSIM800[TempLen + q] == Alert[q]){
            Serial.print(TextSendSIM800[TempLen + q]);
            TempAlert = true;
          }
          else{
            TempAlert = false;
            break;
          }

        }
        if(TempAlert){
          Serial.println("Найдено тревожное событие");
          StatusAlert = true;
        }
  
      }
    }


    /*
    if(strncmp(TextSendSIM800, "STATUS ALERT", 12) == 0){

    }
    */
    /*
    int tempSIM800 = SIM800.availableForWrite();
    SIM800.readBytes(TextSendSIM800, tempSIM800);
    Serial.print(TextSendSIM800);
    */
    /*
      for(int t = 0; t <255; t++){
        Serial.print(TextSendSIM800[t]);Serial.print(": 0x");Serial.print(TextSendSIM800[t], HEX);Serial.println();
        TextSendSIM800[t] = 0x00;
      }
    */
  }


}

void ReadSerial(){//обработка команд с сериала
  if(Serial.available() > 0){// если есть данные
    String TempSerial = "";//создаем строку
    TempSerial = Serial.readString();//считываем байты в строку
    int i = 0;// далее переводим строку в си строку
    for (i = 0; i < TempSerial.length(); i++){
      TextResvSerial[i] = TempSerial[i];//тупо копируем пока есть что копировать
    }
    TextResvSerial[i+1] = 0x00;//закрываем си строку
    //Serial.print(TextResvSerial);
    SIM800.print(TextResvSerial);
    /*
    int tempSerial = Serial.availableForWrite();
    Serial.readBytes(TextResvSerial, tempSerial);
    SIM800.print(TextResvSerial);
    Serial.print(TextResvSerial);
    */
    if(strncmp(TextResvSerial, "STATUS ALERT", 12) == 0){//если  пришла тревога включаем тревогу
      Serial.println("Найдено тревожное событие");
      //i = 0;    //+CMTI: "ME",3
      StatusAlert = true;// тревога включена
    }
  }
}