Po premierze ESPHome w wersji 2026.4 musiałem przerobić m.in. kod swojego „inteligentnego dzwonka” na ESP32, bo „coś tam się zmieniło” i skompilować już się nie dało. Od razu uznałem, że może to zainteresować jeszcze kogoś, a więc warto zrobić o tym wpis. Jak pomyślałem, tak… nie zrobiłem, i temat ostatecznie trafił do przepastnego katalogu z pomysłami na artykuły. Ale dziś odezwał się do mnie kolega, który na bazie mojego dzwonka robił swój, a właśnie dokonał aktualizacji ESPHome, czy może u siebie miałem problem z… Tak więc uznałem, że to dobra okazja, by temat wyciągnąć i wrzucić na tapet. Zwłaszcza że niebawem zapewne premiera ESPHome w wersji 2026.5 i kto wie, może będzie nieaktualny…

Błąd kompilacji „redefinition of uint32_t iteration” w ESPHome 2026.4

W każdym razie jeszcze w ESPHome 2026.3.3 (ostatnia wersja z gałęzi 2026.3) wszystko działa i ładnie się kompiluje, a po aktualizacji do wersji ESPHome 2026.4 (w tym 2026.4.5, czyli aktualnie najnowszej wersji) w oknie z logami wyskakuje błąd:

/config/dzwonek.yaml: In function 'void setup()':
/config/dzwonek.yaml:1005:63: error: redefinition of 'uint32_t iteration'
/config/dzwonek.yaml:1005:43: note: 'uint32_t iteration' previously declared here

I choć odpowiedź jest w pliku YAML, to jednak on nie ma nawet tylu linii, by przejść do linii wskazanej, jako ta z błędem, więc od razu skierowałem się do pliku:

/opt/docker/esphome/config/.esphome/build/dzonek/src/main.cpp

I był to krok właściwy, bo tam znalazłem coś takiego:

delayaction_id_5->set_delay([](uint32_t iteration, uint32_t iteration) -> uint32_t {
return 1000;
});

Mamy niby dwa parametry (parametry funkcji lambda), ale oba mają tę samą nazwę: iteration, czyli:

(uint32_t iteration, uint32_t iteration)

zamiast np.:

(uint32_t iteration, uint32_t iteration_2)

I już bez zanudzania szczegółami napisze tylko, że w C++ po prostu to się nie może udać w takiej postaci…

Zmiany w kodzie YAML

No i tak wracamy do kodu YAML, bo przy okazji odczytu kodu z pliku „main.cpp” widziałem od razu, której funkcji to dotyczy. A konkretnie którego skryptu:


script:
  - id: script_bell_ding_dong
    then:
      - repeat:
          count: 2
          then:
            - repeat:
                count: 2
                then:
                  - button.press: ${device_id}_buzzer_button
                  - delay: 1000ms
            - delay: 2000ms   

Jest to teoretycznie prosta, ale jednak też i złożona konstrukcja, która wywołana aktywuje przycisk sygnalizacyjny w ramach sekwencji: ding + przerwa 1 sekunda + dong + przerwa 1 sekunda + przerwa 2 sekundy + ding + przerwa 1 sekunda + dong, za co odpowiada dwukrotne powtórzenie (repeat) upakowane w inne dwukrotne powtórzenie… I samo to jeszcze przeszło, ale problem zaczyna się ze zwłoką, czyli „delay”, czego dotyczy umieszczony wyżej kod z pliku „main.cpp”.

Z racji tego, że w moim przypadku są to tylko dwa powtórzenia + kolejne dwa, to najprostszym wyjściem było uprościć kod tak, by zrezygnować z drugiego powtórzenia:


script:
  - id: script_bell_ding_dong
    then:
      - repeat:
          count: 2
          then:
            - button.press: ${device_id}_buzzer_button
            - delay: 1000ms
            - button.press: ${device_id}_buzzer_button
            - delay: 3000ms

Powtórzenie w powtórzeniu było „na zaś”, jakbym kiedyś potrzebował zwiększyć liczbę „bipnięć”.

Jeśli jednak kod miałby więcej powtórzeń, to lepiej np. rozbić go na dwa skrypty, i z jednego wywoływać drugi:


script:
  - id: script_bell_beeper
    then:
      - repeat:
          count: 2
          then:
            - button.press: ${device_id}_buzzer_button
            - delay: 1000ms
  - id: script_bell_ding_dong
    then:
      - repeat:
          count: 2
          then:
            - script.execute: script_bell_beeper
            - delay: 2000ms

Dzięki takiemu rozdzieleniu, podczas kompilacji nie będzie problemu, że oba parametry mają taką samą nazwę (iteration), bo dzięki rozbiciu na dwa skrypty, będą w niezależnych funkcjach.

Funkcja tylko i wyłącznie awaryjna

Na koniec uprzedzając ewentualne pytania, czemu „bipam buzzerem”, zamiast wykorzystać inne możliwości związane z powiadomieniem, że ktoś dzwoni: jak najbardziej korzystam z innych opcji (m.in. dzwonek mp3 i komunikat TTS na głośniku po I2S; powiadomienie tekstowe na „inteligentne zegary”; powiadomienie na TV i telefon…), ale to jest funkcja wywoływana awaryjnie, w sytuacji, gdyby z jakiegoś powodu ESP32 obsługujące dzwonek nie tylko nie miało połączenia z Home Assistant, ale i kilkoma innymi ESP32 (za pomocą ESP-Now czy UDP w ESPHome), czyli właściwie bardzo mało prawdopodobna sytuacja, ale że potencjalnie możliwa, to obsłużona… ;-)

(!) Zgłoś błąd na stronie
Pomogłem? To może postawisz mi wirtualną kawę?
LUTy dla D-Cinelike (DJI Mini 3 Pro, DJI Avata, OSMO Pocket) od MiniFly
Wdrożenie Omnibusa w sklepie na WooCommerce
Jak (legalnie) latać dronem w Kategorii Otwartej
Patryk