diff --git a/.github/workflows/component-image.yml b/.github/workflows/component-image.yml
index 6c46330277..2ed1ca7808 100644
--- a/.github/workflows/component-image.yml
+++ b/.github/workflows/component-image.yml
@@ -14,6 +14,7 @@ jobs:
runs-on: ubuntu-latest
outputs:
name: ${{ steps.get_component.outputs.name }}
+ name_lower: ${{ steps.get_component.outputs.name_lower }}
comment_id: ${{ steps.create-comment.outputs.result }}
steps:
- name: Comment
@@ -35,6 +36,7 @@ jobs:
comment="${{ github.event.comment.body }}"
component=$(echo $comment | sed -n 's/^@esphomebot generate image //p')
echo "name=$component" >> $GITHUB_OUTPUT
+ echo "name_lower=${component,,}" >> $GITHUB_OUTPUT
generate:
name: Generate
@@ -52,7 +54,7 @@ jobs:
id: upload-artifact
with:
name: ${{ needs.prepare.outputs.name }}
- path: ${{ needs.prepare.outputs.name }}.svg
+ path: ${{ needs.prepare.outputs.name_lower }}.svg
- name: Update Comment
uses: actions/github-script@v7.0.1
diff --git a/Makefile b/Makefile
index ed0590e92e..1683244729 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
ESPHOME_PATH = ../esphome
-ESPHOME_REF = 2024.8.0
+ESPHOME_REF = 2024.8.3
PAGEFIND_VERSION=1.1.0
PAGEFIND=pagefind
NET_PAGEFIND=../pagefindbin/pagefind
diff --git a/_static/changelog-2024.8.0.png b/_static/changelog-2024.8.0.png
index cf40f46b68..84f76eb193 100644
Binary files a/_static/changelog-2024.8.0.png and b/_static/changelog-2024.8.0.png differ
diff --git a/changelog/2024.8.0.rst b/changelog/2024.8.0.rst
index 93aef64109..205e654470 100644
--- a/changelog/2024.8.0.rst
+++ b/changelog/2024.8.0.rst
@@ -50,6 +50,26 @@ Thank you for your support
We would like to thank all Home Assistant Cloud subscribers for their support. It allows `Nabu Casa `__ to
employ two developers to maintain and further develop the ESPHome project.
+Release 2024.8.1 - August 28
+----------------------------
+
+- [lvgl] Bug fixes :esphomepr:`7338` by :ghuser:`clydebarrow`
+- [core] Clean build if the loaded integrations changed :esphomepr:`7344` by :ghuser:`clydebarrow`
+- [lvgl] Fix race condition involving numbers, switches etc. :esphomepr:`7345` by :ghuser:`clydebarrow`
+- [api] Fix sending the ``once`` flag on ha entity subscription :esphomepr:`7357` by :ghuser:`jesserockz`
+
+Release 2024.8.2 - September 3
+------------------------------
+
+- [datetime] Fix templated args :esphomepr:`7368` by :ghuser:`jesserockz`
+- Enable IPv6 when manual IPv4 is enabled :esphomepr:`7381` by :ghuser:`HeMan`
+- [core] Only clean build files with esp-idf :esphomepr:`7388` by :ghuser:`jesserockz`
+
+Release 2024.8.3 - September 3
+------------------------------
+
+- Bump Dockerfile dependencies :esphomepr:`7386` by :ghuser:`jesserockz`
+
Full list of changes
--------------------
diff --git a/components/binary_sensor/ble_presence.rst b/components/binary_sensor/ble_presence.rst
index c8a5c6565d..4c0ac32586 100644
--- a/components/binary_sensor/ble_presence.rst
+++ b/components/binary_sensor/ble_presence.rst
@@ -82,35 +82,29 @@ Setting Up Devices
------------------
To set up binary sensors for specific BLE beacons you first have to know which MAC address
-to track. Most devices show this screen in some setting menu. If you don't know the MAC address,
+to track. Most devices show this screen in some settings menu. If you don't know the MAC address,
however, you can use the ``esp32_ble_tracker`` hub without any binary sensors attached and read through
the logs to see discovered Bluetooth Low Energy devices.
-.. code-block:: yaml
-
- # Example configuration entry for finding MAC addresses
- esp32_ble_tracker:
-
-Using the configuration above, first you should see a ``Starting scan...`` debug message at
-boot-up. Then, when a BLE device is discovered, you should see messages like
-``Found device XX:XX:XX:XX:XX:XX`` together with some information about their
-address type and advertised name. If you don't see these messages, your device is unfortunately
-currently not supported.
-
.. code-block:: yaml
# Example configuration entry for finding
- # Service UUIDs and iBeacon UUIDs and identifiers
+ # MAC addresses, Service UUIDs, iBeacon UUIDs, and identifiers
esp32_ble_tracker:
+ on_ble_advertise:
+ - then:
logger:
level: VERY_VERBOSE
-You can increase the :ref:`log level ` to ``VERY_VERBOSE`` to review detailed
-data for each discovered BLE device. This will make ESPHome print Service UUIDs, iBeacon UUIDs,
-iBeacon major and minor identifiers, BLE manufacturer data, RSSI and other data useful for
-debugging purposes. Note that this is useful only during set-up and a less verbose log level
-should be specified afterwards.
+Using the configuration above, first, you should see a ``Starting scan...`` debug message at
+boot-up. Then, when a BLE device is discovered, you should see messages like
+``Parse Result:`` together with some information about their MAC address, address type,
+advertised name, Service UUIDs, iBeacon UUIDs, iBeacon major and minor identifiers,
+BLE manufacturer data, RSSI, and other data useful for debugging purposes.
+Note that this is useful only during set-up and a less verbose log level
+should be specified afterwards. If you don't see these messages, your device is unfortunately
+currently not supported.
Please note that devices that show a ``RANDOM`` address type in the logs probably use a privacy
feature called Resolvable Private Addresses to avoid BLE tracking. Since their MAC-address periodically
diff --git a/components/binary_sensor/udp.rst b/components/binary_sensor/udp.rst
new file mode 100644
index 0000000000..a4122ed56d
--- /dev/null
+++ b/components/binary_sensor/udp.rst
@@ -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 `.
+
+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`
diff --git a/components/canbus/esp32_can.rst b/components/canbus/esp32_can.rst
index bc973f08e2..2dbd41d33b 100644
--- a/components/canbus/esp32_can.rst
+++ b/components/canbus/esp32_can.rst
@@ -26,6 +26,8 @@ Configuration variables:
- **rx_pin** (**Required**, :ref:`Pin `): Receive pin.
- **tx_pin** (**Required**, :ref:`Pin `): Transmit pin.
+- **rx_queue_len** (**Optional**, int): Length of RX queue.
+- **tx_queue_len** (**Optional**, int): Length of TX queue, 0 to disable.
- All other options from :ref:`Canbus `.
.. _esp32-can-bit-rate:
diff --git a/components/ch422g.rst b/components/ch422g.rst
new file mode 100644
index 0000000000..6e01234d10
--- /dev/null
+++ b/components/ch422g.rst
@@ -0,0 +1,67 @@
+CH422G I/O Expander
+====================
+
+.. seo::
+ :description: Instructions for setting up CH422G digital port expanders in ESPHome.
+ :image: ch422g.svg
+
+
+The CH422G component allows you to use the **CH422G** I/O expander in ESPHome.
+It uses an :ref:`I²C Bus ` for communication.
+
+Once configured, you can use any of the 8 available GPIO pins for your projects.
+Within ESPHome they can be used in place of internal GPIO pins in many of ESPHome's components such as the GPIO Binary Sensor or GPIO Switch. They are not usable for PWM or other situations requiring an internal GPIO pin.
+
+.. note::
+
+ This I/O Expander chip is used in the *Waveshare ESP32-S3-Touch-LCD-4.3*
+
+.. code-block:: yaml
+
+ # Example configuration entry
+ ch422g:
+ - id: ch422g_hub
+ address: 0x24
+
+ # Individual outputs
+ switch:
+ - platform: gpio
+ name: CH422G Pin 0
+ pin:
+ ch422g: ch422g_hub
+ number: 0
+ mode:
+ output: true
+ inverted: false
+
+
+Configuration variables:
+************************
+
+- **id** (**Required**, :ref:`config-id`): The id to use for this ``ch422g`` component.
+- **address** (*Optional*, int): The I²C address of the driver.
+ Defaults to ``0x24``.
+- **restore_value** (*Optional*, boolean): Writes default flags on setup, overriding values from chips cache.
+ Defaults to ``false``.
+
+
+
+Pin configuration variables:
+****************************
+
+- **ch422g** (**Required**, :ref:`config-id`): The id of the ``ch422g`` component of the pin.
+- **number** (**Required**, int): The pin number. Valid numbers are 0-7.
+- **inverted** (*Optional*, boolean): If all read and written values
+ should be treated as inverted. Defaults to ``false``.
+- **mode** (*Optional*, string): A pin mode to set the pin at. One of ``INPUT`` or ``OUTPUT``.
+
+
+See Also
+--------
+
+- :ref:`i2c`
+- :doc:`switch/gpio`
+- :doc:`binary_sensor/gpio`
+- `CH422G datasheet `__
+- :apiref:`ch422g/ch422g.h`
+- :ghedit:`Edit`
diff --git a/components/climate/climate_ir.rst b/components/climate/climate_ir.rst
index aaf3cc23fc..a6e6764df3 100644
--- a/components/climate/climate_ir.rst
+++ b/components/climate/climate_ir.rst
@@ -162,6 +162,7 @@ The Daikin ARC remotes (``daikin_arc`` climate, ``daikin_arc417``, ``daikin_arc4
- ``yaa``
- ``yac``
- ``yac1fb9``
+ - ``yx1ff``
.. code-block:: yaml
@@ -248,7 +249,7 @@ These air conditioners support two protocols: Midea and Coolix. Therefore, when
.. note::
- - While they are identified as separate models here, the ``RAC-PT1411HWRU-C`` and ``RAC-PT1411HWRU-C`` are
+ - While they are identified as separate models here, the ``RAC-PT1411HWRU-C`` and ``RAC-PT1411HWRU-F`` are
in fact the same physical model/unit. They are separated here only because different IR codes are used
depending on the desired unit of measurement. This only affects how temperature is displayed on the unit itself.
diff --git a/components/datetime/index.rst b/components/datetime/index.rst
index 60ec0001b2..23af22daba 100644
--- a/components/datetime/index.rst
+++ b/components/datetime/index.rst
@@ -121,7 +121,7 @@ The ``date`` provided can be in one of 3 formats:
id: my_datetime_date
date: !lambda |-
// Return an ESPTime struct
- return {.day_of_month: 4, .month: 12, .year: 2023};
+ return {.day_of_month = 4, .month = 12, .year = 2023};
Configuration variables:
@@ -192,7 +192,7 @@ The ``time`` provided can be in one of 3 formats:
id: my_datetime_time
time: !lambda |-
// Return an ESPTime struct
- return {.second: 56, .minute: 34, .hour: 12};
+ return {.second = 56, .minute = 34, .hour = 12};
Configuration variables:
@@ -266,7 +266,7 @@ The ``datetime`` provided can be in one of 3 formats:
id: my_datetime
datetime: !lambda |-
// Return an ESPTime struct
- return {.second: 56, .minute: 34, .hour: 12, .day_of_month: 31, .month: 12, .year: 2024};
+ return {.second = 56, .minute = 34, .hour = 12, .day_of_month = 31, .month = 12, .year = 2024};
Configuration variables:
diff --git a/components/display/ili9xxx.rst b/components/display/ili9xxx.rst
index 1e9f4024f3..493e49f9e6 100644
--- a/components/display/ili9xxx.rst
+++ b/components/display/ili9xxx.rst
@@ -61,9 +61,8 @@ beyond the basic SPI connections, and a reasonable amount of RAM, it is not well
model: ili9341
dc_pin: GPIOXX
reset_pin: GPIOXX
- lambda: |-
- it.fill(COLOR_BLACK);
- it.print(0, 0, id(my_font), id(my_red), TextAlign::TOP_LEFT, "Hello World!");
+ invert_colors: false
+ show_test_card: true
Configuration variables:
************************
@@ -101,7 +100,7 @@ Configuration variables:
- **offset_width** (*Optional*, int): Specify an offset for the x-direction of the display, typically used when an LCD is smaller than the maximum supported by the driver chip. Default is 0
- **offset_height** (*Optional*, int): Specify an offset for the y-direction of the display. Default is 0.
-- **invert_colors** (*Optional*): With this boolean option you can invert the display colors.
+- **invert_colors** (**Required**): Specifies whether the display colors should be inverted. Options are ``true`` or ``false`` - if you are unsure, use ``false`` and change if the colors are not as expected.
- **pixel_mode** (*Optional*): Allows forcing the display into 18 or 16 bit mode. Options are ``18bit`` or ``16bit``. If unspecified, the pixel mode will be determined by the model choice. Not all displays will work in both modes.
- **rotation** (*Optional*): Rotate the display presentation in software. Choose one of ``0°``, ``90°``, ``180°``, or ``270°``. This option cannot be used with ``transform``.
- **transform** (*Optional*): Transform the display presentation using hardware. All defaults are ``false``. This option cannot be used with ``rotation``.
@@ -265,6 +264,7 @@ This config rotates the display into landscape mode using the driver chip.
mirror_x: false
mirror_y: true
color_order: bgr
+ invert_colors: true
data_rate: 80MHz
cs_pin: GPIOXX
dc_pin: GPIO13
diff --git a/components/display/rpi_dpi_rgb.rst b/components/display/rpi_dpi_rgb.rst
index 2b5ae9526f..5a52cc232d 100644
--- a/components/display/rpi_dpi_rgb.rst
+++ b/components/display/rpi_dpi_rgb.rst
@@ -77,6 +77,7 @@ Configuration variables:
- **pclk_pin** (**Required**, :ref:`Pin Schema `): The PCLK pin.
- **hsync_pin** (**Required**, :ref:`Pin Schema `): The Horizontal sync pin.
- **vsync_pin** (**Required**, :ref:`Pin Schema `): The Vertical sync pin.
+- **enable_pin** (*Optional*, :ref:`Pin Schema `): The ENABLE pin.
- **reset_pin** (*Optional*, :ref:`Pin Schema `): The RESET pin.
- **hsync_pulse_width** (*Optional*, int): The horizontal sync pulse width.
- **hsync_front_porch** (*Optional*, int): The horizontal front porch length.
diff --git a/components/display/st7701s.rst b/components/display/st7701s.rst
index ec217ad310..4c921467d4 100644
--- a/components/display/st7701s.rst
+++ b/components/display/st7701s.rst
@@ -130,6 +130,8 @@ The ``init_sequence`` requires a list of elements, one of which may be a single
sequence (the default and currently the only sequence is 1), the remainder must be byte arrays providing additional
init commands, each consisting of a command byte followed by zero or more data bytes.
+A delay may be specified with ``delay ms``
+
These will be collected and sent to the display via SPI during initialisation.
Example configurations
@@ -165,6 +167,7 @@ Seeed Sensecap Indicator
pclk_pin: 21
init_sequence:
- 1 # select canned init sequence number 1
+ - delay 5ms
- [ 0xE0, 0x1F ] # Set sunlight readable enhancement
data_pins:
red:
diff --git a/components/light/esp32_rmt_led_strip.rst b/components/light/esp32_rmt_led_strip.rst
index cb19142449..fc27cc4863 100644
--- a/components/light/esp32_rmt_led_strip.rst
+++ b/components/light/esp32_rmt_led_strip.rst
@@ -34,6 +34,7 @@ Configuration variables
"ESP32-C3", "0, 1"
- **chipset** (**Required**, enum): The chipset to apply known timings from. Not used if specifying the timings manually, see below.
+ - ``WS2811``
- ``WS2812``
- ``SK6812``
- ``APA106``
@@ -67,6 +68,10 @@ please consider adding support to the codebase and add it to the list above.
- **bit0_low** (*Optional*, :ref:`config-time`): The time to hold the data line low for a ``0`` bit.
- **bit1_high** (*Optional*, :ref:`config-time`): The time to hold the data line high for a ``1`` bit.
- **bit1_low** (*Optional*, :ref:`config-time`): The time to hold the data line low for a ``1`` bit.
+- **reset_high** (*Optional*, :ref:`config-time`): The time to hold the data line high after writing
+ the state. Defaults to ``0 us``.
+- **reset_low** (*Optional*, :ref:`config-time`): The time to hold the data line low after writing
+ the state. Defaults to ``0 us``.
See Also
--------
diff --git a/components/lvgl/images/lvgl_align.png b/components/lvgl/images/lvgl_align.png
index e7a1381ca6..f3b97d5cc7 100644
Binary files a/components/lvgl/images/lvgl_align.png and b/components/lvgl/images/lvgl_align.png differ
diff --git a/components/lvgl/images/lvgl_animimg.gif b/components/lvgl/images/lvgl_animimg.gif
index 9f6bce8bee..a24c8ed452 100644
Binary files a/components/lvgl/images/lvgl_animimg.gif and b/components/lvgl/images/lvgl_animimg.gif differ
diff --git a/components/lvgl/images/lvgl_arc.png b/components/lvgl/images/lvgl_arc.png
index d2114ce262..fe2f20fc8c 100644
Binary files a/components/lvgl/images/lvgl_arc.png and b/components/lvgl/images/lvgl_arc.png differ
diff --git a/components/lvgl/images/lvgl_baseobj.png b/components/lvgl/images/lvgl_baseobj.png
index 5fe7294ce6..eebb86d598 100644
Binary files a/components/lvgl/images/lvgl_baseobj.png and b/components/lvgl/images/lvgl_baseobj.png differ
diff --git a/components/lvgl/images/lvgl_boxmodel.png b/components/lvgl/images/lvgl_boxmodel.png
index 98251f4169..e02e802395 100644
Binary files a/components/lvgl/images/lvgl_boxmodel.png and b/components/lvgl/images/lvgl_boxmodel.png differ
diff --git a/components/lvgl/images/lvgl_button.png b/components/lvgl/images/lvgl_button.png
index c80d07f2d1..3d02c82f79 100644
Binary files a/components/lvgl/images/lvgl_button.png and b/components/lvgl/images/lvgl_button.png differ
diff --git a/components/lvgl/images/lvgl_buttonmatrix.png b/components/lvgl/images/lvgl_buttonmatrix.png
index 4842d58f3a..1acde41d1c 100644
Binary files a/components/lvgl/images/lvgl_buttonmatrix.png and b/components/lvgl/images/lvgl_buttonmatrix.png differ
diff --git a/components/lvgl/images/lvgl_checkbox.png b/components/lvgl/images/lvgl_checkbox.png
index 31b63cc7f5..1f4461d705 100644
Binary files a/components/lvgl/images/lvgl_checkbox.png and b/components/lvgl/images/lvgl_checkbox.png differ
diff --git a/components/lvgl/images/lvgl_dropdown.png b/components/lvgl/images/lvgl_dropdown.png
index 191f0bdb53..716f1a9e7a 100644
Binary files a/components/lvgl/images/lvgl_dropdown.png and b/components/lvgl/images/lvgl_dropdown.png differ
diff --git a/components/lvgl/images/lvgl_keyboard.png b/components/lvgl/images/lvgl_keyboard.png
index a9b009d310..b76e2db586 100644
Binary files a/components/lvgl/images/lvgl_keyboard.png and b/components/lvgl/images/lvgl_keyboard.png differ
diff --git a/components/lvgl/images/lvgl_label.png b/components/lvgl/images/lvgl_label.png
index 9a31c4ef3e..3bbc5ca2fd 100644
Binary files a/components/lvgl/images/lvgl_label.png and b/components/lvgl/images/lvgl_label.png differ
diff --git a/components/lvgl/images/lvgl_led.png b/components/lvgl/images/lvgl_led.png
index 0349f1b9cd..16ee18c2e9 100644
Binary files a/components/lvgl/images/lvgl_led.png and b/components/lvgl/images/lvgl_led.png differ
diff --git a/components/lvgl/images/lvgl_line.png b/components/lvgl/images/lvgl_line.png
index 6d85c445b4..0cea675ddc 100644
Binary files a/components/lvgl/images/lvgl_line.png and b/components/lvgl/images/lvgl_line.png differ
diff --git a/components/lvgl/images/lvgl_main_screenshot.png b/components/lvgl/images/lvgl_main_screenshot.png
index a8c971a901..37ba10a3f4 100644
Binary files a/components/lvgl/images/lvgl_main_screenshot.png and b/components/lvgl/images/lvgl_main_screenshot.png differ
diff --git a/components/lvgl/images/lvgl_meter.png b/components/lvgl/images/lvgl_meter.png
index 1283126ccc..2f577a5828 100644
Binary files a/components/lvgl/images/lvgl_meter.png and b/components/lvgl/images/lvgl_meter.png differ
diff --git a/components/lvgl/images/lvgl_msgbox.png b/components/lvgl/images/lvgl_msgbox.png
index 101a40c8b4..630644b3b5 100644
Binary files a/components/lvgl/images/lvgl_msgbox.png and b/components/lvgl/images/lvgl_msgbox.png differ
diff --git a/components/lvgl/images/lvgl_roller.png b/components/lvgl/images/lvgl_roller.png
index 3eab1039c0..8e1be18d76 100644
Binary files a/components/lvgl/images/lvgl_roller.png and b/components/lvgl/images/lvgl_roller.png differ
diff --git a/components/lvgl/images/lvgl_slider.png b/components/lvgl/images/lvgl_slider.png
index d2de4030d2..6ffbadb529 100644
Binary files a/components/lvgl/images/lvgl_slider.png and b/components/lvgl/images/lvgl_slider.png differ
diff --git a/components/lvgl/images/lvgl_spinbox.png b/components/lvgl/images/lvgl_spinbox.png
index 72ebee3c89..afe5fa12cd 100644
Binary files a/components/lvgl/images/lvgl_spinbox.png and b/components/lvgl/images/lvgl_spinbox.png differ
diff --git a/components/lvgl/images/lvgl_spinner.gif b/components/lvgl/images/lvgl_spinner.gif
index cf4b1640f3..107eee14c8 100644
Binary files a/components/lvgl/images/lvgl_spinner.gif and b/components/lvgl/images/lvgl_spinner.gif differ
diff --git a/components/lvgl/images/lvgl_switch.png b/components/lvgl/images/lvgl_switch.png
index 9864b2b79b..dcf2d74cd8 100644
Binary files a/components/lvgl/images/lvgl_switch.png and b/components/lvgl/images/lvgl_switch.png differ
diff --git a/components/lvgl/images/lvgl_symbols.png b/components/lvgl/images/lvgl_symbols.png
index 65320bd91d..3e40188bcf 100644
Binary files a/components/lvgl/images/lvgl_symbols.png and b/components/lvgl/images/lvgl_symbols.png differ
diff --git a/components/lvgl/images/lvgl_tabview.png b/components/lvgl/images/lvgl_tabview.png
index ae18acf31a..057db55ff7 100644
Binary files a/components/lvgl/images/lvgl_tabview.png and b/components/lvgl/images/lvgl_tabview.png differ
diff --git a/components/lvgl/images/lvgl_textarea.png b/components/lvgl/images/lvgl_textarea.png
index 1382f7e100..0970629523 100644
Binary files a/components/lvgl/images/lvgl_textarea.png and b/components/lvgl/images/lvgl_textarea.png differ
diff --git a/components/lvgl/index.rst b/components/lvgl/index.rst
index 7dec755025..d62e0d4613 100644
--- a/components/lvgl/index.rst
+++ b/components/lvgl/index.rst
@@ -10,7 +10,7 @@ embedded graphics library to create beautiful UIs for any MCU, MPU and display t
.. figure:: /components/lvgl/images/lvgl_main_screenshot.png
-To use LVGL with a :ref:`display ` in ESPHome, you'll need an ESP32 or supported ESP32 variant. PSRAM is not a strict requirement but it is generally recommended, especially for color displays with resolutions larger than approximately 240x240 pixels.
+To use LVGL with a :ref:`display ` in ESPHome, you'll need an ESP32 or RP2040. PSRAM is not a strict requirement but it is generally recommended, especially for large color displays.
The graphic display should be configured with ``auto_clear_enabled: false`` and ``update_interval: never``, and should not have any ``lambda`` set.
@@ -640,6 +640,56 @@ This :ref:`action ` shows a specific page (including pages with
then:
- lvgl.page.show: secret_page # shorthand version
+.. _lvgl-widget-focus-action:
+
+``lvgl.widget.focus``
+*********************
+
+This :ref:`action ` moves the input focus to the nominated widget. Used mainly with encoder inputs
+to select a specific widget to receive input events. It may also allow the focus to be frozen on that widget,
+or can be used to move the focus to the next or previous widget in the focus group.
+
+The required config options take one of several forms:
+
+- **id** (**Required**): The ID of the widget to be given focus.
+- **freeze** (*Optional*, boolean): If true will lock the focus to this widget.
+- **editing** (*Optional*, boolean): Sets the editing mode of the widget, i.e. encoder rotation will change the value
+ of the widget, not move the focus. Defaults to false.
+
+or
+
+- **action** (**Required**): Should be one of ``next``, ``previous``, ``mark`` or ``restore``.
+- **group** (*Optional*): The ID of the group within which to move the focus. The default group will be used if not specified
+- **freeze** (*Optional*, boolean): If true will lock the focus to the now selected widget.
+
+
+The ``next`` and ``previous`` actions will move the focus to the next or previous widget within the group.
+The ``mark`` action will save the currently focused widget within the group, and restore it when the ``restore`` action is triggered.
+
+.. code-block:: yaml
+
+ on_...:
+ then:
+ - lvgl.widget.focus:
+ id: my_button
+ freeze: true
+
+ on_...:
+ then:
+ - lvgl.widget.focus: my_button
+
+ on_...:
+ then:
+ - lvgl.widget.focus:
+ group: encoder_group
+ direction: next
+ freeze: true
+
+ on_...:
+ then:
+ - lvgl.widget.focus: previous
+
+
.. _lvgl-conditions:
Conditions
@@ -660,8 +710,9 @@ This :ref:`condition ` checks if the amount of time specified
on_...:
then:
- if:
- condition: lvgl.is_idle
- timeout: 5s
+ condition:
+ lvgl.is_idle:
+ timeout: 5s
then:
- light.turn_off:
id: display_backlight
diff --git a/components/lvgl/widgets.rst b/components/lvgl/widgets.rst
index 3b67721bab..5901044e2c 100644
--- a/components/lvgl/widgets.rst
+++ b/components/lvgl/widgets.rst
@@ -729,7 +729,7 @@ Images are the basic widgets used to display images.
- **offset_y** (*Optional*): Add a vertical offset to the image position.
- **pivot_x** (*Optional*): Horizontal position of the pivot point of rotation, in pixels, relative to the top left corner of the image.
- **pivot_y** (*Optional*): Vertical position of the pivot point of rotation, in pixels, relative to the top left corner of the image.
-- **scale** (*Optional*, 0.1-10): Zoom of the image.
+- **zoom** (*Optional*, 0.1-10): Zoom of the image.
- **src** (**Required**, :ref:`image `): The ID of an existing image configuration.
- Some style options from :ref:`lvgl-styling` for the background rectangle that uses the typical background style properties and the image itself using the image style properties.
@@ -1826,9 +1826,15 @@ ESPHome implements as universal triggers the following interaction events genera
- ``on_scroll``: The widget was scrolled.
- ``on_focus``: The widget is focused.
- ``on_defocus``: The widget is unfocused.
+- ``on_all_events``: Will be triggered on any event sent to the widget - this is useful for debugging.
These triggers can be applied directly to any widget in the LVGL configuration, *given that the widget itself supports generating such events*. For the widgets having a value, the triggers return the current value in variable ``x``; this variable may be used in lambdas defined within those triggers.
+Each trigger also deliver an ``event`` parameter, which is a pointer to the LVGL C type ``lv_event_t``. This may be used in lambdas defined within those triggers. Refer to the `LVGL documentation `_ for more information.
+
+There are additional triggers for pages - each page may have an ``on_load`` and ``on_unload`` trigger. These will be called
+when the page becomes active or inactive respectively.
+
.. code-block:: yaml
# Example triggers:
diff --git a/components/modbus_controller.rst b/components/modbus_controller.rst
index 264f078379..7eca0e6a0c 100644
--- a/components/modbus_controller.rst
+++ b/components/modbus_controller.rst
@@ -54,7 +54,9 @@ Configuration variables:
- **modbus_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the ``modbus`` hub.
-- **address** (**Required**, :ref:`config-id`): The Modbus address of the slave device
+- **address** (**Required**, :ref:`config-id`): The Modbus address of the slave device.
+
+- **allow_duplicate_commands** (*Optional*, boolean): Whether to allow duplicate commands in the queue. Defaults to ``false``.
- **command_throttle** (*Optional*, :ref:`config-time`): minimum time in between 2 requests to the device. Default is ``0ms``.
Some Modbus slave devices limit the rate of requests from the master, so this allows the interval between requests to be altered.
diff --git a/components/number/tuya.rst b/components/number/tuya.rst
index 3b87b76520..97a7b0a603 100644
--- a/components/number/tuya.rst
+++ b/components/number/tuya.rst
@@ -67,6 +67,9 @@ The above configurations will work fine as long as Tuya device publishes the dat
However this is not always the case. To be able to use such "hidden" datapoints as Number, you need to specify additional ``datapoint_hidden`` configuration block.
This block allows to specify the missing datapoint type and, optionally, the value that should be written to the datapoint at initialization.
+TuyaMCU restores the state of all its datapoints after reboot, but with the hidden datapoints there is no way to know what their values are.
+Therefore there is also an option to store them on the ESPHome side and they will be set at initialization. To use this feature, set the ``restore_value`` yaml key to True.
+
.. code-block:: yaml
- platform: "tuya"
@@ -77,6 +80,7 @@ This block allows to specify the missing datapoint type and, optionally, the val
datapoint_hidden:
datapoint_type: int
initial_value: 85
+ restore_value: yes
Configuration variables:
------------------------
@@ -90,6 +94,7 @@ Configuration variables:
- **datapoint_type** (**Required**, string): The datapoint type, one of *int*, *uint*, *enum*.
- **initial_value** (*Optional*, float): The value to be written at initialization. Must be between ``min_value`` and ``max_value``.
+ - **restore_value** (*Optional*, boolean): Saves and loads the state to RTC/Flash. Defaults to ``false``.
- All other options from :ref:`Number `.
diff --git a/components/sensor/bl0906.rst b/components/sensor/bl0906.rst
new file mode 100644
index 0000000000..0006beb95c
--- /dev/null
+++ b/components/sensor/bl0906.rst
@@ -0,0 +1,207 @@
+Belling BL0906 Energy Monitor
+=============================
+
+.. seo::
+ :description: Instructions for setting up BL0906 energy monitor for the Athom Energy Meter
+ :image: bl0906.png
+ :keywords: bl0906, Athom EM2 Energy Meter, Athom EM6 Energy Meter, Athom Energy Meter, ESP32C3 Energy Meter Main Board, Split Single Phase Real Time Whole House Energy Meter
+
+The ``bl0906`` sensor platform allows you to use your BL0906 voltage/current/power and energy
+sensors with ESPHome. This sensor is commonly found in `Athom EM2 Energy Meter `__ and `Athom EM6 Energy Meter `__
+
+.. note::
+
+ The current ratio of the current CT clamp must be 2000:1
+
+As the communication with the BL0906 done using UART, you need
+to have an :ref:`UART bus ` in your configuration with the ``tx_pin`` and ``rx_pin`` connected to the BL0906.
+Additionally, you need to set the baud rate to 19200.
+
+The `Athom EM2 Energy Meter `__ can read 1 voltage channel and 2 Current channels.
+
+.. figure:: images/athom-em2.png
+ :align: center
+ :width: 20.0%
+
+ Athom Single Phase 2 channels Real Time Whole House Energy Meter.
+
+The `Athom EM6 Energy Meter `__ can read 1 voltage channel and 6 Current channels.
+
+.. figure:: images/athom-em6.png
+ :align: center
+ :width: 30.0%
+
+ Athom Single Phase 6 channels Real Time Whole House Energy Meter.
+
+Configuration variables:
+------------------------
+
+- **frequency** (*Optional*): The AC line frequency of the supply voltage. All options from
+ :ref:`Sensor `.
+- **temperature** (*Optional*): Chip internal temperature. All options from
+ :ref:`Sensor `.
+- **voltage** (*Optional*): Use the voltage value of the sensor in V. All options from
+ :ref:`Sensor `.
+- **channel_1** (*Optional*): Use channel 1.
+
+ - **current** (*Optional*): The current value of the channel 1 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 1 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 1 in kWh. All options from
+ :ref:`Sensor `.
+- **channel_2** (*Optional*): Use channel 2.
+
+ - **current** (*Optional*): The current value of the channel 2 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 2 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 2 in kWh. All options from
+ :ref:`Sensor `.
+- **channel_3** (*Optional*): Use channel 3.
+
+ - **current** (*Optional*): The current value of the channel 3 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 3 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 3 in kWh. All options from
+ :ref:`Sensor `.
+- **channel_4** (*Optional*): Use channel 4.
+
+ - **current** (*Optional*): The current value of the channel 4 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 4 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 4 in kWh. All options from
+ :ref:`Sensor `.
+- **channel_5** (*Optional*): Use channel 5.
+
+ - **current** (*Optional*): The current value of the channel 5 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 5 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 5 in kWh. All options from
+ :ref:`Sensor `.
+- **channel_6** (*Optional*): Use channel 6.
+
+ - **current** (*Optional*): The current value of the channel 6 in amperes. All options from
+ :ref:`Sensor `.
+ - **power** (*Optional*): The Power value of the channel 6 in watts. All options from
+ :ref:`Sensor `.
+ - **energy** (*Optional*): The energy value of the channel 6 in kWh. All options from
+ :ref:`Sensor `.
+- **total_energy** (*Optional*): The total energy value of all channels in kWh. All options from
+ :ref:`Sensor `.
+- **total_power** (*Optional*): The total power value of all channels in watts. All options from
+ :ref:`Sensor `.
+- **update_interval** (*Optional*, :ref:`config-time`): The interval to check the
+ sensor. Defaults to ``60s``.
+- **uart_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`UART Component ` if you want
+ to use multiple UART buses.
+
+Example configuration
+---------------------
+
+2 Channel
+^^^^^^^^^^^^^^^^^^
+
+.. code-block:: yaml
+
+ # Example configuration entry
+ sensor:
+ - platform: bl0906
+ frequency:
+ name: 'Frequency'
+ temperature:
+ name: 'Temperature'
+ voltage:
+ name: 'Voltage'
+ channel_1:
+ current:
+ name: 'Current_1'
+ power:
+ name: 'Power_1'
+ energy:
+ name: 'Energy_1'
+ channel_2:
+ current:
+ name: 'Current_2'
+ power:
+ name: 'Power_2'
+ energy:
+ name: 'Energy_2'
+ total_energy:
+ name: 'Total_Energy'
+ total_power:
+ name: 'Total_Power'
+
+6 Channel
+^^^^^^^^^^^^^^^^^^
+
+.. code-block:: yaml
+
+ # Example configuration entry
+ sensor:
+ - platform: bl0906
+ frequency:
+ name: 'Frequency'
+ temperature:
+ name: 'Temperature'
+ voltage:
+ name: 'Voltage'
+ channel_1:
+ current:
+ name: 'Current_1'
+ power:
+ name: 'Power_1'
+ energy:
+ name: 'Energy_1'
+ channel_2:
+ current:
+ name: 'Current_2'
+ power:
+ name: 'Power_2'
+ energy:
+ name: 'Energy_2'
+ channel_3:
+ current:
+ name: 'Current_3'
+ power:
+ name: 'Power_3'
+ energy:
+ name: 'Energy_3'
+ channel_4:
+ current:
+ name: 'Current_4'
+ power:
+ name: 'Power_4'
+ energy:
+ name: 'Energy_4'
+ channel_5:
+ current:
+ name: 'Current_5'
+ power:
+ name: 'Power_5'
+ energy:
+ name: 'Energy_5'
+ channel_6:
+ current:
+ name: 'Current_6'
+ power:
+ name: 'Power_6'
+ energy:
+ name: 'Energy_6'
+ total_energy:
+ name: 'Total_Energy'
+ total_power:
+ name: 'Total_Power'
+
+See Also
+--------
+
+- :ref:`sensor-filters`
+- :doc:`cse7761`
+- :doc:`bl0939`
+- :doc:`bl0940`
+- :apiref:`bl0906/bl0906.h`
+- :ghedit:`Edit`
diff --git a/components/sensor/bl0942.rst b/components/sensor/bl0942.rst
index b2757725ee..e75d66aca9 100644
--- a/components/sensor/bl0942.rst
+++ b/components/sensor/bl0942.rst
@@ -59,6 +59,8 @@ Configuration variables:
sensor. Defaults to ``60s``.
- **uart_id** (*Optional*, :ref:`config-id`): Manually specify the ID of the :ref:`UART Component ` if you want
to use multiple UART buses.
+- **line_frequency** (*Optional*, string): The nominal AC line frequency of the supply voltage. One of ``50Hz``, ``60Hz``. Defaults to ``50Hz``.
+- **address** (*Optional*, int): The address of the BL0942 from its strapping pins. Defaults to ``0``.
See Also
--------
diff --git a/components/sensor/bme68x_bsec2.rst b/components/sensor/bme68x_bsec2.rst
index 6b51359142..36b5d4bc47 100644
--- a/components/sensor/bme68x_bsec2.rst
+++ b/components/sensor/bme68x_bsec2.rst
@@ -52,7 +52,7 @@ The :ref:`I²C ` is required to be set up in your configuration for this se
model: bme680
operating_age: 28d
sample_rate: LP
- voltage: 3.3V
+ supply_voltage: 3.3V
diff --git a/components/sensor/images/apds9306.png b/components/sensor/images/apds9306.png
index 521acbfc8b..f7ff05e218 100644
Binary files a/components/sensor/images/apds9306.png and b/components/sensor/images/apds9306.png differ
diff --git a/components/sensor/images/athom-em2.png b/components/sensor/images/athom-em2.png
new file mode 100644
index 0000000000..7a58a6195c
Binary files /dev/null and b/components/sensor/images/athom-em2.png differ
diff --git a/components/sensor/images/athom-em6.png b/components/sensor/images/athom-em6.png
new file mode 100644
index 0000000000..fddc701fd7
Binary files /dev/null and b/components/sensor/images/athom-em6.png differ
diff --git a/components/sensor/images/m5stack_8angle.jpg b/components/sensor/images/m5stack_8angle.jpg
index 20b444cb49..f9817399de 100644
Binary files a/components/sensor/images/m5stack_8angle.jpg and b/components/sensor/images/m5stack_8angle.jpg differ
diff --git a/components/sensor/udp.rst b/components/sensor/udp.rst
new file mode 100644
index 0000000000..7d5d798c06
--- /dev/null
+++ b/components/sensor/udp.rst
@@ -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 `.
+
+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`
diff --git a/components/touchscreen/gt911.rst b/components/touchscreen/gt911.rst
index 484660afd0..97cced192c 100644
--- a/components/touchscreen/gt911.rst
+++ b/components/touchscreen/gt911.rst
@@ -34,6 +34,7 @@ Configuration variables:
- **id** (*Optional*, :ref:`config-id`): Manually set the ID of this touchscreen.
- **interrupt_pin** (*Optional*, :ref:`Pin Schema `): The touch detection pin.
+- **reset_pin** (*Optional*, :ref:`Pin Schema `): The reset pin.
- All other options from :ref:`Touchscreen `.
diff --git a/components/udp.rst b/components/udp.rst
new file mode 100644
index 0000000000..59a92fd322
--- /dev/null
+++ b/components/udp.rst
@@ -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 `_ 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`
diff --git a/guides/contributing.rst b/guides/contributing.rst
index d6dbee0fca..4a71f82f96 100644
--- a/guides/contributing.rst
+++ b/guides/contributing.rst
@@ -5,75 +5,80 @@ Contributing
:description: Getting started guide for contributing to the ESPHome project
:image: github-circle.svg
-Contributions to the ESPHome suite are very welcome! All the code for the projects
-is hosted on GitHub and you can find the sources here:
+We welcome contributions to the ESPHome suite of code and documentation! All of the project code is hosted on GitHub:
- `ESPHome `__ (Project Source Code)
- `ESPHome-Docs `__ (The documentation which you're reading here)
-Just clone the repository locally, do the changes for your new feature/bug fix and submit
-a pull request.
+Just clone the repository locally, make changes for your new feature/bug fix and submit a pull request.
-Contributing to ESPHome-Docs
-----------------------------
+Contributing to ``esphome-docs``
+--------------------------------
.. image:: /images/logo-docs.svg
:align: center
:width: 60.0%
:class: dark-invert
-One of the areas of ESPHome that can always be improved is the documentation.
-If you see an issue somewhere, a spelling mistakes or if you want to share your awesome
-setup, please feel free to submit a pull request.
+Our documentation can always be improved. We rely on contributions from our users to do so. If you notice an issue (for
+example, spelling/grammar mistakes) or if you want to share your awesome new setup, we encourage you to submit a pull
+request (PR).
The ESPHome documentation is built using `sphinx `__ and uses
-`reStructuredText `__ for all source files.
+`reStructuredText `__ for all source (``.rst``) files.
-If you're not familiar with writing rST, see :ref:`rst-syntax` for a quick refresher.
+If you're not familiar with rST, see :ref:`rst-syntax` for a quick refresher.
-Through Github
+Through GitHub
**************
-This guide essentially goes over the same material found in `GitHub's Editing files in another user's repository `__. You may also find that page helpful to read.
+This guide essentially goes over the same material found in
+`GitHub's Editing files in another user's repository `__.
+You may also find that page helpful to read.
-At the bottom of each page in the docs, there is a "Edit this page on GitHub" link. Click this link and you'll see something like this:
+At the bottom of each page in the docs, there is a "Edit this page on GitHub" link. Click this link and you'll see
+something like this:
.. figure:: images/docs_ghedit_1.png
:align: center
:width: 80.0%
:alt: a screenshot of an rST file opened in GitHub, with the edit button circled
-Click the edit button to start making changes. If you're not sure about some element of syntax, see the quick-start :ref:`rst-syntax` guide.
+Click the edit button to start making changes. If you're unsure about syntax, see the quick-start :ref:`rst-syntax`
+guide.
-Once you've made your changes, give them a useful name and press "Propose changes". At this point, you've made the changes on your own personal copy of the docs in GitHub, but you still need to submit them to us.
+Once you've made your changes, give them a useful name and press "Propose changes". At this point, you've made the
+changes on your own personal copy of the docs in GitHub, but you still need to submit them to us.
.. figure:: images/docs_ghedit_2.png
:align: center
:width: 80.0%
:alt: the commit creation screen in GitHub, with the commit title and "Propose changes" button circled
-To do that, you need to create a "Pull request":
+To do that, you need to create a "Pull request" (PR):
.. figure:: images/docs_ghedit_3.png
:align: center
:width: 80.0%
:alt: the pull request prompt screen in GitHub with the "Create pull request" button circled
-Fill out the new pull request form, replacing the ``[ ]`` with ``[x]`` to indicate that you have followed the instructions.
+Fill out the new pull request form, replacing the ``[ ]`` with ``[x]`` to indicate that you have followed the
+instructions.
.. figure:: images/docs_ghedit_4.png
:align: center
:width: 80.0%
:alt: the pull request creation screen in GitHub with the "Create pull request" button circled
-After waiting a while, you might see a green or a red mark next to your commit in your pull request:
+After a few minutes, you'll see either a green check ✅ or a red ❌ next to your commit in your pull request:
.. figure:: images/docs_ghedit_ci_failed.png
:align: center
:width: 80.0%
:alt: the pull request with a commit with a red x next to it
-This means that there is some error stopping your pull request from being fully processed. Click on the X, click on "Details" next to the lint step, and look and see what's causing your change to fail.
+If you see the red ❌, there is at least one error preventing your pull request from being fully processed. Click on the
+❌, then click on "Details" next to the lint step to determine what's wrong with your change(s).
.. figure:: images/docs_ghedit_ci_details.png
:align: center
@@ -85,9 +90,15 @@ This means that there is some error stopping your pull request from being fully
:width: 80.0%
:alt: log messages showing reason for failed build
-For example, in this case, you'd want to go to line 136 of ``pzemac.rst`` and adjust the number of ``===`` so that it completely underlines the section heading.
+In this example, you need to go to line 136 of ``pzemac.rst`` and adjust the number of ``===`` so that it completely
+underlines the section heading.
-Once you make that change, the pull request will be built again, and hopefully this time where will be no other errors.
+Once you make that change, the pull request will be tested & built again; ideally, this time where will be no remaining
+errors. If, however, more errors are discovered, simply repeat the process above to correct them.
+
+.. note::
+
+ All tests must be passing before we will review (and merge) a pull request.
Build
*****
@@ -100,7 +111,8 @@ Build
docker run --rm -v "${PWD}/":/workspaces/esphome-docs -p 8000:8000 -it ghcr.io/esphome/esphome-docs
- With ``PWD`` referring to the root of the ``esphome-docs`` git repository. Then go to ``:8000`` in your browser.
+ ...with ``PWD`` referring to the root of the ``esphome-docs`` git repository. Then, to see the preview, go to
+ ``:8000`` in your browser.
This way, you don't have to install the dependencies to build the documentation.
@@ -121,16 +133,21 @@ Then, use the provided Makefile to build the changes and start a live-updating w
Notes
*****
-Some notes about the docs:
-
- Use the English language (duh...)
-- An image tells a thousand words, please use them wherever possible. But also don't forget to shrink them, for example
- I often use https://tinypng.com/
-- Try to use examples as often as possible (also while it's great to use highly accurate,
- and domain-specific lingo, it should not interfere with new users understanding the content)
-- Fixes/improvements for the docs themselves should go to the ``current`` branch of the
- esphomedocs repository. New features should be added against the ``next`` branch.
-- Always create new branches in your fork for each pull request.
+- An image is worth a thousand words, please use them wherever possible. Regardless, don't forget to optimize them so
+ pages load quickly; you might try using https://tinypng.com/
+- Try to use examples as often as possible.
+- When using highly accurate, domain-specific terminology, be sure that it does not interfere with new users
+ understanding the content.
+- Be sure to target the correct **base branch** of the ``esphome-docs`` repository:
+
+ - **Fixes/improvements** for documentation must target the ``current`` branch.
+ - **New features** must target the ``next`` branch.
+
+- **Create new branches in your fork** for each pull request; to avoid confusion (and other potential issues), do not
+ make changes directly in the ``next`` and ``current`` branches in your fork.
+- Wrap lines in all files at no more than 120 characters. This makes reviewing PRs faster and easier. Exceptions should
+ be made only for lines which contain long links or other specific content/metadata that cannot be wrapped.
.. _rst-syntax:
@@ -139,10 +156,12 @@ Syntax
Here's a quick RST primer:
-Title hierarchy is based on order of occurrence, not on type of character used to underline it. This
-documents establish the following character order for better consistency.
+Title hierarchy is based on order of occurrence, not on type of character used to underline it. For consistency, we
+adhere to the following order:
-- **Headers**: You can write titles like this:
+- **Headers**:
+
+ You can write titles like this:
.. code-block:: rst
@@ -153,20 +172,27 @@ documents establish the following character order for better consistency.
.. code-block:: rst
- My Sub Section
- --------------
+ My Section
+ ----------
and sub-section headers like this:
.. code-block:: rst
- My Sub-sub Section
- ******************
+ My Sub-section
+ **************
+
+ and sub-sub-section headers like this:
+
+ .. code-block:: rst
+
+ My Sub-sub-section
+ ^^^^^^^^^^^^^^^^^^
.. note::
- The length of the bar below the text **must** match the title Text length.
- Also, titles should be in Title Case
+ - The length of the bar below the text **must** match the title text length.
+ - Section titles should use Title Case.
- **Links**: To create a link to an external resource (for example https://www.google.com), use
``\`Link text \`__``. For example:
@@ -177,8 +203,8 @@ documents establish the following character order for better consistency.
`Google.com `__
-- **References**: To reference another document, use the ``:doc:`` and ``:ref:`` roles (references
- are set up globally and can be used between documents):
+- **References**: To reference another document, use the ``:doc:`` and ``:ref:`` roles (references are set up globally
+ and can be used between documents):
.. code-block:: rst
@@ -223,9 +249,9 @@ documents establish the following character order for better consistency.
.. note::
- Please note the empty line after the ``code-block`` directive. That is necessary.
+ Note that a blank line is *required* after every ``code-block`` directive.
-- **Images**: To show images, use the ``figure`` directive:
+- **Images**: Use the ``figure`` directive to display an image:
.. code-block:: rst
@@ -243,13 +269,11 @@ documents establish the following character order for better consistency.
.. note::
- All images in the documentation need to be as small as possible to ensure
- fast page load times. For normal figures the maximum size should be at most
- about 1000x800 px or so. Additionally, please use online tools like
+ All images in the documentation need to be as small as possible to minimize page load times. Typically, the
+ maximum size should be roughly 1000x800 px or so. Additionally, please use online tools like
https://tinypng.com/ or https://tinyjpg.com/ to further compress images.
-- **Notes and warnings**: You can create simple notes and warnings using the ``note`` and ``warning``
- directives:
+- **Notes and warnings**: You can create simple notes and warnings using the ``note`` and ``warning`` directives:
.. code-block:: rst
@@ -305,28 +329,30 @@ documents establish the following character order for better consistency.
2. Ordered item #2
- **imgtable**: ESPHome uses a custom RST directive to show the table on the front page (see
- `index.rst `__).
- New pages need to be added to the ``imgtable`` list. The syntax is CSV with , (without RST),
- (in top-level images/ directory), (optional - short text to describe the component). The aspect ratio of these images should be 8:10 (or 10:8) but exceptions are possible.
+ `index.rst `__). New pages need to be added to the
+ ``imgtable`` list. The syntax is CSV with , (without RST), (in the top-level
+ ``images/`` directory), (optional; short text to describe the component). The aspect ratio of these images
+ should be 8:10 (or 10:8) but exceptions are possible.
Because these images are served on the main page, they need to be compressed heavily. SVGs are preferred over JPGs
- and JPGs should be max. 300x300px.
+ and JPGs should be no more than 300x300px.
+
If you have imagemagick installed, you can use this command to convert the thumbnail:
.. code-block:: bash
convert -sampling-factor 4:2:0 -strip -interlace Plane -quality 80% -resize 300x300 in.jpg out.jpg
-reStructured text can do a lot more than this, so if you're looking for a more complete guide
-please have a look at the `Sphinx reStructuredText Primer `__.
+reStructured text can do a lot more than this; if you're looking for a more complete guide, please have a look at the
+`Sphinx reStructuredText Primer `__.
.. _setup_dev_env:
-Setting Up Development Environment
-----------------------------------
+Setting Up a Development Environment
+------------------------------------
-For developing new features to ESPHome, you will first need to set up a development environment.
-This is only possible for ``pip`` installs.
+If you want to develop (a) new feature(s) for ESPHome, you need to set up a development environment.
+Note that ``pip`` must be installed before running the ``setup`` script.
.. code-block:: bash
@@ -341,31 +367,29 @@ This is only possible for ``pip`` installs.
git checkout -b my-new-feature
cd ..
-The environment is now ready for use, but you need to activate the Python virtual environment
-every time you are using it.
+The environment is now ready for use, but you'll need to activate the Python virtual environment (venv) each time you
+wish to use it.
.. code-block:: bash
# Activate venv
source venv/bin/activate
-Now you can open ESPHome in your IDE of choice (mine is CLion) with the PlatformIO
-addons (see PlatformIO docs for more info). Then develop the new feature with the
-guidelines below.
+Now you can open ESPHome in your IDE of choice (many of us are using `VSCode `__)
+with the PlatformIO addons (see PlatformIO docs for more info) and develop the new feature with the guidelines below.
-All PRs are automatically checked for some basic formatting/code mistakes with Github Actions.
-These checks *must* pass for your PR to be mergeable.
+All PRs are automatically checked and tested for some common formatting/code errors with Github Actions. *These checks*
+**must all pass** *before we will review (and eventually merge) your PR.*
Setting Up Git Environment
--------------------------
-ESPHome's code-base is hosted on GitHub, and contributing is done exclusively through
-"Pull Requests" (PRs) in the GitHub interface. So you need to set up your git environment
-first.
+ESPHome's codebase is hosted on GitHub; contributing is done exclusively through "Pull Requests" (PRs) in the
+GitHub interface. To use this, you need to set up your ``git`` environment first.
-When you want to create a patch for ESPHome, first go to the repository you want to contribute to
-(esphome, etc) and click fork in the top right corner. This will create
-a fork of the repository that you can modify and create git branches on.
+If you want to contribute changes/fixes you've made back to ESPHome, first, go to the repository you want to contribute
+to (``esphome``, for example) and click "fork" in the top right corner. This will create a fork of the repository that
+you can modify and create branches on.
.. code-block:: bash
@@ -396,27 +420,155 @@ a fork of the repository that you can modify and create git branches on.
git push -u origin
# For example: git push -u origin gpio-switch-fix
-Then go to your repository fork in GitHub and wait for a create pull request message to show
-up in the top (alternatively go to branches and create it from there). Fill out the
-Pull Request template outlining your changes; if your PR is not ready to merge yet please
-mark it as a draft PR in the dropdown of the green "create PR" button.
+Submitting a Pull Request
+*************************
+
+After you have pushed your changes to GitHub, go to your repository fork and look for a "create pull request" button
+near the top of the page (or, alternatively, go to branches and create it from there). As you create the PR:
+
+- Complete the Pull Request template:
+
+ - Include a brief (but complete) summary of your changes.
+ - PRs without a descrption/summary of the changes will not be reviewed or merged, although exceptions may
+ occasionally be made for small PRs and/or PRs made by frequent contributors/maintainers.
+ - **Do not delete the template.**
+
+- **Mark your PR as a draft** if it is not ready to be reviewed or merged yet. Your PR should be considered a draft if:
+
+ - You still plan to make more changes to the code/documentation.
+ - Changes have been requested to the PR but you have not completed making (or discussing) the requested changes yet.
+ - You are waiting on feedback from the community and/or maintainers to complete your changes.
+
+ This lets reviewers know that the PR may continue to change so they will not spend valuable time reviewing it until
+ it is ready. We do this because, if a PR is reviewed and then it changes, it must be re-reviewed. Reviewing a single
+ PR multiple times is not a productive use of time and we try as much as possible to avoid doing so.
+
+Review Process
+**************
+
+ESPHome's maintainers work hard to maintain a high standard for its code, so reviews can take some time. At the bottom
+of each pull request you will see the "Github Actions" continuous integration (CI) checks which will automatically
+analyize all code changed in your branch. These checks try to spot (and suggest corrections for) errors. If any CI
+check fails, please look at the Github Actions log and fix all errors that appear there.
+
+**All automated checks must be passing** before a given PR will be reviewed and (eventually) merged!
+
+**When will my PR be reviewed/merged?**
+
+ESPHome is a big project; we encourage everybody to test, review and comment on PRs. Despite this, reviews can (and
+often do) take some time.
+
+**But howwww looonnnggg???**
+
+Small PRs are easier to review and are often reviewed first. If you want your PR to be reviewed (and merged) quickly,
+here are some tips:
+
+- We would rather review ten ten-line PRs than one 100-line PR.
+- Be sure to follow all :ref:`codebase_standards` as you make changes -- when reviewers have to spend time
+ commenting on/correcting your PR because you didn't name variables correctly or didn't prefix member variable
+ accesses with ``this->``, it wastes time we could be using to review other PRs which *do* follow the standards.
+- If you wish to take on a big project, such as refactoring a substantial section of the codebase or integrating
+ another open source project with ESPHome, please discuss this with us on `Discord `__ or
+ `create a discussion on GitHub `__ **before** you do all the work and
+ attempt to submit a massive PR.
+- While we realize it's not *always* possible, avoid submitting PRs which are thousands of lines in size. Such PRs are
+ simply too complex and take excessive amounts of time to review. Break your work into multiple, smaller PRs to make
+ the changes more tenable for reviewers.
+- If you are not sure about how you should proceed with some changes, **please**
+ `discuss it with us on Discord `__ before you go do a bunch of work that we can't (for
+ whatever reason) accept...and then you have to go back and re-do it all to get your PR merged. It's easier to make
+ corrections early-on -- and we want to help you!
+
+.. _prs-are-being-drafted-when-changes-are-needed:
+
+Why Was My PR was Marked as a Draft?
+************************************
+
+If your PR was reviewed and changes were requested, our bot will automatically mark your PR as a draft. This means that
+the PR is not ready to be merged or further reviewed for the moment.
+
+When a PR is marked as a draft, it tells other reviewers that this particular PR is a work-in-progress and it doesn't
+require their attention yet.
+
+Once you have made the requested changes, you can mark the PR as ready for review again by clicking the "Ready for
+review" button:
+
+.. figure:: images/pr-draft-ready.png
+ :align: center
+ :width: 100.0%
+ :alt: The ready for review button in the bottom of a PR in draft mode
+
+Before you click the "Ready for review" button, ensure that:
+
+- You have addressed all requested changes
+- There are no merge conflicts
+- All CI jobs and checks are passing successfully
+
+Once you've clicked the "Ready for review" button, the PR will return to a normal state again and our bot will
+automatically notify the reviewers who requested the changes that the PR is ready to go!
+
+Updating Your Branches
+**********************
+
+Sometimes you'll want (or need) to bring changes that were made in ESPHome's ``dev`` branch back into your (local copy
+of a) branch.
+
+The examples that follow in this section assume that you have:
+
+- already used ``git remote`` to add ``upstream`` as shown earlier, and
+- your feature branch (the branch from which you created your PR) currently checked out
+
+.. _feature_branches:
-**Review Process:** ESPHome's code base tries to have a high code standard. At the bottom
-of the Pull Request you will be able to see the "Github Actions" continuous integration check which
-will automatically go through your patch and try to spot errors. If the CI check fails,
-please see the Github Actions log and fix all errors that appear there. Only PRs that pass the automated
-checks can be merged!
+Feature Branches
+^^^^^^^^^^^^^^^^
-**Catching up with reality**: Sometimes other commits have been made to the same files
-you edited. Then your changes need to be re-applied on top of the latest changes with
-a "rebase". More info `here `__.
+There are a couple of ways you can update your (local) feature branch. The easiest is by clicking the "Update branch"
+button in GitHub:
+
+.. image:: images/update_branch.png
+ :align: center
+ :width: 80.0%
+ :class: light-invert
+
+...then run ``git pull`` to pull these changes back down from GitHub.
+
+If you prefer to do it the command-line/terminal way, you can do this, instead:
+
+.. code-block:: bash
+
+ # Fetch the latest upstream changes
+ git fetch upstream dev
+ # Merge in the changes we fetched above
+ git merge upstream/dev
+
+Your Local Copy of ``dev``
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+As you create new branches for your work, you'll want to be sure they include all of the latest changes from ESPHome's
+``dev`` branch -- it's not a good practice to create a new feature branch from an outdated ``dev`` branch.
+
+For this reason, you'll periodically want to update your local ``dev`` branch. A more detailed explanation can be found
+`here `__, but here's the TL;DR:
.. code-block:: bash
- # Fetch the latest upstream changes and apply them
+ # Fetch the latest upstream changes
git fetch upstream dev
git rebase upstream/dev
+Note that you can use this procedure for other branches, too, such as ``next`` or ``current`` from ``esphome-docs``.
+
+.. warning::
+
+ Using ``git rebase`` will result in your changes having to be *force-pushed* back up to GitHub.
+
+ **Do not force-push** your branch once your PR is being reviewed; GitHub allows reviewers to mark files a "viewed"
+ and, when you force-push, this history **is lost**, forcing your reviewer to re-review files they may have already
+ reviewed!
+
+ If you must update your branch, use a method described in :ref:`feature_branches`, instead.
+
.. _contributing_to_esphome:
Contributing to ESPHome
@@ -427,21 +579,19 @@ Contributing to ESPHome
:width: 60.0%
:class: dark-invert
-This is a guide to contributing to the ESPHome codebase. ESPHome uses two languages for its project:
-Python and C++.
+This is a guide to contributing to the ESPHome codebase. ESPHome uses two languages for its project: Python and C++.
-The user configuration is read, validated and transformed into a custom firmware
-with the Python side of the firmware.
+The Python side of ESPHome reads a YAML configuration file, validates it and transforms it into a custom firmware which
+includes only the code needed to perform as defined in the configuration file.
-The C++ codebase is what's actually running on the ESP and called the "runtime". This part of
-the codebase should first set up the communication interface to a sensor/component/etc. and
-communicate with the ESPHome core via the defined interfaces (like Sensor, BinarySensor, Switch).
+The C++ part of the codebase is what's actually running on the microcontroller; this is called the "runtime". This part
+of the codebase should first set up the communication interface to a sensor/component/etc. and then communicate with
+the ESPHome core via the defined interfaces (like ``Sensor``, ``BinarySensor`` and ``Switch``, among others).
-1. Directory Structure
-**********************
+Directory Structure
+*******************
-After you've :ref:`set up development environment `, you will have a folder structure
-like this:
+After you've :ref:`set up a development environment `, you will have a folder structure like this:
.. code-block:: text
@@ -464,10 +614,10 @@ like this:
│ │ ├── switch.py
│ ...
-As you can see, all components are in the "components" folder. Each component is in its own
-subfolder which contains the Python code (.py) and the C++ code (.h and .cpp).
+All components are in the "components" folder. Each component is in its own subfolder which contains the Python code
+(``.py``) and the C++ code (``.h`` and ``.cpp``).
-Suppose the user types in the following:
+Consider a YAML configuration file containing the following:
.. code-block:: yaml
@@ -476,34 +626,35 @@ Suppose the user types in the following:
sensor:
- platform: hello2
-In both cases, ESPHome will automatically look for corresponding entries in the "components"
-folder and find the directory with the given name. For example the first entry will make ESPHome
-look at the ``esphome/components/hello1/__init__.py`` file and the second entry will result in
-``esphome/components/hello2/sensor.py``.
+In both cases, ESPHome will automatically look for corresponding entries in the "components" folder and find the
+directory with the given name. In this example, the first entry causes ESPHome to look for the
+``esphome/components/hello1/__init__.py`` file and the second entry tells ESPHome to look for
+``esphome/components/hello2/sensor.py`` or ``esphome/components/hello2/sensor/__init__.py``.
-Let's leave what's written in those files for (2.), but for now you should also know that
-whenever a component is loaded, all the C++ source files in the folder of the component
-are automatically copied into the generated PlatformIO project. So you just need to add the C++
-source files in the folder and the ESPHome core will copy them with no additional code required
-by the component developer.
+Let's leave what's written in those files for :ref:`the next section `, but for now you should also
+know that, whenever a component is loaded, all the C++ source files in the folder of the component are automatically
+copied into the generated PlatformIO project. All you need to do is add the C++ source files in the component's folder
+and the ESPHome core will copy them with no additional code required by the component developer.
.. note::
- For testing you can use :doc:`/components/external_components`.
+ For testing, you can use :doc:`/components/external_components`.
ESPHome also has a ``custom_components`` mechanism like `Home Assistant does
- `__. However this is
- discouraged in favor of :doc:`/components/external_components`.
+ `__. Note, however, that
+ **custom componenets are deprecated** in favor of :doc:`/components/external_components`.
-2. Config Validation
-********************
+.. _config_validation:
-The first thing ESPHome does is read and validate the user config. For this ESPHome has a powerful
-"config validation" mechanism. Each component defines a config schema that is validated against
-the user config.
+Config Validation
+*****************
-To do this, all ESPHome Python modules that can be configured by the user have a special field
-called ``CONFIG_SCHEMA``. An example of such a schema is shown below:
+The first task ESPHome performs is to read and validate the provided YAML configuration file. ESPHome has a powerful
+"config validation" mechanism for this purpose. Each component defines a config schema which is used to validate the
+provided configuration file.
+
+To do this, all ESPHome Python modules that can be configured by the user define a special variable named
+``CONFIG_SCHEMA``. An example of such a schema is shown below:
.. code-block:: python
@@ -517,70 +668,71 @@ called ``CONFIG_SCHEMA``. An example of such a schema is shown below:
cv.Optional(CONF_MY_OPTIONAL_KEY, default=10): cv.int_,
}).extend(cv.COMPONENT_SCHEMA)
-This variable is automatically loaded by the ESPHome core and validated against.
+This variable is automatically loaded by the ESPHome core and is used to validate the provided configuration.
The underlying system ESPHome uses for this is `voluptuous `__.
-Going into how to validate is out of scope for this guide, but the best way to learn is to look
-at examples of how similar components validate user input.
+How validation works is out of scope for this guide; the easiest way to learn is to look at how similar components
+validate user input.
-A few point on validation:
+A few notes on validation:
-- ESPHome puts a lot of effort into **strict validation** - If possible, all validation methods should be as strict
- as possible and detect wrong user input at the validation stage (and not later).
-- All default values should be defined in the schema (and not in C++ codebase or other code parts).
-- Config keys should be descriptive - If the meaning of a key is not immediately obvious you should
- always prefer long_but_descriptive_keys.
+- ESPHome puts a lot of effort into **strict validation**. All validation methods should be as strict as possible and
+ detect incorrect user input at the validation stage, mitigating compiler warnings and/or errors.
+- All default values should be defined in the schema -- not in C++ codebase.
+- Prefer naming configuration keys in a way which is descriptive instead of short. Put another way, if the meaning of a
+ key is not immediately obvious, don't be afraid to use ``long_but_descriptive_keys``. There is no reason to use
+ obscure shorthand. As an example, ``scrn_btn_inpt`` is indeed shorter but more difficult to understand, particularly
+ for new users; avoid naming keys and variables in this way.
-3. Code Generation
-******************
+Code Generation
+***************
-After the user input has been successfully validated, the last step of the Python codebase
-is called: Code generation.
+The last step the Python codebase performs is called *code generation*. This runs only after the user input has been
+successfully validated.
-As you may know, ESPHome converts the user's configuration into C++ code (you can see the generated
-code under ``/src/main.cpp``). Each component must define its own ``to_code`` method
-that converts the user input to C++ code.
+As you may know, ESPHome "converts" the user's YAML configuration into C++ code (you can see the generated code under
+``/src/main.cpp``). Each component must define its own ``to_code`` method that "converts" the user input to
+C++ code.
-This method is also automatically loaded and invoked by the ESPHome core. An example of
-such a method can be seen below:
+This method is also automatically loaded and invoked by the ESPHome core. Here's an example of such a method:
.. code-block:: python
import esphome.codegen as cg
- def to_code(config):
+ async def to_code(config):
var = cg.new_Pvariable(config[CONF_ID])
- yield cg.register_component(var)
+ await cg.register_component(var, config)
cg.add(var.set_my_required_key(config[CONF_MY_REQUIRED_KEY]))
-Again, going into all the details of ESPHome code generation would be out-of-scope. However,
-ESPHome's code generation is 99% syntactic sugar - and again it's probably best to study other
-components and just copy what they do.
+The details of ESPHome code generation is out-of-scope for this document. However, ESPHome's code generation is 99%
+syntactic sugar - and (again) it's probably best to study similar components and just copy what they do.
+
+There's one important concept for the ``to_code`` method: coroutines with ``await``.
-There's one important concept for the ``to_code`` method: coroutines with ``yield``.
-First the problem that leads to coroutines: In ESPHome, components can declare (via ``cg.Pvariable``) and access variables
-(``cg.get_variable()``) - but sometimes when one part of the code base requests a variable
-it has not been declared yet because the code for the component creating the variable has not run yet.
+The problem that necessitates coroutines is this: in ESPHome, components can declare (via ``cg.Pvariable``) and access
+variables (``cg.get_variable()``) -- but sometimes, when one part of the codebase requests a variable, it has not been
+declared yet because the code for the component creating the variable has not yet run.
-To allow for ID references, ESPHome uses so-called ``coroutines``. When you see a ``yield`` statement
-in a ``to_code`` method, ESPHome will call the provided method - and if that method needs to wait
-for a variable to be declared first, ``yield`` will wait until that variable has been declared.
-After that, ``yield`` returns and the method will execute on the next line.
+To allow for ID references, ESPHome uses so-called ``coroutines``. When you see an ``await`` statement in a ``to_code``
+method, ESPHome will call the provided method and, if that method needs to wait for a variable to be declared first,
+``await`` will wait until that variable has been declared. After that, ``await`` returns and the method will execute on
+the next line.
-Next, there's a special method - ``cg.add`` - that you will often use. ``cg.add()`` does a very simple
-thing: Any C++ declared in the parentheses of ``cg.add()`` will be added to the generated code.
-If you do not call "add" a piece of code explicitly, it will not be added to the main.cpp file!
+Next, there's a special method - ``cg.add`` - that you will often use. ``cg.add()`` performs a very simple task: Any
+C++ declared in the parentheses of ``cg.add()`` will be added to the generated code. Note that, if you do not call
+"add" to insert a piece of code explicitly, it will not be added to the ``main.cpp`` file!
-4. Runtime
-**********
+Runtime
+*******
-Okay, the Python part of the codebase is now complete - now let's talk about the C++ part of
-creating a new component.
+At this point, the Python part of the codebase has completed its work. Let's move on and discuss the C++ part of
+components.
-The two major parts of any component roughly are:
+Most components consist of two primary parts/steps:
- - Setup Phase
- - Run Phase
+- Setup Phase
+- Run Phase
When you create a new component, your new component will inherit from :apiclass:`Component`.
That class has a special ``setup()`` method that will be called once to set up the component -
@@ -592,83 +744,96 @@ if communication works (if not, it should call ``mark_failed()``).
Again, look at examples of other components to learn more.
-The next thing that will be called with your component is ``loop()`` (or ``update()`` for a
-:apiclass:`PollingComponent`). In these methods you should retrieve the latest data from the
-component and publish them with the provided methods. One thing to note in these methods
-is that anything in ``loop()`` or ``setup()`` **should not block**. Specifically methods like
-``delay(10)`` should be avoided and delays above ~10ms are not permitted. The reason for this
-is that ESPHome uses a central single-threaded loop for all components - if your component
-blocks the whole loop will be slowed down.
+The next method that will be called with your component is ``loop()`` (or ``update()`` for a
+:apiclass:`PollingComponent`). These methods should retrieve the latest data from your component and publish them with
+the provided methods.
+
+Finally, your component must have a ``dump_config`` method that prints the complete user configuration.
+
+A Note About Delays in Code
+***************************
+
+**Code in** ``loop()``, ``update()`` **and** ``setup()`` **must not block**.
-Finally, your component should have a ``dump_config`` method that prints the user configuration.
+Methods like ``delay()`` should be avoided and **delays longer than 10 ms are not permitted**. Because ESPHome uses a
+single-threaded loop for all components, if your component blocks, it will delay the whole loop, negatively impacting
+other components. This can result in a variety of problems such as network connections being lost.
-5. Extras
-*********
+If your code **must** wait for something to happen (for example, your sensor requires hundreds of milliseconds to
+initialize and/or take a reading), then you'll need to implement a state machine to facilitate this. For example, your
+code can send the "take reading" command, return, and, when the next iteration of ``loop()`` or ``update()`` is called,
+it then attempts to read back the measurement from the sensor.
+
+``loop()`` is called every 16 ms (assuming no other components delay this, which may happen from time to time) and
+``update()`` is called at an interval defined in the user configuration for the component, but only for
+:apiclass:`PollingComponent`.
+
+For any :apiclass:`Component` (which is nearly everything), the well-known ``set_timeout`` method is also available;
+this can be a handy alternative to implemeting a state machine.
+
+Extras
+******
.. note::
- This serves as documentation for some of ESPHome's internals and is not necessarily part of the
- development guide.
+ This serves as documentation for some of ESPHome's internals and is not necessarily part of the development guide.
-All Python modules have some magic symbols that will automatically be loaded by the ESPHome
-loader. These are:
+All Python modules have some magic symbols that will automatically be loaded by the ESPHome loader. These are:
- ``CONFIG_SCHEMA``: The configuration schema to validate the user config against.
-- ``to_code``: The function that will be called with the validated configuration and should
- create the necessary C++ source code.
-- ``DEPENDENCIES``: Mark the component to depend on other components. If the user hasn't explicitly
- added these components in their configuration, a validation error will be generated.
+- ``to_code``: The function that will be called with the validated configuration and should create the necessary C++
+ source code.
+- ``DEPENDENCIES``: Mark the component to depend on other components. If the user hasn't explicitly added these
+ components in their configuration, a validation error will be generated.
- ``AUTO_LOAD``: Automatically load a component if the user hasn't added it manually.
-- ``MULTI_CONF``: Mark this component to accept an array of configurations. If this is an
- integer instead of a boolean, validation will only permit the given number of entries.
-- ``CONFLICTS_WITH``: Mark a list of components as conflicting with this component. If the user
- has one of them in the config, a validation error will be generated.
+- ``MULTI_CONF``: Mark this component to accept an array of configurations. If this is an integer instead of a boolean,
+ validation will only permit the given number of entries.
+- ``CONFLICTS_WITH``: Mark a list of components as conflicting with this component. If the user has one of them in
+ their config, a validation error will be generated.
+- ``CODEOWNERS``: GitHub usernames or team names of people that are responsible for this component. You should add at
+ least your GitHub username here, as well as anyone who helped you to write code that is being included.
-- ``ESP_PLATFORMS``: Provide a list of allowed ESP types this component works with.
-- ``CODEOWNERS``: GitHub usernames or team names of people that are responsible for this component.
- You should add at least your GitHub username here, as well as anyone who helped you to write code
- that is being included.
+.. _codebase_standards:
Codebase Standards
------------------
-Standard for the esphome-core codebase:
+ESPHome's maintainers work hard to maintain a high standard for its code. We try our best to adhere to these standards:
- The C++ code style is based on the
`Google C++ Style Guide `__ with a few modifications.
- - function, method and variable names are ``lower_snake_case``
- - class/struct/enum names should be ``UpperCamelCase``
- - constants should be ``UPPER_SNAKE_CASE``
- - fields should be ``protected`` and ``lower_snake_case_with_trailing_underscore_`` (DO NOT use private)
+ - Function, method and variable names are ``lower_snake_case``
+ - Class/struct/enum names should be ``UpperCamelCase``
+ - Constants should be ``UPPER_SNAKE_CASE``
+ - Fields should be ``protected`` and ``lower_snake_case_with_trailing_underscore_`` (DO NOT use ``private``)
- It's preferred to use long variable/function names over short and non-descriptive ones.
- - All uses of class members and member functions should be prefixed with
- ``this->`` to distinguish them from global functions in code review.
+ - All uses of class members and member functions should be prefixed with ``this->`` to distinguish them from global
+ functions/variables.
- Use two spaces, not tabs.
- - Using ``#define`` s is discouraged and should be replaced with constants.
+ - Using ``#define`` is discouraged and should be replaced with constants or enums (if appropriate).
- Use ``using type_t = int;`` instead of ``typedef int type_t;``
+ - Wrap lines in all files at no more than 120 characters. This makes reviewing PRs faster and easier. Exceptions
+ should be made only for lines where wrapping them would result in a syntax issue.
-- New components should dump their configuration using ``ESP_LOGCONFIG``
- at startup in ``dump_config()``
+- Components should dump their configuration using ``ESP_LOGCONFIG`` at startup in ``dump_config()``.
- ESPHome uses a unified formatting tool for all source files (but this tool can be difficult to install).
When creating a new PR in GitHub, see the Github Actions output to see what formatting needs to be changed
and what potential problems are detected.
-
-- The number of external libraries should be kept to a minimum. If the component you're developing has a simple
- communication interface, please consider implementing the library natively in ESPHome.
-
- - This depends on the communication interface of course - if the library is directly working
- with pins or doesn't do any I/O itself, it's ok. However if it's something like I²C, then ESPHome's
- own communication abstractions should be used. Especially if the library accesses a global variable/state
- like ``Wire`` there's a problem because then the component may not modular (i.e. not possible
- to create two instances of a component on one ESP)
-
-- Components **must** use the provided abstractions like ``sensor``, ``switch`` etc.
- Components should specifically **not** directly access other components like for example
- publish to MQTT topics.
-
-- Implementations for new devices should contain reference links for the datasheet and other sample
- implementations.
+- Use of external libraries should be kept to a minimum:
+
+ - If the component you're developing has a simple communication interface, please consider implementing the library
+ natively in ESPHome.
+ - Libraries which directly manipulate pins or don't do any I/O generally do not cause problems.
+ - Libraries which use hardware interfaces (I²C, for example), should be configured/wrapped to use ESPHome's own
+ communication abstractions.
+ - If the library accesses a global variable/state (``Wire`` is a good example) then there's likely a problem because
+ the component may not be modular. Put another way, this approach may mean that it's not possible to create multiple
+ instances of the component for use wihtin ESPHome.
+
+- Components **must** use the provided abstractions like ``sensor``, ``switch``, etc. Components specifically should
+ **not** directly access other components -- for example, to publish to MQTT topics.
+- Implementations for new devices should contain reference links for the datasheet and other sample implementations.
- Please test your changes :)
.. note::
@@ -694,30 +859,6 @@ Standard for the esphome-core codebase:
# Run lint only over changed files from powershell
docker run --rm -v "$($current_dir):/esphome" -it ghcr.io/esphome/esphome-lint script/quicklint
-
-PRs are being drafted when changes are needed
----------------------------------------------
-
-If there have been changes requested to your PR, our bot will automatically mark your PR as a draft.
-This means that the PR is not ready to be merged or further reviewed for the moment.
-
-Draft PRs tell other reviewers that look at the list of all PRs that this PR is currently in progress and doesn't require their attention yet.
-
-Once you have made the requested changes, you can mark the PR as ready for review again by clicking the "Ready for review button":
-
-.. figure:: images/pr-draft-ready.png
- :align: center
- :width: 100.0%
- :alt: The ready for review button in the bottom of a PR in draft mode
-
-Before you click the "Ready for review" button, ensure you have addressed all requested changes,
-there are no merge conflicts, and that all our CI jobs and checks are passing successfully.
-
-Once you've clicked the "Ready for review" button, the PR will return to a normal state again,
-and our bot will automatically notify the reviewers who requested the changes that the PR is ready to go!
-
-
-
See Also
--------
diff --git a/guides/getting_started_hassio.rst b/guides/getting_started_hassio.rst
index 838d421684..8e18d2fb0d 100644
--- a/guides/getting_started_hassio.rst
+++ b/guides/getting_started_hassio.rst
@@ -7,8 +7,7 @@ Getting Started with ESPHome and Home Assistant
In this guide we’ll go through how to install ESPHome on a device using the ESPHome Dashboard, installed as a Home Assistant add-on.
-But first, here's a very quick introduction to how ESPHome works:
-ESPHome is a *tool* which aims to make managing your ESP boards as simple as possible. It reads in a YAML configuration file and creates custom firmware which it installs on your ESP device. Devices or sensors added in ESPHome's configuration will automatically show up in Home Assistant's UI.
+First, here's a very quick introduction to how ESPHome works. ESPHome is a tool that aims to simplify managing your supported devices. It reads a YAML configuration file, creates custom firmware, and can install it on your device. Any devices or sensors defined in the ESPHome configuration will automatically appear in Home Assistant's user interface.
Installing ESPHome Dashboard
----------------------------
diff --git a/guides/images/update_branch.png b/guides/images/update_branch.png
new file mode 100644
index 0000000000..9d375fdea4
Binary files /dev/null and b/guides/images/update_branch.png differ
diff --git a/guides/supporters.rst b/guides/supporters.rst
index 45e36e3976..2a7385f247 100644
--- a/guides/supporters.rst
+++ b/guides/supporters.rst
@@ -28,6 +28,7 @@ Contributors
- `David Martin (@3ative) `__
- `3VAbdAVE (@3VAbdAVE) `__
- `Vincent (@4xvince) `__
+- `Alexandre Detiste (@a-detiste) `__
- `Alessandro Campolo (@a13ssandr0) `__
- `Aalian Khan (@AalianKhan) `__
- `Adam Liddell (@aaliddell) `__
@@ -38,6 +39,7 @@ Contributors
- `Abel Matser (@abelmatser) `__
- `Abílio Costa (@abmantis) `__
- `Antonio (@acarvajalperez) `__
+- `Angel Cascarino (@ACascarino) `__
- `aceindy (@aceindy) `__
- `Avula Chandra Kiran Reddy (@ackr-8) `__
- `Alex Cortelyou (@acortelyou) `__
@@ -126,6 +128,7 @@ Contributors
- `Anthony (@AnthonyMaiorani) `__
- `Rémi K. (@antibill51) `__
- `Antonio Fiol (@antonio-fiol) `__
+- `Anton Verburg (@antonverburg) `__
- `Aodren Auffrédou-Heinicke (@aodrenah) `__
- `Andy Barratt (@apbarratt) `__
- `Andrey Bodrov (@apbodrov) `__
@@ -226,6 +229,7 @@ Contributors
- `blindguynar (@blindguynar) `__
- `BlueSkyB (@BlueSkyB) `__
- `Scott Smith (@blurfl) `__
+- `Blake (@bmatheny) `__
- `Bruno Medici (@bmedici) `__
- `Bob (@Bmooij) `__
- `Benjamin Klotz (@bnw) `__
@@ -247,6 +251,7 @@ Contributors
- `Brandan Cotton (@Brando47) `__
- `Brad Davidson (@brandond) `__
- `Daniel H Brown (@brauhausdc) `__
+- `Brennan Magee (@BrennanGit) `__
- `Brent Rubell (@brentru) `__
- `Jens Bretschneider (@breti) `__
- `Brett Profitt (@brettp) `__
@@ -360,6 +365,7 @@ Contributors
- `Corey Rice (@crice009) `__
- `crp500 (@crp500) `__
- `cryptelli (@cryptelli) `__
+- `cs-xm (@cs-xm) `__
- `Christian Schwarzgruber (@cslux) `__
- `cstaahl (@cstaahl) `__
- `Chris Talkington (@ctalkington) `__
@@ -525,6 +531,7 @@ Contributors
- `Earle F. Philhower, III (@earlephilhower) `__
- `Ermanno Baschiera (@ebaschiera) `__
- `ebw44 (@ebw44) `__
+- `Ed (@ed-xmos) `__
- `Robert Resch (@edenhaus) `__
- `Niclas Larsson (@edge90) `__
- `EdJoPaTo (@EdJoPaTo) `__
@@ -596,6 +603,7 @@ Contributors
- `Sun Xiangyu (@feizi) `__
- `felixlungu (@felixlungu) `__
- `Felix Storm (@felixstorm) `__
+- `felixstorm-c4a8 (@felixstorm-c4a8) `__
- `Christian Ferbar (@ferbar) `__
- `ferbulous (@ferbulous) `__
- `Federico Ferretti (@ferrets6) `__
@@ -690,6 +698,7 @@ Contributors
- `Oleh Hordiienko (@gordio) `__
- `gordon-zhao (@gordon-zhao) `__
- `Gustavo Ambrozio (@gpambrozio) `__
+- `Geert de Graaf (@GraafG) `__
- `Graham Brown (@grahambrown11) `__
- `Granville Barker (@granvillebarker) `__
- `Antoine GRÉA (@grea09) `__
@@ -841,6 +850,7 @@ Contributors
- `JbLb (@jblb) `__
- `Jonathan Burns (@jburns20) `__
- `James Callaghan (@jcallaghan) `__
+- `Jon Carrier (@jcarrier-xmos) `__
- `Jc Miñarro (@JcMinarro) `__
- `Josh Willox (@jcwillox) `__
- `Joshua Dadswell (@jdads1) `__
@@ -860,6 +870,7 @@ Contributors
- `Jérôme Laban (@jeromelaban) `__
- `Jesse Hills (@jesserockz) `__
- `Jessica Hamilton (@jessicah) `__
+- `Andrzej Skowroński (@jesterret) `__
- `J.G.Aguado (@JGAguado) `__
- `James Szalay (@jgissend10) `__
- `Joel Goguen (@jgoguen) `__
@@ -894,6 +905,7 @@ Contributors
- `John Erik Halse (@johnerikhalse) `__
- `John Moxley (@johnmoxley) `__
- `John White (@johnpwhite) `__
+- `johnshaferXMOS (@johnshaferXMOS) `__
- `Dave Johnston (@johnsto) `__
- `joiboi (@joiboi) `__
- `JonasEr (@JonasEr) `__
@@ -951,6 +963,7 @@ Contributors
- `Keith Burzinski (@kbx81) `__
- `Ken Piper (@Kealper) `__
- `kecajtop (@kecajtop) `__
+- `keithm-xmos (@keithm-xmos) `__
- `Tom Keller (@kellertk) `__
- `Kelvie Wong (@kelvie) `__
- `Kenny Stier (@KennyStier) `__
@@ -975,6 +988,7 @@ Contributors
- `Marcus Klein (@kleini) `__
- `klenaers (@klenaers) `__
- `Kevin Lewis (@kll) `__
+- `kmoulton (@kmoulton) `__
- `KNXBroker (@KNXBroker) `__
- `KoenBreeman (@KoenBreeman) `__
- `Koen Vervloesem (@koenvervloesem) `__
@@ -1045,6 +1059,7 @@ Contributors
- `lingex (@lingex) `__
- `Markus (@Links2004) `__
- `LinusHeu (@LinusHeu) `__
+- `lkindrat-xmos (@lkindrat-xmos) `__
- `lkomurcu (@lkomurcu) `__
- `Luis Andrade (@llluis) `__
- `loadrunner42 (@loadrunner42) `__
@@ -1052,10 +1067,12 @@ Contributors
- `Lode Vermeiren (@lodev) `__
- `Barry Loong (@loongyh) `__
- `Michael Bisbjerg (@LordMike) `__
+- `lorenzspenger (@lorenzspenger) `__
- `LuBeDa (@lubeda) `__
- `Lukáš Maňas (@LucasCZE) `__
- `Lucas Prim (@lucasprim) `__
- `Lucas Reiners (@lucasreiners) `__
+- `Luciano Martin (@lucianomartin) `__
- `Joakim Sørensen (@ludeeus) `__
- `ludrao (@ludrao) `__
- `Luiz Correia (@luizcorreia) `__
@@ -1072,6 +1089,7 @@ Contributors
- `Luke Fitzgerald (@lwfitzgerald) `__
- `Lewis Juggins (@lwis) `__
- `Alex Peters (@Lx) `__
+- `lyj (@lyj0309) `__
- `Linar Yusupov (@lyusupov) `__
- `Michael Klamminger (@m1ch) `__
- `M3C-Owx (@M3C-Owx) `__
@@ -1143,7 +1161,9 @@ Contributors
- `Christian (@max246) `__
- `Max Bachmann (@maxbachmann) `__
- `Maximilian Gerhardt (@maxgerhardt) `__
+- `Michael Banther (@mbanth) `__
- `mbo18 (@mbo18) `__
+- `Jack McCrea (@McCrea) `__
- `mckaymatthew (@mckaymatthew) `__
- `mcmuller (@mcmuller) `__
- `Miguel Diaz Gonçalves (@mdiazgoncalves) `__
@@ -1306,6 +1326,7 @@ Contributors
- `Zvonimir Haramustek (@nitko12) `__
- `Nixspers (@Nixspers) `__
- `Dennis (@Nizzle) `__
+- `nkinnan (@nkinnan) `__
- `Nikolay Kitanov (@nkitanov) `__
- `nldroid (@nldroid) `__
- `Nicolas Liaudat (@nliaudat) `__
@@ -1397,6 +1418,7 @@ Contributors
- `Peter Galantha (@peterg79) `__
- `Peter Halicky (@peterhalicky) `__
- `Peter Polacek (@PeterPolacek) `__
+- `peterv99 (@peterv99) `__
- `Peter Remøy Paulsen (@petrepa) `__
- `Peter Kieser (@pfak) `__
- `Lee (@phatone007) `__
@@ -1616,6 +1638,7 @@ Contributors
- `sherbang (@sherbang) `__
- `Shish (@shish) `__
- `Shreyas Karnik (@shreyaskarnik) `__
+- `shuchitak (@shuchitak) `__
- `sibowler (@sibowler) `__
- `signix (@signix) `__
- `SiliconAvatar (@SiliconAvatar) `__
@@ -1664,6 +1687,7 @@ Contributors
- `Stefan (@stefanroelofs) `__
- `stegm (@stegm) `__
- `Stephen Papierski (@stephenpapierski) `__
+- `Stephen Armitage (@stevearmitage) `__
- `Steve Baxter (@stevebaxter) `__
- `Steven Hack (@steven-hack) `__
- `Stewart (@stewiem2000)