Merge branch 'main' into platformio

This commit is contained in:
Alex
2021-07-14 00:21:22 +03:00
committed by GitHub
14 changed files with 197 additions and 146 deletions

Binary file not shown.

Binary file not shown.

View File

@@ -1,22 +1,30 @@
void sendUDP(char *data) {
Udp.beginPacket(deviceIP, portNum + cfg.group);
Udp.beginPacket(broadIP, portNum + cfg.group);
Udp.write(data);
Udp.endPacket();
}
void sendUDP(byte cmd, int data1 = 0, int data2 = 0, int data3 = 0) {
char reply[20] = "";
mString packet(reply, sizeof(reply));
mString packet(reply);
packet = packet + "GL," + cmd + ',' + data1 + ',' + data2 + ',' + data3;
sendUDP(reply);
//DEBUG("Sending: ");
//DEBUGLN(cmd);
}
void iAmOnline() {
if (onlineTmr.isReady()) {
char reply[10] = "GL_ONL";
mString packet(reply);
packet += cfg.curPreset;
sendUDP(reply);
}
}
void restartUDP() {
Udp.stop();
Udp.begin(portNum + cfg.group);
deviceIP = WiFi.localIP();
deviceIP[3] = 255;
broadIP = WiFi.localIP();
broadIP[3] = 255;
DEBUG("UDP port: ");
DEBUGLN(portNum + cfg.group);
}
@@ -60,7 +68,7 @@ void drawDots(int X, int Y, CRGB color) {
}
void drawClock(byte Y, byte speed, CRGB color) {
if (cfg.deviceType == 1 || cfg.width < 16) return; // лента или мелкая матрица - на выход
if (cfg.deviceType == 1) return; // лента - на выход
byte h1, h2, m1, m2;
if (gotNTP || gotTime) {
h1 = now.hour / 10;
@@ -70,8 +78,10 @@ void drawClock(byte Y, byte speed, CRGB color) {
m2 = now.min % 10;
} else {
h1 = h2 = m1 = m2 = 10;
}
int pos = cfg.width - (now.weekMs / (speed * 2)) % (cfg.width + 26);
}
int pos;
if (speed == 0) pos = cfg.width / 2 - 13;
else pos = cfg.width - (now.weekMs / (speed * 2)) % (cfg.width + 26);
drawDigit(h1, pos, Y, color);
drawDigit(h2, pos + 6, Y, color);
if (now.getMs() < 500) drawDots(pos + 12, Y, color);

View File

@@ -1,73 +1,27 @@
/*
Версия 0.19b
Минимальная версия приложения 1.17!!!
Почищен мусор, оптимизация, повышена стабильность и производительность
Мигает теперь 16 светиков
Снова переделана сетевая политика, упрощён и сильно ускорен парсинг
Изменены пределы по светодиодам, что сильно увеличило производительность
Выключенная (программно) лампа не принимает сервисные команды кроме команды включиться
Добавлены часы, в том числе в рассвет
Slave работает со светомузыкой сам, если не получает данные с мастера
Версия 0.18b
Уменьшена чувствительность хлопков
Увеличена плавность светомузыки
Переделана сетевая политика
Микрофон и датчик света опрашивает только мастер и отсылает данные слейвам своей группы
4 клика - включить первый режим
Отправка точного времени на лампу в режиме АР для работы рассвета и синхронизации эффектов
Версия 0.17b
Автосмена отключается 30 сек во время настройки режимов
Убрана кнопка upload в режимах
Лампа чуть мигает при получении данных
Кастом палитра работает на огне 2020
Вкл выкл двумя хлопками
Плавное выключение
Починил рассвет
Версия 0.16b
Исправлен масштаб огня 2020
Фикс невыключения рассвета
Версия 0.14b
Мелкие баги
Вернул искры огню
Добавлены палитры
Добавлен огонь 2020
Версия 0.13b
Улучшена стабильность
Версия 0.12b
Мелкие исправления
Версия 0.11b
Добавлен редактор палитр
Исправлены мелкие баги в эффектах
Переподключение к роутеру после сброса сети
Настройка ориентации матрицы из приложения
Переработан эффект "Частицы"
Добавлена скорость огня
Переключение на новый/выбранный режим при редактировании
Отправка времени из сервиса (для АР)
Выключение по таймеру теперь плавное
Добавлен рассвет
TODO:
плавная смена режимов
Mqtt?
Базовый пак
Эффект погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ!
ДЛЯ КОМПИЛЯЦИИ ПРОШИВКИ ПОД NODEMCU/WEMOS/ESP01/ESP12 ВЫБИРАТЬ
Инструменты / Плата Generic ESP8266
Инструменты / Flash Size 4MB (FS:2MB OTA)
CPU Frequency / 160 MHz (рекомендуется для стабильности светомузыки!!!)
При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents
ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json
FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases
*/
// ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ! ВНИМАНИЕ!
// ДЛЯ КОМПИЛЯЦИИ ПРОШИВКИ ПОД NODEMCU/WEMOS/ESP01/ESP12 ВЫБИРАТЬ
// Инструменты/Плата Generic ESP8266
// Инструменты/Flash Size 4MB (FS:2MB OTA)
// При прошивке с других прошивок лампы поставить: Инструменты/Erase Flash/All Flash Contents
// ESP core 2.7.4+ http://arduino.esp8266.com/stable/package_esp8266com_index.json
// FastLED 3.4.0+ https://github.com/FastLED/FastLED/releases
/*
Версия 0.23b
Поправлена яркость рассвета
TODO:
Upload -> Применить
Длина огня в светомуз?
Плавная смена режимов
Mqtt
Базовый пак
Поддержка куба
Погода https://it4it.club/topic/40-esp8266-i-parsing-pogodyi-s-openweathermap/
*/
// ---------- Настройки -----------
#define GL_KEY "GL" // ключ сети
@@ -83,7 +37,7 @@
#define PHOT_VCC 14 // питание фоторезистора GPIO14 (D5 на wemos/node)
// ------------ Лента -------------
#define STRIP_PIN 2 // пин ленты GPIO2 (D4 на wemos/node)
#define STRIP_PIN 2 // пин ленты GPIO2 (D4 на wemos/node), GPIO5 (D1) для module
#define MAX_LEDS 300 // макс. светодиодов
#define STRIP_CHIP WS2812 // чип ленты
#define STRIP_COLOR GRB // порядок цветов в ленте
@@ -101,30 +55,43 @@ const char AP_NameChar[] = "GyverLamp2";
const char WiFiPassword[] = "12345678";
// ------------ Прочее -------------
#define GL_VERSION 19 // код версии прошивки
#define GL_VERSION 23 // код версии прошивки
#define EE_TOUT 30000 // таймаут сохранения епром после изменения, мс
#define DEBUG_SERIAL_LAMP // закомментируй чтобы выключить отладку (скорость 115200)
#define EE_KEY 55 // ключ сброса WiFi (измени для сброса всех настроек)
#define EE_KEY 56 // ключ сброса eeprom
#define NTP_UPD_PRD 5 // период обновления времени с NTP сервера, минут
//#define SKIP_WIFI // пропустить подключение к вафле (для отладки)
// ------------ БИЛДЕР -------------
//#define MAX_LEDS 900
#define GL_BUILD 0 // 0: com 300, 1: com 900, 2: esp1 300, 3: esp1 900, 4: module 300, 5: module 900
// esp01
//#define BTN_PIN 0
//#define STRIP_PIN 2
//#define USE_ADC 0
// GL2 module
//#define STRIP_PIN 5 // GPIO5 на gl module (D1 на wemos/node)
#if (GL_BUILD == 0)
#elif (GL_BUILD == 1)
#define MAX_LEDS 900
#elif (GL_BUILD == 2)
#define MAX_LEDS 300
#define BTN_PIN 0
#define STRIP_PIN 2
#define USE_ADC 0
#elif (GL_BUILD == 3)
#define MAX_LEDS 900
#define BTN_PIN 0
#define STRIP_PIN 2
#define USE_ADC 0
#elif (GL_BUILD == 4)
#define MAX_LEDS 300
#define STRIP_PIN 5
#elif (GL_BUILD == 5)
#define MAX_LEDS 900
#define STRIP_PIN 5
#endif
// ---------- БИБЛИОТЕКИ -----------
#define FASTLED_ALLOW_INTERRUPTS 0
//#define FASTLED_ALLOW_INTERRUPTS 0
#include "data.h" // данные
#include "Time.h" // часы
#include "TimeRandom.h" // случайные числа по времени
#include "FastRandom.h" // быстрый рандом
//#include "FastRandom.h" // быстрый рандом
#include "Button.h" // библа кнопки
#include "palettes.h" // палитры
#include "NTPClient-Gyver.h" // сервер времени (модиф)
@@ -147,13 +114,13 @@ Palette pal;
WiFiServer server(80);
WiFiUDP Udp;
WiFiUDP ntpUDP;
IPAddress deviceIP;
IPAddress broadIP;
NTPClient ntp(ntpUDP);
CRGB leds[MAX_LEDS];
Time now;
Button btn(BTN_PIN);
timerMillis EEtmr(EE_TOUT), turnoffTmr, connTmr(120000ul), dawnTmr, holdPresTmr(30000ul), blinkTmr(300);
timerMillis effTmr(30, true);
timerMillis effTmr(30, true), onlineTmr(500, true), postDawn(10 * 60000ul);
TimeRandom trnd;
VolAnalyzer vol(A0), low, high;
FastFilter phot;
@@ -207,4 +174,5 @@ void loop() {
button(); // проверяем кнопку
checkAnalog(); // чтение звука и датчика
yield();
iAmOnline();
}

View File

@@ -5,7 +5,7 @@ void setupADC() {
vol.setDt(700);
vol.setPeriod(5);
vol.setWindow(map(MAX_LEDS, 300, 1200, 20, 1));
vol.setWindow(map(MAX_LEDS, 300, 900, 20, 1));
low.setDt(0);
low.setPeriod(0);
@@ -63,11 +63,11 @@ void checkAnalog() {
void checkMusic() {
vol.tick();
yield();
#if (USE_CLAP == 1)
clap.tick(vol.getRawMax());
if (clap.hasClaps(2)) controlHandler(!cfg.state);
#endif
yield();
if (CUR_PRES.advMode == GL_ADV_LOW || CUR_PRES.advMode == GL_ADV_HIGH) { // частоты
int raw[FFT_SIZE], spectr[FFT_SIZE];
for (int i = 0; i < FFT_SIZE; i++) raw[i] = analogRead(A0);

View File

@@ -29,6 +29,7 @@
#define FOR_i(x,y) for (int i = (x); i < (y); i++)
#define FOR_j(x,y) for (int j = (x); j < (y); j++)
#define FOR_k(x,y) for (int k = (x); k < (y); k++)
#define CUR_PRES preset[cfg.curPreset]
byte scaleFF(byte x, byte b) {
@@ -80,7 +81,7 @@ struct Config {
int16_t length = 16; // длина ленты
int16_t width = 16; // ширина матрицы
byte GMT = 3; // часовой пояс +13
byte GMT = 16; // часовой пояс +13
uint32_t cityID = 1; // city ID
bool mqtt = 0; // mqtt
char mqttID[32]; //
@@ -118,20 +119,22 @@ struct Preset {
byte scale = 100; // масштаб (0.. 255)
byte fromCenter = 0; // эффект из центра (0/1)
byte color = 0; // цвет (0.. 255)
byte rnd = 0; // случайный (0/1)
byte fromPal = 0; // из палитры (0/1)
};
#define DAWN_SIZE 23
#define DAWN_SIZE 24
struct Dawn {
byte state[7] = {0, 0, 0, 0, 0, 0, 0}; // (1/0)
byte hour[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59)
byte minute[7] = {0, 0, 0, 0, 0, 0, 0}; // (0.. 59)
byte bright = 100; // (0.. 255)
byte time = 1; // (5,10,15,20..)
byte post = 1; // (5,10,15,20..)
};
/*
- Каждые 5 минут лампа AP отправляет время (день час минута) на Local лампы всех ролей в сети с ней (GL,6,день,час,мин)
- Если включен АЦП, Мастер отправляет своей группе данные с него на каждой итерации отрисовки эффектов (GL,1,длина,масштаб,яркость)
- Установка времени с мобилы - получают все роли АР и Local (не получившие ntp)
- Каждую секунду устройства шлют посылку GL_ONL
*/

View File

@@ -26,6 +26,11 @@ void EE_startup() {
DEBUGLN(sizeof(cfg) + sizeof(dawn) + sizeof(pal) + sizeof(preset) + 1);
// запускаем всё
if (cfg.deviceType == GL_TYPE_STRIP) {
if (cfg.length > MAX_LEDS) cfg.length = MAX_LEDS;
cfg.width = 1;
}
if (cfg.length * cfg.width > MAX_LEDS) cfg.width = MAX_LEDS / cfg.length;
FastLED.setMaxPowerInVoltsAndMilliamps(STRIP_VOLT, cfg.maxCur * 100);
updPal();
}

View File

@@ -2,12 +2,20 @@ void effectsRoutine() {
static byte prevEff = 255;
if (!effTmr.isReady()) return;
if (dawnTmr.running()) {
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, dawnTmr.getLength8(), scaleFF(dawnTmr.getLength8(), dawn.bright), LINEARBLEND));
drawClock(cfg.length / 2 - 4, 150, 0);
if (dawnTmr.running() || postDawn.running()) {
FastLED.setBrightness(255);
byte thisColor = dawnTmr.getLength8();
if (postDawn.running()) thisColor = 255;
fill_solid(leds, MAX_LEDS, ColorFromPalette(HeatColors_p, thisColor, scaleFF(thisColor, dawn.bright), LINEARBLEND));
drawClock(cfg.length / 2 - 4, 100, 0);
FastLED.show();
if (dawnTmr.isReady()) {
dawnTmr.stop();
postDawn.setInterval(dawn.post * 60000ul);
postDawn.restart();
}
if (postDawn.isReady()) {
postDawn.stop();
FastLED.clear();
FastLED.show();
}
@@ -19,12 +27,15 @@ void effectsRoutine() {
byte thisScale = getScale();
byte thisBright = getBright();
if (cfg.adcMode > 1) { // музыка или яркость
if (musicMode() || briMode()) { // музыка или яркость
if (cfg.role) { // мастер отправляет
static timerMillis adcSend(120, true);
if (adcSend.isReady() && millis() - udpTmr >= 1000) sendUDP(7, thisLength, thisScale, thisBright);
static uint32_t tmr = 0;
if ((millis() - tmr >= musicMode() ? 60 : 1000) && millis() - udpTmr >= 1000) {
sendUDP(7, thisLength, thisScale, thisBright);
tmr = millis();
}
} else { // слейв получает
if (millis() - gotADCtmr < 2000) { // есть сигнал с мастера
if (millis() - gotADCtmr < 4000) { // есть сигнал с мастера
thisLength = udpLength;
thisScale = udpScale;
thisBright = udpBright;
@@ -46,6 +57,7 @@ void effectsRoutine() {
prevEff = CUR_PRES.effect;
loading = true;
}
yield();
// =================================================== ЭФФЕКТЫ ===================================================
switch (CUR_PRES.effect) {
@@ -132,7 +144,8 @@ void effectsRoutine() {
FOR_i(0, cfg.length * cfg.width) leds[i].fadeToBlackBy(70);
{
uint16_t rndVal = 0;
FOR_i(0, thisScale / 8 + 1) {
byte amount = (thisScale >> 3) + 1;
FOR_i(0, amount) {
rndVal = rndVal * 2053 + 13849; // random2053 алгоритм
int homeX = inoise16(i * 100000000ul + (now.weekMs << 3) * CUR_PRES.speed / 255);
homeX = map(homeX, 15000, 50000, 0, cfg.length);
@@ -146,9 +159,15 @@ void effectsRoutine() {
int offsY = inoise8(i * 2500 + 30000 + (now.weekMs >> 1) * CUR_PRES.speed / 255) - 128;
offsY = cfg.length / 2 * offsY / 128;
int thisY = homeY + offsY;
setPix(thisX, thisY, CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255));
setPix(thisX, thisY, CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255)
);
} else {
setLED(thisX, CHSV(CUR_PRES.rnd ? rndVal : CUR_PRES.color, 255, 255));
setLED(thisX, CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255)
);
}
}
}
@@ -204,27 +223,53 @@ void effectsRoutine() {
break;
case 8: // ================================== КОНФЕТТИ ==================================
FOR_i(0, (thisScale >> 3) + 1) {
int x = random(0, cfg.length * cfg.width);
if (leds[x] == CRGB(0, 0, 0)) leds[x] = CHSV(CUR_PRES.rnd ? random(0, 255) : CUR_PRES.color, 255, 255);
}
FOR_i(0, cfg.length * cfg.width) {
if (leds[i].r >= 10 || leds[i].g >= 10 || leds[i].b >= 10) leds[i].fadeToBlackBy(CUR_PRES.speed / 2 + 1);
else leds[i] = 0;
{
byte amount = (thisScale >> 3) + 1;
FOR_i(0, amount) {
int x = random(0, cfg.length * cfg.width);
if (leds[x] == CRGB(0, 0, 0)) leds[x] = CUR_PRES.fromPal ?
ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(i * 255 / amount), 255, LINEARBLEND) :
CHSV(CUR_PRES.color, 255, 255);
}
FOR_i(0, cfg.length * cfg.width) {
if (leds[i].r >= 10 || leds[i].g >= 10 || leds[i].b >= 10) leds[i].fadeToBlackBy(CUR_PRES.speed / 2 + 1);
else leds[i] = 0;
}
}
break;
case 9: // =================================== ЧАСЫ ===================================
case 9: // =================================== СМЕРЧ ===================================
FastLED.clear();
drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), (255 - CUR_PRES.speed), CHSV(CUR_PRES.color, 255, 255));
break;
FOR_k(0, (thisScale >> 5) + 1) {
FOR_i(0, cfg.length) {
//byte thisPos = inoise8(i * 10 - (now.weekMs >> 1) * CUR_PRES.speed / 255, k * 10000);
byte thisPos = inoise8(i * 10 + (now.weekMs >> 3) * CUR_PRES.speed / 255 + k * 10000, (now.weekMs >> 1) * CUR_PRES.speed / 255);
thisPos = map(thisPos, 50, 200, 0, cfg.width);
byte scale = 4;
FOR_j(0, scale) {
CRGB color = ColorFromPalette(paletteArr[CUR_PRES.palette - 1], scalePal(j * 255 / scale), (255 - j * 255 / (scale - 1)), LINEARBLEND);
if (j == 0) {
setPixOverlap(thisPos, i, color);
} else {
setPixOverlap(thisPos - j, i, color);
setPixOverlap(thisPos + j, i, color);
}
}
}
}
break;
case 10: // ================================= ПОГОДА ==================================
case 10: // =================================== ЧАСЫ ===================================
FastLED.clear();
drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), (CUR_PRES.speed < 10) ? 0 : (255 - CUR_PRES.speed), CHSV(CUR_PRES.color, 255, 255));
break;
case 11: // ================================= ПОГОДА ==================================
break;
}
if (CUR_PRES.advMode == GL_ADV_CLOCK && CUR_PRES.effect != 9) drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), 150, 0);
if (CUR_PRES.advMode == GL_ADV_CLOCK && CUR_PRES.effect != 9) drawClock(mapFF(CUR_PRES.scale, 0, cfg.length - 7), 100, 0);
// выводим нажатия кнопки
if (btnClicks > 0) fill_solid(leds, btnClicks, CRGB::White);
if (brTicks > 0) fill_solid(leds, brTicks, CRGB::Cyan);
@@ -236,13 +281,16 @@ void effectsRoutine() {
bool musicMode() {
return ((cfg.adcMode == GL_ADC_MIC || cfg.adcMode == GL_ADC_BOTH) && (CUR_PRES.advMode > 1 && CUR_PRES.advMode <= 4));
}
bool briMode() {
return (cfg.adcMode == GL_ADC_BRI || cfg.adcMode == GL_ADC_BOTH);
}
byte getBright() {
int maxBr = cfg.bright; // макс яркость из конфига
byte fadeBr = 255;
if (CUR_PRES.fadeBright) fadeBr = CUR_PRES.bright; // ограничен вручную
if (cfg.adcMode == GL_ADC_BRI || cfg.adcMode == GL_ADC_BOTH) { // ----> датчик света или оба
if (briMode()) { // ----> датчик света или оба
maxBr = constrain(phot.getFil(), cfg.minLight, cfg.maxLight);
if (cfg.minLight != cfg.maxLight)
maxBr = map(maxBr, cfg.minLight, cfg.maxLight, cfg.minBright, cfg.maxBright);
@@ -298,6 +346,13 @@ byte scalePal(byte val) {
void setPix(int x, int y, CRGB color) {
if (y >= 0 && y < cfg.length && x >= 0 && x < cfg.width) leds[getPix(x, y)] = color;
}
void setPixOverlap(int x, int y, CRGB color) {
if (y < 0) y += cfg.length;
if (x < 0) x += cfg.width;
if (y >= cfg.length) y -= cfg.length;
if (x >= cfg.width) x -= cfg.width;
setPix(x, y, color);
}
void setLED(int x, CRGB color) {
if (x >= 0 && x < cfg.length) leds[x] = color;
}

View File

@@ -1,5 +1,7 @@
// TODO
// защита от переполнения
#ifndef mString_h
#define mString_h
#include <Arduino.h>
char* mUtoa(uint32_t value, char *buffer, bool clear = 1);
char* mLtoa(int32_t value, char *buffer, bool clear = 1);
@@ -53,7 +55,7 @@ class mString {
}
// constructor
mString(char* buffer, int newSize) {
mString(char* buffer, int newSize = -1) {
buf = buffer;
size = newSize;
}
@@ -101,7 +103,7 @@ class mString {
// add
mString& add(const char c) {
byte len = length();
if (len + 1 >= size) return *this;
if (size != -1 && len + 1 >= size) return *this;
buf[len++] = c;
buf[len++] = NULL;
return *this;
@@ -111,13 +113,13 @@ class mString {
do {
buf[len] = *(data++);
} while (buf[len++] != 0);*/
if (length() + strlen(data) >= size) return *this;
if (size != -1 && length() + strlen(data) >= size) return *this;
strcpy(buf + length(), data);
return *this;
}
mString& add(const __FlashStringHelper *data) {
PGM_P p = reinterpret_cast<PGM_P>(data);
if (length() + strlen_P(p) >= size) return *this;
if (size != -1 && length() + strlen_P(p) >= size) return *this;
strcpy_P(buf + length(), p);
return *this;
/*do {
@@ -297,7 +299,7 @@ class mString {
// convert & parse
char operator [] (uint16_t index) const {
return (index < size ? buf[index] : 0);
return buf[index];//(index < size ? buf[index] : 0);
}
char& operator [] (uint16_t index) {
return buf[index];
@@ -356,5 +358,5 @@ class mString {
}
}
private:
};
#endif

View File

@@ -1,6 +1,6 @@
char buf[UDP_TX_PACKET_MAX_SIZE + 1];
void parsing() {
if (Udp.parsePacket()) {
static char buf[UDP_TX_PACKET_MAX_SIZE + 1];
int n = Udp.read(buf, UDP_TX_PACKET_MAX_SIZE);
buf[n] = NULL;
@@ -9,7 +9,7 @@ void parsing() {
if (buf[3] == '7') { // АЦП GL,7,
if (!cfg.role) { // принимаем данные ацп если слейв
int data[3];
mString ints(buf + 5, 20);
mString ints(buf + 5);
ints.parseInts(data, 3);
udpLength = data[0];
udpScale = data[1];
@@ -27,7 +27,7 @@ void parsing() {
// ПАРСИНГ
byte data[MAX_PRESETS * PRES_SIZE + 10];
memset(data, 0, sizeof(data));
memset(data, 0, MAX_PRESETS * PRES_SIZE + 10);
int count = 0;
char *str, *p = buf;
char *ssid, *pass;
@@ -53,7 +53,6 @@ void parsing() {
if (count == 24) strcpy(cfg.mqttPass, str);
}
}
yield();
// тип 0 - control, 1 - config, 2 - effects, 3 - dawn, 4 - from master, 5 - palette, 6 - time
switch (data[1]) {
@@ -81,7 +80,7 @@ void parsing() {
FastLED.clear();
FastLED.show();
char OTA[60];
mString ota(OTA, 60);
mString ota(OTA);
ota.clear();
ota += OTAhost;
ota += OTAfile[data[3]];
@@ -93,6 +92,7 @@ void parsing() {
case 13: // выключить через
if (data[3] == 0) turnoffTmr.stop();
else {
DEBUGLN("Fade");
fadeDown((uint32_t)data[3] * 60000ul);
}
break;
@@ -185,16 +185,16 @@ void parsing() {
void sendToSlaves(byte data1, byte data2) {
if (cfg.role == GL_MASTER) {
char reply[15];
mString packet(reply, sizeof(reply));
mString packet(reply);
packet.clear();
packet = packet + "GL,4," + data1 + ',' + data2;
DEBUG("Sending to Slaves: ");
DEBUGLN(reply);
FOR_i(0, 3) {
FOR_i(0, 4) {
sendUDP(reply);
delay(10);
delay(8);
}
}
}

View File

@@ -42,8 +42,9 @@ void controlHandler(bool state) {
DEBUGLN("stop off timer");
return;
}
if (dawnTmr.running()) {
if (dawnTmr.running() || postDawn.running()) {
dawnTmr.stop();
postDawn.stop();
delay(50);
FastLED.clear();
FastLED.show();
@@ -68,7 +69,7 @@ void setPower(bool state) {
FastLED.clear();
FastLED.show();
}
if (millis() - udpTmr >= 1000) sendToSlaves(0, cfg.state); // пиздец костыль
if (millis() - udpTmr >= 1000) sendToSlaves(0, cfg.state); // пиздец костыль (не отправлять слейвам если команда получена по воздуху)
DEBUGLN(state ? "Power on" : "Power off");
}

View File

@@ -156,7 +156,7 @@ void setupLocal() {
}
void checkUpdate() {
if (cfg.update) {
if (cfg.update) { // было ОТА обновление
if (cfg.version != GL_VERSION) {
cfg.version = GL_VERSION;
blink16(CRGB::Cyan);
@@ -164,10 +164,17 @@ void checkUpdate() {
DEBUGLN(GL_VERSION);
} else {
blink16(CRGB::Blue);
DEBUG("Update to current");
DEBUGLN("Update to current");
}
cfg.update = 0;
EE_updCfg();
} else {
if (cfg.version != GL_VERSION) {
cfg.version = GL_VERSION;
blink16(CRGB::Cyan);
DEBUG("Update to");
DEBUGLN(GL_VERSION);
}
}
}

View File

@@ -1,6 +1,6 @@
void setupTime() {
ntp.setUpdateInterval(NTP_UPD_PRD * 60000ul);
ntp.setTimeOffset((cfg.GMT - 13) * 3600);
ntp.setUpdateInterval(NTP_UPD_PRD * 60000ul / 2); // ставим меньше, так как апдейт вручную
ntp.setTimeOffset((cfg.GMT - 13) * 3600l);
ntp.setPoolServerName(NTPserver);
if (cfg.WiFimode && !connTmr.running()) { // если успешно подключились к WiFi
ntp.begin();
@@ -12,14 +12,14 @@ void setupTime() {
void timeTicker() {
static timerMillis tmr(30, true);
if (tmr.isReady()) {
if (cfg.WiFimode && WiFi.status() == WL_CONNECTED) { // если вайфай подключен
if (cfg.WiFimode && WiFi.status() == WL_CONNECTED && !connTmr.running()) { // если вайфай подключен и это не попытка переподключиться
now.sec = ntp.getSeconds();
now.min = ntp.getMinutes();
now.hour = ntp.getHours();
now.day = ntp.getDay(); // вс 0, сб 6
now.weekMs = now.getWeekS() * 1000ul + ntp.getMillis();
now.setMs(ntp.getMillis());
if (ntp.update()) gotNTP = true;
now.setMs(ntp.getMillis());
if (now.sec == 0 && now.min % NTP_UPD_PRD == 0 && ntp.update()) gotNTP = true;
} else { // если вайфай не подключен
now.tick(); // тикаем своим счётчиком
}
@@ -64,8 +64,7 @@ void checkDawn() {
DEBUG("dawn start ");
DEBUGLN(dawn.time * 60000ul);
dawnTmr.setInterval(dawn.time * 60000ul);
dawnTmr.restart();
FastLED.setBrightness(255);
dawnTmr.restart();
}
}
}
@@ -75,6 +74,7 @@ void checkWorkTime() {
byte curState = isWorkTime(now.hour, cfg.workFrom, cfg.workTo);
if (prevState != curState) { // переключение расписания
prevState = curState;
// todo: проверить пересечение с рассветом
if (curState && !cfg.state && !cfg.manualOff) fade(1); // нужно включить, а лампа выключена и не выключалась вручную
if (!curState && cfg.state) fade(0); // нужно выключить, а лампа включена
}

View File

@@ -38,7 +38,7 @@ class timerMillis {
return _active;
}
byte getLength8() {
return (_active) ? ((millis() - _tmr) * 255ul / _interval) : 0;
return (_active) ? ((min(uint32_t(millis() - _tmr), _interval)) * 255ul / _interval) : 0;
}
private: