diff --git a/android/LedLamp.aia b/android/LedLamp.aia index 85858a5..6911458 100644 Binary files a/android/LedLamp.aia and b/android/LedLamp.aia differ diff --git a/android/LedLamp.apk b/android/LedLamp.apk index 4489773..b3b6bfb 100644 Binary files a/android/LedLamp.apk and b/android/LedLamp.apk differ diff --git a/android/Декомпозиция.txt b/android/Декомпозиция.txt index 1ff89e1..efada89 100644 --- a/android/Декомпозиция.txt +++ b/android/Декомпозиция.txt @@ -24,6 +24,7 @@ System все системные объекты и функции Свойства и методы "классов" ScreenManager + CurrentScreenId свойство: "Текущий отображаемый 'экран'" ShowScreen метод: принимает номер "экрана", устанавливает свойство видимости в true для этого экрана и в false для остальных экранов; вызывает перерисовку "экранов" RebuildAllScreens метод: перерисовывает "экраны", делает их блоки видимыми или видимыми в зависимости от выставленных свойств видимости CloseApplication метод: закрывает приложение @@ -95,12 +96,24 @@ AlarmScreen SatTimePickerAfterTimeSet метод (событие): действия при выборе времени будильника SunTimePickerAfterTimeSet метод (событие): действия при выборе времени будильника TimeBeforeAlarmListPickerAfterPicking метод (событие): действия при выборе времени срабатывания будильника перед "рассветом" - ResetAlarmState метод: "забыть" состояние будильников в android приложении (перед последующим запросом этого состояния) UpdateScreen метод: обновить все элементы управления на "экране" управления будильниками согласно модели данных UpdateControls метод: обновить отображение элементов управления (статусы enabled/disabled) в зависимости от сохранённых свойств (модели данных) TimerScreen Visible свойство: "Видимость экрана устройств" + Initialized свойство: "Экран управления таймером инициализирован" + BlockControlEventsEmitting свойство: "Не генерировать события от элементов управления" (лист пикера); нужно, например, чтобы предотвратить listpicker.afterpicking при его enable/disable + AnimationTimerOn свойство: "таймер, управляющий анимацией функции таймера лампы, включен" + RemainingSeconds свойство: "время до срабатывания таймера лампы" и одновремнно "время до окончания работы таймера, управляющего анимацией функции таймера лампы" + TimerTickMs свойство: "шаг таймера, управляющего анимацией функции таймера лампы" + TimeListPickerAfterPicking метод (событие): действия при выборе пользователем времени до срабатывания таймера лампы (отправка команды модулю) + UpdateControls метод: обновить отображение элементов управления (статусы enabled/disabled) в зависимости от сохранённых свойств (модели данных) + UpdateScreen метод: обновить все элементы управления на "экране" управления таймером согласно модели данных + GetRemainingLabelText метод: получить текст для вывода на метке оставшегося до срабатывания таймера времени + GetTimerSecondsToFire метод: получить количество секунд до срабатывания таймера из полученного в качестве аргумента значения TimeListPicker (выбранной пользователем опции) + HandleAnimation метод: обработать таймер, управляющий анимацией функции таймера лампы (запуск, если не запущен, принудительная остановка, если нужно) + AnimationTimerTimerNow метод: действия при срабатывании события таймера, управляющий анимацией функции таймера лампы (показать/скрыть иконку, обновить текст оставшегося времени) + StopAnimationTimer метод: остановить таймер, управляющий анимацией функции таймера лампы, сбросить его сохранённое состояние в исходное (модель данных) BaсkButtonClick метод (событие): действия при UI кнопки "Назад" на "экране" таймера DeviceManager @@ -109,19 +122,21 @@ DeviceManager Devices свойство: список устройств (хранимое свойство) CurrentDeviceSocket свойство: текущее устройство (хранимое свойство) AlarmState свойство: текущее состояние будильников по дням (вкл/выкл, время каждого, время срабатывания перед "рассветом") + TimerState свойство: текущее состояние таймера (ответ команды TMR_GET) Modes свойство: список доступных режимов, захардкожен одновременно в лампе и в приложении, должен совпадать Initialize метод: вычитывание хранимых свойств и инициализация соответствующих переменных ConnectDeviceSocket метод: стартовать таймер (polling timer) с регулярной отправкой команд GET/DEB на устройство DisconnectDeviceSocket метод: остановить таймер (polling timer) с регулярной отправкой команд GET/DEB на устройство; очистить свойства Connected и State - GetCurrentModeId метод: получить номер текущего эффекта из свойства State - GetCurrentModeName метод: получить имя текущего эффекта из свойства State - GetCurrentBrightness метод: получить значение текущей яркости из свойства State - GetCurrentSpeed метод: получить значение текущей скорости из свойства State - GetCurrentScale метод: получить значение текущего масштаба из свойства State - GetCurrentOn метод: получить значение текущего состояния Вкл/Выкл из свойства State - GetCurrentEspMode метод: получить значение текущего состояния ESP_MODE из свойства State - GetCurrentUseNtp метод: получить значение текущего состояния USE_NTP из свойства State - GetCurrentUseTime метод: получить значение текущего времени на устройстве из свойства State + GetCurrentModeId метод: получить номер текущего эффекта (из свойства State) + GetCurrentModeName метод: получить имя текущего эффекта (из свойства State) + GetCurrentBrightness метод: получить значение текущей яркости (из свойства State) + GetCurrentSpeed метод: получить значение текущей скорости (из свойства State) + GetCurrentScale метод: получить значение текущего масштаба (из свойства State) + GetCurrentOn метод: получить значение текущего состояния Вкл/Выкл (из свойства State) + GetCurrentEspMode метод: получить значение текущего состояния ESP_MODE (из свойства State) + GetCurrentUseNtp метод: получить значение текущего состояния USE_NTP 9из свойства State) + GetTimerOnOffFromState метод: получить значение текущего состояния таймера (из свойства State) + GetCurrentTime метод: получить значение текущего времени на устройстве (из свойства State) SaveDeviceSocketSettings метод: сохранить с базу данных приложения хранимые значения (текущее стройство и список устройств) SetDeviceOffline метод: установить свойства Connected и State в начальное состояние (очистить), соответствует состоянию "устройство не подключено" ResetCurrentDevice метод: установить свойство CurrentDeviceSocket в начальное состояние (очистить), соответствует состоянию "устройство не выбрано" @@ -129,13 +144,20 @@ DeviceManager ValidateIpPort метод: валидировать переданное в качестве параметра значение IP адреса или порта SendUdpCommand метод: отправить команду, приянтую в качестве входного аргумента, на подключенное устройствоС (обобщённый метод) HandleDeviceResponse метод: обработать ответ от подключенного устройства на отправленные команды - GetAlarms метод: отправить команду запроса состояния будильников ALM_GET на устройство + ResetAlarmState метод: "забыть" состояние будильников в android приложении (перед последующим запросом этого состояния) + GetAlarmsSettings метод: отправить команду запроса состояния будильников ALM_GET на устройство GetAlarmOnOff метод: получить состояние вкл/выкл будильника для указанного во входном аргументе дня (из свойства AlarmState) GetAlarmTime метод: получить время срабатывания будильника для указанного во входном аргументе дня (из свойства AlarmState) GetTimeBeforeAlarmIndex метод: получить время срабатывания будильника перед "рассветом" SetAlarmOnOff метод: отправить команду вкл/выкл будильника для заданного дня ALM_SET на устройство SetAlarmTime метод: отправить команду установки времени срабатывания будильника для заданного дня ALM_SET на устройство SetTimeBeforeAlarm метод: отправить команду установки времени срабатывания будильника перед "рассветом" DAWN на устройство + ResetTimerState метод: "забыть" состояние таймера в android приложении (перед последующим запросом этого состояния) + GetTimerSettings метод: отправить команду запроса состояния таймера TMR_GET на устройство + GetTimerOnOff метод: получить значение текущего состояния таймера (из свойства TimerState) + GetTimerTimeOption метод: получить выбранное пользователем значение предуст ановки времени таймера (из свойства TimerState) + GetTimerRemainingSeconds метод: получить оставшееся до срабатывания таймера время (из свойства TimerState) + SetTimerSettings метод: отправить команду установки таймера TMR_SET DiscoverManager TimeoutMs свойство: время ожидания ответа от устройств на multicast команду DISCOVER @@ -171,3 +193,4 @@ StringHelper GetPortFromIpPortString метод: получить PORT из входного параметра формата IP:PORT GetFormattedTimeFromMinutes метод: получить строку с временем в формате hh:mm из входного аргумента (количество минут) GetMinutesFromFormattedTime метод: получить количество минут из форматированной строки (hh:mm), переданной в качестве входного аргумента + diff --git a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino index 4d959e5..4ccaf20 100644 --- a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino +++ b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino @@ -42,6 +42,8 @@ --- 10.08.2019 - Добавлена точная настройка яркости, скорости и масштаба эффектов - Добавлено взаимодействие с android приложением по управлению будильниками + --- 14.08.2019 + - Добавлена функция таймера отключения */ // Ссылка для менеджера плат: @@ -127,6 +129,7 @@ uint8_t AP_STATIC_IP[] = {192, 168, 4, 1}; // статичес #ifdef OTA #include "OtaManager.h" #endif +#include "TimerManager.h" // --- ИНИЦИАЛИЗАЦИЯ ОБЪЕКТОВ ---------- CRGB leds[NUM_LEDS]; @@ -168,7 +171,7 @@ struct int16_t time = 0; } alarm[7]; -uint8_t dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60}; +uint8_t dawnOffsets[] = {5, 10, 15, 20, 25, 30, 40, 50, 60};// опции для выпадающего списка параметра "время перед 'рассветом'" (будильник) uint8_t dawnMode; boolean dawnFlag = false; long thisTime; @@ -179,12 +182,18 @@ boolean loadingFlag = true; boolean ONflag = true; uint32_t eepromTimer; boolean settChanged = false; + // Конфетти, Огонь, Радуга верт., Радуга гориз., Смена цвета, // Безумие 3D, Облака 3D, Лава 3D, Плазма 3D, Радуга 3D, // Павлин 3D, Зебра 3D, Лес 3D, Океан 3D, unsigned char matrixValue[8][16]; +bool TimerManager::TimerRunning = false; +bool TimerManager::TimerHasFired = false; +uint8_t TimerManager::TimerOption = 1U; +uint64_t TimerManager::TimeToFire = 0ULL; + void setup() { @@ -348,6 +357,7 @@ void loop() #ifdef OTA otaManager.HandleOtaUpdate(); // ожидание и обработка команды на обновление прошивки по воздуху #endif + TimerManager::HandleTimer(&ONflag, &changePower); // обработка событий таймера отключения лампы ESP.wdtFeed(); // пнуть собаку yield(); // обработать все "служебные" задачи: WiFi подключение и т.д. } diff --git a/firmware/GyverLamp_v1.4/TimerManager.h b/firmware/GyverLamp_v1.4/TimerManager.h new file mode 100644 index 0000000..05008d4 --- /dev/null +++ b/firmware/GyverLamp_v1.4/TimerManager.h @@ -0,0 +1,30 @@ +class TimerManager +{ + public: + static bool TimerRunning; // флаг "таймер взведён" + static bool TimerHasFired; // флаг "таймер отработал" + static uint8_t TimerOption; // индекс элемента в списке List Picker'а + static uint64_t TimeToFire; // время, в которое должен сработать таймер (millis) + + static void HandleTimer( // функция, обрабатывающая срабатывание таймера, гасит матрицу + bool *ONflag, + void (*changePower)()) + { + if (!TimerManager::TimerHasFired && + TimerManager::TimerRunning && + millis() >= TimerManager::TimeToFire) + { + #ifdef GENERAL_DEBUG + Serial.printf("Выключение по таймеру\n\n"); + #endif + + TimerManager::TimerRunning = false; + TimerManager::TimerHasFired = true; + FastLED.clear(); + delay(2); + FastLED.show(); + *ONflag = !(*ONflag); + changePower(); + } + } +}; diff --git a/firmware/GyverLamp_v1.4/effectTicker.ino b/firmware/GyverLamp_v1.4/effectTicker.ino index 20937aa..281b94f 100644 --- a/firmware/GyverLamp_v1.4/effectTicker.ino +++ b/firmware/GyverLamp_v1.4/effectTicker.ino @@ -57,10 +57,6 @@ void effectsTick() void changePower() { - #ifdef GENERAL_DEBUG - Serial.printf("changePower(); brightness: %d\n", modes[currentMode].brightness); - #endif - if (ONflag) { effectsTick(); @@ -87,4 +83,7 @@ void changePower() delay(2); FastLED.show(); } + TimerManager::TimerRunning = false; + TimerManager::TimerHasFired = false; + TimerManager::TimeToFire = 0ULL; } diff --git a/firmware/GyverLamp_v1.4/noiseEffects.ino b/firmware/GyverLamp_v1.4/noiseEffects.ino index 6562e69..a2b566e 100644 --- a/firmware/GyverLamp_v1.4/noiseEffects.ino +++ b/firmware/GyverLamp_v1.4/noiseEffects.ino @@ -28,7 +28,7 @@ uint8_t noise[WIDTH][WIDTH]; uint8_t noise[HEIGHT][HEIGHT]; #endif -CRGBPalette16 currentPalette( PartyColors_p ); +CRGBPalette16 currentPalette(PartyColors_p); uint8_t colorLoop = 1; uint8_t ihue = 0; diff --git a/firmware/GyverLamp_v1.4/parsing.ino b/firmware/GyverLamp_v1.4/parsing.ino index eccfb45..bfddf91 100644 --- a/firmware/GyverLamp_v1.4/parsing.ino +++ b/firmware/GyverLamp_v1.4/parsing.ino @@ -132,6 +132,20 @@ void parseUDP() } } + else if (inputBuffer.startsWith("TMR_GET")) + { + sendTimer(); + } + + else if (inputBuffer.startsWith("TMR_SET")) + { + TimerManager::TimerRunning = inputBuffer.substring(8, 9).toInt(); + TimerManager::TimerOption = inputBuffer.substring(10, 11).toInt(); + TimerManager::TimeToFire = millis() + (uint64_t)(inputBuffer.substring(12).toInt() * 1000); + TimerManager::TimerHasFired = false; + sendTimer(); + } + else { inputBuffer = ""; @@ -184,6 +198,8 @@ void sendCurrent() inputBuffer += "0"; #endif inputBuffer += " "; + inputBuffer += String((uint8_t)TimerManager::TimerRunning); + inputBuffer += " "; #ifdef USE_NTP inputBuffer += timeClient.getFormattedTime(); #else @@ -208,3 +224,14 @@ void sendAlarms() } inputBuffer += (dawnMode + 1); } + +void sendTimer() +{ + inputBuffer = "TMR"; + inputBuffer += " "; + inputBuffer += String((uint8_t)TimerManager::TimerRunning); + inputBuffer += " "; + inputBuffer += String(TimerManager::TimerOption); + inputBuffer += " "; + inputBuffer += String(TimerManager::TimerRunning ? (uint16_t)floor((TimerManager::TimeToFire - millis()) / 1000) : 0); +}