#include <ESP8266WiFi.h> //библиотека для взаимодействия платы с wi-fi сетями
#include <ESP8266WebServer.h> //библиотека для создания веб-сервера
#include <ESP8266HTTPClient.h> 
#include <Wire.h> //библиотека для работы с шиной I2C
#include <Adafruit_BMP280.h> //библиотека для работы с датчиками bmp280
#include <DNSServer.h>
#include <WiFiManager.h>         
#include <ESP8266SSDP.h>
#include <aREST.h>
#include <FS.h>
#include <ArduinoJson.h> //библиотека для обработки данных
#include <ESP8266WiFiMulti.h> //библиотека для работы с множеством точек досутпа

#include <GyverOLED.h>


using namespace std;
#define PERIOD (5*60*1000) // 5 минут в миллисекундах

ESP8266WiFiMulti wifiMulti;
String myAP;     //режим точки доступа
String mySSID;   //флаг использования собственной точки доступа WiFi
IPAddress myIP;  //хранит IP адресс  
unsigned long oldmillis=PERIOD+PERIOD;    //затравочное ("неправильное") значение

unsigned long when = millis();

const int wf=7; //количество сканирируемых сетей
const int wf_configs=20; //количество сохраняемых элементов в памяти
int count_wifi=20;
String ssid[wf_configs]={}; //массив имен сетей
String password[wf_configs]={}; //массив паролей сетей

String ssid_scan[wf]={};

String whoami;
String Akey;

int rssi[wf]={}; //может принимать значения от 0 до -100 дБм (чем выше значение RSSI (ближе к 0), тем сигнал лучше (мощнее))

size_t indexAppendSsid = 0;
const char* _ssid[wf_configs] ={};
const char* _password[wf_configs] ={};

GyverOLED<SSD1306_128x32, OLED_NO_BUFFER> oled;

const uint8_t bitmap_32x32[] PROGMEM = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xF0, 0x70, 0x70, 0x30, 0x30, 0x30, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF0, 0x70, 0x30, 0x30, 0x20, 0x00, 0x00,
  0x00, 0x30, 0x78, 0xFC, 0x7F, 0x3F, 0x0F, 0x0F, 0x1F, 0x3C, 0x78, 0xF0, 0xE0, 0xC0, 0x80, 0x80, 0x80, 0x40, 0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0x7F, 0x33, 0x13, 0x1E, 0x1C, 0x1C, 0x0E, 0x07, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xE0, 0xF0, 0xF9, 0xF7, 0xEF, 0x5F, 0x3F, 0x7F, 0xFE, 0xFD, 0xFB, 0xF1, 0xE0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x1E, 0x33, 0x33, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x1F, 0x0E, 0x04, 0x00, 0x00, 0x00, 0x00,
};

ESP8266WebServer HTTP(80);   //Web интерфейс для устройства
HTTPClient http;
WiFiServer SERVERaREST(8080);   //aREST и сервер для него
aREST rest = aREST();
File fsUploadFile;

#define BMP280_ADDRESS (0x76) //адрес для подключения датчиков bmp280 через I2C

Adafruit_BMP280 bmp;

String jsonConfig = "{}";                  //переменная, хранящая файл конфигурации

double pressure=0; 
double temp=0; 

double mmHg=133.3; //величина для перевода паскалей в мм.рт.ст

const int n=9; 

String ssidAP;     // SSID точки доступа
String passwordAP = "";     // Пароль точки доступа


void setup() 
{
  Serial.begin(115200); // инициализируем последовательный порт (для отладочных целей)

  oled.init();
  SPIFFS.begin();

  File f = SPIFFS.open("/f_config.txt", "r");
  if (!f)
  {
    Serial.print("Error:file");
    return;
  }
  else 
  {
    whoami= f.readStringUntil('\n');
    if (whoami.charAt(whoami.length()-1) == 13)
    whoami=whoami.substring(0,whoami.length()-1);

    Akey = f.readStringUntil('\n');
    if (Akey.charAt(Akey.length()-1) == 13)
    Akey=Akey.substring(0,Akey.length()-1);

    ssidAP = f.readStringUntil('\n');
    if (ssidAP.charAt(ssidAP.length()-1) == 13)
    ssidAP=ssidAP.substring(0,ssidAP.length()-1);
    
  }
  
  //настраиваем HTTP интерфейс
  HTTP_init();
   //запускаем SSDP сервис
  SSDP_init();

  // регистрируем в aRest функции irControl
  rest.function("irc", irControl);

  // включаем aREST и сервер к нему
  AREST_init();

  //загрузка конфигурации
  LoadConfig(); 
  delay(1000);

  for(size_t i = 0; i < wf_configs; i++) {
      if (ssid[i] != "") 
      {
        count_wifi=count_wifi-1;
      }
  }

  WiFi.persistent(false);
  WiFi.mode(WIFI_STA);  //переключение моудля в режим станции
  
  for (int i=0; i<wf_configs;i++)
  {
     wifiMulti.addAP(_ssid[i],_password[i]);
  }

  ReinitWiFi(0);
  
  delay(10);
 }


void loop() 
{
  oled.clear();
  oled.home();            // курсор в 0,0




  oled.print("       Паскаль     ");   // печатай что угодно: числа, строки, float, как Serial!
  //oled.print("SN");
  oled.println(whoami);

  oled.print("   ");   // печатай что угодно: числа, строки, float, как Serial!
  if (temp>0)
  {
    oled.print("+");
    oled.print(temp);
  }
  if (temp=0)
  {
    oled.print(" ");
    oled.print(temp);
  }
  if (temp<0)
  {
   // oled.print("");
    oled.print(temp);
  }
  //oled.print(temp);
  oled.print(" '");
  oled.println("C");


  oled.print("   ");
  //oled.print("P = ");   // печатай что угодно: числа, строки, float, как Serial!
  oled.print(pressure);
  oled.println(" мм.рт.ст.");
 

  //oled.print("RSSI = ");   // печатай что угодно: числа, строки, float, как Serial!
  oled.print("              ");
  oled.print(WiFi.RSSI());
  oled.println(" дБм");

  delay(4000);
  oled.update();

  pressure=0; // атмосферное давление
  temp=0; // температура
  
    if (!bmp.begin(BMP280_ADDRESS)) 
      {
        oled.print(F("Error     ")); //если датчик не найден - выводим ошибку и номер входа мультиплексора, к которому подключен неисправный датчик
        while (1);
      }
    bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,   //режим работы датчика bmp280
                  Adafruit_BMP280::SAMPLING_X2,   //точность изм. температуры  
                  Adafruit_BMP280::SAMPLING_X16,  //точность изм. давления 
                  Adafruit_BMP280::FILTER_X16,    //уровень фильтрации
                  Adafruit_BMP280::STANDBY_MS_1); //период просыпания, мСек
      
    pressure=bmp.readPressure()/mmHg;  //сумма значений атмосферного давления 
    temp=bmp.readTemperature();      //сумма значений температуры

  
  //передача пакета данных json раз в минуту в базу данных вуза
  //вывод на lcd-экран и в монитор порта название точки доступа, к которой удалось подключиться и ip-адреса раз в минуту
  //if (mnt!=old_time){sendJsonToDB(); lcd_v(); old_time=mnt;}
  //else {old_time=mnt;}

  //apsI0gqvFn
  //проверка/переподключение к сети wi-fi раз в 5 минут
  unsigned long mls;
  unsigned long mls_t;
  mls=millis();
  mls_t=mls%PERIOD;

  if(mls_t<oldmillis)
  {
   ReinitWiFi(1);
   oldmillis=mls_t;
  }


  if (millis() - when >= 60000)
  {
    when = millis();
    sendJsonToDB(); 
   lcd_v();
  }
  HTTP.handleClient();
  delay(1);
  WiFiClient client = SERVERaREST.available();
  if (!client) 
  {
    return;
  }
  while (!client.available()) 
  {
    delay(1);
  }
  rest.handle(client);
}
