Jako entuzjasta inteligentnego domu dość mocno polegam na inteligentnym oświetleniu. Gdy jednak musiałem wyposażyć każdy pokój w kontroler oświetlenia – niekiedy nawet kilka – natrafiłem na problem budżetowy. Komercyjne inteligentne kontrolery są dość drogie. Postanowiłem więc użyć drukarki 3D, dołożyć trochę elektroniki i własnoręcznie zbudować własny kontroler za ułamek tej ceny.
Zaprojektowałem mały macropad ze switchami z klawiatury mechanicznej, płytką ESP32, enkoderem obrotowym do regulacji jasności i kompaktowym wyświetlaczem OLED pokazującym aktualnie aktywną scenę oświetleniową. Enkoder obrotowy ma też wbudowany przycisk – jego naciśnięcie przełącza tryb przyciemniania wyświetlacza, umożliwiając regulację jasności OLED, a kolejne kliknięcie przywraca normalne sterowanie oświetleniem.
Aby nie była to tylko kolejna nudna plastikowa skrzynka, postanowiłem połączyć kilka materiałów Prusament Woodfill, tworząc estetyczne kombinacje kolorystyczne pasujące do drewnianego blatu mojego biurka. Miałem okazję przetestować jeden z egzemplarzy beta Prusa CORE One+ INDX, więc skorzystałem z jego możliwości drukowania wielomateriałowego. Można jednak z łatwością wydrukować ten projekt na drukarce Original Prusa XL, wyposażonej w MMU3, a nawet na standardowej drukarce z jednym narzędziem, bez możliwości drukowania wielomateriałowego. W takim przypadku podczas drukowania trzeba będzie kilka razy ręcznie wymienić filamenty, ale jest to całkowicie wykonalne – choć należy liczyć się z większą ilością odpadów. Dzięki zastosowaniu INDX udało mi się niemal całkowicie wyeliminować odpady filamentu – to świetny bonus dla projektu, ponieważ zaoszczędziłem materiał, który mogę teraz wykorzystać do wydrukowania dodatkowych makropadów lub innych przedmiotów.
Hardware
Żeby projekt był jak najbardziej przystępny, wszystkie części elektroniczne można zdobyć za kilkadziesiąt złotych. Możesz oczywiście pominąć wyświetlacz oraz enkoder i ograniczyć się tylko do przełączników, albo nawet zmniejszyć liczbę klawiszy.
Jako „mózg” makropada można wykorzystać niemal każdą płytkę rozwojową z układem ESP32 lub podobnym, wyposażoną w wystarczającą liczbę wejść i obsługującą Wi-Fi. Doskonałym wyborem są wysokiej jakości płytki takich marek jak Adafruit (np. kompaktowa QT Py ESP32-S3 lub klasyczna Feather ESP32-S3) lub SparkFun (Thing Plus ESP32-S3). W moim przypadku, zanim poszedłem na zakupy online, zagłębiłem się w moją niekończącą się szufladę z częściami zamiennymi i znalazłem podobną płytkę, Xiao ESP32-C3 od Seeed Studio, więc postanowiłem pozostać przy niej w tym projekcie.
Jeśli chodzi o klawisze, zdecydowałem się na niebieskie switche mechaniczne. Być może to dość niszowy wybór i zwykłe klawisze sprawdziłyby się równie dobrze, ale przełączniki mechaniczne po prostu mi odpowiadają ze względu na to satysfakcjonujące uczucie kliknięcia i dźwięk.
Oto krótkie zestawienie tego, co będzie Ci potrzebne do wykonania wersji opisanej w tym artykule:
| Komponent | Orientacyjna cena |
| ESP32 | $8.00 |
| Wyświetlacz OLED 0.91″ | $4 |
| Enkoder obrotowy KY-040 | $1.30 |
| Switche do klawiatury mechanicznej (x6) | $3.50 |
| Filament | ~$3.00 |
| Całkowity koszt sprzętu | ~$19.80 |
Druk 3D i personalizacja projektu
Czas przygotować modele 3D do druku. Możesz zaprojektować je samodzielnie w oprogramowaniu do modelowania 3D, takim jak Autodesk Fusion, lub pobrać gotowe pliki tego projektu z Printables.
Zaimportuj pliki do PrusaSlicera. Dla czystego, eleganckiego wyglądu możesz wydrukować obudowę z jasnego Prusament Woodfill Linden Light. Ponieważ jednak wyobraźnia nie zna granic, możesz też przygotować wersje w żywych kolorach – idealne do pokoju dziecięcego, na przykład w stylu Avengers. Następnie dodaj modyfikatory SVG z prostymi symbolami do klawiszy i gałki enkodera, klikając prawym przyciskiem model w PrusaSlicerze i wybierając Dodaj modyfikator → SVG. Jeśli potrzebujesz bardziej szczegółowego przewodnika na temat modyfikatorów SVG, zajrzyj do naszego artykułu o akcesoriach do sensorycznej zabawy. Ciemniejszy Prusament Chocolate Brown Woodfill na przyciski i jasny Linden Light na symbole tworzą bardzo ładny kontrast. Dzięki wykorzystaniu wielu materiałów w jednym wydruku na drukarce takiej, jak CORE One+ z INDX lub Original Prusa XL, efekt jest niezwykle precyzyjny – zero zanieczyszczenia koloru i absolutne minimum odpadów. Klawisze najlepiej drukować stroną z symbolem skierowaną w dół, na płycie stołu. Na ilustracji poniżej są odwrócone stroną z symbolem do góry tylko po to, żeby pokazać wzory SVG. Gdy wszystkie elementy zostaną wydrukowane, nadchodzi czas na montaż.
Montaż i okablowanie
Najpierw zamontuj switche do klawiatury, po prostu wsuwając je przez otwory w obudowie, aż zaskoczą na swoje miejsce. Następnie zamontuj wyświetlacz, enkoder obrotowy i moduł ESP32, wkładając jego złącze USB-C do przygotowanego otworu z boku obudowy tak, aby było skierowane na zewnątrz. Podczas gdy wyświetlacz i enkoder same w sobie trzymają się dość mocno, zamocowanie modułu ESP32 wymaga nieco większej ostrożności. Użyłem prostej, wydrukowanej podkładki dystansowej, którą wystarczy wsunąć między ściankę obudowy a płytkę, aby ją zaklinować, blokując moduł na miejscu podczas podłączania przewodu USB-C.
Układ zajmuje łącznie jedenaście pinów: sześć przełączników, enkoder (2 piny na obrót i 1 na przycisk) i wyświetlacz I2C (2 piny danych/zegarowy). To dokładnie tyle, ile wejść cyfrowych ma moja płytka ESP32. Poniżej schemat okablowania wykonany w Wokwi – świetnym, darmowym symulatorze działającym w przeglądarce. Wokwi ma też wbudowany symulator, dzięki czemu możesz podłączyć wszystkie komponenty i napisać kod testowy, żeby sprawdzić poprawność okablowania przed złożeniem fizycznego urządzenia.

