diff --git a/android/LedLamp.aia b/android/LedLamp.aia index 72abdcc..656a561 100644 Binary files a/android/LedLamp.aia and b/android/LedLamp.aia differ diff --git a/android/LedLamp.apk b/android/LedLamp.apk index d50fb05..bbba2f8 100644 Binary files a/android/LedLamp.apk and b/android/LedLamp.apk differ diff --git a/firmware/GyverLamp_v1.4/Constants.h b/firmware/GyverLamp_v1.4/Constants.h index a16b49f..8e8afd0 100644 --- a/firmware/GyverLamp_v1.4/Constants.h +++ b/firmware/GyverLamp_v1.4/Constants.h @@ -5,6 +5,7 @@ // --- ESP ----------------------------- #define ESP_MODE (1U) // 0U - WiFi точка доступа, 1U - клиент WiFi (подключение к роутеру) #define ESP_USE_BUTTON // если строка не закомментирована, должна быть подключена кнопка (иначе ESP может регистрировать "фантомные" нажатия и некорректно устанавливать яркость) +#define ESP_RESET_ON_STASRT (false) // true - если при старте нажата кнопка (или кнопки нет!), сохранённые настройки будут сброшены; false - не будут #define ESP_HTTP_PORT (80U) // номер порта, который будет использоваться во время первой утановки имени WiFi сети (и пароля), к которой потом будет подключаться лампа в режиме WiFi клиента (лучше не менять) #define ESP_UDP_PORT (8888U) // номер порта, который будет "слушать" UDP сервер во время работы лампы как в режиме WiFi точки доступа, так и в режиме WiFi клиента (лучше не менять) #define ESP_CONN_TIMEOUT (7U) // время в секундах (ДОЛЖНО БЫТЬ МЕНЬШЕ 8, иначе сработает WDT), которое ESP будет пытаться подключиться к WiFi сети, после его истечения автоматически развернёт WiFi точку доступа diff --git a/firmware/GyverLamp_v1.4/EepromManager.h b/firmware/GyverLamp_v1.4/EepromManager.h index 59ea2da..029da8c 100644 --- a/firmware/GyverLamp_v1.4/EepromManager.h +++ b/firmware/GyverLamp_v1.4/EepromManager.h @@ -6,19 +6,19 @@ * Начало Длина Описание * массив alarm * 0 1 будильник пн вкл/выкл - * 1-2 2 будильник пн время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 1-2 2 будильник пн время в минутах от начала суток (0 - 1440), 2 байта * 3 1 будильник вт вкл/выкл - * 4-5 2 будильник вт время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 4-5 2 будильник вт время в минутах от начала суток (0 - 1440), 2 байта * 6 1 будильник ср вкл/выкл - * 7-8 2 будильник ср время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 7-8 2 будильник ср время в минутах от начала суток (0 - 1440), 2 байта * 9 1 будильник чт вкл/выкл - * 10-11 2 будильник чт время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 10-11 2 будильник чт время в минутах от начала суток (0 - 1440), 2 байта * 12 1 будильник пт вкл/выкл - * 13-14 2 будильник пт время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 13-14 2 будильник пт время в минутах от начала суток (0 - 1440), 2 байта * 15 1 будильник сб вкл/выкл - * 16-17 2 будильник сб время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 16-17 2 будильник сб время в минутах от начала суток (0 - 1440), 2 байта * 18 1 будильник вс вкл/выкл - * 19-20 2 будильник вс время в минутах от начала суток (0 - 1440), должно быть 2 байта + * 19-20 2 будильник вс время в минутах от начала суток (0 - 1440), 2 байта * массив modes * 21-23 3 режим №1: яркость, скорость, масштаб (по одному байту) * 24-26 3 режим №2: яркость, скорость, масштаб (по одному байту) @@ -46,7 +46,7 @@ * 90-92 3 режим №24: яркость, скорость, масштаб (по одному байту) * 93-95 3 режим №25: яркость, скорость, масштаб (по одному байту) * - * 111-134 24 настройки режима избранных эффектов (интервал - 2 байта; разброс - 2 байта; вкл/выкл каждого эффекта - 20 (MODE_AMOUNT) байт; вкл/выкл не хранится в EEPROM) + * 111-141 31 настройки режима избранных эффектов (вкл/выкл - 1 байт; интервал - 2 байта; разброс - 2 байта; инициализировать вкл/выкл - 1 байт; вкл/выкл каждого эффекта - 25 (MODE_AMOUNT) байт; вкл/выкл не хранится в EEPROM) * * 197 1 состояние лампы (вкл/выкл) * 198 1 признак первого запуска (определяет необходимость первоначальной записи всех хранимых настроек) @@ -55,7 +55,7 @@ * * Не используются адреса: * 96-110 15 резерв, можно добавить ещё 5 эффектов - * 135-196 62 если добавить ещё 10 эффектов, начальный адрес неиспользуемой памяти сдвинется с 135 на 145 + * 142-196 55 если добавить ещё 5 эффектов, начальный адрес неиспользуемой памяти сдвинется с 142 на 147 */ #include diff --git a/firmware/GyverLamp_v1.4/FavoritesManager.h b/firmware/GyverLamp_v1.4/FavoritesManager.h index d158bb7..5aeffd7 100644 --- a/firmware/GyverLamp_v1.4/FavoritesManager.h +++ b/firmware/GyverLamp_v1.4/FavoritesManager.h @@ -9,9 +9,10 @@ class FavoritesManager { public: - static bool FavoritesRunning; // флаг "работает режим автоматической смены избранных эффектов" + static uint8_t FavoritesRunning; // флаг "работает режим автоматической смены избранных эффектов" static uint16_t Interval; // статический интервал (время между сменами эффектов) static uint16_t Dispersion; // дополнительный динамический (случайный) интервал (время между сменами эффектов) + static uint8_t UseSavedFavoritesRunning; // флаг, определяющий, нужно ли использовать сохранённое значение FavoritesRunning при перезапуске; еслин нет, "избранное" будет выключено при старте static uint8_t FavoriteModes[MODE_AMOUNT]; // массив, каждый элемент которого соответствует флагу "эффект №... добавлен в избранные" static void SetStatus(char* statusText) // помещает в statusText состояние режима работы избранных эффектов @@ -19,8 +20,10 @@ class FavoritesManager char buff[6]; strcpy_P(statusText, PSTR("FAV ")); - strcat_P(statusText, FavoritesRunning ? PSTR("1") : PSTR("0")); + itoa(FavoritesRunning, buff, 10); + strcat(statusText, buff); strcat_P(statusText, PSTR(" ")); + buff[0] = '\0'; itoa(Interval, buff, 10); strcat(statusText, buff); @@ -32,9 +35,14 @@ class FavoritesManager strcat_P(statusText, PSTR(" ")); buff[0] = '\0'; + itoa(UseSavedFavoritesRunning, buff, 10); + strcat(statusText, buff); + strcat_P(statusText, PSTR(" ")); + buff[0] = '\0'; + for (uint8_t i = 0; i < MODE_AMOUNT; i++) { - itoa((uint8_t)FavoriteModes[i], buff, 10); + itoa(FavoriteModes[i], buff, 10); strcat(statusText, buff); if (i < MODE_AMOUNT - 1) strcat_P(statusText, PSTR(" ")); buff[0] = '\0'; @@ -46,12 +54,13 @@ class FavoritesManager static void ConfigureFavorites(const char* statusText) // принимает statusText, парсит его и инициализирует свойства класса значениями из statusText'а { FavoritesRunning = getFavoritesRunning(statusText); - if (!FavoritesRunning) + if (FavoritesRunning == 0) { nextModeAt = 0; } Interval = getInterval(statusText); Dispersion = getDispersion(statusText); + UseSavedFavoritesRunning = getUseSavedFavoritesRunning(statusText); for (uint8_t i = 0; i < MODE_AMOUNT; i++) { FavoriteModes[i] = getModeOnOff(statusText, i); @@ -67,7 +76,7 @@ class FavoritesManager #endif ) { - if (!FavoritesRunning || + if (FavoritesRunning == 0 || !*ONflag // лампа не переключается на следующий эффект при выключенной матрице #ifdef USE_NTP || *dawnFlag // лампа не переключается на следующий эффект при включенном будильнике @@ -79,7 +88,7 @@ class FavoritesManager if (nextModeAt == 0) // лампа не переключается на следующий эффект сразу после включения режима избранных эффектов { - nextModeAt = getNexTime(); + nextModeAt = getNextTime(); return false; } @@ -87,7 +96,7 @@ class FavoritesManager { *currentMode = getNextFavoriteMode(currentMode); *loadingFlag = true; - nextModeAt = getNexTime(); + nextModeAt = getNextTime(); #ifdef GENERAL_DEBUG Serial.printf_P(PSTR("Переключение на следующий избранный режим: %d\n\n"), (*currentMode)); @@ -101,25 +110,28 @@ class FavoritesManager static void ReadFavoritesFromEeprom() { - Interval = EepromManager::ReadUint16(EEPROM_FAVORITES_START_ADDRESS); - Dispersion = EepromManager::ReadUint16(EEPROM_FAVORITES_START_ADDRESS + 2); + Interval = EepromManager::ReadUint16(EEPROM_FAVORITES_START_ADDRESS + 1); + Dispersion = EepromManager::ReadUint16(EEPROM_FAVORITES_START_ADDRESS + 3); + UseSavedFavoritesRunning = EEPROM.read(EEPROM_FAVORITES_START_ADDRESS + 5); + FavoritesRunning = UseSavedFavoritesRunning > 0 ? EEPROM.read(EEPROM_FAVORITES_START_ADDRESS) : FavoritesRunning; for (uint8_t i = 0; i < MODE_AMOUNT; i++) { - FavoriteModes[i] = EEPROM.read(EEPROM_FAVORITES_START_ADDRESS + i + 4); + FavoriteModes[i] = EEPROM.read(EEPROM_FAVORITES_START_ADDRESS + i + 6); FavoriteModes[i] = FavoriteModes[i] > 0 ? 1 : 0; } } static void SaveFavoritesToEeprom() { - // FavoritesRunning в EEPROM не сохраняем для экономии ресурса памяти - EepromManager::WriteUint16(EEPROM_FAVORITES_START_ADDRESS, Interval); - EepromManager::WriteUint16(EEPROM_FAVORITES_START_ADDRESS + 2, Dispersion); + EEPROM.put(EEPROM_FAVORITES_START_ADDRESS, FavoritesRunning); + EepromManager::WriteUint16(EEPROM_FAVORITES_START_ADDRESS + 1, Interval); + EepromManager::WriteUint16(EEPROM_FAVORITES_START_ADDRESS + 3, Dispersion); + EEPROM.put(EEPROM_FAVORITES_START_ADDRESS + 5, UseSavedFavoritesRunning); for (uint8_t i = 0; i < MODE_AMOUNT; i++) { - EEPROM.put(EEPROM_FAVORITES_START_ADDRESS + i + 4, FavoriteModes[i] > 0 ? 1 : 0); + EEPROM.put(EEPROM_FAVORITES_START_ADDRESS + i + 6, FavoriteModes[i] > 0 ? 1 : 0); } EEPROM.commit(); @@ -127,14 +139,14 @@ class FavoritesManager static void TurnFavoritesOff() { - FavoritesRunning = false; + FavoritesRunning = 0; nextModeAt = 0; } private: static uint32_t nextModeAt; // ближайшее время переключения на следующий избранный эффект (millis()) - static bool isStatusTextCorrect(const char* statusText) // валидирует statusText (проверяет, правильное ли коичество компонентов он содержит) + static bool isStatusTextCorrect(const char* statusText) // валидирует statusText (проверяет, правильное ли количество компонентов он содержит) { char buff[MAX_UDP_BUFFER_SIZE]; strcpy(buff, statusText); @@ -152,23 +164,24 @@ class FavoritesManager static uint8_t getStatusTextNormalComponentsCount() // возвращает правильное ли коичество компонентов для statusText в зависимости от определённого формата команды и количества эффектов { - // "FAV 0/1 <цифра> <цифра> <массив цифр 0/1 для каждого режима>" (вкл/выкл, интервал в секундах, разброс в секундах, вкл/выкл каждого эффекта в избранные) + // "FAV 0/1 <цифра> <цифра> 0/1 <массив цифр 0/1 для каждого режима>" (вкл/выкл, интервал в секундах, разброс в секундах, использовать ли хранимый вкл/выкл, вкл/выкл каждого эффекта в избранные) return 1 + // "FAV" - 1 + // On/Off + 1 + // вкл/выкл 1 + // интервал 1 + // разброс + 1 + // использовать ли хранимый вкл/выкл MODE_AMOUNT; // 0/1 для каждого эффекта } - static bool getFavoritesRunning(const char* statusText) // возвращает признак вкл/выкл режима избранных эффектов из statusText + static uint8_t getFavoritesRunning(const char* statusText) // возвращает признак вкл/выкл режима избранных эффектов из statusText { char lexem[2]; memset(lexem, 0, 2); strcpy(lexem, getLexNo(statusText, 1)); return lexem != NULL ? !strcmp(lexem, "1") - : false; + : 0; } static uint16_t getInterval(const char* statusText) // возвращает интервал (постоянную составляющую) переключения избранных эффектов из statusText @@ -191,11 +204,21 @@ class FavoritesManager : DEFAULT_FAVORITES_DISPERSION; } + static uint8_t getUseSavedFavoritesRunning(const char* statusText)// возвращает признак вкл/выкл режима избранных эффектов из statusText + { + char lexem[2]; + memset(lexem, 0, 2); + strcpy(lexem, getLexNo(statusText, 4)); + return lexem != NULL + ? !strcmp(lexem, "1") + : 0; + } + static bool getModeOnOff(const char* statusText, uint8_t modeId) // возвращает признак включения указанного эффекта в избранные эффекты { char lexem[2]; memset(lexem, 0, 2); - strcpy(lexem, getLexNo(statusText, modeId + 4)); + strcpy(lexem, getLexNo(statusText, modeId + 5)); return lexem != NULL ? !strcmp(lexem, "1") : false; @@ -248,7 +271,7 @@ class FavoritesManager return result; } - static uint32_t getNexTime() // определяет время следующего переключения на следующий избранный эффект + static uint32_t getNextTime() // определяет время следующего переключения на следующий избранный эффект { return millis() + Interval * 1000 + random(0, Dispersion + 1) * 1000; } diff --git a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino index 9698cdd..411311e 100644 --- a/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino +++ b/firmware/GyverLamp_v1.4/GyverLamp_v1.4.ino @@ -62,6 +62,9 @@ - Добавлено сохранение состояния (вкл/выкл) лампы в EEPROM память - Добавлен новый эффект белого света (с горизонтальной полосой) - Реорганизован код, исправлены ошибки + --- 20.09.2019 + - Добавлена возможность сохранять состояние (вкл/выкл) режима "Избранное"; не сбрасывается выключением матрицы, не сбрасывается перезапуском модуля esp + - Убрана очистка параметров WiFi при старте с зажатой кнопкой; регулируется директивой ESP_RESET_ON_STASRT, которая определена как false по умолчанию */ // Ссылка для менеджера плат: @@ -141,9 +144,10 @@ bool TimerManager::TimerHasFired = false; uint8_t TimerManager::TimerOption = 1U; uint64_t TimerManager::TimeToFire = 0ULL; -bool FavoritesManager::FavoritesRunning = false; +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; @@ -156,11 +160,11 @@ void setup() ESP.wdtDisable(); //ESP.wdtEnable(WDTO_8S); - #ifdef ESP_USE_BUTTON + #ifdef ESP_USE_BUTTON && ESP_RESET_ON_STASRT touch.setStepTimeout(100); touch.setClickTimeout(500); buttonTick(); - if (touch.state()) // сброс сохранённых SSID и пароля при старте с зажатой кнопкой + if (touch.state()) // сброс сохранённых SSID и пароля при старте с зажатой кнопкой, если разрешено { wifiManager.resetSettings(); diff --git a/firmware/GyverLamp_v1.4/effectTicker.ino b/firmware/GyverLamp_v1.4/effectTicker.ino index 37e343f..8114046 100644 --- a/firmware/GyverLamp_v1.4/effectTicker.ino +++ b/firmware/GyverLamp_v1.4/effectTicker.ino @@ -74,5 +74,8 @@ void changePower() TimerManager::TimerHasFired = false; TimerManager::TimeToFire = 0ULL; - FavoritesManager::TurnFavoritesOff(); + if (FavoritesManager::UseSavedFavoritesRunning == 0) // если выбрана опция Сохранять состояние (вкл/выкл) "избранного", то ни выключение модуля, ни выключение матрицы не сбрасывают текущее состояние (вкл/выкл) "избранного" + { + FavoritesManager::TurnFavoritesOff(); + } }