mirror of
https://github.com/gunner47/GyverLamp.git
synced 2025-08-06 16:47:17 +03:00
467 lines
29 KiB
C++
467 lines
29 KiB
C++
/*
|
||
Скетч к проекту "Многофункциональный RGB светильник"
|
||
Страница проекта (схемы, описания): https://alexgyver.ru/GyverLamp/
|
||
Исходники на GitHub: https://github.com/AlexGyver/GyverLamp/
|
||
Нравится, как написан код? Поддержи автора! https://alexgyver.ru/support_alex/
|
||
Автор: AlexGyver, AlexGyver Technologies, 2019
|
||
https://AlexGyver.ru/
|
||
*/
|
||
|
||
/*
|
||
Версия 1.4:
|
||
- Исправлен баг при смене режимов
|
||
- Исправлены тормоза в режиме точки доступа
|
||
--- 08.07.2019
|
||
- Исправлены параметры и процесс подключения к WiFi сети (таймаут 7 секунд) и развёртываия WiFi точки доступа (параметры имени/пароля)
|
||
- Добавлено "#define USE_NTP" - позволяет запретить обращаться в интернет
|
||
- Добавлено "#define ESP_USE_BUTTON - позволяет собирать лампу без физической кнопки, иначе яркость эффектов самопроизвольно растёт до максимальной
|
||
- Переработаны параметры IP адресов, STA_STATIC_IP теперь пустой по умолчанию - избавляет от путаницы с IP адресами из неправильных диапазонов
|
||
- Добавлено "#define GENERAL_DEBUG" - выводит в Serial/Telnet некоторые отладочные сообщения
|
||
- Добавлено "#define WIFIMAN_DEBUG (true)" - выводит в Serial/Telnet отладочные сообщения библиотеки WiFiManager
|
||
- Добавлена таблица с тест кейсами
|
||
- Форматирование кода, комментарии
|
||
--- 11.07.2019
|
||
- Исправлена ошибка невыключения матрицы после срабатывания будильника, если до будильника матрица была выключенной
|
||
- Дополнена таблица с тест кейсами
|
||
--- 14.07.2019
|
||
- Исправлена ошибка выключения будильника, если перед его срабатыванием был активен эффект "матрица" (или другой эффект, где задействовано мало светодиодов)
|
||
- Добавлено управление по воздуху:
|
||
-- работает только в режиме WiFi клиента
|
||
-- работает при подключенной кнопке (потому что режим прошивки активируется кнопкой)
|
||
--- 16.07.2019
|
||
- Исправлено регулярное подвисание матрицы на 1-2 секунды при отсутствии подключения к интернету (но при успешном подключении к WiFi)
|
||
--- 28.07.2019
|
||
- Доработано взаимодействие с android приложением (отправка состояния после каждой операции)
|
||
--- 01.08.2019
|
||
- Возврат к стандартной библиотеке GyverButton (изменениё из неё перенесено в button.ino
|
||
- Добавлены 2 эффекта: Светлячки со шлейфом и Белый свет
|
||
- При запросе обновления по воздуху (2 четверных касания к кнопке) лампа переключается в режим "Матрица" для визуального подтверждения готовности к прошивке
|
||
- В android приложение добавлена функция сканирования сети и добавления ламп с помощью multicast пакетов, доработка прошивки под это
|
||
--- 03.08.2019
|
||
- Исправлены ошибки взаимодействия android приложения с лампой, в вывод команды CURR добавлено текущее время (или millis(), если время не синхронизировано)
|
||
--- 10.08.2019
|
||
- Добавлена точная настройка яркости, скорости и масштаба эффектов
|
||
- Добавлено взаимодействие с android приложением по управлению будильниками
|
||
--- 14.08.2019
|
||
- Добавлена функция таймера отключения
|
||
--- 26.08.2019
|
||
- Добавлен режим автоматического переключения избранных эффектов
|
||
- Реорганизован код, исправлены ошибки
|
||
--- 28.08.2019
|
||
- Добавлен вызов режима обновления модуля esp из android приложения
|
||
--- 30.08.2019
|
||
- Эффект "Светлячки со шлейфами" переименован в "Угасающие пиксели"
|
||
- Добавлены 5 новых эффекта: "Радуга диагональная", "Метель", "Звездопад", "Светлячки со шлейфами" (новый) и "Блуждающий кубик"
|
||
- Исправлены ошибки
|
||
--- 04.09.2019
|
||
- Большая часть определений (констант) перенесена в файл Constants.h
|
||
- Большая оптимизация использования памяти
|
||
- Исправлена ошибка невключения эффекта "Белый свет" приложением и кнопкой
|
||
- Исправлена ошибка неправильного выбора интервала в режиме Избранное в android приложении
|
||
--- 16.09.2019
|
||
- Добавлено сохранение состояния (вкл/выкл) лампы в EEPROM память
|
||
- Добавлен новый эффект белого света (с горизонтальной полосой)
|
||
- Реорганизован код, исправлены ошибки
|
||
--- 20.09.2019
|
||
- Добавлена возможность сохранять состояние (вкл/выкл) режима "Избранное"; не сбрасывается выключением матрицы, не сбрасывается перезапуском модуля esp
|
||
- Убрана очистка параметров WiFi при старте с зажатой кнопкой; регулируется директивой ESP_RESET_ON_START, которая определена как false по умолчанию
|
||
--- 24.09.2019
|
||
- Добавлены изменения из прошивка от Alex Gyver v1.5: бегущая строка с IP адресом лампы по пятикратному клику на кнопку
|
||
--- 29.09.2019
|
||
- Добавлена опция вывода отладочных сообщений по пртоколу telnet вместо serial для удалённой отладки
|
||
- Исправлена ошибка регулировки яркости кнопкой
|
||
--- 05.10.2019
|
||
- Добавлено управление по протоколу MQTT
|
||
- Исправлена ошибка выключения будильника кнопкой
|
||
- Добавлена задержка в 1 секунду сразу после старта, в течение которой нужно нажать кнопку, чтобы очистить сохранённые параметры WiFi (если ESP_RESET_ON_START == true)
|
||
--- 12.10.2019
|
||
- Добавлена возможность сменить рабочий режим лампы (ESP_MODE) без необходимости перепрошивки; вызывается по семикратному клику по кнопке при включенной матрице; сохраняется в EEPROM
|
||
- Изменён алгоритм работы будильника:
|
||
- * обновление его оттенка/яркости происходит 1 раз в 3 секунды вместо 1 раза в минуту
|
||
- * диоды разбиты на 6 групп, первой из которых назначается новый оттенок/яркость 1 раз в 3 секунды, вторая "отстаёт" на 1 шаг, третья - на 2 шага и т.д. (для большей плавности)
|
||
- Добавлена визуальная сигнализация о некоторых важных действиях/состояниях лампы:
|
||
- * при запуске в режиме WiFi клиента и ещё не настроенных параметрах WiFi сети (когда их нужно ввести) - 1 вспышка жёлтым
|
||
- * если лампа стартовала в режиме WiFi клиента с ненастроенными параметрами WiFi сети, и они не были введены за отведённый таймаут (перед перезагрузкой) - 1 вспышка красным
|
||
- * при переходе лампы в режим обновления по воздуху (OTA) по двум четырёхкратным кликам по кнопке или по кнопке OTA из android приложения - 2 вспышки жёлтым
|
||
- * если лампа была переведена в режим OTA, но не дождалась прошивки за отведённый таймаут (перед перезагрузкой) - 2 вспышки красным
|
||
- * при переключении рабочего режима лампы WiFi точка доступа/WiFi клиент семикратным кликом по кнопке (перед перезагрузкой) - 3 вспышки красным
|
||
- * при запросе вывода времени бегущей строкой, если время не синхронизировано - 4 вспышки красным
|
||
- Уменьшен таймаут подключения к WiFi сети до 6 секунд; вызвано увеличившейся продолжительностью работы функции setup(), она в сумме должна быть меньше 8 секунд
|
||
- Оптимизирован код
|
||
--- 14.10.2019
|
||
- Если при первом старте в режиме WiFi клиента запрашиваемые имя и пароль WiFi сети не введены за отведённый таймаут (5 минут), лампа перезагрузится в режиме точки доступа
|
||
- Добавлен вывод времени бегущей строкой:
|
||
- * по запросу - шестикратному клику - текущее время белым цветом;
|
||
- * периодически - определяется константой PRINT_TIME в Constants.h - от раза в час (красным цветом) до раза в минуту (синим цветом) с яркостью текущего эффекта как при включенной, так и при выключенной матрице
|
||
--- 19.10.2019
|
||
- Добавлены "ночные часы" (от NIGHT_HOURS_START до NIGHT_HOURS_STOP включительно) и "дневные часы" (всё остальное время), для которых доступна регулировка яркости для вывода времени бегущей строкой - NIGHT_HOURS_BRIGHTNESS и DAY_HOURS_BRIGHTNESS
|
||
--- 20.10.2019
|
||
- Добавлена блокировка кнопки на лампе из android приложения; сохраняется в EEPROM память
|
||
--- 24.10.2019
|
||
- Добавлен вывод сигнала (HIGH/LOW - настраивается константой MOSFET_LEVEL) синхронно с включением матрицы на пин MOSFET транзистора (настраивается константой MOSFET_PIN)
|
||
- Добавлен вывод сигнала (HIGH/LOW - настраивается константой ALARM_LEVEL) на пин будильника (настраивается константой ALARM_PIN); сигнал подаётся в течение одной минуты, начиная со времени, на которое заведён будильник
|
||
--- 02.11.2019
|
||
- Добавлен переход на летнее/зимнее время (изменены настройки часового пояса, см. Constants.h); добавлена библиотека Timezone
|
||
- Добавлен эффект Белый огонь
|
||
- Исправлена ошибка сброса сигнала на пине ALARM_PIN при отключении будильника вручную
|
||
- Добавлена сигнализация (4 вспышки красным) при запросе вывода времени шестикратным кликом, если время не синхронизировано
|
||
*/
|
||
|
||
// Ссылка для менеджера плат:
|
||
// https://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||
|
||
|
||
#include "pgmspace.h"
|
||
#include "Constants.h"
|
||
#include <FastLED.h>
|
||
#include <ESP8266WiFi.h>
|
||
#include <ESP8266WebServer.h>
|
||
#include <WiFiManager.h>
|
||
#include <WiFiUdp.h>
|
||
#include <EEPROM.h>
|
||
#include "Types.h"
|
||
#include "timerMinim.h"
|
||
#ifdef ESP_USE_BUTTON
|
||
#include <GyverButton.h>
|
||
#endif
|
||
#include "fonts.h"
|
||
#ifdef USE_NTP
|
||
#include <NTPClient.h>
|
||
#include <Timezone.h>
|
||
#endif
|
||
#include <TimeLib.h>
|
||
#ifdef OTA
|
||
#include "OtaManager.h"
|
||
#endif
|
||
#if USE_MQTT
|
||
#include "MqttManager.h"
|
||
#endif
|
||
#include "TimerManager.h"
|
||
#include "FavoritesManager.h"
|
||
#include "EepromManager.h"
|
||
|
||
|
||
// --- ИНИЦИАЛИЗАЦИЯ ОБЪЕКТОВ ----------
|
||
CRGB leds[NUM_LEDS];
|
||
WiFiManager wifiManager;
|
||
WiFiServer wifiServer(ESP_HTTP_PORT);
|
||
WiFiUDP Udp;
|
||
|
||
#ifdef USE_NTP
|
||
WiFiUDP ntpUDP;
|
||
NTPClient timeClient(ntpUDP, NTP_ADDRESS, 0, NTP_INTERVAL); // объект, запрашивающий время с ntp сервера; в нём смещение часового пояса не используется (перенесено в объект localTimeZone); здесь всегда должно быть время UTC
|
||
#ifdef SUMMER_WINTER_TIME
|
||
TimeChangeRule summerTime = { SUMMER_TIMEZONE_NAME, SUMMER_WEEK_NUM, SUMMER_WEEKDAY, SUMMER_MONTH, SUMMER_HOUR, SUMMER_OFFSET };
|
||
TimeChangeRule winterTime = { WINTER_TIMEZONE_NAME, WINTER_WEEK_NUM, WINTER_WEEKDAY, WINTER_MONTH, WINTER_HOUR, WINTER_OFFSET };
|
||
Timezone localTimeZone(summerTime, winterTime);
|
||
#else
|
||
TimeChangeRule localTime = { LOCAL_TIMEZONE_NAME, LOCAL_WEEK_NUM, LOCAL_WEEKDAY, LOCAL_MONTH, LOCAL_HOUR, LOCAL_OFFSET };
|
||
Timezone localTimeZone(localTime);
|
||
#endif
|
||
#endif
|
||
|
||
timerMinim timeTimer(3000);
|
||
bool ntpServerAddressResolved = false;
|
||
bool timeSynched = false;
|
||
uint32_t lastTimePrinted = 0U;
|
||
|
||
#ifdef ESP_USE_BUTTON
|
||
GButton touch(BTN_PIN, LOW_PULL, NORM_OPEN);
|
||
#endif
|
||
|
||
#ifdef OTA
|
||
OtaManager otaManager(&showWarning);
|
||
OtaPhase OtaManager::OtaFlag = OtaPhase::None;
|
||
#endif
|
||
|
||
#if USE_MQTT
|
||
AsyncMqttClient* mqttClient = NULL;
|
||
AsyncMqttClient* MqttManager::mqttClient = NULL;
|
||
char* MqttManager::mqttServer = NULL;
|
||
char* MqttManager::mqttUser = NULL;
|
||
char* MqttManager::mqttPassword = NULL;
|
||
char* MqttManager::clientId = NULL;
|
||
char* MqttManager::lampInputBuffer = NULL;
|
||
char* MqttManager::topicInput = NULL;
|
||
char* MqttManager::topicOutput = NULL;
|
||
bool MqttManager::needToPublish = false;
|
||
char MqttManager::mqttBuffer[] = {};
|
||
uint32_t MqttManager::mqttLastConnectingAttempt = 0;
|
||
SendCurrentDelegate MqttManager::sendCurrentDelegate = NULL;
|
||
#endif
|
||
|
||
// --- ИНИЦИАЛИЗАЦИЯ ПЕРЕМЕННЫХ -------
|
||
uint16_t localPort = ESP_UDP_PORT;
|
||
char packetBuffer[MAX_UDP_BUFFER_SIZE]; // buffer to hold incoming packet
|
||
char inputBuffer[MAX_UDP_BUFFER_SIZE];
|
||
static const uint8_t maxDim = max(WIDTH, HEIGHT);
|
||
|
||
ModeType modes[MODE_AMOUNT];
|
||
AlarmType alarms[7];
|
||
|
||
static const uint8_t dawnOffsets[] PROGMEM = {5, 10, 15, 20, 25, 30, 40, 50, 60}; // опции для выпадающего списка параметра "время перед 'рассветом'" (будильник); синхронизировано с android приложением
|
||
uint8_t dawnMode;
|
||
bool dawnFlag = false;
|
||
uint32_t thisTime;
|
||
bool manualOff = false;
|
||
|
||
int8_t currentMode = 0;
|
||
bool loadingFlag = true;
|
||
bool ONflag = false;
|
||
uint32_t eepromTimeout;
|
||
bool settChanged = false;
|
||
bool buttonEnabled = true;
|
||
|
||
unsigned char matrixValue[8][16];
|
||
|
||
bool TimerManager::TimerRunning = false;
|
||
bool TimerManager::TimerHasFired = false;
|
||
uint8_t TimerManager::TimerOption = 1U;
|
||
uint64_t TimerManager::TimeToFire = 0ULL;
|
||
|
||
uint8_t FavoritesManager::FavoritesRunning = 0;
|
||
uint16_t FavoritesManager::Interval = DEFAULT_FAVORITES_INTERVAL;
|
||
uint16_t FavoritesManager::Dispersion = DEFAULT_FAVORITES_DISPERSION;
|
||
uint8_t FavoritesManager::UseSavedFavoritesRunning = 0;
|
||
uint8_t FavoritesManager::FavoriteModes[MODE_AMOUNT] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||
uint32_t FavoritesManager::nextModeAt = 0UL;
|
||
|
||
|
||
void setup()
|
||
{
|
||
Serial.begin(115200);
|
||
Serial.println();
|
||
ESP.wdtEnable(WDTO_8S);
|
||
|
||
|
||
// ПИНЫ
|
||
#ifdef MOSFET_PIN // инициализация пина, управляющего MOSFET транзистором в состояние "выключен"
|
||
pinMode(MOSFET_PIN, OUTPUT);
|
||
#ifdef MOSFET_LEVEL
|
||
digitalWrite(MOSFET_PIN, !MOSFET_LEVEL);
|
||
#endif
|
||
#endif
|
||
|
||
#ifdef ALARM_PIN // инициализация пина, управляющего будильником в состояние "выключен"
|
||
pinMode(ALARM_PIN, OUTPUT);
|
||
#ifdef ALARM_LEVEL
|
||
digitalWrite(ALARM_PIN, !ALARM_LEVEL);
|
||
#endif
|
||
#endif
|
||
|
||
|
||
// TELNET
|
||
#if defined(GENERAL_DEBUG) && GENERAL_DEBUG_TELNET
|
||
telnetServer.begin();
|
||
for (uint8_t i = 0; i < 100; i++) // пауза 10 секунд в отладочном режиме, чтобы успеть подключиться по протоколу telnet до вывода первых сообщений
|
||
{
|
||
handleTelnetClient();
|
||
delay(100);
|
||
ESP.wdtFeed();
|
||
}
|
||
#endif
|
||
|
||
|
||
// КНОПКА
|
||
#if defined(ESP_USE_BUTTON)
|
||
touch.setStepTimeout(BUTTON_STEP_TIMEOUT);
|
||
touch.setClickTimeout(BUTTON_CLICK_TIMEOUT);
|
||
#if ESP_RESET_ON_START
|
||
delay(1000); // ожидание инициализации модуля кнопки ttp223 (по спецификации 250мс)
|
||
if (digitalRead(BTN_PIN))
|
||
{
|
||
wifiManager.resetSettings(); // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено
|
||
LOG.println(F("Настройки WiFiManager сброшены"));
|
||
}
|
||
buttonEnabled = true; // при сбросе параметров WiFi сразу после старта с зажатой кнопкой, также разблокируется кнопка, если была заблокирована раньше
|
||
EepromManager::SaveButtonEnabled(&buttonEnabled);
|
||
ESP.wdtFeed();
|
||
#endif
|
||
#endif
|
||
|
||
|
||
// ЛЕНТА/МАТРИЦА
|
||
FastLED.addLeds<WS2812B, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS)/*.setCorrection(TypicalLEDStrip)*/;
|
||
FastLED.setBrightness(BRIGHTNESS);
|
||
if (CURRENT_LIMIT > 0)
|
||
{
|
||
FastLED.setMaxPowerInVoltsAndMilliamps(5, CURRENT_LIMIT);
|
||
}
|
||
FastLED.clear();
|
||
FastLED.show();
|
||
|
||
|
||
// EEPROM
|
||
EepromManager::InitEepromSettings( // инициализация EEPROM; запись начального состояния настроек, если их там ещё нет; инициализация настроек лампы значениями из EEPROM
|
||
modes, alarms, &espMode, &ONflag, &dawnMode, ¤tMode, &buttonEnabled,
|
||
&(FavoritesManager::ReadFavoritesFromEeprom),
|
||
&(FavoritesManager::SaveFavoritesToEeprom));
|
||
LOG.printf_P(PSTR("Рабочий режим лампы: ESP_MODE = %d\n"), espMode);
|
||
|
||
|
||
// WI-FI
|
||
wifiManager.setDebugOutput(WIFIMAN_DEBUG); // вывод отладочных сообщений
|
||
// wifiManager.setMinimumSignalQuality(); // установка минимально приемлемого уровня сигнала WiFi сетей (8% по умолчанию)
|
||
if (espMode == 0U) // режим WiFi точки доступа
|
||
{
|
||
// wifiManager.setConfigPortalBlocking(false);
|
||
|
||
if (sizeof(AP_STATIC_IP))
|
||
{
|
||
LOG.println(F("Используется статический IP адрес WiFi точки доступа"));
|
||
wifiManager.setAPStaticIPConfig( // wifiManager.startConfigPortal использовать нельзя, т.к. он блокирует вычислительный процесс внутри себя, а затем перезагружает ESP, т.е. предназначен только для ввода SSID и пароля
|
||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], AP_STATIC_IP[3]), // IP адрес WiFi точки доступа
|
||
IPAddress(AP_STATIC_IP[0], AP_STATIC_IP[1], AP_STATIC_IP[2], 1), // первый доступный IP адрес сети
|
||
IPAddress(255, 255, 255, 0)); // маска подсети
|
||
}
|
||
|
||
WiFi.softAP(AP_NAME, AP_PASS);
|
||
|
||
LOG.println(F("Старт в режиме WiFi точки доступа"));
|
||
LOG.print(F("IP адрес: "));
|
||
LOG.println(WiFi.softAPIP());
|
||
|
||
wifiServer.begin();
|
||
}
|
||
else // режим WiFi клиента (подключаемся к роутеру, если есть сохранённые SSID и пароль, иначе создаём WiFi точку доступа и запрашиваем их)
|
||
{
|
||
LOG.println(F("Старт в режиме WiFi клиента (подключение к роутеру)"));
|
||
|
||
if (WiFi.SSID().length())
|
||
{
|
||
LOG.printf_P(PSTR("Подключение к WiFi сети: %s\n"), WiFi.SSID().c_str());
|
||
}
|
||
else
|
||
{
|
||
LOG.println(F("WiFi сеть не определена, запуск WiFi точки доступа для настройки параметров подключения к WiFi сети..."));
|
||
showWarning(CRGB::Yellow, 1000U, 500U); // мигание жёлтым цветом 0,5 секунды (1 раз) - нужно ввести параметры WiFi сети для подключения
|
||
}
|
||
|
||
if (sizeof(STA_STATIC_IP))
|
||
{
|
||
LOG.print(F("Сконфигурирован статический IP адрес: "));
|
||
LOG.printf_P(PSTR("%u.%u.%u.%u\n"), STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], STA_STATIC_IP[3]);
|
||
wifiManager.setSTAStaticIPConfig(
|
||
IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], STA_STATIC_IP[3]), // статический IP адрес ESP в режиме WiFi клиента
|
||
IPAddress(STA_STATIC_IP[0], STA_STATIC_IP[1], STA_STATIC_IP[2], 1), // первый доступный IP адрес сети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы)
|
||
IPAddress(255, 255, 255, 0)); // маска подсети (справедливо для 99,99% случаев; для сетей меньше чем на 255 адресов нужно вынести в константы)
|
||
}
|
||
|
||
wifiManager.setConnectTimeout(ESP_CONN_TIMEOUT); // установка времени ожидания подключения к WiFi сети, затем старт WiFi точки доступа
|
||
wifiManager.setConfigPortalTimeout(ESP_CONF_TIMEOUT); // установка времени работы WiFi точки доступа, затем перезагрузка; отключить watchdog?
|
||
wifiManager.autoConnect(AP_NAME, AP_PASS); // пытаемся подключиться к сохранённой ранее WiFi сети; в случае ошибки, будет развёрнута WiFi точка доступа с указанными AP_NAME и паролем на время ESP_CONN_TIMEOUT секунд; http://AP_STATIC_IP:ESP_HTTP_PORT (обычно http://192.168.0.1:80) - страница для ввода SSID и пароля от WiFi сети роутера
|
||
|
||
if (WiFi.status() != WL_CONNECTED)
|
||
{
|
||
LOG.println(F("Время ожидания ввода SSID и пароля от WiFi сети или подключения к WiFi сети превышено\nЛампа будет перезагружена в режиме WiFi точки доступа!\n"));
|
||
|
||
espMode = (espMode == 0U) ? 1U : 0U;
|
||
EepromManager::SaveEspMode(&espMode);
|
||
|
||
LOG.printf_P(PSTR("Рабочий режим лампы изменён и сохранён в энергонезависимую память\nНовый рабочий режим: ESP_MODE = %d, %s\nРестарт...\n"),
|
||
espMode, espMode == 0U ? F("WiFi точка доступа") : F("WiFi клиент (подключение к роутеру)"));
|
||
|
||
showWarning(CRGB::Red, 1000U, 500U); // мигание красным цветом 0,5 секунды (1 раз) - ожидание ввода SSID'а и пароля WiFi сети прекращено, перезагрузка
|
||
ESP.restart();
|
||
}
|
||
|
||
LOG.print(F("IP адрес: "));
|
||
LOG.println(WiFi.localIP());
|
||
}
|
||
ESP.wdtFeed();
|
||
|
||
LOG.printf_P(PSTR("Порт UDP сервера: %u\n"), localPort);
|
||
Udp.begin(localPort);
|
||
|
||
|
||
// NTP
|
||
#ifdef USE_NTP
|
||
timeClient.begin();
|
||
ESP.wdtFeed();
|
||
#endif
|
||
|
||
|
||
// MQTT
|
||
#if (USE_MQTT)
|
||
if (espMode == 1U)
|
||
{
|
||
mqttClient = new AsyncMqttClient();
|
||
MqttManager::setupMqtt(mqttClient, inputBuffer, &sendCurrent); // создание экземпляров объектов для работы с MQTT, их инициализация и подключение к MQTT брокеру
|
||
}
|
||
ESP.wdtFeed();
|
||
#endif
|
||
|
||
|
||
// ОСТАЛЬНОЕ
|
||
memset(matrixValue, 0, sizeof(matrixValue));
|
||
randomSeed(micros());
|
||
changePower();
|
||
loadingFlag = true;
|
||
}
|
||
|
||
|
||
void loop()
|
||
{
|
||
parseUDP();
|
||
effectsTick();
|
||
|
||
EepromManager::HandleEepromTick(&settChanged, &eepromTimeout, &ONflag,
|
||
¤tMode, modes, &(FavoritesManager::SaveFavoritesToEeprom));
|
||
|
||
#ifdef USE_NTP
|
||
timeTick();
|
||
#endif
|
||
|
||
#ifdef ESP_USE_BUTTON
|
||
if (buttonEnabled)
|
||
{
|
||
buttonTick();
|
||
}
|
||
#endif
|
||
|
||
#ifdef OTA
|
||
otaManager.HandleOtaUpdate(); // ожидание и обработка команды на обновление прошивки по воздуху
|
||
#endif
|
||
|
||
TimerManager::HandleTimer(&ONflag, &settChanged, // обработка событий таймера отключения лампы
|
||
&eepromTimeout, &changePower);
|
||
|
||
if (FavoritesManager::HandleFavorites( // обработка режима избранных эффектов
|
||
&ONflag,
|
||
¤tMode,
|
||
&loadingFlag
|
||
#ifdef USE_NTP
|
||
, &dawnFlag
|
||
#endif
|
||
))
|
||
{
|
||
FastLED.setBrightness(modes[currentMode].Brightness);
|
||
FastLED.clear();
|
||
delay(1);
|
||
}
|
||
|
||
#if USE_MQTT
|
||
if (espMode == 1U && mqttClient && WiFi.isConnected() && !mqttClient->connected())
|
||
{
|
||
MqttManager::mqttConnect(); // библиотека не умеет восстанавливать соединение в случае потери подключения к MQTT брокеру, нужно управлять этим явно
|
||
MqttManager::needToPublish = true;
|
||
}
|
||
|
||
if (MqttManager::needToPublish)
|
||
{
|
||
if (strlen(inputBuffer) > 0) // проверка входящего MQTT сообщения; если оно не пустое - выполнение команды из него и формирование MQTT ответа
|
||
{
|
||
processInputBuffer(inputBuffer, MqttManager::mqttBuffer, true);
|
||
}
|
||
|
||
MqttManager::publishState();
|
||
}
|
||
#endif
|
||
|
||
#if defined(GENERAL_DEBUG) && GENERAL_DEBUG_TELNET
|
||
handleTelnetClient();
|
||
#endif
|
||
|
||
ESP.wdtFeed(); // пнуть собаку
|
||
}
|