[sx126x] Require a sync word for a link with FSK

Without one the radio cannot tell that a packet is arriving, so listen
before talk does nothing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
clydebarrow
2026-10-20 09:35:06 +11:00
co-authored by Claude Opus 5.5
parent 6449084613
commit 87d3f3d4cc
2 changed files with 28 additions and 4 deletions
@@ -4,12 +4,15 @@ from esphome.components.packet_interface.radio_link import (
radio_link_final_validate,
radio_link_schema,
)
import esphome.config_validation as cv
from esphome.types import ConfigType
from .. import (
CONF_MODULATION,
CONF_PAYLOAD_LENGTH,
CONF_RX_START,
CONF_SX126X_ID,
CONF_SYNC_VALUE,
DOMAIN,
SX126x,
SX126xListener,
@@ -25,8 +28,21 @@ SX126xPacketInterface = sx126x_ns.class_(
CONFIG_SCHEMA = radio_link_schema(SX126xPacketInterface, CONF_SX126X_ID, SX126x)
def _check_fsk(config: ConfigType, radio: ConfigType) -> None:
"""Without LoRa, the radio can tell that a packet is arriving only from its sync word, which listen before talk
needs.
"""
if radio[CONF_MODULATION] != "LORA" and not radio[CONF_SYNC_VALUE]:
raise cv.Invalid(
f"Without LoRa modulation the radio needs a '{CONF_SYNC_VALUE}', so that the link can tell when a packet "
"is arriving and not send over it",
path=[CONF_SX126X_ID],
)
FINAL_VALIDATE_SCHEMA = radio_link_final_validate(
CONF_SX126X_ID, CONF_PAYLOAD_LENGTH, CONF_RX_START
CONF_SX126X_ID, CONF_PAYLOAD_LENGTH, CONF_RX_START, _check_fsk
)
+11 -3
View File
@@ -90,7 +90,7 @@ class _FullConfig(dict):
(
sx126x_packet_interface,
"sx126x",
{"payload_length": 10},
_lora(payload_length=10),
{},
"payload_length",
{"payload_length": 0},
@@ -143,6 +143,14 @@ class _FullConfig(dict):
"sync_value",
{"preamble_detect": 2},
),
(
sx126x_packet_interface,
"sx126x",
{"modulation": "FSK", "payload_length": 0, "sync_value": []},
{},
"sync_value",
{"sync_value": [0x12, 0x34]},
),
],
)
def test_radio_settings_checked(
@@ -154,7 +162,7 @@ def test_radio_settings_checked(
fix: dict | None,
) -> None:
"""Packets vary in length; FSK or OOK on an SX127x needs packet mode, a sync word or preamble detection, and
holds at most 64 bytes.
holds at most 64 bytes; FSK on an SX126x needs a sync word.
"""
config = {f"{domain}_id": "radio", CONF_MAX_PACKET_SIZE: 64, **link}
token = fv.full_config.set(_FullConfig(domain, radio))
@@ -190,7 +198,7 @@ def test_radio_settings_checked(
)
def test_rx_start_needed_for_replies(setup_core, link: dict, match: str | None) -> None:
"""A radio that sleeps after sending suits only a link whose layers need no packets back."""
sleeping = {"payload_length": 0, "rx_start": False}
sleeping = _lora(payload_length=0, rx_start=False)
config = sx126x_packet_interface.CONFIG_SCHEMA({"sx126x_id": "radio", **link})
token = fv.full_config.set(_FullConfig("sx126x", sleeping))
try: