// ============================================
// Sketch bmenu test
// ============================================
// ================== BUTTONY ==================
#define BTN_SET 2 //in PL
#define BTN_UP 3 //in PL
#define BTN_DOWN 4
#define BUZZ 5
#include <LiquidCrystal_I2C.h>
extern LiquidCrystal_I2C lcd;
extern void loading(uint8_t col, uint8_t row);
void beep();
// ================== HODNOTY / STAVY ==================
// Temp definice struktury
struct Vars_t {
uint8_t workMode; //0 = AUTO, 1 = MAN
int poolTemp; // 15–32 °C
bool pump; // false;
bool heatValve; // false;
bool filtValve; //false;
int stopWatch; // 0; // ukladame v minutach, prepocitame na cas
bool stopWatchAction; // = false; // 0 = AUTO, 1 = MAN
bool stavWifi; // true/false
int daylightValue; // 0–100 %
bool firmwareUpgr;
};
// Vytvoření globální proměnné Vars s výchozími hodnotami
Vars_t Vars = {
0, // workMode
25, // poolTemp
false, //pump
false, //heatValve
false, //stavFilt
0, //stopWatch
false, // stopWatchAction // false = AUTO, true = MAN
false, //stavWifi
80, //daylightValue
false //firmwareUpgr
};
//int manTime = 0;
// ---------- TIME / DATE ----------
//tohle nacteme z cipu hodin
int editHour = 12;
int editMinute = 30;
int editDay = 15;
int editMonth = 11;
int editYear = 2025;
// -----------------------------------------------------
// ================== MENU STAV ==================
uint8_t menuLevel = 0; // 0 = home, 1 = list, 2 = edit
uint8_t menuGroup = 0; // 0 = AUTO, 1 = MAN, 2 = SET
uint8_t menuIndex = 0;
// ================== EDIT STAV ==================
enum EditContext {
EDIT_NONE = 0,
EDIT_POOL_TEMP,
EDIT_STOPWATCH,
EDIT_DATETIME,
EDIT_DAYLIGHT,
EDIT_WIFI
// další kontexty můžeš přidat sem
};
EditContext editCtx = EDIT_NONE;
// ================== MENU TYPY ==================
enum MenuItemType {
MI_ACTION = 0, // volat funkci
MI_TOGGLE_BOOL, // přepnout bool
MI_EDIT_SCREEN, // vstoupit do editu
MI_EXIT // návrat na home
};
typedef void (*EditFunction)();
// Struktura položky menu
struct MenuItem {
const char* label;
MenuItemType type;
EditFunction onEnter; // pro ACTION / EDIT_SCREEN
bool* togglePtr; // pro TOGGLE_BOOL
};
// ================== PŘEDDEKLARACE ==================
void homeScreen();
void showAnyMenu();
void showManMenu();
void startEdit(EditContext ctx);
void showEditScreen();
void handleEditUp();
void handleEditDown();
void handleEditSet();
// konkrétní edit funkce
void enterPoolTempEdit();
void enterStopwatchEdit();
void enterDateTimeEdit();
void enterDaylightEdit();
// akční funkce deklarace
void actionStopAll();
void actionNoop();
void enterSetMenu();
void aboutSunreg();
//blikaci datum na upravy hodin
bool blinkState = true;
unsigned long lastBlink = 0;
const unsigned long blinkInterval = 400; // ms
bool showStopwatchHold = false; //pro stisk DOWN zobrazeni zbyvajciho casu
unsigned long lastStopwatchTick = 0;
//blikaci funkce pro polozky editace
void handleBlink() {
if (editCtx != EDIT_DATETIME) return;
if (millis() - lastBlink >= blinkInterval) {
lastBlink = millis();
blinkState = !blinkState;
showEditScreen(); // překreslí s efektem blikání
}
}
// ================== AUTO MENU ==================
const MenuItem autoMenu[] = {
// label type onEnter togglePtr
{ "Pool temp", MI_EDIT_SCREEN, enterPoolTempEdit, nullptr },
{ "Filtration", MI_ACTION, actionNoop, nullptr },
{ "Exit MENU", MI_EXIT, nullptr, nullptr }
};
const uint8_t autoMenuSize = sizeof(autoMenu) / sizeof(autoMenu[0]);
// ================== MAN MENU ==================
const MenuItem manMenu[] = {
{ "Pump", MI_TOGGLE_BOOL, nullptr, &Vars.pump },
{ "Heating", MI_TOGGLE_BOOL, nullptr, &Vars.heatValve },
{ "Filtration", MI_TOGGLE_BOOL, nullptr, &Vars.filtValve },
{ "Stopwatch", MI_EDIT_SCREEN, enterStopwatchEdit,nullptr },
{ "Stpw action", MI_TOGGLE_BOOL, nullptr, &Vars.stopWatchAction },
{ "STOP all", MI_ACTION, actionStopAll, nullptr },
{ "Settings", MI_ACTION, enterSetMenu, nullptr },
{ "Exit MENU", MI_EXIT, nullptr, nullptr }
};
const uint8_t manMenuSize = sizeof(manMenu) / sizeof(manMenu[0]);
// ================== SET MENU ==================
const MenuItem setMenu[] = {
{ "Wi-Fi", MI_EDIT_SCREEN, enterWifiEdit, &Vars.stavWifi },
{ "Date/Time", MI_EDIT_SCREEN, enterDateTimeEdit, nullptr },
{ "Daylight", MI_EDIT_SCREEN, enterDaylightEdit, nullptr },
{ "Heat circ", MI_ACTION, actionNoop, nullptr },
{ "Pool circ", MI_ACTION, actionNoop, nullptr },
{ "Disp sleep", MI_ACTION, actionNoop, nullptr },
{ "Filt duration", MI_ACTION, actionNoop, nullptr },
{ "RCHK time", MI_ACTION, actionNoop, nullptr },
{ "Firmwr upgr", MI_TOGGLE_BOOL, nullptr, &Vars.firmwareUpgr },
{ "Buzzer frq", MI_ACTION, actionNoop, nullptr },
{ "About SUNREG", MI_ACTION, aboutSunreg, nullptr },
{ "Exit MENU", MI_EXIT, nullptr, nullptr }
};
const uint8_t setMenuSize = sizeof(setMenu) / sizeof(setMenu[0]);
// ================== AKTUÁLNÍ MENU POINTER ==================
const MenuItem* currentMenu = nullptr;
uint8_t currentMenuSize = 0;
// ================== OSTATNÍ ==================
unsigned long lastPress = 0;
const unsigned long debounceMs = 180;
//Globální proměnná pro označení editovaného pole datum,cas
uint8_t dtFieldIndex = 0;
// 0=hour, 1=minute, 2=day, 3=month, 4=year
// =======================================================
// MENU – SET
// =======================================================
void showSetMenu() {
Serial.println("showSetMenu ...");
lcd.clear();
const MenuItem &item = currentMenu[menuIndex];
// horní řádek – název
lcd.setCursor(0,0);
lcd.print(item.label);
Serial.print("Toggle ");
Serial.println( *(item.togglePtr) );
// stavová hodnota (pokud má togglePtr)
/*if (item.togglePtr != nullptr) {
lcd.setCursor(13,0);
lcd.print(*(item.togglePtr) ? " on" : "off");
}*/
if (item.type == MI_TOGGLE_BOOL && item.togglePtr != nullptr) {
lcd.setCursor(13, 0);
lcd.print(*(item.togglePtr) ? " on" : "off");
}
// spodní řádek – další položka
lcd.setCursor(0,1);
if (menuIndex < currentMenuSize - 1) {
const char* nextLabel = currentMenu[menuIndex + 1].label;
// pokud to NENÍ EXIT MENU → zobraz nextMenu symbol
if (strcmp(nextLabel, "EXIT MENU") != 0) {
lcd.write(7); // nextMnu symbol
} else {
lcd.print(' '); // mezera místo symbolu
}
lcd.print(nextLabel);
} else {
lcd.print(" "); // prázdný spodní řádek
}
}
// =======================================================
// MENU – AUTO univerzální výpis
// =======================================================
void showAnyMenu() {
if (!currentMenu || currentMenuSize == 0) return;
lcd.clear();
// horní řádek – aktivní položka
lcd.setCursor(0,0);
lcd.print(currentMenu[menuIndex].label);
// spodní řádek – další položka nebo prázdno
lcd.setCursor(0,1);
if (menuIndex < currentMenuSize - 1) {
const char* nextLabel = currentMenu[menuIndex + 1].label;
// pokud to NENÍ EXIT MENU → zobraz nextMenu symbol
if (strcmp(nextLabel, "EXIT MENU") != 0) {
lcd.write(7); // nextMnu symbol
} else {
lcd.print(' '); // mezera místo symbolu
}
lcd.print(nextLabel);
} else {
lcd.print(" "); // prázdný spodní řádek
}
}
// =======================================================
// MENU – MAN: speciální výpis s ON/OFF/MAN/AUTO
// =======================================================
/*
void showManMenu() {
if (!currentMenu || currentMenuSize == 0) return;
lcd.clear();
// horní řádek – název
lcd.setCursor(0,0);
lcd.print(currentMenu[menuIndex].label);
// stav vpravo
const MenuItem &item = currentMenu[menuIndex];
Serial.print( "ITEM ");
Serial.print(item.label);
Serial.print( " - ");
Serial.println((uintptr_t)&item, HEX);
// Pump / Heating / Filtration ON/OFF
/*lcd.setCursor(13,0);
if (&item == &manMenu[0]) lcd.print(Vars.pump ? " on" : "off");
if (&item == &manMenu[1]) lcd.print(Vars.heatValve ? " on" : "off");
if (&item == &manMenu[2]) lcd.print(Vars.filtValve ? " on" : "off");
*/
/*
if (item.type == MI_TOGGLE_BOOL && item.togglePtr != nullptr) {
lcd.setCursor(13, 0);
lcd.print(*(item.togglePtr) ? " on" : "off");
}
// Stpw action – MAN/AUTO
if (&item == &manMenu[4]) {
lcd.setCursor(12,0);
if (Vars.stopWatchAction) lcd.print(" MAN"); else lcd.print("AUTO");
}
// spodní řádek – další položka
lcd.setCursor(0,1);
if (menuIndex < currentMenuSize - 1) {
const char* nextLabel = currentMenu[menuIndex + 1].label;
// pokud to NENÍ EXIT MENU → zobraz nextMenu symbol
if (strcmp(nextLabel, "EXIT MENU") != 0) {
lcd.write(7); // nextMnu symbol
} else {
lcd.print(' '); // mezera místo symbolu
}
lcd.print(nextLabel);
} else {
lcd.print(" "); // prázdný spodní řádek
}
}*/
void showManMenu() {
if (!currentMenu || currentMenuSize == 0) return;
lcd.clear();
const MenuItem &item = currentMenu[menuIndex];
lcd.setCursor(0,0);
lcd.print(item.label);
// výpis hodnot na pravý okraj
lcd.setCursor(11, 0); // 16 znaků → posun
lcd.print(" "); // vyčistit
lcd.setCursor(13, 0);
if (item.togglePtr != nullptr) {
// on/off
lcd.print(*(item.togglePtr) ? "on " : "off");
}
// speciální položka Stopwatch → zobraz zbylý čas
if (&item == &manMenu[3]) {
lcd.setCursor(11, 0);
String t = formatStopwatch(Vars.stopWatch);
int pad = 16 - t.length();
for(int i = 0; i < pad; i++) lcd.print(' ');
lcd.print(t);
}
// Stpw action – MAN/AUTO
if (&item == &manMenu[4]) {
lcd.setCursor(12,0);
lcd.print(Vars.stopWatchAction ? "MAN" : "AUTO");
}
// spodní řádek
lcd.setCursor(0,1);
if (menuIndex < currentMenuSize - 1) {
const char* nextLabel = currentMenu[menuIndex + 1].label;
if (strcasecmp(nextLabel, "Exit MENU") != 0) lcd.write(7);
else lcd.print(' ');
lcd.print(nextLabel);
} else {
lcd.print(" ");
}
}
// =======================================================
// EDIT – START + OBECNÝ RENDERER
// =======================================================
void startEdit(EditContext ctx) {
editCtx = ctx;
menuLevel = 2;
showEditScreen();
}
void showEditScreen() {
lcd.clear();
switch (editCtx) {
case EDIT_POOL_TEMP:
lcdAutoMode(); //zobrazi automode
break;
case EDIT_STOPWATCH:
lcd.setCursor(0,0);
lcd.print("Stopwatch");
lcd.setCursor(0,1);
if (Vars.stopWatch == 0) {
lcd.print("(0-12hod) off"); // 12 znaků -> zarovnání doprava
} else {
int h = Vars.stopWatch / 60;
int m = Vars.stopWatch % 60;
char buf[6]; // "hh:mm"
sprintf(buf, "%02d:%02d", h, m);
// zarovnat doprava na 16 znaků
int padding = 16 - strlen(buf);
for(int i = 0; i < padding; i++) lcd.print(' ');
lcd.print(buf);
}
break;
case EDIT_WIFI:
//Spusteni WIFI on/off
//pri on bude kontrola jestli je nastavena sit a heslo, pokud ne tak
Serial.println("EDIT_WIFI vtup");
//nahoru a dolu je on a off
//pokud je uozen sit a heslo ,tak se ykusi pripojit
//jiz ok, tak budeme pripojovat, Connecting a loading
//pokud se nepodaru, tak shodime sit smaznem hodnoty a nastavime SSID SUNREG-Wi
break;
case EDIT_DATETIME:
lcd.clear();
lcd.setCursor(0,0);
if (editHour < 10) lcd.print("0");
lcd.print(editHour);
lcd.print(":");
if (editMinute < 10) lcd.print("0");
lcd.print(editMinute);
lcd.setCursor(0,1);
if (editDay < 10) lcd.print("0");
lcd.print(editDay);
lcd.print(".");
if (editMonth < 10) lcd.print("0");
lcd.print(editMonth);
lcd.print(".");
lcd.print(editYear);
break;
case EDIT_DAYLIGHT:
lcd.setCursor(0,0);
lcd.print("Daylight");
lcd.setCursor(0,1);
lcd.print("Value: ");
lcd.print(Vars.daylightValue);
lcd.print("%");
break;
default:
lcd.setCursor(0,0);
lcd.print("Edit mode");
lcd.setCursor(0,1);
lcd.print("No handler");
break;
}
}
// =======================================================
// EDIT – UP / DOWN / SET
// =======================================================
void handleEditUp() {
switch (editCtx) {
case EDIT_POOL_TEMP:
if (Vars.poolTemp < 32) Vars.poolTemp++;
break;
case EDIT_STOPWATCH:
if (Vars.stopWatch < 720) { // max 12 hodin
Vars.stopWatch += 15;
if (Vars.stopWatch > 720) Vars.stopWatch = 720;
}
break;
case EDIT_DATETIME:
switch (dtFieldIndex) {
case 0: // hour
if (editHour < 23) editHour++;
else editHour = 0;
break;
case 1: // minute
if (editMinute < 59) editMinute++;
else editMinute = 0;
break;
case 2: // day
if (editDay < 31) editDay++;
else editDay = 1;
break;
case 3: // month
if (editMonth < 12) editMonth++;
else editMonth = 1;
break;
case 4: // year
if (editYear < 2099) editYear++;
break;
}
break;
case EDIT_DAYLIGHT:
if (Vars.daylightValue < 100) Vars.daylightValue++;
break;
default:
break;
}
showEditScreen();
}
void handleEditDown() {
switch (editCtx) {
case EDIT_POOL_TEMP:
if (Vars.poolTemp > 15) Vars.poolTemp--;
else beep();
break;
case EDIT_STOPWATCH:
if (Vars.stopWatch >= 15) {
Vars.stopWatch -= 15;
} else {
Vars.stopWatch = 0;
beep();
}
break;
case EDIT_DATETIME:
switch (dtFieldIndex) {
case 0: if (editHour > 0) editHour--; else editHour = 23; break;
case 1: if (editMinute > 0) editMinute--; else editMinute = 59; break;
case 2: if (editDay > 1) editDay--; else editDay = 31; break;
case 3: if (editMonth > 1) editMonth--; else editMonth = 12; break;
case 4: if (editYear > 2020) editYear--; else beep(); break;
}
break;
case EDIT_DAYLIGHT:
if (Vars.daylightValue > 0) Vars.daylightValue--;
else beep();
break;
default:
break;
}
showEditScreen();
}
void handleEditSet() {
// Tady případně můžeš uložit hodnoty do EEPROM apod.
if (editCtx == EDIT_DATETIME) {
dtFieldIndex++;
// Pokud jsme prošli vše → uložit a skončit
if (dtFieldIndex > 4) {
dtFieldIndex = 0;
editCtx = EDIT_NONE;
menuLevel = 1;
// návrat do SET menu
if (menuGroup == 2) showSetMenu();
else if (menuGroup == 1) showManMenu();
else showAnyMenu();
return;
}
if (editCtx == EDIT_STOPWATCH) {
// po uložení → návrat a přepočítání
editCtx = EDIT_NONE;
menuLevel = 1;
if (menuGroup == 1) showManMenu(); // správně vykreslí čas
else showAnyMenu();
return;
}
showEditScreen();
return;
}
if (editCtx == EDIT_DAYLIGHT) {
// save daylight to config
}
menuLevel = 1;
if (menuGroup == 1) showManMenu();
else showAnyMenu();
}
// =======================================================
// KONKRÉTNÍ EDIT FUNKCE (pro MenuItem.onEnter)
// =======================================================
void enterPoolTempEdit() {
startEdit(EDIT_POOL_TEMP);
}
void enterStopwatchEdit() {
startEdit(EDIT_STOPWATCH);
}
// =======================================================
// AKCE (ACTION položky)
// =======================================================
void actionStopAll() {
Vars.pump = false;
Vars.heatValve = false;
Vars.filtValve = false;
lcd.clear();
lcd.setCursor(0,0);
lcd.print("All stopped");
delay(1000);
// návrat zpět do menu
if (menuGroup == 1) showManMenu();
else showAnyMenu();
}
void actionNoop() {
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Not implemented");
delay(600);
if (menuGroup == 1) showManMenu();
else showAnyMenu();
}
// =======================================================
// VSTUP DO MENU PODLE REŽIMU
// =======================================================
void enterMenuByWorkMode() {
menuLevel = 1;
menuIndex = 0;
if (Vars.workMode == 0) { // AUTO
menuGroup = 0;
currentMenu = autoMenu;
currentMenuSize = autoMenuSize;
showAnyMenu();
} else { // MAN
menuGroup = 1;
currentMenu = manMenu;
currentMenuSize = manMenuSize;
showManMenu();
}
}
void enterSetMenu() {
menuLevel = 1;
menuGroup = 2;
menuIndex = 0;
currentMenu = setMenu;
currentMenuSize = setMenuSize;
//showAnyMenu();
showSetMenu();
}
// =======================================================
// BUTTON HANDLER
// =======================================================
void buttons() {
if (millis() - lastPress < debounceMs) return;
// ---------------- SET ----------------
if (!digitalRead(BTN_SET)) {
lastPress = millis();
// HOME → vstup do menu dle režimu
if (menuLevel == 0) {
enterMenuByWorkMode();
return;
}
// EDIT → potvrzení a návrat
if (menuLevel == 2) {
handleEditSet();
return;
}
// LIST → rozhodnutí
if (menuLevel == 1 && currentMenu != nullptr) {
const MenuItem &item = currentMenu[menuIndex];
// EXIT
if (item.type == MI_EXIT) {
menuLevel = 0;
homeScreen();
return;
}
// TOGGLE BOOL (např. Pump, Heating, Filtration, Stpw action)
if (item.type == MI_TOGGLE_BOOL && item.togglePtr != nullptr) {
*(item.togglePtr) = !(*(item.togglePtr));
if (menuGroup == 1) showManMenu();
else showAnyMenu();
return;
}
// EDIT SCREEN
if (item.type == MI_EDIT_SCREEN && item.onEnter != nullptr) {
item.onEnter(); // nastaví editCtx a vykreslí
return;
}
// ACTION
if (item.type == MI_ACTION) {
if (item.onEnter != nullptr) item.onEnter();
else actionNoop();
return;
}
// Fallback – nic
lcd.clear();
lcd.setCursor(0,0);
lcd.print("Unknown item");
delay(500);
if (menuGroup == 1) showManMenu();
else showAnyMenu();
return;
}
}
// ---------------- UP ----------------
if (!digitalRead(BTN_UP)) {
lastPress = millis();
// EDIT režim – mění hodnotu
if (menuLevel == 2) {
handleEditUp();
return;
}
// HOME – přepnutí do AUTO (bez zbytečného překreslování)
if (menuLevel == 0) {
if (Vars.workMode != 0) {
Vars.workMode = 0;
homeScreen();
}
return;
}
// LIST – posun v menu nahoru
if (menuLevel == 1 && currentMenu != nullptr) {
if (menuIndex > 0) menuIndex--;
/*if (menuGroup == 1) showManMenu();
else showAnyMenu();
return;
*/
if (menuGroup == 2) {
showSetMenu();
} else if (menuGroup == 1) {
showManMenu();
} else {
showAnyMenu();
}
}
}
// ---------------- DOWN ----------------
if (!digitalRead(BTN_DOWN)) {
lastPress = millis();
// ----------------------------------------------
// HOLD zobrazení stopek na hlavní stránce MAN
// ----------------------------------------------
if (menuLevel == 0 && Vars.workMode == 1 && Vars.stopWatch > 0) {
if (!showStopwatchHold) {
showStopwatchHold = true;
lcdStopwatchHoldScreen();
}
lastPress = millis(); // reset debounce
return; // NELEZ DO MENU OVLÁDÁNÍ
}
// EDIT režim – mění hodnotu
if (menuLevel == 2) {
handleEditDown();
return;
}
// HOME – přepnutí do MAN (bez zbytečného překreslování)
if (menuLevel == 0) {
if (Vars.workMode != 1) {
Vars.workMode = 1;
homeScreen();
}
return;
}
// LIST – posun v menu dolů
if (menuLevel == 1 && currentMenu != nullptr) {
if (menuIndex < currentMenuSize - 1) menuIndex++;
/*if (menuGroup == 1) showManMenu();
else showAnyMenu();
return;*/
if (menuGroup == 2) {
showSetMenu();
} else if (menuGroup == 1) {
showManMenu();
} else {
showAnyMenu();
}
}
}
}
// =======================================================
// NASTAVENI WIFI
// =======================================================
void enterWifiEdit(){
dtFieldIndex = 0;
editCtx = EDIT_WIFI;
menuLevel = 2;
//loading pokud je SSID SUNREG
loading(15,1);
}
// =======================================================
// NASTAVCENI DATA CASU
// =======================================================
void enterDateTimeEdit() {
dtFieldIndex = 0;
editCtx = EDIT_DATETIME;
menuLevel = 2;
showEditScreen(); // vykreslí statickou podobu HH:MM / DD.MM.YYYY
blinkState = true;
lastBlink = millis();
// ---------- LOKÁLNÍ EDITAČNÍ LOOP ----------
while (editCtx == EDIT_DATETIME) {
buttons(); // obslouží stisky UP/DOWN/SET
blinkDateTimeField(); // bliká pouze upravované pole
}
}
void enterDaylightEdit() {
startEdit(EDIT_DAYLIGHT);
}
//volani blikani polozky data pro upravu
void blinkDateTimeField() {
if (millis() - lastBlink < blinkInterval) return;
lastBlink = millis();
blinkState = !blinkState;
switch (dtFieldIndex) {
case 0: // HH
lcd.setCursor(0,0);
if (!blinkState) lcd.print(" ");
else {
if (editHour < 10) lcd.print("0");
lcd.print(editHour);
}
break;
case 1: // MM
lcd.setCursor(3,0);
if (!blinkState) lcd.print(" ");
else {
if (editMinute < 10) lcd.print("0");
lcd.print(editMinute);
}
break;
case 2: // DD
lcd.setCursor(0,1);
if (!blinkState) lcd.print(" ");
else {
if (editDay < 10) lcd.print("0");
lcd.print(editDay);
}
break;
case 3: // MM (měsíc)
lcd.setCursor(3,1);
if (!blinkState) lcd.print(" ");
else {
if (editMonth < 10) lcd.print("0");
lcd.print(editMonth);
}
break;
case 4: // YYYY
lcd.setCursor(6,1);
if (!blinkState) lcd.print(" ");
else lcd.print(editYear);
break;
}
}
void beep(){
digitalWrite(5, HIGH);
delay(50); // krátké pípnutí
digitalWrite(5, LOW);
}
/*
//Formatovani casu
String formatStopwatch(int minutes) {
if (minutes == 0) return "off";
int h = minutes / 60;
int m = minutes % 60;
char buf[6];
sprintf(buf, "%02d:%02d", h, m);
return String(buf);
}*/
//ukonceni stopek, vypne vse a nastavi podle action
void stopStopwatchAndApplyMode() {
// vypnout všechna zařízení
Vars.pump = false;
Vars.heatValve = false;
Vars.filtValve = false;
// vynulovat stopky
Vars.stopWatch = 0;
// přepnout režim podle stopWatchAction
// false = AUTO, true = MAN
if (Vars.stopWatchAction == false) {
Vars.workMode = 0; // AUTO
} else {
Vars.workMode = 1; // MAN
}
// uložit hodnoty, pokud máš EEPROM
// saveConfig(); // pokud existuje
// překreslit hlavní obrazovku
homeScreen();
}
void handleStopwatch() {
// stopky běží jen v MAN režimu
if (Vars.workMode != 1) return;
// stopWatch = 0 → nic nedělat
if (Vars.stopWatch == 0) return;
// tick každých 60 000 ms = 1 minuta
if (millis() - lastStopwatchTick >= 60000) {
lastStopwatchTick = millis();
if (Vars.stopWatch > 0) {
Vars.stopWatch -= 15; // odečítat vždy 15 minut
if (Vars.stopWatch < 0) Vars.stopWatch = 0;
}
// pokud doběhlo → vypnout
if (Vars.stopWatch == 0) {
stopStopwatchAndApplyMode();
}
}
}
void updateStopwatch() {
// Stopky běží pouze:
// - v MAN režimu
// - na hlavní obrazovce (menuLevel == 0)
// - čas > 0
if (Vars.workMode != 1) return;
if (menuLevel != 0) return;
if (Vars.stopWatch == 0) return;
// každých 60000 ms - odečteme 1 minutu
if (millis() - lastStopwatchTick >= 60000) {
lastStopwatchTick = millis();
Vars.stopWatch--;
// dobehly
if (Vars.stopWatch == 0) {
Vars.pump = false;
Vars.heatValve = false;
Vars.filtValve = false;
// přepnutí režimu dle uživatele
Vars.workMode = Vars.stopWatchAction ? 1 : 0;
homeScreen(); // překreslit
}
}
}
// =======================================================
// SETUP & LOOP
// =======================================================
void setup() {
Serial.begin(115200);
delay(50);
//inicializace LCD
lcdInit();
//tohle bude v init buttons
pinMode(BTN_SET, INPUT_PULLUP);
pinMode(BTN_UP, INPUT_PULLUP);
pinMode(BTN_DOWN, INPUT_PULLUP);
pinMode(BUZZ, OUTPUT);
//jen docasne,
homeScreen();
}
//tady by to chtelo jeste predat jak promenna se ma ulozit
void saveConfig() {
// sem dáš reálné ukládání do EEPROM / SPIFFS
// např:
// EEPROM.put(0, Vars);
// EEPROM.commit();
}
void loop() {
buttons(); //hlavni funkce zachytavni tlacitek
lcdBlinkHourglass(); // blikání přesýpacích hodin pokud je stopwatch
updateStopwatch();
// návrat z HOLD obrazovky po uvolnění BTN_DOWN
/*
if (showStopwatchHold) {
if (digitalRead(BTN_DOWN)) { // tlačítko PUŠTĚNO
showStopwatchHold = false;
homeScreen(); // návrat na MAN screen
}
}
*/
//tohle odsunout na editaci data a hodin
if (menuLevel == 2 && editCtx == EDIT_DATETIME) {
blinkDateTimeField();
}
//loading symbol *
//loading(15, 1);
//handleStopwatch(); // odpočítávání stopek
}