Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
esphome::home_io_control Namespace Reference

Namespaces

namespace  decisions
namespace  exchange
namespace  detail
namespace  pairing
namespace  advisor
namespace  pairing_responder
namespace  crypto

Classes

struct  DeviceConfig
 YAML-declared device metadata for registration; defaults match an undeclared device. More...
class  DeviceRegistry
 Owns the per-hub device table, update callbacks, and linked-remote associations. More...
class  ExchangeEngine
 Authenticated exchange engine — outbound and inbound protocol flows. More...
class  IOHomeControlComponent
 The main IO-Homecontrol component. More...
struct  Lr1121BootloaderRequirement
 One (target firmware, required bootloader) pairing from Semtech's published compatibility matrix. More...
struct  ManagementActionResult
 Result of a hub-level management action such as rename. More...
class  ManagementActions
 Encapsulates hub-level management operations exposed as Home Assistant actions. More...
struct  PendingOperation
 A single queued operation to be dispatched from loop(). More...
class  OperationQueue
 Serialized pending-operation queue with coalescing, deduplication, and two-band ordering. More...
class  PairingEngine
 Owns and drives all three phases of the IO-Homecontrol device pairing flow. More...
struct  PairingTelemetryEvent
 One recorded telemetry event. More...
class  PairingTelemetry
 Fixed-size per-attempt telemetry recorder for the pairing flow. More...
class  IOHomeAcceptForeignPairingSwitch
 Hub-level switch entity: ON arms the key-extraction responder for 10 minutes, OFF disarms it immediately. More...
class  IOHomeActiveIssueTextSensor
 Diagnostic text sensor that publishes the symbolic name of a device's most recent CMD_ERROR_RESP result code (e.g. More...
class  IOHomeCover
 Cover entity representing an IO‑Homecontrol shutter/awning/blind. More...
class  IOHomeCoverFavoriteButton
 Button entity that sends the protocol's favorite or My-position command. More...
class  IOHomeCoverVentButton
 Button entity that sends the ventilation position command. More...
class  IOHomeDeviceNameTextSensor
 Diagnostic text sensor that publishes the cached device name. More...
class  IOHomeDiscoverButton
 Button entity that triggers device discovery and pairing when pressed in Home Assistant. More...
class  DeviceBoundEntity
 Mixin holding the hub-device binding shared by all IO-Homecontrol entity platforms. More...
class  DeviceBoundCompanion
 Mixin holding the hub/device binding shared by the auto-generated per-device companion diagnostic sensors (device name, active issue, RSSI, last contact, exchange failures). More...
class  IOHomeExchangeFailuresSensor
 Diagnostic sensor that publishes a device's cumulative count of outbound exchanges that timed out (no valid response) — see detail::record_exchange_timeout() in hub_internal.h. More...
class  IOHomeLastContactSensor
 Diagnostic sensor that publishes seconds elapsed since the last frame received from a device (see detail::update_link_health() in hub_internal.h). More...
class  IOHomeLight
 Binary or dimmable light entity for IO‑Homecontrol devices. More...
class  IOHomeLock
 Lock entity for IO-Homecontrol lock devices. More...
class  IOHomePairingResultTextSensor
 Diagnostic text sensor that publishes PairingTelemetry::result_sensor_string() after every pairing attempt. More...
class  IOHomeRssiSensor
 Diagnostic sensor that publishes a device's smoothed (EMA) RSSI in dBm. More...
class  IOHomeSwitch
 Binary switch entity for IO‑Homecontrol on/off devices. More...
struct  OneWayFrameInfo
 Decoded representation of a 1W remote frame. More...
struct  DiscoveryResponseInfo
 Extended discovery-response fields (manufacturer, Multi Information Byte, backbone address, timestamp) plus flags recording how much of the payload was actually present. More...
struct  IoDevice
 Runtime state of a paired IO‑Homecontrol device. More...
struct  IoFrame
 Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data). More...
class  SpiAccess
 Interface for SPI bus access. More...
struct  RadioTxConfig
 Configuration for transmitting a packet: carrier frequency and preamble length. More...
struct  RadioRxPacket
 Raw packet received from the radio. More...
struct  RadioCaptureInfo
 Diagnostic capture from a radio operation. More...
class  RadioDriver
 Abstract radio driver for IO-Homecontrol. More...
class  RadioLR1121
 LR1121 implementation of RadioDriver. More...
struct  UartProbeResult
 Result of the UART probe: best candidate frame within a raw capture. More...
class  SoftPhyDriverBase
 Shared RX/TX driver flow for the software-PHY radios (SX1262, LR1121). More...
class  RadioSX1262
 SX1262 implementation of RadioDriver. More...
class  RadioSX1276
 SX1276 implementation of RadioDriver. More...
struct  PollTracking
 Per-device poll scheduling state. More...
class  StatusPollPolicy
 Per-hub poll scheduling and failure-backoff policy. More...
struct  TuningConfig
 All runtime tunable parameters for pairing and radio diagnostics. More...
class  IOHomeTuningNumber
 Runtime-tunable number entity. More...
class  IOHomeTuningSelect
 Runtime-tunable select entity. More...
struct  TuningNumberParam
 One numeric tuning parameter: its wire name plus accessors over TuningConfig. More...
struct  TuningSelectParam
 One select tuning parameter: its wire name plus string accessors over TuningConfig. More...

Typedefs

using DeviceUpdateCallback = std::function<void(const std::string &device_id, const IoDevice &device)>
 Callback type invoked when a device's state changes.

Enumerations

enum class  BootloaderSupport : uint8_t { SUPPORTED , UNSUPPORTED , UNKNOWN_TARGET }
 Whether a target firmware version is known to work with a given bootloader version. More...
enum class  BootloaderMismatch : uint8_t { NONE , TARGET_NEEDS_NEWER , TARGET_NEEDS_OLDER }
 Direction of a bootloader/target mismatch, for messaging. More...
enum class  BootloaderUpgradePath : uint8_t { NOT_APPLICABLE , AVAILABLE , BLOCKED_UNKNOWN_TARGET , BLOCKED_BOOTLOADER_NEWER }
 Whether the three-stage bootloader-rewrite sequence (ADR 0021) is applicable, and if not, why. More...
enum class  FlashDecision : uint8_t {
  PROCEED , ALREADY_INSTALLED , NEEDS_CONFIRMATION , REJECT_WRONG_CHIP ,
  REJECT_BOOTLOADER_TOO_OLD
}
 Outcome of lr1121_flash_decision(). More...
enum class  ScanAddResult : uint8_t { ADDED , DUPLICATE , FULL }
 Outcome of add_scan_responder(), so callers can tell a harmless repeat from real loss. More...
enum class  PendingOperationType : uint8_t {
  SET_POSITION , SET_TILT , SET_POSITION_AND_TILT , DEVICE_COMMAND ,
  SET_LIGHT_STATE , SET_LOCK_STATE , SET_SWITCH_STATE , REQUEST_STATUS ,
  REQUEST_NAME , DISCOVER_AND_PAIR
}
 Discriminator for entries in the pending-operation deque. More...
enum class  PairingTelemetryEventKind : uint8_t {
  TX , RX , RX_REJECT , LBT_DEFER ,
  HOP , PHASE
}
 Kind of a recorded telemetry event. More...
enum class  PairingOutcome : uint8_t {
  NONE , PAIRED , NO_RESPONSE , INVALID_RESPONSE ,
  KEY_EXCHANGE_FAILED , CONFIG_FAILED
}
 Final disposition of a pairing attempt, used by the result sensor string. More...
enum class  DeviceNameValidationError : uint8_t {
  NONE = 0x00 , EMPTY = 0x01 , TOO_LONG = 0x02 , INVALID_UTF8 = 0x03 ,
  UNSUPPORTED_CHAR = 0x04
}
 Validation result for outbound device-name writes. More...
enum class  AddressClass : uint8_t {
  UNICAST = 0 , BROADCAST_ALL , BROADCAST_TYPE , DISCOVERY ,
  UNKNOWN_BROADCAST
}
 Address classification categories for diagnostic purposes. More...
enum class  DeviceType : uint8_t {
  UNKNOWN = 0x00 , VENETIAN_BLIND = 0x01 , ROLLER_SHUTTER = 0x02 , AWNING = 0x03 ,
  WINDOW_OPENER = 0x04 , GARAGE_OPENER = 0x05 , LIGHT = 0x06 , GATE_OPENER = 0x07 ,
  ROLLING_DOOR_OPENER = 0x08 , LOCK = 0x09 , BLIND = 0x0A , SCREEN = 0x0B ,
  BEACON = 0x0C , DUAL_SHUTTER = 0x0D , HEATING_TEMPERATURE_INTERFACE = 0x0E , ON_OFF_SWITCH = 0x0F ,
  HORIZONTAL_AWNING = 0x10 , EXTERNAL_VENETIAN_BLIND = 0x11 , LOUVRE_BLIND = 0x12 , CURTAIN_TRACK = 0x13 ,
  VENTILATION_POINT = 0x14 , EXTERIOR_HEATING = 0x15 , HEAT_PUMP = 0x16 , INTRUSION_ALARM = 0x17 ,
  SWINGING_SHUTTER = 0x18
}
 Device type identifiers reported by IO‑Homecontrol products. More...
enum class  DeviceCapabilityClass : uint8_t {
  UNKNOWN = 0x00 , COVER = 0x01 , LIGHT = 0x02 , SWITCH = 0x03 ,
  SENSOR = 0x04 , BEACON = 0x05 , CLIMATE = 0x06 , LOCK = 0x07
}
 High‑level capability class derived from DeviceType. More...
enum class  CoverCommand : uint8_t { STOP = 0 , FAVORITE = 1 , VENT = 2 , FORCE_OPEN = 3 }
 Named device commands for cover-type actuators. More...
enum class  SX1262RxBandwidth : uint8_t {
  BW_58_6_KHZ = 0x0C , BW_78_2_KHZ = 0x1B , BW_117_3_KHZ = 0x0B , BW_156_2_KHZ = 0x09 ,
  BW_187_2_KHZ = 0x07
}
 Valid SX1262 RX bandwidth options (kHz register values). More...
enum class  SX1276RxBandwidth : uint8_t {
  BW_20_8_KHZ = 0x14 , BW_41_7_KHZ = 0x13 , BW_62_5_KHZ = 0x03 , BW_83_3_KHZ = 0x12 ,
  BW_125_0_KHZ = 0x02
}
 Valid SX1276 RX bandwidth options (RegRxBw register bytes). More...
enum class  LR1121RxBandwidth : uint8_t {
  BW_39_0_KHZ = 0x1C , BW_46_9_KHZ = 0x14 , BW_58_6_KHZ = 0x0C , BW_78_2_KHZ = 0x1B ,
  BW_117_3_KHZ = 0x0B , BW_156_2_KHZ = 0x1A , BW_187_2_KHZ = 0x12
}
 Valid LR1121 RX bandwidth options (register values). More...
enum class  DiscoveryCommand : uint8_t { DISCOVER = 0x28 , DISCOVER_SPE = 0x2A , DISCOVER_ALT = 0x2E }
 Discovery request command codes. More...

Functions

bool stored_node_id_is_valid (const uint8_t id[NODE_ID_SIZE])
 Check if a stored node ID is valid (not all-zero, not all-0xFF).
std::string format_position (float pos)
 Format a position float as a human‑readable string (e.g.
const char * pairing_stage_name (pairing::PairingState state)
 Get a short, log/telemetry-friendly name for a pairing state.
void bytes_to_hex (const uint8_t *data, uint8_t len, char *out, size_t out_size)
void decode_ctrl1_flags (uint8_t ctrl1, char *out, size_t out_size)
 Render decoded CTRL1 flags into a short annotation string.
void render_frame_hex_redacted (const uint8_t *data, uint8_t len, char *out, size_t out_size)
 Render a frame's bytes as spaced hex text, masking the payload when the command carries key material (see command_carries_key_material()).
constexpr bool lr1121_bootloader_is_lr1121 (uint16_t bootloader_version)
constexpr const char * lr1121_chip_family_for_bootloader (uint16_t bootloader_version)
 Human-readable chip family for a bootloader version that is not one of the two LR1121 values above, for an actionable REJECT_WRONG_CHIP message.
constexpr const char * lr1121_chip_family_for_device_type (uint8_t device_type)
 Human-readable chip family for a normal-mode device_type that is not the LR1121 value above, for an actionable REJECT_WRONG_CHIP message (the layer-3 counterpart of lr1121_chip_family_for_bootloader() above).
constexpr BootloaderSupport lr1121_bootloader_supports_target (uint16_t target_fw, uint16_t bootloader_version)
 Look up whether target_fw is known to require bootloader_version.
constexpr uint16_t lr1121_required_bootloader_for (uint16_t target_fw)
 Required bootloader for a known target firmware version.
constexpr BootloaderMismatch lr1121_bootloader_mismatch_kind (uint16_t target_fw, uint16_t bootloader_version)
 Classify a bootloader/target mismatch by direction; see BootloaderMismatch.
constexpr BootloaderUpgradePath lr1121_bootloader_upgrade_path (bool block_present, bool bootloader_version_known, uint16_t bootloader_version, uint16_t loader_fw, uint16_t target_fw)
 Whether the three-stage bootloader upgrade is applicable for the current cached state.
constexpr FlashDecision lr1121_flash_decision (uint8_t device_type, uint8_t bootloader_chip_type, uint16_t bootloader_version, uint16_t installed_fw, uint16_t target_fw, bool already_confirmed)
 The single decision point for whether/how to flash target_fw.
static std::string normalize_device_id_argument (const std::string &device_id)
static std::string bool_to_string (bool value)
static std::string format_result_code (uint8_t result_code)
static ManagementActionResult make_management_result (const std::string &action, const std::string &device_id)
static void log_multiline_result (const char *tag, bool is_warning, const std::string &prefix, const std::string &message)
 Log prefix followed by message, one line per log call rather than one call for the whole (possibly multi-line) string.
static bool apply_error_response (const IoFrame &response, ManagementActionResult &result)
 Decode a CMD_ERROR_RESP frame's result code into result.
static std::string format_scan_reply_line (const ScanResponder &responder, const std::string &device_id, bool known)
 Format one roll-call responder's report line(s).
static ScanAddResult add_scan_responder (ScanResponder *responders, uint8_t &count, uint8_t capacity, const IoFrame &frame, int16_t rssi_dbm)
 Record a responder unless its address is already present.
std::string trim_ascii_whitespace (const std::string &value)
 Trim leading and trailing ASCII whitespace from a string.
std::string decode_device_name_payload (const uint8_t *data, uint8_t len)
 Decode a device-name payload from IO-homecontrol's Latin-1 wire format into UTF-8.
DeviceNameValidationError encode_device_name_payload (const std::string &name, uint8_t payload[DEVICE_NAME_WRITE_PAYLOAD_SIZE], std::string &normalized_name)
 Validate and encode a user-supplied UTF-8 device name into the fixed Latin-1 write payload.
const char * device_name_validation_error_name (DeviceNameValidationError error)
 Return a stable symbolic name for a device-name validation result.
const char * device_name_validation_error_description (DeviceNameValidationError error)
 Return a human-readable explanation for a device-name validation result.
AddressClass classify_address (const uint8_t addr[NODE_ID_SIZE])
 Classify an IO-Homecontrol 3-byte address.
const char * address_class_name (AddressClass address_class)
 Get a human-readable name for an address classification.
DeviceType broadcast_target_type (const uint8_t addr[NODE_ID_SIZE])
 Extract the target device type from a typed broadcast address.
void decode_1w_main_intent (uint8_t main0, uint8_t main1, char *out, size_t out_size)
 Decode the "main" position/command bytes from a 1W execute payload.
std::optional< float > oneway_intent_to_target (uint8_t main0, uint8_t main1)
 Resolve a 1W main-byte pair to an optimistic IO target position, if unambiguous.
OneWayFrameInfo decode_1w_frame (const IoFrame &frame)
 Decode a parsed 1W frame into a structured OneWayFrameInfo.
DiscoveryResponseInfo decode_discovery_response (const IoFrame &frame, IoDevice &device, std::string &device_id)
 Decode a discovery-response payload (CMD_DISCOVER_RESP 0x29 or CMD_DISCOVER_SPE_RESP 0x2B — both carry the identical DISCOVERY_RESP_FULL_SIZE layout) into device metadata.
bool create_execute_position (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power, uint8_t position)
 Build a position execute command (0x00) to move a device to a numeric position.
bool create_execute_command (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power, CoverCommand cmd)
 Build a named-command execute frame (0x00) for STOP, FAVORITE, or VENT.
bool create_force_open (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power, uint8_t open_position)
 Build a force-open execute frame (0x00): an ordinary position command to the device's wire-scale "fully open" value, sent at elevated ACEI priority (see EXECUTE_ACEI_FORCE_OPEN).
bool create_get_status (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a get-status request (0x03). The device responds with its current position.
bool create_get_name (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power)
 Build a get-name request (0x50).
bool create_set_name (IoFrame &f, const uint8_t *own, const uint8_t *dst, const uint8_t payload[DEVICE_NAME_WRITE_PAYLOAD_SIZE])
 Build an authenticated set-name request (0x52) using a fixed zero-padded Latin-1 payload.
bool create_identify (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build an authenticated device-identify request (0x1E).
bool create_execute_tilt (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power, uint8_t tilt_percent)
 Build a tilt execute command (0x00) for devices that support slat angle control.
bool create_execute_position_and_tilt (IoFrame &f, const uint8_t *own, const uint8_t *dst, bool low_power, uint8_t position, uint8_t tilt_percent)
 Build a combined position-and-tilt execute command (0x00) — setClosureAndOrientation.
bool create_get_status_tilt (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a tilt-aware get-status request (0x03) that returns the extended 16-byte tilt payload.
bool create_discover (IoFrame &f, const uint8_t *own)
 Build a discovery broadcast (0x28).
bool create_discovery_request (IoFrame &f, const uint8_t *own, uint8_t command, const uint8_t *dst, bool low_power, bool payload_enabled, uint8_t payload, const uint8_t *system_key)
 Build a configurable discovery request command (0x28, 0x2A, or 0x2E).
bool create_discover_resp (IoFrame &f, const uint8_t *own, const uint8_t *dst, DeviceType type, uint8_t subtype, uint8_t manufacturer_id)
 Build a discovery response (0x29) — device side, used only by the key-extraction responder.
static bool create_device_terminal_ack (IoFrame &f, const uint8_t *own, const uint8_t *dst, uint8_t cmd)
 Build a bare device→hub terminal acknowledgement: no payload, END set, START and LOW_POWER clear.
bool create_key_confirm (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a key-confirm frame (0x33) — device side, used only by the key-extraction responder.
bool create_discover_confirm_ack (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a discovery-confirm acknowledgement (0x2D) — device side, used only by the key-extraction responder.
bool recover_system_key_from_transfer (const uint8_t transfer_payload[AES_KEY_SIZE], const uint8_t challenge[HMAC_SIZE], uint8_t out_key[AES_KEY_SIZE])
 Recover the system key from a CMD_KEY_TRANSFER payload.
bool create_key_init (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a key-init request (0x31) to start the pairing key exchange with a discovered device.
bool create_key_transfer (IoFrame &f, IoFrame &old_frame, const uint8_t *dst, const uint8_t *src, const uint8_t key[AES_KEY_SIZE], const uint8_t challenge[HMAC_SIZE])
 Build a key-transfer frame (0x32) containing the system key encrypted with the transfer key.
static bool create_challenge_req_framed (IoFrame &f, const uint8_t *dst, const uint8_t *src, const uint8_t challenge[HMAC_SIZE], bool start, bool low_power)
 Build a challenge request (0x3C) with caller-chosen framing bits.
bool create_challenge_req (IoFrame &f, const uint8_t *dst, const uint8_t *src, const uint8_t challenge[HMAC_SIZE])
 Build a challenge request (0x3C) using a caller-supplied challenge.
bool create_challenge_req (IoFrame &f, const uint8_t *dst, const uint8_t *src)
 Build a challenge request (0x3C) containing 6 random bytes.
bool create_challenge_req_device_role (IoFrame &f, const uint8_t *dst, const uint8_t *src, const uint8_t challenge[HMAC_SIZE])
 Build a device-role challenge request (0x3C) — device side, used only by the key-extraction responder.
bool create_challenge_resp (IoFrame &f, const uint8_t *dst, const uint8_t *src, const uint8_t challenge[HMAC_SIZE], const IoFrame &origin, const uint8_t *key)
 Build a challenge response (0x3D) proving we know the system key.
bool create_status_update_resp (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a status-update acknowledgment (0x72).
bool create_set_config1 (IoFrame &f, const uint8_t *own, const uint8_t *dst)
 Build a set-config command (0x6F) to tell the device to automatically send status updates when controlled by any remote (not just us).
const char * command_name (uint8_t cmd)
 Get a human-readable name for any IO-Homecontrol command ID.
const char * manufacturer_name (uint8_t id)
 Get a human-readable manufacturer name from the protocol manufacturer byte.
const char * att_class_name (uint8_t att_class)
 Get a human-readable turnaround time string for an ATT class value.
const char * power_save_mode_name (uint8_t mode)
 Get a human-readable power save mode name.
const char * originator_name (uint8_t originator)
 Get a human-readable name for a command originator byte.
const char * acei_level_name (uint8_t level)
 Get a human-readable name for an ACEI priority level (0–7).
const char * command_result_name (uint8_t result)
 Return a stable symbolic name for a CMD_ERROR_RESP result code.
const char * command_result_description (uint8_t result)
 Return a human-readable explanation for a CMD_ERROR_RESP result code.
bool is_limitation_result (uint8_t result)
 Check whether a result code represents an environmental or control limitation.
uint8_t discovery_att_class (uint8_t flags)
 Extract the ATT class field from a discovery response's Multi Information Byte.
uint8_t discovery_power_save_mode (uint8_t flags)
 Extract the power save mode field from a discovery response's Multi Information Byte.
bool default_inverted_for_type (DeviceType type)
 Determine whether a device type has inverted position mapping by default.
const char * cover_command_name (CoverCommand cmd)
 Get a human-readable name for a CoverCommand.
DeviceType decode_packed_device_type (uint8_t type_msb, uint8_t type_subtype)
 Decode a protocol-packed device type from two metadata bytes.
uint8_t decode_packed_device_subtype (uint8_t type_subtype)
 Decode a protocol-packed device subtype from the second metadata byte.
void encode_packed_device_type (DeviceType type, uint8_t subtype, uint8_t &type_msb, uint8_t &type_subtype)
 Encode a DeviceType/subtype pair into the two-byte packed metadata format used by discovery responses — the inverse of decode_packed_device_type()/decode_packed_device_subtype().
void decode_position_report (uint16_t target_raw, uint16_t current_raw, bool is_stopped, float &target, float &position)
 Decode target/current position values from a status frame.
bool has_reached_target_position (float target, float position)
 Has the device reached its target within tolerance?
float decode_tilt_report (uint16_t tilt_raw)
 Decode tilt angle from raw 16‑bit value.
const char * device_type_name (DeviceType type)
 Convert a DeviceType to a lowercase string identifier.
const char * yaml_device_type_name (DeviceType type)
 Return the YAML-friendly device-type name for types exposed in the Python schema.
DeviceCapabilityClass device_capability_class (DeviceType type)
 Map a raw IO‑Homecontrol type to the closest ESPHome/Home Assistant entity family.
const char * device_capability_class_name (DeviceType type)
 Get a human‑readable name for a capability class.
bool device_supports_position_control (DeviceType type)
 Does this device type support precise position control (0–100)?
bool device_supports_binary_control (DeviceType type)
 Does this device type support binary on/off control?
bool device_supports_lock_control (DeviceType type)
 Does this device type support binary lock/unlock control via execute commands?
bool device_supports_status_requests (DeviceType type)
 Does this device type support status request commands (0x03)?
bool device_supports_tilt (DeviceType type)
 Does this device type support tilt (slat angle) control?
bool device_supports_vent (DeviceType type)
 Does this device type support the ventilation position command?
const char * device_operation_profile_name (DeviceType type)
 Human‑readable operation profile name for a device type.
std::string format_device_type_diagnostic (DeviceType type)
 Human-readable device type string for diagnostics, including the raw numeric value.
std::string format_device_type_for_yaml (DeviceType type)
 Build the YAML value for a device's io_device_type key.
std::string build_device_yaml_snippet (DeviceType type, uint8_t subtype, const std::string &device_id, bool metadata_complete, bool inverted)
 Build the ready-to-paste YAML block describing a device, for both a fully-decoded device and one whose type/subtype wasn't reported.
int16_t rssi_scaled_to_dbm (int16_t scaled)
 Convert an rssi_ema_scaled fixed-point value to whole dBm (round half away from zero).
int16_t device_rssi_ema_dbm (const IoDevice &dev)
 A device's smoothed RSSI in whole dBm.
static int hex_nibble (char ch)
bool hex_to_bytes (const std::string &hex, uint8_t *out, uint8_t len)
 Convert a hex string (e.g., "123ABC") to a byte array.
std::string node_id_to_string (const uint8_t id[NODE_ID_SIZE])
 Format a 3‑byte node ID as a 6‑character uppercase hex string.
uint16_t crc_ccitt (const uint8_t *data, uint8_t len)
 CRC-CCITT used by the IO-Homecontrol protocol for frame validation.
void init_frame (IoFrame &f, bool is_2w=true, bool start=false, bool end=false, bool low_power=false)
 Initialize an IoFrame header (ctrl0/ctrl1) with flags.
void set_dst (IoFrame &f, const uint8_t id[NODE_ID_SIZE])
 Set destination node ID.
void set_src (IoFrame &f, const uint8_t id[NODE_ID_SIZE])
 Set source node ID.
bool set_cmd (IoFrame &f, uint8_t cmd, const uint8_t *params=nullptr, uint8_t params_len=0)
 Set command and payload.
uint8_t frame_length (const IoFrame &f)
 Get total frame length from ctrl0.
bool is_start (const IoFrame &f)
 Check START flag.
bool is_end (const IoFrame &f)
 Check END flag.
uint8_t serialize (const IoFrame &f, uint8_t *buf, uint8_t buf_size)
 Serialize a parsed frame into a wire buffer (without CRC).
bool parse (const uint8_t *buf, uint8_t buf_len, IoFrame &f)
 Parse a wire buffer into a parsed IoFrame (validates length and CTRL0).
constexpr bool lr1121_firmware_is_outdated (uint8_t fw_major, uint8_t fw_minor)
 Pure comparison against the known-latest constants above — no I/O, host-testable.
uint8_t decode_uart_probe (const uint8_t *raw, uint8_t raw_len, uint8_t bit_offset, uint8_t *decoded, uint8_t decoded_max_len)
 Decode a raw UART‑encoded bitstream into bytes.
static std::pair< uint8_t, uint8_t > find_crc_valid_frame (const uint8_t *decoded, uint8_t decoded_len)
 Try to find a CRC-valid IO-Homecontrol frame within a decoded UART byte stream.
UartProbeResult find_uart_probe (const uint8_t *raw, uint8_t raw_len)
 Search raw RX buffer for the best CRC-validated IO-Homecontrol frame.
uint8_t soft_phy_raw_bytes_for_frame (uint8_t frame_len)
 Raw on-air bytes needed to carry a whole frame: frame_len protocol bytes plus the two trailing CRC bytes, each UART-packed into a 10-bit cell.
uint8_t soft_phy_peek_frame_length (const uint8_t *raw, uint8_t raw_len)
 Recover a frame's total length from the very first UART cell of a reception.
uint8_t uart_encode_packet (const uint8_t *data, uint8_t len, uint8_t *encoded, uint8_t encoded_max_len)
 UART-encode a buffer of bytes (start bit 0, 8 data bits LSB-first, stop bit 1).
constexpr uint32_t soft_phy_air_time_us (uint32_t raw_bytes)
 On-air time in microseconds for raw_bytes bytes at the protocol's line rate.
bool command_carries_key_material (uint8_t cmd)
 Whether a frame command's payload carries key material that must never be logged or reported verbatim.
bool contains_key_material (const uint8_t *buf, size_t len, const uint8_t *system_key)
 Whether a buffer contains the system key as a contiguous run of bytes.
uint32_t settle_delay_ms (uint32_t interval_ms, uint32_t hint_delay_ms, bool cap_for_stop)
 Resolve the follow-up settle-poll delay while a device may still be moving.
float sx1262_bandwidth_to_khz (SX1262RxBandwidth bw)
 Convert a bandwidth enum to the numeric kHz value used in YAML/logs.
std::string sx1262_bandwidth_to_string (SX1262RxBandwidth bw)
 Format a bandwidth enum as its YAML/UI option string (bare kHz number, e.g.
std::optional< SX1262RxBandwidthsx1262_bandwidth_from_string (const std::string &value)
 Convert a YAML bandwidth string to the enum value.
float sx1276_bandwidth_to_khz (SX1276RxBandwidth bw)
 Convert an SX1276 bandwidth enum to the numeric kHz value used in YAML/logs.
std::string sx1276_bandwidth_to_string (SX1276RxBandwidth bw)
 Format an SX1276 bandwidth enum as its YAML/UI option string (bare kHz number).
std::optional< SX1276RxBandwidthsx1276_bandwidth_from_string (const std::string &value)
 Convert a YAML SX1276 bandwidth string to the enum value.
float lr1121_bandwidth_to_khz (LR1121RxBandwidth bw)
 Convert an LR1121 bandwidth enum to the numeric kHz value used in YAML/logs.
std::string lr1121_bandwidth_to_string (LR1121RxBandwidth bw)
 Format an LR1121 bandwidth enum as its YAML/UI option string (bare kHz number).
std::optional< LR1121RxBandwidthlr1121_bandwidth_from_string (const std::string &value)
 Convert a YAML LR1121 bandwidth string to the enum value.
std::optional< DiscoveryCommanddiscovery_command_from_string (const std::string &value)
 Parse a discovery command string (e.g., "0x28") into the enum.
std::string discovery_command_to_string (DiscoveryCommand cmd)
 Format a discovery command enum for YAML/logs.
std::string discovery_commands_to_csv (const std::vector< DiscoveryCommand > &commands)
 Format the ordered discovery command list as a UI/preset option string.
std::string discovery_commands_to_string (const std::vector< DiscoveryCommand > &commands)
 Format the ordered discovery command list for logs.
const uint8_t * resolve_discovery_destination (uint8_t command, bool destination_auto, const uint8_t destination[NODE_ID_SIZE])
 Resolve the destination address for a discovery command.
std::string discovery_destination_to_string (bool destination_auto, const uint8_t destination[NODE_ID_SIZE])
 Format a destination option for YAML/logs.
std::string discovery_payload_to_string (bool payload_enabled, uint8_t payload)
 Format a payload option for YAML/logs.
std::string tuning_update_log_line (const std::string &name, const std::string &value)
 Format a single tuning update for the log.
std::string tuning_config_snapshot (const TuningConfig &cfg)
 Format the current tuning configuration as a one-line YAML-compatible snapshot.
std::string tuning_config_full_snapshot (const TuningConfig &cfg)
 Format the current tuning configuration as a full one-line snapshot.
const TuningNumberParamfind_tuning_number (const std::string &name)
 Look up a numeric tuning parameter by name; returns nullptr if unknown.
const TuningSelectParamfind_tuning_select (const std::string &name)
 Look up a select tuning parameter by name; returns nullptr if unknown.
Table iteration

Range accessors over the full parameter tables, for enumeration and tests.

const TuningNumberParamtuning_number_params_begin ()
const TuningNumberParamtuning_number_params_end ()
const TuningSelectParamtuning_select_params_begin ()
const TuningSelectParamtuning_select_params_end ()

Variables

static constexpr const char * TAG = "home_io_control"
static const char *const TAG = "home_io_control.exchange"
static const char *const TAG = detail::TAG
constexpr uint8_t DEFAULT_TX_POWER_DBM = 17
 Default TX power used unless YAML overrides it.
constexpr uint8_t DEFAULT_PA_PIN_PA_BOOST = 0x80
 SX1276 PA_CONFIG selector for the PA_BOOST output path.
constexpr uint8_t DEFAULT_TCXO_VOLTAGE_SETTING_1P8V = 0x03
 SX1262 DIO3 setting value for a 1.8 V TCXO.
constexpr size_t POSITION_TEXT_BUFFER_SIZE = 16
 Buffer for formatted position strings such as "100%".
constexpr size_t FRAME_LOG_HEX_BUFFER_SIZE = 220
 Fits a full 32-byte frame rendered as spaced hex text.
constexpr size_t FRAME_LOG_FLAGS_BUFFER_SIZE = 32
 Buffer for decoded CTRL1 flag annotations.
constexpr uint8_t LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x03
 LR1121 GetVersion type byte in normal mode — must match radio_lr1121.h's LR1121_DEVICE_TYPE (0x03).
constexpr uint8_t LR1110_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x01
 Normal-mode GetVersion type bytes for the two chips an LR1121 is most easily confused with — companions to LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS above, used only to name the chip family in a REJECT_WRONG_CHIP message.
constexpr uint8_t LR1120_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x02
constexpr uint8_t LR1121_BOOTLOADER_TYPE_FOR_FIRMWARE_DECISIONS = 0xDF
 LR1121 GetVersion type byte reported while running the bootloader (LR11XX_TYPE_PRODUCTION_MODE) — must match radio_lr1121_firmware_updater.h's LR1121_UPDATER_BOOTLOADER_TYPE (0xDF).
constexpr uint16_t LR1121_BOOTLOADER_2100 = 0x2100
 LR1121 bootloader versions, from Semtech's published compatibility matrix.
constexpr uint16_t LR1121_BOOTLOADER_2101 = 0x2101
constexpr uint16_t LR1120_BOOTLOADER_2000 = 0x2000
 Bootloader versions reported by the two chips an LR1121 is most easily confused with — used only to name the chip family in a REJECT_WRONG_CHIP message.
constexpr uint16_t LR1120_BOOTLOADER_2001 = 0x2001
constexpr uint16_t LR1110_BOOTLOADER_6500 = 0x6500
constexpr uint16_t LR1110_BOOTLOADER_1001 = 0x1001
constexpr uint16_t LR1121_LOADER_2100 = 0x2100
 Version the lr1121_loader_2100.bin bootloader-*loader* image reports of itself.
constexpr Lr1121BootloaderRequirement LR1121_KNOWN_BOOTLOADER_REQUIREMENTS []
 Bootloader requirements we know about, copied from Semtech's published pairings (SWTL001/application/src/lr11xx_update_utils.c :: compatibility_matrix[]): 0x0101/0x0102/0x0103 need bootloader 0x2100, 0x0104 needs 0x2101.
static constexpr uint8_t BINARY_ENTITY_ON_POSITION = 0
 Position value written for binary ON commands (light on, switch on, lock unlock).
static constexpr uint8_t BINARY_ENTITY_OFF_POSITION = 100
 Position value written for binary OFF commands (light off, switch off, lock lock).
static constexpr uint8_t PAIRING_TELEMETRY_MAX_EVENTS = 32
 Maximum number of events recorded per pairing attempt.
static const char *const TAG = "home_io_control.key_extraction_switch"
static const char *const TAG = "home_io_control.active_issue"
static const char *const TAG = "home_io_control.cover"
static const char *const TAG = "home_io_control.favorite_button"
static const char *const TAG = "home_io_control.vent_button"
static const char *const TAG = "home_io_control.device_name"
static const char *const TAG = "home_io_control.exchange_failures"
static const char *const TAG = "home_io_control.last_contact"
static const char *const TAG = "home_io_control.light"
static const char *const TAG = "home_io_control.lock"
static const char *const TAG = "home_io_control.pairing_result"
static const char *const TAG = "home_io_control.rssi"
static const char *const TAG = "home_io_control.switch"
static constexpr uint8_t ONEWAY_EXECUTE_MIN_DATA_LEN = 4
 Minimum data bytes for decode of execute/activate‑mode intent fields.
static constexpr uint8_t DEVICE_NAME_WRITE_CHAR_LIMIT = 15
 Reference write limit before the trailing null.
static constexpr uint8_t DEVICE_NAME_WRITE_PAYLOAD_SIZE
 Fixed write payload: 15 visible chars plus trailing null/padding.
static constexpr uint16_t LATIN1_CODEPOINT_MAX = 0x00FF
 Highest Unicode code point representable in Latin-1.
static constexpr size_t ONEWAY_INTENT_BUFFER_SIZE = 24
 Buffer size for the decoded 1W main-intent string.
static constexpr uint8_t CMD_EXECUTE = 0x00
 Set position/open/close/stop — requires authentication.
static constexpr uint8_t CMD_ACTIVATE_MODE = 0x01
 Activate device mode (scene, ventilation) — requires auth.
static constexpr uint8_t CMD_PRIVATE = 0x03
 Get device status — no authentication needed.
static constexpr uint8_t CMD_PRIVATE_RESP = 0x04
 Response to 0x00 and 0x03 (contains position data).
static constexpr uint8_t CMD_PRIVATE2
 Content otherwise undecoded by the wire parser.
static constexpr uint8_t CMD_PRIVATE2_RESP = 0x0D
 Response to CMD_PRIVATE2. See CMD_PRIVATE2's comment.
static constexpr uint8_t CMD_SET_SENSOR = 0x19
 Inject sensor value into a device.
static constexpr uint8_t CMD_SET_SENSOR_ACK = 0x1A
 Acknowledgment to CMD_SET_SENSOR.
static constexpr uint8_t CMD_IDENTIFY = 0x1E
 Device physical identification / jog — requires authentication.
static constexpr uint8_t CMD_WRITE_PRIVATE = 0x20
 Write private register (climate/heating devices).
static constexpr uint8_t CMD_WRITE_PRIVATE_ACK = 0x21
 Acknowledgment to CMD_WRITE_PRIVATE.
static constexpr uint8_t CMD_DISCOVER_REQ = 0x28
 Broadcast discovery request.
static constexpr uint8_t CMD_DISCOVER_RESP = 0x29
 Device responds with its ID and type.
static constexpr uint8_t CMD_DISCOVER_SPE_REQ
 Broadcast roll-call answered by every device that already holds this controller's system key, regardless of device type.
static constexpr uint8_t CMD_DISCOVER_SPE_RESP
 Roll-call reply to CMD_DISCOVER_SPE_REQ, sent only by devices that already hold the requesting controller's system key.
static constexpr uint8_t CMD_DISCOVER_CONFIRM = 0x2C
 Confirm discovery to device.
static constexpr uint8_t CMD_DISCOVER_CONFIRM_ACK = 0x2D
 Device acknowledges confirmation.
static constexpr uint8_t CMD_DISCOVER_ALT_REQ
 Alternate discovery.
static constexpr uint8_t CMD_DISCOVER_ALT_RESP
 Reply to an addressed (non-broadcast) CMD_DISCOVER_ALT_REQ, following a 0x3C/0x3D challenge-response.
static constexpr uint8_t CMD_ONEWAY_ADD_CONTROLLER
 1W "add controller": a 1W device broadcasts this while its key-copy gesture is active, handing its network's wrapped system key to whichever controller is listening — see docs/commands.md#30-send-1w-key in the reference project linked from issue #66.
static constexpr uint8_t CMD_ONEWAY_REMOVE = 0x39
 1W "remove controller" (un-pair a 1W remote from a device); same payload shape as 0x2E.
static constexpr uint8_t CMD_KEY_INIT = 0x31
 Initiate key transfer to device.
static constexpr uint8_t CMD_KEY_TRANSFER = 0x32
 Send encrypted system key to device.
static constexpr uint8_t CMD_KEY_CONFIRM = 0x33
 Device confirms key was received.
static constexpr uint8_t CMD_ADDRESS_REQ = 0x36
 Address assignment request.
static constexpr uint8_t CMD_ADDRESS_RESP
 Address assignment response: the device returns its own 3-byte backbone address, byte-identical to the one it reported at data[2..4] (DISCOVERY_RESP_BACKBONE_OFFSET) of its CMD_DISCOVER_RESP earlier in the same session — an independent confirmation of that offset.
static constexpr uint8_t CMD_LAUNCH_KEY_TRANSFER
 Device-initiated ("pull") key transfer request.
static constexpr uint8_t CMD_CHALLENGE_REQ
 6-byte random challenge.
static constexpr uint8_t CMD_CHALLENGE_RESP
 HMAC proof answering a 0x3C.
static constexpr uint8_t CMD_UNKNOWN4A_REQ
 Content undecoded.
static constexpr uint8_t CMD_UNKNOWN4A_RESP
 Observed on the wire (tests/corpus/captures/issues/) answering an ON_OFF_SWITCH-type device's traffic, but its request opcode is unconfirmed — it is not established to be CMD_UNKNOWN4A_REQ's reply rather than CMD_GET_GENERAL_INFO3's.
static constexpr uint8_t CMD_GET_NAME = 0x50
 Request device name.
static constexpr uint8_t CMD_GET_NAME_RESP = 0x51
 Device name response.
static constexpr uint8_t CMD_SET_NAME = 0x52
 Set device name (authenticated).
static constexpr uint8_t CMD_SET_NAME_RESP = 0x53
 Device-name write response.
static constexpr uint8_t CMD_GET_INFO1
 Request device general info 1 (unimplemented; we only use 0x56/0x57).
static constexpr uint8_t CMD_GET_INFO1_RESP = 0x55
 Device general info 1 response (unimplemented; we only use 0x56/0x57).
static constexpr uint8_t CMD_GET_INFO2 = 0x56
 Request device type/model info.
static constexpr uint8_t CMD_GET_INFO2_RESP = 0x57
 Device type/model response.
static constexpr uint8_t CMD_GET_GENERAL_INFO3
 Observed on the wire (tests/corpus/captures/issues/) with no payload.
static constexpr uint8_t CMD_GET_GENERAL_INFO3_RESP
 Never captured on our own wire.
static constexpr uint8_t CMD_SET_CONFIG1 = 0x6F
 Configure device to auto-send status updates.
static constexpr uint8_t CMD_SET_CONFIG1_RESP
 Config response.
static constexpr uint8_t CMD_STATUS_UPDATE = 0x71
 Device-initiated status update (needs auth).
static constexpr uint8_t CMD_STATUS_UPDATE_RESP = 0x72
 Acknowledge status update.
static constexpr uint8_t CMD_SEND_RAW_MESSAGE
 reference/iown-homecontrol heads this "Send Raw Message / Find Hardware ("Service")" — its own quoting, not settled naming.
static constexpr uint8_t CMD_READ_GROUPS
 reference/iown-homecontrol heads this "Actuator: Read Groups / "ActuatorAnyConfigIsLocal" (?) / "Service ACK"" — three candidate names, one flagged with its own question mark, from the source itself.
static constexpr uint8_t CMD_REBOOT
 reference/iown-homecontrol heads this "Reboot / Service Status" — two candidate names, one of them destructive-sounding, on no field evidence at all.
static constexpr uint8_t CMD_SERVICE_STATUS_ACK
 reference/iown-homecontrol lists this opcode with its body marked TBD — no description at all, not even a hedge to reproduce.
static constexpr uint8_t CMD_ERROR_RESP = 0xFE
 Error response to any command.
static constexpr uint8_t RESULT_UNKNOWN_STATUS_REPLY = 0x00
 Device returned an unknown status reply.
static constexpr uint8_t RESULT_COMMAND_COMPLETED_OK = 0x01
 No errors detected.
static constexpr uint8_t RESULT_NO_CONTACT = 0x02
 No communication to node.
static constexpr uint8_t RESULT_MANUALLY_OPERATED = 0x03
 Manually operated by a user.
static constexpr uint8_t RESULT_BLOCKED = 0x04
 Node blocked by an object.
static constexpr uint8_t RESULT_WRONG_SYSTEMKEY = 0x05
 Node contains the wrong system key.
static constexpr uint8_t RESULT_PRIORITY_LEVEL_LOCKED = 0x06
 Node is locked on this priority level.
static constexpr uint8_t RESULT_REACHED_WRONG_POSITION = 0x07
 Node stopped in another position than expected.
static constexpr uint8_t RESULT_ERROR_DURING_EXECUTION = 0x08
 Generic execution failure.
static constexpr uint8_t RESULT_NO_EXECUTION = 0x09
 Node did not move.
static constexpr uint8_t RESULT_CALIBRATING = 0x0A
 Node is calibrating.
static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_HIGH = 0x0B
 Node power consumption is too high.
static constexpr uint8_t RESULT_POWER_CONSUMPTION_TOO_LOW = 0x0C
 Node power consumption is too low.
static constexpr uint8_t RESULT_LOCK_POSITION_OPEN = 0x0D
 Lock command failed because the door is open.
static constexpr uint8_t RESULT_MOTION_TIME_TOO_LONG = 0x0E
 Target was not reached in time.
static constexpr uint8_t RESULT_THERMAL_PROTECTION = 0x0F
 Node entered thermal protection mode.
static constexpr uint8_t RESULT_PRODUCT_NOT_OPERATIONAL = 0x10
 Node is not currently operational.
static constexpr uint8_t RESULT_FILTER_MAINTENANCE_NEEDED = 0x11
 Filter needs maintenance.
static constexpr uint8_t RESULT_BATTERY_LEVEL = 0x12
 Battery level is low.
static constexpr uint8_t RESULT_TARGET_MODIFIED = 0x13
 Node modified the requested target value.
static constexpr uint8_t RESULT_MODE_NOT_IMPLEMENTED = 0x14
 Mode is not supported by the node.
static constexpr uint8_t RESULT_COMMAND_INCOMPATIBLE_TO_MOVEMENT = 0x15
 Command cannot move the node that way.
static constexpr uint8_t RESULT_USER_ACTION = 0x16
 User action overrode the command.
static constexpr uint8_t RESULT_DEAD_BOLT_ERROR = 0x17
 Dead bolt error.
static constexpr uint8_t RESULT_AUTOMATIC_CYCLE_ENGAGED = 0x18
 Node entered automatic cycle mode.
static constexpr uint8_t RESULT_WRONG_LOAD_CONNECTED = 0x19
 Wrong load connected to node.
static constexpr uint8_t RESULT_COLOUR_NOT_REACHABLE = 0x1A
 Requested colour not reachable.
static constexpr uint8_t RESULT_TARGET_NOT_REACHABLE = 0x1B
 Requested target not reachable.
static constexpr uint8_t RESULT_BAD_INDEX_RECEIVED = 0x1C
 Invalid index received.
static constexpr uint8_t RESULT_COMMAND_OVERRULED = 0x1D
 Command was overruled by a newer command.
static constexpr uint8_t RESULT_NODE_WAITING_FOR_POWER = 0x1E
 Node is waiting for power.
static constexpr uint8_t RESULT_NODE_LOCKED = 0x20
 Node is locked.
static constexpr uint8_t RESULT_WRONG_POSITION = 0x21
 Node reports wrong position.
static constexpr uint8_t RESULT_LIMITS_NOT_SET = 0x22
 Device limits are not set.
static constexpr uint8_t RESULT_IP_NOT_SET = 0x23
 Intermediate position is not set.
static constexpr uint8_t RESULT_OUT_OF_RANGE = 0x24
 Requested value is out of range.
static constexpr uint8_t RESULT_PRIORITY_LOCKED_NON_EXEC
 Priority locked, command not executed (ACEI priority too low).
static constexpr uint8_t RESULT_INFORMATION_CODE = 0xDF
 Information-only code with unknown semantics.
static constexpr uint8_t RESULT_PARAMETER_LIMITED = 0xE0
 Parameter limited by an unknown device.
static constexpr uint8_t RESULT_LIMITATION_BY_LOCAL_USER = 0xE1
 Parameter limited by local button.
static constexpr uint8_t RESULT_LIMITATION_BY_USER = 0xE2
 Parameter limited by a remote control.
static constexpr uint8_t RESULT_LIMITATION_BY_RAIN = 0xE3
 Parameter limited by a rain sensor.
static constexpr uint8_t RESULT_LIMITATION_BY_TIMER = 0xE4
 Parameter limited by a timer.
static constexpr uint8_t RESULT_LIMITATION_BY_SCD = 0xE5
 Parameter limited by a security actuator.
static constexpr uint8_t RESULT_LIMITATION_BY_UPS = 0xE6
 Parameter limited by a power supply.
static constexpr uint8_t RESULT_LIMITATION_BY_UNKNOWN_DEVICE = 0xE7
 Parameter limited by an unknown device.
static constexpr uint8_t RESULT_LIMITATION_BY_SAAC = 0xEA
 Parameter limited by a standalone automatic controller.
static constexpr uint8_t RESULT_LIMITATION_BY_WIND = 0xEB
 Parameter limited by a wind sensor.
static constexpr uint8_t RESULT_LIMITATION_BY_MYSELF = 0xEC
 Parameter limited by the node itself.
static constexpr uint8_t RESULT_LIMITATION_BY_AUTOMATIC_CYCLE = 0xED
 Parameter limited by an automatic cycle.
static constexpr uint8_t RESULT_LIMITATION_BY_EMERGENCY = 0xEE
 Parameter limited by an emergency.
static constexpr uint8_t POS_STOP = 0xD2
 Position values in the IO protocol.
static constexpr uint8_t POS_UNKNOWN = 0xD4
 Wire value: position unknown / keep current.
static constexpr uint8_t POS_FAVORITE = 0xD8
 Wire value: move to favorite/"My" position.
static constexpr uint8_t POS_SECURED_TARGET = 0xD1
 Wire value for the secured target position command.
static constexpr uint8_t POS_DEFAULT = 0xD3
 Wire value for the default position command.
static constexpr uint8_t POS_FORCE_OPEN = 0x64
 Ambiguous wire value used only for passive 1W-traffic intent decoding (decode_1w_main_intent() / oneway_intent_to_target() in proto_codecs.cpp).
static constexpr uint8_t POS_VENT_MODIFIER = 0x03
 Modifier byte for the ventilation command.
static constexpr uint8_t STATUS_STOPPED = 0x01
 Status byte flags in CMD_PRIVATE_RESP and CMD_STATUS_UPDATE.
static constexpr uint8_t STATUS_EXPECTED = 0x80
 Byte 1 bit 7: device will send auto status update.
static constexpr uint8_t STATUS_TILT_SELECTOR = 0x20
 Extended status payload marker for tilt-capable devices.
static constexpr uint8_t TRANSFER_KEY [AES_KEY_SIZE]
 The transfer key is a hardcoded key used ONLY during pairing to obfuscate the system key during over-the-air transfer.
static constexpr uint16_t CRC_POLYNOMIAL_REVERSED = 0x8408
 Reversed CRC-CCITT polynomial used by IO-homecontrol.
static constexpr uint16_t CRC_LSB_MASK = 0x0001
 Least-significant-bit mask for reflected CRC update.
static constexpr uint8_t BROADCAST_DISCOVER [NODE_ID_SIZE] = {0x00, 0x00, 0x3B}
 Broadcast address for device discovery (0x00003B).
static constexpr uint8_t BROADCAST_DISCOVER_ALT [NODE_ID_SIZE] = {0x00, 0x00, 0x3F}
 Alternate discovery / 1W broadcast address (0x00003F).
static constexpr uint8_t MANUFACTURER_ID_MAX = 12
 Maximum manufacturer ID with a known name in the lookup table.
static constexpr uint16_t STATUS_POS_MAX = 0xC800
 In status responses, position is encoded as a 16-bit value where 0x0000 = fully open (0%) and 0xC800 = fully closed (100%).
static constexpr uint16_t STATUS_POS_TOLERANCE_RAW = 100
 Target-reached tolerance expressed in raw IO-homecontrol position units.
static constexpr uint8_t DEVICE_METADATA_SIZE = 2
 Packed device metadata uses two bytes where the high 8 bits carry the upper type bits and the low byte carries both the remaining type bits and the 6-bit manufacturer subtype.
static constexpr uint8_t DEVICE_TYPE_LOW_BITS_SHIFT = 2
static constexpr uint8_t DEVICE_TYPE_HIGH_BITS_SHIFT = 6
static constexpr uint8_t DEVICE_SUBTYPE_MASK = 0x3F
static constexpr float UNKNOWN_POSITION = 212.0F
 Sentinel value meaning "position is not known yet".
static constexpr uint8_t DEVICE_NAME_BUFFER_SIZE = 32
 Device name storage including null terminator.
static constexpr int16_t RSSI_UNKNOWN_DBM = INT16_MIN
 Sentinel value meaning "no RSSI sample recorded yet" for last_rssi_dbm/rssi_ema_scaled.
static constexpr int16_t RSSI_EMA_SCALE = 8
 EMA weight denominator and fixed-point scale for IoDevice::rssi_ema_scaled.
static constexpr uint8_t CTRL0_END = 0x80
 Control byte 0 (CTRL0) bit definitions.
static constexpr uint8_t CTRL0_START = 0x40
 Bit 6: first frame in exchange (uses long preamble).
static constexpr uint8_t CTRL0_PROTOCOL_1W = 0x20
 Bit 5: 1=OneWay protocol, 0=TwoWay protocol.
static constexpr uint8_t CTRL0_LENGTH_MASK = 0x1F
 Bits [4:0]: frame length - 1.
static constexpr uint8_t CTRL1_VERSION_MASK = 0x03
 Control byte 1 (CTRL1) bit definitions.
static constexpr uint8_t CTRL1_PRIORITY = 0x04
 Bit 2: high-priority frame.
static constexpr uint8_t CTRL1_ACK = 0x10
 Bit 4: sender can handle 2W responses (ACK-capable).
static constexpr uint8_t CTRL1_LOW_POWER = 0x20
 Bit 5: low-power device (e.g., solar-powered).
static constexpr uint8_t CTRL1_ROUTED = 0x40
 Bit 6: frame was relayed through a repeater.
static constexpr uint8_t CTRL1_BEACON = 0x80
 Bit 7: beacon announcement frame.
static constexpr uint8_t NODE_ID_SIZE = 3
 Device/node addresses are 3 bytes (e.g., "123ABC").
static constexpr uint8_t NODE_ID_STRING_SIZE = (NODE_ID_SIZE * 2) + 1
 Uppercase hex node ID plus null terminator.
static constexpr uint8_t HMAC_SIZE = 6
 Authentication HMAC is 6 bytes (truncated AES output).
static constexpr uint8_t AES_KEY_SIZE = 16
 AES-128 key size.
static constexpr uint8_t AES_BLOCK_SIZE = 16
 AES block size.
static constexpr uint8_t IV_SIZE = 16
 Initialization vector size for AES.
static constexpr uint8_t IV_PADDING = 0x55
 Padding byte used in IV construction.
static constexpr uint8_t BITS_PER_BYTE = 8
 Number of bits in one protocol byte.
static constexpr uint8_t FRAME_MIN_SIZE = 9
 Minimum frame: CTRL0+CTRL1+DST(3)+SRC(3)+CMD(1).
static constexpr uint8_t FRAME_MAX_SIZE = 32
 Maximum frame size (9 header + 23 data).
static constexpr uint8_t FRAME_MAX_DATA_SIZE = 23
 Maximum data bytes after command ID.
static constexpr uint8_t FRAME_CMD_OFFSET = 8
 Byte offset of the command ID in a raw wire buffer.
static constexpr uint8_t FRAME_CRC_SIZE = 2
 CRC-CCITT trailer appended after the frame body.
static constexpr uint32_t FREQ_CH1 = 868250000
 The protocol uses 3 frequency channels in the 868 MHz ISM band.
static constexpr uint32_t FREQ_CH2 = 868950000
 Channel 2: 868.95 MHz (1W and 2W, TX channel).
static constexpr uint32_t FREQ_CH3 = 869850000
 Channel 3: 869.85 MHz (2W only).
static constexpr uint16_t LONG_PREAMBLE = 1024
 Preamble is a sequence of 0xAA bytes that precedes every frame.
static constexpr uint16_t SHORT_PREAMBLE = 8
 8 bytes for response/continuation frames
static constexpr int32_t HOP_TIME_US = 2700
 Timing constants for frequency hopping and response waiting.
static constexpr int32_t RESPONSE_CHANNEL_WAIT_MS = 50
 Per-channel dwell while waiting for an exchange response.
static constexpr int32_t RESPONSE_WAIT_MS = 500
 Wait for response to non-start frame.
static constexpr int32_t RESPONSE_START_WAIT_MS = 1000
 Wait for a response to a start frame — the first frame of an exchange, and the one a sleeping device has just been woken by.
static constexpr int32_t RESPONSE_AUTH_WAIT_MS
 Wait for final response after challenge response.
static constexpr int32_t EXCHANGE_RETRY_DELAY_MS = 250
 Gap between retries within one HA command.
static constexpr uint8_t EXCHANGE_RETRY_COUNT = 3
 Attempts per command before reporting failure.
static constexpr int16_t LBT_RSSI_THRESHOLD_DBM = -90
 Listen-before-talk (LBT) parameters for ETSI EN 300 220 compliance.
static constexpr uint8_t LBT_MAX_RETRIES = 5
 Max carrier-sense attempts before TX anyway.
static constexpr uint8_t LBT_RETRY_DELAY_MS = 5
 Backoff between LBT checks (≥ 5ms per ETSI).
static constexpr uint16_t PAIRING_DISCOVERY_WAIT_MS = 2000
 Canonical defaults for the chip-neutral runtime-tunable pairing/discovery parameters.
static constexpr uint16_t PAIRING_DISCOVERY_INITIAL_DWELL_MS = 300
 Dwell on CH2 before discovery hopping begins.
static constexpr uint8_t PAIRING_KEY_EXCHANGE_RETRIES = 3
 Retries for the authenticated key-exchange phase.
constexpr uint8_t RADIO_PACKET_BUFFER_SIZE
 Scratch buffer size for raw radio packets and recovered frames.
static const char *const TAG = "home_io_control.lr1121"
static const uint32_t LR1121_BUSY_TIMEOUT_MS = 3000
static constexpr uint16_t LR1121_CMD_GET_STATUS = 0x0100
 cross-checked
static constexpr uint16_t LR1121_CMD_GET_VERSION = 0x0101
 cross-checked
static constexpr uint16_t LR1121_CMD_GET_ERRORS = 0x010D
 cross-checked (2-byte response)
static constexpr uint16_t LR1121_CMD_CLEAR_ERRORS
 hardware-verified (called on every init/RX cycle, never rejected — see log_command_status_())
static constexpr uint16_t LR1121_CMD_WRITE_BUFFER = 0x0109
 cross-checked
static constexpr uint16_t LR1121_CMD_READ_BUFFER = 0x010A
 cross-checked
static constexpr uint16_t LR1121_CMD_WRITE_REG_MEM_MASK32
 cross-checked (Semtech SWDR001 lr11xx_radio.c / RadioLib LR11x0_commands.h)
static constexpr uint16_t LR1121_CMD_CALIBRATE = 0x010F
 cross-checked
static constexpr uint16_t LR1121_CMD_CALIBRATE_IMAGE = 0x0111
 cross-checked (RadioLib calibrateImageRejection)
static constexpr uint16_t LR1121_CMD_SET_DIO_AS_RF_SWITCH = 0x0112
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_DIO_IRQ_PARAMS = 0x0113
 cross-checked
static constexpr uint16_t LR1121_CMD_CLEAR_IRQ = 0x0114
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_TCXO_MODE = 0x0117
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_STANDBY = 0x011C
 cross-checked
static constexpr uint16_t LR1121_CMD_GET_RX_BUFFER_STATUS = 0x0203
 cross-checked
static constexpr uint16_t LR1121_CMD_GET_PKT_STATUS
 cross-checked (Semtech SWDR001 lr11xx_radio.c :: lr11xx_radio_get_gfsk_pkt_status — 0 request params, 4-byte GFSK response: [rssi_sync, rssi_avg, rx_len, status_flags], rssi_sync/avg both decode via -(raw>>1) dBm, same formula as LR1121_CMD_GET_RSSI_INST)
static constexpr uint16_t LR1121_CMD_GET_RSSI_INST = 0x0205
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_GFSK_SYNC_WORD = 0x0206
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_RX = 0x0209
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_TX = 0x020A
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_RF_FREQUENCY = 0x020B
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_PACKET_TYPE = 0x020E
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_MODULATION_PARAMS = 0x020F
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_PACKET_PARAMS = 0x0210
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_TX_PARAMS = 0x0211
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_RX_TX_FALLBACK_MODE = 0x0213
 cross-checked
static constexpr uint16_t LR1121_CMD_SET_PA_CONFIG = 0x0215
 cross-checked
static constexpr uint32_t LR1121_IRQ_TX_DONE = 1UL << 2
static constexpr uint32_t LR1121_IRQ_RX_DONE = 1UL << 3
static constexpr uint32_t LR1121_IRQ_PREAMBLE_DETECTED = 1UL << 4
static constexpr uint32_t LR1121_IRQ_SYNC_WORD_VALID = 1UL << 5
static constexpr uint32_t LR1121_IRQ_CRC_ERR = 1UL << 7
static constexpr uint32_t LR1121_IRQ_TIMEOUT = 1UL << 10
static constexpr uint32_t LR1121_IRQ_ACTIVITY_MASK
 IRQ bits that represent a terminal radio event — a frame finished decoding, an outbound frame completed, or the chip gave up on its own.
static constexpr uint32_t LR1121_IRQ_DIO_ENABLE_MASK
 DIO-routed IRQ enable mask: TxDone|RxDone|PreambleDetected|SyncWordValid|Timeout (design implementation §Step 2, item 2 — deliberately excludes CrcErr from the DIO-routed set, unlike SX1262; CrcErr is still visible in the raw status word for capture diagnostics).
static constexpr uint8_t LR1121_DEVICE_TYPE = 0x03
 cross-checked (design §1.2 "Identity" row)
static constexpr uint8_t LR1121_KNOWN_LATEST_FW_MAJOR = 0x01
 Newest LR1121 transceiver firmware known at the time this file was last updated, per the version-numbered filenames and CHANGELOG.md at https://github.com/Lora-net/radio_firmware_images/tree/master/lr1121/transceiver — the same two bytes GetVersion reports as fw_major/fw_minor (e.g.
static constexpr uint8_t LR1121_KNOWN_LATEST_FW_MINOR = 0x04
static constexpr uint8_t LR1121_PACKET_TYPE_GFSK = 0x01
 cross-checked (design §3.2 step 5)
static constexpr uint8_t LR1121_GFSK_CRC_OFF = 0x01
 cross-checked (same encoding as SX126x)
static constexpr uint8_t LR1121_GFSK_PACKET_FIXED_LENGTH = 0x00
 cross-checked (same encoding as SX126x)
static constexpr uint8_t LR1121_PREAMBLE_DETECTOR_16_BIT = 0x05
 Preamble detector length selector: 16 bits.
static constexpr uint8_t LR1121_SYNC_WORD_PARAM_24_BITS = 0x18
 Sync word length: 24 bits, encoded as a literal bit count — cross-checked, identical encoding to SX1262's SX1262_SYNC_WORD_PARAM_24_BITS.
static constexpr uint8_t LR1121_CALIBRATE_ALL_BLOCKS = 0x3F
 Calibrate "all blocks" bitmask.
static constexpr uint8_t LR1121_FALLBACK_STDBY_XOSC = 0x02
 SetRxTxFallbackMode value for STDBY_XOSC.
static constexpr uint32_t LR1121_REG_HIGH_ACP_WORKAROUND_ADDR = 0x00F30054
 High-ACP (adjacent channel power) TX-quality erratum: clear bit 30 of this register before every SetRx/SetTx.
static constexpr uint32_t LR1121_REG_HIGH_ACP_WORKAROUND_MASK = 1UL << 30
static constexpr uint32_t LR1121_REG_HIGH_ACP_WORKAROUND_VALUE = 0x00000000
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_1_ADDR = 0x00F20344
 GFSK modulation workaround register trio, standard (non-0.6/1.2kbps) values for our 38.4kbps config — applied after every modulation-params write, mirroring RadioLib's workaroundGFSK() ("always the first step, even when resetting" per its own comment on the first write).
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_1_MASK = 0x00000030
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_1_VALUE = 0x00000010
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_2_ADDR = 0x00F20348
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_2_MASK = 0x00000005
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_2_VALUE = 0x00000001
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_3_ADDR = 0x00F20244
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_3_MASK = 0x0001FF03
static constexpr uint32_t LR1121_REG_GFSK_WORKAROUND_3_VALUE = 0x00000A01
static constexpr uint8_t LR1121_IMAGE_CAL_FREQ1 = 0xD7
 Banded image calibration for 868.25-869.85MHz +/-4MHz (~860-876MHz), matching RadioLib's setFrequency() margin.
static constexpr uint8_t LR1121_IMAGE_CAL_FREQ2 = 0xDB
static constexpr uint8_t LR1121_RFSWITCH_ENABLE_DIO5_DIO6 = 0x03
 DIO5 + DIO6 are switch pins.
static constexpr uint8_t LR1121_RFSWITCH_STANDBY = 0x00
 Both low.
static constexpr uint8_t LR1121_RFSWITCH_RX = 0x01
 DIO5 high.
static constexpr uint8_t LR1121_RFSWITCH_TX = 0x02
 DIO6 high (both LP and HP PA).
static constexpr uint8_t LR1121_RFSWITCH_TX_HP = 0x02
 Same as TX (LP PA only used today).
static constexpr uint8_t LR1121_RFSWITCH_TX_HF = 0x00
 2.4GHz path unused; both low.
static constexpr uint8_t LR1121_RFSWITCH_GNSS = 0x00
 Unused; both low.
static constexpr uint8_t LR1121_RFSWITCH_WIFI = 0x00
 Unused; both low.
static constexpr uint8_t LR1121_TCXO_STARTUP_DELAY_TICKS_MSB = 0x00
 LR1121 TCXO voltage on the T3-S3 board — 3.0V, confirmed on real hardware.
static constexpr uint8_t LR1121_TCXO_STARTUP_DELAY_TICKS_MID = 0x01
static constexpr uint8_t LR1121_TCXO_STARTUP_DELAY_TICKS_LSB = 0x40
 0x140 ticks at 30.52us/tick (32.768kHz RTC) is ~9.8ms, not the ~5ms the SX1262-derived comment used to claim (that chip's tick base differs) — harmless either way (longer startup is safe).
static constexpr int32_t LR1121_EXCHANGE_RESPONSE_WAIT_SLICE_MS = 600
 LR1121-specific per-channel dwell while waiting for authenticated exchange responses.
static const uint8_t UART_PROBE_MAX_BIT_OFFSET = 10
 Maximum bit offset to search for valid UART decode start position.
static constexpr uint8_t UART_CELL_BITS = 10
 Bits an on-air UART cell spends per protocol byte: start(1) + data(8) + stop(1).
static const char *const TAG = "home_io_control.soft_phy"
static constexpr uint8_t SOFT_PHY_RX_PROBE_PACKET_LEN = 48
 Fixed raw-RX probe length: chosen from captures of 23-25 byte protocol frames after UART packing and CRC appending — the longest frame (25 bytes + 2 CRC) UART-packs to 34 raw bytes, so 48 bytes preserves complete traffic (with margin for leading noise before the frame start) without relying on either chip's variable-length engine.
static constexpr uint32_t SOFT_PHY_ALL_IRQ_BITS = 0xFFFFFFFF
 Sentinel meaning "every IRQ bit counts as activity" — the default for SoftPhyDriverBase::activity_irq_mask, correct for chips (SX1262) whose hardware-level IRQ mask already excludes the one bit (PreambleDetected) that would need special handling.
static constexpr uint8_t SOFT_PHY_EARLY_HEADER_RAW_BYTES = 3
 Raw bytes read in the first stage of a length-driven receive — enough to hold CTRL0's UART cell (10 bits) at any of the probe's bit alignments (up to 9 bits of slack).
static constexpr uint8_t SOFT_PHY_EARLY_READ_MARGIN_BYTES = 2
 Air-time margin added before every mid-reception buffer read, in raw bytes.
static constexpr uint32_t SOFT_PHY_EARLY_POLL_US = 100
 Poll interval while waiting out a frame's remaining air time, in microseconds.
static constexpr uint32_t SOFT_PHY_EARLY_MIN_WINDOW_MS = 12
 Smallest receive window a length-driven receive will be attempted in, in milliseconds.
static constexpr uint32_t SOFT_PHY_LINE_RATE_BPS = 38400
 Protocol line rate. The same 38400 bps every driver programs into its own bitrate register.
static constexpr uint32_t SOFT_PHY_US_PER_SECOND = 1000000
 Microseconds in a second, for the air-time arithmetic below.
static const char *const TAG = "home_io_control.sx1262"
static const uint8_t SX1262_SYNC_WORD_PARAM_24_BITS = 0x18
static constexpr uint8_t SX1262_SET_STANDBY = 0x80
static constexpr uint8_t SX1262_SET_RX = 0x82
static constexpr uint8_t SX1262_SET_TX = 0x83
static constexpr uint8_t SX1262_SET_RF_FREQUENCY = 0x86
static constexpr uint8_t SX1262_SET_RX_TX_FALLBACK_MODE = 0x93
static constexpr uint8_t SX1262_WRITE_BUFFER = 0x0E
static constexpr uint8_t SX1262_READ_BUFFER = 0x1E
static constexpr uint8_t SX1262_SET_DIO_IRQ_PARAMS = 0x08
static constexpr uint8_t SX1262_GET_IRQ_STATUS = 0x12
static constexpr uint8_t SX1262_GET_PACKET_STATUS = 0x14
static constexpr uint8_t SX1262_GET_DEVICE_ERRORS = 0x17
static constexpr uint8_t SX1262_CLEAR_IRQ_STATUS = 0x02
static constexpr uint8_t SX1262_CLEAR_DEVICE_ERRORS = 0x07
static constexpr uint8_t SX1262_SET_PACKET_TYPE = 0x8A
static constexpr uint8_t SX1262_SET_MODULATION_PARAMS = 0x8B
static constexpr uint8_t SX1262_SET_PACKET_PARAMS = 0x8C
static constexpr uint8_t SX1262_SET_BUFFER_BASE_ADDRESS = 0x8F
static constexpr uint8_t SX1262_SET_PA_CONFIG = 0x95
static constexpr uint8_t SX1262_SET_TX_PARAMS = 0x8E
static constexpr uint8_t SX1262_SET_DIO2_AS_RF_SWITCH_CTRL = 0x9D
static constexpr uint8_t SX1262_SET_DIO3_AS_TCXO_CTRL = 0x97
static constexpr uint8_t SX1262_CALIBRATE = 0x89
static constexpr uint8_t SX1262_CALIBRATE_IMAGE = 0x98
static constexpr uint8_t SX1262_GET_RX_BUFFER_STATUS = 0x13
static constexpr uint8_t SX1262_GET_RSSI_INST = 0x15
static constexpr uint8_t SX1262_SET_REGULATOR_MODE = 0x96
static constexpr uint8_t SX1262_GET_STATUS = 0xC0
static constexpr uint8_t SX1262_WRITE_REGISTER = 0x0D
static constexpr uint8_t SX1262_READ_REGISTER = 0x1D
static constexpr uint16_t SX1262_IRQ_TX_DONE = 0x0001
static constexpr uint16_t SX1262_IRQ_RX_DONE = 0x0002
static constexpr uint16_t SX1262_IRQ_PREAMBLE_DETECTED = 0x0004
static constexpr uint16_t SX1262_IRQ_SYNC_WORD_VALID = 0x0008
static constexpr uint16_t SX1262_IRQ_CRC_ERR = 0x0040
static constexpr uint16_t SX1262_REG_SYNC_WORD = 0x06C0
static constexpr uint16_t SX1262_REG_RX_GAIN = 0x08AC
static constexpr uint16_t SX1262_REG_TX_CLAMP_CONFIG = 0x08D8
static constexpr uint16_t SX1262_REG_TX_MODULATION = 0x0889
 TX modulation-quality erratum register (SX1262 datasheet §15.1, "Modulation Quality with 500 kHz LoRa Bandwidth" — the title names LoRa, but the workaround table covers every modulation).
static constexpr uint8_t SX1262_TX_MODULATION_GFSK_BIT = 0x04
 Bit 2 of SX1262_REG_TX_MODULATION — the (G)FSK-correct value is 1.
static constexpr uint8_t SX1262_TX_BUFFER_BASE = 0x00
 Data-buffer split programmed by configure_buffer_base(): TX packets build from 0x00, RX packets land at 0x80.
static constexpr uint8_t SX1262_RX_BUFFER_BASE = 0x80
static constexpr uint8_t SX1262_GFSK_PACKET_TYPE_KNOWN_LENGTH = 0x00
static constexpr uint8_t SX1262_GFSK_CRC_OFF = 0x01
static constexpr uint8_t SX1262_FALLBACK_STDBY_XOSC = 0x30
static constexpr int32_t SX1262_EXCHANGE_RESPONSE_WAIT_SLICE_MS = 90
 SX1262-specific per-channel dwell while waiting for authenticated exchange responses.
static const char *const TAG = "home_io_control.sx1276"
static constexpr uint8_t REG_FIFO = 0x00
 FIFO read/write access.
static constexpr uint8_t REG_OP_MODE = 0x01
 Operating mode (sleep/standby/tx/rx).
static constexpr uint8_t REG_BITRATE_MSB = 0x02
 Bit rate MSB = FXOSC / bitrate.
static constexpr uint8_t REG_BITRATE_LSB = 0x03
static constexpr uint8_t REG_FDEV_MSB = 0x04
 Frequency deviation MSB.
static constexpr uint8_t REG_FDEV_LSB = 0x05
static constexpr uint8_t REG_FRF_MSB = 0x06
 Carrier frequency MSB (freq = FRF * FXOSC / 2^19).
static constexpr uint8_t REG_FRF_MID = 0x07
static constexpr uint8_t REG_FRF_LSB = 0x08
static constexpr uint8_t REG_PA_CONFIG = 0x09
 Power amplifier config (pin select + power level).
static constexpr uint8_t REG_PA_RAMP = 0x0A
 PA ramp time and modulation shaping.
static constexpr uint8_t REG_LNA = 0x0C
 Low noise amplifier gain and boost.
static constexpr uint8_t REG_RX_CONFIG = 0x0D
 Receiver configuration (AFC, AGC, trigger).
static constexpr uint8_t REG_RSSI_CONFIG = 0x0E
 RSSI smoothing.
static constexpr uint8_t REG_RX_BW = 0x12
 Receiver bandwidth.
static constexpr uint8_t REG_AFC_BW = 0x13
 AFC bandwidth.
static constexpr uint8_t REG_AFC_FEI = 0x1A
 AFC auto clear.
static constexpr uint8_t REG_PREAMBLE_DETECT = 0x1F
 Preamble detector config.
static constexpr uint8_t REG_OSC = 0x24
 Oscillator / clock output.
static constexpr uint8_t REG_RSSI_VALUE = 0x11
 Instant RSSI value in FSK mode.
static constexpr uint8_t REG_PREAMBLE_MSB = 0x25
 TX preamble length MSB.
static constexpr uint8_t REG_PREAMBLE_LSB = 0x26
static constexpr uint8_t REG_SYNC_CONFIG = 0x27
 Sync word config (size, polarity, enable).
static constexpr uint8_t REG_SYNC_VALUE1 = 0x28
 Sync word byte 1 (registers 0x28-0x2F for bytes 1-8).
static constexpr uint8_t REG_PACKET_CONFIG1 = 0x30
 Packet format, CRC, encoding.
static constexpr uint8_t REG_PACKET_CONFIG2 = 0x31
 Packet mode, IoHomeOn, PowerFrame.
static constexpr uint8_t REG_PAYLOAD_LENGTH = 0x32
 Max payload length.
static constexpr uint8_t REG_FIFO_THRESH = 0x35
 FIFO threshold for TX start condition.
static constexpr uint8_t REG_IRQ_FLAGS1 = 0x3E
 IRQ flags: mode ready, preamble detect, etc.
static constexpr uint8_t REG_IRQ_FLAGS2 = 0x3F
 IRQ flags: FIFO full/empty, payload ready, CRC ok.
static constexpr uint8_t REG_DIO_MAPPING1 = 0x40
 DIO0-DIO3 pin mapping.
static constexpr uint8_t REG_DIO_MAPPING2 = 0x41
 DIO4-DIO5 pin mapping.
static constexpr uint8_t REG_VERSION = 0x42
 Chip version (should read 0x12 for SX1276).
static constexpr uint8_t REG_PLLHOP = 0x44
 PLL hop: fast frequency change without standby.
static constexpr uint8_t REG_IMAGE_CAL = 0x3B
 Image calibration.
static constexpr uint8_t MODE_SLEEP = 0x00
static constexpr uint8_t MODE_STDBY = 0x01
static constexpr uint8_t MODE_TX = 0x03
static constexpr uint8_t MODE_RX = 0x05
static constexpr uint8_t MODE_MASK = 0x07
static constexpr uint32_t FXOSC = 32000000U
 SX1276 crystal oscillator frequency (32 MHz).
static constexpr uint32_t MAX_TRACKED_STATUS_POLL_WINDOW_MS = 600000
 Hard stop for bounded follow-up polling after a command or remote activity.
static constexpr uint32_t INITIAL_STATUS_REQUEST_DELAY_MS = 5000
 Delay before the first post-boot status request from an entity.
static constexpr uint32_t REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS = 2000
 Delay before polling after overheard remote traffic.
static constexpr uint32_t ONEWAY_QUIET_PERIOD_MS = 700
 Hold queued background polls back for this long after any 1W frame, so a poll the hub itself scheduled does not occupy the (half-duplex) radio while the remote is still transmitting.
static constexpr uint32_t ONEWAY_POLL_DEFER_CAP_MS = 5000
 Hard cap on how long sustained 1W traffic may hold a background poll back in total, measured from the start of the burst rather than the most recent frame.
static constexpr uint32_t DEFAULT_SETTLE_POLL_DELAY_MS = 3000
 Default follow-up settle-poll delay used while a device may still be moving, when no explicit poll interval is configured (interval_ms == 0).
static constexpr uint32_t STOP_SETTLE_POLL_CAP_MS = 1000
 Upper bound on the settle-poll delay after a STOP command.
static constexpr uint16_t SX1262_RESPONSE_PREAMBLE = 8
 SX1262-specific preamble for response/continuation frames within an exchange.
static constexpr uint16_t SX1262_POST_TX_SETTLE_US = 500
 SX1262-specific post-TX settling delay before re-entering RX.
static constexpr uint16_t SX1276_RESPONSE_PREAMBLE = 12
 SX1276 preamble for response/continuation frames within an exchange.
static constexpr uint16_t SX1276_DISCOVERY_HOP_SLICE_MS = 5
 Per-channel dwell while SX1276 pairing discovery hops across channels.
static constexpr uint16_t SX1262_DISCOVERY_HOP_SLICE_MS = 200
 Per-channel dwell while SX1262 pairing discovery hops across channels.
static constexpr uint16_t LR1121_RESPONSE_PREAMBLE = SX1262_RESPONSE_PREAMBLE
 LR1121-specific preamble for response/continuation frames within an exchange.
static constexpr uint16_t LR1121_POST_TX_SETTLE_US = SX1262_POST_TX_SETTLE_US
 LR1121-specific post-TX settling delay before re-entering RX.
static constexpr uint16_t LR1121_DISCOVERY_HOP_SLICE_MS = SX1262_DISCOVERY_HOP_SLICE_MS
 Per-channel dwell while LR1121 pairing discovery hops across channels.
static constexpr TuningNumberParam NUMBER_PARAMS []
static constexpr TuningSelectParam SELECT_PARAMS []
Pairing timing constants

Timeouts and retry limits for the pairing flow's blocking waits.

constexpr uint32_t PAIRING_DISCOVERY_RESPONSE_TIMEOUT_MS = 2000
 Discovery wait window after sending 0x28.
constexpr uint8_t PAIRING_DISCOVERY_MAX_ATTEMPTS = 3
 Retry discovery TX up to this many times.
constexpr uint32_t PAIRING_KEY_CHALLENGE_TIMEOUT_MS = 500
 Wait window for the device's 0x3C challenge.
constexpr uint32_t PAIRING_KEY_CONFIRM_TIMEOUT_MS = 500
 Wait for 0x33 key confirm after sending 0x32.
constexpr uint32_t PAIRING_KEY_CONFIRM_SLICE_MS = 150
 RX slice during key confirm wait (hop each slice).
static constexpr uint8_t ADDRESS_SUFFIX_MASK = 0x3F
 Well-known address suffix values in the broadcast address space.
static constexpr uint8_t ADDRESS_SUFFIX_BROADCAST = 0x3F
 Suffix for "all devices of this type" broadcast.
static constexpr uint8_t ADDRESS_SUFFIX_DISCOVERY = 0x3B
 Suffix for discovery-related broadcasts.
static constexpr uint8_t MANUFACTURER_VELUX = 1
 IO-Homecontrol manufacturer ID constants.
static constexpr uint8_t MANUFACTURER_SOMFY = 2
 Somfy (shutters, awnings, blinds).
static constexpr uint8_t MANUFACTURER_HONEYWELL = 3
 Honeywell.
static constexpr uint8_t MANUFACTURER_HORMANN = 4
 Hörmann (garage doors, gates).
static constexpr uint8_t MANUFACTURER_ASSA_ABLOY = 5
 ASSA ABLOY (locks, access).
static constexpr uint8_t MANUFACTURER_NIKO = 6
 Niko (switches, home automation).
static constexpr uint8_t MANUFACTURER_WINDOW_MASTER = 7
 WINDOW MASTER (ventilation).
static constexpr uint8_t MANUFACTURER_RENSON = 8
 Renson (ventilation, sun protection).
static constexpr uint8_t MANUFACTURER_CIAT = 9
 CIAT (HVAC).
static constexpr uint8_t MANUFACTURER_SECUYOU = 10
 Secuyou (security).
static constexpr uint8_t MANUFACTURER_OVERKIZ = 11
 OVERKIZ (Somfy connectivity platform).
static constexpr uint8_t MANUFACTURER_ATLANTIC_GROUP = 12
 Atlantic Group (heating, hot water).
static constexpr uint8_t ORIGINATOR_LOCAL_USER = 0x00
 Command originator codes indicating what or who triggered a command.
static constexpr uint8_t ORIGINATOR_USER_REMOTE = 0x01
 User sent command from a remote control.
static constexpr uint8_t ORIGINATOR_RAIN_SENSOR = 0x02
 Rain sensor triggered the movement.
static constexpr uint8_t ORIGINATOR_TIMER = 0x03
 Timer or schedule triggered the movement.
static constexpr uint8_t ORIGINATOR_SECURITY = 0x04
 Security controlling device (SCD) action.
static constexpr uint8_t ORIGINATOR_UPS = 0x05
 Uninterruptible power supply action.
static constexpr uint8_t ORIGINATOR_SMART_CONTROLLER = 0x06
 Smart function controller.
static constexpr uint8_t ORIGINATOR_LIFESTYLE = 0x07
 Lifestyle scenario controller.
static constexpr uint8_t ORIGINATOR_SAAC = 0x08
 Stand-alone automatic controller (SAAC).
static constexpr uint8_t ORIGINATOR_WIND_SENSOR = 0x09
 Wind sensor triggered the movement.
static constexpr uint8_t ORIGINATOR_LOAD_SHEDDING = 0x0B
 Load-shedding manager.
static constexpr uint8_t ORIGINATOR_LOCAL_LIGHT = 0x0C
 Local light sensor.
static constexpr uint8_t ORIGINATOR_ENVIRONMENT = 0x0D
 Unspecified environment sensor.
static constexpr uint8_t ORIGINATOR_MYSELF = 0x10
 Actuator decided to move by itself.
static constexpr uint8_t ORIGINATOR_AUTOMATIC_CYCLE = 0xFE
 Automatic cycle / external access.
static constexpr uint8_t ORIGINATOR_EMERGENCY = 0xFF
 Emergency command (never disabled).
static constexpr uint8_t ACEI_VALID_BIT = 0x01
 ACEI byte bit-field definitions.
static constexpr uint8_t ACEI_EXTENDED_MASK = 0x06
 Bits [2:1]: extended field.
static constexpr uint8_t ACEI_EXTENDED_SHIFT = 1
 Shift for extended field extraction.
static constexpr uint8_t ACEI_SERVICE_MASK = 0x18
 Bits [4:3]: service type.
static constexpr uint8_t ACEI_SERVICE_SHIFT = 3
 Shift for service field extraction.
static constexpr uint8_t ACEI_LEVEL_MASK = 0xE0
 Bits [7:5]: priority level (0–7).
static constexpr uint8_t ACEI_LEVEL_SHIFT = 5
 Shift for priority level extraction.
static constexpr uint8_t ACEI_LEVEL_PROTECTION_HUMAN = 0
 ACEI priority level values (0–7).
static constexpr uint8_t ACEI_LEVEL_PROTECTION_SENSOR = 1
 Goods/environment protection via sensors.
static constexpr uint8_t ACEI_LEVEL_USER_HIGH = 2
 High-priority user controller.
static constexpr uint8_t ACEI_LEVEL_USER_DEFAULT = 3
 Default remote controller priority.
static constexpr uint8_t ACEI_LEVEL_COMFORT_1 = 4
 Comfort automation level 1.
static constexpr uint8_t ACEI_LEVEL_COMFORT_2 = 5
 Comfort automation level 2.
static constexpr uint8_t ACEI_LEVEL_AUTO_SAAC = 6
 Stand-alone automatic controller.
static constexpr uint8_t ACEI_LEVEL_AUTO_DEFAULT = 7
 Default automatic level (lowest).
static constexpr uint8_t DISCOVERY_RESP_BACKBONE_OFFSET = 2
 Byte offsets within CMD_DISCOVER_RESP (0x29) payload data.
static constexpr uint8_t DISCOVERY_RESP_MANUFACTURER_OFFSET = 5
 Manufacturer ID at data[5].
static constexpr uint8_t DISCOVERY_RESP_FLAGS_OFFSET = 6
 Flags byte at data[6].
static constexpr uint8_t DISCOVERY_RESP_TIMESTAMP_OFFSET = 7
 Timestamp starts at data[7] (2 bytes).
static constexpr uint8_t DISCOVERY_RESP_FULL_SIZE = 9
 Full discovery response payload size.
static constexpr uint8_t DISCOVERY_FLAGS_ATT_MASK = 0xC0
 Bit masks and shifts for the Multi Information Byte fields.
static constexpr uint8_t DISCOVERY_FLAGS_ATT_SHIFT = 6
 Shift for ATT field extraction.
static constexpr uint8_t DISCOVERY_FLAGS_SYNC_CTRL_GRP = 0x20
 Bit 5: supports sync control group.
static constexpr uint8_t DISCOVERY_FLAGS_RF_SUPPORT = 0x08
 Bit 3: RF support in node (0=yes, 1=no).
static constexpr uint8_t DISCOVERY_FLAGS_POWER_SAVE_MASK = 0x03
 Bits [1:0]: power save mode.
static constexpr uint8_t ATT_CLASS_5S = 0
 Actuator Turnaround Time (ATT) class values.
static constexpr uint8_t ATT_CLASS_10S = 1
 Response within 10 seconds.
static constexpr uint8_t ATT_CLASS_20S = 2
 Response within 20 seconds.
static constexpr uint8_t ATT_CLASS_40S = 3
 Response within 40 seconds.
static constexpr uint8_t POWER_SAVE_ALWAYS_ALIVE = 0
 Power save mode values from the Multi Information Byte.
static constexpr uint8_t POWER_SAVE_LOW_POWER = 1
 Device sleeps — needs long preamble to wake.
Background-poll retry delays after silent failures (no reply received)
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MS = 5000
 First retry after a silent failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP2_MS = 15000
 Second retry after a silent failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP3_MS = 30000
 Third retry after a silent failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP4_MS = 60000
 Fourth retry after a silent failure.
static constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MAX_MS
 Steady-state backoff after many silent failures.
Background-poll retry delays after auth-shaped failures (0x3C challenge seen)
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MS = 30000
 First retry after a challenge-seen failure.
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_STEP2_MS = 120000
 Second retry.
static constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MAX_MS = 300000
 Steady-state after repeated auth failures.

Typedef Documentation

◆ DeviceUpdateCallback

using esphome::home_io_control::DeviceUpdateCallback = std::function<void(const std::string &device_id, const IoDevice &device)>

Callback type invoked when a device's state changes.

Definition at line 23 of file device_registry.h.

Enumeration Type Documentation

◆ AddressClass

enum class esphome::home_io_control::AddressClass : uint8_t
strong

Address classification categories for diagnostic purposes.

IO-Homecontrol uses the target address field to encode both unicast device addresses and broadcast targets. The first byte being 0x00 indicates a broadcast; the remaining bytes encode the target device type.

Enumerator
UNICAST 

Normal device-to-device unicast address (first byte != 0x00).

BROADCAST_ALL 

Broadcast to all devices of a type (address suffix 0x3F).

BROADCAST_TYPE 

Broadcast to specific device type with non-standard suffix.

DISCOVERY 

Discovery-related broadcast (address suffix 0x3B).

UNKNOWN_BROADCAST 

Broadcast pattern that does not match known suffixes.

Definition at line 95 of file proto_codecs.h.

◆ BootloaderMismatch

enum class esphome::home_io_control::BootloaderMismatch : uint8_t
strong

Direction of a bootloader/target mismatch, for messaging.

lr1121_flash_decision()'s REJECT_BOOTLOADER_TOO_OLD verdict fires whenever lr1121_bootloader_supports_target() returns UNSUPPORTED, which covers both directions: the target needs a newer bootloader than this chip has (the only direction reachable before the bootloader-update feature existed), and the target needs an OLDER bootloader than this chip has – a downgrade, unreachable until a chip can actually be running 0x2101. Used for messaging only, in both the transceiver-only and bootloader-update builds – it never changes lr1121_flash_decision()'s own verdict.

Enumerator
NONE 

target_fw is unknown, or its required bootloader matches bootloader_version.

TARGET_NEEDS_NEWER 

The "too old" direction – what REJECT_BOOTLOADER_TOO_OLD has always meant until now.

TARGET_NEEDS_OLDER 

The "too new" direction – a downgrade, newly reachable once this feature ships.

Definition at line 155 of file lr1121_firmware_decisions.h.

◆ BootloaderSupport

enum class esphome::home_io_control::BootloaderSupport : uint8_t
strong

Whether a target firmware version is known to work with a given bootloader version.

Enumerator
SUPPORTED 

Both versions known, and the pairing is in LR1121_KNOWN_BOOTLOADER_REQUIREMENTS.

UNSUPPORTED 

target_fw is known, but not paired with this bootloader_version.

UNKNOWN_TARGET 

target_fw does not appear in LR1121_KNOWN_BOOTLOADER_REQUIREMENTS at all.

Definition at line 111 of file lr1121_firmware_decisions.h.

◆ BootloaderUpgradePath

Whether the three-stage bootloader-rewrite sequence (ADR 0021) is applicable, and if not, why.

Enumerator
NOT_APPLICABLE 

No block, or no upgrade needed/possible to evaluate. Keep the original verdict.

AVAILABLE 

Three-stage is possible. Still requires the arming switch to actually run.

BLOCKED_UNKNOWN_TARGET 

Block present, but this build cannot know what the target needs.

BLOCKED_BOOTLOADER_NEWER 

Target needs an OLDER bootloader. Not reachable today, likely never.

Definition at line 173 of file lr1121_firmware_decisions.h.

◆ CoverCommand

enum class esphome::home_io_control::CoverCommand : uint8_t
strong

Named device commands for cover-type actuators.

These represent the discrete non-positional actions a controller can send to a cover device. Each maps to a specific wire encoding in the CMD_EXECUTE payload. Using this enum avoids conflating numeric positions (0–100) with command codes.

Enumerator
STOP 

Stop movement immediately.

FAVORITE 

Move to stored favorite/"My" position.

VENT 

Move to ventilation position (window-type devices).

FORCE_OPEN 

Move to fully open at elevated priority; intended to bypass soft locks and environmental limits (confirmed on real hardware to move correctly; bypassing an active lock is still unconfirmed — see create_force_open() in proto_commands.cpp).

Definition at line 187 of file proto_device_model.h.

◆ DeviceCapabilityClass

High‑level capability class derived from DeviceType.

Enumerator
UNKNOWN 

Unknown capability.

COVER 

Position‑controlled cover (shutter/blind/awning).

LIGHT 

Binary on/off light.

SWITCH 

Binary on/off switch.

SENSOR 

Sensor device.

BEACON 

Beacon.

CLIMATE 

Climate device (heating/cooling).

LOCK 

Lock.

Definition at line 54 of file proto_device_model.h.

◆ DeviceNameValidationError

Validation result for outbound device-name writes.

Enumerator
NONE 

Name is valid and encodable.

EMPTY 

Name is empty after normalization.

TOO_LONG 

Name exceeds the 15-character write limit.

INVALID_UTF8 

Name contains malformed UTF-8 bytes.

UNSUPPORTED_CHAR 

Name contains characters outside Latin-1.

Definition at line 34 of file proto_codecs.h.

◆ DeviceType

enum class esphome::home_io_control::DeviceType : uint8_t
strong

Device type identifiers reported by IO‑Homecontrol products.

The numeric values follow the official specification. Do not reassign or reorder these.

Enumerator
UNKNOWN 

Unknown/unspecified device.

VENETIAN_BLIND 

Venetian blind.

ROLLER_SHUTTER 

Roller shutter.

AWNING 

Awning.

WINDOW_OPENER 

Window opening actuator.

GARAGE_OPENER 

Garage door opener.

LIGHT 

Binary light.

GATE_OPENER 

Gate opener.

ROLLING_DOOR_OPENER 

Rolling door opener.

LOCK 

Lock.

BLIND 

Generic blind.

SCREEN 

Insect/privacy screen.

BEACON 

Beacon (unpaired/announcement).

DUAL_SHUTTER 

Dual-section shutter.

HEATING_TEMPERATURE_INTERFACE 

Heating temperature interface.

ON_OFF_SWITCH 

Generic on/off switch.

HORIZONTAL_AWNING 

Horizontal awning (open/close inverted).

EXTERNAL_VENETIAN_BLIND 

External venetian blind.

LOUVRE_BLIND 

Louvre blind.

CURTAIN_TRACK 

Curtain track.

VENTILATION_POINT 

Ventilation point.

EXTERIOR_HEATING 

Exterior heating.

HEAT_PUMP 

Heat pump.

INTRUSION_ALARM 

Intrusion alarm.

SWINGING_SHUTTER 

Swinging shutter.

Definition at line 25 of file proto_device_model.h.

◆ DiscoveryCommand

enum class esphome::home_io_control::DiscoveryCommand : uint8_t
strong

Discovery request command codes.

Enumerator
DISCOVER 

Standard broadcast discovery request (to 0x00003B).

DISCOVER_SPE 

SPE roll-call request (self-authenticating; see CMD_DISCOVER_SPE_REQ).

Deliberately not offered as a pairing_discovery_commands preset in tuning.py: only devices that already hold the system key answer it, so it can never help reach a device in learning mode. Retained here because the command byte is still needed to send a roll-call, and because discovery_command_from_string() stays permissive enough to parse it — do not remove either as dead code.

DISCOVER_ALT 

Alternate broadcast discovery (to 0x00003F), with optional payload byte.

Definition at line 71 of file tuning_config.h.

◆ FlashDecision

enum class esphome::home_io_control::FlashDecision : uint8_t
strong

Outcome of lr1121_flash_decision().

Enumerator
PROCEED 

Safe to erase and write.

ALREADY_INSTALLED 

target_fw == installed_fw (both known) — the post-success state.

NEEDS_CONFIRMATION 

Not unsafe, but not an unambiguous "yes" either — needs a second press.

REJECT_WRONG_CHIP 

device_type or bootloader_version doesn't identify an LR1121.

REJECT_BOOTLOADER_TOO_OLD 

target_fw is known and positively incompatible with this bootloader.

Definition at line 234 of file lr1121_firmware_decisions.h.

◆ LR1121RxBandwidth

enum class esphome::home_io_control::LR1121RxBandwidth : uint8_t
strong

Valid LR1121 RX bandwidth options (register values).

NOT the same encoding as SX1262, despite the earlier design assumption ("same encoding, same table") that this enum used to be a type alias of SX1262RxBandwidth on. 2026-07-17 hardware bring-up cross-checked the actual byte values against RadioLib's LR11x0_commands.h and found two of the five borrowed SX1262 values were wrong for this chip: the byte reused here for "156.2 kHz" actually selects 467.0 kHz on real LR1121 silicon, and the byte reused for "187.2 kHz" isn't a valid GFSK bandwidth code at all. This is now its own distinct enum with every value confirmed against RadioLib, plus two narrower options (39.0/46.9 kHz) added for tuning-bed experimentation — SX1276's own default (41.7 kHz, see SX1276RxBandwidth) is documented as validated against real devices, notably narrower than LR1121/SX1262's shared 117.3 kHz default, and a plausible lever for the marginal reception seen during bring-up.

Enumerator
BW_39_0_KHZ 

39.0 kHz — narrowest; close to SX1276's validated 41.7 kHz default.

BW_46_9_KHZ 

46.9 kHz — narrow.

BW_58_6_KHZ 

58.6 kHz.

BW_78_2_KHZ 

78.2 kHz.

BW_117_3_KHZ 

117.3 kHz — default.

BW_156_2_KHZ 

156.2 kHz — wider tolerance for LO offset.

BW_187_2_KHZ 

187.2 kHz — widest selectable option.

Definition at line 60 of file tuning_config.h.

◆ PairingOutcome

enum class esphome::home_io_control::PairingOutcome : uint8_t
strong

Final disposition of a pairing attempt, used by the result sensor string.

Enumerator
NONE 

No attempt has completed yet (initial state).

PAIRED 

All three phases completed successfully.

NO_RESPONSE 

No device responded to discovery.

INVALID_RESPONSE 

Discovery saw traffic but nothing valid.

KEY_EXCHANGE_FAILED 

Discovery succeeded but the key exchange did not complete.

CONFIG_FAILED 

Key exchange succeeded but SetConfig1 failed (still counted as paired).

Definition at line 57 of file pairing_telemetry.h.

◆ PairingTelemetryEventKind

Kind of a recorded telemetry event.

Enumerator
TX 

We transmitted a frame.

RX 

We received and accepted a frame for the current wait.

RX_REJECT 

We received a frame that parsed but was rejected (wrong source, wrong command, etc.).

LBT_DEFER 

A listen-before-talk check deferred a transmit because the channel was busy.

HOP 

The radio hopped to a different channel while waiting.

PHASE 

The pairing state machine advanced to a new phase.

Definition at line 28 of file pairing_telemetry.h.

◆ PendingOperationType

Discriminator for entries in the pending-operation deque.

Enumerator
SET_POSITION 

set_device_position call (position 0–100 or special values).

SET_TILT 

set_device_tilt call (tilt percentage 0–100).

SET_POSITION_AND_TILT 

Combined set_device_position_and_tilt call.

DEVICE_COMMAND 

Named device command (STOP, FAVORITE, VENT).

SET_LIGHT_STATE 

set_light_state call (binary on/off).

SET_LOCK_STATE 

set_lock_state call (locked/unlocked).

SET_SWITCH_STATE 

set_switch_state call (binary on/off).

REQUEST_STATUS 

request_device_status call (poll for current position).

REQUEST_NAME 

request_device_name call (poll for stored device name).

DISCOVER_AND_PAIR 

discover_and_pair call (starts 3-phase pairing flow).

Definition at line 27 of file operation_queue.h.

◆ ScanAddResult

enum class esphome::home_io_control::ScanAddResult : uint8_t
strong

Outcome of add_scan_responder(), so callers can tell a harmless repeat from real loss.

Enumerator
ADDED 

New responder recorded.

DUPLICATE 

Already recorded from an earlier reply; nothing changed.

FULL 

Dropped: SCAN_MAX_REPLIES distinct responders already recorded.

Definition at line 493 of file management_actions.cpp.

◆ SX1262RxBandwidth

enum class esphome::home_io_control::SX1262RxBandwidth : uint8_t
strong

Valid SX1262 RX bandwidth options (kHz register values).

The numeric values are the register-encoded (double-sideband) bandwidth selectors used by RadioSX1262::set_rx_bandwidth().

Enumerator
BW_58_6_KHZ 

58.6 kHz — narrowest; SX1276-equivalent width, marginal on the default TX→RX turnaround.

BW_78_2_KHZ 

78.2 kHz — narrow.

BW_117_3_KHZ 

117.3 kHz — default.

BW_156_2_KHZ 

156.2 kHz — wider tolerance for LO offset.

BW_187_2_KHZ 

187.2 kHz — widest selectable option.

Definition at line 26 of file tuning_config.h.

◆ SX1276RxBandwidth

enum class esphome::home_io_control::SX1276RxBandwidth : uint8_t
strong

Valid SX1276 RX bandwidth options (RegRxBw register bytes).

The numeric values are the SX1276 RegRxBw encodings (RxBwMant in bits[4:3], RxBwExp in bits[2:0]) written verbatim to both REG_RX_BW and REG_AFC_BW. Double-sideband bandwidth = FXOSC / (RxBwMant * 2^(RxBwExp+2)) with FXOSC = 32 MHz. Narrower rejects more out-of-band noise (higher sensitivity); wider tolerates more LO frequency offset.

Enumerator
BW_20_8_KHZ 

20.8 kHz — narrowest; maximal noise rejection, least LO-offset tolerance.

BW_41_7_KHZ 

41.7 kHz — default (validated against real devices).

BW_62_5_KHZ 

62.5 kHz.

BW_83_3_KHZ 

83.3 kHz.

BW_125_0_KHZ 

125.0 kHz — widest selectable option.

Definition at line 40 of file tuning_config.h.

Function Documentation

◆ acei_level_name()

const char * esphome::home_io_control::acei_level_name ( uint8_t level)

Get a human-readable name for an ACEI priority level (0–7).

Priority levels form a hierarchy: level 0 (human protection) is highest and overrides all others. Level 3 is the default for remote controllers.

Parameters
levelPriority level value (0–7).
Returns
Null-terminated string such as "user_default" or "protection_sensor".

Definition at line 209 of file proto_constants.cpp.

◆ add_scan_responder()

ScanAddResult esphome::home_io_control::add_scan_responder ( ScanResponder * responders,
uint8_t & count,
uint8_t capacity,
const IoFrame & frame,
int16_t rssi_dbm )
static

Record a responder unless its address is already present.

Deduplication is by node ID across the whole scan, so a device that answers several of the three attempts — or twice inside one attempt — still yields one entry. The duplicate check runs before the capacity check so that repeat replies from already-recorded devices never look like overflow once the array is full.

Parameters
respondersAccumulated array, appended to in place.
countIn: entries already present. Out: updated count.
capacityMaximum entries responders can hold.
frameReply frame to decode and store.
rssi_dbmRSSI of that reply.
Returns
Which of the three outcomes occurred.

Definition at line 511 of file management_actions.cpp.

Here is the call graph for this function:

◆ address_class_name()

const char * esphome::home_io_control::address_class_name ( AddressClass address_class)

Get a human-readable name for an address classification.

Parameters
address_classClassification returned by classify_address().
Returns
Null-terminated string such as "broadcast_all" or "unicast".

Definition at line 207 of file proto_codecs.cpp.

◆ apply_error_response()

bool esphome::home_io_control::apply_error_response ( const IoFrame & response,
ManagementActionResult & result )
static

Decode a CMD_ERROR_RESP frame's result code into result.

Populates has_result_code/result_code but deliberately leaves result.message untouched: rename and identify_device report different wording for the same decoded code, so message composition stays with each caller. On an empty error response, sets a stock message itself (there is no code to report) and returns false; callers should treat that the same way as a decoded code, just without result-code-specific wording.

Parameters
responseFrame whose cmd is CMD_ERROR_RESP.
resultResult to populate.
Returns
true if a result code was decoded, false if the response carried no data.

Definition at line 214 of file management_actions.cpp.

◆ att_class_name()

const char * esphome::home_io_control::att_class_name ( uint8_t att_class)

Get a human-readable turnaround time string for an ATT class value.

Parameters
att_classATT class (0–3) extracted from the Multi Information Byte.
Returns
Null-terminated string such as "5s", "10s", "20s", or "40s".

Definition at line 144 of file proto_constants.cpp.

◆ bool_to_string()

std::string esphome::home_io_control::bool_to_string ( bool value)
static

Definition at line 154 of file management_actions.cpp.

◆ broadcast_target_type()

DeviceType esphome::home_io_control::broadcast_target_type ( const uint8_t addr[NODE_ID_SIZE])

Extract the target device type from a typed broadcast address.

Broadcast addresses encode the device type in bits [9:2] of the combined address bytes 1–2. This function extracts that type. Returns UNKNOWN if the address is not a broadcast (first byte != 0x00).

Parameters
addrThree-byte broadcast address.
Returns
DeviceType encoded in the address, or DeviceType::UNKNOWN for unicast.

Definition at line 223 of file proto_codecs.cpp.

◆ build_device_yaml_snippet()

std::string esphome::home_io_control::build_device_yaml_snippet ( DeviceType type,
uint8_t subtype,
const std::string & device_id,
bool metadata_complete,
bool inverted )

Build the ready-to-paste YAML block describing a device, for both a fully-decoded device and one whose type/subtype wasn't reported.

With metadata_complete == false, the type/subtype are unknown, so the returned snippet uses a <cover|light|switch|lock> platform placeholder and a commented-out io_device_type explanation; type, subtype, and inverted are ignored in this case.

With metadata_complete == true, the snippet names the concrete ESPHome platform for type and fills in io_subtype and (for an inverted cover) invert_position: true. If type has no known ESPHome platform, an empty string is returned instead — the caller decides what to say when there's no snippet to show.

Parameters
typeDecoded device type.
subtypeDecoded device subtype; only used when metadata_complete is true.
device_idHex device ID string (e.g. "38B4A1").
metadata_completeWhether the discovery response included type/subtype metadata.
invertedWhether the device's open/close positions are swapped; only used when metadata_complete is true and type is a cover.
Returns
Multi-line YAML snippet, or an empty string when metadata_complete is true but type maps to no ESPHome platform.

Definition at line 364 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ bytes_to_hex()

void esphome::home_io_control::bytes_to_hex ( const uint8_t * data,
uint8_t len,
char * out,
size_t out_size )
inline

Definition at line 22 of file log_frame.h.

◆ classify_address()

AddressClass esphome::home_io_control::classify_address ( const uint8_t addr[NODE_ID_SIZE])

Classify an IO-Homecontrol 3-byte address.

Determines whether an address is unicast, a typed broadcast, or a discovery-related broadcast based on protocol addressing rules.

Parameters
addrThree-byte node address to classify.
Returns
Classification indicating the address type.

Definition at line 183 of file proto_codecs.cpp.

◆ command_carries_key_material()

bool esphome::home_io_control::command_carries_key_material ( uint8_t cmd)
inline

Whether a frame command's payload carries key material that must never be logged or reported verbatim.

CMD_KEY_TRANSFER (0x32) carries the system key encrypted with the pairing transfer key — still key material, so callers rendering frame bytes must mask this payload rather than print it.

CMD_CHALLENGE_REQ (0x3C) and CMD_CHALLENGE_RESP (0x3D) are masked for the same reason even though neither carries the key itself: create_hmac() builds the 0x3D payload by AES-128-ECB encrypting an IV built from the 0x3C challenge and the challenged frame's own (plaintext) transcript under the system key, then truncating to 6 bytes (proto_crypto.cpp). Logging both frames publishes a known-plaintext/known-ciphertext pair for that block cipher under the system key, so they get the same treatment as literal key material.

CMD_ONEWAY_ADD_CONTROLLER (0x30) is masked even though this codebase has no 1W key-adoption feature and never builds or parses this command itself: the radio receives every frame that matches the IO-Homecontrol sync word regardless of destination address (see log_component_capture()'s doc comment), so a neighboring installation's 1W device performing its key-copy gesture is overheard and logged like any other traffic. That broadcast hands its network's wrapped system key to whoever is listening, so the raw command byte alone is enough to know the payload must be masked even without decoding it.

Parameters
cmdFrame command byte.
Returns
true if the payload of a frame with this command must be masked.

Definition at line 46 of file redaction.h.

◆ command_name()

const char * esphome::home_io_control::command_name ( uint8_t cmd)

Get a human-readable name for any IO-Homecontrol command ID.

Returns a short uppercase identifier suitable for log lines (e.g., "EXECUTE", "DISCOVER_REQ", "CHALLENGE_RESP"). Unknown commands return "UNKNOWN_CMD".

Parameters
cmdCommand byte from the frame header.
Returns
Null-terminated string.

Definition at line 10 of file proto_constants.cpp.

◆ command_result_description()

const char * esphome::home_io_control::command_result_description ( uint8_t result)

Return a human-readable explanation for a CMD_ERROR_RESP result code.

Parameters
resultResult byte from CMD_ERROR_RESP data[0].
Returns
Short description suitable for warn-level logs.

Definition at line 341 of file proto_constants.cpp.

◆ command_result_name()

const char * esphome::home_io_control::command_result_name ( uint8_t result)

Return a stable symbolic name for a CMD_ERROR_RESP result code.

Parameters
resultResult byte from CMD_ERROR_RESP data[0].
Returns
Uppercase symbolic name, or "UNKNOWN_RESULT_CODE" when unmapped.

Definition at line 232 of file proto_constants.cpp.

◆ contains_key_material()

bool esphome::home_io_control::contains_key_material ( const uint8_t * buf,
size_t len,
const uint8_t * system_key )
inline

Whether a buffer contains the system key as a contiguous run of bytes.

A last-line-of-defense scan for accidental key leaks in ad hoc debug or report text, independent of which command produced the buffer.

Parameters
bufBuffer to scan.
lenLength of buf in bytes.
system_keyPointer to the AES_KEY_SIZE-byte system key.
Returns
true if system_key appears anywhere in buf.

Definition at line 59 of file redaction.h.

◆ cover_command_name()

const char * esphome::home_io_control::cover_command_name ( CoverCommand cmd)

Get a human-readable name for a CoverCommand.

Parameters
cmdThe cover command to name.
Returns
Null-terminated string such as "STOP", "FAVORITE", or "VENT".

Definition at line 46 of file proto_device_model.cpp.

◆ crc_ccitt()

uint16_t esphome::home_io_control::crc_ccitt ( const uint8_t * data,
uint8_t len )

CRC-CCITT used by the IO-Homecontrol protocol for frame validation.

Compute CRC‑CCITT (poly 0x1021, init 0x0000) over a buffer.

Polynomial: 0x1021 (reversed 0x8408), initial value: 0x0000. Radio chips with native IO-Homecontrol framing compute this in hardware; drivers for other chips call this helper instead.

Used by radio drivers without hardware IO-Homecontrol CRC support and by frame validation in tests.

Parameters
dataPointer to data bytes.
lenNumber of bytes.
Returns
16‑bit CRC value.

Definition at line 60 of file proto_frame.cpp.

◆ create_challenge_req() [1/2]

bool esphome::home_io_control::create_challenge_req ( IoFrame & f,
const uint8_t * dst,
const uint8_t * src )

Build a challenge request (0x3C) containing 6 random bytes.

Used when WE need to authenticate an incoming request from a device.

Used when we need to authenticate an incoming request from a device.

Parameters
fIoFrame to populate.
dstTarget device node ID (device we're challenging).
srcController node ID.
Returns
true on success.

Definition at line 388 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_challenge_req() [2/2]

bool esphome::home_io_control::create_challenge_req ( IoFrame & f,
const uint8_t * dst,
const uint8_t * src,
const uint8_t challenge[HMAC_SIZE] )

Build a challenge request (0x3C) using a caller-supplied challenge.

Build a challenge request (0x3C) using a caller-supplied challenge instead of generating a fresh one internally.

See proto_commands.h. low_power is set because the target is a device that may be battery/solar powered (see create_set_name above).

The no-challenge overload above generates its own random bytes and does not expose them, which is fine for the normal inbound-auth path (the challenge is only ever needed once, to build this same frame). A caller that needs the exact bytes again later — the key-extraction responder decrypting the corresponding CMD_KEY_TRANSFER (0x32) — generates the challenge itself and passes it in here, keeping the transmitted 0x3C and the later decrypt on one source of truth. Note that responder uses create_challenge_req_device_role() below, not this overload.

Parameters
fIoFrame to populate.
dstTarget device node ID (device we're challenging).
srcOur own node ID.
challengeCaller-supplied 6-byte challenge (e.g. from crypto::generate_challenge()).
Returns
true on success.

Definition at line 382 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_challenge_req_device_role()

bool esphome::home_io_control::create_challenge_req_device_role ( IoFrame & f,
const uint8_t * dst,
const uint8_t * src,
const uint8_t challenge[HMAC_SIZE] )

Build a device-role challenge request (0x3C) — device side, used only by the key-extraction responder.

Build a challenge request (0x3C) in the device direction — used only by the key-extraction responder to challenge a foreign hub that sent us CMD_KEY_INIT (0x31).

See proto_commands.h for why the framing bits differ from the controller-role builders above.

Same command and payload as the controller-role builders above, but framed the way a real device frames it: START clear and LOW_POWER clear. Both controller-role overloads set both bits, which is correct for their direction — LOW_POWER describes the target of a controller-originated frame (a device that may be battery/solar powered, see this header's convention note), and the controller's 0x3C opens its own inbound-auth exchange. Neither holds for a device answering a hub's key-init: real devices' pairing 0x3C frames in tests/corpus/captures/somfy_dimmer/pairing_full.yaml (0E 00 …) and velux_kux100/pairing_full.yaml carry neither bit, because the frame is a continuation of the hub's already-open exchange and is addressed to a mains-powered hub — and this exact builder, exercised against a real hub, produces the identical 0E 00 shape in tests/corpus/captures/issues/issue_45_velux_kig300_key_extraction_success.yaml.

Parameters
fIoFrame to populate.
dstThe foreign hub's node ID (from the inbound 0x31's src).
srcOur advertised (throwaway) node ID.
challengeCaller-supplied 6-byte challenge, retained for the later 0x32 decrypt.
Returns
true on success.

Definition at line 397 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_challenge_req_framed()

bool esphome::home_io_control::create_challenge_req_framed ( IoFrame & f,
const uint8_t * dst,
const uint8_t * src,
const uint8_t challenge[HMAC_SIZE],
bool start,
bool low_power )
static

Build a challenge request (0x3C) with caller-chosen framing bits.

Shared by the controller-role and device-role builders below, which differ only in those bits.

Definition at line 371 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_challenge_resp()

bool esphome::home_io_control::create_challenge_resp ( IoFrame & f,
const uint8_t * dst,
const uint8_t * src,
const uint8_t challenge[HMAC_SIZE],
const IoFrame & origin,
const uint8_t * key )

Build a challenge response (0x3D) proving we know the system key.

The HMAC is computed over [original_command_id + original_data] using the challenge.

HMAC is computed over [original_command_id + original_data] using the challenge.

Parameters
fIoFrame to populate.
dstTarget device node ID.
srcController node ID.
challenge6‑byte challenge from the device.
originOriginal request frame that triggered the challenge.
keySystem key (16 bytes).
Note
The HMAC derivation uses the challenge as IV salt; see create_hmac() in proto_crypto.h for the exact construction. This frame authenticates the controller to the device for the current exchange.
Returns
true on success.

Definition at line 404 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_device_terminal_ack()

bool esphome::home_io_control::create_device_terminal_ack ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
uint8_t cmd )
static

Build a bare device→hub terminal acknowledgement: no payload, END set, START and LOW_POWER clear.

Shared by create_key_confirm() and create_discover_confirm_ack(), which are the same frame shape and differ only in command byte — real captures of both (tests/corpus/captures/somfy_dimmer/pairing_full.yaml's 0x33 88 00 …, velux_kux100/pairing_full.yaml's 0x2D 88 08 …, and this project's own key-extraction responder against a real hub in tests/corpus/captures/issues/issue_45_velux_kig300_key_extraction_success.yaml, both 0x2D and 0x33 as 88 00 …) show a device closing its half of a two-frame handshake this way. LOW_POWER stays clear because that bit describes the target of a controller-originated frame (see the header's convention note); a device does not flag a frame it sends to the hub as low-power.

Definition at line 318 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_discover()

bool esphome::home_io_control::create_discover ( IoFrame & f,
const uint8_t * own )

Build a discovery broadcast (0x28).

Sent to the broadcast address 0x00003B. Only devices in pairing mode (PROG button pressed) will respond.

Sent to the broadcast address; only devices in pairing mode (PROG button pressed) will respond.

Parameters
fIoFrame to populate.
ownController node ID.
Note
Destination is BROADCAST_DISCOVER (0x00003B). The device responds with CMD_DISCOVER_RESP (0x29) containing its node ID and type/subtype. The controller then switches to point‑to‑point communication for phases 2 and 3.
Returns
true on success.

Definition at line 227 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_discover_confirm_ack()

bool esphome::home_io_control::create_discover_confirm_ack ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a discovery-confirm acknowledgement (0x2D) — device side, used only by the key-extraction responder.

Build a discovery-confirm acknowledgement (0x2D) — the device's answer to a hub's CMD_DISCOVER_CONFIRM (0x2C), which a hub sends directly to a freshly-discovered device before it will proceed to the key exchange.

See proto_commands.h for the full contract.

Device-side only, like create_discover_resp()/create_key_confirm() above; this project's own controller role never sends 0x2C, so there is no counterpart builder for the other direction. No payload and END set, matching real devices' 0x2D in tests/corpus/captures/velux_kux100/pairing_full.yaml; for a second independent hub, tests/corpus/captures/issues/issue_45_somfy_connectivity_kit_key_extraction_stall.yaml, where an already-paired device answers the same hub the key-extraction responder was talking to; and for this exact builder exercised against a real hub, tests/corpus/captures/issues/issue_45_velux_kig300_key_extraction_success.yaml.

Parameters
fIoFrame to populate.
ownOur advertised (throwaway) node ID.
dstDestination node ID (the hub that sent the discovery confirm).
Returns
true on success.

Definition at line 333 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_discover_resp()

bool esphome::home_io_control::create_discover_resp ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
DeviceType type,
uint8_t subtype,
uint8_t manufacturer_id )

Build a discovery response (0x29) — device side, used only by the key-extraction responder.

Build a discovery response (0x29) — the device side of discovery, used by the key-extraction responder (see pairing_responder.h) to emulate an unpaired device.

See proto_commands.h for the full contract and the real-capture cross-check.

Almost every builder in this file speaks the controller side of the protocol; this one, create_key_confirm(), create_discover_confirm_ack(), and create_challenge_req_device_role() below speak the device side, needed only for that one reverse-role feature. Device-side frames never set CTRL1_LOW_POWER: that bit describes the target of a controller-originated frame, and a device's replies are addressed to a mains-powered hub. Payload layout matches the full 9-byte discovery response format documented at DISCOVERY_RESP_BACKBONE_OFFSET/_MANUFACTURER_OFFSET/_FLAGS_OFFSET/_TIMESTAMP_OFFSET (proto_constants.h), cross-checked against a real Somfy actuator's captured 0x29 (tests/corpus/captures/somfy_awning/pairing_lab_discovery_response.yaml): backbone address equals the device's own node ID, start+end set, low_power clear.

Parameters
fIoFrame to populate.
ownOur advertised (throwaway) node ID — used as both src and the backbone address.
dstDestination node ID (the discovering hub's real node ID, from its 0x28's src).
typeDevice type to advertise.
subtypeDevice subtype to advertise.
manufacturer_idManufacturer ID to advertise (see MANUFACTURER_* in proto_constants.h).
Note
The flags byte (turnaround class, power-save) and timestamp are best-effort placeholder values (0x00) — a real hub may require different values; unverified without hardware.
Returns
true on success.

Definition at line 285 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_discovery_request()

bool esphome::home_io_control::create_discovery_request ( IoFrame & f,
const uint8_t * own,
uint8_t command,
const uint8_t * dst,
bool low_power,
bool payload_enabled,
uint8_t payload,
const uint8_t * system_key )

Build a configurable discovery request command (0x28, 0x2A, or 0x2E).

Build a discovery request with configurable command, destination, and payload.

For 0x2A (Discover SPE), the payload is a 6-byte random nonce followed by a 6-byte HMAC over the command byte alone, using that nonce as the challenge and the supplied system key — one frame carrying a whole challenge-response, which is what lets a broadcast be authenticated. This requires a valid system key; it will not work for a motor that has never been paired with this controller's key.

Supports the command codes 0x28 (DISCOVER_REQ), 0x2A (DISCOVER_SPE_REQ), and 0x2E (DISCOVER_ALT_REQ, alternate discovery). For 0x2A the payload is a 6-byte random nonce followed by a 6-byte HMAC computed over [cmd + nonce] using the supplied system key.

Parameters
fIoFrame to populate.
ownController's 3-byte node ID.
commandDiscovery command code (0x28, 0x2A, or 0x2E).
dstDestination node ID (broadcast or explicit).
low_powerTrue to set the LOW_POWER flag in CTRL1.
payload_enabledTrue when the optional payload byte is enabled.
payloadOptional payload byte (only used when command requires a payload).
system_key16-byte system key; only used for 0x2A HMAC computation.
Returns
true on success; false for unsupported command or missing key for 0x2A.

Definition at line 242 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_execute_command()

bool esphome::home_io_control::create_execute_command ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power,
CoverCommand cmd )

Build a named-command execute frame (0x00) for STOP, FAVORITE, or VENT.

FORCE_OPEN is deliberately not handled here — unlike these three, it needs to know the device's wire-scale "fully open" position (0 or 100 depending on IoDevice::inverted, e.g. horizontal awnings), which this builder has no way to know. Use create_force_open() instead; see its comments for why.

Each maps to a specific wire encoding in the 6-byte special CMD_EXECUTE payload:

  • STOP: main=0xD2, modifier=0x00
  • FAVORITE: main=0xD8, modifier=0x00
  • VENT: main=0xD8, modifier=0x03

This cleanly separates "move to position X" from "execute named action" without overloading a single numeric parameter.

FORCE_OPEN is NOT handled here — see create_force_open() instead. Unlike these three, it needs a device-specific "fully open" wire position (0 or 100 depending on inversion), which this generic dispatch has no way to supply; passing CoverCommand::FORCE_OPEN returns false.

Parameters
fIoFrame to populate.
ownController's 3‑byte node ID (source address).
dstTarget device's 3‑byte node ID (destination address).
low_powerTrue if target is battery/solar‑powered (sets CTRL1_LOW_POWER).
cmdNamed command to execute (STOP, FAVORITE, or VENT).
Returns
true on success; false for invalid/unsupported command.

Definition at line 91 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_execute_position()

bool esphome::home_io_control::create_execute_position ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power,
uint8_t position )

Build a position execute command (0x00) to move a device to a numeric position.

Encodes a 0–100 position value into the standard 8-byte execute payload with originator, ACEI, and functional parameter fields. The wire encoding doubles the position value (0→0x00, 100→0xC8).

Parameters
fIoFrame to populate.
ownController's 3‑byte node ID (source address).
dstTarget device's 3‑byte node ID (destination address).
low_powerTrue if target is battery/solar‑powered (sets CTRL1_LOW_POWER).
positionDesired position 0–100 (0=fully open, 100=fully closed).
Returns
true on success; false if position > 100.

Definition at line 75 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_execute_position_and_tilt()

bool esphome::home_io_control::create_execute_position_and_tilt ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power,
uint8_t position,
uint8_t tilt_percent )

Build a combined position-and-tilt execute command (0x00) — setClosureAndOrientation.

Build a combined position‑and‑tilt execute command (0x00).

Sets both the cover position and the slat angle atomically in one frame, corresponding to the protocol's setClosureAndOrientation use case.

Parameters
fIoFrame to populate.
ownController node ID.
dstTarget device node ID.
low_powerTrue if target is battery/solar‑powered (sets CTRL1_LOW_POWER).
positionDesired position 0–100 (open→closed).
tilt_percent0 = fully closed, 100 = fully open.
Returns
true on success; false if position exceeds limits.

Definition at line 194 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_execute_tilt()

bool esphome::home_io_control::create_execute_tilt ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power,
uint8_t tilt_percent )

Build a tilt execute command (0x00) for devices that support slat angle control.

Build an execute‑tilt command (0x00) for slat angle control.

Parameters
fIoFrame to populate.
ownController node ID.
dstTarget device node ID.
low_powerTrue if target is battery/solar‑powered (sets CTRL1_LOW_POWER).
tilt_percent0 = fully closed, 100 = fully open.
Note
This uses the same command (0x00) as position control but with a different payload format indicating a tilt operation. The receiver infers tilt from the payload structure. Only devices that advertise tilt support (see device_supports_tilt in proto_frame.h) will honor this.
Returns
true on success.

Definition at line 175 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_force_open()

bool esphome::home_io_control::create_force_open ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power,
uint8_t open_position )

Build a force-open execute frame (0x00): an ordinary position command to the device's wire-scale "fully open" value, sent at elevated ACEI priority (see EXECUTE_ACEI_FORCE_OPEN).

Build a force-open execute frame (0x00): move to the device's wire-scale "fully open" position at elevated ACEI priority (level 0, protection_human) instead of the usual user_high level — see EXECUTE_ACEI_FORCE_OPEN in proto_commands.cpp for why priority elevation, not a special position byte, is the protocol's real mechanism for getting past an environmental soft lock.

Takes the target position explicitly rather than assuming 0, because "fully open" is not always wire-position 0: IoDevice::inverted devices (e.g. horizontal awnings) have open/close swapped, so their fully-open wire position is 100. An earlier version of this builder hardcoded 0; on a real inverted awning that targeted its already-*closed* resting position, a real-hardware-confirmed no-op rather than a lock bypass. The caller (execute_device_command_() in hub_operations.cpp) is responsible for resolving the correct value from the target IoDevice.

Parameters
fIoFrame to populate.
ownController's 3‑byte node ID (source address).
dstTarget device's 3‑byte node ID (destination address).
low_powerTrue if target is battery/solar‑powered (sets CTRL1_LOW_POWER).
open_positionThe device's wire-scale position value that means "fully open": 0 for ordinary devices, 100 for IoDevice::inverted ones (e.g. horizontal awnings) — the caller must resolve this from the target device, this builder does not have access to device state. Getting this wrong sends an ordinary, harmless-looking position command to the device's already-resting position instead of moving it anywhere.
Returns
true on success.
Note
The elevated-priority override has not yet been confirmed against a real active environmental lock.

Definition at line 127 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_get_name()

bool esphome::home_io_control::create_get_name ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
bool low_power )

Build a get-name request (0x50).

The device responds with its stored display name.

Parameters
fIoFrame to populate.
ownController's 3-byte node ID.
dstTarget device's 3-byte node ID.
low_powerTrue if target is battery/solar-powered (sets CTRL1_LOW_POWER).
Returns
true on success.

Definition at line 146 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_get_status()

bool esphome::home_io_control::create_get_status ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a get-status request (0x03). The device responds with its current position.

Build a get‑status request (0x03).

The device responds with its current position.

Parameters
fIoFrame to populate.
ownController's 3‑byte node ID.
dstTarget device's 3‑byte node ID.
Returns
true on success.

Definition at line 136 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_get_status_tilt()

bool esphome::home_io_control::create_get_status_tilt ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a tilt-aware get-status request (0x03) that returns the extended 16-byte tilt payload.

Build a tilt‑aware get‑status request (0x03 with extended payload) that returns the 16‑byte tilt block in the response.

Parameters
fIoFrame to populate.
ownController node ID.
dstTarget device node ID.
Returns
true on success.

Definition at line 216 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_identify()

bool esphome::home_io_control::create_identify ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build an authenticated device-identify request (0x1E).

Build an authenticated device-identify request (0x1E) that makes a device physically identify itself (brief jog / flash).

Parameters
fIoFrame to populate.
ownController's 3-byte node ID (source address).
dstTarget device's 3-byte node ID (destination address).
Note
The device may reply with CMD_ERROR_RESP instead of a dedicated identify response; callers should treat that reply as an expected, non-fatal outcome rather than a failure.
Returns
true on success.

Definition at line 165 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_key_confirm()

bool esphome::home_io_control::create_key_confirm ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a key-confirm frame (0x33) — device side, used only by the key-extraction responder.

Build a key-confirm frame (0x33) — the device's acknowledgement that it received and installed the system key, sent after decrypting a CMD_KEY_TRANSFER (0x32).

See proto_commands.h for the full contract and the real-capture cross-check.

Device-side counterpart to create_key_transfer(); used only by the key-extraction responder (see create_discover_resp() above for why this direction exists at all). No payload and END set, matching real devices' 0x33 in tests/corpus/captures/somfy_dimmer/pairing_full.yaml, velux_kux100/pairing_full.yaml, and (this project's own key-extraction responder against a real hub) tests/corpus/captures/issues/issue_45_velux_kig300_key_extraction_success.yaml — 0x33 closes the key-exchange sequence that CMD_KEY_INIT (0x31) opened with START.

Parameters
fIoFrame to populate.
ownOur advertised (throwaway) node ID.
dstDestination node ID (the hub that sent the key transfer).
Returns
true on success.

Definition at line 327 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_key_init()

bool esphome::home_io_control::create_key_init ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a key-init request (0x31) to start the pairing key exchange with a discovered device.

Build a key‑init request (0x31) to start pairing key exchange with a discovered device.

Parameters
fIoFrame to populate.
ownController node ID.
dstDiscovered device node ID.
Returns
true on success.

Definition at line 347 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_key_transfer()

bool esphome::home_io_control::create_key_transfer ( IoFrame & f,
IoFrame & old_frame,
const uint8_t * dst,
const uint8_t * src,
const uint8_t key[AES_KEY_SIZE],
const uint8_t challenge[HMAC_SIZE] )

Build a key-transfer frame (0x32) containing the system key encrypted with the transfer key.

Build a key‑transfer frame (0x32) containing the system key encrypted with the transfer key.

Parameters
fIoFrame to populate.
old_frameThe key‑init frame (used to derive the encryption IV).
dstTarget device node ID.
srcController node ID.
keyThe 16‑byte system key to transfer.
challenge6‑byte challenge received from device in its 0x3C response.
Note
The system key is obfuscated via the XOR‑AES construction in crypt_key(). The transfer key (hardcoded in proto_frame.h) is the same for all IO‑Homecontrol devices worldwide; its purpose is to protect the system key in transit during initial pairing. Once transferred, the device uses the system key for all subsequent authenticated exchanges.
Returns
true on success.

Definition at line 355 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_set_config1()

bool esphome::home_io_control::create_set_config1 ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a set-config command (0x6F) to tell the device to automatically send status updates when controlled by any remote (not just us).

Build a set‑config command (0x6F) telling the device to automatically send status updates when controlled by any remote.

Not all devices support this.

Parameters
fIoFrame to populate.
ownController node ID.
dstTarget device node ID.
Note
This configures the device to emit CMD_STATUS_UPDATE (0x71) frames whenever it is controlled by any remote (including the paired controller). This enables HA to receive unsolicited position updates. The controller must still authenticate the status update using the inbound auth flow (hub_exchange.h).
Todo
Confirm on real hardware which device families actually honor this SetConfig1 payload and emit unsolicited status updates after pairing.
Returns
true on success.

Definition at line 434 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_set_name()

bool esphome::home_io_control::create_set_name ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst,
const uint8_t payload[DEVICE_NAME_WRITE_PAYLOAD_SIZE] )

Build an authenticated set-name request (0x52) using a fixed zero-padded Latin-1 payload.

Parameters
fIoFrame to populate.
ownController's 3-byte node ID.
dstTarget device's 3-byte node ID.
payloadPre-validated fixed payload produced by encode_device_name_payload().
Returns
true on success.

Definition at line 153 of file proto_commands.cpp.

Here is the call graph for this function:

◆ create_status_update_resp()

bool esphome::home_io_control::create_status_update_resp ( IoFrame & f,
const uint8_t * own,
const uint8_t * dst )

Build a status-update acknowledgment (0x72).

Build a status‑update acknowledgment (0x72).

Sent after authenticating a device's status update. The response is sent on all 3 channels to ensure the device receives it.

Sent after authenticating a device's status update; broadcast on all 3 channels for reliability.

Parameters
fIoFrame to populate.
ownController node ID.
dstDevice node ID that sent the update.
Returns
true on success.

Definition at line 423 of file proto_commands.cpp.

Here is the call graph for this function:

◆ decode_1w_frame()

OneWayFrameInfo esphome::home_io_control::decode_1w_frame ( const IoFrame & frame)

Decode a parsed 1W frame into a structured OneWayFrameInfo.

Extracts target device type from the broadcast address. For execute/activate-mode commands, also decodes originator, ACEI priority, and position/command intent.

Parameters
frameParsed IoFrame with CTRL0_PROTOCOL_1W set.
Returns
Populated OneWayFrameInfo.

Definition at line 313 of file proto_codecs.cpp.

Here is the call graph for this function:

◆ decode_1w_main_intent()

void esphome::home_io_control::decode_1w_main_intent ( uint8_t main0,
uint8_t main1,
char * out,
size_t out_size )

Decode the "main" position/command bytes from a 1W execute payload.

1W remotes encode their command intent in a 2-byte main field:

  • main[0]: position (0–200 mapped to 0–100%), or a special command code.
  • main[1]: modifier byte (0x03 = ventilation for POS_FAVORITE).
Parameters
main0First main byte (position or special code).
main1Second main byte (modifier).
outBuffer to write the decoded string into (e.g., "CLOSE", "position 75%").
out_sizeSize of the output buffer.

Definition at line 238 of file proto_codecs.cpp.

◆ decode_ctrl1_flags()

void esphome::home_io_control::decode_ctrl1_flags ( uint8_t ctrl1,
char * out,
size_t out_size )
inline

Render decoded CTRL1 flags into a short annotation string.

Parameters
ctrl1The CTRL1 byte from a frame.
outBuffer to write into (at least FRAME_LOG_FLAGS_BUFFER_SIZE bytes).
out_sizeSize of the output buffer.

Definition at line 35 of file log_frame.h.

◆ decode_device_name_payload()

std::string esphome::home_io_control::decode_device_name_payload ( const uint8_t * data,
uint8_t len )

Decode a device-name payload from IO-homecontrol's Latin-1 wire format into UTF-8.

Some devices prepend an extra byte before the first character and many pad the payload with trailing 0x00 or 0x20 bytes. This helper normalizes those quirks and truncates the result to fit DEVICE_NAME_BUFFER_SIZE - 1 bytes when copied into IoDevice::name.

Parameters
dataRaw payload pointer from CMD_GET_NAME_RESP.
lenRaw payload length in bytes.
Returns
Normalized UTF-8 name, or an empty string when the payload carries no usable characters.

Definition at line 75 of file proto_codecs.cpp.

◆ decode_discovery_response()

DiscoveryResponseInfo esphome::home_io_control::decode_discovery_response ( const IoFrame & frame,
IoDevice & device,
std::string & device_id )

Decode a discovery-response payload (CMD_DISCOVER_RESP 0x29 or CMD_DISCOVER_SPE_RESP 0x2B — both carry the identical DISCOVERY_RESP_FULL_SIZE layout) into device metadata.

Pure: no logging, no side effects. Extended fields (manufacturer, flags, timestamp) are returned rather than logged so each caller can present them its own way. Sets device.node_id/type/subtype/inverted/position/target/is_stopped and device_id exactly as a discovery reply implies: type/subtype and inversion come from the packed metadata bytes when present, position/target default to the unknown sentinel, and the device is assumed stopped. Every field read is guarded on frame.data_len, so a short or truncated payload degrades gracefully instead of reading past the end.

Parameters
frameParsed discovery-response frame.
deviceOutput: device record populated from the frame.
device_idOutput: hex device ID string derived from frame.src.
Returns
Extended discovery fields (manufacturer/flags/timestamp) and length flags.

Definition at line 336 of file proto_codecs.cpp.

Here is the call graph for this function:

◆ decode_packed_device_subtype()

uint8_t esphome::home_io_control::decode_packed_device_subtype ( uint8_t type_subtype)

Decode a protocol-packed device subtype from the second metadata byte.

Parameters
type_subtypeSecond metadata byte containing subtype in bits [5:0].
Returns
Manufacturer-specific subtype.

Definition at line 66 of file proto_device_model.cpp.

◆ decode_packed_device_type()

DeviceType esphome::home_io_control::decode_packed_device_type ( uint8_t type_msb,
uint8_t type_subtype )

Decode a protocol-packed device type from two metadata bytes.

Parameters
type_msbFirst metadata byte.
type_subtypeSecond metadata byte containing the remaining type bits and subtype.
Returns
Decoded device type.

Definition at line 61 of file proto_device_model.cpp.

◆ decode_position_report()

void esphome::home_io_control::decode_position_report ( uint16_t target_raw,
uint16_t current_raw,
bool is_stopped,
float & target,
float & position )

Decode target/current position values from a status frame.

Parameters
target_raw16‑bit raw target value.
current_raw16‑bit raw current value.
is_stoppedTrue if device reports stopped.
targetOutput target position (0–100 or UNKNOWN_POSITION).
positionOutput current position (0–100 or UNKNOWN_POSITION).

Definition at line 74 of file proto_device_model.cpp.

◆ decode_tilt_report()

float esphome::home_io_control::decode_tilt_report ( uint16_t tilt_raw)

Decode tilt angle from raw 16‑bit value.

Parameters
tilt_rawRaw tilt value from status frame.
Returns
Tilt percentage (0 = closed, 100 = open) or UNKNOWN_POSITION.

Definition at line 107 of file proto_device_model.cpp.

◆ decode_uart_probe()

uint8_t esphome::home_io_control::decode_uart_probe ( const uint8_t * raw,
uint8_t raw_len,
uint8_t bit_offset,
uint8_t * decoded,
uint8_t decoded_max_len )

Decode a raw UART‑encoded bitstream into bytes.

Decode a UART-encoded bitstream from the given bit offset.

IO‑Homecontrol uses a UART‑like encoding over the air: each byte is represented by a 10‑bit sequence (start bit 0, 8 data bits LSB‑first, stop bit 1). This function slides a window across the raw bitstream and attempts to recover the original bytes. It stops when the sync pattern (0 followed by 1) is not found.

Parameters
rawRaw bytes from the radio buffer.
raw_lenNumber of raw bytes available.
bit_offsetInitial bit position to start decoding (probe offset).
decodedOutput buffer for decoded bytes.
decoded_max_lenCapacity of decoded buffer.
Returns
Number of bytes successfully decoded.

Definition at line 47 of file radio_soft_phy.cpp.

◆ default_inverted_for_type()

bool esphome::home_io_control::default_inverted_for_type ( DeviceType type)

Determine whether a device type has inverted position mapping by default.

Parameters
typeDevice type.
Returns
true for horizontal awnings; false otherwise.

Definition at line 44 of file proto_device_model.cpp.

◆ device_capability_class()

DeviceCapabilityClass esphome::home_io_control::device_capability_class ( DeviceType type)

Map a raw IO‑Homecontrol type to the closest ESPHome/Home Assistant entity family.

Parameters
typeRaw device type.
Returns
Capability class (COVER, LIGHT, SWITCH, etc.).

Definition at line 219 of file proto_device_model.cpp.

◆ device_capability_class_name()

const char * esphome::home_io_control::device_capability_class_name ( DeviceType type)

Get a human‑readable name for a capability class.

Parameters
typeDevice type (unused, kept for signature compatibility).
Returns
String like "cover", "light", "switch", "unknown".

Definition at line 264 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_name_validation_error_description()

const char * esphome::home_io_control::device_name_validation_error_description ( DeviceNameValidationError error)

Return a human-readable explanation for a device-name validation result.

Parameters
errorValidation result.
Returns
Short message suitable for logs and Home Assistant action events.

Definition at line 166 of file proto_codecs.cpp.

◆ device_name_validation_error_name()

const char * esphome::home_io_control::device_name_validation_error_name ( DeviceNameValidationError error)

Return a stable symbolic name for a device-name validation result.

Parameters
errorValidation result.
Returns
Uppercase symbolic name.

Definition at line 149 of file proto_codecs.cpp.

◆ device_operation_profile_name()

const char * esphome::home_io_control::device_operation_profile_name ( DeviceType type)

Human‑readable operation profile name for a device type.

Used for logging and diagnostics.

Parameters
typeDevice type.
Returns
String such as "cover_position", "cover_position_tilt", "binary_on_off", "lock", etc.

Definition at line 326 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_rssi_ema_dbm()

int16_t esphome::home_io_control::device_rssi_ema_dbm ( const IoDevice & dev)
inline

A device's smoothed RSSI in whole dBm.

Parameters
devDevice record to read.
Returns
Rounded EMA in dBm, or RSSI_UNKNOWN_DBM when no sample has been recorded yet.

Definition at line 291 of file proto_device_model.h.

Here is the call graph for this function:

◆ device_supports_binary_control()

bool esphome::home_io_control::device_supports_binary_control ( DeviceType type)

Does this device type support binary on/off control?

Parameters
typeDevice type.
Returns
true for lights and switches.

Definition at line 290 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_supports_lock_control()

bool esphome::home_io_control::device_supports_lock_control ( DeviceType type)

Does this device type support binary lock/unlock control via execute commands?

Parameters
typeDevice type.
Returns
true for lock devices.

Definition at line 295 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_supports_position_control()

bool esphome::home_io_control::device_supports_position_control ( DeviceType type)

Does this device type support precise position control (0–100)?

Parameters
typeDevice type.
Returns
true for cover‑family devices.

Definition at line 286 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_supports_status_requests()

bool esphome::home_io_control::device_supports_status_requests ( DeviceType type)

Does this device type support status request commands (0x03)?

Parameters
typeDevice type.
Returns
true for covers, binary devices, and lock devices.

Definition at line 299 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ device_supports_tilt()

bool esphome::home_io_control::device_supports_tilt ( DeviceType type)

Does this device type support tilt (slat angle) control?

Parameters
typeDevice type.
Returns
true for venetian blinds, blinds, external venetian blinds, louvre blinds.

Definition at line 304 of file proto_device_model.cpp.

◆ device_supports_vent()

bool esphome::home_io_control::device_supports_vent ( DeviceType type)

Does this device type support the ventilation position command?

The ventilation command moves window-type actuators to a predefined partially-open position suitable for air exchange without fully opening.

Parameters
typeDevice type.
Returns
true for WINDOW_OPENER and VENTILATION_POINT.

Definition at line 316 of file proto_device_model.cpp.

◆ device_type_name()

const char * esphome::home_io_control::device_type_name ( DeviceType type)

Convert a DeviceType to a lowercase string identifier.

Parameters
typeDevice type enum.
Returns
Null‑terminated string name (e.g., "roller_shutter").

Definition at line 113 of file proto_device_model.cpp.

◆ discovery_att_class()

uint8_t esphome::home_io_control::discovery_att_class ( uint8_t flags)
inline

Extract the ATT class field from a discovery response's Multi Information Byte.

Parameters
flagsMulti Information Byte (data[DISCOVERY_RESP_FLAGS_OFFSET]).
Returns
ATT class value (0–3); pass to att_class_name() for a human-readable string.

Definition at line 527 of file proto_constants.h.

◆ discovery_command_from_string()

std::optional< DiscoveryCommand > esphome::home_io_control::discovery_command_from_string ( const std::string & value)

Parse a discovery command string (e.g., "0x28") into the enum.

Parameters
valueString to parse.
Returns
Discovery command enum, or std::nullopt on invalid input.

Definition at line 188 of file tuning_config.cpp.

◆ discovery_command_to_string()

std::string esphome::home_io_control::discovery_command_to_string ( DiscoveryCommand cmd)

Format a discovery command enum for YAML/logs.

Parameters
cmdDiscovery command enum.
Returns
Lowercase hex string such as "0x28".

Definition at line 201 of file tuning_config.cpp.

◆ discovery_commands_to_csv()

std::string esphome::home_io_control::discovery_commands_to_csv ( const std::vector< DiscoveryCommand > & commands)

Format the ordered discovery command list as a UI/preset option string.

Matches the comma-separated select option labels (no brackets) so a boot-time snapshot round-trips to a selectable dropdown value.

Parameters
commandsOrdered list of discovery commands.
Returns
Comma-separated list such as "0x28,0x2E" (empty string when the list is empty).

Definition at line 207 of file tuning_config.cpp.

Here is the call graph for this function:

◆ discovery_commands_to_string()

std::string esphome::home_io_control::discovery_commands_to_string ( const std::vector< DiscoveryCommand > & commands)

Format the ordered discovery command list for logs.

Parameters
commandsOrdered list of discovery commands.
Returns
Bracketed comma-separated list such as "[0x28,0x2E]".

Definition at line 217 of file tuning_config.cpp.

Here is the call graph for this function:

◆ discovery_destination_to_string()

std::string esphome::home_io_control::discovery_destination_to_string ( bool destination_auto,
const uint8_t destination[NODE_ID_SIZE] )

Format a destination option for YAML/logs.

Parameters
destination_autoWhether automatic destination mapping is used.
destinationExplicit 3-byte destination when auto is false.
Returns
"auto" or a hex address such as "0x00003B".

Definition at line 238 of file tuning_config.cpp.

◆ discovery_payload_to_string()

std::string esphome::home_io_control::discovery_payload_to_string ( bool payload_enabled,
uint8_t payload )

Format a payload option for YAML/logs.

Parameters
payload_enabledWhether the optional payload is enabled.
payloadThe payload byte when enabled.
Returns
"none" or a hex byte such as "0x00".

Definition at line 246 of file tuning_config.cpp.

◆ discovery_power_save_mode()

uint8_t esphome::home_io_control::discovery_power_save_mode ( uint8_t flags)
inline

Extract the power save mode field from a discovery response's Multi Information Byte.

Parameters
flagsMulti Information Byte (data[DISCOVERY_RESP_FLAGS_OFFSET]).
Returns
Power save mode value (0–1); pass to power_save_mode_name() for a human-readable string.

Definition at line 534 of file proto_constants.h.

◆ encode_device_name_payload()

DeviceNameValidationError esphome::home_io_control::encode_device_name_payload ( const std::string & name,
uint8_t payload[DEVICE_NAME_WRITE_PAYLOAD_SIZE],
std::string & normalized_name )

Validate and encode a user-supplied UTF-8 device name into the fixed Latin-1 write payload.

The outbound payload is a fixed 16-byte field: up to 15 Latin-1 characters followed by trailing zero padding. Leading and trailing ASCII whitespace are trimmed before validation so write-back verification against the device's padded storage is deterministic.

Parameters
nameUser-supplied UTF-8 device name.
payloadOutput buffer for the fixed write payload (16 bytes, zero-padded on success).
normalized_nameOutput normalized UTF-8 name used for later verification/logging.
Returns
Validation status indicating success or the reason the name cannot be written.

Definition at line 94 of file proto_codecs.cpp.

Here is the call graph for this function:

◆ encode_packed_device_type()

void esphome::home_io_control::encode_packed_device_type ( DeviceType type,
uint8_t subtype,
uint8_t & type_msb,
uint8_t & type_subtype )

Encode a DeviceType/subtype pair into the two-byte packed metadata format used by discovery responses — the inverse of decode_packed_device_type()/decode_packed_device_subtype().

Parameters
typeDevice type to encode.
subtypeManufacturer-specific subtype; only bits [5:0] are used.
type_msbOutput: first metadata byte.
type_subtypeOutput: second metadata byte (top 2 type bits + 6-bit subtype).

Definition at line 68 of file proto_device_model.cpp.

◆ find_crc_valid_frame()

std::pair< uint8_t, uint8_t > esphome::home_io_control::find_crc_valid_frame ( const uint8_t * decoded,
uint8_t decoded_len )
static

Try to find a CRC-valid IO-Homecontrol frame within a decoded UART byte stream.

Parameters
decodedDecoded byte buffer from UART probe.
decoded_lenNumber of decoded bytes.
Returns
Frame start index and length if found, or {0, 0} if no valid frame.

Definition at line 131 of file radio_soft_phy.cpp.

Here is the call graph for this function:

◆ find_tuning_number()

const TuningNumberParam * esphome::home_io_control::find_tuning_number ( const std::string & name)

Look up a numeric tuning parameter by name; returns nullptr if unknown.

Definition at line 166 of file tuning_registry.cpp.

◆ find_tuning_select()

const TuningSelectParam * esphome::home_io_control::find_tuning_select ( const std::string & name)

Look up a select tuning parameter by name; returns nullptr if unknown.

Definition at line 174 of file tuning_registry.cpp.

◆ find_uart_probe()

UartProbeResult esphome::home_io_control::find_uart_probe ( const uint8_t * raw,
uint8_t raw_len )

Search raw RX buffer for the best CRC-validated IO-Homecontrol frame.

Definition at line 153 of file radio_soft_phy.cpp.

Here is the call graph for this function:

◆ format_device_type_diagnostic()

std::string esphome::home_io_control::format_device_type_diagnostic ( DeviceType type)

Human-readable device type string for diagnostics, including the raw numeric value.

Parameters
typeDevice type.
Returns
String such as "horizontal_awning (0x10)", or the raw hex form ("0x1A") when the type has no symbolic name.

Definition at line 347 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ format_device_type_for_yaml()

std::string esphome::home_io_control::format_device_type_for_yaml ( DeviceType type)

Build the YAML value for a device's io_device_type key.

Parameters
typeDevice type.
Returns
A quoted symbolic name (e.g. "horizontal_awning") when one exists, otherwise the raw hex form (e.g. 0x1A) for a type with no YAML alias.

Definition at line 356 of file proto_device_model.cpp.

Here is the call graph for this function:

◆ format_position()

std::string esphome::home_io_control::format_position ( float pos)
inline

Format a position float as a human‑readable string (e.g.

"50%", "unknown").

Parameters
posPosition value (0–100 or UNKNOWN_POSITION).
Returns
String like "50%" or "unknown".

Definition at line 827 of file hub_core.h.

◆ format_result_code()

std::string esphome::home_io_control::format_result_code ( uint8_t result_code)
static

Definition at line 156 of file management_actions.cpp.

◆ format_scan_reply_line()

std::string esphome::home_io_control::format_scan_reply_line ( const ScanResponder & responder,
const std::string & device_id,
bool known )
static

Format one roll-call responder's report line(s).

Known responders get a single summary line; unknown responders get the same summary line plus a lead-in sentence and a ready-to-paste YAML block (or, if the decoded type has no ESPHome platform, an explanatory line instead of a blank) — the same "paste this in" framing a successful pairing prints.

Parameters
responderDecoded responder record.
device_idHex device ID string for this responder, rebuilt from responder.src.
knownTrue if this device is already registered on this hub.

Definition at line 468 of file management_actions.cpp.

Here is the call graph for this function:

◆ frame_length()

uint8_t esphome::home_io_control::frame_length ( const IoFrame & f)

Get total frame length from ctrl0.

Parameters
fParsed frame.
Returns
Length in bytes.

Definition at line 101 of file proto_frame.cpp.

◆ has_reached_target_position()

bool esphome::home_io_control::has_reached_target_position ( float target,
float position )

Has the device reached its target within tolerance?

Parameters
targetTarget position (0–100 or UNKNOWN_POSITION).
positionCurrent position (0–100 or UNKNOWN_POSITION).
Returns
true if positions match within STATUS_POS_TOLERANCE_RAW.

Definition at line 100 of file proto_device_model.cpp.

◆ hex_nibble()

int esphome::home_io_control::hex_nibble ( char ch)
static

Definition at line 22 of file proto_frame.cpp.

◆ hex_to_bytes()

bool esphome::home_io_control::hex_to_bytes ( const std::string & hex,
uint8_t * out,
uint8_t len )

Convert a hex string (e.g., "123ABC") to a byte array.

Parameters
hexHex string (must be exactly len*2 characters).
outOutput buffer (at least len bytes).
lenNumber of bytes to produce.
Returns
true on success; false if hex length mismatch or non‑hex characters.

Definition at line 31 of file proto_frame.cpp.

Here is the call graph for this function:

◆ init_frame()

void esphome::home_io_control::init_frame ( IoFrame & f,
bool is_2w = true,
bool start = false,
bool end = false,
bool low_power = false )

Initialize an IoFrame header (ctrl0/ctrl1) with flags.

Note: CTRL1_ACK is NOT automatically set on outbound frames. Some real-world devices reject frames with unexpected CTRL1 bits, causing total communication failure. The ACK constant is retained for inbound frame parsing and logging only.

Parameters
fFrame to initialize.
is_2wTrue for 2‑way (default), false for 1‑way.
startSet START flag (first frame in exchange).
endSet END flag (final frame in exchange).
low_powerSet LOW_POWER flag.

Definition at line 70 of file proto_frame.cpp.

◆ is_end()

bool esphome::home_io_control::is_end ( const IoFrame & f)

Check END flag.

Parameters
fParsed frame.
Returns
true if END flag is set.

Definition at line 103 of file proto_frame.cpp.

◆ is_limitation_result()

bool esphome::home_io_control::is_limitation_result ( uint8_t result)

Check whether a result code represents an environmental or control limitation.

Parameters
resultResult byte from CMD_ERROR_RESP data[0].
Returns
true when the response reports a limitation rather than a generic execution error.

Definition at line 450 of file proto_constants.cpp.

◆ is_start()

bool esphome::home_io_control::is_start ( const IoFrame & f)

Check START flag.

Parameters
fParsed frame.
Returns
true if START flag is set.

Definition at line 102 of file proto_frame.cpp.

◆ log_multiline_result()

void esphome::home_io_control::log_multiline_result ( const char * tag,
bool is_warning,
const std::string & prefix,
const std::string & message )
static

Log prefix followed by message, one line per log call rather than one call for the whole (possibly multi-line) string.

ESPHome formats each log call into a fixed 512-byte buffer (ESPHOME_LOGGER_TX_BUFFER_SIZE, esphome/core/defines.h) and silently truncates anything longer; scan_paired_devices()'s report exceeds that once it includes a YAML snippet, and would truncate mid-line if logged as a single call — confirmed on real hardware 2026-08-10, where a 3-device report cut off mid-snippet with no error and no indication anything was lost. Splitting by line keeps every individual call's payload small regardless of how long the full message is. The Home Assistant event (built from the same untruncated std::string, not from this log) is unaffected either way.

Parameters
tagLog tag.
is_warningTrue to log at WARN, false for INFO.
prefixPrepended to the message's first line only (e.g. "Management action X: ").
messageMessage to log; may contain embedded \n line breaks.

Definition at line 184 of file management_actions.cpp.

◆ lr1121_bandwidth_from_string()

std::optional< LR1121RxBandwidth > esphome::home_io_control::lr1121_bandwidth_from_string ( const std::string & value)

Convert a YAML LR1121 bandwidth string to the enum value.

Parameters
valueYAML string such as "117.3" or "39.0kHz".
Returns
Bandwidth enum, or std::nullopt on invalid input.

Definition at line 162 of file tuning_config.cpp.

◆ lr1121_bandwidth_to_khz()

float esphome::home_io_control::lr1121_bandwidth_to_khz ( LR1121RxBandwidth bw)

Convert an LR1121 bandwidth enum to the numeric kHz value used in YAML/logs.

Parameters
bwLR1121 bandwidth enum.
Returns
Floating-point kHz value (39.0, 46.9, 58.6, 78.2, 117.3, 156.2, or 187.2).

Definition at line 136 of file tuning_config.cpp.

◆ lr1121_bandwidth_to_string()

std::string esphome::home_io_control::lr1121_bandwidth_to_string ( LR1121RxBandwidth bw)

Format an LR1121 bandwidth enum as its YAML/UI option string (bare kHz number).

Parameters
bwLR1121 bandwidth enum.
Returns
Bandwidth rendered with one decimal place (e.g. "117.3").

Definition at line 156 of file tuning_config.cpp.

Here is the call graph for this function:

◆ lr1121_bootloader_is_lr1121()

bool esphome::home_io_control::lr1121_bootloader_is_lr1121 ( uint16_t bootloader_version)
nodiscardconstexpr
Returns
true if bootloader_version is one of the two bootloader versions an LR1121 (as opposed to an LR1120 or LR1110) can report.

Definition at line 62 of file lr1121_firmware_decisions.h.

◆ lr1121_bootloader_mismatch_kind()

BootloaderMismatch esphome::home_io_control::lr1121_bootloader_mismatch_kind ( uint16_t target_fw,
uint16_t bootloader_version )
nodiscardconstexpr

Classify a bootloader/target mismatch by direction; see BootloaderMismatch.

Definition at line 162 of file lr1121_firmware_decisions.h.

Here is the call graph for this function:

◆ lr1121_bootloader_supports_target()

BootloaderSupport esphome::home_io_control::lr1121_bootloader_supports_target ( uint16_t target_fw,
uint16_t bootloader_version )
nodiscardconstexpr

Look up whether target_fw is known to require bootloader_version.

A target absent from LR1121_KNOWN_BOOTLOADER_REQUIREMENTS is UNKNOWN_TARGET, never UNSUPPORTED — the table is a snapshot of what Semtech had published when this file was last updated, not an allow-list; a future firmware version this build has never heard of must not be rejected on that basis alone (see lr1121_flash_decision()'s three-way rule).

Definition at line 123 of file lr1121_firmware_decisions.h.

◆ lr1121_bootloader_upgrade_path()

BootloaderUpgradePath esphome::home_io_control::lr1121_bootloader_upgrade_path ( bool block_present,
bool bootloader_version_known,
uint16_t bootloader_version,
uint16_t loader_fw,
uint16_t target_fw )
nodiscardconstexpr

Whether the three-stage bootloader upgrade is applicable for the current cached state.

A post-filter, consulted only when lr1121_flash_decision() has already returned REJECT_BOOTLOADER_TOO_OLD – it never runs earlier and never changes that function's verdict (see this header's file comment and lr1121_flash_decision()'s doc comment). The evaluation order below is the specification – each rule exists to close a specific way an irreversible write could be justified on insufficient evidence:

  1. !block_present -> NOT_APPLICABLE – feature not built in.
  2. !bootloader_version_known -> NOT_APPLICABLE – an unknown current bootloader cannot justify an irreversible write. Note run_lr1121_flash_sequence_() adopts a fresh reading at flash time for the ordinary transceiver path; that allowance must not extend to here.
  3. bootloader_version doesn't identify an LR1121 -> NOT_APPLICABLE – REJECT_WRONG_CHIP owns wrong-chip messaging, this function does not duplicate it.
  4. loader_fw != bootloader_version -> NOT_APPLICABLE – Semtech's equality rule for the loader image (see LR1121_LOADER_2100); also the "chip is already on 0x2101" case, since no 0x2101-chip can equal the 0x2100 loader.
  5. target not in the compatibility table (required == 0) -> BLOCKED_UNKNOWN_TARGET – never gamble an irreversible write on an unrecognised target.
  6. required == bootloader_version -> NOT_APPLICABLE – no upgrade needed.
  7. required > bootloader_version -> AVAILABLE – the one path that proceeds.
  8. else (required < bootloader_version) -> BLOCKED_BOOTLOADER_NEWER – a downgrade. The 0x8101 report includes an anti-rollback check, whose exact semantics Semtech does not document, but which most likely makes this permanently impossible; ADR 0021 records how far that is inference.
    Parameters
    block_presentWhether a bootloader: sub-block is configured (the build flag).
    bootloader_version_knownWhether the boot-time excursion successfully read a bootloader version – same "unknown is never evidence" sentinel rule as lr1121_flash_decision().
    bootloader_versionBootloader version read at boot; meaningless if !bootloader_version_known.
    loader_fwVersion parsed from the bootloader: sub-block's loader source: image.
    target_fwConfigured target firmware version (0 if unknown).

Definition at line 210 of file lr1121_firmware_decisions.h.

Here is the call graph for this function:

◆ lr1121_chip_family_for_bootloader()

const char * esphome::home_io_control::lr1121_chip_family_for_bootloader ( uint16_t bootloader_version)
nodiscardconstexpr

Human-readable chip family for a bootloader version that is not one of the two LR1121 values above, for an actionable REJECT_WRONG_CHIP message.

Moved here from hub wiring so the LR1120/LR1110 bootloader IDs live in one place (next to the LR1121 ones they are compared against) and the mapping is host-testable without a hub.

Definition at line 70 of file lr1121_firmware_decisions.h.

◆ lr1121_chip_family_for_device_type()

const char * esphome::home_io_control::lr1121_chip_family_for_device_type ( uint8_t device_type)
nodiscardconstexpr

Human-readable chip family for a normal-mode device_type that is not the LR1121 value above, for an actionable REJECT_WRONG_CHIP message (the layer-3 counterpart of lr1121_chip_family_for_bootloader() above).

Definition at line 81 of file lr1121_firmware_decisions.h.

◆ lr1121_firmware_is_outdated()

bool esphome::home_io_control::lr1121_firmware_is_outdated ( uint8_t fw_major,
uint8_t fw_minor )
nodiscardconstexpr

Pure comparison against the known-latest constants above — no I/O, host-testable.

Only ever flags a version as outdated when it is strictly older than what this file knows about; versions equal to or newer than LR1121_KNOWN_LATEST_FW_* (including any real future firmware this snapshot predates) are never flagged, so a stale baked-in constant fails silent rather than crying wolf.

Definition at line 135 of file radio_lr1121.h.

◆ lr1121_flash_decision()

FlashDecision esphome::home_io_control::lr1121_flash_decision ( uint8_t device_type,
uint8_t bootloader_chip_type,
uint16_t bootloader_version,
uint16_t installed_fw,
uint16_t target_fw,
bool already_confirmed )
nodiscardconstexpr

The single decision point for whether/how to flash target_fw.

Order of checks. Layers 3 and 4 below are the two chip-identity checks (normal-mode device_type and bootloader-mode version); everything else exists to make sure an absent read is never mistaken for evidence:

  1. Boot excursion never completed at all (bootloader_version unknown) – nothing below can be evaluated, so this is checked first and short-circuits straight to NEEDS_CONFIRMATION.
  2. Layer 4 – bootloader-mode identity: type must be the production-silicon byte AND the bootloader version must be one an LR1121 actually reports (as opposed to an LR1120 or LR1110, which also answer bootloader-mode GetVersion, just with different values).
  3. Normal-mode read never happened (device_type unknown, e.g. after a failed init()) – unknown is not evidence of the wrong chip, so this is checked before layer 3 can turn it into a false REJECT_WRONG_CHIP.
  4. Layer 3 – normal-mode chip identity: distinguishes LR1121 from LR1110/LR1120 while normal-mode firmware can still answer.
  5. Bootloader/target compatibility (the three-way rule – known-compatible proceeds, known-incompatible refuses, unknown-target asks for confirmation rather than refusing so a future firmware release keeps working without a code change here).
  6. Only once the pairing is positively known-good: the not-newer-so-confirm version compare.

Every input below has its own "unknown" sentinel, and every one of them routes to NEEDS_CONFIRMATION rather than a rejection or a false PROCEED – an absent read is never evidence of anything, safe or unsafe:

  • bootloader_version == 0: the boot-time excursion never successfully read one. 0x0000 is not a value any real LR11xx bootloader reports.
  • device_type == 0: the normal-mode read never happened at all (failed init(), or the read itself failed). Deliberately still allowed to reach a flash after confirmation – a radio that failed to initialize is exactly the case reflashing is meant to recover.
  • target_fw == 0: the build could not derive a version from the filename and none was configured; can never match a LR1121_KNOWN_BOOTLOADER_REQUIREMENTS entry (none uses 0), so it always resolves to BootloaderSupport::UNKNOWN_TARGET.
  • installed_fw == 0: the installed version is unknown (device_type known-good but the firmware-version bytes could not be read) – treated exactly like "not newer", never as "older than everything" the way a naive target_fw > installed_fw would.
Parameters
device_typeChip identity byte from a normal-mode GetVersion (layer 3); 0 if that read never happened.
bootloader_chip_typetype byte from the bootloader-mode GetVersion read at boot (layer 4); 0xDF (LR1121_BOOTLOADER_TYPE_FOR_FIRMWARE_DECISIONS) for production silicon of any LR11xx family, or 0 if the boot excursion never completed.
bootloader_versionBootloader version read at boot; one of LR1121_BOOTLOADER_2100/2101 for a genuine LR1121, or 0 if never successfully read.
installed_fwCurrently-installed transceiver firmware version (0 if unknown, e.g. after a failed init()).
target_fwConfigured target firmware version (0 if unknown — see above).
already_confirmedTrue on a second button press within the confirmation window; allows every non-hard-reject outcome to proceed instead of asking again.
Returns
The decision; see FlashDecision.

Definition at line 290 of file lr1121_firmware_decisions.h.

Here is the call graph for this function:

◆ lr1121_required_bootloader_for()

uint16_t esphome::home_io_control::lr1121_required_bootloader_for ( uint16_t target_fw)
nodiscardconstexpr

Required bootloader for a known target firmware version.

Returns
The paired bootloader from LR1121_KNOWN_BOOTLOADER_REQUIREMENTS, or 0 when target_fw is not in the table – an "unverified", not "incompatible", target (see that table's comment), and never a real requirement value since no table entry uses 0.

Definition at line 138 of file lr1121_firmware_decisions.h.

◆ make_management_result()

ManagementActionResult esphome::home_io_control::make_management_result ( const std::string & action,
const std::string & device_id )
static

Definition at line 162 of file management_actions.cpp.

◆ manufacturer_name()

const char * esphome::home_io_control::manufacturer_name ( uint8_t id)

Get a human-readable manufacturer name from the protocol manufacturer byte.

The manufacturer ID is a 1-based index assigned by the IO-Homecontrol alliance. IDs outside the known range return "unknown". When an unknown ID appears at runtime, the pairing flow logs a warning suggesting the user file a GitHub issue.

Parameters
idManufacturer ID byte (1–12 for known manufacturers).
Returns
Null-terminated lowercase string such as "unknown", or mixed-case name like "Somfy".

Definition at line 113 of file proto_constants.cpp.

◆ node_id_to_string()

std::string esphome::home_io_control::node_id_to_string ( const uint8_t id[NODE_ID_SIZE])

Format a 3‑byte node ID as a 6‑character uppercase hex string.

Parameters
id3‑byte node ID.
Returns
Hex string (e.g., "123ABC").

Definition at line 50 of file proto_frame.cpp.

◆ normalize_device_id_argument()

std::string esphome::home_io_control::normalize_device_id_argument ( const std::string & device_id)
static

Definition at line 147 of file management_actions.cpp.

Here is the call graph for this function:

◆ oneway_intent_to_target()

std::optional< float > esphome::home_io_control::oneway_intent_to_target ( uint8_t main0,
uint8_t main1 )

Resolve a 1W main-byte pair to an optimistic IO target position, if unambiguous.

Shares decode_1w_main_intent()'s special-code checks so the two never disagree. Returns empty for POS_STOP (the caller must clear any optimistic target instead — stop is not a target) and for codes with no settled position (FAVORITE/VENT/FORCE_OPEN/SECURED_TARGET/ DEFAULT/UNKNOWN) — those cases still get a confirmation poll, just no optimistic claim.

Parameters
main0First main byte (position or special code).
main1Second main byte (modifier); unused by every branch that resolves a target.
Returns
IO target position (0=open, 100=closed) if resolvable; empty otherwise.

Definition at line 292 of file proto_codecs.cpp.

◆ originator_name()

const char * esphome::home_io_control::originator_name ( uint8_t originator)

Get a human-readable name for a command originator byte.

Parameters
originatorOriginator code from the first data byte of CMD_EXECUTE.
Returns
Null-terminated string such as "rain_sensor" or "user_remote".

Definition at line 170 of file proto_constants.cpp.

◆ pairing_stage_name()

const char * esphome::home_io_control::pairing_stage_name ( pairing::PairingState state)
inline

Get a short, log/telemetry-friendly name for a pairing state.

Parameters
statePairing state.
Returns
Null-terminated lowercase string such as "wait_key_challenge".

Definition at line 76 of file hub_pairing.h.

◆ parse()

bool esphome::home_io_control::parse ( const uint8_t * buf,
uint8_t buf_len,
IoFrame & f )

Parse a wire buffer into a parsed IoFrame (validates length and CTRL0).

Parameters
bufRaw byte buffer.
buf_lenNumber of bytes in buf.
fOutput parsed frame.
Returns
true if parse succeeded; false otherwise.

Definition at line 132 of file proto_frame.cpp.

Here is the call graph for this function:

◆ power_save_mode_name()

const char * esphome::home_io_control::power_save_mode_name ( uint8_t mode)

Get a human-readable power save mode name.

Parameters
modePower save value (0–1) extracted from the Multi Information Byte.
Returns
Null-terminated string such as "always_alive" or "low_power".

Definition at line 159 of file proto_constants.cpp.

◆ recover_system_key_from_transfer()

bool esphome::home_io_control::recover_system_key_from_transfer ( const uint8_t transfer_payload[AES_KEY_SIZE],
const uint8_t challenge[HMAC_SIZE],
uint8_t out_key[AES_KEY_SIZE] )

Recover the system key from a CMD_KEY_TRANSFER payload.

Recover the system key from an inbound CMD_KEY_TRANSFER (0x32) payload — the decode counterpart to create_key_transfer()'s encode.

See proto_commands.h for the full contract; this is the single place the IV-data convention ({CMD_KEY_INIT}, len 1) lives for the decode direction, mirroring create_key_transfer()'s encode side below.

Centralizes the IV-data convention in one place: create_key_transfer() derives its IV from the preceding CMD_KEY_INIT (0x31) command byte only (see its own doxygen), so decoding must use that same single-byte {CMD_KEY_INIT} — not the 0x32 frame's own command byte, and not the discovery frame. crypt_key() is symmetric, so this is the same primitive in reverse.

Parameters
transfer_payload16-byte CMD_KEY_TRANSFER payload (frame.data).
challengeThe 6-byte challenge we generated and sent in our own CMD_CHALLENGE_REQ (0x3C) — the far side mixes this into its IV, so decoding requires the exact same bytes.
out_keyOutput: recovered 16-byte system key.
Returns
true on success (crypt_key() AES failure is the only false case).

Definition at line 340 of file proto_commands.cpp.

Here is the call graph for this function:

◆ render_frame_hex_redacted()

void esphome::home_io_control::render_frame_hex_redacted ( const uint8_t * data,
uint8_t len,
char * out,
size_t out_size )
inline

Render a frame's bytes as spaced hex text, masking the payload when the command carries key material (see command_carries_key_material()).

Kept outside the IOHOME_FRAME_LOG guard so the redaction behavior is unit-testable independent of the firmware-only logging build flag.

Warning
IOHOME_UNSAFE_LOG_KEY_MATERIAL disables the masking below entirely. It exists solely so a maintainer can capture a genuine pairing exchange for tests/corpus/ (see tests/corpus/README.md's key-hygiene section) when the normal ingest.py --rekey flow has no other way to obtain the raw bytes. Never set it outside a deliberate, local, own-hardware capture session: build with it, capture the one exchange you need, --rekey immediately, then rebuild without it. Never commit a config with it enabled, never use it on a device whose logs anyone else can see, and never paste output captured under it into an issue/chat before re-keying. hub_core.cpp's setup() logs a loud warning every boot while this is defined specifically so an accidentally-left-on build can't stay quiet.
Parameters
dataRaw serialized frame bytes (header + payload, no CRC).
lenTotal length of data.
outBuffer to write the rendered text into.
out_sizeSize of out.

Definition at line 71 of file log_frame.h.

Here is the call graph for this function:

◆ resolve_discovery_destination()

const uint8_t * esphome::home_io_control::resolve_discovery_destination ( uint8_t command,
bool destination_auto,
const uint8_t destination[NODE_ID_SIZE] )

Resolve the destination address for a discovery command.

When destination_auto is true, returns the conventional address for the given command code. Otherwise returns the configured destination value.

Parameters
commandDiscovery command code.
destination_autoWhether to use the automatic mapping.
destinationExplicit 3-byte destination when auto is false.
Returns
Pointer to the resolved 3-byte node ID.

Definition at line 221 of file tuning_config.cpp.

◆ rssi_scaled_to_dbm()

int16_t esphome::home_io_control::rssi_scaled_to_dbm ( int16_t scaled)
inline

Convert an rssi_ema_scaled fixed-point value to whole dBm (round half away from zero).

Parameters
scaledFixed-point EMA value in 1/RSSI_EMA_SCALE dBm units (not the sentinel).
Returns
Rounded dBm value.

Definition at line 283 of file proto_device_model.h.

◆ serialize()

uint8_t esphome::home_io_control::serialize ( const IoFrame & f,
uint8_t * buf,
uint8_t buf_size )

Serialize a parsed frame into a wire buffer (without CRC).

Parameters
fParsed frame.
bufOutput buffer (must be at least frame_length(f) bytes).
buf_sizeSize of buf.
Returns
Number of bytes written, or 0 on failure.

Definition at line 105 of file proto_frame.cpp.

Here is the call graph for this function:

◆ set_cmd()

bool esphome::home_io_control::set_cmd ( IoFrame & f,
uint8_t cmd,
const uint8_t * params = nullptr,
uint8_t params_len = 0 )

Set command and payload.

Parameters
fFrame to modify.
cmdCommand ID.
paramsPointer to payload bytes (may be nullptr for zero‑length).
params_lenPayload length (0–23).
Returns
true if frame fits within size limits; false otherwise.

Definition at line 85 of file proto_frame.cpp.

◆ set_dst()

void esphome::home_io_control::set_dst ( IoFrame & f,
const uint8_t id[NODE_ID_SIZE] )

Set destination node ID.

Parameters
fFrame to modify.
id3‑byte destination address.

Definition at line 82 of file proto_frame.cpp.

◆ set_src()

void esphome::home_io_control::set_src ( IoFrame & f,
const uint8_t id[NODE_ID_SIZE] )

Set source node ID.

Parameters
fFrame to modify.
id3‑byte source address.

Definition at line 83 of file proto_frame.cpp.

◆ settle_delay_ms()

uint32_t esphome::home_io_control::settle_delay_ms ( uint32_t interval_ms,
uint32_t hint_delay_ms,
bool cap_for_stop )
inlinenodiscard

Resolve the follow-up settle-poll delay while a device may still be moving.

This is the single source of truth for the motion-tracking cadence. The delay is the configured interval_ms, or DEFAULT_SETTLE_POLL_DELAY_MS when no interval is configured (interval_ms == 0). A device-provided byte-7 hint (hint_delay_ms, 0 when absent) and a STOP command (cap_for_stop) may only shorten the delay, never lengthen it.

Note: this resolves the settle delay only — it is intentionally independent of whether a device keeps polling after coming to rest. Periodic monitoring after rest remains opt-in and is gated on interval_ms != 0 by the command paths, so defaulting the settle delay here does not turn every device into a periodic poller.

Returns
Settle delay in milliseconds (always non-zero).

Definition at line 77 of file status_poll_policy.h.

◆ soft_phy_air_time_us()

uint32_t esphome::home_io_control::soft_phy_air_time_us ( uint32_t raw_bytes)
constexpr

On-air time in microseconds for raw_bytes bytes at the protocol's line rate.

One byte is 8 / 38400 s = 208.333 µs. Computed as an integer division rounded up, so the result never falls short of a whole byte's air time and a caller that waits on it never reads the chip's buffer early. The numerator peaks around 360 million for the longest frame this is ever asked about, well inside uint32_t.

Definition at line 78 of file radio_soft_phy_driver_base.h.

◆ soft_phy_peek_frame_length()

uint8_t esphome::home_io_control::soft_phy_peek_frame_length ( const uint8_t * raw,
uint8_t raw_len )

Recover a frame's total length from the very first UART cell of a reception.

CTRL0 bits [4:0] hold frame_length - 1 (see proto_frame.h), and CTRL0 is the first byte after the sync word — so ten bits of air time are enough to learn how long the whole frame will be. Alignment is not yet known at that point, so every probe offset is tried and the largest plausible answer wins: over-waiting by a few bytes costs a little latency, whereas under-waiting would truncate the frame.

Parameters
rawRaw bytes read from the chip's data buffer, starting at the reception's own offset.
raw_lenNumber of raw bytes available (three is enough at any alignment).
Returns
Plausible frame length in bytes, or 0 when no offset yields one.

Definition at line 200 of file radio_soft_phy.cpp.

Here is the call graph for this function:

◆ soft_phy_raw_bytes_for_frame()

uint8_t esphome::home_io_control::soft_phy_raw_bytes_for_frame ( uint8_t frame_len)

Raw on-air bytes needed to carry a whole frame: frame_len protocol bytes plus the two trailing CRC bytes, each UART-packed into a 10-bit cell.

This is what makes a length-driven receive possible at all: a frame's own size is knowable from its first decoded byte, so the raw byte count it will occupy is knowable too — no chip needs to tell us where the frame ends.

Parameters
frame_lenProtocol frame length in bytes (CTRL0's own length field, +1).
Returns
Raw byte count, rounded up to whole bytes.

Definition at line 192 of file radio_soft_phy.cpp.

◆ stored_node_id_is_valid()

bool esphome::home_io_control::stored_node_id_is_valid ( const uint8_t id[NODE_ID_SIZE])
inline

Check if a stored node ID is valid (not all-zero, not all-0xFF).

Parameters
id3‑byte node ID buffer.
Returns
true if the ID is non-zero and non-0xFF.

Definition at line 814 of file hub_core.h.

◆ sx1262_bandwidth_from_string()

std::optional< SX1262RxBandwidth > esphome::home_io_control::sx1262_bandwidth_from_string ( const std::string & value)

Convert a YAML bandwidth string to the enum value.

Parameters
valueYAML string such as "117.3kHz" or "156.2kHz".
Returns
Bandwidth enum, or std::nullopt on invalid input.

Definition at line 70 of file tuning_config.cpp.

◆ sx1262_bandwidth_to_khz()

float esphome::home_io_control::sx1262_bandwidth_to_khz ( SX1262RxBandwidth bw)

Convert a bandwidth enum to the numeric kHz value used in YAML/logs.

Parameters
bwSX1262 bandwidth enum.
Returns
Floating-point kHz value (58.6, 78.2, 117.3, 156.2, or 187.2).

Definition at line 48 of file tuning_config.cpp.

◆ sx1262_bandwidth_to_string()

std::string esphome::home_io_control::sx1262_bandwidth_to_string ( SX1262RxBandwidth bw)

Format a bandwidth enum as its YAML/UI option string (bare kHz number, e.g.

"117.3").

Parameters
bwSX1262 bandwidth enum.
Returns
Bandwidth rendered with one decimal place and a "kHz" suffix.

Definition at line 64 of file tuning_config.cpp.

Here is the call graph for this function:

◆ sx1276_bandwidth_from_string()

std::optional< SX1276RxBandwidth > esphome::home_io_control::sx1276_bandwidth_from_string ( const std::string & value)

Convert a YAML SX1276 bandwidth string to the enum value.

Parameters
valueYAML string such as "41.7" or "83.3kHz".
Returns
Bandwidth enum, or std::nullopt on invalid input.

Definition at line 114 of file tuning_config.cpp.

◆ sx1276_bandwidth_to_khz()

float esphome::home_io_control::sx1276_bandwidth_to_khz ( SX1276RxBandwidth bw)

Convert an SX1276 bandwidth enum to the numeric kHz value used in YAML/logs.

Parameters
bwSX1276 bandwidth enum.
Returns
Floating-point kHz value (20.8, 41.7, 62.5, 83.3, or 125.0).

Definition at line 92 of file tuning_config.cpp.

◆ sx1276_bandwidth_to_string()

std::string esphome::home_io_control::sx1276_bandwidth_to_string ( SX1276RxBandwidth bw)

Format an SX1276 bandwidth enum as its YAML/UI option string (bare kHz number).

Parameters
bwSX1276 bandwidth enum.
Returns
Bandwidth rendered with one decimal place (e.g. "41.7").

Definition at line 108 of file tuning_config.cpp.

Here is the call graph for this function:

◆ trim_ascii_whitespace()

std::string esphome::home_io_control::trim_ascii_whitespace ( const std::string & value)

Trim leading and trailing ASCII whitespace from a string.

This is shared by device-name validation and management actions so both paths normalize input consistently before comparing or writing device metadata.

Parameters
valueInput string.
Returns
Copy of the string with leading and trailing ASCII whitespace removed.

Definition at line 63 of file proto_codecs.cpp.

◆ tuning_config_full_snapshot()

std::string esphome::home_io_control::tuning_config_full_snapshot ( const TuningConfig & cfg)

Format the current tuning configuration as a full one-line snapshot.

Emits every non-default value, regardless of whether it was changed from YAML or from the HA UI. This is logged at the start of every pairing attempt.

Parameters
cfgCurrent tuning configuration.
Returns
One-line snapshot string, or a "defaults" marker when nothing is overridden.

Definition at line 314 of file tuning_config.cpp.

Here is the call graph for this function:

◆ tuning_config_snapshot()

std::string esphome::home_io_control::tuning_config_snapshot ( const TuningConfig & cfg)

Format the current tuning configuration as a one-line YAML-compatible snapshot.

Only values that differ from the default are emitted, so the line can be copied back into YAML with minimal editing. When all values are default, an empty string is returned.

Parameters
cfgCurrent tuning configuration.
Returns
One-line snapshot string, or empty when no overrides are active.

Definition at line 258 of file tuning_config.cpp.

Here is the call graph for this function:

◆ tuning_number_params_begin()

const TuningNumberParam * esphome::home_io_control::tuning_number_params_begin ( )

Definition at line 182 of file tuning_registry.cpp.

◆ tuning_number_params_end()

const TuningNumberParam * esphome::home_io_control::tuning_number_params_end ( )

Definition at line 183 of file tuning_registry.cpp.

◆ tuning_select_params_begin()

const TuningSelectParam * esphome::home_io_control::tuning_select_params_begin ( )

Definition at line 184 of file tuning_registry.cpp.

◆ tuning_select_params_end()

const TuningSelectParam * esphome::home_io_control::tuning_select_params_end ( )

Definition at line 185 of file tuning_registry.cpp.

◆ tuning_update_log_line()

std::string esphome::home_io_control::tuning_update_log_line ( const std::string & name,
const std::string & value )

Format a single tuning update for the log.

Parameters
nameYAML key name of the updated parameter.
valueYAML-compatible string representation of the new value.
Returns
One-line log string suitable for ESP_LOGI.

Definition at line 254 of file tuning_config.cpp.

◆ uart_encode_packet()

uint8_t esphome::home_io_control::uart_encode_packet ( const uint8_t * data,
uint8_t len,
uint8_t * encoded,
uint8_t encoded_max_len )

UART-encode a buffer of bytes (start bit 0, 8 data bits LSB-first, stop bit 1).

Returns
Number of encoded bytes, or 0 if the output buffer is too small.

Definition at line 216 of file radio_soft_phy.cpp.

◆ yaml_device_type_name()

const char * esphome::home_io_control::yaml_device_type_name ( DeviceType type)

Return the YAML-friendly device-type name for types exposed in the Python schema.

Parameters
typeDevice type enum.
Returns
Null‑terminated string (e.g., "external_venetian_blind"), or nullptr if the type has no symbolic YAML alias (user must use a raw numeric value).

Definition at line 170 of file proto_device_model.cpp.

Variable Documentation

◆ ACEI_EXTENDED_MASK

uint8_t esphome::home_io_control::ACEI_EXTENDED_MASK = 0x06
staticconstexpr

Bits [2:1]: extended field.

Definition at line 440 of file proto_constants.h.

◆ ACEI_EXTENDED_SHIFT

uint8_t esphome::home_io_control::ACEI_EXTENDED_SHIFT = 1
staticconstexpr

Shift for extended field extraction.

Definition at line 441 of file proto_constants.h.

◆ ACEI_LEVEL_AUTO_DEFAULT

uint8_t esphome::home_io_control::ACEI_LEVEL_AUTO_DEFAULT = 7
staticconstexpr

Default automatic level (lowest).

Definition at line 459 of file proto_constants.h.

◆ ACEI_LEVEL_AUTO_SAAC

uint8_t esphome::home_io_control::ACEI_LEVEL_AUTO_SAAC = 6
staticconstexpr

Stand-alone automatic controller.

Definition at line 458 of file proto_constants.h.

◆ ACEI_LEVEL_COMFORT_1

uint8_t esphome::home_io_control::ACEI_LEVEL_COMFORT_1 = 4
staticconstexpr

Comfort automation level 1.

Definition at line 456 of file proto_constants.h.

◆ ACEI_LEVEL_COMFORT_2

uint8_t esphome::home_io_control::ACEI_LEVEL_COMFORT_2 = 5
staticconstexpr

Comfort automation level 2.

Definition at line 457 of file proto_constants.h.

◆ ACEI_LEVEL_MASK

uint8_t esphome::home_io_control::ACEI_LEVEL_MASK = 0xE0
staticconstexpr

Bits [7:5]: priority level (0–7).

Definition at line 444 of file proto_constants.h.

◆ ACEI_LEVEL_PROTECTION_HUMAN

uint8_t esphome::home_io_control::ACEI_LEVEL_PROTECTION_HUMAN = 0
staticconstexpr

ACEI priority level values (0–7).

These values are extracted from the ACEI byte via (acei & ACEI_LEVEL_MASK) >> ACEI_LEVEL_SHIFT. Personal safety (highest, overrides all).

Definition at line 452 of file proto_constants.h.

◆ ACEI_LEVEL_PROTECTION_SENSOR

uint8_t esphome::home_io_control::ACEI_LEVEL_PROTECTION_SENSOR = 1
staticconstexpr

Goods/environment protection via sensors.

Definition at line 453 of file proto_constants.h.

◆ ACEI_LEVEL_SHIFT

uint8_t esphome::home_io_control::ACEI_LEVEL_SHIFT = 5
staticconstexpr

Shift for priority level extraction.

Definition at line 445 of file proto_constants.h.

◆ ACEI_LEVEL_USER_DEFAULT

uint8_t esphome::home_io_control::ACEI_LEVEL_USER_DEFAULT = 3
staticconstexpr

Default remote controller priority.

Definition at line 455 of file proto_constants.h.

◆ ACEI_LEVEL_USER_HIGH

uint8_t esphome::home_io_control::ACEI_LEVEL_USER_HIGH = 2
staticconstexpr

High-priority user controller.

Definition at line 454 of file proto_constants.h.

◆ ACEI_SERVICE_MASK

uint8_t esphome::home_io_control::ACEI_SERVICE_MASK = 0x18
staticconstexpr

Bits [4:3]: service type.

Definition at line 442 of file proto_constants.h.

◆ ACEI_SERVICE_SHIFT

uint8_t esphome::home_io_control::ACEI_SERVICE_SHIFT = 3
staticconstexpr

Shift for service field extraction.

Definition at line 443 of file proto_constants.h.

◆ ACEI_VALID_BIT

uint8_t esphome::home_io_control::ACEI_VALID_BIT = 0x01
staticconstexpr

ACEI byte bit-field definitions.

The ACEI byte is the second byte of the CMD_EXECUTE payload. It encodes the priority level and service class of the command, controlling which commands can override others. Devices reject commands with lower priority than their current locked level (resulting in RESULT_PRIORITY_LEVEL_LOCKED). Bit 0: command validity flag.

Definition at line 439 of file proto_constants.h.

◆ ADDRESS_SUFFIX_BROADCAST

uint8_t esphome::home_io_control::ADDRESS_SUFFIX_BROADCAST = 0x3F
staticconstexpr

Suffix for "all devices of this type" broadcast.

Definition at line 86 of file proto_codecs.h.

◆ ADDRESS_SUFFIX_DISCOVERY

uint8_t esphome::home_io_control::ADDRESS_SUFFIX_DISCOVERY = 0x3B
staticconstexpr

Suffix for discovery-related broadcasts.

Definition at line 87 of file proto_codecs.h.

◆ ADDRESS_SUFFIX_MASK

uint8_t esphome::home_io_control::ADDRESS_SUFFIX_MASK = 0x3F
staticconstexpr

Well-known address suffix values in the broadcast address space.

When the first byte of a 3-byte IO-Homecontrol address is 0x00, the low 6 bits of the third byte carry a suffix that identifies the broadcast category. Mask to extract the 6-bit suffix from addr[2].

Definition at line 85 of file proto_codecs.h.

◆ AES_BLOCK_SIZE

uint8_t esphome::home_io_control::AES_BLOCK_SIZE = 16
staticconstexpr

AES block size.

Definition at line 24 of file proto_sizes.h.

◆ AES_KEY_SIZE

uint8_t esphome::home_io_control::AES_KEY_SIZE = 16
staticconstexpr

AES-128 key size.

Definition at line 23 of file proto_sizes.h.

◆ ATT_CLASS_10S

uint8_t esphome::home_io_control::ATT_CLASS_10S = 1
staticconstexpr

Response within 10 seconds.

Definition at line 510 of file proto_constants.h.

◆ ATT_CLASS_20S

uint8_t esphome::home_io_control::ATT_CLASS_20S = 2
staticconstexpr

Response within 20 seconds.

Definition at line 511 of file proto_constants.h.

◆ ATT_CLASS_40S

uint8_t esphome::home_io_control::ATT_CLASS_40S = 3
staticconstexpr

Response within 40 seconds.

Definition at line 512 of file proto_constants.h.

◆ ATT_CLASS_5S

uint8_t esphome::home_io_control::ATT_CLASS_5S = 0
staticconstexpr

Actuator Turnaround Time (ATT) class values.

Indicates the maximum time window in which the actuator normally responds after receiving a command. Extracted from the Multi Information Byte via (flags & DISCOVERY_FLAGS_ATT_MASK) >> DISCOVERY_FLAGS_ATT_SHIFT. Response within 5 seconds.

Definition at line 509 of file proto_constants.h.

◆ BINARY_ENTITY_OFF_POSITION

uint8_t esphome::home_io_control::BINARY_ENTITY_OFF_POSITION = 100
staticconstexpr

Position value written for binary OFF commands (light off, switch off, lock lock).

Definition at line 24 of file operation_queue.h.

◆ BINARY_ENTITY_ON_POSITION

uint8_t esphome::home_io_control::BINARY_ENTITY_ON_POSITION = 0
staticconstexpr

Position value written for binary ON commands (light on, switch on, lock unlock).

Definition at line 22 of file operation_queue.h.

◆ BITS_PER_BYTE

uint8_t esphome::home_io_control::BITS_PER_BYTE = 8
staticconstexpr

Number of bits in one protocol byte.

Definition at line 27 of file proto_sizes.h.

◆ BROADCAST_DISCOVER

uint8_t esphome::home_io_control::BROADCAST_DISCOVER[NODE_ID_SIZE] = {0x00, 0x00, 0x3B}
staticconstexpr

Broadcast address for device discovery (0x00003B).

Used as destination in CMD_DISCOVER_REQ frames to trigger all pairable devices to respond.

Definition at line 339 of file proto_constants.h.

◆ BROADCAST_DISCOVER_ALT

uint8_t esphome::home_io_control::BROADCAST_DISCOVER_ALT[NODE_ID_SIZE] = {0x00, 0x00, 0x3F}
staticconstexpr

Alternate discovery / 1W broadcast address (0x00003F).

Used as destination for CMD_DISCOVER_ALT_REQ (0x2E) alternate discovery, and the address on which devices in 1W-triggered pairing mode listen. Distinct from the 2W discovery broadcast BROADCAST_DISCOVER (0x00003B).

Definition at line 345 of file proto_constants.h.

◆ CMD_ACTIVATE_MODE

uint8_t esphome::home_io_control::CMD_ACTIVATE_MODE = 0x01
staticconstexpr

Activate device mode (scene, ventilation) — requires auth.

Definition at line 25 of file proto_constants.h.

◆ CMD_ADDRESS_REQ

uint8_t esphome::home_io_control::CMD_ADDRESS_REQ = 0x36
staticconstexpr

Address assignment request.

Definition at line 122 of file proto_constants.h.

◆ CMD_ADDRESS_RESP

uint8_t esphome::home_io_control::CMD_ADDRESS_RESP
staticconstexpr
Initial value:
=
0x37

Address assignment response: the device returns its own 3-byte backbone address, byte-identical to the one it reported at data[2..4] (DISCOVERY_RESP_BACKBONE_OFFSET) of its CMD_DISCOVER_RESP earlier in the same session — an independent confirmation of that offset.

Only capture of this pair: tests/corpus/captures/velux_kux100/pairing_full.yaml, where a Velux KLR200 closes pairing with 0x36 and then challenges the 0x37 it gets back (see CMD_CHALLENGE_REQ). Neither command is sent or handled anywhere in this codebase.

Definition at line 123 of file proto_constants.h.

◆ CMD_CHALLENGE_REQ

uint8_t esphome::home_io_control::CMD_CHALLENGE_REQ
staticconstexpr
Initial value:
=
0x3C

6-byte random challenge.

Usually a device challenging a controller's command — the only direction this codebase implements — but the protocol is symmetric and controllers challenge devices too: in tests/corpus/captures/velux_kux100/pairing_full.yaml a KLR200 issues 0x3C against the device's own CMD_ADDRESS_RESP.

Definition at line 140 of file proto_constants.h.

◆ CMD_CHALLENGE_RESP

uint8_t esphome::home_io_control::CMD_CHALLENGE_RESP
staticconstexpr
Initial value:
=
0x3D

HMAC proof answering a 0x3C.

Whoever is challenged authenticates its own preceding frame: the transcript is [cmd, data...] of the challenged party's last frame (create_challenge_resp()), never the challenger's. That holds in both directions — the device-side 0x3D in pairing_full.yaml (over its own 0x37) was recomputed under that installation's recovered key and confirmed before the capture was re-keyed, so it is measured, not assumed by symmetry.

Definition at line 146 of file proto_constants.h.

◆ CMD_DISCOVER_ALT_REQ

uint8_t esphome::home_io_control::CMD_DISCOVER_ALT_REQ
staticconstexpr
Initial value:
=
0x2E

Alternate discovery.

Broadcast (to 0x00003F) draws no response at all on every device this project has real evidence for — a Somfy Izymo dimmer (tests/corpus/captures/somfy_dimmer/discover_alt_no_response.yaml) and a Velux KLR200/KUX100 pair (tests/corpus/captures/velux_kux100/ discover_alt_broadcast_no_response.yaml) both went unanswered; the older "response is 0x29" guess never had real evidence and appears to have been wrong. Directly addressed to a known device instead of broadcast, it does draw a response, but a 0x3C/0x3D challenge-response followed by CMD_DISCOVER_ALT_RESP (0x2F), not 0x29 — see tests/corpus/captures/velux_kux100/ discover_alt_addressed_challenge_response.yaml.

Definition at line 87 of file proto_constants.h.

◆ CMD_DISCOVER_ALT_RESP

uint8_t esphome::home_io_control::CMD_DISCOVER_ALT_RESP
staticconstexpr
Initial value:
=
0x2F

Reply to an addressed (non-broadcast) CMD_DISCOVER_ALT_REQ, following a 0x3C/0x3D challenge-response.

See CMD_DISCOVER_ALT_REQ's comment and tests/corpus/captures/velux_kux100/discover_alt_addressed_challenge_response.yaml — the only capture this project has of it. Not otherwise used anywhere in this codebase (no dispatch logic added).

Definition at line 98 of file proto_constants.h.

◆ CMD_DISCOVER_CONFIRM

uint8_t esphome::home_io_control::CMD_DISCOVER_CONFIRM = 0x2C
staticconstexpr

Confirm discovery to device.

Definition at line 85 of file proto_constants.h.

◆ CMD_DISCOVER_CONFIRM_ACK

uint8_t esphome::home_io_control::CMD_DISCOVER_CONFIRM_ACK = 0x2D
staticconstexpr

Device acknowledges confirmation.

Definition at line 86 of file proto_constants.h.

◆ CMD_DISCOVER_REQ

uint8_t esphome::home_io_control::CMD_DISCOVER_REQ = 0x28
staticconstexpr

Broadcast discovery request.

Definition at line 48 of file proto_constants.h.

◆ CMD_DISCOVER_RESP

uint8_t esphome::home_io_control::CMD_DISCOVER_RESP = 0x29
staticconstexpr

Device responds with its ID and type.

Definition at line 49 of file proto_constants.h.

◆ CMD_DISCOVER_SPE_REQ

uint8_t esphome::home_io_control::CMD_DISCOVER_SPE_REQ
staticconstexpr
Initial value:
=
0x2A

Broadcast roll-call answered by every device that already holds this controller's system key, regardless of device type.

A device that holds no key yet — one in learning mode, mid-pairing — has nothing to authenticate the request against and stays silent, so this enumerates already-managed devices and cannot discover new ones. Do not offer it as a pairing-discovery command: it can only ever add replies from devices already paired, never help reach an unpaired one. The 12-byte payload authenticates itself in a single frame — 6 random challenge bytes followed by a 6-byte HMAC over the command byte alone — instead of the usual 0x3C/0x3D round trip, which is what lets it be broadcast; create_discovery_request() (proto_commands.cpp) builds it to match. Real captured bytes: tests/corpus/captures/velux_kux100/pairing_full.yaml (request shape, HMAC recomputed under that installation's key before the capture was re-keyed) and tests/corpus/captures/somfy_awning/discover_spe_paired_rollcall.yaml plus tests/corpus/captures/somfy_dimmer/discover_spe_paired_rollcall.yaml (two awnings and a dimmer answering one broadcast). No dispatch path consumes the reply yet; classify_pairing_discovery_response() accepts only 0x29 and must not be extended to accept 0x2B, because a roll-call reply from an already-paired device is not a newly-discovered one and must never enter the pairing flow. See CMD_DISCOVER_SPE_RESP.

Definition at line 50 of file proto_constants.h.

◆ CMD_DISCOVER_SPE_RESP

uint8_t esphome::home_io_control::CMD_DISCOVER_SPE_RESP
staticconstexpr
Initial value:
=
0x2B

Roll-call reply to CMD_DISCOVER_SPE_REQ, sent only by devices that already hold the requesting controller's system key.

The payload is the same DISCOVERY_RESP_FULL_SIZE layout as a CMD_DISCOVER_RESP (0x29), so every DISCOVERY_RESP_*_OFFSET constant below applies unchanged — packed type/subtype at data[0..1], backbone address at DISCOVERY_RESP_BACKBONE_OFFSET, manufacturer at DISCOVERY_RESP_MANUFACTURER_OFFSET, Multi Information Byte at DISCOVERY_RESP_FLAGS_OFFSET, timestamp at DISCOVERY_RESP_TIMESTAMP_OFFSET — and PairingEngine::parse_device_from_discovery() decodes a 0x2B correctly with no special-casing. Real captured replies (two awnings and a dimmer) are in tests/corpus/captures/somfy_awning/ and .../somfy_dimmer/ discover_spe_paired_rollcall.yaml. The timestamp is the field that advances between successive replies from one device; it is not a response to the request's random challenge, since that HMAC covers only the constant command byte. Treat a reply as self-description, not proof of identity: nothing in it is bound to the request, so report it, never act on it. No dispatch path consumes a 0x2B yet.

Definition at line 70 of file proto_constants.h.

◆ CMD_ERROR_RESP

uint8_t esphome::home_io_control::CMD_ERROR_RESP = 0xFE
staticconstexpr

Error response to any command.

Definition at line 219 of file proto_constants.h.

◆ CMD_EXECUTE

uint8_t esphome::home_io_control::CMD_EXECUTE = 0x00
staticconstexpr

Set position/open/close/stop — requires authentication.

Definition at line 24 of file proto_constants.h.

◆ CMD_GET_GENERAL_INFO3

uint8_t esphome::home_io_control::CMD_GET_GENERAL_INFO3
staticconstexpr
Initial value:
=
0x58

Observed on the wire (tests/corpus/captures/issues/) with no payload.

Content undecoded. Not sent or handled anywhere in this codebase.

Definition at line 182 of file proto_constants.h.

◆ CMD_GET_GENERAL_INFO3_RESP

uint8_t esphome::home_io_control::CMD_GET_GENERAL_INFO3_RESP
staticconstexpr
Initial value:
=
0x59

Never captured on our own wire.

This constant exists so a received 0x59 frame renders by name instead of as UNKNOWN_CMD. Not sent or handled anywhere in this codebase.

Definition at line 185 of file proto_constants.h.

◆ CMD_GET_INFO1

uint8_t esphome::home_io_control::CMD_GET_INFO1
staticconstexpr
Initial value:
=
0x54

Request device general info 1 (unimplemented; we only use 0x56/0x57).

Definition at line 175 of file proto_constants.h.

◆ CMD_GET_INFO1_RESP

uint8_t esphome::home_io_control::CMD_GET_INFO1_RESP = 0x55
staticconstexpr

Device general info 1 response (unimplemented; we only use 0x56/0x57).

Never observed in our corpus or in any field log — this codebase has never sent CMD_GET_INFO1 to prompt one.

Definition at line 177 of file proto_constants.h.

◆ CMD_GET_INFO2

uint8_t esphome::home_io_control::CMD_GET_INFO2 = 0x56
staticconstexpr

Request device type/model info.

Definition at line 180 of file proto_constants.h.

◆ CMD_GET_INFO2_RESP

uint8_t esphome::home_io_control::CMD_GET_INFO2_RESP = 0x57
staticconstexpr

Device type/model response.

Definition at line 181 of file proto_constants.h.

◆ CMD_GET_NAME

uint8_t esphome::home_io_control::CMD_GET_NAME = 0x50
staticconstexpr

Request device name.

Definition at line 171 of file proto_constants.h.

◆ CMD_GET_NAME_RESP

uint8_t esphome::home_io_control::CMD_GET_NAME_RESP = 0x51
staticconstexpr

Device name response.

Definition at line 172 of file proto_constants.h.

◆ CMD_IDENTIFY

uint8_t esphome::home_io_control::CMD_IDENTIFY = 0x1E
staticconstexpr

Device physical identification / jog — requires authentication.

Definition at line 42 of file proto_constants.h.

◆ CMD_KEY_CONFIRM

uint8_t esphome::home_io_control::CMD_KEY_CONFIRM = 0x33
staticconstexpr

Device confirms key was received.

Definition at line 119 of file proto_constants.h.

◆ CMD_KEY_INIT

uint8_t esphome::home_io_control::CMD_KEY_INIT = 0x31
staticconstexpr

Initiate key transfer to device.

Definition at line 117 of file proto_constants.h.

◆ CMD_KEY_TRANSFER

uint8_t esphome::home_io_control::CMD_KEY_TRANSFER = 0x32
staticconstexpr

Send encrypted system key to device.

Definition at line 118 of file proto_constants.h.

◆ CMD_LAUNCH_KEY_TRANSFER

uint8_t esphome::home_io_control::CMD_LAUNCH_KEY_TRANSFER
staticconstexpr
Initial value:
=
0x38

Device-initiated ("pull") key transfer request.

reference/iown-homecontrol documents its shape as a command ID plus a 6-byte challenge, nothing more. Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase — the constant is used only to construct a hypothetical device-side IV in tests/proto_crypto_test.cpp, exercising the crypto primitive, not a dispatch path.

Definition at line 131 of file proto_constants.h.

◆ CMD_ONEWAY_ADD_CONTROLLER

uint8_t esphome::home_io_control::CMD_ONEWAY_ADD_CONTROLLER
staticconstexpr
Initial value:
=
0x30

1W "add controller": a 1W device broadcasts this while its key-copy gesture is active, handing its network's wrapped system key to whichever controller is listening — see docs/commands.md#30-send-1w-key in the reference project linked from issue #66.

Not parsed or handled anywhere in this codebase (no 1W key-adoption feature exists here); the constant exists solely so redaction.h can recognize and mask any such frame this hub's radio passively overhears from a neighboring installation's 1W pairing gesture, the same way it already does for CMD_ONEWAY_REMOVE in pairing_advisor.cpp.

Definition at line 104 of file proto_constants.h.

◆ CMD_ONEWAY_REMOVE

uint8_t esphome::home_io_control::CMD_ONEWAY_REMOVE = 0x39
staticconstexpr

1W "remove controller" (un-pair a 1W remote from a device); same payload shape as 0x2E.

Definition at line 113 of file proto_constants.h.

◆ CMD_PRIVATE

uint8_t esphome::home_io_control::CMD_PRIVATE = 0x03
staticconstexpr

Get device status — no authentication needed.

Definition at line 26 of file proto_constants.h.

◆ CMD_PRIVATE2

uint8_t esphome::home_io_control::CMD_PRIVATE2
staticconstexpr
Initial value:
=
0x0C

Content otherwise undecoded by the wire parser.

Its request payload matches CMD_EXECUTE's POS_FAVORITE/POS_VENT_MODIFIER stored-position selector with the execution prefix stripped, so it reads like a stored-position readback rather than a live telemetry poll — see tests/corpus/captures/somfy_rs100_oximo/ and captures/issues/issue_45_*.yaml for real request/response pairs. Not handled by any dispatch path in this codebase.

Definition at line 28 of file proto_constants.h.

◆ CMD_PRIVATE2_RESP

uint8_t esphome::home_io_control::CMD_PRIVATE2_RESP = 0x0D
staticconstexpr

Response to CMD_PRIVATE2. See CMD_PRIVATE2's comment.

Definition at line 35 of file proto_constants.h.

◆ CMD_PRIVATE_RESP

uint8_t esphome::home_io_control::CMD_PRIVATE_RESP = 0x04
staticconstexpr

Response to 0x00 and 0x03 (contains position data).

Definition at line 27 of file proto_constants.h.

◆ CMD_READ_GROUPS

uint8_t esphome::home_io_control::CMD_READ_GROUPS
staticconstexpr
Initial value:
=
0xF1

reference/iown-homecontrol heads this "Actuator: Read Groups / "ActuatorAnyConfigIsLocal" (?) / "Service ACK"" — three candidate names, one flagged with its own question mark, from the source itself.

Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase.

Definition at line 204 of file proto_constants.h.

◆ CMD_REBOOT

uint8_t esphome::home_io_control::CMD_REBOOT
staticconstexpr
Initial value:
=
0xF2

reference/iown-homecontrol heads this "Reboot / Service Status" — two candidate names, one of them destructive-sounding, on no field evidence at all.

Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase; treat the "reboot" reading with particular caution; it is a guess.

Definition at line 209 of file proto_constants.h.

◆ CMD_SEND_RAW_MESSAGE

uint8_t esphome::home_io_control::CMD_SEND_RAW_MESSAGE
staticconstexpr
Initial value:
=
0xF0

reference/iown-homecontrol heads this "Send Raw Message / Find Hardware ("Service")" — its own quoting, not settled naming.

Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase.

Definition at line 200 of file proto_constants.h.

◆ CMD_SERVICE_STATUS_ACK

uint8_t esphome::home_io_control::CMD_SERVICE_STATUS_ACK
staticconstexpr
Initial value:
=
0xF3

reference/iown-homecontrol lists this opcode with its body marked TBD — no description at all, not even a hedge to reproduce.

Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase.

Definition at line 214 of file proto_constants.h.

◆ CMD_SET_CONFIG1

uint8_t esphome::home_io_control::CMD_SET_CONFIG1 = 0x6F
staticconstexpr

Configure device to auto-send status updates.

Definition at line 191 of file proto_constants.h.

◆ CMD_SET_CONFIG1_RESP

uint8_t esphome::home_io_control::CMD_SET_CONFIG1_RESP
staticconstexpr
Initial value:
=
0x70

Config response.

reference/iown-homecontrol does not document this opcode at all. Never observed in our corpus or in any field log, and not sent or handled anywhere in this codebase beyond the generic "is this a known command byte" check in radio_soft_phy.cpp.

Definition at line 192 of file proto_constants.h.

◆ CMD_SET_NAME

uint8_t esphome::home_io_control::CMD_SET_NAME = 0x52
staticconstexpr

Set device name (authenticated).

Definition at line 173 of file proto_constants.h.

◆ CMD_SET_NAME_RESP

uint8_t esphome::home_io_control::CMD_SET_NAME_RESP = 0x53
staticconstexpr

Device-name write response.

Definition at line 174 of file proto_constants.h.

◆ CMD_SET_SENSOR

uint8_t esphome::home_io_control::CMD_SET_SENSOR = 0x19
staticconstexpr

Inject sensor value into a device.

Definition at line 38 of file proto_constants.h.

◆ CMD_SET_SENSOR_ACK

uint8_t esphome::home_io_control::CMD_SET_SENSOR_ACK = 0x1A
staticconstexpr

Acknowledgment to CMD_SET_SENSOR.

Definition at line 39 of file proto_constants.h.

◆ CMD_STATUS_UPDATE

uint8_t esphome::home_io_control::CMD_STATUS_UPDATE = 0x71
staticconstexpr

Device-initiated status update (needs auth).

Definition at line 197 of file proto_constants.h.

◆ CMD_STATUS_UPDATE_RESP

uint8_t esphome::home_io_control::CMD_STATUS_UPDATE_RESP = 0x72
staticconstexpr

Acknowledge status update.

Definition at line 198 of file proto_constants.h.

◆ CMD_UNKNOWN4A_REQ

uint8_t esphome::home_io_control::CMD_UNKNOWN4A_REQ
staticconstexpr
Initial value:
=
0x4A

Content undecoded.

The leading published interpretation of this opcode is "Delete File" (a large-data-transfer / "ioblob" request), with "Rename File" as a conflicting second reading — both writes, and no project this codebase draws on has ever transmitted it. Never captured on the wire either. This constant exists solely so a received 0x4A frame renders by name in the log instead of as UNKNOWN_CMD; it must never be sent, and no builder for it exists anywhere in this codebase — see CMD_ONEWAY_ADD_CONTROLLER for the same "named but never sent" precedent, and docs/adr/ for the standing decision not to add one.

Definition at line 155 of file proto_constants.h.

◆ CMD_UNKNOWN4A_RESP

uint8_t esphome::home_io_control::CMD_UNKNOWN4A_RESP
staticconstexpr
Initial value:
=
0x4B

Observed on the wire (tests/corpus/captures/issues/) answering an ON_OFF_SWITCH-type device's traffic, but its request opcode is unconfirmed — it is not established to be CMD_UNKNOWN4A_REQ's reply rather than CMD_GET_GENERAL_INFO3's.

Content undecoded. Not sent or handled anywhere in this codebase.

Definition at line 164 of file proto_constants.h.

◆ CMD_WRITE_PRIVATE

uint8_t esphome::home_io_control::CMD_WRITE_PRIVATE = 0x20
staticconstexpr

Write private register (climate/heating devices).

Definition at line 44 of file proto_constants.h.

◆ CMD_WRITE_PRIVATE_ACK

uint8_t esphome::home_io_control::CMD_WRITE_PRIVATE_ACK = 0x21
staticconstexpr

Acknowledgment to CMD_WRITE_PRIVATE.

Definition at line 45 of file proto_constants.h.

◆ CRC_LSB_MASK

uint16_t esphome::home_io_control::CRC_LSB_MASK = 0x0001
staticconstexpr

Least-significant-bit mask for reflected CRC update.

Definition at line 335 of file proto_constants.h.

◆ CRC_POLYNOMIAL_REVERSED

uint16_t esphome::home_io_control::CRC_POLYNOMIAL_REVERSED = 0x8408
staticconstexpr

Reversed CRC-CCITT polynomial used by IO-homecontrol.

Definition at line 334 of file proto_constants.h.

◆ CTRL0_END

uint8_t esphome::home_io_control::CTRL0_END = 0x80
staticconstexpr

Control byte 0 (CTRL0) bit definitions.

CTRL0 encodes frame flags and the total frame length. Bits [4:0] = frame_length - 1 (so 0x08 means 9 bytes total).

  • START (bit 6): first frame in an exchange; uses long preamble (1024 bytes).
  • END (bit 7): last frame in an exchange; set on responses and command completions.
  • 1W (bit 5): 1=OneWay protocol (no response expected), 0=TwoWay (response expected). For 2W operation, the controller sets START on initial command and device replies with END; subsequent frames in an authenticated exchange also carry END. Bit 7: last frame in exchange

Definition at line 40 of file proto_frame.h.

◆ CTRL0_LENGTH_MASK

uint8_t esphome::home_io_control::CTRL0_LENGTH_MASK = 0x1F
staticconstexpr

Bits [4:0]: frame length - 1.

Definition at line 43 of file proto_frame.h.

◆ CTRL0_PROTOCOL_1W

uint8_t esphome::home_io_control::CTRL0_PROTOCOL_1W = 0x20
staticconstexpr

Bit 5: 1=OneWay protocol, 0=TwoWay protocol.

Definition at line 42 of file proto_frame.h.

◆ CTRL0_START

uint8_t esphome::home_io_control::CTRL0_START = 0x40
staticconstexpr

Bit 6: first frame in exchange (uses long preamble).

Definition at line 41 of file proto_frame.h.

◆ CTRL1_ACK

uint8_t esphome::home_io_control::CTRL1_ACK = 0x10
staticconstexpr

Bit 4: sender can handle 2W responses (ACK-capable).

Definition at line 56 of file proto_frame.h.

◆ CTRL1_BEACON

uint8_t esphome::home_io_control::CTRL1_BEACON = 0x80
staticconstexpr

Bit 7: beacon announcement frame.

Definition at line 59 of file proto_frame.h.

◆ CTRL1_LOW_POWER

uint8_t esphome::home_io_control::CTRL1_LOW_POWER = 0x20
staticconstexpr

Bit 5: low-power device (e.g., solar-powered).

Definition at line 57 of file proto_frame.h.

◆ CTRL1_PRIORITY

uint8_t esphome::home_io_control::CTRL1_PRIORITY = 0x04
staticconstexpr

Bit 2: high-priority frame.

Definition at line 55 of file proto_frame.h.

◆ CTRL1_ROUTED

uint8_t esphome::home_io_control::CTRL1_ROUTED = 0x40
staticconstexpr

Bit 6: frame was relayed through a repeater.

Definition at line 58 of file proto_frame.h.

◆ CTRL1_VERSION_MASK

uint8_t esphome::home_io_control::CTRL1_VERSION_MASK = 0x03
staticconstexpr

Control byte 1 (CTRL1) bit definitions.

CTRL1 carries protocol metadata flags that describe the frame's routing, power mode, and priority characteristics.

  • VERSION (bits [1:0]): protocol version number (usually 0 for current devices).
  • PRIORITY (bit 2): marks a high-priority frame (e.g., discovery, security commands).
  • ACK (bit 4): sender can handle 2W responses (set on all outbound 2W frames).
  • LOW_POWER (bit 5): device is battery/solar powered; may sleep and requires long preamble to wake.
  • ROUTED (bit 6): frame was relayed through a repeater node rather than direct.
  • BEACON (bit 7): beacon announcement frame (device presence advertisement). Bits [1:0]: protocol version (usually 0).

Definition at line 54 of file proto_frame.h.

◆ DEFAULT_PA_PIN_PA_BOOST

uint8_t esphome::home_io_control::DEFAULT_PA_PIN_PA_BOOST = 0x80
inlineconstexpr

SX1276 PA_CONFIG selector for the PA_BOOST output path.

Definition at line 56 of file hub_core.h.

◆ DEFAULT_SETTLE_POLL_DELAY_MS

uint32_t esphome::home_io_control::DEFAULT_SETTLE_POLL_DELAY_MS = 3000
staticconstexpr

Default follow-up settle-poll delay used while a device may still be moving, when no explicit poll interval is configured (interval_ms == 0).

Short on purpose so hint-less devices are re-checked promptly and the motion-tracking loop terminates soon after the device comes to rest.

Definition at line 58 of file status_poll_policy.h.

◆ DEFAULT_TCXO_VOLTAGE_SETTING_1P8V

uint8_t esphome::home_io_control::DEFAULT_TCXO_VOLTAGE_SETTING_1P8V = 0x03
inlineconstexpr

SX1262 DIO3 setting value for a 1.8 V TCXO.

Definition at line 57 of file hub_core.h.

◆ DEFAULT_TX_POWER_DBM

uint8_t esphome::home_io_control::DEFAULT_TX_POWER_DBM = 17
inlineconstexpr

Default TX power used unless YAML overrides it.

Definition at line 55 of file hub_core.h.

◆ DEVICE_METADATA_SIZE

uint8_t esphome::home_io_control::DEVICE_METADATA_SIZE = 2
staticconstexpr

Packed device metadata uses two bytes where the high 8 bits carry the upper type bits and the low byte carries both the remaining type bits and the 6-bit manufacturer subtype.

Definition at line 216 of file proto_device_model.h.

◆ DEVICE_NAME_BUFFER_SIZE

uint8_t esphome::home_io_control::DEVICE_NAME_BUFFER_SIZE = 32
staticconstexpr

Device name storage including null terminator.

Definition at line 228 of file proto_device_model.h.

◆ DEVICE_NAME_WRITE_CHAR_LIMIT

uint8_t esphome::home_io_control::DEVICE_NAME_WRITE_CHAR_LIMIT = 15
staticconstexpr

Reference write limit before the trailing null.

Definition at line 28 of file proto_codecs.h.

◆ DEVICE_NAME_WRITE_PAYLOAD_SIZE

uint8_t esphome::home_io_control::DEVICE_NAME_WRITE_PAYLOAD_SIZE
staticconstexpr
Initial value:
=
static constexpr uint8_t DEVICE_NAME_WRITE_CHAR_LIMIT
Reference write limit before the trailing null.

Fixed write payload: 15 visible chars plus trailing null/padding.

Definition at line 29 of file proto_codecs.h.

◆ DEVICE_SUBTYPE_MASK

uint8_t esphome::home_io_control::DEVICE_SUBTYPE_MASK = 0x3F
staticconstexpr

Definition at line 219 of file proto_device_model.h.

◆ DEVICE_TYPE_HIGH_BITS_SHIFT

uint8_t esphome::home_io_control::DEVICE_TYPE_HIGH_BITS_SHIFT = 6
staticconstexpr

Definition at line 218 of file proto_device_model.h.

◆ DEVICE_TYPE_LOW_BITS_SHIFT

uint8_t esphome::home_io_control::DEVICE_TYPE_LOW_BITS_SHIFT = 2
staticconstexpr

Definition at line 217 of file proto_device_model.h.

◆ DISCOVERY_FLAGS_ATT_MASK

uint8_t esphome::home_io_control::DISCOVERY_FLAGS_ATT_MASK = 0xC0
staticconstexpr

Bit masks and shifts for the Multi Information Byte fields.

Bits [7:6]: actuator turnaround time class.

Definition at line 496 of file proto_constants.h.

◆ DISCOVERY_FLAGS_ATT_SHIFT

uint8_t esphome::home_io_control::DISCOVERY_FLAGS_ATT_SHIFT = 6
staticconstexpr

Shift for ATT field extraction.

Definition at line 497 of file proto_constants.h.

◆ DISCOVERY_FLAGS_POWER_SAVE_MASK

uint8_t esphome::home_io_control::DISCOVERY_FLAGS_POWER_SAVE_MASK = 0x03
staticconstexpr

Bits [1:0]: power save mode.

Definition at line 500 of file proto_constants.h.

◆ DISCOVERY_FLAGS_RF_SUPPORT

uint8_t esphome::home_io_control::DISCOVERY_FLAGS_RF_SUPPORT = 0x08
staticconstexpr

Bit 3: RF support in node (0=yes, 1=no).

Definition at line 499 of file proto_constants.h.

◆ DISCOVERY_FLAGS_SYNC_CTRL_GRP

uint8_t esphome::home_io_control::DISCOVERY_FLAGS_SYNC_CTRL_GRP = 0x20
staticconstexpr

Bit 5: supports sync control group.

Definition at line 498 of file proto_constants.h.

◆ DISCOVERY_RESP_BACKBONE_OFFSET

uint8_t esphome::home_io_control::DISCOVERY_RESP_BACKBONE_OFFSET = 2
staticconstexpr

Byte offsets within CMD_DISCOVER_RESP (0x29) payload data.

The full discovery response carries up to 9 bytes of device metadata: bytes 0–1 hold the packed device type/subtype (already parsed by decode_packed_device_type()), and bytes 2–8 hold additional fields. Backbone address starts at data[2] (3 bytes); cross-confirmed by CMD_ADDRESS_RESP (0x37), which returns the same 3 bytes for the same device (see that constant's comment).

Definition at line 480 of file proto_constants.h.

◆ DISCOVERY_RESP_FLAGS_OFFSET

uint8_t esphome::home_io_control::DISCOVERY_RESP_FLAGS_OFFSET = 6
staticconstexpr

Flags byte at data[6].

Definition at line 485 of file proto_constants.h.

◆ DISCOVERY_RESP_FULL_SIZE

uint8_t esphome::home_io_control::DISCOVERY_RESP_FULL_SIZE = 9
staticconstexpr

Full discovery response payload size.

Definition at line 487 of file proto_constants.h.

◆ DISCOVERY_RESP_MANUFACTURER_OFFSET

uint8_t esphome::home_io_control::DISCOVERY_RESP_MANUFACTURER_OFFSET = 5
staticconstexpr

Manufacturer ID at data[5].

Definition at line 484 of file proto_constants.h.

◆ DISCOVERY_RESP_TIMESTAMP_OFFSET

uint8_t esphome::home_io_control::DISCOVERY_RESP_TIMESTAMP_OFFSET = 7
staticconstexpr

Timestamp starts at data[7] (2 bytes).

Definition at line 486 of file proto_constants.h.

◆ EXCHANGE_RETRY_COUNT

uint8_t esphome::home_io_control::EXCHANGE_RETRY_COUNT = 3
staticconstexpr

Attempts per command before reporting failure.

Definition at line 72 of file proto_timing.h.

◆ EXCHANGE_RETRY_DELAY_MS

int32_t esphome::home_io_control::EXCHANGE_RETRY_DELAY_MS = 250
staticconstexpr

Gap between retries within one HA command.

Definition at line 71 of file proto_timing.h.

◆ FRAME_CMD_OFFSET

uint8_t esphome::home_io_control::FRAME_CMD_OFFSET = 8
staticconstexpr

Byte offset of the command ID in a raw wire buffer.

Definition at line 32 of file proto_sizes.h.

◆ FRAME_CRC_SIZE

uint8_t esphome::home_io_control::FRAME_CRC_SIZE = 2
staticconstexpr

CRC-CCITT trailer appended after the frame body.

Definition at line 33 of file proto_sizes.h.

◆ FRAME_LOG_FLAGS_BUFFER_SIZE

size_t esphome::home_io_control::FRAME_LOG_FLAGS_BUFFER_SIZE = 32
inlineconstexpr

Buffer for decoded CTRL1 flag annotations.

Definition at line 20 of file log_frame.h.

◆ FRAME_LOG_HEX_BUFFER_SIZE

size_t esphome::home_io_control::FRAME_LOG_HEX_BUFFER_SIZE = 220
inlineconstexpr

Fits a full 32-byte frame rendered as spaced hex text.

Definition at line 19 of file log_frame.h.

◆ FRAME_MAX_DATA_SIZE

uint8_t esphome::home_io_control::FRAME_MAX_DATA_SIZE = 23
staticconstexpr

Maximum data bytes after command ID.

Definition at line 31 of file proto_sizes.h.

◆ FRAME_MAX_SIZE

uint8_t esphome::home_io_control::FRAME_MAX_SIZE = 32
staticconstexpr

Maximum frame size (9 header + 23 data).

Definition at line 30 of file proto_sizes.h.

◆ FRAME_MIN_SIZE

uint8_t esphome::home_io_control::FRAME_MIN_SIZE = 9
staticconstexpr

Minimum frame: CTRL0+CTRL1+DST(3)+SRC(3)+CMD(1).

Definition at line 29 of file proto_sizes.h.

◆ FREQ_CH1

uint32_t esphome::home_io_control::FREQ_CH1 = 868250000
staticconstexpr

The protocol uses 3 frequency channels in the 868 MHz ISM band.

IO-Homecontrol uses 3 channels in the 868 MHz SRD band. In 1W (one-way) mode, only CH2 is used. In 2W (two-way) mode, the controller hops across all three channels every ~2.7ms when idle. Commands are sent on CH2; responses may arrive on any channel within the exchange wait window. Channel 1: 868.25 MHz (2W only)

Definition at line 21 of file proto_timing.h.

◆ FREQ_CH2

uint32_t esphome::home_io_control::FREQ_CH2 = 868950000
staticconstexpr

Channel 2: 868.95 MHz (1W and 2W, TX channel).

Definition at line 22 of file proto_timing.h.

◆ FREQ_CH3

uint32_t esphome::home_io_control::FREQ_CH3 = 869850000
staticconstexpr

Channel 3: 869.85 MHz (2W only).

Definition at line 23 of file proto_timing.h.

◆ FXOSC

uint32_t esphome::home_io_control::FXOSC = 32000000U
staticconstexpr

SX1276 crystal oscillator frequency (32 MHz).

Used to calculate register values for bitrate, frequency deviation, and carrier frequency.

Definition at line 67 of file radio_sx1276.h.

◆ HMAC_SIZE

uint8_t esphome::home_io_control::HMAC_SIZE = 6
staticconstexpr

Authentication HMAC is 6 bytes (truncated AES output).

Definition at line 22 of file proto_sizes.h.

◆ HOP_TIME_US

int32_t esphome::home_io_control::HOP_TIME_US = 2700
staticconstexpr

Timing constants for frequency hopping and response waiting.

Time per channel when hopping (2.7ms)

Definition at line 39 of file proto_timing.h.

◆ INITIAL_STATUS_REQUEST_DELAY_MS

uint32_t esphome::home_io_control::INITIAL_STATUS_REQUEST_DELAY_MS = 5000
staticconstexpr

Delay before the first post-boot status request from an entity.

Definition at line 39 of file status_poll_policy.h.

◆ IV_PADDING

uint8_t esphome::home_io_control::IV_PADDING = 0x55
staticconstexpr

Padding byte used in IV construction.

Definition at line 26 of file proto_sizes.h.

◆ IV_SIZE

uint8_t esphome::home_io_control::IV_SIZE = 16
staticconstexpr

Initialization vector size for AES.

Definition at line 25 of file proto_sizes.h.

◆ LATIN1_CODEPOINT_MAX

uint16_t esphome::home_io_control::LATIN1_CODEPOINT_MAX = 0x00FF
staticconstexpr

Highest Unicode code point representable in Latin-1.

Definition at line 31 of file proto_codecs.h.

◆ LBT_MAX_RETRIES

uint8_t esphome::home_io_control::LBT_MAX_RETRIES = 5
staticconstexpr

Max carrier-sense attempts before TX anyway.

Definition at line 79 of file proto_timing.h.

◆ LBT_RETRY_DELAY_MS

uint8_t esphome::home_io_control::LBT_RETRY_DELAY_MS = 5
staticconstexpr

Backoff between LBT checks (≥ 5ms per ETSI).

Definition at line 80 of file proto_timing.h.

◆ LBT_RSSI_THRESHOLD_DBM

int16_t esphome::home_io_control::LBT_RSSI_THRESHOLD_DBM = -90
staticconstexpr

Listen-before-talk (LBT) parameters for ETSI EN 300 220 compliance.

Before transmitting, the radio checks that the channel RSSI is below the threshold. If the channel is busy, TX is deferred by LBT_RETRY_DELAY_MS up to LBT_MAX_RETRIES times. Channel-free threshold (ETSI: ≤ -90 dBm)

Definition at line 78 of file proto_timing.h.

◆ LONG_PREAMBLE

uint16_t esphome::home_io_control::LONG_PREAMBLE = 1024
staticconstexpr

Preamble is a sequence of 0xAA bytes that precedes every frame.

The first frame in an exchange uses a long preamble (1024 bytes = 8192 bits) so the receiver has time to detect it while hopping. Subsequent frames in the same exchange use a short preamble (8 bytes) since both sides are already on the same channel. Solar-powered devices need the long preamble to wake up. 1024 bytes for initial/start frames

Definition at line 30 of file proto_timing.h.

◆ LR1110_BOOTLOADER_1001

uint16_t esphome::home_io_control::LR1110_BOOTLOADER_1001 = 0x1001
inlineconstexpr

Definition at line 51 of file lr1121_firmware_decisions.h.

◆ LR1110_BOOTLOADER_6500

uint16_t esphome::home_io_control::LR1110_BOOTLOADER_6500 = 0x6500
inlineconstexpr

Definition at line 50 of file lr1121_firmware_decisions.h.

◆ LR1110_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS

uint8_t esphome::home_io_control::LR1110_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x01
inlineconstexpr

Normal-mode GetVersion type bytes for the two chips an LR1121 is most easily confused with — companions to LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS above, used only to name the chip family in a REJECT_WRONG_CHIP message.

Last checked 2026-08-05.

Definition at line 28 of file lr1121_firmware_decisions.h.

◆ LR1120_BOOTLOADER_2000

uint16_t esphome::home_io_control::LR1120_BOOTLOADER_2000 = 0x2000
inlineconstexpr

Bootloader versions reported by the two chips an LR1121 is most easily confused with — used only to name the chip family in a REJECT_WRONG_CHIP message.

Same snapshot discipline as LR1121_BOOTLOADER_2100/2101; last checked 2026-08-05.

Definition at line 48 of file lr1121_firmware_decisions.h.

◆ LR1120_BOOTLOADER_2001

uint16_t esphome::home_io_control::LR1120_BOOTLOADER_2001 = 0x2001
inlineconstexpr

Definition at line 49 of file lr1121_firmware_decisions.h.

◆ LR1120_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS

uint8_t esphome::home_io_control::LR1120_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x02
inlineconstexpr

Definition at line 29 of file lr1121_firmware_decisions.h.

◆ LR1121_BOOTLOADER_2100

uint16_t esphome::home_io_control::LR1121_BOOTLOADER_2100 = 0x2100
inlineconstexpr

LR1121 bootloader versions, from Semtech's published compatibility matrix.

An LR1121 reports one of these two; LR1120 reports 0x2000/0x2001 and LR1110 0x6500/0x1001, which is what makes checking against these two a chip-family check as well as a capability check.

Definition at line 42 of file lr1121_firmware_decisions.h.

◆ LR1121_BOOTLOADER_2101

uint16_t esphome::home_io_control::LR1121_BOOTLOADER_2101 = 0x2101
inlineconstexpr

Definition at line 43 of file lr1121_firmware_decisions.h.

◆ LR1121_BOOTLOADER_TYPE_FOR_FIRMWARE_DECISIONS

uint8_t esphome::home_io_control::LR1121_BOOTLOADER_TYPE_FOR_FIRMWARE_DECISIONS = 0xDF
inlineconstexpr

LR1121 GetVersion type byte reported while running the bootloader (LR11XX_TYPE_PRODUCTION_MODE) — must match radio_lr1121_firmware_updater.h's LR1121_UPDATER_BOOTLOADER_TYPE (0xDF).

Kept as a separate constant for the same dependency-free reason as LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS above. Note this byte identifies production silicon, not chip family — bootloader type is 0xDF on an LR1120 or LR1110 too, which is why chip family is decided from the bootloader version, not this byte.

Definition at line 37 of file lr1121_firmware_decisions.h.

◆ LR1121_BUSY_TIMEOUT_MS

const uint32_t esphome::home_io_control::LR1121_BUSY_TIMEOUT_MS = 3000
static

Definition at line 34 of file radio_lr1121.cpp.

◆ LR1121_CALIBRATE_ALL_BLOCKS

uint8_t esphome::home_io_control::LR1121_CALIBRATE_ALL_BLOCKS = 0x3F
staticconstexpr

Calibrate "all blocks" bitmask.

LR11xx calibration blocks are LF-RC(0)/HF-RC(1)/PLL(2)/ ADC(3)/IMG(4)/PLL-TX(5), so "all" = 0x3F — NOT the SX126x value (0x7F), which uses a different bit layout for a different chip.

Definition at line 154 of file radio_lr1121.h.

◆ LR1121_CMD_CALIBRATE

uint16_t esphome::home_io_control::LR1121_CMD_CALIBRATE = 0x010F
staticconstexpr

cross-checked

Definition at line 50 of file radio_lr1121.h.

◆ LR1121_CMD_CALIBRATE_IMAGE

uint16_t esphome::home_io_control::LR1121_CMD_CALIBRATE_IMAGE = 0x0111
staticconstexpr

cross-checked (RadioLib calibrateImageRejection)

Definition at line 51 of file radio_lr1121.h.

◆ LR1121_CMD_CLEAR_ERRORS

uint16_t esphome::home_io_control::LR1121_CMD_CLEAR_ERRORS
staticconstexpr
Initial value:
=
0x010E

hardware-verified (called on every init/RX cycle, never rejected — see log_command_status_())

Definition at line 44 of file radio_lr1121.h.

◆ LR1121_CMD_CLEAR_IRQ

uint16_t esphome::home_io_control::LR1121_CMD_CLEAR_IRQ = 0x0114
staticconstexpr

cross-checked

Definition at line 54 of file radio_lr1121.h.

◆ LR1121_CMD_GET_ERRORS

uint16_t esphome::home_io_control::LR1121_CMD_GET_ERRORS = 0x010D
staticconstexpr

cross-checked (2-byte response)

Definition at line 43 of file radio_lr1121.h.

◆ LR1121_CMD_GET_PKT_STATUS

uint16_t esphome::home_io_control::LR1121_CMD_GET_PKT_STATUS
staticconstexpr
Initial value:
=
0x0204

cross-checked (Semtech SWDR001 lr11xx_radio.c :: lr11xx_radio_get_gfsk_pkt_status — 0 request params, 4-byte GFSK response: [rssi_sync, rssi_avg, rx_len, status_flags], rssi_sync/avg both decode via -(raw>>1) dBm, same formula as LR1121_CMD_GET_RSSI_INST)

Definition at line 58 of file radio_lr1121.h.

◆ LR1121_CMD_GET_RSSI_INST

uint16_t esphome::home_io_control::LR1121_CMD_GET_RSSI_INST = 0x0205
staticconstexpr

cross-checked

Definition at line 62 of file radio_lr1121.h.

◆ LR1121_CMD_GET_RX_BUFFER_STATUS

uint16_t esphome::home_io_control::LR1121_CMD_GET_RX_BUFFER_STATUS = 0x0203
staticconstexpr

cross-checked

Definition at line 57 of file radio_lr1121.h.

◆ LR1121_CMD_GET_STATUS

uint16_t esphome::home_io_control::LR1121_CMD_GET_STATUS = 0x0100
staticconstexpr

cross-checked

Definition at line 41 of file radio_lr1121.h.

◆ LR1121_CMD_GET_VERSION

uint16_t esphome::home_io_control::LR1121_CMD_GET_VERSION = 0x0101
staticconstexpr

cross-checked

Definition at line 42 of file radio_lr1121.h.

◆ LR1121_CMD_READ_BUFFER

uint16_t esphome::home_io_control::LR1121_CMD_READ_BUFFER = 0x010A
staticconstexpr

cross-checked

Definition at line 47 of file radio_lr1121.h.

◆ LR1121_CMD_SET_DIO_AS_RF_SWITCH

uint16_t esphome::home_io_control::LR1121_CMD_SET_DIO_AS_RF_SWITCH = 0x0112
staticconstexpr

cross-checked

Definition at line 52 of file radio_lr1121.h.

◆ LR1121_CMD_SET_DIO_IRQ_PARAMS

uint16_t esphome::home_io_control::LR1121_CMD_SET_DIO_IRQ_PARAMS = 0x0113
staticconstexpr

cross-checked

Definition at line 53 of file radio_lr1121.h.

◆ LR1121_CMD_SET_GFSK_SYNC_WORD

uint16_t esphome::home_io_control::LR1121_CMD_SET_GFSK_SYNC_WORD = 0x0206
staticconstexpr

cross-checked

Definition at line 63 of file radio_lr1121.h.

◆ LR1121_CMD_SET_MODULATION_PARAMS

uint16_t esphome::home_io_control::LR1121_CMD_SET_MODULATION_PARAMS = 0x020F
staticconstexpr

cross-checked

Definition at line 68 of file radio_lr1121.h.

◆ LR1121_CMD_SET_PA_CONFIG

uint16_t esphome::home_io_control::LR1121_CMD_SET_PA_CONFIG = 0x0215
staticconstexpr

cross-checked

Definition at line 72 of file radio_lr1121.h.

◆ LR1121_CMD_SET_PACKET_PARAMS

uint16_t esphome::home_io_control::LR1121_CMD_SET_PACKET_PARAMS = 0x0210
staticconstexpr

cross-checked

Definition at line 69 of file radio_lr1121.h.

◆ LR1121_CMD_SET_PACKET_TYPE

uint16_t esphome::home_io_control::LR1121_CMD_SET_PACKET_TYPE = 0x020E
staticconstexpr

cross-checked

Definition at line 67 of file radio_lr1121.h.

◆ LR1121_CMD_SET_RF_FREQUENCY

uint16_t esphome::home_io_control::LR1121_CMD_SET_RF_FREQUENCY = 0x020B
staticconstexpr

cross-checked

Definition at line 66 of file radio_lr1121.h.

◆ LR1121_CMD_SET_RX

uint16_t esphome::home_io_control::LR1121_CMD_SET_RX = 0x0209
staticconstexpr

cross-checked

Definition at line 64 of file radio_lr1121.h.

◆ LR1121_CMD_SET_RX_TX_FALLBACK_MODE

uint16_t esphome::home_io_control::LR1121_CMD_SET_RX_TX_FALLBACK_MODE = 0x0213
staticconstexpr

cross-checked

Definition at line 71 of file radio_lr1121.h.

◆ LR1121_CMD_SET_STANDBY

uint16_t esphome::home_io_control::LR1121_CMD_SET_STANDBY = 0x011C
staticconstexpr

cross-checked

Definition at line 56 of file radio_lr1121.h.

◆ LR1121_CMD_SET_TCXO_MODE

uint16_t esphome::home_io_control::LR1121_CMD_SET_TCXO_MODE = 0x0117
staticconstexpr

cross-checked

Definition at line 55 of file radio_lr1121.h.

◆ LR1121_CMD_SET_TX

uint16_t esphome::home_io_control::LR1121_CMD_SET_TX = 0x020A
staticconstexpr

cross-checked

Definition at line 65 of file radio_lr1121.h.

◆ LR1121_CMD_SET_TX_PARAMS

uint16_t esphome::home_io_control::LR1121_CMD_SET_TX_PARAMS = 0x0211
staticconstexpr

cross-checked

Definition at line 70 of file radio_lr1121.h.

◆ LR1121_CMD_WRITE_BUFFER

uint16_t esphome::home_io_control::LR1121_CMD_WRITE_BUFFER = 0x0109
staticconstexpr

cross-checked

Definition at line 46 of file radio_lr1121.h.

◆ LR1121_CMD_WRITE_REG_MEM_MASK32

uint16_t esphome::home_io_control::LR1121_CMD_WRITE_REG_MEM_MASK32
staticconstexpr
Initial value:
=
0x010C

cross-checked (Semtech SWDR001 lr11xx_radio.c / RadioLib LR11x0_commands.h)

Definition at line 48 of file radio_lr1121.h.

◆ LR1121_DEVICE_TYPE

uint8_t esphome::home_io_control::LR1121_DEVICE_TYPE = 0x03
staticconstexpr

cross-checked (design §1.2 "Identity" row)

Definition at line 106 of file radio_lr1121.h.

◆ LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS

uint8_t esphome::home_io_control::LR1121_DEVICE_TYPE_FOR_FIRMWARE_DECISIONS = 0x03
inlineconstexpr

LR1121 GetVersion type byte in normal mode — must match radio_lr1121.h's LR1121_DEVICE_TYPE (0x03).

Kept as a separate constant, not a shared header include, so this header stays dependency-free; see the file header for why. A static_assert in tests/radio_lr1121_firmware_updater_test.cpp (a translation unit that already includes both headers) guards the two from silently drifting apart.

Definition at line 23 of file lr1121_firmware_decisions.h.

◆ LR1121_DISCOVERY_HOP_SLICE_MS

uint16_t esphome::home_io_control::LR1121_DISCOVERY_HOP_SLICE_MS = SX1262_DISCOVERY_HOP_SLICE_MS
staticconstexpr

Per-channel dwell while LR1121 pairing discovery hops across channels.

LR1121 frequency changes require a standby→SetRfFrequency→RX cycle, same as the SX1262, so the dwell is seeded from the SX1262-validated default pending Step 7 hardware tuning.

Definition at line 150 of file tuning_config.h.

◆ LR1121_EXCHANGE_RESPONSE_WAIT_SLICE_MS

int32_t esphome::home_io_control::LR1121_EXCHANGE_RESPONSE_WAIT_SLICE_MS = 600
staticconstexpr

LR1121-specific per-channel dwell while waiting for authenticated exchange responses.

NOT seeded from the SX1262 value anymore (was 90, matching SX1262_EXCHANGE_RESPONSE_WAIT_SLICE_MS exactly) — see 2026-07-17 hardware bring-up: golden captures for this exact device (tests/corpus/captures/somfy_awning/exchange_open_sx1276.yaml) show the device's first reply arriving ~287ms after the request, on the same channel the request went out on, against a 300ms total wait budget split into 90ms per-channel hop slices (CH2→CH3→CH1→CH2). That only leaves the last ~30ms hop-back-to-CH2 slice to catch it — survivable for SX1262/SX1276, but LR1121's two-transaction 16-bit-opcode SPI protocol makes each hop's SetStandby/SetRfFrequency/ SetRx round-trip slower, which can push the hop-back-to-CH2 moment past 287ms and cause a clean miss every try. Set above the largest response-wait budget (RESPONSE_WAIT_MS=500 in proto_timing.h) so this driver never hops away from the request's channel while waiting for a reply — real replies for this device only ever arrive on that same channel anyway, so hopping during the wait was actively counterproductive, not just slow.

Definition at line 232 of file radio_lr1121.h.

◆ LR1121_FALLBACK_STDBY_XOSC

uint8_t esphome::home_io_control::LR1121_FALLBACK_STDBY_XOSC = 0x02
staticconstexpr

SetRxTxFallbackMode value for STDBY_XOSC.

LR11xx fallback-mode is a small sequential enum (FS=0x00, STDBY_RC=0x01, STDBY_XOSC=0x02), unlike SX126x's raw standby-mode byte (0x30) reused directly in that field.

Definition at line 159 of file radio_lr1121.h.

◆ LR1121_GFSK_CRC_OFF

uint8_t esphome::home_io_control::LR1121_GFSK_CRC_OFF = 0x01
staticconstexpr

cross-checked (same encoding as SX126x)

Definition at line 141 of file radio_lr1121.h.

◆ LR1121_GFSK_PACKET_FIXED_LENGTH

uint8_t esphome::home_io_control::LR1121_GFSK_PACKET_FIXED_LENGTH = 0x00
staticconstexpr

cross-checked (same encoding as SX126x)

Definition at line 142 of file radio_lr1121.h.

◆ LR1121_IMAGE_CAL_FREQ1

uint8_t esphome::home_io_control::LR1121_IMAGE_CAL_FREQ1 = 0xD7
staticconstexpr

Banded image calibration for 868.25-869.85MHz +/-4MHz (~860-876MHz), matching RadioLib's setFrequency() margin.

CalibImage params are {floor((fmin-1)/4), ceil((fmax+1)/4)}.

Definition at line 190 of file radio_lr1121.h.

◆ LR1121_IMAGE_CAL_FREQ2

uint8_t esphome::home_io_control::LR1121_IMAGE_CAL_FREQ2 = 0xDB
staticconstexpr

Definition at line 191 of file radio_lr1121.h.

◆ LR1121_IRQ_ACTIVITY_MASK

uint32_t esphome::home_io_control::LR1121_IRQ_ACTIVITY_MASK
staticconstexpr
Initial value:
=
static constexpr uint32_t LR1121_IRQ_TIMEOUT
static constexpr uint32_t LR1121_IRQ_TX_DONE
static constexpr uint32_t LR1121_IRQ_CRC_ERR
static constexpr uint32_t LR1121_IRQ_SYNC_WORD_VALID
static constexpr uint32_t LR1121_IRQ_RX_DONE

IRQ bits that represent a terminal radio event — a frame finished decoding, an outbound frame completed, or the chip gave up on its own.

Deliberately excludes PREAMBLE_DETECTED, even though it's part of LR1121_IRQ_DIO_ENABLE_MASK: a preamble alone means a frame may still be arriving, so SoftPhyDriverBase's poll_until_activity_()/check_for_packet() (gated by RadioLR1121::activity_irq_mask) must not treat it as terminal — doing so would tear down RX mid-reception.

Definition at line 92 of file radio_lr1121.h.

◆ LR1121_IRQ_CRC_ERR

uint32_t esphome::home_io_control::LR1121_IRQ_CRC_ERR = 1UL << 7
staticconstexpr

Definition at line 83 of file radio_lr1121.h.

◆ LR1121_IRQ_DIO_ENABLE_MASK

uint32_t esphome::home_io_control::LR1121_IRQ_DIO_ENABLE_MASK
staticconstexpr
Initial value:

DIO-routed IRQ enable mask: TxDone|RxDone|PreambleDetected|SyncWordValid|Timeout (design implementation §Step 2, item 2 — deliberately excludes CrcErr from the DIO-routed set, unlike SX1262; CrcErr is still visible in the raw status word for capture diagnostics).

Definition at line 98 of file radio_lr1121.h.

◆ LR1121_IRQ_PREAMBLE_DETECTED

uint32_t esphome::home_io_control::LR1121_IRQ_PREAMBLE_DETECTED = 1UL << 4
staticconstexpr

Definition at line 81 of file radio_lr1121.h.

◆ LR1121_IRQ_RX_DONE

uint32_t esphome::home_io_control::LR1121_IRQ_RX_DONE = 1UL << 3
staticconstexpr

Definition at line 80 of file radio_lr1121.h.

◆ LR1121_IRQ_SYNC_WORD_VALID

uint32_t esphome::home_io_control::LR1121_IRQ_SYNC_WORD_VALID = 1UL << 5
staticconstexpr

Definition at line 82 of file radio_lr1121.h.

◆ LR1121_IRQ_TIMEOUT

uint32_t esphome::home_io_control::LR1121_IRQ_TIMEOUT = 1UL << 10
staticconstexpr

Definition at line 84 of file radio_lr1121.h.

◆ LR1121_IRQ_TX_DONE

uint32_t esphome::home_io_control::LR1121_IRQ_TX_DONE = 1UL << 2
staticconstexpr

Definition at line 79 of file radio_lr1121.h.

◆ LR1121_KNOWN_BOOTLOADER_REQUIREMENTS

Lr1121BootloaderRequirement esphome::home_io_control::LR1121_KNOWN_BOOTLOADER_REQUIREMENTS[]
inlineconstexpr
Initial value:
= {
}
constexpr uint16_t LR1121_BOOTLOADER_2100
LR1121 bootloader versions, from Semtech's published compatibility matrix.
constexpr uint16_t LR1121_BOOTLOADER_2101

Bootloader requirements we know about, copied from Semtech's published pairings (SWTL001/application/src/lr11xx_update_utils.c :: compatibility_matrix[]): 0x0101/0x0102/0x0103 need bootloader 0x2100, 0x0104 needs 0x2101.

This is an ADVISORY list of pairs we can warn about, not a compatibility authority — it is a point-in-time snapshot and a target absent from it is "unverified", never "incompatible". Extending this when Semtech publishes a new image is a one-line edit; it belongs next to LR1121_KNOWN_LATEST_FW_* (radio_lr1121.h) as the same kind of snapshot, with the same staleness discipline. Last checked 2026-08-05.

Definition at line 103 of file lr1121_firmware_decisions.h.

◆ LR1121_KNOWN_LATEST_FW_MAJOR

uint8_t esphome::home_io_control::LR1121_KNOWN_LATEST_FW_MAJOR = 0x01
staticconstexpr

Newest LR1121 transceiver firmware known at the time this file was last updated, per the version-numbered filenames and CHANGELOG.md at https://github.com/Lora-net/radio_firmware_images/tree/master/lr1121/transceiver — the same two bytes GetVersion reports as fw_major/fw_minor (e.g.

lr1121_transceiver_0104.bin is major=0x01, minor=0x04). Deliberately NOT queried live (baked in, per design decision) — this is a point-in-time snapshot that will go stale as Semtech ships new firmware, and needs a manual refresh here when it does.

Last checked 2026-08-05: latest is 0x0104 (2026-04-01), which per that changelog fixes CVE-2025-14857/-14858/-14859 (see https://www.semtech.com/company/security/security-bulletins) on top of earlier feature/bugfix releases — not just a cosmetic version bump.

Reachability caveat: this project's lr1121_firmware_update: feature (docs/home_io_control.md) can flash any published image, but 0x0104 requires bootloader 0x2101. Reaching it from the common 0x2100 bootloader needs the separate, opt-in bootloader rewrite (ADR 0021) — an irreversible operation gated behind its own arming switch — so without that opted in, 0x0103 is the practical ceiling. The "update available" line below can therefore point at a version that is not reachable on a given chip as currently configured; the flash feature's own boot-time bootloader-version report is what tells a user which case they are in.

Definition at line 127 of file radio_lr1121.h.

◆ LR1121_KNOWN_LATEST_FW_MINOR

uint8_t esphome::home_io_control::LR1121_KNOWN_LATEST_FW_MINOR = 0x04
staticconstexpr

Definition at line 128 of file radio_lr1121.h.

◆ LR1121_LOADER_2100

uint16_t esphome::home_io_control::LR1121_LOADER_2100 = 0x2100
inlineconstexpr

Version the lr1121_loader_2100.bin bootloader-*loader* image reports of itself.

Numerically identical to LR1121_BOOTLOADER_2100, but a distinct concept: this is the loader firmware's own self-reported version, which Semtech's compatibility rule requires to equal the bootloader version currently running before the loader may be used – not a "requires bootloader >= X" rule like LR1121_KNOWN_BOOTLOADER_REQUIREMENTS below.

Definition at line 58 of file lr1121_firmware_decisions.h.

◆ LR1121_PACKET_TYPE_GFSK

uint8_t esphome::home_io_control::LR1121_PACKET_TYPE_GFSK = 0x01
staticconstexpr

cross-checked (design §3.2 step 5)

Definition at line 140 of file radio_lr1121.h.

◆ LR1121_POST_TX_SETTLE_US

uint16_t esphome::home_io_control::LR1121_POST_TX_SETTLE_US = SX1262_POST_TX_SETTLE_US
staticconstexpr

LR1121-specific post-TX settling delay before re-entering RX.

Seeded from the SX1262-validated default; same rationale as LR1121_RESPONSE_PREAMBLE.

Definition at line 144 of file tuning_config.h.

◆ LR1121_PREAMBLE_DETECTOR_16_BIT

uint8_t esphome::home_io_control::LR1121_PREAMBLE_DETECTOR_16_BIT = 0x05
staticconstexpr

Preamble detector length selector: 16 bits.

Shares the SX126x GFSK preamble-detector enum (0x00 off, 0x04=8bit, 0x05=16bit, 0x06=24bit, 0x07=32bit) — the LR11xx sub-GHz GFSK modem descends from the same core.

Definition at line 146 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_1_ADDR

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_ADDR = 0x00F20344
staticconstexpr

GFSK modulation workaround register trio, standard (non-0.6/1.2kbps) values for our 38.4kbps config — applied after every modulation-params write, mirroring RadioLib's workaroundGFSK() ("always the first step, even when resetting" per its own comment on the first write).

Definition at line 178 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_1_MASK

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_MASK = 0x00000030
staticconstexpr

Definition at line 179 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_1_VALUE

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_1_VALUE = 0x00000010
staticconstexpr

Definition at line 180 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_2_ADDR

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_ADDR = 0x00F20348
staticconstexpr

Definition at line 181 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_2_MASK

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_MASK = 0x00000005
staticconstexpr

Definition at line 182 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_2_VALUE

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_2_VALUE = 0x00000001
staticconstexpr

Definition at line 183 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_3_ADDR

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_ADDR = 0x00F20244
staticconstexpr

Definition at line 184 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_3_MASK

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_MASK = 0x0001FF03
staticconstexpr

Definition at line 185 of file radio_lr1121.h.

◆ LR1121_REG_GFSK_WORKAROUND_3_VALUE

uint32_t esphome::home_io_control::LR1121_REG_GFSK_WORKAROUND_3_VALUE = 0x00000A01
staticconstexpr

Definition at line 186 of file radio_lr1121.h.

◆ LR1121_REG_HIGH_ACP_WORKAROUND_ADDR

uint32_t esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_ADDR = 0x00F30054
staticconstexpr

High-ACP (adjacent channel power) TX-quality erratum: clear bit 30 of this register before every SetRx/SetTx.

Without it the chip's TX spectrum has excess spectral regrowth — plausibly why our own (tolerant) monitors decode our frames byte-exact while the awning's spec-compliant receiver mostly can't.

Definition at line 171 of file radio_lr1121.h.

◆ LR1121_REG_HIGH_ACP_WORKAROUND_MASK

uint32_t esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_MASK = 1UL << 30
staticconstexpr

Definition at line 172 of file radio_lr1121.h.

◆ LR1121_REG_HIGH_ACP_WORKAROUND_VALUE

uint32_t esphome::home_io_control::LR1121_REG_HIGH_ACP_WORKAROUND_VALUE = 0x00000000
staticconstexpr

Definition at line 173 of file radio_lr1121.h.

◆ LR1121_RESPONSE_PREAMBLE

uint16_t esphome::home_io_control::LR1121_RESPONSE_PREAMBLE = SX1262_RESPONSE_PREAMBLE
staticconstexpr

LR1121-specific preamble for response/continuation frames within an exchange.

Seeded from the SX1262-validated default (design doc §3.2: "seed every timing/tuning default from the validated SX1262 values ... they encode protocol-side realities more than chip quirks"). Not yet independently validated on LR1121 hardware — see the implementation plan's Step 7 (loopback tuning), which folds a measured value back here.

Definition at line 139 of file tuning_config.h.

◆ LR1121_RFSWITCH_ENABLE_DIO5_DIO6

uint8_t esphome::home_io_control::LR1121_RFSWITCH_ENABLE_DIO5_DIO6 = 0x03
staticconstexpr

DIO5 + DIO6 are switch pins.

Definition at line 202 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_GNSS

uint8_t esphome::home_io_control::LR1121_RFSWITCH_GNSS = 0x00
staticconstexpr

Unused; both low.

Definition at line 208 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_RX

uint8_t esphome::home_io_control::LR1121_RFSWITCH_RX = 0x01
staticconstexpr

DIO5 high.

Definition at line 204 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_STANDBY

uint8_t esphome::home_io_control::LR1121_RFSWITCH_STANDBY = 0x00
staticconstexpr

Both low.

Definition at line 203 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_TX

uint8_t esphome::home_io_control::LR1121_RFSWITCH_TX = 0x02
staticconstexpr

DIO6 high (both LP and HP PA).

Definition at line 205 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_TX_HF

uint8_t esphome::home_io_control::LR1121_RFSWITCH_TX_HF = 0x00
staticconstexpr

2.4GHz path unused; both low.

Definition at line 207 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_TX_HP

uint8_t esphome::home_io_control::LR1121_RFSWITCH_TX_HP = 0x02
staticconstexpr

Same as TX (LP PA only used today).

Definition at line 206 of file radio_lr1121.h.

◆ LR1121_RFSWITCH_WIFI

uint8_t esphome::home_io_control::LR1121_RFSWITCH_WIFI = 0x00
staticconstexpr

Unused; both low.

Definition at line 209 of file radio_lr1121.h.

◆ LR1121_SYNC_WORD_PARAM_24_BITS

uint8_t esphome::home_io_control::LR1121_SYNC_WORD_PARAM_24_BITS = 0x18
staticconstexpr

Sync word length: 24 bits, encoded as a literal bit count — cross-checked, identical encoding to SX1262's SX1262_SYNC_WORD_PARAM_24_BITS.

Definition at line 149 of file radio_lr1121.h.

◆ LR1121_TCXO_STARTUP_DELAY_TICKS_LSB

uint8_t esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_LSB = 0x40
staticconstexpr

0x140 ticks at 30.52us/tick (32.768kHz RTC) is ~9.8ms, not the ~5ms the SX1262-derived comment used to claim (that chip's tick base differs) — harmless either way (longer startup is safe).

Definition at line 216 of file radio_lr1121.h.

◆ LR1121_TCXO_STARTUP_DELAY_TICKS_MID

uint8_t esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_MID = 0x01
staticconstexpr

Definition at line 213 of file radio_lr1121.h.

◆ LR1121_TCXO_STARTUP_DELAY_TICKS_MSB

uint8_t esphome::home_io_control::LR1121_TCXO_STARTUP_DELAY_TICKS_MSB = 0x00
staticconstexpr

LR1121 TCXO voltage on the T3-S3 board — 3.0V, confirmed on real hardware.

Definition at line 212 of file radio_lr1121.h.

◆ MANUFACTURER_ASSA_ABLOY

uint8_t esphome::home_io_control::MANUFACTURER_ASSA_ABLOY = 5
staticconstexpr

ASSA ABLOY (locks, access).

Definition at line 375 of file proto_constants.h.

◆ MANUFACTURER_ATLANTIC_GROUP

uint8_t esphome::home_io_control::MANUFACTURER_ATLANTIC_GROUP = 12
staticconstexpr

Atlantic Group (heating, hot water).

Definition at line 382 of file proto_constants.h.

◆ MANUFACTURER_CIAT

uint8_t esphome::home_io_control::MANUFACTURER_CIAT = 9
staticconstexpr

CIAT (HVAC).

Definition at line 379 of file proto_constants.h.

◆ MANUFACTURER_HONEYWELL

uint8_t esphome::home_io_control::MANUFACTURER_HONEYWELL = 3
staticconstexpr

Honeywell.

Definition at line 373 of file proto_constants.h.

◆ MANUFACTURER_HORMANN

uint8_t esphome::home_io_control::MANUFACTURER_HORMANN = 4
staticconstexpr

Hörmann (garage doors, gates).

Definition at line 374 of file proto_constants.h.

◆ MANUFACTURER_ID_MAX

uint8_t esphome::home_io_control::MANUFACTURER_ID_MAX = 12
staticconstexpr

Maximum manufacturer ID with a known name in the lookup table.

Definition at line 364 of file proto_constants.h.

◆ MANUFACTURER_NIKO

uint8_t esphome::home_io_control::MANUFACTURER_NIKO = 6
staticconstexpr

Niko (switches, home automation).

Definition at line 376 of file proto_constants.h.

◆ MANUFACTURER_OVERKIZ

uint8_t esphome::home_io_control::MANUFACTURER_OVERKIZ = 11
staticconstexpr

OVERKIZ (Somfy connectivity platform).

Definition at line 381 of file proto_constants.h.

◆ MANUFACTURER_RENSON

uint8_t esphome::home_io_control::MANUFACTURER_RENSON = 8
staticconstexpr

Renson (ventilation, sun protection).

Definition at line 378 of file proto_constants.h.

◆ MANUFACTURER_SECUYOU

uint8_t esphome::home_io_control::MANUFACTURER_SECUYOU = 10
staticconstexpr

Secuyou (security).

Definition at line 380 of file proto_constants.h.

◆ MANUFACTURER_SOMFY

uint8_t esphome::home_io_control::MANUFACTURER_SOMFY = 2
staticconstexpr

Somfy (shutters, awnings, blinds).

Definition at line 372 of file proto_constants.h.

◆ MANUFACTURER_VELUX

uint8_t esphome::home_io_control::MANUFACTURER_VELUX = 1
staticconstexpr

IO-Homecontrol manufacturer ID constants.

These 1-based identifiers are assigned by the IO-Homecontrol alliance and appear in the discovery response payload at DISCOVERY_RESP_MANUFACTURER_OFFSET. VELUX (roof windows, skylights).

Definition at line 371 of file proto_constants.h.

◆ MANUFACTURER_WINDOW_MASTER

uint8_t esphome::home_io_control::MANUFACTURER_WINDOW_MASTER = 7
staticconstexpr

WINDOW MASTER (ventilation).

Definition at line 377 of file proto_constants.h.

◆ MAX_TRACKED_STATUS_POLL_WINDOW_MS

uint32_t esphome::home_io_control::MAX_TRACKED_STATUS_POLL_WINDOW_MS = 600000
staticconstexpr

Hard stop for bounded follow-up polling after a command or remote activity.

Definition at line 37 of file status_poll_policy.h.

◆ MODE_MASK

uint8_t esphome::home_io_control::MODE_MASK = 0x07
staticconstexpr

Definition at line 63 of file radio_sx1276.h.

◆ MODE_RX

uint8_t esphome::home_io_control::MODE_RX = 0x05
staticconstexpr

Definition at line 62 of file radio_sx1276.h.

◆ MODE_SLEEP

uint8_t esphome::home_io_control::MODE_SLEEP = 0x00
staticconstexpr

Definition at line 59 of file radio_sx1276.h.

◆ MODE_STDBY

uint8_t esphome::home_io_control::MODE_STDBY = 0x01
staticconstexpr

Definition at line 60 of file radio_sx1276.h.

◆ MODE_TX

uint8_t esphome::home_io_control::MODE_TX = 0x03
staticconstexpr

Definition at line 61 of file radio_sx1276.h.

◆ NODE_ID_SIZE

uint8_t esphome::home_io_control::NODE_ID_SIZE = 3
staticconstexpr

Device/node addresses are 3 bytes (e.g., "123ABC").

Definition at line 20 of file proto_sizes.h.

◆ NODE_ID_STRING_SIZE

uint8_t esphome::home_io_control::NODE_ID_STRING_SIZE = (NODE_ID_SIZE * 2) + 1
staticconstexpr

Uppercase hex node ID plus null terminator.

Definition at line 21 of file proto_sizes.h.

◆ NUMBER_PARAMS

TuningNumberParam esphome::home_io_control::NUMBER_PARAMS[]
staticconstexpr

Definition at line 23 of file tuning_registry.cpp.

◆ ONEWAY_EXECUTE_MIN_DATA_LEN

uint8_t esphome::home_io_control::ONEWAY_EXECUTE_MIN_DATA_LEN = 4
staticconstexpr

Minimum data bytes for decode of execute/activate‑mode intent fields.

Definition at line 311 of file proto_codecs.cpp.

◆ ONEWAY_INTENT_BUFFER_SIZE

size_t esphome::home_io_control::ONEWAY_INTENT_BUFFER_SIZE = 24
staticconstexpr

Buffer size for the decoded 1W main-intent string.

Definition at line 153 of file proto_codecs.h.

◆ ONEWAY_POLL_DEFER_CAP_MS

uint32_t esphome::home_io_control::ONEWAY_POLL_DEFER_CAP_MS = 5000
staticconstexpr

Hard cap on how long sustained 1W traffic may hold a background poll back in total, measured from the start of the burst rather than the most recent frame.

ONEWAY_QUIET_PERIOD_MS re-arms on every frame, so without this cap traffic arriving faster than the quiet period apart — a stuck remote, a chatty neighbour's sensor — could starve background polls, and therefore device state freshness, indefinitely. Comfortably above a legitimate ~160ms burst; bounds the worst case without meaningfully affecting normal operation.

Definition at line 53 of file status_poll_policy.h.

◆ ONEWAY_QUIET_PERIOD_MS

uint32_t esphome::home_io_control::ONEWAY_QUIET_PERIOD_MS = 700
staticconstexpr

Hold queued background polls back for this long after any 1W frame, so a poll the hub itself scheduled does not occupy the (half-duplex) radio while the remote is still transmitting.

Comfortably longer than the ~160ms reliability burst; short enough to barely shift poll timing otherwise. Only background polls yield — see decisions::defer_background_poll_for_1w_activity().

Definition at line 46 of file status_poll_policy.h.

◆ ORIGINATOR_AUTOMATIC_CYCLE

uint8_t esphome::home_io_control::ORIGINATOR_AUTOMATIC_CYCLE = 0xFE
staticconstexpr

Automatic cycle / external access.

Definition at line 418 of file proto_constants.h.

◆ ORIGINATOR_EMERGENCY

uint8_t esphome::home_io_control::ORIGINATOR_EMERGENCY = 0xFF
staticconstexpr

Emergency command (never disabled).

Definition at line 419 of file proto_constants.h.

◆ ORIGINATOR_ENVIRONMENT

uint8_t esphome::home_io_control::ORIGINATOR_ENVIRONMENT = 0x0D
staticconstexpr

Unspecified environment sensor.

Definition at line 416 of file proto_constants.h.

◆ ORIGINATOR_LIFESTYLE

uint8_t esphome::home_io_control::ORIGINATOR_LIFESTYLE = 0x07
staticconstexpr

Lifestyle scenario controller.

Definition at line 411 of file proto_constants.h.

◆ ORIGINATOR_LOAD_SHEDDING

uint8_t esphome::home_io_control::ORIGINATOR_LOAD_SHEDDING = 0x0B
staticconstexpr

Load-shedding manager.

Definition at line 414 of file proto_constants.h.

◆ ORIGINATOR_LOCAL_LIGHT

uint8_t esphome::home_io_control::ORIGINATOR_LOCAL_LIGHT = 0x0C
staticconstexpr

Local light sensor.

Definition at line 415 of file proto_constants.h.

◆ ORIGINATOR_LOCAL_USER

uint8_t esphome::home_io_control::ORIGINATOR_LOCAL_USER = 0x00
staticconstexpr

Command originator codes indicating what or who triggered a command.

The originator byte is the first byte of the CMD_EXECUTE payload. It tells the actuator (and any eavesdropping controller) who initiated the movement. This is useful for understanding device-initiated status updates. User pressed a button on the actuator.

Definition at line 404 of file proto_constants.h.

◆ ORIGINATOR_MYSELF

uint8_t esphome::home_io_control::ORIGINATOR_MYSELF = 0x10
staticconstexpr

Actuator decided to move by itself.

Definition at line 417 of file proto_constants.h.

◆ ORIGINATOR_RAIN_SENSOR

uint8_t esphome::home_io_control::ORIGINATOR_RAIN_SENSOR = 0x02
staticconstexpr

Rain sensor triggered the movement.

Definition at line 406 of file proto_constants.h.

◆ ORIGINATOR_SAAC

uint8_t esphome::home_io_control::ORIGINATOR_SAAC = 0x08
staticconstexpr

Stand-alone automatic controller (SAAC).

Definition at line 412 of file proto_constants.h.

◆ ORIGINATOR_SECURITY

uint8_t esphome::home_io_control::ORIGINATOR_SECURITY = 0x04
staticconstexpr

Security controlling device (SCD) action.

Definition at line 408 of file proto_constants.h.

◆ ORIGINATOR_SMART_CONTROLLER

uint8_t esphome::home_io_control::ORIGINATOR_SMART_CONTROLLER = 0x06
staticconstexpr

Smart function controller.

Definition at line 410 of file proto_constants.h.

◆ ORIGINATOR_TIMER

uint8_t esphome::home_io_control::ORIGINATOR_TIMER = 0x03
staticconstexpr

Timer or schedule triggered the movement.

Definition at line 407 of file proto_constants.h.

◆ ORIGINATOR_UPS

uint8_t esphome::home_io_control::ORIGINATOR_UPS = 0x05
staticconstexpr

Uninterruptible power supply action.

Definition at line 409 of file proto_constants.h.

◆ ORIGINATOR_USER_REMOTE

uint8_t esphome::home_io_control::ORIGINATOR_USER_REMOTE = 0x01
staticconstexpr

User sent command from a remote control.

Definition at line 405 of file proto_constants.h.

◆ ORIGINATOR_WIND_SENSOR

uint8_t esphome::home_io_control::ORIGINATOR_WIND_SENSOR = 0x09
staticconstexpr

Wind sensor triggered the movement.

Definition at line 413 of file proto_constants.h.

◆ PAIRING_DISCOVERY_INITIAL_DWELL_MS

uint16_t esphome::home_io_control::PAIRING_DISCOVERY_INITIAL_DWELL_MS = 300
staticconstexpr

Dwell on CH2 before discovery hopping begins.

Definition at line 90 of file proto_timing.h.

◆ PAIRING_DISCOVERY_MAX_ATTEMPTS

uint8_t esphome::home_io_control::PAIRING_DISCOVERY_MAX_ATTEMPTS = 3
inlineconstexpr

Retry discovery TX up to this many times.

Definition at line 49 of file pairing_engine.h.

◆ PAIRING_DISCOVERY_RESPONSE_TIMEOUT_MS

uint32_t esphome::home_io_control::PAIRING_DISCOVERY_RESPONSE_TIMEOUT_MS = 2000
inlineconstexpr

Discovery wait window after sending 0x28.

Definition at line 48 of file pairing_engine.h.

◆ PAIRING_DISCOVERY_WAIT_MS

uint16_t esphome::home_io_control::PAIRING_DISCOVERY_WAIT_MS = 2000
staticconstexpr

Canonical defaults for the chip-neutral runtime-tunable pairing/discovery parameters.

These are the single source of truth for the diagnostics tuning layer: TuningConfig initializes its fields from them, and the ESPHome YAML schema falls back to them when a key is omitted. Adjust a value here and both the compiled default and the documented YAML default follow. Chip-specific tuning defaults live in tuning_config.h instead. See Pairing/Radio Diagnostics Tuning. Wait window after sending each discovery command.

Definition at line 89 of file proto_timing.h.

◆ PAIRING_KEY_CHALLENGE_TIMEOUT_MS

uint32_t esphome::home_io_control::PAIRING_KEY_CHALLENGE_TIMEOUT_MS = 500
inlineconstexpr

Wait window for the device's 0x3C challenge.

Definition at line 50 of file pairing_engine.h.

◆ PAIRING_KEY_CONFIRM_SLICE_MS

uint32_t esphome::home_io_control::PAIRING_KEY_CONFIRM_SLICE_MS = 150
inlineconstexpr

RX slice during key confirm wait (hop each slice).

Definition at line 52 of file pairing_engine.h.

◆ PAIRING_KEY_CONFIRM_TIMEOUT_MS

uint32_t esphome::home_io_control::PAIRING_KEY_CONFIRM_TIMEOUT_MS = 500
inlineconstexpr

Wait for 0x33 key confirm after sending 0x32.

Definition at line 51 of file pairing_engine.h.

◆ PAIRING_KEY_EXCHANGE_RETRIES

uint8_t esphome::home_io_control::PAIRING_KEY_EXCHANGE_RETRIES = 3
staticconstexpr

Retries for the authenticated key-exchange phase.

Definition at line 91 of file proto_timing.h.

◆ PAIRING_TELEMETRY_MAX_EVENTS

uint8_t esphome::home_io_control::PAIRING_TELEMETRY_MAX_EVENTS = 32
staticconstexpr

Maximum number of events recorded per pairing attempt.

Events beyond this bound are still counted in PairingTelemetry::heard_count() but not stored — the array is a fixed-size ring-free buffer (first N events), not a true ring.

Definition at line 41 of file pairing_telemetry.h.

◆ POS_DEFAULT

uint8_t esphome::home_io_control::POS_DEFAULT = 0xD3
staticconstexpr

Wire value for the default position command.

Moves the actuator to its factory or user-configured default position.

Definition at line 298 of file proto_constants.h.

◆ POS_FAVORITE

uint8_t esphome::home_io_control::POS_FAVORITE = 0xD8
staticconstexpr

Wire value: move to favorite/"My" position.

Definition at line 286 of file proto_constants.h.

◆ POS_FORCE_OPEN

uint8_t esphome::home_io_control::POS_FORCE_OPEN = 0x64
staticconstexpr

Ambiguous wire value used only for passive 1W-traffic intent decoding (decode_1w_main_intent() / oneway_intent_to_target() in proto_codecs.cpp).

0x64 (100) is simultaneously the ordinary doubled-position wire value for 50% and a value some physical 1W remotes send for their "force open" button — the protocol has no dedicated override code, so the two are indistinguishable on the wire. For passively decoding someone else's remote traffic, "FORCE_OPEN" is the more useful diagnostic label (physical remotes rarely send a numeric 50%). This is NOT used by any outbound builder in this codebase: real-hardware testing confirmed that sending main=0x64 as an outbound 2W CMD_EXECUTE command makes a real device move to 50% open, not bypass anything — see create_force_open() in proto_commands.cpp for the actual (ACEI-priority-based) force-open implementation.

Definition at line 312 of file proto_constants.h.

◆ POS_SECURED_TARGET

uint8_t esphome::home_io_control::POS_SECURED_TARGET = 0xD1
staticconstexpr

Wire value for the secured target position command.

Moves the actuator to its pre-programmed secured/safety position from the Execution Parameter Buffer. Typically sent by environmental sensors (wind, rain) to retract an awning or close a shutter to a wind-safe state.

Definition at line 293 of file proto_constants.h.

◆ POS_STOP

uint8_t esphome::home_io_control::POS_STOP = 0xD2
staticconstexpr

Position values in the IO protocol.

Normal positions are 0-100 (0=fully open, 100=fully closed). Special values above 100 are control commands encoded as the "main" parameter byte in CMD_EXECUTE payloads. These are internal wire constants — callers should prefer CoverCommand for type-safe command dispatch. Wire value: stop movement.

Definition at line 284 of file proto_constants.h.

◆ POS_UNKNOWN

uint8_t esphome::home_io_control::POS_UNKNOWN = 0xD4
staticconstexpr

Wire value: position unknown / keep current.

Definition at line 285 of file proto_constants.h.

◆ POS_VENT_MODIFIER

uint8_t esphome::home_io_control::POS_VENT_MODIFIER = 0x03
staticconstexpr

Modifier byte for the ventilation command.

Both favorite and ventilation use POS_FAVORITE (0xD8) as the main parameter byte, but ventilation sets the secondary byte (main[1]) to 0x03 while favorite leaves it 0x00.

Definition at line 318 of file proto_constants.h.

◆ POSITION_TEXT_BUFFER_SIZE

size_t esphome::home_io_control::POSITION_TEXT_BUFFER_SIZE = 16
inlineconstexpr

Buffer for formatted position strings such as "100%".

Definition at line 58 of file hub_core.h.

◆ POWER_SAVE_ALWAYS_ALIVE

uint8_t esphome::home_io_control::POWER_SAVE_ALWAYS_ALIVE = 0
staticconstexpr

Power save mode values from the Multi Information Byte.

Extracted from flags & DISCOVERY_FLAGS_POWER_SAVE_MASK. Devices in low-power mode require long preamble (1024 bytes) to wake their receiver. Device is always listening — short preamble works.

Definition at line 520 of file proto_constants.h.

◆ POWER_SAVE_LOW_POWER

uint8_t esphome::home_io_control::POWER_SAVE_LOW_POWER = 1
staticconstexpr

Device sleeps — needs long preamble to wake.

Definition at line 521 of file proto_constants.h.

◆ RADIO_PACKET_BUFFER_SIZE

uint8_t esphome::home_io_control::RADIO_PACKET_BUFFER_SIZE
inlineconstexpr
Initial value:
=
64

Scratch buffer size for raw radio packets and recovered frames.

Definition at line 22 of file radio_interface.h.

◆ REG_AFC_BW

uint8_t esphome::home_io_control::REG_AFC_BW = 0x13
staticconstexpr

AFC bandwidth.

Definition at line 37 of file radio_sx1276.h.

◆ REG_AFC_FEI

uint8_t esphome::home_io_control::REG_AFC_FEI = 0x1A
staticconstexpr

AFC auto clear.

Definition at line 38 of file radio_sx1276.h.

◆ REG_BITRATE_LSB

uint8_t esphome::home_io_control::REG_BITRATE_LSB = 0x03
staticconstexpr

Definition at line 25 of file radio_sx1276.h.

◆ REG_BITRATE_MSB

uint8_t esphome::home_io_control::REG_BITRATE_MSB = 0x02
staticconstexpr

Bit rate MSB = FXOSC / bitrate.

Definition at line 24 of file radio_sx1276.h.

◆ REG_DIO_MAPPING1

uint8_t esphome::home_io_control::REG_DIO_MAPPING1 = 0x40
staticconstexpr

DIO0-DIO3 pin mapping.

Definition at line 52 of file radio_sx1276.h.

◆ REG_DIO_MAPPING2

uint8_t esphome::home_io_control::REG_DIO_MAPPING2 = 0x41
staticconstexpr

DIO4-DIO5 pin mapping.

Definition at line 53 of file radio_sx1276.h.

◆ REG_FDEV_LSB

uint8_t esphome::home_io_control::REG_FDEV_LSB = 0x05
staticconstexpr

Definition at line 27 of file radio_sx1276.h.

◆ REG_FDEV_MSB

uint8_t esphome::home_io_control::REG_FDEV_MSB = 0x04
staticconstexpr

Frequency deviation MSB.

Definition at line 26 of file radio_sx1276.h.

◆ REG_FIFO

uint8_t esphome::home_io_control::REG_FIFO = 0x00
staticconstexpr

FIFO read/write access.

Definition at line 22 of file radio_sx1276.h.

◆ REG_FIFO_THRESH

uint8_t esphome::home_io_control::REG_FIFO_THRESH = 0x35
staticconstexpr

FIFO threshold for TX start condition.

Definition at line 49 of file radio_sx1276.h.

◆ REG_FRF_LSB

uint8_t esphome::home_io_control::REG_FRF_LSB = 0x08
staticconstexpr

Definition at line 30 of file radio_sx1276.h.

◆ REG_FRF_MID

uint8_t esphome::home_io_control::REG_FRF_MID = 0x07
staticconstexpr

Definition at line 29 of file radio_sx1276.h.

◆ REG_FRF_MSB

uint8_t esphome::home_io_control::REG_FRF_MSB = 0x06
staticconstexpr

Carrier frequency MSB (freq = FRF * FXOSC / 2^19).

Definition at line 28 of file radio_sx1276.h.

◆ REG_IMAGE_CAL

uint8_t esphome::home_io_control::REG_IMAGE_CAL = 0x3B
staticconstexpr

Image calibration.

Definition at line 56 of file radio_sx1276.h.

◆ REG_IRQ_FLAGS1

uint8_t esphome::home_io_control::REG_IRQ_FLAGS1 = 0x3E
staticconstexpr

IRQ flags: mode ready, preamble detect, etc.

Definition at line 50 of file radio_sx1276.h.

◆ REG_IRQ_FLAGS2

uint8_t esphome::home_io_control::REG_IRQ_FLAGS2 = 0x3F
staticconstexpr

IRQ flags: FIFO full/empty, payload ready, CRC ok.

Definition at line 51 of file radio_sx1276.h.

◆ REG_LNA

uint8_t esphome::home_io_control::REG_LNA = 0x0C
staticconstexpr

Low noise amplifier gain and boost.

Definition at line 33 of file radio_sx1276.h.

◆ REG_OP_MODE

uint8_t esphome::home_io_control::REG_OP_MODE = 0x01
staticconstexpr

Operating mode (sleep/standby/tx/rx).

Definition at line 23 of file radio_sx1276.h.

◆ REG_OSC

uint8_t esphome::home_io_control::REG_OSC = 0x24
staticconstexpr

Oscillator / clock output.

Definition at line 40 of file radio_sx1276.h.

◆ REG_PA_CONFIG

uint8_t esphome::home_io_control::REG_PA_CONFIG = 0x09
staticconstexpr

Power amplifier config (pin select + power level).

Definition at line 31 of file radio_sx1276.h.

◆ REG_PA_RAMP

uint8_t esphome::home_io_control::REG_PA_RAMP = 0x0A
staticconstexpr

PA ramp time and modulation shaping.

Definition at line 32 of file radio_sx1276.h.

◆ REG_PACKET_CONFIG1

uint8_t esphome::home_io_control::REG_PACKET_CONFIG1 = 0x30
staticconstexpr

Packet format, CRC, encoding.

Definition at line 46 of file radio_sx1276.h.

◆ REG_PACKET_CONFIG2

uint8_t esphome::home_io_control::REG_PACKET_CONFIG2 = 0x31
staticconstexpr

Packet mode, IoHomeOn, PowerFrame.

Definition at line 47 of file radio_sx1276.h.

◆ REG_PAYLOAD_LENGTH

uint8_t esphome::home_io_control::REG_PAYLOAD_LENGTH = 0x32
staticconstexpr

Max payload length.

Definition at line 48 of file radio_sx1276.h.

◆ REG_PLLHOP

uint8_t esphome::home_io_control::REG_PLLHOP = 0x44
staticconstexpr

PLL hop: fast frequency change without standby.

Definition at line 55 of file radio_sx1276.h.

◆ REG_PREAMBLE_DETECT

uint8_t esphome::home_io_control::REG_PREAMBLE_DETECT = 0x1F
staticconstexpr

Preamble detector config.

Definition at line 39 of file radio_sx1276.h.

◆ REG_PREAMBLE_LSB

uint8_t esphome::home_io_control::REG_PREAMBLE_LSB = 0x26
staticconstexpr

Definition at line 43 of file radio_sx1276.h.

◆ REG_PREAMBLE_MSB

uint8_t esphome::home_io_control::REG_PREAMBLE_MSB = 0x25
staticconstexpr

TX preamble length MSB.

Definition at line 42 of file radio_sx1276.h.

◆ REG_RSSI_CONFIG

uint8_t esphome::home_io_control::REG_RSSI_CONFIG = 0x0E
staticconstexpr

RSSI smoothing.

Definition at line 35 of file radio_sx1276.h.

◆ REG_RSSI_VALUE

uint8_t esphome::home_io_control::REG_RSSI_VALUE = 0x11
staticconstexpr

Instant RSSI value in FSK mode.

Definition at line 41 of file radio_sx1276.h.

◆ REG_RX_BW

uint8_t esphome::home_io_control::REG_RX_BW = 0x12
staticconstexpr

Receiver bandwidth.

Definition at line 36 of file radio_sx1276.h.

◆ REG_RX_CONFIG

uint8_t esphome::home_io_control::REG_RX_CONFIG = 0x0D
staticconstexpr

Receiver configuration (AFC, AGC, trigger).

Definition at line 34 of file radio_sx1276.h.

◆ REG_SYNC_CONFIG

uint8_t esphome::home_io_control::REG_SYNC_CONFIG = 0x27
staticconstexpr

Sync word config (size, polarity, enable).

Definition at line 44 of file radio_sx1276.h.

◆ REG_SYNC_VALUE1

uint8_t esphome::home_io_control::REG_SYNC_VALUE1 = 0x28
staticconstexpr

Sync word byte 1 (registers 0x28-0x2F for bytes 1-8).

Definition at line 45 of file radio_sx1276.h.

◆ REG_VERSION

uint8_t esphome::home_io_control::REG_VERSION = 0x42
staticconstexpr

Chip version (should read 0x12 for SX1276).

Definition at line 54 of file radio_sx1276.h.

◆ REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS

uint32_t esphome::home_io_control::REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS = 2000
staticconstexpr

Delay before polling after overheard remote traffic.

Definition at line 41 of file status_poll_policy.h.

◆ RESPONSE_AUTH_WAIT_MS

int32_t esphome::home_io_control::RESPONSE_AUTH_WAIT_MS
staticconstexpr
Initial value:
=
static constexpr int32_t RESPONSE_WAIT_MS
Wait for response to non-start frame.

Wait for final response after challenge response.

Definition at line 69 of file proto_timing.h.

◆ RESPONSE_CHANNEL_WAIT_MS

int32_t esphome::home_io_control::RESPONSE_CHANNEL_WAIT_MS = 50
staticconstexpr

Per-channel dwell while waiting for an exchange response.

Definition at line 40 of file proto_timing.h.

◆ RESPONSE_START_WAIT_MS

int32_t esphome::home_io_control::RESPONSE_START_WAIT_MS = 1000
staticconstexpr

Wait for a response to a start frame — the first frame of an exchange, and the one a sleeping device has just been woken by.

This was 300 ms, shorter than the non-start budget above despite its own comment promising "longer". That inversion is backwards for the case it covers: a start frame is preceded by a 1024-byte (213 ms) wake-up preamble precisely because the target may have been asleep, and a device that has just woken is the slowest it will ever be to answer.

Field captures of a Somfy RS100 solar actuator (2026-08-14, third-party listener, three controllers on one network) measured its request→reply latency at 29 ms, 781 ms, 1548 ms, 1945 ms, 2469 ms and 3052 ms — the same device, minutes apart. A Somfy Oximo 40 on the same network answered in ~23 ms every time, day or night, and is also solar: reply latency is a per-model behaviour, not something the power source predicts, so there is no device class this budget can safely be tuned for. Against a 300 ms budget the RS100 was reachable only in its fastest state, which is why it answered intermittently and grew worse as the day went on. tests/corpus/captures/issues/field_rs100_pairing_key_transfer_timeout.yaml shows the same device class at 1020 ms and 1639 ms, and LR1121_EXCHANGE_RESPONSE_WAIT_SLICE_MS documents a Somfy awning replying at 287 ms against the old 300 ms budget — margin that thin was already known to be a problem on a fast device.

1000 ms restores the documented intent and covers the bulk of the observed spread without unbounded loop blocking (see ADR 0013 — the exchange blocks the ESPHome loop, and a failed exchange costs EXCHANGE_RETRY_COUNT of these). Devices slower still are reachable by raising exchange_start_response_wait_ms from YAML rather than by rebuilding.

Definition at line 67 of file proto_timing.h.

◆ RESPONSE_WAIT_MS

int32_t esphome::home_io_control::RESPONSE_WAIT_MS = 500
staticconstexpr

Wait for response to non-start frame.

Definition at line 41 of file proto_timing.h.

◆ RESULT_AUTOMATIC_CYCLE_ENGAGED

uint8_t esphome::home_io_control::RESULT_AUTOMATIC_CYCLE_ENGAGED = 0x18
staticconstexpr

Node entered automatic cycle mode.

Definition at line 246 of file proto_constants.h.

◆ RESULT_BAD_INDEX_RECEIVED

uint8_t esphome::home_io_control::RESULT_BAD_INDEX_RECEIVED = 0x1C
staticconstexpr

Invalid index received.

Definition at line 250 of file proto_constants.h.

◆ RESULT_BATTERY_LEVEL

uint8_t esphome::home_io_control::RESULT_BATTERY_LEVEL = 0x12
staticconstexpr

Battery level is low.

Definition at line 240 of file proto_constants.h.

◆ RESULT_BLOCKED

uint8_t esphome::home_io_control::RESULT_BLOCKED = 0x04
staticconstexpr

Node blocked by an object.

Definition at line 226 of file proto_constants.h.

◆ RESULT_CALIBRATING

uint8_t esphome::home_io_control::RESULT_CALIBRATING = 0x0A
staticconstexpr

Node is calibrating.

Definition at line 232 of file proto_constants.h.

◆ RESULT_COLOUR_NOT_REACHABLE

uint8_t esphome::home_io_control::RESULT_COLOUR_NOT_REACHABLE = 0x1A
staticconstexpr

Requested colour not reachable.

Definition at line 248 of file proto_constants.h.

◆ RESULT_COMMAND_COMPLETED_OK

uint8_t esphome::home_io_control::RESULT_COMMAND_COMPLETED_OK = 0x01
staticconstexpr

No errors detected.

Definition at line 223 of file proto_constants.h.

◆ RESULT_COMMAND_INCOMPATIBLE_TO_MOVEMENT

uint8_t esphome::home_io_control::RESULT_COMMAND_INCOMPATIBLE_TO_MOVEMENT = 0x15
staticconstexpr

Command cannot move the node that way.

Definition at line 243 of file proto_constants.h.

◆ RESULT_COMMAND_OVERRULED

uint8_t esphome::home_io_control::RESULT_COMMAND_OVERRULED = 0x1D
staticconstexpr

Command was overruled by a newer command.

Definition at line 251 of file proto_constants.h.

◆ RESULT_DEAD_BOLT_ERROR

uint8_t esphome::home_io_control::RESULT_DEAD_BOLT_ERROR = 0x17
staticconstexpr

Dead bolt error.

Definition at line 245 of file proto_constants.h.

◆ RESULT_ERROR_DURING_EXECUTION

uint8_t esphome::home_io_control::RESULT_ERROR_DURING_EXECUTION = 0x08
staticconstexpr

Generic execution failure.

Definition at line 230 of file proto_constants.h.

◆ RESULT_FILTER_MAINTENANCE_NEEDED

uint8_t esphome::home_io_control::RESULT_FILTER_MAINTENANCE_NEEDED = 0x11
staticconstexpr

Filter needs maintenance.

Definition at line 239 of file proto_constants.h.

◆ RESULT_INFORMATION_CODE

uint8_t esphome::home_io_control::RESULT_INFORMATION_CODE = 0xDF
staticconstexpr

Information-only code with unknown semantics.

Definition at line 260 of file proto_constants.h.

◆ RESULT_IP_NOT_SET

uint8_t esphome::home_io_control::RESULT_IP_NOT_SET = 0x23
staticconstexpr

Intermediate position is not set.

Definition at line 256 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_AUTOMATIC_CYCLE

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_AUTOMATIC_CYCLE = 0xED
staticconstexpr

Parameter limited by an automatic cycle.

Definition at line 272 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_EMERGENCY

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_EMERGENCY = 0xEE
staticconstexpr

Parameter limited by an emergency.

Definition at line 273 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_LOCAL_USER

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_LOCAL_USER = 0xE1
staticconstexpr

Parameter limited by local button.

Definition at line 262 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_MYSELF

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_MYSELF = 0xEC
staticconstexpr

Parameter limited by the node itself.

Definition at line 271 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_RAIN

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_RAIN = 0xE3
staticconstexpr

Parameter limited by a rain sensor.

Definition at line 264 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_SAAC

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_SAAC = 0xEA
staticconstexpr

Parameter limited by a standalone automatic controller.

Definition at line 269 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_SCD

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_SCD = 0xE5
staticconstexpr

Parameter limited by a security actuator.

Definition at line 266 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_TIMER

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_TIMER = 0xE4
staticconstexpr

Parameter limited by a timer.

Definition at line 265 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_UNKNOWN_DEVICE

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_UNKNOWN_DEVICE = 0xE7
staticconstexpr

Parameter limited by an unknown device.

Definition at line 268 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_UPS

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_UPS = 0xE6
staticconstexpr

Parameter limited by a power supply.

Definition at line 267 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_USER

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_USER = 0xE2
staticconstexpr

Parameter limited by a remote control.

Definition at line 263 of file proto_constants.h.

◆ RESULT_LIMITATION_BY_WIND

uint8_t esphome::home_io_control::RESULT_LIMITATION_BY_WIND = 0xEB
staticconstexpr

Parameter limited by a wind sensor.

Definition at line 270 of file proto_constants.h.

◆ RESULT_LIMITS_NOT_SET

uint8_t esphome::home_io_control::RESULT_LIMITS_NOT_SET = 0x22
staticconstexpr

Device limits are not set.

Definition at line 255 of file proto_constants.h.

◆ RESULT_LOCK_POSITION_OPEN

uint8_t esphome::home_io_control::RESULT_LOCK_POSITION_OPEN = 0x0D
staticconstexpr

Lock command failed because the door is open.

Definition at line 235 of file proto_constants.h.

◆ RESULT_MANUALLY_OPERATED

uint8_t esphome::home_io_control::RESULT_MANUALLY_OPERATED = 0x03
staticconstexpr

Manually operated by a user.

Definition at line 225 of file proto_constants.h.

◆ RESULT_MODE_NOT_IMPLEMENTED

uint8_t esphome::home_io_control::RESULT_MODE_NOT_IMPLEMENTED = 0x14
staticconstexpr

Mode is not supported by the node.

Definition at line 242 of file proto_constants.h.

◆ RESULT_MOTION_TIME_TOO_LONG

uint8_t esphome::home_io_control::RESULT_MOTION_TIME_TOO_LONG = 0x0E
staticconstexpr

Target was not reached in time.

Definition at line 236 of file proto_constants.h.

◆ RESULT_NO_CONTACT

uint8_t esphome::home_io_control::RESULT_NO_CONTACT = 0x02
staticconstexpr

No communication to node.

Definition at line 224 of file proto_constants.h.

◆ RESULT_NO_EXECUTION

uint8_t esphome::home_io_control::RESULT_NO_EXECUTION = 0x09
staticconstexpr

Node did not move.

Definition at line 231 of file proto_constants.h.

◆ RESULT_NODE_LOCKED

uint8_t esphome::home_io_control::RESULT_NODE_LOCKED = 0x20
staticconstexpr

Node is locked.

Definition at line 253 of file proto_constants.h.

◆ RESULT_NODE_WAITING_FOR_POWER

uint8_t esphome::home_io_control::RESULT_NODE_WAITING_FOR_POWER = 0x1E
staticconstexpr

Node is waiting for power.

Definition at line 252 of file proto_constants.h.

◆ RESULT_OUT_OF_RANGE

uint8_t esphome::home_io_control::RESULT_OUT_OF_RANGE = 0x24
staticconstexpr

Requested value is out of range.

Definition at line 257 of file proto_constants.h.

◆ RESULT_PARAMETER_LIMITED

uint8_t esphome::home_io_control::RESULT_PARAMETER_LIMITED = 0xE0
staticconstexpr

Parameter limited by an unknown device.

Definition at line 261 of file proto_constants.h.

◆ RESULT_POWER_CONSUMPTION_TOO_HIGH

uint8_t esphome::home_io_control::RESULT_POWER_CONSUMPTION_TOO_HIGH = 0x0B
staticconstexpr

Node power consumption is too high.

Definition at line 233 of file proto_constants.h.

◆ RESULT_POWER_CONSUMPTION_TOO_LOW

uint8_t esphome::home_io_control::RESULT_POWER_CONSUMPTION_TOO_LOW = 0x0C
staticconstexpr

Node power consumption is too low.

Definition at line 234 of file proto_constants.h.

◆ RESULT_PRIORITY_LEVEL_LOCKED

uint8_t esphome::home_io_control::RESULT_PRIORITY_LEVEL_LOCKED = 0x06
staticconstexpr

Node is locked on this priority level.

Definition at line 228 of file proto_constants.h.

◆ RESULT_PRIORITY_LOCKED_NON_EXEC

uint8_t esphome::home_io_control::RESULT_PRIORITY_LOCKED_NON_EXEC
staticconstexpr
Initial value:
=
0x38

Priority locked, command not executed (ACEI priority too low).

Definition at line 258 of file proto_constants.h.

◆ RESULT_PRODUCT_NOT_OPERATIONAL

uint8_t esphome::home_io_control::RESULT_PRODUCT_NOT_OPERATIONAL = 0x10
staticconstexpr

Node is not currently operational.

Definition at line 238 of file proto_constants.h.

◆ RESULT_REACHED_WRONG_POSITION

uint8_t esphome::home_io_control::RESULT_REACHED_WRONG_POSITION = 0x07
staticconstexpr

Node stopped in another position than expected.

Definition at line 229 of file proto_constants.h.

◆ RESULT_TARGET_MODIFIED

uint8_t esphome::home_io_control::RESULT_TARGET_MODIFIED = 0x13
staticconstexpr

Node modified the requested target value.

Definition at line 241 of file proto_constants.h.

◆ RESULT_TARGET_NOT_REACHABLE

uint8_t esphome::home_io_control::RESULT_TARGET_NOT_REACHABLE = 0x1B
staticconstexpr

Requested target not reachable.

Definition at line 249 of file proto_constants.h.

◆ RESULT_THERMAL_PROTECTION

uint8_t esphome::home_io_control::RESULT_THERMAL_PROTECTION = 0x0F
staticconstexpr

Node entered thermal protection mode.

Definition at line 237 of file proto_constants.h.

◆ RESULT_UNKNOWN_STATUS_REPLY

uint8_t esphome::home_io_control::RESULT_UNKNOWN_STATUS_REPLY = 0x00
staticconstexpr

Device returned an unknown status reply.

Definition at line 222 of file proto_constants.h.

◆ RESULT_USER_ACTION

uint8_t esphome::home_io_control::RESULT_USER_ACTION = 0x16
staticconstexpr

User action overrode the command.

Definition at line 244 of file proto_constants.h.

◆ RESULT_WRONG_LOAD_CONNECTED

uint8_t esphome::home_io_control::RESULT_WRONG_LOAD_CONNECTED = 0x19
staticconstexpr

Wrong load connected to node.

Definition at line 247 of file proto_constants.h.

◆ RESULT_WRONG_POSITION

uint8_t esphome::home_io_control::RESULT_WRONG_POSITION = 0x21
staticconstexpr

Node reports wrong position.

Definition at line 254 of file proto_constants.h.

◆ RESULT_WRONG_SYSTEMKEY

uint8_t esphome::home_io_control::RESULT_WRONG_SYSTEMKEY = 0x05
staticconstexpr

Node contains the wrong system key.

Definition at line 227 of file proto_constants.h.

◆ RSSI_EMA_SCALE

int16_t esphome::home_io_control::RSSI_EMA_SCALE = 8
staticconstexpr

EMA weight denominator and fixed-point scale for IoDevice::rssi_ema_scaled.

One constant serves both roles by construction: the update S += x − round(S/N) blends each new sample x in at weight 1/N while keeping S = N × EMA.

Definition at line 238 of file proto_device_model.h.

◆ RSSI_UNKNOWN_DBM

int16_t esphome::home_io_control::RSSI_UNKNOWN_DBM = INT16_MIN
staticconstexpr

Sentinel value meaning "no RSSI sample recorded yet" for last_rssi_dbm/rssi_ema_scaled.

A real RSSI reading from these radios is always well above INT16_MIN — and so is any real rssi_ema_scaled fixed-point value.

Definition at line 233 of file proto_device_model.h.

◆ SELECT_PARAMS

TuningSelectParam esphome::home_io_control::SELECT_PARAMS[]
staticconstexpr

Definition at line 67 of file tuning_registry.cpp.

◆ SHORT_PREAMBLE

uint16_t esphome::home_io_control::SHORT_PREAMBLE = 8
staticconstexpr

8 bytes for response/continuation frames

Definition at line 31 of file proto_timing.h.

◆ SOFT_PHY_ALL_IRQ_BITS

uint32_t esphome::home_io_control::SOFT_PHY_ALL_IRQ_BITS = 0xFFFFFFFF
staticconstexpr

Sentinel meaning "every IRQ bit counts as activity" — the default for SoftPhyDriverBase::activity_irq_mask, correct for chips (SX1262) whose hardware-level IRQ mask already excludes the one bit (PreambleDetected) that would need special handling.

Definition at line 44 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_EARLY_HEADER_RAW_BYTES

uint8_t esphome::home_io_control::SOFT_PHY_EARLY_HEADER_RAW_BYTES = 3
staticconstexpr

Raw bytes read in the first stage of a length-driven receive — enough to hold CTRL0's UART cell (10 bits) at any of the probe's bit alignments (up to 9 bits of slack).

Definition at line 48 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_EARLY_MIN_WINDOW_MS

uint32_t esphome::home_io_control::SOFT_PHY_EARLY_MIN_WINDOW_MS = 12
staticconstexpr

Smallest receive window a length-driven receive will be attempted in, in milliseconds.

The longest possible frame (FRAME_MAX_SIZE + CRC, UART-packed) occupies ~9.4 ms of air time, so a caller with less than this left cannot finish one either way. Declining up front keeps the early path from spending a short window's whole budget on a receive it cannot complete.

Definition at line 65 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_EARLY_POLL_US

uint32_t esphome::home_io_control::SOFT_PHY_EARLY_POLL_US = 100
staticconstexpr

Poll interval while waiting out a frame's remaining air time, in microseconds.

Definition at line 58 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_EARLY_READ_MARGIN_BYTES

uint8_t esphome::home_io_control::SOFT_PHY_EARLY_READ_MARGIN_BYTES = 2
staticconstexpr

Air-time margin added before every mid-reception buffer read, in raw bytes.

Covers the lag between a byte finishing on air and the chip having it in its data buffer, plus the granularity of the polled sync-word observation. Two byte-times is generous at this line rate and still leaves a length-driven receive far ahead of the fixed-length RX_DONE.

Definition at line 55 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_LINE_RATE_BPS

uint32_t esphome::home_io_control::SOFT_PHY_LINE_RATE_BPS = 38400
staticconstexpr

Protocol line rate. The same 38400 bps every driver programs into its own bitrate register.

Definition at line 68 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_RX_PROBE_PACKET_LEN

uint8_t esphome::home_io_control::SOFT_PHY_RX_PROBE_PACKET_LEN = 48
staticconstexpr

Fixed raw-RX probe length: chosen from captures of 23-25 byte protocol frames after UART packing and CRC appending — the longest frame (25 bytes + 2 CRC) UART-packs to 34 raw bytes, so 48 bytes preserves complete traffic (with margin for leading noise before the frame start) without relying on either chip's variable-length engine.

This is a protocol-frame-size property, not a chip quirk, so both drivers share one value — used here for the raw-probe threshold in SoftPhyDriverBase::read_rx_packet and by each driver's own set_rx_packet_params() for the configured RX payload length.

Definition at line 39 of file radio_soft_phy_driver_base.h.

◆ SOFT_PHY_US_PER_SECOND

uint32_t esphome::home_io_control::SOFT_PHY_US_PER_SECOND = 1000000
staticconstexpr

Microseconds in a second, for the air-time arithmetic below.

Definition at line 70 of file radio_soft_phy_driver_base.h.

◆ STATUS_AUTH_RETRY_AFTER_FAIL_MAX_MS

uint32_t esphome::home_io_control::STATUS_AUTH_RETRY_AFTER_FAIL_MAX_MS = 300000
staticconstexpr

Steady-state after repeated auth failures.

Definition at line 33 of file status_poll_policy.h.

◆ STATUS_AUTH_RETRY_AFTER_FAIL_MS

uint32_t esphome::home_io_control::STATUS_AUTH_RETRY_AFTER_FAIL_MS = 30000
staticconstexpr

First retry after a challenge-seen failure.

Definition at line 31 of file status_poll_policy.h.

◆ STATUS_AUTH_RETRY_AFTER_FAIL_STEP2_MS

uint32_t esphome::home_io_control::STATUS_AUTH_RETRY_AFTER_FAIL_STEP2_MS = 120000
staticconstexpr

Second retry.

Definition at line 32 of file status_poll_policy.h.

◆ STATUS_EXPECTED

uint8_t esphome::home_io_control::STATUS_EXPECTED = 0x80
staticconstexpr

Byte 1 bit 7: device will send auto status update.

Definition at line 322 of file proto_constants.h.

◆ STATUS_POS_MAX

uint16_t esphome::home_io_control::STATUS_POS_MAX = 0xC800
staticconstexpr

In status responses, position is encoded as a 16-bit value where 0x0000 = fully open (0%) and 0xC800 = fully closed (100%).

Definition at line 208 of file proto_device_model.h.

◆ STATUS_POS_TOLERANCE_RAW

uint16_t esphome::home_io_control::STATUS_POS_TOLERANCE_RAW = 100
staticconstexpr

Target-reached tolerance expressed in raw IO-homecontrol position units.

100 raw units out of 51200 full-scale is about 0.195%, so this only absorbs tiny target/current mismatches from device rounding or early stopped flags.

Definition at line 212 of file proto_device_model.h.

◆ STATUS_RETRY_AFTER_FAIL_MAX_MS

uint32_t esphome::home_io_control::STATUS_RETRY_AFTER_FAIL_MAX_MS
staticconstexpr
Initial value:
=
300000

Steady-state backoff after many silent failures.

Definition at line 25 of file status_poll_policy.h.

◆ STATUS_RETRY_AFTER_FAIL_MS

uint32_t esphome::home_io_control::STATUS_RETRY_AFTER_FAIL_MS = 5000
staticconstexpr

First retry after a silent failure.

Definition at line 21 of file status_poll_policy.h.

◆ STATUS_RETRY_AFTER_FAIL_STEP2_MS

uint32_t esphome::home_io_control::STATUS_RETRY_AFTER_FAIL_STEP2_MS = 15000
staticconstexpr

Second retry after a silent failure.

Definition at line 22 of file status_poll_policy.h.

◆ STATUS_RETRY_AFTER_FAIL_STEP3_MS

uint32_t esphome::home_io_control::STATUS_RETRY_AFTER_FAIL_STEP3_MS = 30000
staticconstexpr

Third retry after a silent failure.

Definition at line 23 of file status_poll_policy.h.

◆ STATUS_RETRY_AFTER_FAIL_STEP4_MS

uint32_t esphome::home_io_control::STATUS_RETRY_AFTER_FAIL_STEP4_MS = 60000
staticconstexpr

Fourth retry after a silent failure.

Definition at line 24 of file status_poll_policy.h.

◆ STATUS_STOPPED

uint8_t esphome::home_io_control::STATUS_STOPPED = 0x01
staticconstexpr

Status byte flags in CMD_PRIVATE_RESP and CMD_STATUS_UPDATE.

Byte 0 bit 0: device is not moving

Definition at line 321 of file proto_constants.h.

◆ STATUS_TILT_SELECTOR

uint8_t esphome::home_io_control::STATUS_TILT_SELECTOR = 0x20
staticconstexpr

Extended status payload marker for tilt-capable devices.

Definition at line 323 of file proto_constants.h.

◆ STOP_SETTLE_POLL_CAP_MS

uint32_t esphome::home_io_control::STOP_SETTLE_POLL_CAP_MS = 1000
staticconstexpr

Upper bound on the settle-poll delay after a STOP command.

STOP should confirm the resting position quickly, so it always settles faster than a normal move, regardless of the configured interval or device hint.

Definition at line 62 of file status_poll_policy.h.

◆ SX1262_CALIBRATE

uint8_t esphome::home_io_control::SX1262_CALIBRATE = 0x89
staticconstexpr

Definition at line 48 of file radio_sx1262.h.

◆ SX1262_CALIBRATE_IMAGE

uint8_t esphome::home_io_control::SX1262_CALIBRATE_IMAGE = 0x98
staticconstexpr

Definition at line 49 of file radio_sx1262.h.

◆ SX1262_CLEAR_DEVICE_ERRORS

uint8_t esphome::home_io_control::SX1262_CLEAR_DEVICE_ERRORS = 0x07
staticconstexpr

Definition at line 39 of file radio_sx1262.h.

◆ SX1262_CLEAR_IRQ_STATUS

uint8_t esphome::home_io_control::SX1262_CLEAR_IRQ_STATUS = 0x02
staticconstexpr

Definition at line 38 of file radio_sx1262.h.

◆ SX1262_DISCOVERY_HOP_SLICE_MS

uint16_t esphome::home_io_control::SX1262_DISCOVERY_HOP_SLICE_MS = 200
staticconstexpr

Per-channel dwell while SX1262 pairing discovery hops across channels.

SX1262 frequency changes require a standby→SetRfFrequency→RX cycle, so the dwell must be much longer than on the SX1276 for short-preamble responses on alternate channels to be caught reliably.

Definition at line 131 of file tuning_config.h.

◆ SX1262_EXCHANGE_RESPONSE_WAIT_SLICE_MS

int32_t esphome::home_io_control::SX1262_EXCHANGE_RESPONSE_WAIT_SLICE_MS = 90
staticconstexpr

SX1262-specific per-channel dwell while waiting for authenticated exchange responses.

A 50 ms dwell was short enough that the controller could hop away from the request channel just before the device emitted its post-auth reply. Using 90 ms keeps the SX1262 receiver on that channel long enough for the observed device turn-around after 0x3D, without inflating the overall 300/500 ms exchange windows for the rest of the protocol.

Definition at line 101 of file radio_sx1262.h.

◆ SX1262_FALLBACK_STDBY_XOSC

uint8_t esphome::home_io_control::SX1262_FALLBACK_STDBY_XOSC = 0x30
staticconstexpr

Definition at line 93 of file radio_sx1262.h.

◆ SX1262_GET_DEVICE_ERRORS

uint8_t esphome::home_io_control::SX1262_GET_DEVICE_ERRORS = 0x17
staticconstexpr

Definition at line 37 of file radio_sx1262.h.

◆ SX1262_GET_IRQ_STATUS

uint8_t esphome::home_io_control::SX1262_GET_IRQ_STATUS = 0x12
staticconstexpr

Definition at line 35 of file radio_sx1262.h.

◆ SX1262_GET_PACKET_STATUS

uint8_t esphome::home_io_control::SX1262_GET_PACKET_STATUS = 0x14
staticconstexpr

Definition at line 36 of file radio_sx1262.h.

◆ SX1262_GET_RSSI_INST

uint8_t esphome::home_io_control::SX1262_GET_RSSI_INST = 0x15
staticconstexpr

Definition at line 51 of file radio_sx1262.h.

◆ SX1262_GET_RX_BUFFER_STATUS

uint8_t esphome::home_io_control::SX1262_GET_RX_BUFFER_STATUS = 0x13
staticconstexpr

Definition at line 50 of file radio_sx1262.h.

◆ SX1262_GET_STATUS

uint8_t esphome::home_io_control::SX1262_GET_STATUS = 0xC0
staticconstexpr

Definition at line 53 of file radio_sx1262.h.

◆ SX1262_GFSK_CRC_OFF

uint8_t esphome::home_io_control::SX1262_GFSK_CRC_OFF = 0x01
staticconstexpr

Definition at line 92 of file radio_sx1262.h.

◆ SX1262_GFSK_PACKET_TYPE_KNOWN_LENGTH

uint8_t esphome::home_io_control::SX1262_GFSK_PACKET_TYPE_KNOWN_LENGTH = 0x00
staticconstexpr

Definition at line 91 of file radio_sx1262.h.

◆ SX1262_IRQ_CRC_ERR

uint16_t esphome::home_io_control::SX1262_IRQ_CRC_ERR = 0x0040
staticconstexpr

Definition at line 67 of file radio_sx1262.h.

◆ SX1262_IRQ_PREAMBLE_DETECTED

uint16_t esphome::home_io_control::SX1262_IRQ_PREAMBLE_DETECTED = 0x0004
staticconstexpr

Definition at line 65 of file radio_sx1262.h.

◆ SX1262_IRQ_RX_DONE

uint16_t esphome::home_io_control::SX1262_IRQ_RX_DONE = 0x0002
staticconstexpr

Definition at line 64 of file radio_sx1262.h.

◆ SX1262_IRQ_SYNC_WORD_VALID

uint16_t esphome::home_io_control::SX1262_IRQ_SYNC_WORD_VALID = 0x0008
staticconstexpr

Definition at line 66 of file radio_sx1262.h.

◆ SX1262_IRQ_TX_DONE

uint16_t esphome::home_io_control::SX1262_IRQ_TX_DONE = 0x0001
staticconstexpr

Definition at line 63 of file radio_sx1262.h.

◆ SX1262_POST_TX_SETTLE_US

uint16_t esphome::home_io_control::SX1262_POST_TX_SETTLE_US = 500
staticconstexpr

SX1262-specific post-TX settling delay before re-entering RX.

The SX1262 GFSK demodulator needs time to stabilize after TX before it can reliably receive the next frame. A 500 µs delay was validated as the minimum that prevents challenge-byte corruption during pairing and tight-turnaround authenticated exchanges.

Definition at line 110 of file tuning_config.h.

◆ SX1262_READ_BUFFER

uint8_t esphome::home_io_control::SX1262_READ_BUFFER = 0x1E
staticconstexpr

Definition at line 33 of file radio_sx1262.h.

◆ SX1262_READ_REGISTER

uint8_t esphome::home_io_control::SX1262_READ_REGISTER = 0x1D
staticconstexpr

Definition at line 57 of file radio_sx1262.h.

◆ SX1262_REG_RX_GAIN

uint16_t esphome::home_io_control::SX1262_REG_RX_GAIN = 0x08AC
staticconstexpr

Definition at line 70 of file radio_sx1262.h.

◆ SX1262_REG_SYNC_WORD

uint16_t esphome::home_io_control::SX1262_REG_SYNC_WORD = 0x06C0
staticconstexpr

Definition at line 69 of file radio_sx1262.h.

◆ SX1262_REG_TX_CLAMP_CONFIG

uint16_t esphome::home_io_control::SX1262_REG_TX_CLAMP_CONFIG = 0x08D8
staticconstexpr

Definition at line 71 of file radio_sx1262.h.

◆ SX1262_REG_TX_MODULATION

uint16_t esphome::home_io_control::SX1262_REG_TX_MODULATION = 0x0889
staticconstexpr

TX modulation-quality erratum register (SX1262 datasheet §15.1, "Modulation Quality with 500 kHz LoRa Bandwidth" — the title names LoRa, but the workaround table covers every modulation).

Bit 2 must be cleared only for LoRa at BW 500 kHz and set to 1 for everything else, explicitly including any (G)FSK configuration — which is all this driver ever uses. Semtech's own driver and RadioLib apply it as TxModulation / fixModulationQuality(). Leaving it at its reset value degrades transmitted modulation quality, which on this protocol shows up as a peer that intermittently fails to decode an otherwise strong frame. Counterpart to the already-applied TxClamp erratum (SX1262_REG_TX_CLAMP_CONFIG).

Definition at line 81 of file radio_sx1262.h.

◆ SX1262_RESPONSE_PREAMBLE

uint16_t esphome::home_io_control::SX1262_RESPONSE_PREAMBLE = 8
staticconstexpr

SX1262-specific preamble for response/continuation frames within an exchange.

Applies to any tight-turnaround frame sent immediately after receiving from the device — 0x3D challenge responses, 0x32 key transfers after receiving 0x3C, and any future protocol frame in that position — giving the peer's receiver time to lock back on after the SX1262's own TX→RX turnaround.

8 bytes was validated on real hardware (Heltec V3.2 ↔ Device actuator) as the minimum that gives reliable lock-on without perturbing exchange timing; it matches the protocol's own nominal SHORT_PREAMBLE floor.

This constant is byte-denominated, like every other preamble value in this codebase (LONG_PREAMBLE, SHORT_PREAMBLE) — RadioSX1262::set_packet_params_() is the one place that converts to the chip's bit-denominated SetPacketParams field, right before the value leaves for the wire.

Definition at line 102 of file tuning_config.h.

◆ SX1262_RX_BUFFER_BASE

uint8_t esphome::home_io_control::SX1262_RX_BUFFER_BASE = 0x80
staticconstexpr

Definition at line 89 of file radio_sx1262.h.

◆ SX1262_SET_BUFFER_BASE_ADDRESS

uint8_t esphome::home_io_control::SX1262_SET_BUFFER_BASE_ADDRESS = 0x8F
staticconstexpr

Definition at line 43 of file radio_sx1262.h.

◆ SX1262_SET_DIO2_AS_RF_SWITCH_CTRL

uint8_t esphome::home_io_control::SX1262_SET_DIO2_AS_RF_SWITCH_CTRL = 0x9D
staticconstexpr

Definition at line 46 of file radio_sx1262.h.

◆ SX1262_SET_DIO3_AS_TCXO_CTRL

uint8_t esphome::home_io_control::SX1262_SET_DIO3_AS_TCXO_CTRL = 0x97
staticconstexpr

Definition at line 47 of file radio_sx1262.h.

◆ SX1262_SET_DIO_IRQ_PARAMS

uint8_t esphome::home_io_control::SX1262_SET_DIO_IRQ_PARAMS = 0x08
staticconstexpr

Definition at line 34 of file radio_sx1262.h.

◆ SX1262_SET_MODULATION_PARAMS

uint8_t esphome::home_io_control::SX1262_SET_MODULATION_PARAMS = 0x8B
staticconstexpr

Definition at line 41 of file radio_sx1262.h.

◆ SX1262_SET_PA_CONFIG

uint8_t esphome::home_io_control::SX1262_SET_PA_CONFIG = 0x95
staticconstexpr

Definition at line 44 of file radio_sx1262.h.

◆ SX1262_SET_PACKET_PARAMS

uint8_t esphome::home_io_control::SX1262_SET_PACKET_PARAMS = 0x8C
staticconstexpr

Definition at line 42 of file radio_sx1262.h.

◆ SX1262_SET_PACKET_TYPE

uint8_t esphome::home_io_control::SX1262_SET_PACKET_TYPE = 0x8A
staticconstexpr

Definition at line 40 of file radio_sx1262.h.

◆ SX1262_SET_REGULATOR_MODE

uint8_t esphome::home_io_control::SX1262_SET_REGULATOR_MODE = 0x96
staticconstexpr

Definition at line 52 of file radio_sx1262.h.

◆ SX1262_SET_RF_FREQUENCY

uint8_t esphome::home_io_control::SX1262_SET_RF_FREQUENCY = 0x86
staticconstexpr

Definition at line 30 of file radio_sx1262.h.

◆ SX1262_SET_RX

uint8_t esphome::home_io_control::SX1262_SET_RX = 0x82
staticconstexpr

Definition at line 28 of file radio_sx1262.h.

◆ SX1262_SET_RX_TX_FALLBACK_MODE

uint8_t esphome::home_io_control::SX1262_SET_RX_TX_FALLBACK_MODE = 0x93
staticconstexpr

Definition at line 31 of file radio_sx1262.h.

◆ SX1262_SET_STANDBY

uint8_t esphome::home_io_control::SX1262_SET_STANDBY = 0x80
staticconstexpr

Definition at line 27 of file radio_sx1262.h.

◆ SX1262_SET_TX

uint8_t esphome::home_io_control::SX1262_SET_TX = 0x83
staticconstexpr

Definition at line 29 of file radio_sx1262.h.

◆ SX1262_SET_TX_PARAMS

uint8_t esphome::home_io_control::SX1262_SET_TX_PARAMS = 0x8E
staticconstexpr

Definition at line 45 of file radio_sx1262.h.

◆ SX1262_SYNC_WORD_PARAM_24_BITS

const uint8_t esphome::home_io_control::SX1262_SYNC_WORD_PARAM_24_BITS = 0x18
static

Definition at line 29 of file radio_sx1262.cpp.

◆ SX1262_TX_BUFFER_BASE

uint8_t esphome::home_io_control::SX1262_TX_BUFFER_BASE = 0x00
staticconstexpr

Data-buffer split programmed by configure_buffer_base(): TX packets build from 0x00, RX packets land at 0x80.

The RX base doubles as the read offset for a length-driven receive — a single in-flight packet always starts exactly there.

Definition at line 88 of file radio_sx1262.h.

◆ SX1262_TX_MODULATION_GFSK_BIT

uint8_t esphome::home_io_control::SX1262_TX_MODULATION_GFSK_BIT = 0x04
staticconstexpr

Bit 2 of SX1262_REG_TX_MODULATION — the (G)FSK-correct value is 1.

Definition at line 83 of file radio_sx1262.h.

◆ SX1262_WRITE_BUFFER

uint8_t esphome::home_io_control::SX1262_WRITE_BUFFER = 0x0E
staticconstexpr

Definition at line 32 of file radio_sx1262.h.

◆ SX1262_WRITE_REGISTER

uint8_t esphome::home_io_control::SX1262_WRITE_REGISTER = 0x0D
staticconstexpr

Definition at line 56 of file radio_sx1262.h.

◆ SX1276_DISCOVERY_HOP_SLICE_MS

uint16_t esphome::home_io_control::SX1276_DISCOVERY_HOP_SLICE_MS = 5
staticconstexpr

Per-channel dwell while SX1276 pairing discovery hops across channels.

The SX1276 supports FastHop (no standby transition), so a short slice keeps discovery sweeping all three channels quickly.

Definition at line 124 of file tuning_config.h.

◆ SX1276_RESPONSE_PREAMBLE

uint16_t esphome::home_io_control::SX1276_RESPONSE_PREAMBLE = 12
staticconstexpr

SX1276 preamble for response/continuation frames within an exchange.

The SX1276 originally reused the protocol's 8-byte SHORT_PREAMBLE for reply frames. A slightly longer 12-byte preamble was found on real hardware to improve the peer device's lock-on without measurably affecting exchange timing, so 12 is the default. Runtime-tunable down to SHORT_PREAMBLE or up for a marginal-range install.

Definition at line 118 of file tuning_config.h.

◆ TAG [1/20]

const char* esphome::home_io_control::TAG = "home_io_control"
staticconstexpr

Definition at line 15 of file device_registry.cpp.

◆ TAG [2/20]

const char* const esphome::home_io_control::TAG = "home_io_control.exchange"
static

Definition at line 26 of file exchange_engine.cpp.

◆ TAG [3/20]

const char* const esphome::home_io_control::TAG = detail::TAG
static

Definition at line 37 of file hub_core.cpp.

◆ TAG [4/20]

const char* const esphome::home_io_control::TAG = "home_io_control.key_extraction_switch"
static

Definition at line 12 of file platform_accept_foreign_pairing_switch.cpp.

◆ TAG [5/20]

const char* const esphome::home_io_control::TAG = "home_io_control.active_issue"
static

Definition at line 13 of file platform_active_issue_text_sensor.cpp.

◆ TAG [6/20]

const char* const esphome::home_io_control::TAG = "home_io_control.cover"
static

Definition at line 12 of file platform_cover.cpp.

◆ TAG [7/20]

const char* const esphome::home_io_control::TAG = "home_io_control.favorite_button"
static

Definition at line 12 of file platform_cover_favorite_button.cpp.

◆ TAG [8/20]

const char* const esphome::home_io_control::TAG = "home_io_control.vent_button"
static

Definition at line 12 of file platform_cover_vent_button.cpp.

◆ TAG [9/20]

const char* const esphome::home_io_control::TAG = "home_io_control.device_name"
static

Definition at line 13 of file platform_device_name_text_sensor.cpp.

◆ TAG [10/20]

const char* const esphome::home_io_control::TAG = "home_io_control.exchange_failures"
static

Definition at line 12 of file platform_exchange_failures_sensor.cpp.

◆ TAG [11/20]

const char* const esphome::home_io_control::TAG = "home_io_control.last_contact"
static

Definition at line 13 of file platform_last_contact_sensor.cpp.

◆ TAG [12/20]

const char* const esphome::home_io_control::TAG = "home_io_control.light"
static

Definition at line 12 of file platform_light.cpp.

◆ TAG [13/20]

const char* const esphome::home_io_control::TAG = "home_io_control.lock"
static

Definition at line 13 of file platform_lock.cpp.

◆ TAG [14/20]

const char* const esphome::home_io_control::TAG = "home_io_control.pairing_result"
static

Definition at line 12 of file platform_pairing_result_text_sensor.cpp.

◆ TAG [15/20]

const char* const esphome::home_io_control::TAG = "home_io_control.rssi"
static

Definition at line 12 of file platform_rssi_sensor.cpp.

◆ TAG [16/20]

const char* const esphome::home_io_control::TAG = "home_io_control.switch"
static

Definition at line 12 of file platform_switch.cpp.

◆ TAG [17/20]

const char* const esphome::home_io_control::TAG = "home_io_control.lr1121"
static

Definition at line 27 of file radio_lr1121.cpp.

◆ TAG [18/20]

const char* const esphome::home_io_control::TAG = "home_io_control.soft_phy"
static

Definition at line 23 of file radio_soft_phy_driver_base.cpp.

◆ TAG [19/20]

const char* const esphome::home_io_control::TAG = "home_io_control.sx1262"
static

Definition at line 28 of file radio_sx1262.cpp.

◆ TAG [20/20]

const char* const esphome::home_io_control::TAG = "home_io_control.sx1276"
static

Definition at line 20 of file radio_sx1276.cpp.

◆ TRANSFER_KEY

uint8_t esphome::home_io_control::TRANSFER_KEY[AES_KEY_SIZE]
staticconstexpr
Initial value:
= {0x34, 0xC3, 0x46, 0x6E, 0xD8, 0x8F, 0x4E, 0x8E,
0x16, 0xAA, 0x47, 0x39, 0x49, 0x88, 0x43, 0x73}

The transfer key is a hardcoded key used ONLY during pairing to obfuscate the system key during over-the-air transfer.

It is NOT the system key. This is the same across all IO-Homecontrol devices worldwide.

Definition at line 332 of file proto_constants.h.

◆ UART_CELL_BITS

uint8_t esphome::home_io_control::UART_CELL_BITS = 10
staticconstexpr

Bits an on-air UART cell spends per protocol byte: start(1) + data(8) + stop(1).

Definition at line 38 of file radio_soft_phy.h.

◆ UART_PROBE_MAX_BIT_OFFSET

const uint8_t esphome::home_io_control::UART_PROBE_MAX_BIT_OFFSET = 10
static

Maximum bit offset to search for valid UART decode start position.

The UART frame is 10 bits (start + 8 data). If the sync word is not aligned, we probe up to 10 bits offset to recover the correct framing.

Definition at line 23 of file radio_soft_phy.cpp.

◆ UNKNOWN_POSITION

float esphome::home_io_control::UNKNOWN_POSITION = 212.0F
staticconstexpr

Sentinel value meaning "position is not known yet".

Matches POS_UNKNOWN (0xD4 = 212 decimal) for easy debugging.

Definition at line 227 of file proto_device_model.h.