[rs485_frame] a generic, YAML-declarative engine for DLE/STX/ETX byte-stuffed framed serial buses#6719
Open
b3nj1 wants to merge 1 commit into
Open
[rs485_frame] a generic, YAML-declarative engine for DLE/STX/ETX byte-stuffed framed serial buses#6719b3nj1 wants to merge 1 commit into
b3nj1 wants to merge 1 commit into
Conversation
15 tasks
✅ Deploy Preview for esphome ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Author
|
@esphomebot generate image rs485_frame |
Adds a new `rs485_frame` component: a generic, YAML-declarative engine for **DLE/STX/ETX byte-stuffed framed serial buses** (the framing family used by Hayward AquaLogic/ProLogic, Jandy AquaLink RS, and many other RS485 controllers). The idea grew out of ESPHome's existing serial tooling — the Serial Proxy in particular sparked it — and aims to complement that work by adding a piece that today usually lives in custom C++: reassembling byte-stuffed frames, validating a configurable CRC variant, and scheduling half-duplex transmits gated on a received frame, all declaratively from YAML. The component provides: - **RX framing engine** — DLE byte-stuffed frame reassembly with escape unwrapping, an intra-frame timeout that recovers from mid-frame cable pulls/noise, and `max_frame_length` bounding. All scratch buffers are pre-reserved in `setup()`; the receive path performs no heap allocation. - **Configurable CRC** — `none` / `sum8` / `sum16` / `xor8` / `crc16_modbus`, each selectable as header-inclusive or payload-only, with RX able to accept either coverage. - **Half-duplex TX scheduling** — three gate modes (`frame_trigger`, `idle_gap`, `fixed_delay`), a pre-reserved allocation-free TX ring buffer (`replace_latest` / `fifo`), and optional `idle_command` keepalives. - **`on_frame:` triggers** with multi-prefix `frame_type` matching, so all RX payload decoding is done in user YAML/lambdas (no per-protocol C++). - **`command_format:`** — a data-driven command encoder (preamble / command_size / endianness / repeat / postamble) that expresses every supported protocol's command layout as YAML data, plus a templatable `rs485_frame.send_frame` action for arbitrary frames. - **Platforms:** `button` (raw-frame or `command:` form), `number` (lambda encoder), `sensor` / `text_sensor` (hub diagnostics: frames received, CRC failures, commands sent/dropped, queue depth, keepalive interval, last frame type). - **Optional `sniffer_stats:`** diagnostic (compiled out entirely unless configured via `USE_RS485_FRAME_SNIFFER_STATS`) that buckets RX frames by type and logs cadence and unique-payload histograms — useful for reverse-engineering an unknown bus. - **Optional `discovery:`** mode (compiled out entirely unless configured via `USE_RS485_FRAME_DISCOVERY`) that turns the hub into a passive analyzer for a completely unknown bus: it captures raw bytes, segments them by idle gap, and reports the candidate framing bytes, escape scheme, and CRC variant, gated by a configurable framing-confidence threshold. An optional `baud_sweep` cycles the UART through candidate baud rates and data-bit widths (runtime UART reconfiguration on ESP-IDF and ESP8266) and locks onto the best-scoring setting, then prints a ready-to-paste `uart:`/`framing:` block. Discovery and `sniffer_stats:` are mutually exclusive (discovery bypasses the validated-frame path). There are **no built-in device profiles**. The component is a single generic engine configured explicitly (framing bytes, required `crc:`, `command_format:`, `tx.gate`), which keeps all vendor specifics out of the codebase. Ready-to-flash configurations for specific controllers (e.g. Hayward AquaLogic) live in a separate community [examples repository](https://github.com/b3nj1/rs485_frame-examples) rather than in core. The discovery and sniffer features are what let a user go from "unknown bus" to a working config without prior protocol knowledge. For a worked end-to-end example, see this [annotated Hayward AquaLogic capture](https://github.com/b3nj1/rs485_frame-examples/blob/main/captures/hayward-aqualogic-20260529.md): it walks a real bus from `discovery:` + baud sweep (auto-detecting 19200 8-data-bit framing and the `sum16` CRC), through the `sniffer_stats:` frame-type table on an idle bus and under live remote commands, to decoded frames — every CRC verified by hand.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Pull request in esphome with YAML changes (if applicable):
Documentation for a new esphome component added in above PR:
Adds a new
rs485_framecomponent: a generic, YAML-declarative engine for DLE/STX/ETX byte-stuffedframed serial buses (the framing family used by Hayward AquaLogic/ProLogic, Jandy AquaLink RS, and
other RS485 controllers). It grew out of ESPHome's existing serial tooling, the Serial Proxy in
particular, and complements that work by adding a layer that today usually lives in custom C++:
reassembling byte-stuffed frames, validating a configurable CRC, and scheduling half-duplex transmits
gated on a received frame, all declaratively from YAML.
Checklist
I am merging into
nextbecause this is new documentation that has a matching pull-request in esphome as linked above.or
I am merging into
currentbecause this is a fix, change and/or adjustment in the current documentation and is not for a new component or feature.Link added in
/src/content/docs/components/index.mdxwhen creating new documents for new components or cookbook.New Component Images
If you are adding a new component to ESPHome, you can automatically generate a standardized black and white component name image for the documentation.
To generate a component image:
Comment on this pull request with the following command, replacing
component_namewith your component name in lower_case format with underscores (e.g.,bme280,sht3x,dallas_temp):The ESPHome bot will respond with a downloadable ZIP file containing the SVG image.
Extract the SVG file and place it in the
/public/images/folder of this repository.Use the image in your component's index table entry in
/src/content/docs/components/index.mdx.Example: For a component called "DHT22 Temperature Sensor", use:
Note: All images used in ImgTable components must be placed in
/public/images/as the component resolves them to absolute paths.