Uważaj, patrząc na płytkę: fizyczne oznaczenia wydrukowane na PCB (D0-D10) różnią się od wewnętrznych rejestrów (GPIO) używanych w kodzie. Oto mapowanie pinów:
5V / 5V0 – VCC (wspólna linia zasilająca dla wyświetlacza OLED i enkodera obrotowego)
GND – GND (wspólny minus dla wszystkich elementów i klawiszy mechanicznych)
D0 (Wewnętrzne GPIO 2) – Klawisz 1
D1 (Wewnętrzne GPIO 3) – Klawisz 2
D2 (Wewnętrzne GPIO 4) – Klawisz 3
D3 (Wewnętrzne GPIO 5) – Klawisz 4
D4 (Wewnętrzne GPIO 6) – OLED SDA (linia danych)
D5 (Wewnętrzne GPIO 7) – OLED SCL (linia zegara)
D6 (Wewnętrzne GPIO 21) – CLK enkodera (pin obrotowy A)
D7 (Wewnętrzne GPIO 20) – DT enkodera (pin obrotowy B)
D8 (Wewnętrzne GPIO 8) – Przełącznik enkodera (wbudowany przycisk enkodera)
D9 (Wewnętrzne GPIO 9) – Przycisk 5
D10 (Wewnętrzne GPIO 10) – Klawisz 6
Przy wstępnych testach możesz podłączyć wszystko złączami Dupont, jak ja. Jednak przestrzeni w obudowie jest dość mało, a te złącza nie są wystarczająco pewne do codziennego użytku. Żeby zapewnić stuprocentową niezawodność i wygodne rozmieszczenie komponentów, gorąco polecam wszystko przylutować.
Konfiguracja oprogramowania (ESPHome)
Skoro wszystko jest podłączone, czas na (vibe)coding 😎! Podłączenie ESP32 do komputera PC lub Mac to łatwizna. Wystarczy podłączyć go przez USB-C, pobrać niezbędne narzędzia i wgrać kod do płytki przez terminal. Na Macu możesz użyć Pythona i jego pakietu ESPHome, instalowanego przez menedżer pakietów pip poleceniem pip3 install esphome.
Po zakończeniu instalacji utwórz dwa pliki YAML: keyboard.yaml i secrets.yaml. Plik keyboard.yaml zawiera cały kod dla ESP32, a secrets.yaml bezpiecznie przechowuje dane logowania do Wi-Fi. Będziesz też potrzebować pliku z czcionką. W tym projekcie użyłem czcionki Nunito z biblioteki Google Fonts. Znajdziesz ją tutaj: https://fonts.google.com/specimen/Nunito. Pobierz i wypakuj plik, umieść wersję o regularnym kroju (Nunito-Regular.ttf) w tym samym folderze co pozostałe pliki i zmień jej nazwę na font.ttf.
Uwaga: ten kod jest przygotowany specjalnie dla Seeed Studio XIAO ESP32-C3. Jeśli używasz innej płytki ESP32, musisz dostosować parametr board: oraz mapowanie pinów GPIO do swojego sprzętu. Jeśli nie wiesz, jak to zrobić, nie wahaj się poprosić swojego ulubionego asystenta AI o pomoc! 🙂
Poniżej kompletny plik keyboard.yaml. Niech nie zrażą Cię długie sekcje oznaczona jako lambda:. Obsługują one logikę działającą w tle – na przykład przeliczają surowe dane jasności na czytelne wartości procentowe (%) i formatują tekst wyświetlany na ekranie OLED.
esphome:
name: keyboard
on_boot:
priority: -100
then:
- sensor.rotary_encoder.set_value:
id: rotary_knob
value: 10
- sensor.template.publish:
id: ha_knob
state: 10
- binary_sensor.template.publish:
id: ha_service_mode
state: false
esp32:
board: seeed_xiao_esp32c3
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
captive_portal:
api:
on_client_connected:
- lambda: |-
id(ha_service_mode).publish_state(id(service_mode));
id(ha_active_key_sensor).publish_state(id(active_text));
services:
- service: set_display_text
variables:
new_text: string
then:
- lambda: |-
id(active_text) = new_text;
id(ha_active_key_sensor).publish_state(new_text);
id(oled_display).update();
logger:
baud_rate: 115200
i2c:
sda: 6
scl: 7
globals:
- id: active_text
type: std::string
initial_value: '"OFF"'
- id: service_mode
type: bool
initial_value: 'false'
- id: saved_light_steps
type: int
initial_value: '10'
- id: display_steps
type: int
initial_value: '10'
script:
- id: block_feedback_script
mode: restart
then:
- delay: 800ms
font:
- file: "font.ttf"
id: font_large
size: 14
- file: "font.ttf"
id: font_sub
size: 10
text_sensor:
- platform: template
name: "Active Key"
id: ha_active_key_sensor
sensor:
- platform: template
name: "Rotary Knob"
id: ha_knob
- platform: rotary_encoder
id: rotary_knob
pin_a: 21
pin_b: 20
min_value: 0
max_value: 10
resolution: 2
on_value:
then:
- lambda: |-
if (isnan(x)) return;
if (id(service_mode)) {
if (x == 0) id(rotary_knob).set_value(1);
id(oled_display).set_contrast(id(rotary_knob).state / 10.0);
} else {
if (x == 0 and id(ha_light_state).state) id(rotary_knob).set_value(1);
id(block_feedback_script).execute();
id(ha_knob).publish_state(id(rotary_knob).state);
}
- component.update: oled_display
- platform: homeassistant
id: ha_light_brightness
entity_id: light.office
attribute: brightness
on_value:
then:
- lambda: |-
if (not id(service_mode) and not id(block_feedback_script).is_running() and not isnan(x)) {
int steps = round((x / 255.0) * 10.0);
id(rotary_knob).set_value(steps);
id(ha_knob).publish_state(steps);
}
- component.update: oled_display
binary_sensor:
- platform: template
name: "Service Mode"
id: ha_service_mode
- platform: status
id: ha_connection_status
- platform: homeassistant
id: ha_light_state
entity_id: light.office
filters:
- delayed_off: 500ms
on_state:
then:
- lambda: |-
if (not x) {
if (not id(service_mode)) {
id(rotary_knob).set_value(0);
id(ha_knob).publish_state(0);
} else {
id(saved_light_steps) = 0;
}
id(active_text) = "OFF";
id(ha_active_key_sensor).publish_state("OFF");
id(oled_display).update();
}
- platform: gpio
name: "Encoder Press"
pin: {number: 8, mode: INPUT_PULLUP, inverted: true}
on_press:
then:
- lambda: |-
float current_state = isnan(id(rotary_knob).state) ? 10.0 : id(rotary_knob).state;
if (not id(service_mode)) {
id(saved_light_steps) = (int)current_state;
id(service_mode) = true;
id(rotary_knob).set_value(id(display_steps));
id(ha_service_mode).publish_state(true);
} else {
id(display_steps) = (int)current_state;
id(service_mode) = false;
id(rotary_knob).set_value(id(saved_light_steps));
id(ha_knob).publish_state(id(saved_light_steps));
id(ha_service_mode).publish_state(false);
}
- component.update: oled_display
- platform: gpio
name: "Key 1"
pin: {number: 2, mode: INPUT_PULLUP, inverted: true}
- platform: gpio
name: "Key 2"
pin: {number: 3, mode: INPUT_PULLUP, inverted: true}
- platform: gpio
name: "Key 3"
pin: {number: 4, mode: INPUT_PULLUP, inverted: true}
- platform: gpio
name: "Key 4"
pin: {number: 5, mode: INPUT_PULLUP, inverted: true}
- platform: gpio
name: "Key 5"
pin: {number: 9, mode: INPUT_PULLUP, inverted: true}
- platform: gpio
name: "Key 6"
pin: {number: 10, mode: INPUT_PULLUP, inverted: true}
display:
- platform: ssd1306_i2c
id: oled_display
model: "SSD1306 128x32"
address: 0x3C
rotation: 180
lambda: |-
if (id(service_mode)) {
it.print(0, 0, id(font_large), "DISPLAY");
} else {
it.print(0, 0, id(font_large), id(active_text).c_str());
}
if (id(ha_connection_status).state) {
it.print(82, 0, id(font_sub), "HA: OK");
} else {
it.print(82, 0, id(font_sub), "HA: --");
}
it.printf(0, 19, id(font_sub), "Int: %.0f%%", isnan(id(rotary_knob).state) ? 0.0 : id(rotary_knob).state * 10.0);
if (wifi::global_wifi_component->is_connected()) {
it.print(75, 19, id(font_sub), "Wi-Fi: OK");
} else {
it.print(75, 19, id(font_sub), "Wi-Fi: --");
}
Hasło do Wi-Fi znajduje się w osobnym pliku secrets.yaml. Utwórz go i uzupełnij własnymi danymi:
wifi_ssid: "moja_sieć_wi-fi"
wifi_password: "niemożliwe_do_złamania_hasło"
Teraz możesz skompilować i wgrać kod do ESP32 poleceniem python3 -m esphome run keyboard.yaml. Pamiętaj, że polecenie należy uruchomić z poziomu folderu, w którym znajduje się plik YAML. Gdy terminal wyświetli zapytanie, wpisz numer odpowiadający podłączonemu portowi USB i naciśnij Enter. Jeśli wgrywanie przebiegło pomyślnie, w terminalu powinien pojawić się log komunikacji między komputerem a ESP32, a wyświetlacz powinien się włączyć.
Wyświetlacz pokazuje m.in. status połączenia Wi-Fi, który po kilku sekundach powinien wyświetlić „OK”. Zobaczysz też linię „HA” oznaczającą status połączenia z Home Assistant. Na razie nie musisz się tym przejmować – gdy skonfigurujemy wszystko w HA, powinna też pokazywać OK. Jeśli widzisz logi, a wyświetlacz pokazuje informacje, ESP32 został pomyślnie zaprogramowany i możesz przejść do konfiguracji Home Assistant. Możesz pozostawić moduł ESP32 podłączony do portu USB w komputerze lub użyć dowolnej standardowej ładowarki USB 5 V do zasilania macropadu.
Konfiguracja Home Assistant
1. Dodawanie ESP32 do Home Assistant
Dzięki natywnej integracji ESPHome Home Assistant powinien automatycznie rozpoznać nowy macropad.
- Przejdź do
Settings → Devices & Servicesw panelu Home Assistant. - Spójrz na górę zakładki Integrations. Powinno pojawić się nowo wykryte urządzenie ESPHome o nazwie
keyboard. - Kliknij Configure i postępuj zgodnie z instrukcjami na ekranie, żeby dodać urządzenie.
- Uwaga: Jeśli nie pojawia się automatycznie, kliknij Add Integration w prawym dolnym rogu, wyszukaj ESPHome i wprowadź lokalny adres IP ESP32.
Po dodaniu Home Assistant automatycznie wczytuje wszystkie klawisze, enkoder i przełącznik trybu serwisowego.
2. Tworzenie pomocniczej grupy oświetlenia
Żeby projekt był schludny i uniwersalny, unikamy na sztywno wpisywania konkretnych żarówek bezpośrednio do kodu. Zamiast tego utwórz pomocnik Light Group. Dzięki temu, gdy wymienisz żarówki, wystarczy zaktualizować tę grupę – automatyzacja pozostaje bez zmian.
- Przejdź do Settings → Devices & Services i kliknij zakładkę Helpers na górze.
- Kliknij + Create Helper w prawym dolnym rogu.
- Przewiń w dół, wybierz Group, a następnie
Light Group.- Nazwij pomocnika Office (automatycznie zostanie wygenerowany wymagany identyfikator encji:
light.office).- W sekcji Members wybierz swoje inteligentne żarówki, którymi ma sterować macropad.
- Kliknij Submit / Create.
Po podłączeniu macropada i skonfigurowaniu grupy świateł możemy połączyć wszystko za pomocą głównego skryptu automatyzacji.
- Przejdź do Settings → Automations & Scenes i kliknij Create Automation.
- Wybierz Create new automation, następnie kliknij trzy kropki w prawym górnym rogu i wybierz Edit in YAML
- Wyczyść domyślny kod, wklej poniższy skrypt i kliknij Save
W tym przewodniku przypisałem sześciu klawiszom aktywację prostych scen kolorystycznych (niebieski, zielony, czerwony itp.), ale możesz je dostosować do wyzwalania dowolnej sceny – prostej lub zaawansowanej.
alias: Light Office - Master Control
description: Master Control for Macropad
triggers:
- entity_id: binary_sensor.keyboard_key_1
to: "on"
id: press_k1
trigger: state
- entity_id: binary_sensor.keyboard_key_2
to: "on"
id: press_k2
trigger: state
- entity_id: binary_sensor.keyboard_key_3
to: "on"
id: press_k3
trigger: state
- entity_id: binary_sensor.keyboard_key_4
to: "on"
id: press_k4
trigger: state
- entity_id: binary_sensor.keyboard_key_5
to: "on"
id: press_k5
trigger: state
- entity_id: binary_sensor.keyboard_key_6
to: "on"
id: press_k6
trigger: state
- entity_id: sensor.keyboard_rotary_knob
id: knob_rotation
trigger: state
conditions:
- condition: state
entity_id: binary_sensor.keyboard_service_mode
state: "off"
actions:
- choose:
- conditions:
- condition: trigger
id: knob_rotation
sequence:
- action: light.turn_on
metadata: {}
target:
entity_id: light.office
data:
brightness_pct: "{{ (trigger.to_state.state | int(10)) * 10 }}"
- conditions:
- condition: trigger
id: press_k1
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: Blue
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 4
- 51
- 255
- action: esphome.keyboard_set_display_text
data:
new_text: Blue
- conditions:
- condition: trigger
id: press_k2
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: Green
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 0
- 249
- 0
- action: esphome.keyboard_set_display_text
data:
new_text: Green
- conditions:
- condition: trigger
id: press_k3
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: Red
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 255
- 0
- 0
- action: esphome.keyboard_set_display_text
data:
new_text: Red
- conditions:
- condition: trigger
id: press_k4
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: Yellow
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 255
- 255
- 0
- action: esphome.keyboard_set_display_text
data:
new_text: Yellow
- conditions:
- condition: trigger
id: press_k5
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: Purple
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 255
- 0
- 255
- action: esphome.keyboard_set_display_text
data:
new_text: Purple
- conditions:
- condition: trigger
id: press_k6
sequence:
- choose:
- conditions:
- condition: state
entity_id: sensor.keyboard_active_key
state: White
sequence:
- action: light.turn_off
target:
entity_id: light.office
default:
- action: light.turn_on
target:
entity_id: light.office
data:
brightness_pct: 100
rgb_color:
- 255
- 255
- 255
- action: esphome.keyboard_set_display_text
data:
new_text: White
mode: restart
Edytor YAML w Home Assistant wygląda tak:
Testy i podsumowanie
Gdy wszystko jest wgrane, czas przetestować macropad. Naciśnij klawisz – scena oświetleniowa powinna natychmiast się zmienić. Obróć enkoder – intensywność światła powinna się zmienić. Wyświetlacz OLED powinien też poprawnie pokazywać aktualnie wybraną scenę.
Gdy wszystko działa, wystarczy wydrukować dolną pokrywę i zamknąć obudowę. Dzięki mocowaniu na wcisk trzyma się pewnie bez kleju ani śrub. Ponieważ w wersji testowej zostawiłem grube złącza Dupont, potrzebowałem nieco więcej miejsca w środku – dlatego zrobiłem nieco wyższą dolną część. Przy okazji wykorzystałem to, łącząc różne materiały Prusament Woodfill, żeby stworzyć ładny pasek przejściowy. Jeśli zdecydujesz się przylutować komponenty, możesz zmniejszyć dolną pokrywę, co znacząco obniży wysokość macropada.
Choć sam używam tego macropada tylko do sterowania oświetleniem, możesz go przypisać do dowolnej funkcji inteligentnego domu. Skoro logikę obsługuje Home Assistant, naciśnięcie klawisza lub obrót enkodera może sterować roletami, uruchamiać odkurzacz automatyczny, albo wywołać automatyzację Spotify i zrobić Rickrolla gościom. Granicą jest tylko wyobraźnia! Gdy zbudujesz swój pierwszy taki projekt, trudno nie rozglądać się po domu w poszukiwaniu kolejnych miejsc, gdzie drukarka 3D i elektronika mogą się sprwadzić.
Pamiętaj, że praca z Home Assistant i ESPHome wiąże się z obsługą wrażliwych danych sieciowych. Choć ta konfiguracja działa w moim środowisku, konieczne może być dostosowanie kodu do własnego układu inteligentnego domu. Konfiguracja jest udostępniana w stanie, w jakim jest, bez żadnych gwarancji. Sprawdź wszystko dokładnie i zawsze używaj funkcji secrets w ESPHome, żeby chronić swoje prywatne dane logowania.
Udanego drukowania!









Musisz się zalogować, aby móc dodać komentarz.