// Learn about the ESP32 WiFi simulation in
// https://docs.wokwi.com/guides/esp32-wifi
#include <WiFi.h> // Библиотека для создания Wi-Fi подключения (клиент или точка доступа) ESP32
// #include <ESP8266WiFi.h> // Библиотека для создания Wi-Fi подключения (клиент или точка доступа) ESP8266
// #include <WiFiClient.h> // Библиотека для связи с сетевыми хостами (локальными и интернет)
// #include <Wire.h>
#include <ArduinoJson.h>
#include <TimeLib.h>
#include <LiquidCrystal_I2C.h>
WiFiClient client; // Создаём объект для работы с удалёнными хостами
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
String regionID = "213"; // Код региона по Yandex для выбора часового пояса https://tech.yandex.ru/xml/doc/dg/reference/regions-docpage/
String SunriseTime, SunsetTime, Temperature, Iconka, sCurDate, sCurTime;
String sLightStart = "05:00", sLightStop = "22:00";
char icon[20];
int iMode = 0; //0-Auto, 1-On, 2-Off
int iScrn = 0; //0-1, 1-2, 2-3
int lastStateMode = HIGH;
int lastStateScrn = HIGH;
bool bIsBtnReleased = true;
unsigned long lastBtnMs = 0;
uint8_t symb_gradus[8] = {B01100, B10010, B10010, B01100, B00000, B00000, B00000, B00000,};
#define RELE_PIN 15
#define BUTTON_MODE_PIN 14
#define BUTTON_SCRN_PIN 27
//----------------------------------------------------------------------------------------------------
void setup() {
Serial.begin(9600); // Инициализируем вывод данных на серийный порт со скоростью 9600 бод
Serial.println("\n\n");
Serial.println(sLightStop);
Serial.println(sLightStop.substring(0, 2).toInt());
Serial.println(sLightStop.substring(3, 5).toInt());
// EEPROM.begin(100); // для esp8266/esp32
// pinMode(LED_BUILT, OUTPUT);
// digitalWrite(LED_BUILT, HIGH);
pinMode(RELE_PIN, OUTPUT);
pinMode(BUTTON_MODE_PIN, INPUT_PULLUP);
pinMode(BUTTON_SCRN_PIN, INPUT_PULLUP);
//----------
digitalWrite(RELE_PIN, HIGH);
lcd.init();
lcd.backlight();
// lcd.noBacklight();
lcd.createChar(0, symb_gradus);
WiFiConnectAndGetTime ();
digitalWrite(RELE_PIN, LOW);
//----------
bIsBtnReleased = true;
lastBtnMs = millis();
}
//----------------------------------------------------------------------------------------------------
void loop2() {
}
//----------------------------------------------------------------------------------------------------
void loop() {
unsigned long lMs = millis();
if (lMs - lastBtnMs >= 30000) {
lcd.noBacklight();
}
if (lMs % 1000 == 0) {
delay(5);
if (second() >= 0 && second() < 1) {
if (minute() % 10 == 0) { // Каждые 10 минут обновляем время и температуру
WiFiConnectAndGetTime ();
}
if (iScrn == 0) {
ClockPrint(); // Выводим дату, время и температуру в порт
ClockDisplay();
modeDisplay();
}
}
if (iScrn == 2) {
fullClockDisplay();
modeDisplay();
}
}
// -----
if (bIsBtnReleased) {
bIsBtnReleased = false;
lcd.clear();
if (iScrn == 0) {
ClockPrint(); // Выводим дату, время и температуру в порт
ClockDisplay();
modeDisplay();
}
if (iScrn == 1) {
sunSettingDisplay();
lightSettingDisplay();
}
if (iScrn == 2) {
fullClockDisplay();
modeDisplay();
}
}
// -----
int value;
value = digitalRead(BUTTON_MODE_PIN);
if (lastStateMode != value) {
lcd.backlight();
lastStateMode = value;
if (value == LOW) {
iMode = (iMode + 1) % 3;
if (iScrn == 0) {
modeDisplay();
}
// bIsBtnReleased = true;
lastBtnMs = millis();
}
}
value = digitalRead(BUTTON_SCRN_PIN);
if (lastStateScrn != value) {
lcd.backlight();
lastStateScrn = value;
if (value == LOW) {
iScrn = (iScrn + 1) % 3;
bIsBtnReleased = true;
lastBtnMs = millis();
}
}
if (iMode == 1) {
if (digitalRead(RELE_PIN) == LOW) {
digitalWrite(RELE_PIN, HIGH);
}
} else if (iMode == 2) {
if (digitalRead(RELE_PIN) == HIGH) {
digitalWrite(RELE_PIN, LOW);
}
} else {
sCurTime = leadNull(hour()) + ":" + leadNull(minute());
if ((sCurTime >= sLightStart) && (sCurTime < sLightStop)) {
if ((sCurTime < SunriseTime) || (sCurTime >= SunsetTime)) {
digitalWrite(RELE_PIN, HIGH);
}
else {
digitalWrite(RELE_PIN, LOW);
}
}
else {
digitalWrite(RELE_PIN, LOW);
}
}
delay(1);
}
//----------------------------------------------------------------------------------------------------
void WiFiConnectAndGetTime () { // Подключение к WiFi
if (WiFi.status() != WL_CONNECTED) {
while (!WiFiConnect()) {
lcd.clear();
lcd.print("Wait WiFi 10 sec");
WiFi.disconnect();
delay(10000);
}
}
while (!GetTimeAndWeather()) { // Синхронизируем время микроконтроллера с реальным временем и получаем информацию о погоде
lcd.clear();
lcd.print("Wait Time 5 sec");
delay(5000);
}
}
//----------------------------------------------------------------------------------------------------
bool WiFiConnect() { // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
int iTryConnect = 0;
bool bNorm = false;
while (!bNorm && iTryConnect < 10) {
lcd.clear();
lcd.print("Connect N" + String(iTryConnect + 1) + "...");
// WiFi.begin(ssid, password); // Соединяемся с WiFi-сетью
WiFi.begin("Wokwi-GUEST", "", 6); // Соединяемся с WiFi-сетью
int i = 0;
while (WiFi.status() != WL_CONNECTED) { // Пока соединение не установено
i++;
if (i > 15) {
i = 1;
lcd.setCursor(0, 1);
lcd.print(' ');
}
lcd.setCursor(i, 1);
lcd.print('.');
delay(500); // делаем задержку в пол секунды, пока соединение не установится
}
if (WiFi.status() == WL_CONNECTED) {
bNorm = true;
}
iTryConnect++;
}
return bNorm;
}
//----------------------------------------------------------------------------------------------------
bool GetTimeAndWeather() { // Функция синхронизации времени работы программы с реальным временем и получения информации о погоде
lcd.clear();
lcd.print("Get Time");
delay(500);
lcd.setCursor(9, 0);
lcd.print("G");
if (client.connect("yandex.com", 443)) { // Если удаётся установить соединение с указанным хостом (Порт 443 для https)
client.println("GET /time/sync.json?geo=" + regionID + " HTTP/1.1\r\nHost: yandex.com\r\nConnection: close\r\n\r\n"); // Отправляем параметры запроса
//yandex.com/time/sync.json?geo=213
delay(1000); // Даём серверу время, чтобы обработать запрос
char endOfHeaders[] = "\r\n\r\n"; // Системные заголовки ответа сервера отделяются от остального содержимого двойным переводом строки
if (!client.find(endOfHeaders)) { // Отбрасываем системные заголовки ответа сервера
Serial.println("Invalid response"); // Если ответ сервера не содержит системных заголовков, значит что-то пошло не так
return false; // и пора прекращать всё это дело
}
String st = "";
while (client.available()) {
char c = client.read();
st = st + c;
}
//Serial.print("client = ");
Serial.println(st);
client.stop(); // Разрываем соединение с сервером
Serial.println();
DynamicJsonDocument jsonDoc(1024); // Инициализируем JSON-документ
DeserializationError error = deserializeJson(jsonDoc, st);
if (error) {
Serial.print("deserializeJson() failed: ");
Serial.println(error.c_str());
lcd.setCursor(9, 0);
lcd.print(" ");
return false;
}
long long longCurTime = jsonDoc["time"]; // Достаём значение реального текущего времени из JSON и отбрасываем от него миллисекунды
String StringCurrentTime = jsonDoc["time"].as<String>().substring(0, 10); // Достаём значение реального текущего времени из JSON и отбрасываем от него миллисекунды
long longOffset = jsonDoc["clocks"][regionID]["offset"]; // Достаём значение смещения времени по часовому поясу (в миллисекундах)
String StringOffset = jsonDoc["clocks"][regionID]["offset"].as<String>(); // Достаём значение смещения времени по часовому поясу (в миллисекундах)
SunriseTime = jsonDoc["clocks"][regionID]["sunrise"].as<String>(); // Достаём время восхода - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunrise
SunsetTime = jsonDoc["clocks"][regionID]["sunset"].as<String>(); // Достаём время заката - Третий уровень вложенности пары ключ/значение clocks -> значение RegionID -> sunset
Temperature = jsonDoc["clocks"][regionID]["weather"]["temp"].as<String>();// Достаём время заката - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> temp
Iconka = jsonDoc["clocks"][regionID]["weather"]["icon"].as<String>();
strcpy(icon, jsonDoc["clocks"][regionID]["weather"]["icon"].as<String>().c_str()); // Достаём иконку - Четвёртый уровень вложенности пары ключ/значение clocks -> значение RegionID -> weather -> icon
// jsonDoc.clear(); // Очищаем буфер парсера JSON
setTime((int)(longCurTime / 1000) + (longOffset / 1000)); // Синхронизируем время
lcd.setCursor(9, 0);
lcd.print(" ");
return true;
}
}
//----------------------------------------------------------------------------------------------------
void fullClockDisplay() { // Эта функция выводит дату, время и температуру дисплей
lcd.setCursor(0, 0);
sCurDate = leadNull(hour()) + ":" + leadNull(minute()) + ":" + leadNull(second());
lcd.print(sCurDate);
lcd.setCursor(0, 1);
sCurDate = leadNull(day()) + '.' + leadNull(month()) + "." + leadNull(year());
lcd.print(sCurDate);
}
//----------------------------------------------------------------------------------------------------
void ClockPrint() { // Эта функция выводит дату и время на монитор серийного порта
sCurDate = leadNull(day()) + '.' + leadNull(month()) + "." + leadNull(year()) + " " + leadNull(hour()) + ":" + leadNull(minute()) + ":" + leadNull(second());
Serial.print("Tekuschie data i vremya: ");
Serial.println(sCurDate);
Serial.println("\nVoshod v " + SunriseTime); // Выводим время восхода
Serial.println("Zakat v " + SunsetTime); // Выводим время восхода
Serial.println("\nTemperatura: " + Temperature + " C"); // Выводим время восхода
}
//----------------------------------------------------------------------------------------------------
void ClockDisplay() { // Эта функция выводит дату, время и температуру дисплей
lcd.setCursor(0, 0);
// sCurDate = leadNull(day()) + '.' + leadNull(month()) + "." + leadNull(year()).substring(2, 4) + " " + leadNull(hour()) + ":" + leadNull(minute()) + ":" + leadNull(second());
sCurDate = leadNull(day()) + '.' + leadNull(month()) + "." + leadNull(year()).substring(2, 4) + " " + leadNull(hour()) + ":" + leadNull(minute());
// sCurDate = leadNull(day()) + '.' + leadNull(month()) + " " + leadNull(hour()) + ":" + leadNull(minute()) + ":" + leadNull(second());
lcd.print(sCurDate);
lcd.setCursor(0, 1);
lcd.print("Temp: " + Temperature);
lcd.write(0);
lcd.print("C");
}
//----------------------------------------------------------------------------------------------------
void modeDisplay() { // Эта функция режим на дисплей
lcd.setCursor(13, 1);
lcd.print("R:" + String(iMode));
}
//----------------------------------------------------------------------------------------------------
void sunSettingDisplay() { // Эта функция режим на дисплей
lcd.setCursor(0, 0);
// SunriseTime = "04:05";
// SunsetTime = "04:10";
lcd.print("Sun: " + SunriseTime + "-" + SunsetTime);
}
//----------------------------------------------------------------------------------------------------
void lightSettingDisplay() { // Эта функция режим на дисплей
lcd.setCursor(0, 1);
lcd.print("Lgt: " + sLightStart + "-" + sLightStop + "");
}
//----------------------------------------------------------------------------------------------------
String leadNull(int digits){ // Функция добавляет ведущий ноль
String out = "";
if (digits < 10)
out += "0";
return out + String(digits);
}