Set initial caption ustawi w cloud nazwę, jeśli nie było tam nic wcześniej ustawione.
Potem już zmiana nie działa
Pytania techniczne dotyczące kodu [bramka ZigBee]
Moderator: vajera
-
vajera
- Posts: 7290
- Joined: Wed Oct 31, 2018 7:58 am
- Location: Biedrusko
- Has thanked: 289 times
- Been thanked: 161 times
@klew - poniżej efekt moich wielotygodniowych walk z brakiem pamięci:
Tyle opisu przypadku, a teraz pora na poszerzoną diagnostykę i opis leczenia
Przeglądając bezkresne zakamarki Internetu trafiłem kilka dni temu na taki oto wpis:
https://www.reddit.com/r/esp32/comments ... oide_and_a
Pozwolę sobie zacytować kluczowy fragment:

Znalazłem plik \SuplaDevice\src\supla\arduino_esp_platform.cpp , a w nim taki fragment kodu:
To oznacza, że w każdej sytuacji opisanej powyżej w pkt. 4 SuplaDevice dynamicznie usuwa i tworzy obiekt WiFiClientSecure 
Zmodyfikowałem, więc swoją lokalną kopię tego pliku - póki co jest to oczywiście wersja robocza:
Powiem szczerze, że nie zakładałem, że to w ogóle zadziała - jest to w sumie proteza a la MacGyver
, ale ku mojemu zaskoczeniu kod się skompilował bramka ruszyła i...działa.
Testowa bramka pracuje już prawie dwie godziny, w tym czasie wielokrotnie rozłączałem router w telefonie - po jego ponownym włączeniu bramka nawiązywała połączenie SSL bez najmniejszego problemu, parametry wolnej pamięci RAM pozostają bez zmian.
@klew - pytanie do Ciebie - czy widzisz przestrzeń na pull request, czy raczej mam to zostawić jako lokalną modyfikację biblioteki SuplaDevice?
- Problem stał się zauważalny po wprowadzeniu newGUI, ale co do zasady istniał już wcześniej, tylko wtedy było więcej RAMu do dyspozycji.
ㅤ - Moje środowisko testowe wygląda następująco:
- bramka Z2S (ESP32 C6),
- minimum 7 urządzeń Zigbee dodanych do bramki,
- 15 - 20 kanałów Supla (binarne, przekaźniki, liczniki elektryczne, HVAC).
- Pierwsze uruchomienie zwykle przebiega bezproblemowo - bramka loguje się do sieci WiFi, następnie do serwera Supla, uruchamia się stos Zigbeee, bramka wchodzi w tryb parowania.
ㅤ - Problem pojawia się w bardzo konkretnej sytuacji - gdy z jakiegokolwiek powodu Supla straci połączenie z serwerem:
- utrata połączenia z WiFi,
- jakakolwiek zmiana w Cloud (np. zmiana nazwy, funkcji przekaźnika itp.), czyli coś co dzieje się dosyć często ,
- awaria serwera Supla.
- W momencie nawiązania ponownego połączenia (sytuacja dotyczy szyfrowanego połączenia z serwerem) bardzo często pojawia się w logach błąd modułu ssl_client dotyczący braku pamięci, co skutkuje brakiem połączenia bramki z serwerem Supla.
ㅤ - Wielu użytkowników może tego nigdy nie zauważyć z kilku powodów:
- bramka ma zaledwie kilka kanałów Supla - wtedy problem zwykle nie występuje - a przynajmniej nie od razu, gdyż ma on tendencję do kumulowania się,
- w przypadku braku połączenia z siecią po około 5 minutach dochodzi automatycznie do ponownego uruchomienia bramki - patrz pkt. 3 - tylko, że w tej sytuacji część danych nie trafi do Supla a użytkownik może odnieść wrażenie, że bramka się często zawiesza.
- W przypadku ESP32 C5, który ma nieco mniej pamięci RAM niż C6, bramka nie była praktycznie w stanie normalnie pracować. Oczywiście C5 ma pamięć PSRAM, ale nie udało mi się zmusić klienta SSL do korzystania z niej.
ㅤ - Zacząłem już dopuszczać do świadomości fakt, że dla bardziej rozbudowanych bramek jedyną opcją będzie S3+C6, ale wciąż jeszcze próbowałem znaleźć jakiekolwiek rozwiązanie, równoległe optymalizując kod, gdzie się da.
ㅤ - Najgorsze było to, że bramka ma pod dostatkiem pamięci, np. Free Heap: 63764 B | Minimal Free Heap: 1912 B | HeapSize: 361260 B | MaxAllocHeap: 19444 B, ale w momencie ponownego nawiązania połączenia SSL robi się wąskie gardło

