|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
IO-Homecontrol covers a wide range of motors and actuators, and every model can behave slightly differently during pairing — different discovery commands, timings, or radio settings. Nobody can test against every device in the field, so getting pairing to work reliably on a specific device sometimes needs per-device fine-tuning.
The tuning: block exists for exactly that. It exposes the pairing and radio parameters that are normally fixed, so you can experiment on a stubborn device and find a working combination — then copy that combination back into your configuration.
Add a tuning: block under home_io_control: and set ui_controls: true:
home_io_control: node_id: "C0FFEE" system_key: "..." tuning: ui_controls: true
ui_controls: true exposes every parameter as a Home Assistant number or select entity, so you can change values live from the UI without reflashing for each experiment. The entities appear under the device's Configuration section, grouped into Radio … and Pairing … names.
Turn on verbose logging. Set the logger to DEBUG so you can see the pairing exchange and the raw packet capture:
At boot and at the start of every pairing attempt, the component logs the active overrides:
or, when nothing is overridden:
Each UI change is also logged in YAML-compatible form, ready to paste back:
Parameters fall into two groups: the radio / physical layer (how the chip transmits and receives) and the pairing protocol (which frames are sent and how the hub waits for answers). The Radio column shows which chip a parameter affects — a chip-specific parameter (SX1262, SX1276, or LR1121) is ignored on any other chip's boards; both applies everywhere.
Each parameter below has a short What we've seen note. These summarise concrete behaviour observed while getting pairing to work — treat them as starting hints, not guarantees, because your device may differ.
| Parameter | Radio | Default | Range / options | What it does |
|---|---|---|---|---|
| sx1262_rx_bandwidth | SX1262 | 58.6 | 39.0 / 46.9 / 58.6 / 78.2 / 117.3 / 156.2 / 187.2 (kHz) | Receiver bandwidth (double-sideband). Widen it when one device's replies are missed. |
| sx1262_response_preamble | SX1262 | 8 | 8–256 B | Preamble length on reply frames, for the peer to lock on. |
| sx1262_post_tx_settle_us | SX1262 | 500 | 0–2000 µs | Settling delay after TX before switching back to RX. |
| sx1276_rx_bandwidth | SX1276 | 41.7 | 20.8 / 41.7 / 62.5 / 83.3 / 125.0 (kHz) | Receiver bandwidth (single-sideband, so 41.7 spans 83.4 kHz); wider tolerates LO offset, narrower rejects more noise. |
| sx1276_response_preamble | SX1276 | 12 | 8–256 B | Preamble length on reply frames, for the peer to lock on. |
| sx1276_discovery_hop_slice_ms | SX1276 | 5 | 5–200 ms | Per-channel dwell for any hopping listen — discovery and the scan_paired_devices roll-call alike. |
| sx1262_discovery_hop_slice_ms | SX1262 | 7 | 0–500 ms | Per-channel dwell for any hopping listen — discovery and the scan_paired_devices roll-call alike. |
| exchange_start_response_wait_ms | both | 400 | 200–4000 ms | How long to listen for a reply to a start frame (the first frame of a command). |
| exchange_response_wait_ms | both | 500 | 200–4000 ms | How long to listen for a reply to a continuation frame, and for the post-auth final response. |
| exchange_total_budget_ms | both | 2500 | 500–12000 ms | Wall-clock ceiling on one whole exchange, including retries. |
| lr1121_rx_bandwidth | LR1121 | 117.3 | 39.0 / 46.9 / 58.6 / 78.2 / 117.3 / 156.2 / 187.2 (kHz) | Receiver bandwidth (double-sideband). 117.3 is validated on real LR1121 hardware. |
| lr1121_response_preamble | LR1121 | 8 | 8–256 B | Preamble length on reply frames, for the peer to lock on. |
| lr1121_post_tx_settle_us | LR1121 | 500 | 0–2000 µs | Settling delay after TX before switching back to RX. |
| lr1121_discovery_hop_slice_ms | LR1121 | 7 | 0–500 ms | Per-channel dwell for any hopping listen — discovery and the scan_paired_devices roll-call alike. |
| cold_broadcast_reply_preamble | both | 80 | 8–256 B | Preamble length for the key-extraction responder's discovery reply (0x29) — the one reply a hopping peer has to catch cold. |
| normal_start_preamble | both | 48 on SX1262/LR1121, 32 on SX1276 | 8–256 B | Preamble length for a directed start frame to a device not declared low_power: — an always-alive receiver that does not need the 1024-byte wake-up burst. Low-power devices lead with LONG_PREAMBLE unless `low_power_wake_belief` believes them awake. Also governs a 1W oneway_controllers: identity's non-wake-up copies when its own low_power: is false or true (unset keeps 1W on LONG_PREAMBLE — see Sending 1W commands). |
| low_power_wake_belief | both | true | true / false | Diagnostic switch. On, a low_power: device that was recently moving or heard from gets the short start preamble on its first try; off, every try uses the 1024-byte wake-up preamble. See below. |
| lbt_max_retries | both | 5 | 0–10 | Listen-before-talk carrier-sense attempts before TX. |
| lbt_rssi_threshold_dbm | both | -90 | -95 to -70 dBm | RSSI below which the channel counts as free. |
| pairing_discovery_commands | both | ["0x28"] | ordered list of 0x28 / 0x2E | Which discovery command(s) to send, and in what order. |
| pairing_discovery_destination | both | auto | auto / 0x00003B / 0x00003F / 0x0001BB / 0x0001BF | Address the discovery frames are sent to. The last two are lighting-class addresses — see below. |
| pairing_discovery_payload | both | none | none / 0x00 | Optional payload byte (used by the alternate command). |
| pairing_discovery_low_power | both | false | true / false | Sets the LOW_POWER flag in discovery frames. |
| pairing_discovery_ack_capable | both | false | true / false | Sets the ACK (CTRL1_ACK) flag on the discovery broadcast only. Off by default — see note below. |
| pairing_discovery_wait_ms | both | 2000 | 500–5000 ms | How long to wait for a response after each discovery TX. Also the per-attempt listen window for each of the scan_paired_devices roll-call's attempts (up to six: three per power class). |
| pairing_discovery_initial_dwell_ms | both | 300 | 0–500 ms | Settle delay before the first discovery TX. |
| pairing_key_exchange_retries | both | 3 | 1–5 | Retries for the authenticated key-exchange phase. |
| scan_power_classes | both | both | both / always_alive / low_power | Which device power classes the scan_paired_devices roll-call calls. |
| pairing_discover_confirm | both | send | skip / send / send_with_ack | Whether/how to send DISCOVER_CONFIRM (0x2C) to a freshly-discovered device before the key exchange. |
| pairing_key_init_delay_ms | both | 300 | 0–10000 ms | Pause after the discover-confirm step (ACKed, refused, or silent) and before KEY_INIT (0x31). |
| pairing_discovery_listen_channels | both | skip_request | skip_request / all | Which channels the wait for a discovery response covers. |
ui_controls itself is a feature toggle (default false) that exposes these as entities; it is not a tunable.
GFSK receiver bandwidth on the SX1262. Change it when frames arrive but fail to decode — the did not parse as a frame warnings in the log are a direct count of that.
The values are double-sideband: the total width of the filter, centred on the hub's own frequency. Semtech sizes a GFSK filter as bitrate + 2 × deviation + carrier offset, which is 76.8 kHz for this waveform before any offset. The SX1262 has no automatic frequency correction in this mode, so the filter alone has to absorb how far a device's transmitter sits from nominal.
Observations: 58.6 kHz is the default. It is below the 76.8 kHz figure, so it trims the edges of even an on-frequency signal, but it made a Somfy RS100 solar shutter respond reliably where 117.3 did not. A device whose transmitter sits off nominal needs the opposite: a Somfy LightVar_Wh_io dimmer went from mostly missed replies to 9 of 11 commands confirmed at 156.2, with 117.3 and 187.2 both worse in the same test (issue #119). The setting applies to every device, so pick the value your least cooperative device needs and check that the others still answer.
If one device's replies are missed — wait_first_timeout, or a challenge that arrives without its final response — while other devices are fine, try 117.3 and 156.2. 39.0 and 46.9 are well below the 76.8 kHz figure; use them only to probe a noisy install.
How long a preamble the SX1262 puts in front of its reply frames (the key-transfer and authentication responses), giving the peer time to lock on after the hub transmits. Raise it when key exchange stalls right after discovery on an SX1262 board, especially with a device that has never been paired before.
Observations: the SX1262's modulation is marginal for short preambles on the fast post-TX turnaround. Already-paired devices lock onto an on-air preamble of 8 bytes reliably. Brand-new devices often fail to decode on-air preambles of 1/4/8 bytes and need something substantially longer — exactly how much, up to the protocol's full 1024-byte long preamble, has not yet been independently validated on this chip, so treat any specific number above 8 as untested rather than known-good. The same "not below the tens of bytes" caution is why normal_start_preamble (below) defaults to 32 rather than 8.
How long the SX1262 waits after transmitting before switching back to receive. Increase it when fast replies (the challenge or key frames) arrive corrupted.
Observations: experiments here established ~500 µs as the minimum that keeps the demodulator from mangling the first bytes of a quick reply after the transmit→standby→receive transition. It works hand-in-hand with bandwidth — a narrower bandwidth generally wants a longer settle.
How long the hub listens for a device's reply before giving up on a try. Raise exchange_start_response_wait_ms when a device ignores commands but is known to be in range and correctly paired.
Observations: for this device class, reply latency is fast-or-never rather than variably slow — a device answers within a few milliseconds of the carrier dropping, or it does not answer at all. A failure therefore shows up as no frame received rather than as a late arrival, so raising this value cannot fix a device that genuinely fails to respond; check wait_ms in the logs first. The 400 ms default sits comfortably above every directly measured reply from this device class while keeping a failed exchange inside exchange_total_budget_ms. Raise it only for a device you have confirmed genuinely answers late.
Every millisecond here is loop-blocking time on a failed exchange only (a successful one returns as soon as the reply lands, see ADR 0013), and a failure costs this window once per retry. Raise it for a stubborn device; lower it if slow failures are worse for you than missed commands.
Wall-clock ceiling on one whole exchange, including retries. exchange_start_response_wait_ms and exchange_response_wait_ms set how long each try waits; this caps how long all of them together may run, so a try only starts if there is still budget left for it.
Observations: this exists to keep a failing command from blocking the ESPHome loop past its own "took a long time for an operation" warning threshold (2550 ms — see ADR 0013). If you raise either response-wait parameter, raise this too, or later retries within the same command will silently be skipped once the budget runs out.
GFSK receiver bandwidth on the SX1276, written to both the RX and AFC bandwidth registers. Change it when discovery or key-exchange replies fail to decode cleanly on an SX1276 board.
Observations: the values are single-sideband — half the filter's total width — so the default 41.7 kHz spans 83.4 kHz, just above the 76.8 kHz Semtech sizing figure for this waveform, and is validated against real devices. The SX1276 also re-centres on each packet's carrier automatically, which absorbs a device's frequency offset that the SX1262 cannot. It has worked reliably at this default across the devices tested here, so this knob is exposed for marginal-range or drifting installs rather than because a change was needed. Widen it (62.5/83.3/125.0) when a device's transmitter drifts more than the controller's radio, at the cost of admitting more noise; narrow to 20.8 for maximum noise rejection on a clean signal.
How long a preamble the SX1276 puts in front of its reply frames (the key-transfer and authentication responses), giving the peer time to lock on after the hub transmits. Raise it if key exchange stalls right after discovery on an SX1276 board.
Observations: the default here is 12 bytes — longer than the protocol's 8-byte short preamble, which on hardware measurably improves the peer's lock-on at no timing cost. That is also longer than the SX1262's 8 (see the SX1262 section above: brand-new devices needed noticeably more than that on the SX1262, so don't read the SX1276's smaller number as evidence 12 is generous; it has never needed raising in testing here). Lengthen it further for a stubborn or marginal-range device.
How long the receiver dwells on each channel while hopping. This governs every rotating listen in the project, not just discovery: pairing discovery and the scan_paired_devices broadcast roll-call both rotate across channels and both fall back to this value when they have no loop-specific reason to dwell differently (neither does today). Change it when a device is clearly present but its discovery response, or its roll-call reply, is never caught.
Observations: because a device often answers on a different channel than the request was sent on, hopping during the wait is essential — a hop slice that never rotates would miss it. Both chips dwell only a few milliseconds per channel and extend the dwell when a preamble or sync word is detected, so a caught reply is not cut off mid-retune: the SX1276 uses a naturally fast hop cycle, and a short SX1262 dwell fits more retunes into the same window, so the receiver is more often already on the right channel when a reply starts. The floor of 0 is not a physically meaningful minimum for the chip — coverage degrades gradually below the low single digits and only collapses at the literal 0, where wait_for_packet(..., 0) returns before anything can be observed at all — so it is left open as an experimentally checkable floor rather than assumed. Values near that floor are for probing it, not for everyday tuning.
The LR1121 equivalents of the four SX1262 knobs above — same meaning (lr1121_discovery_hop_slice_ms governs the roll-call as well as discovery, same as its SX1262/SX1276 counterparts), same register-level reasoning (the LR1121's GFSK bandwidth encoding is register-identical to the SX1262's, and it needs the same standby→retune→RX hop cycle, no fast hop). Three of the four share SX1262's default values (lr1121_response_preamble, lr1121_post_tx_settle_us, lr1121_discovery_hop_slice_ms); lr1121_rx_bandwidth instead keeps its own wider default, 117.3 kHz, which clears the 76.8 kHz sizing figure and is validated on this chip. lr1121_discovery_hop_slice_ms is measured independently on LR1121 rather than merely inherited, since the two chips are validated separately and could in principle diverge.
Observations: the defaults were seeded from SX1262's validated values and are confirmed working on real LR1121 hardware — authenticated open/close/stop exchanges complete reliably against a real awning at the stock settings. The main variable that still matters in practice is RF link quality (RSSI) rather than these timing/bandwidth knobs — weak signal shows up as intermittent frame loss on either leg of an exchange, which the existing per-command retry already absorbs.
Sized independently of response_preamble(): it governs only the "Recover System Key" feature's discovery reply (0x29), the sole device-role reply that is start=true and therefore the one a hopping/scanning peer has to catch cold, rather than a peer already parked on a held channel.
The preamble in front of a directed start frame (EXECUTE, status poll, GET_NAME, rename, identify, probe) whose target is not declared low_power:. An always-listening receiver does not need the ~213 ms 1024-byte wake-up burst, and some receivers never lock onto one that long — so a normal start frame gets this shorter preamble, matching what real hubs send to an always-alive device. A device declared low_power: true keeps LONG_PREAMBLE on its start frames unless it is believed awake — see `low_power_wake_belief`.
The default depends on your radio. An SX1262 or LR1121 board starts at 48 bytes, an SX1276 board at 32 (ADR 0042). The software PHY those two chips share puts less usable preamble on air than its programmed length suggests: measured against a Somfy dimmer, an SX1262 was answered on the first try 79% of the time at 32 bytes and every time at 48, while an SX1276 sending the same programmed 32 was answered every time. The config dump in your logs prints the value it resolved and whether it came from YAML or the radio.
Setting this key yourself always wins, including a value below the default — useful if you are bisecting a reception problem and want to see where your own device stops answering.
The same value governs a 1W identity's non-wake-up copies once its own low_power: is set to false or true — see Sending 1W commands. Left unset, an identity keeps LONG_PREAMBLE on every copy regardless of this setting.
Sized independently of response_preamble() (that knob is a per-chip TX→RX turnaround property; this is a cold-peer property). The 32-byte default is 256 bits, well inside the range real hubs use; drop it toward 8 only if a start frame is still not being heard and raise it toward LONG_PREAMBLE if a marginal always-alive link needs more. Because it is a live tuning knob, bisecting the right value needs no rebuild.
A diagnostic switch, on by default. If a device declared low_power: true got worse after updating, set this to false and report it.
A duty-cycled receiver that is asleep needs the 1024-byte wake-up preamble. One that is awake — a VELUX solar roller shutter mid-travel, for example — ignores that long preamble and answers only the short one, so a stop or status poll sent to a moving shutter with the long preamble goes unanswered. With this on, the hub tracks per device whether it was recently moving or heard from, and orders the tries of each directed exchange accordingly:
| Believed | Try 1 | Try 2 | Try 3 |
|---|---|---|---|
| awake (a stop, or a move the device accepted in the last 2 minutes that is not yet known to have ended) | short | wake-up | short |
| maybe awake (heard from in the last 30 s) | short | wake-up | wake-up |
| asleep | wake-up | wake-up | wake-up |
"Short" is `normal_start_preamble`. A wrong belief costs one try, not the exchange, because every plan still sends the wake-up preamble at least once. A status poll allowed only one try (most scheduled polls) sends the first try's preamble; if it misses, the next poll a few seconds later has three tries. The poll right after an accepted stop always gets all three. Always-alive devices are unaffected, and the frame itself never changes between tries.
To see which preamble reaches a device how soon after it last answered, read the per-try log lines. Each carries preamble= (bytes) and age_ms= (time since the device was last heard; n/a when it never was, or the switch is off):
Off restores the old behaviour: the wake-up preamble on every try to a low_power: device.
Listen-Before-Talk: before transmitting, the hub checks the channel is quieter than the threshold, retrying up to max_retries times, then transmits anyway. Loosen them when transmissions are delayed on a channel that only looks busy. The threshold applies to the signal level at the antenna: on a board with a front-end module the amplifier's gain is removed from the reading first (see Hardware), so the same value means the same on every board.
Observations: a device's own pairing-mode beacons made the channel read as busy (around -77 to -83 dBm), which tripped every LBT retry before each discovery transmit and slowed pairing noticeably. Raising the threshold (less sensitive) or lowering the retry count lets the hub transmit through that.
Which discovery command(s) the hub broadcasts, and in what order; it sends them in sequence and stops at the first device response.
0x2A (SPE roll-call) is not an option here, on purpose. It looks superficially similar — authenticated with the configured system_key, broadcast to 0x00003B — but only devices that already hold your key answer it. A device sitting in learning mode, waiting to be paired, holds no key yet and stays silent. So adding it to this list cannot help a pairing attempt succeed; it would only add replies from devices you have already paired. It is a "who is still out there" roll-call over your existing devices — a different question entirely from "who wants to pair".
If a "who is still out there" roll-call over your already-paired devices is what you actually want, that is exactly what the scan_paired_devices hub action does — see Home Assistant actions.
Observations: plain 0x28 to 0x00003B is what works. Broadcast 0x2E has drawn no response on every device this project has real hardware evidence for — a Somfy Izymo dimmer and a Velux KLR200/KUX100 pair both went unanswered (see the CMD_DISCOVER_ALT_REQ doc comment in proto_constants.h, and GitHub issue #27 where two independent reporters also tried it with no result). It only draws a response when addressed directly to an already-known node ID, which is no help for first-contact pairing where the node ID is exactly what you don't have yet. Real full-featured controllers (Tahoma) are seen broadcasting both 0x28 and 0x2E during pairing, which is why the combined preset (0x28,0x2E) still exists in the Home Assistant selector — but on the evidence gathered so far, that's the controller hedging its bets, not 0x2E actually reaching a device 0x28 couldn't. Don't reach for 0x2E as a fix for a stuck device; see A tuning plan for what to try instead.
The address the discovery frames are sent to. With auto each command uses its conventional address (above). An explicit 0x00003B / 0x00003F forces every configured command to that address — useful for deliberately sending 0x28 to the alternate address, or vice-versa.
0x0001BB and 0x0001BF are different in kind: they name the lighting device class rather than every device. An io broadcast address packs the device type into its high bits, so light (type 6) gives 0x0001BF with the all-subtypes mask and 0x0001BB with discovery's mask. Reach for one only when a light or dimmer never answers the ordinary class-less discovery, and expect nothing from it on any other device — a class-typed address is, by construction, ignored by everything outside that class. Report what happens either way; no light has yet been confirmed to answer one.
An optional single 0x00 payload byte, and the LOW_POWER frame flag.
Observations: the alternate discovery path is conventionally sent with the 0x00 payload and LOW_POWER set, and some devices filter on them; they have no effect on the plain 0x28 path, so only enable them alongside 0x2E.
Sets CTRL1_ACK ("sender can handle 2W responses") on the discovery broadcast (0x28/0x2E) only — not on any other frame in the pairing handshake. It has no effect on the scan_paired_devices roll-call (0x2A) either, which is a separate, unrelated request path with its own fixed frame shapes: the roll-call's low-power pass sets CTRL1_ACK itself, unconditionally, as part of that pass's frame — see `scan_power_classes`.
Off by default, and scoped to the discovery broadcast on purpose. Setting CTRL1_ACK on every outbound frame silences real Somfy awnings: they drop a frame carrying an unexpected CTRL1 bit, with no error and no reply. Real VELUX hubs send their discovery broadcast with this bit set, and it is part of the confirmed pairing setup for a VELUX SSL solar roller shutter (see VELUX INTEGRA). For other families, turn it on only to test a device that never answers 0x28, and turn it back off if it doesn't help.
The preamble length (in bytes) on the discovery broadcast itself (0x28/0x2E). Defaults to 1024 (LONG_PREAMBLE): a factory-fresh device in learning mode is exactly the kind of duty-cycled receiver that wake-up burst exists for.
Some receivers never lock onto a preamble this long while they are awake, which is why every directed start frame derives its preamble from the target's power class (see normal_start_preamble above). The discovery broadcast can't do that: discovery runs before anything is known about the device, so it uses this setting.
A VELUX SSL solar roller shutter needs 32. It answers nothing at 1024 and answers within ~80 ms at 32. Somfy devices answer either way. Try it for any genuinely unpaired device that doesn't answer 0x28 (see A tuning plan):
tuning: ui_controls: true pairing_discovery_preamble: 32 # NORMAL_START_PREAMBLE's value; try 8 (SHORT_PREAMBLE) too
It also shortens the rest of pairing. The frames the hub then sends directly to the discovered device (discover-confirm 0x2C, key-init 0x31, and the phase-3 SetConfig1 0x6F) never use a longer preamble than this setting. The device has just answered a discovery with this preamble, so it is listening and hears it, and some VELUX receivers ignore every frame behind the 1024-byte wake-up burst those frames would otherwise carry (ADR 0029). The log says so when it happens (Pairing: directed frames to … use the 32-byte discovery preamble it just answered). At the default 1024 nothing changes. Normal operation after pairing is not affected: it follows the device's own low_power setting and its wake belief (see `low_power_wake_belief`).
How long to wait for a response after each discovery transmit, and an initial settle before the first transmit. pairing_discovery_wait_ms also sets the per-attempt listen window for the scan_paired_devices action (see Scan Paired Devices); at the default scan_power_classes: both that action makes six attempts (three channels, times two power classes), so its total runtime is roughly 6x this value — 3x with `scan_power_classes` narrowed to one class.
Observations: the 300 ms initial dwell mirrors the conventional wait after a start frame. Lengthening the wait only helps when responses are intermittent — merely extending the dwell without hopping across channels did not help in testing; the fix was the hopping itself.
How many times to retry the authenticated key exchange, each attempt using a fresh challenge.
Observations: the key-transfer step is the most fragile part of the flow on SX1262 — a device may acknowledge the challenge yet never confirm the key. That is usually a preamble/turnaround problem, so if extra retries alone don't help, address sx1262_response_preamble and sx1262_post_tx_settle_us first. Retries mainly guard against occasional transient decode failures.
Which device power classes the scan_paired_devices roll-call calls (see Scan Paired Devices):
Bisecting a mixed installation in the field is the main reason to touch this: run low_power alone to confirm which devices only answer the wake-up call, then always_alive alone to confirm the rest still answer without it.
Whether — and how — the hub sends CMD_DISCOVER_CONFIRM (0x2C) directly to a freshly-discovered device before proceeding to the key exchange (0x31). Every real controller this project has captured sends this frame between the device's discovery response (0x29) and its own key-init (0x31).
The step never fails a pairing attempt in any mode: a refusal, silence, or wrong reply is logged and pairing proceeds to the key exchange regardless. Cost: about +0.3 s (the pause) plus the device's own reply latency when a 0x2D comes back on the first try; with no answer at all, up to roughly 4.8 s for an always-alive target and 5.4 s for a low-power one (three 1.5 s tries, the longer figure from the low-power target's wake-up preamble), pause included.
A pause after the discover-confirm step and before CMD_KEY_INIT (0x31), applied regardless of whether the device answered, refused, or stayed silent — for one simple rule instead of a per-outcome one. Real controllers leave several seconds here, and they appear to spend that time re-broadcasting 0x28 to look for more devices on the same channel, which this project's single-device discovery phase has no equivalent of. 300 ms keeps pairing fast; a Somfy Izymo dimmer pairs with both 300 and 5000. Raise it only for a device that answers the 0x2C but stays silent to the key exchange. Has no effect when pairing_discover_confirm is skip.
Which of the three channels the hub listens on while waiting for a discovery response.
A broadcast's answers are not pinned to the channel the request went out on: each device that answers keeps hopping on its own schedule, so the channel it happens to be on when it replies is largely independent of the one that carried the request. Somfy always-alive replies seem to never come back on the request channel, so the default skip_request spends the whole window on the two channels that carry nearly all of them — a third more dwell on each.
Set all when a device never answers discovery at all. That measurement comes from devices we already hear, so it cannot speak for one whose replies we might be missing entirely; all costs a third of the dwell on the other two channels and removes the only blind spot the default has.
The "Last Pairing Result" sensor that comes with the Discover & Pair button summarises every attempt in one machine-readable line. Its lbt and advice fields are the two most useful while tuning: a high lbt count with a channel_busy advice code means the channel, not the parameters above, is the bottleneck. The full field reference and advice codes are in Diagnosing a failed pairing attempt.
lbt_max_retries and lbt_rssi_threshold_dbm exist for diagnostics only. Setting the threshold too high (e.g. -45 dBm) or the retry count too low can force transmissions on a busy channel and may violate local regulations for the 868 MHz SRD band. Do not leave aggressive LBT values in a production configuration.