mirror of
https://github.com/esphome/esphome-docs.git
synced 2024-11-10 10:11:29 +01:00
Document UDP component (#3918)
Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: H. Árkosi Róbert <robreg@zsurob.hu>
This commit is contained in:
parent
f1b0f2e58f
commit
31f188f262
49
components/binary_sensor/udp.rst
Normal file
49
components/binary_sensor/udp.rst
Normal file
@ -0,0 +1,49 @@
|
||||
UDP Binary Sensor
|
||||
=================
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a UDP binary sensor.
|
||||
:image: udp.svg
|
||||
|
||||
The ``udp`` binary sensor platform allows you to receive binary sensor data directly from another ESPHome node.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Example configuration entry
|
||||
binary_sensor:
|
||||
- platform: udp
|
||||
id: switch_status
|
||||
provider: light-switch
|
||||
remote_id: light_switch
|
||||
|
||||
Configuration variables
|
||||
-----------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **provider** (**Required**, string): The name of the provider node.
|
||||
- **remote_id** (*Optional*, :ref:`config-id`): The ID of the original binary sensor in the provider device. If not specified defaults to the ID configured with ``id:``.
|
||||
- **name** (*Optional*, string): The name of the binary sensor.
|
||||
- **internal** (*Optional*, boolean): Whether the sensor should be exposed via API (e.g. to Home Assistant.) Defaults to ``true`` if name is not set, required if name is provided.
|
||||
- All other options from :ref:`Binary Sensor <config-binary_sensor>`.
|
||||
|
||||
At least one of ``id`` and ``remote_id`` must be configured.
|
||||
|
||||
Publishing to Home Assistant
|
||||
----------------------------
|
||||
|
||||
Typically this type of binary sensor would be used for internal automation purposes rather than having it published back to
|
||||
Home Assistant, since it would be a duplicate of the original sensor.
|
||||
|
||||
If it *is* desired to expose the binary sensor to Home Assistant, then the ``internal:`` configuration setting needs to be explicitly
|
||||
set to ``false`` and a name provided.
|
||||
Only the state (i.e. binary value) of the remote sensor is received by the consumer, so any other attributes must be explicitly
|
||||
configured.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
- :doc:`/components/udp`
|
||||
- :doc:`/components/sensor/index`
|
||||
- :ref:`automation`
|
||||
- :apiref:`udp/udp_component.h`
|
||||
- :ghedit:`Edit`
|
49
components/sensor/udp.rst
Normal file
49
components/sensor/udp.rst
Normal file
@ -0,0 +1,49 @@
|
||||
UDP Sensor
|
||||
==========
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a UDP sensor.
|
||||
:image: udp.svg
|
||||
|
||||
The ``udp`` sensor platform allows you to receive numeric sensor data directly from another ESPHome node.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Example configuration entry
|
||||
sensor:
|
||||
- platform: udp
|
||||
id: temperature_id
|
||||
provider: thermometer
|
||||
remote_id: temp_id
|
||||
|
||||
Configuration variables
|
||||
-----------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **provider** (**Required**, string): The name of the provider node.
|
||||
- **remote_id** (*Optional*, :ref:`config-id`): The ID of the original sensor in the provider node. If not specified defaults to the ID configured with ``id:``.
|
||||
- **name** (*Optional*, string): The name of the sensor.
|
||||
- **internal** (*Optional*, boolean): Whether the sensor should be exposed via API (e.g. to Home Assistant.) Defaults to ``true`` if name is not set, required if name is provided.
|
||||
- All other options from :ref:`Sensor <config-sensor>`.
|
||||
|
||||
At least one of ``id`` and ``remote_id`` must be configured.
|
||||
|
||||
Publishing to Home Assistant
|
||||
----------------------------
|
||||
|
||||
Typically this type of sensor would be used for internal automation purposes rather than having it published back to
|
||||
Home Assistant, since it would be a duplicate of the original sensor.
|
||||
|
||||
If it *is* desired to expose the sensor to Home Assistant, then the ``internal:`` configuration setting needs to be explicitly
|
||||
set to ``false`` and a name provided.
|
||||
Only the state (i.e. numeric value) of the remote sensor is received by the consumer, so any other attributes must be explicitly
|
||||
configured.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
- :doc:`/components/udp`
|
||||
- :doc:`/components/binary_sensor/index`
|
||||
- :ref:`automation`
|
||||
- :apiref:`udp/udp_component.h`
|
||||
- :ghedit:`Edit`
|
300
components/udp.rst
Normal file
300
components/udp.rst
Normal file
@ -0,0 +1,300 @@
|
||||
.. _udp:
|
||||
|
||||
UDP Component
|
||||
=============
|
||||
|
||||
.. seo::
|
||||
:description: Instructions for setting up a UDP component on ESPHome
|
||||
:image: udp.svg
|
||||
:keywords: UDP
|
||||
|
||||
The purpose of this component is to allow ESPHome nodes to directly communicate with each over an IP network.
|
||||
It permits the state of sensors and binary sensors to be broadcast via UDP packets
|
||||
to other nodes on the same LAN, or to specific IP addresses (which may be in remote, but reachable networks).
|
||||
|
||||
Nodes may be *providers* which broadcast sensor data, or *consumers* which receive sensor data from one or more
|
||||
providers. A node may be both a provider and a consumer. Optional security is provided by one or more of:
|
||||
|
||||
- encryption using a shared secret key
|
||||
- a rolling code
|
||||
- a challenge-response (ping-pong) key
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Example configuration entry
|
||||
udp:
|
||||
update_interval: 5s
|
||||
encryption: "REPLACEME"
|
||||
rolling_code_enable: true
|
||||
binary_sensors:
|
||||
- binary_sensor_id1
|
||||
sensors:
|
||||
- sensor_id1
|
||||
- id: sensor_id2
|
||||
broadcast_id: different_id
|
||||
|
||||
providers:
|
||||
- name: some-device-name
|
||||
encryption: "REPLACEME with some key"
|
||||
|
||||
sensor:
|
||||
- platform: udp
|
||||
provider: some-device-name
|
||||
id: local_sensor_id
|
||||
remote_id: some_sensor_id
|
||||
|
||||
binary_sensor:
|
||||
- platform: udp
|
||||
provider: unencrypted-device
|
||||
id: other_binary_sensor_id # also used as remote_id
|
||||
|
||||
Configuration variables:
|
||||
------------------------
|
||||
|
||||
- **id** (*Optional*, :ref:`config-id`): Manually specify the ID used for code generation.
|
||||
- **update_interval** (*Optional*, :ref:`config-time`): Interval between full broadcasts. Defaults to 15s.
|
||||
- **port** (*Optional*, int): The destination UDP port number to use. Defaults to ``18511``.
|
||||
- **addresses** (*Optional*, list of IPv4 addresses): One or more IP addresses to broadcast data to. Defaults to ``255.255.255.255``
|
||||
which is the local network broadcast address.
|
||||
- **sensors** (*Optional*, list): A list of sensor IDs to be broadcast. Each entry may be just the sensor id, or may set a different id to be broadcast.
|
||||
|
||||
- **id** (**Required**, :ref:`config-id`): The id of the sensor to be used
|
||||
- **broadcast_id** (*Optional*, string): The id to be used for this sensor in the broadcast. Defaults to the same as the internal id.
|
||||
|
||||
- **binary_sensors** (*Optional*, list): A list of binary sensor IDs to be broadcast.
|
||||
|
||||
- **id** (**Required**, :ref:`config-id`): The id of the binary sensor to be used
|
||||
- **broadcast_id** (*Optional*, string): The id to be used for this binary sensor in the broadcast. Defaults to the same as the internal id.
|
||||
|
||||
- **encryption** (*Optional*, string): The encryption key to use when broadcasting. Default is no encryption. This may be
|
||||
any string, and will be hashed to form a 256 bit key.
|
||||
- **rolling_code_enable** (*Optional*, boolean): Enables a rolling code to be included in all broadcasts. Requires ``encryption`` to be set. Defaults to ``false``. Can be set only on the provider side.
|
||||
- **ping_pong_enable** (*Optional*, boolean): When set, requires encrypted providers to include a *nonce* generated by this device in broadcasts. Defaults to ``false``. Can be set only on the consumer side.
|
||||
- **ping_pong_recycle_time** (*Optional*, :ref:`config-time`): Controls how often the ping-pong key is regenerated. Requires ``ping_pong_enable`` to be set. Defaults to 10 minutes. Can be set only on the consumer side.
|
||||
- **providers** (*Optional*, list): A list of provider device names and optionally their secret encryption keys.
|
||||
|
||||
- **name** (**Required**, string): The device name of the provider.
|
||||
- **encryption** (*Optional*, string): The provider's encryption key.
|
||||
|
||||
Wherever a provider name is required, this should be the node name configured in the ``esphome:`` block.
|
||||
|
||||
This component supports multiple configurations, making it possible to differentiate between consumers when providing data to them.
|
||||
When receiving data in such a configuration, sensors need an ``udp_id`` configuration item to know where to expect data to come from.
|
||||
|
||||
Reliability
|
||||
-----------
|
||||
|
||||
UDP, like any other network protocol, does not provide a guarantee that data will be delivered, but unlike TCP it does not
|
||||
even provide any indication whether data has been successfully delivered or not. When any of the configured sensors changes state,
|
||||
the component will broadcast that sensor's state, but since this may not be delivered to a consumer, the UDP component
|
||||
also broadcasts *all* sensor data on a timed schedule, set by ``update_interval``. Even this does not guarantee
|
||||
delivery, but in practice unless the network has failed, updates will eventually be delivered, albeit possibly after
|
||||
some delay.
|
||||
|
||||
Security
|
||||
--------
|
||||
|
||||
By default there is no security - all data is transmitted in clear text on the network. This would be appropriate
|
||||
for non-sensitive sensor data or perhaps on a fully secured wired network. For other cases the data can be encrypted
|
||||
by providing an encryption key, which is shared between the provider and consumer.
|
||||
|
||||
Encryption alone ensures that data cannot be read in transit and protects against spoofing of data, but does not protect
|
||||
against replay attacks (where a threat actor records a transmission and replays it later, e.g. to repeat an action.)
|
||||
|
||||
A rolling code can be enabled which mitigates replay attacks - each transmission contains a 64 bit value which is
|
||||
guaranteed to monotonically increase, so the consumer will reject any data which contains a rolling code
|
||||
already seen. The rolling code also ensures that the data in every packet is different, which makes brute-force
|
||||
attacks on the encryption much more difficult. This is enabled in the provider configuration and adds minor overhead.
|
||||
|
||||
.. note::
|
||||
|
||||
The rolling code's upper 32 bit field is incremented and written to flash *once* at reboot on the provider node.
|
||||
It's also incremented and written to flash when the lower 32 bit field overflows, which can only happen after
|
||||
a very long time. The consumer side does not store the d rolling codes in flash.
|
||||
|
||||
For further protection a ``ping-pong`` (or challenge-response) facility is available, which can be enabled in the
|
||||
consumer configuration. The consumer periodically generates a 32 bit random number (a *nonce* aka "Number used Once")
|
||||
and broadcasts it as a *ping*. Any provider receiving this nonce will include it in any future encrypted broadcasts as
|
||||
*pong*. The consumer expects to get back its most recently transmitted *ping* in any packets it receives, and will reject
|
||||
any that do not contain it.
|
||||
|
||||
Use of the ping-pong feature will add to network traffic and the size of the transmitted packets (a single packet may
|
||||
include up to 4 nonces from different devices) but provides a high level of protection against replay attacks. It does
|
||||
require a 2-way network connection, and it only works on local networks because the consumer can only *broadcast* the
|
||||
nonce to the providers.
|
||||
|
||||
.. note::
|
||||
|
||||
Occasionally a ``Ping key not seen`` warning message may appear in the device log. This is expected, because it may
|
||||
happen that while the consumer has regenerated the *ping* key, it subsequently received a *pong* with the previous key,
|
||||
most likely because the messages crossed in transit. In such a case, the message will be rejected, but the next message
|
||||
will contain the correct *pong*.
|
||||
|
||||
Because of this, ``ping-pong`` is only recommended to be used for state transmissions, which are updated periodically
|
||||
at ``update_interval``.
|
||||
|
||||
**Security considerations**
|
||||
|
||||
The encryption used is `XXTEA <https://en.wikipedia.org/wiki/XXTEA>`_ which is fast and compact. Although XXTEA is known
|
||||
to be susceptible to a chosen-plaintext attack, such an attack is not possible with this application, and it otherwise
|
||||
has no published weaknesses [#f1]_. The implementation used here has been modified slightly to use a 256 bit key which
|
||||
will strengthen security compared to the original 128 bit key.
|
||||
|
||||
When encryption is used, all data is encrypted except the sender node name, and the initial request for a ping-pong key.
|
||||
Broadcasting names does not compromise security, since this information would already be available via mDNS.
|
||||
Requesting a key in clear text does not reduce the security of the key, since it is the ability to encrypt this key
|
||||
with the shared secret key that provides the security assurance.
|
||||
|
||||
This does mean however that there is a possible Denial of Service attack by a malicious node overwriting a valid
|
||||
ping-pong key, which will result in packets being rejected by the legitimate consumer.
|
||||
|
||||
Configuration examples
|
||||
----------------------
|
||||
|
||||
This example couples two light switches in two different devices, so that switching either one on or off will cause
|
||||
the other to follow suit. In each case a template binary_sensor is used to mirror the switch state.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# Device 1
|
||||
esphome:
|
||||
name: device-1
|
||||
|
||||
udp:
|
||||
binary_sensors:
|
||||
- relay1_sensor
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
pin: GPIO6
|
||||
id: relay1
|
||||
name: "Device 1 switch"
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
id: relay1_sensor
|
||||
lambda: "return id(relay1).state;"
|
||||
|
||||
- platform: udp
|
||||
provider: device-2
|
||||
id: relay2_sensor
|
||||
on_press:
|
||||
switch.turn_on: relay1
|
||||
on_release:
|
||||
switch.turn_off: relay1
|
||||
|
||||
|
||||
# Device 2
|
||||
esphome:
|
||||
name: device-2
|
||||
|
||||
udp:
|
||||
binary_sensors:
|
||||
- relay2_sensor
|
||||
|
||||
switch:
|
||||
- platform: gpio
|
||||
pin: GPIO6
|
||||
id: relay2
|
||||
name: "Device 2 switch"
|
||||
|
||||
binary_sensor:
|
||||
- platform: template
|
||||
id: relay2_sensor
|
||||
lambda: "return id(relay2).state;"
|
||||
|
||||
- platform: udp
|
||||
provider: device-1
|
||||
id: relay1_sensor
|
||||
on_press:
|
||||
switch.turn_on: relay2
|
||||
on_release:
|
||||
switch.turn_off: relay2
|
||||
|
||||
The following example shows a device using encryption to read a sensor and two binary sensors from two different
|
||||
devices, one with encryption and ping-pong and one without. It also rebroadcasts one of those binary sensors with its own
|
||||
encryption and a rolling code to a remote host.
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
udp:
|
||||
update_interval: 60s
|
||||
addresses: ["10.87.135.110"]
|
||||
ping_pong_enable: true
|
||||
rolling_code_enable: true
|
||||
encryption: "Muddy Waters"
|
||||
binary_sensors:
|
||||
- tick_tock
|
||||
providers:
|
||||
- name: st7735s
|
||||
encryption: "Blind Willie Johnson"
|
||||
# - name: room-lights # Not required here since no encryption
|
||||
|
||||
binary_sensor:
|
||||
- platform: udp
|
||||
provider: st7735s
|
||||
id: tick_tock
|
||||
- platform: udp
|
||||
provider: room-lights
|
||||
id: relay1_sensor
|
||||
|
||||
sensor:
|
||||
- platform: udp
|
||||
provider: st7735s
|
||||
id: wifi_signal_sensor
|
||||
|
||||
The example below shows a provider device separating data sent to different consumers. There are two provider confgurations, with different IDs.
|
||||
The ``udp_internal`` provider broadcasts the selected sensor states in plain every 10 seconds to all the network members, while the ``udp_external``
|
||||
provider sends other sensors data to an external IP address and port, with encryption. The node also listens to data from a ``remote-node`` through
|
||||
the port specified in the ``udp_external`` configuration:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
udp:
|
||||
- id: udp_internal
|
||||
update_interval: 10s
|
||||
sensors:
|
||||
- temp_outdoor
|
||||
- temp_rooma
|
||||
- temp_roomb
|
||||
- temp_roomc
|
||||
- temp_garage
|
||||
- temp_water
|
||||
- humi_rooma
|
||||
- humi_roomb
|
||||
- humi_roomc
|
||||
|
||||
- id: udp_external
|
||||
update_interval: 60s
|
||||
encryption: "Muddy Waters"
|
||||
ping_pong_enable: true
|
||||
rolling_code_enable: true
|
||||
port: 38512
|
||||
addresses:
|
||||
- 10.87.135.110
|
||||
binary_sensors:
|
||||
- binary_sensor_door
|
||||
sensors:
|
||||
- temp_outdoor
|
||||
|
||||
binary_sensor:
|
||||
- platform: udp
|
||||
id: binary_sensor_unlock
|
||||
udp_id: udp_external
|
||||
provider: remote-node
|
||||
remote_id: binary_sensor_unlock_me
|
||||
on_press:
|
||||
- lambda: |-
|
||||
ESP_LOGI("main", "d command to binary_sensor_unlock");
|
||||
|
||||
|
||||
.. [#f1] As known in 2024.06.
|
||||
|
||||
See Also
|
||||
--------
|
||||
|
||||
- :doc:`/components/binary_sensor/udp`
|
||||
- :doc:`/components/sensor/udp`
|
||||
- :ref:`automation`
|
||||
- :apiref:`udp/udp_component.h`
|
||||
- :ghedit:`Edit`
|
1
images/udp.svg
Normal file
1
images/udp.svg
Normal file
@ -0,0 +1 @@
|
||||
<svg viewBox="0 0 69 25" id="svg5" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg"><defs id="defs9"/><path d="M5 0H64a5 5 0 015 5v15a5 5 0 01-5 5H5a5 5 0 01-5-5V5a5 5 0 015-5z" style="fill:#000" id="path2"/><g aria-label="UDP" id="component-text" style="font-weight:900;font-size:25px;font-family:Montserrat;letter-spacing:1.1px;fill:#fffffc"><path d="m14.8 21.4q-4.025.0-6.275-2.175t-2.25-6.1V3.5h5.9v9.45q0 2 .725 2.85.725.825 1.95.825 1.25.0 1.95-.825.725-.85.725-2.85V3.5h5.8v9.625q0 3.925-2.25 6.1Q18.825 21.4 14.8 21.4z" id="path11"/><path d="M27.12501 21V3.5h8.625q2.925.0 5.15 1.075 2.225 1.05 3.475 3t1.25 4.65q0 2.725-1.25 4.7-1.25 1.95-3.475 3.025-2.225 1.05-5.15 1.05zm5.9-4.6h2.475q1.25.0 2.175-.475.95-.475 1.475-1.4.525-.95.525-2.3.0-1.325-.525-2.25t-1.475-1.4q-.925-.475-2.175-.475h-2.475z" id="path13"/><path d="M48.875016 21V3.5h8.425q2.45.0 4.225.8 1.8.8 2.775 2.3.975 1.475.975 3.5t-.975 3.5q-.975 1.475-2.775 2.3-1.775.8-4.225.8h-5.15l2.625-2.525V21zm5.9-6.175-2.625-2.675h4.775q1.225.0 1.8-.55.6-.55.6-1.5t-.6-1.5q-.575-.55-1.8-.55h-4.775l2.625-2.675z" id="path15"/></g></svg>
|
After Width: | Height: | Size: 1.1 KiB |
@ -204,6 +204,7 @@ Network Protocols
|
||||
HTTP Request, components/http_request, connection.svg, dark-invert
|
||||
mDNS, components/mdns, radio-tower.svg, dark-invert
|
||||
WireGuard, components/wireguard, wireguard_custom_logo.svg
|
||||
UDP, components/udp, udp.svg
|
||||
|
||||
Bluetooth/BLE
|
||||
-------------
|
||||
@ -1156,7 +1157,6 @@ Cookbook
|
||||
Sonoff Fishpond Pump, cookbook/sonoff-fishpond-pump, cookbook-sonoff-fishpond-pump.jpg
|
||||
Arduino Port Extender, cookbook/arduino_port_extender, arduino_logo.svg
|
||||
EHMTX a matrix status/text display, cookbook/ehmtx, ehmtx.jpg
|
||||
Share data directly between ESPHome nodes, cookbook/http_request_sensor, connection.svg, dark-invert
|
||||
|
||||
Do you have other awesome automations or cool setups? Please feel free to add them to the
|
||||
documentation for others to copy. See :doc:`Contributing </guides/contributing>`.
|
||||
|
Loading…
Reference in New Issue
Block a user