Harmonogram ogarnięty.
Niestety ciągle mam kłopot z zapisem danych.
Po kolei, wgrywan na nowo firmware z kasowaniem pamięci, podaje dane do serwera zapisz i reset. Moduł się ładnie dodaje i wszystko chodzi.
Wchodzę na lokalne IP i na moją stronę SmartPool, zapisuje konfigurację i moduł dalej działa poprawnie aż do resetu (?) - odłączenia prądu i ponownym zasilaniu ponownie jest w trybie konfiguracji,
Teraz jestem już w pracy, ale będę kombinować z podejrzeniem danych do zapisu..
No bo chyba pamięci nie powinno braknąć na parę suwaków i termometrów. Patrząc na to co GG albo bramka ZigBee pamięta.
SmartPool - pomoc przy kodzie ;)
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
Niedawno do SD dodwałem token CSRF do formularzy w web interface. Jeśli używasz "main" zamiast oficjalmnych releaseów, to ten token jest sprawdzany.Lector wrote: Mon Jun 01, 2026 11:09 am Harmonogram ogarnięty.
Niestety ciągle mam kłopot z zapisem danych.
Po kolei, wgrywan na nowo firmware z kasowaniem pamięci, podaje dane do serwera zapisz i reset. Moduł się ładnie dodaje i wszystko chodzi.
Wchodzę na lokalne IP i na moją stronę SmartPool, zapisuje konfigurację i moduł dalej działa poprawnie aż do resetu (?) - odłączenia prądu i ponownym zasilaniu ponownie jest w trybie konfiguracji,
Teraz jestem już w pracy, ale będę kombinować z podejrzeniem danych do zapisu..
No bo chyba pamięci nie powinno braknąć na parę suwaków i termometrów. Patrząc na to co GG albo bramka ZigBee pamięta.
Kod wymaga, aby to był pierwszy element w przetwarzanym POST HTML. Tak powinno być, o ile nie masz np. zepsutego HTML na urządzeniu. Najprościej pobrać sobie wygenerowany HTML i wrzucić go do jakiegoś online HTML validator, który sprawdzi, czy wszystko masz poprawnie podomykane.
W kolejnym kroku -> sprawdź logi
Najlepsze suple dla Twojego domu 
-
Lector
- Posts: 2471
- Joined: Fri Nov 17, 2017 2:26 pm
- Location: Poznań
- Has thanked: 13 times
- Been thanked: 25 times
SD mam w 26.4 - to co pobiera z automatu Arduino Ide.
Jak mam wstawić ten token?
Jak mam wstawić ten token?
Code: Select all
html += "<form action=/smartpool method=POST><input type=\"hidden\" name=\"supla_csrf\" value=\"" + server->arg("supla_csrf") + "\">";Niespełniony automatyk. 
https://3d-lamp.photos/
https://pool.lector.top/
https://3d-lamp.photos/
https://pool.lector.top/
-
Lector
- Posts: 2471
- Joined: Fri Nov 17, 2017 2:26 pm
- Location: Poznań
- Has thanked: 13 times
- Been thanked: 25 times
Zrobiłem to co chciałem, cała logika działa poprawnie (jeszcze nie wiem jak z termometrami), ale ciągle mam problem z zapisem konfiguracji. Po zaniku napięcie i powrocie mam tryb konfiguracji.
A jeszcze nie pamieta i stanu.
Code: Select all
#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/control/relay.h>
#include <supla/control/button.h>
#include <supla/control/hvac_base.h>
#include <supla/clock/clock.h>
#include <supla/network/html/time_parameters.h>
#include <supla/network/html/hvac_parameters.h>
#include <supla/control/internal_pin_output.h>
#include <supla/device/status_led.h>
#include <supla/control/action_trigger.h>
#include <supla/control/virtual_relay.h>
#include <supla/storage/storage.h>
#include <supla/storage/config.h>
#include <supla/storage/littlefs_config.h>
#include <supla/network/esp_web_server.h>
#include <supla/network/html/device_info.h>
#include <supla/network/html/protocol_parameters.h>
#include <supla/network/html/status_led_parameters.h>
#include <supla/network/html/wifi_parameters.h>
#include <supla/device/supla_ca_cert.h>
#ifdef ARDUINO_ARCH_ESP32
#include <HTTPUpdateServer.h>
#else
#include <ESP8266HTTPUpdateServer.h>
#endif
#include <OneWire.h>
#include <DallasTemperature.h>
#include <supla/sensor/thermometer.h>
// ======================================================
// GPIO - ESP32 Relay X8
// ======================================================
#define STATUS_LED_GPIO 23
#define BUTTON_CFG_GPIO 0
#define RELAY_1_GPIO 32
#define RELAY_2_GPIO 33
#define RELAY_3_GPIO 25
#define RELAY_4_GPIO 26
#define RELAY_5_GPIO 27
#define RELAY_6_GPIO 14
#define RELAY_7_GPIO 12
#define RELAY_8_GPIO 13
#define ONE_WIRE_BUS 16
#define LIGHT_BUTTON_GPIO 17
// ======================================================
// CONFIG & VARIABLES
// ======================================================
const char* const SENSOR_NAMES[] = {
"Woda w basenie",
"Woda w solarach",
"Woda powrotna",
"Powietrze"
};
const int SENSOR_COUNT = sizeof(SENSOR_NAMES) / sizeof(SENSOR_NAMES[0]);
Supla::ESPWifi wifi;
Supla::LittleFsConfig configSupla;
Supla::Device::StatusLed statusLed(STATUS_LED_GPIO, false);
Supla::EspWebServer suplaServer;
#ifdef ARDUINO_ARCH_ESP32
HTTPUpdateServer httpUpdater;
#else
ESP8266HTTPUpdateServer httpUpdater;
#endif
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);
DeviceAddress discoveredAddresses[10];
int discoveredCount = 0;
Supla::Control::Relay* relayLock = nullptr;
Supla::Control::Relay* relayPump = nullptr;
Supla::Control::Relay* relayChlorine = nullptr;
Supla::Control::Relay* relayHeatPump = nullptr;
Supla::Control::Relay* relayUV = nullptr;
Supla::Control::Relay* relayLight = nullptr;
Supla::Control::VirtualRelay* virtualRelay = nullptr;
Supla::Control::HvacBase* hvacPool = nullptr;
bool depChlorine = false;
bool depUV = false;
bool lockPump = false;
bool lockChlorine = false;
bool lockHeating = false;
bool lockUV = false;
bool schControlDependencies = true;
bool schEnabled = true;
unsigned long heatPumpStartTime = 0;
bool heatPumpRunningInAuto = false;
// ======================================================
// DS18B20
// ======================================================
void scanDS18B20() {
pinMode(ONE_WIRE_BUS, INPUT_PULLUP);
delay(250);
sensors.begin();
delay(50);
discoveredCount = 0;
DeviceAddress tempAddr;
oneWire.reset_search();
while (oneWire.search(tempAddr) && discoveredCount < 10) {
if (sensors.validAddress(tempAddr) && tempAddr[0] == 0x28) {
memcpy(discoveredAddresses[discoveredCount], tempAddr, sizeof(DeviceAddress));
discoveredCount++;
}
}
}
class ConfigurableDS18B20 : public Supla::Sensor::Thermometer {
public:
ConfigurableDS18B20(int sensorNumber) : sensorNum(sensorNumber) {
memset(deviceAddress, 0, sizeof(deviceAddress));
}
void onInit() override {
loadAddress();
channel.setNewValue(getValue());
}
double getValue() override {
if (deviceAddress[0] == 0 && deviceAddress[7] == 0) return -275.0;
sensors.requestTemperaturesByAddress(deviceAddress);
double temp = sensors.getTempC(deviceAddress);
if (temp == DEVICE_DISCONNECTED_C) return -275.0;
return temp;
}
void loadAddress() {
auto cfg = Supla::Storage::ConfigInstance();
if (!cfg) return;
char key[20];
for (int i = 0; i < 8; i++) {
snprintf(key, sizeof(key), "ds_%d_byte_%d", sensorNum, i);
uint8_t b = 0;
cfg->getUInt8(key, &b);
deviceAddress[i] = b;
}
}
protected:
int sensorNum;
DeviceAddress deviceAddress;
};
ConfigurableDS18B20* dsSensors[SENSOR_COUNT];
// ======================================================
// FUNKCJE POMOCNICZE
// ======================================================
void setRelayBlocked(Supla::Control::Relay* relay, bool blocked) {
if (!relay || !relay->getChannel()) return;
if (blocked) {
relay->turnOff();
relay->getChannel()->setStateOffline();
} else {
relay->getChannel()->setStateOnline();
}
}
// ======================================================
// ZAPIS FORMULARZA
// ======================================================
void handleSmartPoolSaveAction() {
auto server = suplaServer.getServerPtr();
if (!server) return;
auto cfg = Supla::Storage::ConfigInstance();
if (cfg) {
cfg->setUInt8("lock_pump", server->hasArg("lock_pump") ? 1 : 0);
cfg->setUInt8("lock_chlor", server->hasArg("lock_chlor") ? 1 : 0);
cfg->setUInt8("lock_heat", server->hasArg("lock_heat") ? 1 : 0);
cfg->setUInt8("lock_uv", server->hasArg("lock_uv") ? 1 : 0);
cfg->setUInt8("dep_chlorine", server->hasArg("dep_chlorine") ? 1 : 0);
cfg->setUInt8("dep_uv", server->hasArg("dep_uv") ? 1 : 0);
cfg->setUInt8("p_sch_dep", server->hasArg("p_sch_dep") ? 1 : 0);
for (int t = 0; t < SENSOR_COUNT; t++) {
char argName[20];
snprintf(argName, sizeof(argName), "ds_assign_%d", t);
if (server->hasArg(argName)) {
int selectedIdx = server->arg(argName).toInt();
char idxKey[20];
snprintf(idxKey, sizeof(idxKey), "ds_idx_%d", t);
cfg->setUInt8(idxKey, selectedIdx);
char byteKey[20];
for (int i = 0; i < 8; i++) {
snprintf(byteKey, sizeof(byteKey), "ds_%d_byte_%d", t, i);
cfg->setUInt8(byteKey, (selectedIdx >= 0 && selectedIdx < discoveredCount) ? discoveredAddresses[selectedIdx][i] : 0);
}
}
}
if (server->hasArg("heat_on_t1")) cfg->setUInt8("heat_on_t1", server->arg("heat_on_t1").toInt());
if (server->hasArg("heat_on_t2")) cfg->setUInt8("heat_on_t2", server->arg("heat_on_t2").toInt());
if (server->hasArg("heat_on_diff")) cfg->setInt32("heat_on_diff", server->arg("heat_on_diff").toInt());
if (server->hasArg("heat_off_t1")) cfg->setUInt8("heat_off_t1", server->arg("heat_off_t1").toInt());
if (server->hasArg("heat_off_t2")) cfg->setUInt8("heat_off_t2", server->arg("heat_off_t2").toInt());
if (server->hasArg("heat_off_diff")) cfg->setInt32("heat_off_diff", server->arg("heat_off_diff").toInt());
if (server->hasArg("heat_min_time")) cfg->setInt32("heat_min_time", server->arg("heat_min_time").toInt());
cfg->commit();
for (int i = 0; i < SENSOR_COUNT; i++) {
if (dsSensors[i]) dsSensors[i]->loadAddress();
}
}
server->sendHeader("Location", "/smartpool?saved=1");
server->send(303, "text/plain", "");
}
// ======================================================
// STRONA WWW
// ======================================================
void handleSmartPoolPage() {
auto server = suplaServer.getServerPtr();
if (!server) return;
auto cfg = Supla::Storage::ConfigInstance();
String html = "";
html += "<!doctype html><html lang=en><head><meta charset=UTF-8><meta name=viewport content=width=device-width,initial-scale=1,maximum-scale=1,user-scalable=no><title>SUPLA-SmartPool</title><style>*,*::before,*::after{box-sizing:border-box}html:focus-within{scroll-behavior:smooth}html,body,h1,h2,h3,h4,p{font-family:HelveticaNeue,Helvetica,Arial,sans-serif;margin:0;padding:0}body{min-height:100vh;text-rendering:optimizeSpeed;line-height:1.5;font-size:14px;background:#00d151;color:#fff}h1,h3{margin:10px 0;font-weight:300;font-size:23px}.wrapper{display:flex;flex-direction:column;justify-content:center;min-height:100vh}.content{text-align:center;padding:20px 10px}.box{background:#fff;color:#000;border-radius:10px;padding:5px 10px;margin:10px 0;box-shadow:0 5px 6px rgb(0 0 0 / .3)}#msg{position:fixed;top:0;left:0;width:100%;height:119px;box-sizing:border-box;padding:15px 20px;background:#ffe836;color:#000;text-align:center;font-size:26px;box-shadow:0 2px 5px rgb(0 0 0 / .3);z-index:9999;display:flex;align-items:center;justify-content:center}.form{text-align:left;max-width:500px;margin:0 auto;margin-top:-40px;padding:10px;padding-top:70px}.form-field{display:flex;align-items:center;padding:8px 10px;border-top:1px solid #00d150;margin:0 -10px}.box>.form-field:first-of-type{border-top:0}.form-field label{width:250px;margin-right:5px;color:#00d151}@media screen and (max-width:530px){.form-field{flex-direction:column}.form-field label{width:100%;margin:3px 0}}.form-field input,.form-field select{width:100%;border:1px solid #ccc;border-radius:6px;padding:3px 8px;background:#fff}.form-field.right-checkbox label:last-child{width:100%;text-align:center}.switch{position:relative;display:inline-block;width:51px;height:25px}.switch input{opacity:0;width:0;height:0}.slider{position:absolute;cursor:pointer;inset:0;background-color:#ccc;transition:.4s;border-radius:34px}.slider:before{position:absolute;content:\"\";height:17px;width:17px;left:4px;bottom:4px;background-color:#fff;transition:.4s;border-radius:50%}input:checked+.slider{background-color:#00d151}input:checked+.slider:before{transform:translateX(26px)}button{display:block;color:#fff;background:#000;width:100%;border:0;border-radius:10px;padding:10px;text-transform:uppercase;cursor:pointer;font-size:1.3em;margin-top:15px}</style></head><body><div class=wrapper><div class=content><div class=form><h1>SmartPool</h1>";
if (server->hasArg("saved")) html += "<div id=\"msg\">Data saved</div>";
html += "<form action=/smartpool method=POST><input type=\"hidden\" name=\"supla_csrf\" value=\"" + server->arg("supla_csrf") + "\">";
html += "<div class=box><h3>Czujniki DS18B20</h3>";
for (int t = 0; t < SENSOR_COUNT; t++) {
uint8_t selectedIdx = 255;
if (cfg) {
char key[20];
snprintf(key, sizeof(key), "ds_idx_%d", t);
cfg->getUInt8(key, &selectedIdx);
}
html += "<div class=form-field><label for=ds_assign_" + String(t) + ">" + String(SENSOR_NAMES[t]) + "</label><div><select name=ds_assign_" + String(t) + " id=ds_assign_" + String(t) + "><option value=255" + String(selectedIdx == 255 ? " selected" : "") + ">Nie przypisany</option>";
for (int i = 0; i < discoveredCount; i++) {
String idStr = "ID: ";
for (int b = 0; b < 4; b++) {
char hex[4];
snprintf(hex, sizeof(hex), "%02X", discoveredAddresses[i][b]);
idStr += hex;
}
html += "<option value=\"" + String(i) + "\"" + String(selectedIdx == i ? " selected" : "") + ">" + idStr + "...</option>";
}
html += "</select></div></div>";
}
html += "</div>";
uint8_t h_on_t1 = 0, h_on_t2 = 1, h_off_t1 = 0, h_off_t2 = 2;
int32_t h_on_diff = 5, h_off_diff = 3, h_min_time = 5;
if (cfg) {
cfg->getUInt8("heat_on_t1", &h_on_t1);
cfg->getUInt8("heat_on_t2", &h_on_t2);
cfg->getInt32("heat_on_diff", &h_on_diff);
cfg->getUInt8("heat_off_t1", &h_off_t1);
cfg->getUInt8("heat_off_t2", &h_off_t2);
cfg->getInt32("heat_off_diff", &h_off_diff);
cfg->getInt32("heat_min_time", &h_min_time);
}
html += "<div class=box><h3>Pompa ogrzewania</h3>";
html += "<div class=form-field style=gap:6px;><label>Warunek startu pompy</label><select name=heat_on_t1>";
for (int i = 0; i < SENSOR_COUNT; i++) html += "<option value=\"" + String(i) + "\"" + String(h_on_t1 == i ? " selected" : "") + ">" + String(SENSOR_NAMES[i]) + "</option>";
html += "</select><span><</span><select name=heat_on_t2>";
for (int i = 0; i < SENSOR_COUNT; i++) html += "<option value=\"" + String(i) + "\"" + String(h_on_t2 == i ? " selected" : "") + ">" + String(SENSOR_NAMES[i]) + "</option>";
html += "</select><span>o</span><input type=number min=0 name=heat_on_diff style=width:60px value=\"" + String(h_on_diff) + "\"></div>";
html += "<div class=form-field style=gap:6px;><label>Warunek stopu pompy</label><select name=heat_off_t1>";
for (int i = 0; i < SENSOR_COUNT; i++) html += "<option value=\"" + String(i) + "\"" + String(h_off_t1 == i ? " selected" : "") + ">" + String(SENSOR_NAMES[i]) + "</option>";
html += "</select><span><</span><select name=heat_off_t2>";
for (int i = 0; i < SENSOR_COUNT; i++) html += "<option value=\"" + String(i) + "\"" + String(h_off_t2 == i ? " selected" : "") + ">" + String(SENSOR_NAMES[i]) + "</option>";
html += "</select><span>o</span><input type=number min=0 name=heat_off_diff style=width:60px value=\"" + String(h_off_diff) + "\"></div>";
html += "<div class=form-field style=justify-content:space-between;><label>Minimalny czas pracy (min.)</label><input type=number min=0 name=heat_min_time style=width:60px;text-align:center value=\"" + String(h_min_time) + "\"></div></div>";
auto addToggleSwitch = [](String name, String label, uint8_t val) {
return "<div class=\"form-field right-checkbox\"><label for=\"" + name + "\">" + label + "</label><label><span class=switch><input type=checkbox value=1 name=\"" + name + "\" id=\"" + name + "\"" + String(val ? " checked" : "") + "><span class=slider></span></span></label></div>";
};
uint8_t l_pump = 0, l_chlor = 0, l_heat = 0, l_uv = 0, depSch = 0;
if (cfg) {
cfg->getUInt8("lock_pump", &l_pump);
cfg->getUInt8("lock_chlor", &l_chlor);
cfg->getUInt8("lock_heat", &l_heat);
cfg->getUInt8("lock_uv", &l_uv);
cfg->getUInt8("p_sch_dep", &depSch);
}
html += "<div class=box><h3>Zabezpieczenie - blokada</h3>";
html += addToggleSwitch("lock_pump", "Pompa filtracyjna", l_pump);
html += addToggleSwitch("lock_chlor", "Generator chloru i ozonu", l_chlor);
html += addToggleSwitch("lock_heat", "Pompa ogrzewania", l_heat);
html += addToggleSwitch("lock_uv", "Lampa UV-C", l_uv);
html += "</div>";
uint8_t chlorine = 0, uv = 0;
if (cfg) {
cfg->getUInt8("dep_chlorine", &chlorine);
cfg->getUInt8("dep_uv", &uv);
}
html += "<div class=box><h3>Kanały zależne od pompy filtracyjnej</h3>";
html += addToggleSwitch("dep_chlorine", "Generator chloru", chlorine);
html += addToggleSwitch("dep_uv", "Lampa UV-C", uv);
html += "</div>";
html += "<div class=box><h3>Harmonogramy pompy filtracyjnej</h3>";
html += addToggleSwitch("p_sch_dep", "Steruj kanałami zależnymi", depSch);
html += "</div>";
html += "<script>setTimeout(function(){var msgEl=document.getElementById('msg');if(msgEl){msgEl.remove();}},3200);</script>";
html += "<button type=button onclick=\"window.location.href='/'\">SUPLA SETTINGS</button>";
html += "<button type=button onclick=\"window.location.href='/update'\">UPDATE FIRMWARE</button>";
html += "<button type=submit>SAVE</button>";
html += "</form></div></div></div></body></html>";
server->send(200, "text/html", html);
}
class SmartPoolMenuLink : public Supla::HtmlElement {
public:
SmartPoolMenuLink() : HtmlElement(Supla::HTML_SECTION_FORM) {}
void send(Supla::WebSender* sender) override {
sender->send("</div><button type=button onclick=\"window.location.href='/smartpool'\">SMARTPOOL SETTINGS</button><button type=button onclick=\"window.location.href='/update'\">UPDATE FIRMWARE</button><div>");
}
};
// ======================================================
// HARMONOGRAM HVAC
// ======================================================
void checkHvacSchedulePump() {
auto cfg = Supla::Storage::ConfigInstance();
if (!cfg || !relayPump || !hvacPool || !virtualRelay) return;
bool harmonogramActive = virtualRelay->isOn();
if (!harmonogramActive) return;
auto currentProgram = hvacPool->getCurrentProgram();
double my_temp = currentProgram.SetpointTemperatureHeat / 100.0;
bool shouldBeOn = false;
if (my_temp >= 40.0) {
shouldBeOn = true;
} else if (my_temp <= 20.0) {
shouldBeOn = false;
} else {
shouldBeOn = false;
}
bool pumpState = relayPump->isOn();
if (shouldBeOn && !pumpState) {
relayPump->turnOn();
uint8_t dep = 0;
cfg->getUInt8("p_sch_dep", &dep);
if (dep == 1) {
bool schDepChlorine = false;
bool schDepUV = false;
uint8_t temp = 0;
cfg->getUInt8("dep_chlorine", &temp);
schDepChlorine = (temp == 1);
cfg->getUInt8("dep_uv", &temp);
schDepUV = (temp == 1);
bool mainLockActive = (relayLock && relayLock->isOn());
cfg->getUInt8("lock_chlor", &temp);
if (mainLockActive && temp == 1) schDepChlorine = false;
cfg->getUInt8("lock_uv", &temp);
if (mainLockActive && temp == 1) schDepUV = false;
if (schDepChlorine && relayChlorine && !relayChlorine->isOn()) {
relayChlorine->turnOn();
}
if (schDepUV && relayUV && !relayUV->isOn()) {
relayUV->turnOn();
}
}
} else if (!shouldBeOn && pumpState) {
relayPump->turnOff();
}
if (shouldBeOn && pumpState) {
uint8_t dep = 0;
cfg->getUInt8("p_sch_dep", &dep);
if (dep == 1) {
bool schDepChlorine = false;
bool schDepUV = false;
uint8_t temp = 0;
cfg->getUInt8("dep_chlorine", &temp);
schDepChlorine = (temp == 1);
cfg->getUInt8("dep_uv", &temp);
schDepUV = (temp == 1);
bool mainLockActive = (relayLock && relayLock->isOn());
cfg->getUInt8("lock_chlor", &temp);
if (mainLockActive && temp == 1) schDepChlorine = false;
cfg->getUInt8("lock_uv", &temp);
if (mainLockActive && temp == 1) schDepUV = false;
if (schDepChlorine && relayChlorine && !relayChlorine->isOn()) {
relayChlorine->turnOn();
}
if (schDepUV && relayUV && !relayUV->isOn()) {
relayUV->turnOn();
}
}
}
}
// ======================================================
// LOGIKA ZALEŻNOŚCI
// ======================================================
void handleRelayDependencies() {
auto cfg = Supla::Storage::ConfigInstance();
if (cfg) {
uint8_t temp = 0;
cfg->getUInt8("lock_pump", &temp); lockPump = (temp == 1);
cfg->getUInt8("lock_chlor", &temp); lockChlorine = (temp == 1);
cfg->getUInt8("lock_heat", &temp); lockHeating = (temp == 1);
cfg->getUInt8("lock_uv", &temp); lockUV = (temp == 1);
cfg->getUInt8("dep_chlorine", &temp); depChlorine = (temp == 1);
cfg->getUInt8("dep_uv", &temp); depUV = (temp == 1);
}
bool mainLockActive = (relayLock && relayLock->isOn());
setRelayBlocked(relayPump, mainLockActive && lockPump);
setRelayBlocked(relayChlorine, mainLockActive && lockChlorine);
setRelayBlocked(relayHeatPump, mainLockActive && lockHeating);
setRelayBlocked(relayUV, mainLockActive && lockUV);
if (mainLockActive && lockHeating) {
heatPumpRunningInAuto = false;
}
if (relayPump && !(mainLockActive && lockPump)) {
static bool lastPumpState = false;
bool currentPumpState = relayPump->isOn();
if (lastPumpState == true && currentPumpState == false) {
if (depChlorine && relayChlorine && relayChlorine->isOn()) relayChlorine->turnOff();
if (depUV && relayUV && relayUV->isOn()) relayUV->turnOff();
lastPumpState = currentPumpState;
return;
}
if (!currentPumpState) {
if (depChlorine && relayChlorine && relayChlorine->isOn()) {
relayPump->turnOn();
currentPumpState = true;
} else if (depUV && relayUV && relayUV->isOn()) {
relayPump->turnOn();
currentPumpState = true;
}
}
if (!currentPumpState) {
if (depChlorine && relayChlorine && relayChlorine->isOn()) relayChlorine->turnOff();
if (depUV && relayUV && relayUV->isOn()) relayUV->turnOff();
}
lastPumpState = currentPumpState;
}
}
void handleRelayLocks() {
bool mainLockActive = (relayLock && relayLock->isOn());
setRelayBlocked(relayPump, mainLockActive && lockPump);
setRelayBlocked(relayChlorine, mainLockActive && lockChlorine);
setRelayBlocked(relayHeatPump, mainLockActive && lockHeating);
setRelayBlocked(relayUV, mainLockActive && lockUV);
if (mainLockActive && lockHeating) {
heatPumpRunningInAuto = false;
}
}
// ======================================================
// SETUP
// ======================================================
void setup() {
Serial.begin(115200);
delay(1000);
new Supla::Clock;
SuplaDevice.allowWorkInOfflineMode(0);
SuplaDevice.setName("SUPLA-SmartPool");
SuplaDevice.setSwVersion("SmartPool v2.4");
new Supla::Html::DeviceInfo(&SuplaDevice);
new Supla::Html::WifiParameters;
new Supla::Html::ProtocolParameters(false, false);
new Supla::Html::StatusLedParameters;
new Supla::Html::TimeParameters(&SuplaDevice);
new SmartPoolMenuLink();
relayLock = new Supla::Control::Relay(RELAY_1_GPIO, true);
relayPump = new Supla::Control::Relay(RELAY_2_GPIO, true);
relayChlorine = new Supla::Control::Relay(RELAY_3_GPIO, true);
relayHeatPump = new Supla::Control::Relay(RELAY_4_GPIO, true);
relayUV = new Supla::Control::Relay(RELAY_5_GPIO, true);
relayLight = new Supla::Control::Relay(RELAY_6_GPIO, true);
relayLock->getChannel()->setChannelNumber(0);
relayLock->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
relayLock->setInitialCaption("Zabezpieczenie");
relayPump->getChannel()->setChannelNumber(1);
relayPump->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
relayPump->setInitialCaption("Pompa filtracyjna");
relayChlorine->getChannel()->setChannelNumber(2);
relayChlorine->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
relayChlorine->setInitialCaption("Generator chloru i ozonu");
relayHeatPump->getChannel()->setChannelNumber(3);
relayHeatPump->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
relayHeatPump->setInitialCaption("Pompa ogrzewania");
relayUV->getChannel()->setChannelNumber(4);
relayUV->setDefaultFunction(SUPLA_CHANNELFNC_LIGHTSWITCH);
relayUV->setInitialCaption("Lampa UV-C");
relayLight->getChannel()->setChannelNumber(5);
relayLight->setDefaultFunction(SUPLA_CHANNELFNC_LIGHTSWITCH);
relayLight->setInitialCaption("Oświetlenie basenu");
virtualRelay = new Supla::Control::VirtualRelay();
virtualRelay->getChannel()->setChannelNumber(6);
virtualRelay->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
virtualRelay->setInitialCaption("Harmonogram pompy filtracyjnej");
virtualRelay->setDefaultStateRestore();
pinMode(RELAY_7_GPIO, OUTPUT);
pinMode(RELAY_8_GPIO, OUTPUT);
digitalWrite(RELAY_7_GPIO, LOW);
digitalWrite(RELAY_8_GPIO, LOW);
auto buttonLight = new Supla::Control::Button(LIGHT_BUTTON_GPIO, true, true);
buttonLight->setHoldTime(1000);
buttonLight->setMulticlickTime(300);
auto atLight = new Supla::Control::ActionTrigger();
atLight->setRelatedChannel(relayLight);
atLight->attach(buttonLight);
buttonLight->addAction(Supla::TOGGLE, relayLight, Supla::ON_PRESS);
buttonLight->addAction(Supla::TOGGLE, relayLock, Supla::ON_HOLD);
auto hvacOutput = new Supla::Control::InternalPinOutput(-1);
hvacPool = new Supla::Control::HvacBase(hvacOutput);
hvacPool->getChannel()->setChannelNumber(7);
hvacPool->setInitialCaption("Termostat Basenu");
hvacPool->setMainThermometerChannelNo(8);
hvacPool->setDefaultTemperatureRoomMin(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 2000);
hvacPool->setDefaultTemperatureRoomMax(SUPLA_CHANNELFNC_HVAC_THERMOSTAT, 4000);
hvacPool->getChannel()->setHvacSetpointTemperatureHeat(3300);
hvacPool->setTemperatureHisteresis(10);
hvacPool->setTemperatureHisteresisMin(10);
hvacPool->setTemperatureHisteresisMax(1000);
scanDS18B20();
for (int i = 0; i < SENSOR_COUNT; i++) {
dsSensors[i] = new ConfigurableDS18B20(i);
dsSensors[i]->getChannel()->setChannelNumber(8 + i);
dsSensors[i]->setInitialCaption(SENSOR_NAMES[i]);
}
auto buttonCfg = new Supla::Control::Button(BUTTON_CFG_GPIO, true, true);
buttonCfg->configureAsConfigButton(&SuplaDevice);
SuplaDevice.setSuplaCACert(suplaCACert);
SuplaDevice.setSupla3rdPartyCACert(supla3rdCACert);
SuplaDevice.begin(21);
if (suplaServer.getServerPtr()) {
httpUpdater.setup(suplaServer.getServerPtr(), "/update");
suplaServer.getServerPtr()->on("/smartpool", HTTP_GET, handleSmartPoolPage);
suplaServer.getServerPtr()->on("/smartpool", HTTP_POST, handleSmartPoolSaveAction);
}
}
// ======================================================
// LOOP
// ======================================================
void loop() {
SuplaDevice.iterate();
handleRelayLocks();
static unsigned long lastTimeAndTempCheck = 0;
if (millis() - lastTimeAndTempCheck >= 10000) {
lastTimeAndTempCheck = millis();
checkHvacSchedulePump();
if (hvacPool) {
bool hvacEnabled = hvacPool->getMode() != SUPLA_HVAC_MODE_OFF;
digitalWrite(RELAY_7_GPIO, hvacEnabled ? HIGH : LOW);
bool hvacHeating = false;
double currentTemp = dsSensors[0]->getValue();
double targetTemp = hvacPool->getTemperatureSetpointHeat() / 100.0;
double hysteresis = hvacPool->getCurrentHysteresis(false) / 100.0;
if (hvacEnabled && currentTemp > -100 && currentTemp < (targetTemp - hysteresis)) {
hvacHeating = true;
}
bool mainLockActive = (relayLock && relayLock->isOn());
if (mainLockActive && lockHeating) hvacHeating = false;
digitalWrite(RELAY_8_GPIO, hvacHeating ? HIGH : LOW);
}
}
handleRelayDependencies();
static bool LOCAL_WEB_SERVER = false;
if (!LOCAL_WEB_SERVER && Supla::Network::IsReady()) {
LOCAL_WEB_SERVER = true;
SuplaDevice.handleAction(0, Supla::START_LOCAL_WEB_SERVER);
}
}Code: Select all
virtualRelay = new Supla::Control::VirtualRelay();
virtualRelay->getChannel()->setChannelNumber(6);
virtualRelay->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH);
virtualRelay->setInitialCaption("Harmonogram pompy filtracyjnej");
virtualRelay->setDefaultStateRestore();Niespełniony automatyk. 
https://3d-lamp.photos/
https://pool.lector.top/
https://3d-lamp.photos/
https://pool.lector.top/
-
Lector
- Posts: 2471
- Joined: Fri Nov 17, 2017 2:26 pm
- Location: Poznań
- Has thanked: 13 times
- Been thanked: 25 times
Już myślałem ze mi się udało rozwiązać problem, ale jednak nie.
W załączeniu daje logi.
W załączeniu daje logi.
You do not have the required permissions to view the files attached to this post.
Niespełniony automatyk. 
https://3d-lamp.photos/
https://pool.lector.top/
https://3d-lamp.photos/
https://pool.lector.top/
-
Lector
- Posts: 2471
- Joined: Fri Nov 17, 2017 2:26 pm
- Location: Poznań
- Has thanked: 13 times
- Been thanked: 25 times
Takie może głupie pytanie. Czy zapis mojej konfiguracji ma być do tego samego pliku co supla?
W tedy moja konfiguracja nadpisywała ustawienia Supli?
Teraz próbuje rozbić na dwa pliki.
W tedy moja konfiguracja nadpisywała ustawienia Supli?
Teraz próbuje rozbić na dwa pliki.
Niespełniony automatyk. 
https://3d-lamp.photos/
https://pool.lector.top/
https://3d-lamp.photos/
https://pool.lector.top/
-
vajera
- Posts: 7290
- Joined: Wed Oct 31, 2018 7:58 am
- Location: Biedrusko
- Has thanked: 289 times
- Been thanked: 161 times
Jeżeli używasz klasy Config to możesz zapisywać do tego samego pliku, co Supla. Pamiętaj tylko, że domyślny rozmiar Config to chyba 1024 bajty.Lector wrote: Tue Jun 02, 2026 7:21 pm Takie może głupie pytanie. Czy zapis mojej konfiguracji ma być do tego samego pliku co supla?
W tedy moja konfiguracja nadpisywała ustawienia Supli?
Teraz próbuje rozbić na dwa pliki.
Bramka Zigbee <=> SUPLA
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
Więcej informacji tutaj:
https://forum.supla.org/viewforum.php?f=127
FAQ https://forum.supla.org/viewtopic.php?t=17277
-
lukfud
- Posts: 2480
- Joined: Thu Nov 23, 2017 11:33 pm
- Location: Warszawa
- Has thanked: 13 times
- Been thanked: 11 times
brakuje:Lector wrote: Mon Jun 01, 2026 8:10 pm A jeszcze nie pamieta i stanu.Code: Select all
virtualRelay = new Supla::Control::VirtualRelay(); virtualRelay->getChannel()->setChannelNumber(6); virtualRelay->setDefaultFunction(SUPLA_CHANNELFNC_POWERSWITCH); virtualRelay->setInitialCaption("Harmonogram pompy filtracyjnej"); virtualRelay->setDefaultStateRestore();
Code: Select all
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom;
https://www.facebook.com/groups/supladiy
https://www.facebook.com/groups/suplazamel
https://www.facebook.com/groups/suplaauraton
https://smartnerzeczy.pl
https://www.facebook.com/groups/suplazamel
https://www.facebook.com/groups/suplaauraton
https://smartnerzeczy.pl