Tyle opisu przypadku, a teraz pora na poszerzoną diagnostykę i opis leczenia
Przeglądając bezkresne zakamarki Internetu trafiłem kilka dni temu na taki oto wpis:
https://www.reddit.com/r/esp32/comments ... oide_and_a
Pozwolę sobie zacytować kluczowy fragment:
Pomyślałem sobie, że nie zaszkodzi wypróbować ten pomysł, chociaż szczerze mówiąc miałem obawy, czy dam radę zmodyfikować kod SuplaDevice w tym zakresie i jednocześnie nic nie popsućAfter beating my head against a heap memory leak for about a week, I learned something today -- WiFiClientSecure doesn't like being created and destroyed.
If you have an ESP32 program which makes recurring HTTP/HTTPS calls, don't make multiple WiFiClientSecure objects or destroy the client after each use -- save a pointer to one global object in setup() and just reuse it. Same applies to WiFiClient, though the heap space "lost" is much lower.
On an ESP32-WROOM board I was seeing a panic reboot every 8 hours, with the single global "client" object I've gone 10+ hours so far with no decrease in free heap!
Znalazłem plik \SuplaDevice\src\supla\arduino_esp_platform.cpp , a w nim taki fragment kodu:
Code: Select all
~ArduinoEspClient() {
if (wifiClient) {
wifiClient->stop();
delete wifiClient;
}
}
...........
void stop() override {
if (wifiClient) {
wifiClient->stop();
delete wifiClient;
wifiClient = nullptr;
log_i("Oops!...I Did Again!"); //to moje
}
}
...................
if (sslEnabled) {
clientSec = new WiFiClientSecure();
wifiClient = clientSec;
.........
Zmodyfikowałem, więc swoją lokalną kopię tego pliku - póki co jest to oczywiście wersja robocza:
Code: Select all
static WiFiClientSecure myWiFiClientSecure;
..........................................................................
class ArduinoEspClient : public Client {
public:
~ArduinoEspClient() {
if (wifiClient) {
//wifiClient->stop();
//delete wifiClient;
}
}
......................................................................
void stop() override {
if (wifiClient) {
//wifiClient->stop();
//delete wifiClient;
//wifiClient = nullptr;
}
}
..................................................................
if (sslEnabled) {
clientSec = &myWiFiClientSecure;//new WiFiClientSecure();
wifiClient = clientSec;
Testowa bramka pracuje już prawie dwie godziny, w tym czasie wielokrotnie rozłączałem router w telefonie - po jego ponownym włączeniu bramka nawiązywała połączenie SSL bez najmniejszego problemu, parametry wolnej pamięci RAM pozostają bez zmian.
@klew - pytanie do Ciebie - czy widzisz przestrzeń na pull request, czy raczej mam to zostawić jako lokalną modyfikację biblioteki SuplaDevice?
Last edited by vajera on Thu Sep 18, 2025 1:39 pm, edited 1 time in total.
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
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
PR jak najbardziej, ale sprawdź to najpierw na wszystkich boardach ESP32
Tam ogólnie już tego rodzaju problemy kiedyś były i to kasowanie i tworzenie było chyba dodane, aby zaradzić memory leakom, które następowały przy kolejnych połączeniach ssl.
Ogólnie trzeba by się przekopać przez historię na github i poszukać kiedy/gdzie/dlaczego to niszczenie i tworzenie zostało dodane.
Osobiście uważam, że jak się klienta niszczy to powinien zwolnić pamięć. Jeśli tego nie robi, to poprawić to u źródła, czyli poszukać przyczyny w boardach ESP i tam poprawić. Lub chociaż tam błąd zgłosić.
Chyba, że coś powinno być wykonane przed zniszczeniem obiektu, ale to znowu trzeba poszukać.
Najlepsze suple dla Twojego domu 
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
Przejrzałem trochę kod i wrzuciłem jakąś propozycję zmiany, choć nie testowałem
Także proszę o testy. Fajnie by było gdyby zebrać jakiś feedback dla ESP8266 oraz kilku wariantów ESP32.
Ogólnie ten leak, o którym wcześniej pisałem, dotyczył ESP8266. Workaroundem na leakowanie przy reconnect było tam całkowite wyłączenie stosu Wi-Fi i włączenie go od nowa...
Aktualnie w kodzie wyrzuciłem kasowanie clienta przy metodzie stop() i nie tworzę nowego przy nawiązywaniu połączenia, gdy obiekt już istnieje.
Wydaje mi się, że powinno wszystko działać.Jedyna problematyczna sytuacja dotyczy scenariusza, gdy ktoś na tym samym kliencie spróbuje nawiązać raz szyfrowane i raz nieszyfrowane połączenie. Także takich rzeczy proszę nie robić ;P
Także proszę o testy. Fajnie by było gdyby zebrać jakiś feedback dla ESP8266 oraz kilku wariantów ESP32.
Ogólnie ten leak, o którym wcześniej pisałem, dotyczył ESP8266. Workaroundem na leakowanie przy reconnect było tam całkowite wyłączenie stosu Wi-Fi i włączenie go od nowa...
Aktualnie w kodzie wyrzuciłem kasowanie clienta przy metodzie stop() i nie tworzę nowego przy nawiązywaniu połączenia, gdy obiekt już istnieje.
Wydaje mi się, że powinno wszystko działać.Jedyna problematyczna sytuacja dotyczy scenariusza, gdy ktoś na tym samym kliencie spróbuje nawiązać raz szyfrowane i raz nieszyfrowane połączenie. Także takich rzeczy proszę nie robić ;P
Najlepsze suple dla Twojego domu 
-
vajera
- Posts: 7290
- Joined: Wed Oct 31, 2018 7:58 am
- Location: Biedrusko
- Has thanked: 289 times
- Been thanked: 161 times
@Klew - wracam do tematu Hvac i czujnika binarnego 
Przy pierwszym dodaniu urządzenia wykonuje się następujący kod:
Czyli zgodnie z Twoimi wytycznymi ustawiam kanał czujnika binarnego na identyczny z kanałem Hvac.
Przy każdym kolejnym uruchomieniu bramki wykonuje się funkcja initZ2SDeviceHvac, a w niej:
Teraz moje pytanie - czy również w tej funkcji powinna pojawić się następująca linia kodu?
Jeżeli tak, to co w sytuacji, gdy w międzyczasie użytkownik zmienił kanał czujnika binarnego na inny - to się ustawi w onLoad...()?
Przy pierwszym dodaniu urządzenia wykonuje się następujący kod:
Code: Select all
void addZ2SDeviceHvac(ZigbeeGateway * gateway, zbg_device_params_t *device, uint8_t free_slot, uint8_t trv_thermometer_slot) {
auto Supla_Z2S_HvacBase = new Supla::Control::HvacBaseEE();
Supla_Z2S_HvacBase->setMainThermometerChannelNo(z2s_channels_table[trv_thermometer_slot].Supla_channel);
Supla_Z2S_HvacBase->setBinarySensorChannelNo(Supla_Z2S_HvacBase->getChannel()->getChannelNumber());
Przy każdym kolejnym uruchomieniu bramki wykonuje się funkcja initZ2SDeviceHvac, a w niej:
Code: Select all
auto Supla_Z2S_HvacBase = new Supla::Control::HvacBaseEE(Supla_Z2S_TRVInterface);Code: Select all
Supla_Z2S_HvacBase->getChannel()->setChannelNumber(z2s_channels_table[channel_number_slot].Supla_channel);Code: Select all
Supla_Z2S_HvacBase->setBinarySensorChannelNo(z2s_channels_table[channel_number_slot].Supla_channel);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
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
Ogólnie wszystkie defaulty powinieneś ustawić za każdym razem na klasie. Także ten binary i termometr raczej powinny się w konstruktorze inicjalizować.vajera wrote: Thu Oct 02, 2025 3:58 pm @Klew - wracam do tematu Hvac i czujnika binarnego
...
Jeżeli tak, to co w sytuacji, gdy w międzyczasie użytkownik zmienił kanał czujnika binarnego na inny - to się ustawi w onLoad...()?
Jeśli zmieniasz numery kanałów (hvac, binary, etc) to to też trzeba ręcznie poprawić - przed suplową inicjalizacją elementów.
Nie wiem też, w którym momencie tworzysz te obiekty - powinny być utworzone przed "SuplaDevice.begin()", albo w trakcie jakiegoś "onLoadConfig" na obiekcie "konfiguratora urządzenia"
Jeśli dodajesz Elementy w runtime (np. przy parowaniu) i chcesz aby działały bez resetu bramki, to też trzeba ręcznie wywołać kilka operacji. Warto też dodać tam wymuszony zapis do "state storage", bo dodanie nowego elementu, zmienia strukturę storage i jeśli zrobisz reset bramki, to odczyt starego storage może się nie udać i stan kanałów przepadnie.
Przy bramkach koniecznie trzeba też używać "enableChannelNumbers()" na instancji storage. Bez tego musiałbyś zachować identyczną kolejność tworzenia Elementów za każdym razem.
Najlepsze suple dla Twojego domu 
-
vajera
- Posts: 7290
- Joined: Wed Oct 31, 2018 7:58 am
- Location: Biedrusko
- Has thanked: 289 times
- Been thanked: 161 times
To może tutaj jest pies pogrzebany.klew wrote: Fri Oct 03, 2025 9:51 amOgólnie wszystkie defaulty powinieneś ustawić za każdym razem na klasie. Także ten binary i termometr raczej powinny się w konstruktorze inicjalizować.vajera wrote: Thu Oct 02, 2025 3:58 pm @Klew - wracam do tematu Hvac i czujnika binarnego
...
Jeżeli tak, to co w sytuacji, gdy w międzyczasie użytkownik zmienił kanał czujnika binarnego na inny - to się ustawi w onLoad...()?
Jeśli zmieniasz numery kanałów (hvac, binary, etc) to to też trzeba ręcznie poprawić - przed suplową inicjalizacją elementów.
Tworzone są prawilnie - przed begin();Nie wiem też, w którym momencie tworzysz te obiekty - powinny być utworzone przed "SuplaDevice.begin()", albo w trakcie jakiegoś "onLoadConfig" na obiekcie "konfiguratora urządzenia"![]()
Może kiedyś podejdę do tematu dodawania urządzeń w locie, ale póki co ten mechanizm z resetem nie jest chyba zbyt uciążliwy. Chyba, że ktoś zacznie stawiać bramki na 30 termometrówJeśli dodajesz Elementy w runtime (np. przy parowaniu) i chcesz aby działały bez resetu bramki, to też trzeba ręcznie wywołać kilka operacji. Warto też dodać tam wymuszony zapis do "state storage", bo dodanie nowego elementu, zmienia strukturę storage i jeśli zrobisz reset bramki, to odczyt starego storage może się nie udać i stan kanałów przepadnie.
Przy bramkach koniecznie trzeba też używać "enableChannelNumbers()" na instancji storage. Bez tego musiałbyś zachować identyczną kolejność tworzenia Elementów za każdym razem.
Dziękuję za uwagę o zapisie do state storage, natomiast o tej funkcji enableChannelNumbers() nigdy wcześniej nie słyszałem - od dawna jest w SD?
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
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
Stan przepadnie. Pytanie czego stan trzymasz?vajera wrote: Fri Oct 03, 2025 10:08 am Dziękuję za uwagę o zapisie do state storage, natomiast o tej funkcji enableChannelNumbers() nigdy wcześniej nie słyszałem - od dawna jest w SD?Pytanie, czy jak ją teraz włączę, to stan kanałów w istniejących bramkach przepadnie?
Najlepsze suple dla Twojego domu 
-
vajera
- Posts: 7290
- Joined: Wed Oct 31, 2018 7:58 am
- Location: Biedrusko
- Has thanked: 289 times
- Been thanked: 161 times
Przepadnie, ale jednorazowo, prawda?klew wrote: Fri Oct 03, 2025 10:57 amStan przepadnie. Pytanie czego stan trzymasz?vajera wrote: Fri Oct 03, 2025 10:08 am Dziękuję za uwagę o zapisie do state storage, natomiast o tej funkcji enableChannelNumbers() nigdy wcześniej nie słyszałem - od dawna jest w SD?Pytanie, czy jak ją teraz włączę, to stan kanałów w istniejących bramkach przepadnie?
Bo w zasadzie to te urządzenia ZigBee powinny same stan przechowywać.
Aktualnie to ten switch Enable gateway notifications oraz czujniki binarne, o ile użytkownik nie włączył mechanizmu timeout
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
-
klew
- Posts: 13908
- Joined: Thu Jun 27, 2019 12:16 pm
- Location: Wrocław
- Has thanked: 134 times
- Been thanked: 137 times
vajera wrote: Fri Oct 03, 2025 11:08 am Przepadnie, ale jednorazowo, prawda?
Aktualnie to ten switch Enable gateway notifications oraz czujniki binarne, o ile użytkownik nie włączył mechanizmu timeout
Tak, jednorazowo.
Najlepsze suple dla Twojego domu 
