Komunikacja UDP między urządzeniami
Jak połączyć dwa urządzenia boneIO ESP za pomocą komponentu UDP w ESPHome, aby mogły współdzielić stany czujników i synchronizować wejścia — bez serwera czy brokera.
Komunikacja UDP między urządzeniami
Komponent UDP w ESPHome, w połączeniu z Packet Transport, pozwala dwóm (lub więcej) urządzeniom boneIO ESP na bezpośrednią komunikację w sieci lokalnej. Jest to przydatne, gdy chcesz, aby jedno urządzenie reagowało na wejście lub stan czujnika z innego urządzenia — bez pośrednictwa Home Assistant ani żadnego innego brokera.
Typowe zastosowania:
- Przycisk na Dimmerze A steruje światłem na Dimmerze B
- Czujnik temperatury z jednego urządzenia jest wyświetlany lub wykorzystywany na drugim
- Synchronizacja stanów czujników binarnych między urządzeniami
Jak to działa
- Provider (dostawca) — urządzenie, które rozgłasza stany swoich czujników/czujników binarnych przez UDP.
- Consumer (odbiorca) — urządzenie, które odbiera te stany i może na nie reagować.
Jedno urządzenie może być jednocześnie providerem i consumerem.
Dane są wysyłane przez broadcast UDP w sieci lokalnej (domyślny port 18511). W podstawowej konfiguracji nie trzeba podawać adresów IP — wszystkie urządzenia w tej samej podsieci odbiorą broadcast.
Wymagania
- Dwa (lub więcej) urządzenia boneIO ESP w tej samej sieci.
- ESPHome 2025.6.0 lub nowszy (obsługa UDP + Packet Transport).
- Dostęp do dashboardu ESPHome w celu edycji konfiguracji YAML.
Przykład: Dwa boneIO Dimmer Gen2
W tym scenariuszu mamy dwa urządzenia boneIO Dimmer Gen2. Chcemy, aby Wejście 1 na Dimmerze A przełączało Światło CHL 01 na Dimmerze B i odwrotnie.
Schemat sieci
┌──────────────────┐ broadcast UDP ┌──────────────────┐
│ Dimmer A │ ◄──────────────────────────► │ Dimmer B │
│ │ (port 18511) │ │
│ IN_01 ──► toggle│ │ IN_01 ──► toggle│
│ światło na B │ │ światło na A │
│ │ │ │
│ CHL 01 (światło)│ │ CHL 01 (światło)│
└──────────────────┘ └──────────────────┘Konfiguracja Dimmera A
Dodaj poniższe sekcje do konfiguracji YAML Dimmera A. Kluczowe elementy to udp, packet_transport oraz binary_sensor z platform: packet_transport.
substitutions:
name: boneio-dimmer-a
friendly_name: "BoneIO Dimmer A"
# ... (standardowe sekcje esphome, esp32, ethernet, i2c, output, light)
# ──────────────────────────────────────────────
# Transport UDP — rozgłaszanie i odbieranie w LAN
# ──────────────────────────────────────────────
udp:
# ──────────────────────────────────────────────
# Packet Transport — co wysyłać i od kogo odbierać
# ──────────────────────────────────────────────
packet_transport:
platform: udp
update_interval: 5s
# Rozgłaszaj te czujniki binarne do innych urządzeń
binary_sensors:
- in_01_state_dimmer_a
# Zadeklaruj providerów, od których chcemy odbierać dane
providers:
- name: boneio-dimmer-b # musi odpowiadać wartości 'name' w ESPHome Dimmera B
# ──────────────────────────────────────────────
# Template binary sensor — odzwierciedla stan IN_01 do rozgłaszania
# ──────────────────────────────────────────────
binary_sensor:
# Fizyczne wejście
- platform: gpio
name: "IN_01"
id: in_01
pin:
pcf8574: pcf_inputs
number: 0
mode:
input: true
inverted: true
on_press:
then:
- light.toggle: chl_01
# Template sensor odzwierciedlający IN_01 — jest rozgłaszany przez UDP
- platform: template
id: in_01_state_dimmer_a
lambda: "return id(in_01).state;"
# Odbiór stanu IN_01 z Dimmera B — przełącz lokalne światło
- platform: packet_transport
provider: boneio-dimmer-b
id: in_01_state_dimmer_b # musi odpowiadać broadcast id na Dimmerze B
on_press:
then:
- light.toggle: chl_01Konfiguracja Dimmera B
Konfiguracja jest symetryczna — Dimmer B rozgłasza swój in_01_state_dimmer_b i nasłuchuje na in_01_state_dimmer_a z Dimmera A.
substitutions:
name: boneio-dimmer-b
friendly_name: "BoneIO Dimmer B"
# ... (standardowe sekcje esphome, esp32, ethernet, i2c, output, light)
# ──────────────────────────────────────────────
# Transport UDP
# ──────────────────────────────────────────────
udp:
# ──────────────────────────────────────────────
# Packet Transport
# ──────────────────────────────────────────────
packet_transport:
platform: udp
update_interval: 5s
binary_sensors:
- in_01_state_dimmer_b
providers:
- name: boneio-dimmer-a # musi odpowiadać wartości 'name' w ESPHome Dimmera A
# ──────────────────────────────────────────────
# Czujniki binarne
# ──────────────────────────────────────────────
binary_sensor:
# Fizyczne wejście
- platform: gpio
name: "IN_01"
id: in_01
pin:
pcf8574: pcf_inputs
number: 0
mode:
input: true
inverted: true
on_press:
then:
- light.toggle: chl_01
# Template sensor — rozgłaszany przez UDP
- platform: template
id: in_01_state_dimmer_b
lambda: "return id(in_01).state;"
# Odbiór z Dimmera A
- platform: packet_transport
provider: boneio-dimmer-a
id: in_01_state_dimmer_a # musi odpowiadać broadcast id na Dimmerze A
on_press:
then:
- light.toggle: chl_01Multi-Click przez UDP
Gdy używasz on_multi_click z UDP, zawsze przetwarzaj timing na urządzeniu źródłowym (Dimmer A). Urządzenie źródłowe wykrywa wzorzec kliknięcia lokalnie i pulsuje template binary sensor dla każdego typu zdarzenia. Urządzenie zdalne (Dimmer B) odbiera te impulsy przez packet_transport i steruje swoimi światłami.
Dlaczego nie wysyłać surowego stanu przycisku? Wykrywanie multi-click opiera się na precyzyjnym timingu. Wysyłanie surowych zdarzeń press/release przez UDP wprowadziłoby jitter sieciowy i niestabilne wykrywanie po stronie odbiorcy. Rozwiązując wzorzec kliknięcia lokalnie, Dimmer B dostaje czysty, natychmiastowy sygnał.
Dimmer A — wykrywa multi-click, rozgłasza wyniki
udp:
packet_transport:
platform: udp
update_interval: 5s
binary_sensors:
- single_click_dimmer_a_in_01
- double_click_dimmer_a_in_01
- long_press_dimmer_a_in_01
providers:
- name: boneio-dimmer-b
light:
- platform: monochromatic
output: chl01
name: "CHL 01"
id: chl_01
default_transition_length: 2s
gamma_correct: 0
- platform: monochromatic
output: chl02
name: "CHL 02"
id: chl_02
default_transition_length: 2s
gamma_correct: 0
- platform: monochromatic
output: chl03
name: "CHL 03"
id: chl_03
default_transition_length: 2s
gamma_correct: 0
binary_sensor:
# Fizyczne wejście z detekcją multi-click
- platform: gpio
name: "IN_01"
id: in_01
pin:
pcf8574: pcf_inputs
number: 0
mode:
input: true
inverted: true
on_multi_click:
# Długie naciśnięcie
- timing:
- ON for at least 1.4s
then:
- logger.log: "Wykryto długie naciśnięcie"
- light.toggle: chl_01
- binary_sensor.template.publish:
id: long_press_dimmer_a_in_01
state: ON
- delay: 200ms
- binary_sensor.template.publish:
id: long_press_dimmer_a_in_01
state: OFF
# Podwójne kliknięcie
- timing:
- ON for at most 1s
- OFF for at most 0.5s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "Wykryto podwójne kliknięcie"
- light.toggle: chl_02
- binary_sensor.template.publish:
id: double_click_dimmer_a_in_01
state: ON
- delay: 200ms
- binary_sensor.template.publish:
id: double_click_dimmer_a_in_01
state: OFF
# Pojedyncze kliknięcie
- timing:
- ON for at most 1s
- OFF for at least 0.5s
then:
- logger.log: "Wykryto pojedyncze kliknięcie"
- light.toggle: chl_03
- binary_sensor.template.publish:
id: single_click_dimmer_a_in_01
state: ON
- delay: 200ms
- binary_sensor.template.publish:
id: single_click_dimmer_a_in_01
state: OFF
# Template binary sensory — puls ON/OFF rozgłaszany przez UDP
- platform: template
id: single_click_dimmer_a_in_01
- platform: template
id: double_click_dimmer_a_in_01
- platform: template
id: long_press_dimmer_a_in_01Dimmer B — odbiera zdarzenia multi-click, steruje światłami
udp:
packet_transport:
platform: udp
providers:
- name: boneio-dimmer-a
light:
- platform: monochromatic
output: chl01
name: "CHL 01"
id: chl_01
default_transition_length: 2s
gamma_correct: 0
- platform: monochromatic
output: chl02
name: "CHL 02"
id: chl_02
default_transition_length: 2s
gamma_correct: 0
- platform: monochromatic
output: chl03
name: "CHL 03"
id: chl_03
default_transition_length: 2s
gamma_correct: 0
binary_sensor:
# Odbiór zdarzeń kliknięć z Dimmera A
- platform: packet_transport
provider: boneio-dimmer-a
id: long_press_dimmer_a_in_01
on_press:
then:
- light.toggle: chl_01
- platform: packet_transport
provider: boneio-dimmer-a
id: double_click_dimmer_a_in_01
on_press:
then:
- light.toggle: chl_02
- platform: packet_transport
provider: boneio-dimmer-a
id: single_click_dimmer_a_in_01
on_press:
then:
- light.toggle: chl_03Jak to działa: Dimmer A wykrywa wzorzec kliknięcia i krótko pulsuje (ON → 200ms → OFF) odpowiedni template binary sensor.
packet_transportrozgłasza zmianę stanu. Dimmer B odbiera ją i używaon_pressdo przełączenia odpowiedniego światła.
Przykład: Input24 Gen2 → 32x10 Lights
Częsta konfiguracja — boneIO Input24 Gen2 ma 24 wejścia, ale nie ma wyjść świetlnych, natomiast boneIO 32x10 Lights ma 32 wyjścia przekaźnikowe, ale może nie mieć wystarczającej liczby lokalnych wejść. Dzięki UDP możesz nacisnąć przycisk na Input24 i przełączyć światło na 32x10.
Schemat sieci
┌──────────────────┐ broadcast UDP ┌──────────────────┐
│ Input24 Gen2 │ ─────────────────────────► │ 32x10 Lights │
│ (ESP32-S3) │ (port 18511) │ (ESP32) │
│ │ │ │
│ IN_01 ──► wysyła│ │ odbiera ──► │
│ stan przez UDP │ │ light.toggle │
│ │ │ Light 01 │
└──────────────────┘ └──────────────────┘Input24 Gen2 — pełna konfiguracja (rozgłasza wszystkie 24 wejścia)
substitutions:
name: boneio-input24-gen2-01
friendly_name: "boneIO ESP Input24 Gen2"
serial_prefix: "esp24"
firmware_manifest: "https://boneio.eu/fwesp/boneio-input24-gen2-01.json"
esphome:
name: "${name}"
friendly_name: "${friendly_name}"
name_add_mac_suffix: true
project:
name: boneio.input24-gen2
version: "0.1"
esp32:
board: esp32-s3-devkitc-1
framework:
type: esp-idf
ethernet:
id: eth
type: W5500
clk_pin: GPIO13
mosi_pin: GPIO39
miso_pin: GPIO38
cs_pin: GPIO12
interrupt_pin: GPIO2
reset_pin: GPIO1
clock_speed: 25MHz
i2c:
sda: GPIO10
scl: GPIO11
scan: true
frequency: 400kHz
uart:
id: boneio_uart
rx_pin: GPIO21
tx_pin: GPIO14
baud_rate: 9600
stop_bits: 1
modbus:
send_wait_time: 80ms
uart_id: boneio_uart
id: boneio_modbus
packages:
internals_packages:
url: https://github.com/boneIO-eu/esphome
ref: packages-v2.0.0
files: ["packages/devices/serial_no.yaml"]
dashboard_import:
package_import_url: github://boneIO-eu/esphome/boneio-input24_gen2-v0_1.yaml@latest
import_full_config: true
pcf8574:
- id: pcf_inputs_1_to_8
address: 0x38
- id: pcf_inputs_9_to_24
address: 0x20
pcf8575: true
logger:
hardware_uart: UART0
api:
reboot_timeout: 0s
ota:
- platform: esphome
- platform: web_server
web_server:
port: 80
version: 3
local: true
sensor:
- platform: lm75b
id: boneIO_temp
name: "Temperature"
update_interval: 30s
entity_category: diagnostic
on_value_range:
- above: 70.0
then:
- switch.turn_on: buzzer
- below: 70.0
then:
- switch.turn_off: buzzer
switch:
- platform: gpio
id: buzzer
name: "Buzzer"
pin:
number: GPIO9
mode:
output: true
inverted: false
# ──────────────────────────────────────────────
# UDP + Packet Transport — rozgłaszanie wszystkich 24 wejść
# ──────────────────────────────────────────────
udp:
packet_transport:
platform: udp
update_interval: 5s
binary_sensors:
- in_01_state_input24
- in_02_state_input24
- in_03_state_input24
- in_04_state_input24
- in_05_state_input24
- in_06_state_input24
- in_07_state_input24
- in_08_state_input24
- in_09_state_input24
- in_10_state_input24
- in_11_state_input24
- in_12_state_input24
- in_13_state_input24
- in_14_state_input24
- in_15_state_input24
- in_16_state_input24
- in_17_state_input24
- in_18_state_input24
- in_19_state_input24
- in_20_state_input24
- in_21_state_input24
- in_22_state_input24
- in_23_state_input24
- in_24_state_input24
# ──────────────────────────────────────────────
# Wejścia fizyczne (IN_01 do IN_08 — pcf_inputs_1_to_8)
# ──────────────────────────────────────────────
binary_sensor:
- platform: gpio
name: "IN_01"
id: in_01
pin:
pcf8574: pcf_inputs_1_to_8
number: 0
mode:
input: true
inverted: true
- platform: gpio
name: "IN_02"
id: in_02
pin:
pcf8574: pcf_inputs_1_to_8
number: 1
mode:
input: true
inverted: true
- platform: gpio
name: "IN_03"
id: in_03
pin:
pcf8574: pcf_inputs_1_to_8
number: 2
mode:
input: true
inverted: true
- platform: gpio
name: "IN_04"
id: in_04
pin:
pcf8574: pcf_inputs_1_to_8
number: 3
mode:
input: true
inverted: true
- platform: gpio
name: "IN_05"
id: in_05
pin:
pcf8574: pcf_inputs_1_to_8
number: 4
mode:
input: true
inverted: true
- platform: gpio
name: "IN_06"
id: in_06
pin:
pcf8574: pcf_inputs_1_to_8
number: 5
mode:
input: true
inverted: true
- platform: gpio
name: "IN_07"
id: in_07
pin:
pcf8574: pcf_inputs_1_to_8
number: 6
mode:
input: true
inverted: true
- platform: gpio
name: "IN_08"
id: in_08
pin:
pcf8574: pcf_inputs_1_to_8
number: 7
mode:
input: true
inverted: true
# ──────────────────────────────────────────────
# Wejścia fizyczne (IN_09 do IN_24 — pcf_inputs_9_to_24)
# ──────────────────────────────────────────────
- platform: gpio
name: "IN_09"
id: in_09
pin:
pcf8574: pcf_inputs_9_to_24
number: 7
mode:
input: true
inverted: true
- platform: gpio
name: "IN_10"
id: in_10
pin:
pcf8574: pcf_inputs_9_to_24
number: 6
mode:
input: true
inverted: true
- platform: gpio
name: "IN_11"
id: in_11
pin:
pcf8574: pcf_inputs_9_to_24
number: 5
mode:
input: true
inverted: true
- platform: gpio
name: "IN_12"
id: in_12
pin:
pcf8574: pcf_inputs_9_to_24
number: 4
mode:
input: true
inverted: true
- platform: gpio
name: "IN_13"
id: in_13
pin:
pcf8574: pcf_inputs_9_to_24
number: 3
mode:
input: true
inverted: true
- platform: gpio
name: "IN_14"
id: in_14
pin:
pcf8574: pcf_inputs_9_to_24
number: 2
mode:
input: true
inverted: true
- platform: gpio
name: "IN_15"
id: in_15
pin:
pcf8574: pcf_inputs_9_to_24
number: 1
mode:
input: true
inverted: true
- platform: gpio
name: "IN_16"
id: in_16
pin:
pcf8574: pcf_inputs_9_to_24
number: 0
mode:
input: true
inverted: true
- platform: gpio
name: "IN_17"
id: in_17
pin:
pcf8574: pcf_inputs_9_to_24
number: 15
mode:
input: true
inverted: true
- platform: gpio
name: "IN_18"
id: in_18
pin:
pcf8574: pcf_inputs_9_to_24
number: 14
mode:
input: true
inverted: true
- platform: gpio
name: "IN_19"
id: in_19
pin:
pcf8574: pcf_inputs_9_to_24
number: 13
mode:
input: true
inverted: true
- platform: gpio
name: "IN_20"
id: in_20
pin:
pcf8574: pcf_inputs_9_to_24
number: 12
mode:
input: true
inverted: true
- platform: gpio
name: "IN_21"
id: in_21
pin:
pcf8574: pcf_inputs_9_to_24
number: 11
mode:
input: true
inverted: true
- platform: gpio
name: "IN_22"
id: in_22
pin:
pcf8574: pcf_inputs_9_to_24
number: 10
mode:
input: true
inverted: true
- platform: gpio
name: "IN_23"
id: in_23
pin:
pcf8574: pcf_inputs_9_to_24
number: 9
mode:
input: true
inverted: true
- platform: gpio
name: "IN_24"
id: in_24
pin:
pcf8574: pcf_inputs_9_to_24
number: 8
mode:
input: true
inverted: true
# ──────────────────────────────────────────────
# Template sensory — odzwierciedlają każde wejście do rozgłaszania UDP
# ──────────────────────────────────────────────
- platform: template
id: in_01_state_input24
lambda: "return id(in_01).state;"
- platform: template
id: in_02_state_input24
lambda: "return id(in_02).state;"
- platform: template
id: in_03_state_input24
lambda: "return id(in_03).state;"
- platform: template
id: in_04_state_input24
lambda: "return id(in_04).state;"
- platform: template
id: in_05_state_input24
lambda: "return id(in_05).state;"
- platform: template
id: in_06_state_input24
lambda: "return id(in_06).state;"
- platform: template
id: in_07_state_input24
lambda: "return id(in_07).state;"
- platform: template
id: in_08_state_input24
lambda: "return id(in_08).state;"
- platform: template
id: in_09_state_input24
lambda: "return id(in_09).state;"
- platform: template
id: in_10_state_input24
lambda: "return id(in_10).state;"
- platform: template
id: in_11_state_input24
lambda: "return id(in_11).state;"
- platform: template
id: in_12_state_input24
lambda: "return id(in_12).state;"
- platform: template
id: in_13_state_input24
lambda: "return id(in_13).state;"
- platform: template
id: in_14_state_input24
lambda: "return id(in_14).state;"
- platform: template
id: in_15_state_input24
lambda: "return id(in_15).state;"
- platform: template
id: in_16_state_input24
lambda: "return id(in_16).state;"
- platform: template
id: in_17_state_input24
lambda: "return id(in_17).state;"
- platform: template
id: in_18_state_input24
lambda: "return id(in_18).state;"
- platform: template
id: in_19_state_input24
lambda: "return id(in_19).state;"
- platform: template
id: in_20_state_input24
lambda: "return id(in_20).state;"
- platform: template
id: in_21_state_input24
lambda: "return id(in_21).state;"
- platform: template
id: in_22_state_input24
lambda: "return id(in_22).state;"
- platform: template
id: in_23_state_input24
lambda: "return id(in_23).state;"
- platform: template
id: in_24_state_input24
lambda: "return id(in_24).state;"Uwaga: Input24 Gen2 nie ma wyjść świetlnych, więc działa wyłącznie jako provider. Nie potrzebuje sekcji
providers.
32x10 Lights — consumer (odbiera IN_01 z Input24, przełącza Light 01)
Po stronie 32x10 wystarczy dodać sekcje UDP/Packet Transport do istniejącej konfiguracji. Reszta konfiguracji (światła, lokalne wejścia) pozostaje bez zmian.
# ──────────────────────────────────────────────
# UDP + Packet Transport
# ──────────────────────────────────────────────
udp:
packet_transport:
platform: udp
providers:
- name: boneio-input24-gen2-01 # musi odpowiadać wartości 'name' w ESPHome Input24
# Dodaj to do istniejącej sekcji binary_sensor:
binary_sensor:
# ... (zachowaj wszystkie istniejące lokalne wejścia IN_01..IN_32 bez zmian)
# Odbiór IN_01 z Input24 Gen2 — przełącz Light 01
- platform: packet_transport
provider: boneio-input24-gen2-01
id: in_01_state_input24
on_press:
then:
- light.toggle: light_01Skalowanie: Aby reagować na więcej wejść z Input24, dodaj kolejne
packet_transportbinary sensory na 32x10 — np.in_02_state_input24→light.toggle: light_02, itd. Wszystkie 24 wejścia są już rozgłaszane.
Współdzielenie danych z czujników (np. temperatura)
Możesz również współdzielić wartości czujników między urządzeniami. Na przykład rozgłaszanie wbudowanego czujnika temperatury z Dimmera A, aby Dimmer B mógł go wyświetlać:
packet_transport:
platform: udp
update_interval: 30s
sensors:
- boneIO_temp # id czujnika temperatury lm75bpacket_transport:
platform: udp
providers:
- name: boneio-dimmer-a
sensor:
- platform: packet_transport
provider: boneio-dimmer-a
id: boneIO_temp # to samo id co na Dimmerze A
name: "Temperatura Dimmera A"Dodanie szyfrowania
Dla większego bezpieczeństwa możesz zaszyfrować komunikację UDP. Obie strony muszą używać tego samego klucza szyfrowania:
packet_transport:
platform: udp
encryption: "moj-tajny-klucz"
rolling_code_enable: true
# ... reszta konfiguracji
providers:
- name: boneio-dimmer-b
encryption: "moj-tajny-klucz"Wskazówka: Przechowuj klucz szyfrowania w pliku
secrets.yamli odwołuj się do niego przez!secret udp_encryption_key.
Ważne informacje
Packet Transport obsługuje wyłącznie
sensoribinary_sensor! Komponentpacket_transportmoże jedynie rozgłaszać i odbierać encje typusensoribinary_sensor. Nie obsługuje świateł, przełączników, rolet, zdarzeń (event) ani żadnych innych typów encji. Dlatego używamy template binary sensorów jako „nośników sygnału" do przesyłania zdarzeń kliknięć między urządzeniami (patrz przykład Multi-Click powyżej).
- Wymagana ta sama sieć — broadcast UDP działa tylko w obrębie tej samej podsieci. Jeśli urządzenia są w różnych VLAN-ach, musisz podać jawne adresy IP w
udp→addresses. - Brak gwarancji dostarczenia — UDP nie gwarantuje dostarczenia pakietów. Komponent
packet_transportperiodycznie retransmituje dane (kontrolowane przezupdate_interval), aby to zminimalizować. - Nazwy urządzeń mają znaczenie — wartość
provider: namemusi dokładnie odpowiadać wartościesphome: namedrugiego urządzenia. Jeśli provider maname_add_mac_suffix: true, rzeczywista nazwa urządzenia będzie miała dopisany suffix z adresu MAC (np.boneio-input24-gen2-01-a1b2c3). Pełną nazwę znajdziesz w logach ESPHome przy starcie urządzenia lub w nazwie urządzenia w Home Assistant. Użyj tej pełnej nazwy wprovider: name. - Unikalne ID — każde urządzenie powinno rozgłaszać pod unikalnym id (np.
in_01_state_dimmer_a,in_01_state_dimmer_b), aby uniknąć pomyłek. Consumer odwołuje się do zdalnego id dopasowując nazwę providera + id. - Wersja ESPHome — upewnij się, że oba urządzenia korzystają z ESPHome 2025.6.0+ dla pełnej obsługi UDP + Packet Transport.