28#include "esphome/core/component.h"
29#include "esphome/core/hal.h"
30#include "esphome/components/api/custom_api_device.h"
31#include "esphome/components/spi/spi.h"
69#ifdef IOHOME_LR1121_FIRMWARE_UPDATE
76inline constexpr uint8_t LR1121_FLASH_WARN_BLOCKING_MAX_CS = 255;
97 public api::CustomAPIDevice,
98 public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW,
99 spi::CLOCK_PHASE_LEADING, spi::DATA_RATE_8MHZ>,
116 uint16_t preamble) {
return this->
transmit_frame_(frame, freq, preamble); },
122 this->set_timeout(name, delay_ms, std::move(cb));
126 [
this](
const IoFrame &frame, uint32_t freq, uint16_t preamble) {
129 [
this](
const char *name, uint32_t delay_ms, std::function<void()> cb) {
130 this->set_timeout(name, delay_ms, std::move(cb));
132#ifdef IOHOME_LR1121_FIRMWARE_UPDATE
138 lr1121_firmware_update_(
140 [
this]() { this->warn_if_blocking_over_ = LR1121_FLASH_WARN_BLOCKING_MAX_CS; },
this)
156 return dev !=
nullptr && dev->
has_system_key ? dev->system_key :
nullptr;
170 void setup()
override;
172 void loop()
override;
187 uint8_t
spi_transfer(uint8_t data)
override {
return this->transfer_byte(data); }
190 void spi_write(uint8_t data)
override { this->write_byte(data); }
193 uint8_t
spi_read()
override {
return this->read_byte(); }
479 virtual void add_device(
const std::string &device_id);
523 virtual bool set_device_tilt(
const std::string &device_id, uint8_t tilt_percent);
590 const std::string &index) {
601 const std::string &first_index,
const std::string &last_index) {
616 const std::string &value) {
636 virtual bool set_fan_position(
const std::string &device_id, uint8_t position);
651 virtual bool set_lock_state(
const std::string &device_id,
bool locked);
805#ifdef IOHOME_LR1121_FIRMWARE_UPDATE
813 void trigger_lr1121_firmware_update() { this->lr1121_firmware_update_.trigger(); }
815#ifdef IOHOME_LR1121_BOOTLOADER_UPDATE
827 void set_bootloader_rewrite_allowed(
bool allowed) {
828 this->lr1121_firmware_update_.set_bootloader_rewrite_allowed(allowed);
840 bool transmit_frame_(
const IoFrame &frame, uint32_t freq, uint16_t preamble);
848 uint8_t max_tries = EXCHANGE_RETRY_COUNT);
935 const bool next_op_is_background =
941 ONEWAY_QUIET_PERIOD_MS, ONEWAY_POLL_DEFER_CAP_MS);
949 uint32_t delay_ms = REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS);
957 const std::string &src_id)
const;
984 uint32_t retry_after_fail_ms);
1031 uint32_t retry_after_fail_ms = 0, uint8_t max_tries = EXCHANGE_RETRY_COUNT);
1049 const std::function<
bool(
const IoDevice &)> &accepts,
const char *rejection_profile,
1064 const std::function<
bool(
const IoDevice &)> &accepts,
const char *rejection_profile,
1080 this->
busy_ =
false;
1168 void api_probe_device_(
const std::string &device_id,
const std::string &probe,
const std::string &index) {
1172 void api_probe_sweep_(
const std::string &device_id,
const std::string &probe,
const std::string &first_index,
1173 const std::string &last_index) {
1206#ifdef IOHOME_LR1121_FIRMWARE_UPDATE
1212 void run_lr1121_boot_time_bootloader_read_() { this->lr1121_firmware_update_.run_boot_time_bootloader_read(); }
1216 void cache_lr1121_flash_verdict_() { this->lr1121_firmware_update_.cache_flash_verdict(); }
1219 void dump_lr1121_firmware_update_debug_()
const { this->lr1121_firmware_update_.dump_debug(); }
1297#ifdef IOHOME_LR1121_FIRMWARE_UPDATE
1303 Lr1121FirmwareUpdateController lr1121_firmware_update_;
1330 if (pos == UNKNOWN_POSITION) {
1334 snprintf(buf,
sizeof(buf),
"%.0f%%", pos);
Owns the per-hub device table, update callbacks, and linked-remote associations.
bool apply_optimistic_tilt(const std::string &device_id, float tilt_percent)
Set an optimistic slat angle ahead of a confirming poll, and notify.
void add_linked_remote_class(DeviceType type, const std::string &device_id)
Record that a remote's typed-broadcast presses (e.g.
bool apply_optimistic_target(const std::string &device_id, float target_io_position)
Set an optimistic target position ahead of a confirming poll/response, and notify.
bool apply_optimistic_stop(const std::string &device_id, bool restorable=false)
Predict that a device has stopped (e.g.
void add_linked_remote(const std::string &remote_id, const std::string &device_id)
Record that a remote node controls a registered device.
void subscribe(DeviceUpdateCallback cb)
Register a callback that fires whenever a device's state changes.
IoDevice * get(const std::string &device_id)
Retrieve a registered device by ID.
void set_wake_evidence_spent_handler(WakeEvidenceSpentHandler handler)
Install what to do when an exchange planned on an AWAKE belief drew no frame at all: the receiver did...
void log_debug_unconfirmed(const char *device_id) const
Log the debug snapshot for an exchange that ended accepted-but-unconfirmed, at INFO.
void log_debug(const char *device_id) const
Log the debug snapshot as a WARN-level structured line.
void set_device_key_provider(DeviceKeyProvider provider)
Install the source of per-device system keys.
void set_target_evidence_provider(TargetEvidenceProvider provider)
Install the source of per-target evidence.
InternalGPIOPin * fem_en_pin_
Front-end module enable.
InternalGPIOPin * fem_pa_pin_
Front-end module PA switch.
std::string describe_last_commander(const IoDevice &dev) const
Render a device's "last commanded by" string, resolving this hub's own node ID.
void send_oneway_command(const std::string &controller_id, CoverCommand cmd)
Queue a 1W named command, sent as the given controller identity.
virtual bool set_lock_state(const std::string &device_id, bool locked)
Semantic lock helper for lock entities.
virtual ManagementActionResult scan_paired_devices()
Broadcast a roll-call and report every device that answers (see ManagementActions::scan_paired_device...
void dump_oneway_controllers_config_() const
Emit the 1W controller identities to the config dump — node, class, and the resolved ACEI / broadcast...
virtual bool set_fan_position(const std::string &device_id, uint8_t position)
Send a heat level to an exterior heater (a fan entity) as an IO position.
void set_tx_power(uint8_t power)
Set transmit power (dBm).
InternalGPIOPin * dio4_pin_
SX1276 DIO4 preamble detect (optional).
virtual void set_key_extraction_armed(bool armed)
Arm or disarm the "Recover System Key" (key extraction) responder.
bool execute_request_and_update_(const std::string &device_id, const IoFrame &request, bool warn_on_no_response, uint32_t retry_after_fail_ms=0, uint8_t max_tries=EXCHANGE_RETRY_COUNT)
Shared request/response helper for high-level operations: exchange_and_record_() plus update_device_s...
void api_probe_device_(const std::string &device_id, const std::string &probe, const std::string &index)
Native API callback: run a single diagnostic probe against a registered device.
void add_exposed_sender(const std::string &sender_id)
Allow a 1W sender (identified by its node ID) to fire the esphome.home_io_control_sender_event event ...
void api_force_open_device_(const std::string &device_id)
Native API callback: force-open a registered cover device.
void execute_oneway_position_(const std::string &controller_id, uint8_t position)
Send a queued 1W numeric position.
void maybe_fire_sender_event_(const OneWayFrameInfo &info, bool linked, const std::string &src_id)
Fire the sender HA event for a decoded 1W frame, if the sender is exposed.
virtual void queue_set_fan_position(const std::string &device_id, uint8_t position)
Async form of set_fan_position() that keeps radio work serialized on the main loop.
void set_node_id(const std::string &id)
Set the controller's node ID (hex string).
virtual bool set_device_position_and_tilt(const std::string &device_id, uint8_t position, uint8_t tilt_percent)
Set both position and tilt of a tilt-capable cover in one atomic command.
void add_oneway_controller(const OneWayControllerIdentity &identity)
Register a configured 1W controller identity (see oneway_controller.h).
virtual bool set_device_tilt(const std::string &device_id, uint8_t tilt_percent)
Send a tilt command to a tilt‑capable cover.
InternalGPIOPin * dio1_pin_
SX1262 DIO1 interrupt; also carries the LR1121's DIO9 IRQ line.
void execute_oneway_enroll_(const std::string &controller_id)
Send a queued 1W enrollment (add-controller).
IOHomeControlComponent()
Initialize ExchangeEngine, PairingEngine, and ManagementActions with double-pointer/ reference indire...
uint32_t last_1w_activity_ms_
millis() of the most recent 1W frame of any kind, including ones dropped as duplicates — a repeat sti...
virtual bool send_heating_command(const std::string &device_id, HeatingFunction fn, float value)
Run one heating function on the heater's private register protocol (CMD_WRITE_PRIVATE 0x20): a write ...
void send_oneway_position(const std::string &controller_id, uint8_t position)
Queue a 1W numeric position, sent as the given controller identity.
virtual bool set_switch_state(const std::string &device_id, bool on)
Semantic binary helper for switch entities.
bool run_execute_operation_(const std::string &device_id, const ExecuteRequestSpec &spec, const std::function< bool(const IoDevice &)> &accepts, const char *rejection_profile, const std::function< bool(IoFrame &, const IoDevice &)> &build)
Funnel for the four execute-family operations: runs try_execute_operation_() and, on any false return...
void api_scan_paired_devices_()
Native API callback: broadcast a roll-call scan of already-paired devices.
void set_rst_pin(InternalGPIOPin *pin)
Set the radio reset pin.
virtual bool apply_optimistic_stop(const std::string &device_id)
Predict that a device has stopped (e.g.
void arm_execute_confirmation_poll_(const std::string &device_id, bool for_stop)
Arm the confirming poll that follows a command, because a CMD_EXECUTE reply is never trusted for posi...
virtual void queue_set_device_tilt(const std::string &device_id, uint8_t tilt_percent)
Queue an async tilt update; returns immediately, executed in loop().
void execute_oneway_(F &&send)
Shared bookkeeping for every 1W transmit: mark the radio busy for the duration of send,...
void begin_status_poll_tracking_(const std::string &device_id, uint32_t initial_delay_ms)
Begin bounded follow-up polling for a device after a command or overheard remote activity.
void dump_config() override
Dump configuration and radio debug info to the log.
void update_tuning_select(const std::string &name, const std::string &value)
Receive a select tuning update from a HA select entity.
InternalGPIOPin * rst_pin_
virtual void register_device_callback(DeviceUpdateCallback cb)
Register a callback invoked when any device updates.
void set_pa_pin(uint8_t pa_pin)
Set PA boost pin configuration.
bool handle_error_response_(const std::string &device_id, const IoFrame &request, const IoFrame &response, uint32_t retry_after_fail_ms)
Handle an explicit CMD_ERROR_RESP refusal from the device: record the result code,...
virtual bool set_heating_temperature(const std::string &device_id, uint16_t main_parameter, const HeatingFp &fp)
Command a heater that carries a temperature or an alias in its main parameter (the heating temperatur...
virtual IoDevice * get_device(const std::string &device_id)
Retrieve a device by ID; returns nullptr if not found.
bool diagnostic_probes_enabled() const
Whether diagnostic probes are enabled for this build.
virtual void queue_request_device_status(const std::string &device_id)
Queue an async status request; returns immediately, executed in loop().
void api_probe_sweep_(const std::string &device_id, const std::string &probe, const std::string &first_index, const std::string &last_index)
Native API callback: run a bounded diagnostic probe sweep against a registered device.
void update_tuning_number(const std::string &name, float value)
Receive a numeric tuning update from a HA number entity.
void record_oneway_pairing_gesture_(const IoFrame &frame, uint32_t now)
If frame matches a 1W remote's pairing gesture (decisions::is_one_way_pairing_gesture()),...
void spi_enable() override
Enable the SPI bus.
virtual void add_device(const std::string &device_id)
Add a device to the registry by device ID only (undeclared/legacy path).
void set_fem_en_pin(InternalGPIOPin *pin)
Set the front‑end module enable pin.
virtual void set_oneway_key_adoption_armed(bool armed)
Arm or disarm the 1W controller-key adoption listener.
InternalGPIOPin * vfem_pin_
Front-end module power.
TuningConfig tuning_
Runtime tuning overrides.
void log_exchange_unconfirmed_debug_(const char *device_id) const
Log the last exchange debug snapshot for an accepted-but-unconfirmed exchange, at INFO.
ExchangeOutcome send_and_receive_(const IoFrame &request, IoFrame &response, uint32_t freq, uint8_t max_tries=EXCHANGE_RETRY_COUNT)
Main request/response exchange with retry and automatic authentication.
virtual void set_device_status_poll_interval(const std::string &device_id, uint32_t poll_interval_ms)
Configure the optional follow-up polling interval for a registered device.
std::vector< std::string > resolve_1w_target_devices_(const OneWayFrameInfo &info, const std::string &src_id) const
Resolve the set of devices a 1W frame should affect: devices linked to the sending remote by node ID,...
void process_pending_operation_()
Pop next pending operation from the queue and execute it (set position, request status,...
StatusPollPolicy poll_policy_
void schedule_status_poll_(const std::string &device_id, uint32_t delay_ms)
Schedule a delayed status poll for a registered device using the Component timeout API.
void hop_frequency_()
Delegate channel hop to ExchangeEngine (which owns last_hop_us_).
void add_linked_remote(const std::string &remote_id, const std::string &device_id)
Declare that a remote (identified by its node ID) controls a registered device.
virtual void set_device_dimmable(const std::string &device_id, bool dimmable)
Set a device's dimmable flag (see IoDevice::dimmable).
virtual bool read_heating_register(const std::string &device_id, HeatingFunction fn, float *value_out, uint8_t max_tries)
Read one register of a heater and fold the decoded value into IoDevice::heating.
void execute_oneway_unenroll_(const std::string &controller_id)
Send a queued 1W un-enrollment (remove-controller).
float get_tuning_number_value(const std::string &name) const
Current value of a numeric tuning parameter, used to seed a HA number entity on boot.
bool defer_background_poll_() const
Whether loop() should skip dispatching the queue this iteration because the pending work is a backgro...
void set_dio1_pin(InternalGPIOPin *pin)
Set the DIO1 interrupt pin (SX1262; also carries the LR1121's DIO9 IRQ line).
virtual ManagementActionResult force_open_device(const std::string &device_id)
Move a cover device to fully open at elevated priority, intended to bypass wind/rain soft locks.
const PairingTelemetry & pairing_telemetry() const
bool diagnostic_probes_enabled_
Whether diagnostic probes (ManagementActions::probe_device()/probe_sweep()) are enabled.
void update_device_status_(const IoFrame &frame, bool trust_position=true)
Extract supported position or metadata info from a response frame and merge it into the device record...
void api_heating_control_(const std::string &device_id, const std::string &function, const std::string &value)
Native API callback: run a heating/climate function (CMD_WRITE_PRIVATE 0x20) against a registered cli...
virtual void queue_request_device_name(const std::string &device_id)
Queue an async device-name request; returns immediately, executed in loop().
virtual void queue_request_device_limitation(const std::string &device_id)
Queue an async minimum-limitation read for the rain sensor poll; executed in loop() as a background o...
void resolve_start_preamble_default_()
Resolve normal_start_preamble from the driver when YAML did not set it (ADR 0042).
void set_radio_test_mode(bool active)
Suspend the hub's normal loop (packet processing, hopping, polling).
RecentOneWayPairingSighting recent_oneway_pairing_sighting_
Most recent 1W pairing-gesture frame seen on the hub's normal passive RX path (e.g.
void set_radio_type(const std::string &type)
Set radio type ("sx1276", "sx1262", or "lr1121"); required by the YAML schema.
void api_oneway_remove_controller_(const std::string &controller_id)
Native API callback: queue a 1W un-enrollment (remove-controller) for a controller identity.
virtual void queue_set_lock_state(const std::string &device_id, bool locked)
Async form of set_lock_state() that keeps radio work serialized on the main loop.
uint32_t last_pairing_end_ms_
millis() when the last pairing attempt ended; 0 before the first one (see queue_discover_and_pair()).
virtual void queue_set_light_position(const std::string &device_id, uint8_t position)
Async form of set_light_position() that keeps radio work serialized on the main loop.
void schedule_device_polls_(const std::vector< std::string > &device_ids, uint32_t delay_ms)
Schedule status polls for a fixed list of devices (shared by the id-linked and class-linked 1W paths,...
void loop() override
Main loop: process pending operations and drive radio state machine.
bool try_execute_operation_(const std::string &device_id, const ExecuteRequestSpec &spec, const std::function< bool(const IoDevice &)> &accepts, const char *rejection_profile, const std::function< bool(IoFrame &, const IoDevice &)> &build)
Shared skeleton for the four execute-family operations (position, named command, tilt,...
void log_exchange_debug_(const char *device_id) const
Log the last exchange debug snapshot (delegates to exchange_engine_).
void set_pairing_result_callback(std::function< void()> cb)
Register a callback invoked once, right after every discover_and_pair() attempt completes — used by t...
void schedule_background_poll_backoff_(const std::string &device_id, bool auth_like)
Apply backoff after a failed background status poll and log the result.
PairingTelemetry pairing_telemetry_
Per-attempt pairing telemetry.
void send_oneway_unenroll(const std::string &controller_id)
Queue a standalone 1W un-enrollment (remove-controller) for the given controller identity,...
OneWayTransmitter oneway_transmitter_
Owns the 1W controller identities, their rolling-sequence counters and the transmit burst.
virtual ManagementActionResult heating_control(const std::string &device_id, const std::string &function, const std::string &value)
Run one 2W heating/climate function (CMD_WRITE_PRIVATE 0x20) against a registered climate device — th...
void add_oneway_command_report_callback(OneWayCommandReportFn callback)
Subscribe to the report emitted after every 1W command attempt.
std::string radio_failure_reason_
Why setup() gave up on the radio, or empty.
virtual void set_device_rain_poll_interval(const std::string &device_id, uint32_t interval_ms)
Opt a registered device into the periodic rain sensor poll (a read of its minimum limitation).
std::string radio_type_
"sx1276", "sx1262", or "lr1121"; required by the YAML schema.
void api_rename_device_(const std::string &device_id, const std::string &new_name)
Native API callback: rename a registered device.
uint8_t system_key_[AES_KEY_SIZE]
virtual bool request_device_limitation(const std::string &device_id)
Read the device's minimum limitation and derive its rain sensor state from the reply.
float get_setup_priority() const override
Get setup priority (HARDWARE to initialize early).
void record_1w_activity_(uint32_t now)
Record that a 1W frame just went out on the radio — ours or someone else's — updating last_1w_activit...
bool key_extraction_awaiting_reply_() const
True while the key-extraction responder is mid-attempt and still within its bounded CH2-hold window.
virtual void queue_set_device_position_and_tilt(const std::string &device_id, uint8_t position, uint8_t tilt_percent)
Queue an async combined position+tilt update; returns immediately, executed in loop().
void set_busy_pin(InternalGPIOPin *pin)
Set the BUSY pin (SX1262/LR1121).
virtual bool queue_device_command(const std::string &device_id, CoverCommand cmd)
Queue an async named command (STOP, FAVORITE, VENT, FORCE_OPEN); returns immediately,...
virtual ManagementActionResult identify_device(const std::string &device_id)
Trigger a device's physical identify (brief jog/flash) so a user can confirm which physical motor a d...
void apply_rain_poll_result_(const std::string &device_id, RainSensorState reading, const std::string &limit_text)
Fold one rain poll outcome into the device's rain sensor state and tell subscribers.
virtual bool discover_and_pair()
Discover and pair a device that is in pairing mode.
RadioDriver * select_and_construct_radio_(const char **chip_name_out)
Select and construct the radio driver named by the required radio_type config field.
bool poll_heating_device_(const std::string &device_id)
Poll a heater: read its room temperature, setpoint, mode and regulator state (stopping at the first f...
void api_oneway_set_position_(const std::string &controller_id, const std::string &position)
Native API callback: queue a 1W position for a controller identity.
uint8_t spi_read() override
Read one byte (MISO only).
void api_identify_device_(const std::string &device_id)
Native API callback: trigger a registered device's physical identify.
bool transmit_frame_(const IoFrame &frame, uint32_t freq, uint16_t preamble)
Transmit a raw IoFrame on the current frequency with given preamble length.
virtual bool set_heating_level(const std::string &device_id, uint8_t level)
Set the heating level of a heater that is commanded with levels (the plain electrical heater).
void set_dio0_pin(InternalGPIOPin *pin)
Set the DIO0 interrupt pin (SX1276).
void set_tuning_config(const TuningConfig &config)
Apply the tuning configuration generated from YAML / UI entities.
void send_oneway_action(const std::string &controller_id, OneWayButtonAction action)
Queue whichever of position/command a generated button's action resolves to.
bool radio_test_mode_
When true, loop() is suspended for loopback testing.
void set_vfem_pin(InternalGPIOPin *pin)
Set the VFEM power pin.
ExchangeEngine exchange_engine_
Owns all authenticated exchange and LBT/hop logic.
RequestResult exchange_and_record_(const std::string &device_id, const IoFrame &request, IoFrame &response, const RequestOptions &options)
Run one authenticated request/response exchange on the standard command channel and record its outcom...
RequestResult
What exchange_and_record_() found.
virtual bool apply_optimistic_tilt(const std::string &device_id, float tilt_percent)
Set an optimistic slat angle ahead of a confirming status poll, and notify.
const OneWayControllerRegistry & oneway_controllers() const
void schedule_heating_poll_(const std::string &device_id, uint32_t delay_ms)
Arm the heater's regular-cadence poll timer.
virtual ManagementActionResult probe_sweep(const std::string &device_id, const std::string &probe, const std::string &first_index, const std::string &last_index)
Walk a bounded index range, one probe_device() call per index (see ManagementActions::probe_sweep()).
void set_oneway_key_adoption_armed_callback(std::function< void(bool)> cb)
Register a callback invoked whenever the 1W key-adoption armed state changes — manual toggle,...
bool oneway_key_adoption_armed() const
Whether the 1W key-adoption listener is currently armed.
virtual bool set_light_state(const std::string &device_id, bool on)
Semantic binary helper for light entities.
esphome::home_io_control::ManagementActionResult ManagementActionResult
Result payload used by hub-level management actions such as rename.
PairingEngine pairing_engine_
Owns the three-phase device pairing flow.
virtual void set_device_silent(const std::string &device_id, bool silent)
Select a device's travel profile at runtime (see IOHomeCoverSilentSwitch).
InternalGPIOPin * dio0_pin_
SX1276 DIO0 interrupt.
void set_system_key(const std::string &key)
Set the system key (hex string).
ManagementActions management_actions_
Owns rename, identify, force-open, scan_paired_devices, and other hub-level HA actions.
virtual void queue_set_light_state(const std::string &device_id, bool on)
Async form of set_light_state() that keeps radio work serialized on the main loop.
void schedule_linked_remote_polls_(const std::string &remote_id, uint32_t delay_ms=REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS)
Schedule status polls for all devices associated with a linked remote.
void spi_write(uint8_t data) override
Write one byte (MOSI only).
std::vector< OneWayCommandReportFn > oneway_report_callbacks_
Subscribers to the per-command 1W report; one per "Last 1W Command" sensor.
void set_tcxo_voltage(uint8_t voltage)
Set the SX1262/LR1121 TCXO control-voltage code (0-based, TCXO_VOLTAGE_OPTIONS in hub_validators....
OnewayKeyAdoption oneway_key_adoption_
Opt-in, receive-only 1W controller-key adoption listener (oneway_key_adoption.cpp).
void notify_device_update_(const std::string &id)
Fire all registered device update callbacks for the given device ID.
std::string system_key_str_
virtual void queue_set_device_position(const std::string &device_id, uint8_t position)
Queue an async position update; returns immediately, executed in loop().
virtual ManagementActionResult rename_device(const std::string &device_id, const std::string &new_name)
Rename a device and verify the result by reading the name back.
std::string get_tuning_select_value(const std::string &name) const
Current option string of a select tuning parameter, used to seed a HA select entity on boot.
OneWayTransmitter & oneway_transmitter()
virtual void queue_set_switch_state(const std::string &device_id, bool on)
Async form of set_switch_state() that keeps radio work serialized on the main loop.
void set_dio4_pin(InternalGPIOPin *pin)
Set the DIO4 preamble‑detect pin (SX1276, optional).
decisions::OneWayDedupState last_1w_logged_
Identity of the last processed 1W frame, for burst suppression; see decisions::is_duplicate_1w_frame(...
bool exchange_heating_(const std::string &device_id, const char *label, const IoFrame &request, IoFrame &response, uint8_t max_tries)
The exchange every heating frame shares: send on the command channel, record the outcome (exchange co...
void send_oneway_enroll(const std::string &controller_id)
Queue a 1W enrollment for the given controller identity — the enroll button's press handler.
std::function< void()> pairing_result_callback_
Invoked once after every pairing attempt completes; see set_pairing_result_callback().
virtual bool set_device_position(const std::string &device_id, uint8_t position)
Send a position command to a device.
void setup() override
Initialize hardware (radio and device registry).
KeyExtractionResponder key_extraction_
Device-role responder for the "Recover System Key" feature (key_extraction_responder....
uint8_t node_id_[NODE_ID_SIZE]
uint8_t spi_transfer(uint8_t data) override
Transfer one byte full‑duplex.
virtual bool request_device_name(const std::string &device_id)
Request the stored device name from a device.
std::vector< std::string > exposed_senders_
1W sender node IDs (remotes or sensors) allowed to fire the sender HA event (add_exposed_sender).
uint8_t tcxo_voltage_
SX1262/LR1121 TCXO voltage setting (default 1.8 V).
virtual void set_device_temperature_range(const std::string &device_id, float min_c, float max_c)
Set the temperature encoding range of a heater that carries a temperature in its main parameter (YAML...
virtual bool apply_optimistic_target(const std::string &device_id, float target_io_position)
Set an optimistic target position ahead of a confirming poll/response, and notify.
void process_received_packet_(const RadioRxPacket &packet)
Parse a received frame, merge supported device state or metadata, and notify callbacks.
bool execute_device_command_(const std::string &device_id, CoverCommand cmd)
Execute a named device command (STOP, FAVORITE, VENT, FORCE_OPEN) via the authenticated exchange.
void set_fem_profile(FemProfile profile)
Set which FEM part fem_pa_pin is wired to (fem: in YAML) — selects whether the SX1262 driver drives t...
bool authenticate_request_(const IoFrame &request, uint32_t freq)
Handle an inbound authenticated command from a device (status updates, etc.).
void spi_disable() override
Disable the SPI bus.
RainPollPolicy rain_poll_policy_
Schedule of the opt-in rain sensor poll.
InternalGPIOPin * busy_pin_
SX1262/LR1121 BUSY pin.
void trigger_scan_paired_devices()
Entry point for the "Scan Paired Devices" button: run the roll-call and publish its report to the log...
void register_management_actions_()
Register hub-level Home Assistant actions; called from setup().
void apply_tuning_to_radio_()
Apply the current tuning configuration to the active radio driver.
FemProfile fem_profile_
Which FEM part fem_pa_pin_ belongs to, if any.
virtual void queue_discover_and_pair()
Queue a pairing operation; executed in loop() when radio idle.
uint32_t first_1w_activity_ms_
millis() of the first 1W frame in the current burst.
virtual bool request_device_status(const std::string &device_id)
Request current status from a device.
void add_linked_remote_class(DeviceType type, const std::string &device_id)
Declare that a device class's typed 1W broadcasts (e.g.
bool apply_optimistic_linked_state_(const OneWayFrameInfo &info, const std::vector< std::string > &device_ids)
Apply optimistic target state to every device in device_ids, when the decoded frame carries a resolva...
virtual ManagementActionResult probe_device(const std::string &device_id, const std::string &probe, const std::string &index)
Send a single diagnostic probe frame to a registered device and report the raw reply (see ManagementA...
void set_key_extraction_armed_callback(std::function< void(bool)> cb)
Register a callback invoked whenever the key-extraction armed state changes — manual toggle,...
virtual bool set_light_position(const std::string &device_id, uint8_t position)
Send an arbitrary IO position (0-100) to a light entity.
void execute_oneway_command_(const std::string &controller_id, CoverCommand cmd)
Send a queued 1W named command.
void set_diagnostic_probes_enabled(bool enabled)
Set whether ManagementActions::probe_device()/probe_sweep() are allowed to run.
void set_fem_pa_pin(InternalGPIOPin *pin)
Set the FEM PA switch pin.
RadioDriver * get_radio() const
Get the underlying radio driver (for diagnostics and test tooling).
Encapsulates hub-level management operations exposed as Home Assistant actions.
void api_probe_device(const std::string &device_id, const std::string &probe, const std::string &index)
Native API callback: run a single diagnostic probe and publish the result as a HA event.
void register_actions()
Register all management actions (rename, identify, force-open, ...) with ESPHome's native API server.
void api_rename_device(const std::string &device_id, const std::string &new_name)
Native API callback: rename a device and publish the result as a HA event.
void api_oneway_set_position(const std::string &controller_id, const std::string &position)
Native API callback: queue a 1W position for a controller identity.
ManagementActionResult scan_paired_devices()
Broadcast a roll-call and report every device that answers.
ManagementActionResult probe_device(const std::string &device_id, const std::string &probe, const std::string &index)
Send a single diagnostic probe frame to an already-paired device and report the raw reply.
ManagementActionResult rename_device(const std::string &device_id, const std::string &new_name)
Rename a registered device and verify the result by reading the name back.
void api_oneway_remove_controller(const std::string &controller_id)
Native API callback: queue a standalone 1W un-enrollment (remove-controller, CMD 0x39) for a controll...
void api_heating_control(const std::string &device_id, const std::string &function, const std::string &value)
Native API callback: run a heating/climate function and publish the result as a HA event.
void api_force_open_device(const std::string &device_id)
Native API callback: force-open a device and publish the result as a HA event.
ManagementActionResult identify_device(const std::string &device_id)
Trigger a registered device's physical identify (brief jog/flash).
ManagementActionResult force_open_device(const std::string &device_id)
Move a registered cover device to fully open at elevated priority, intended to bypass wind/rain soft ...
void api_probe_sweep(const std::string &device_id, const std::string &probe, const std::string &first_index, const std::string &last_index)
Native API callback: run a bounded probe sweep and publish the result as a HA event.
void api_scan_paired_devices()
Native API callback: run a roll-call scan and publish the result as a HA event.
void api_identify_device(const std::string &device_id)
Native API callback: trigger a device's physical identify and publish the result as a HA event.
ManagementActionResult heating_control(const std::string &device_id, const std::string &function, const std::string &value)
Send one 2W heating/climate function (CMD_WRITE_PRIVATE 0x20) to a registered climate device.
ManagementActionResult probe_sweep(const std::string &device_id, const std::string &probe, const std::string &first_index, const std::string &last_index)
Walk a bounded index range, one probe_device() call per index, in one user gesture.
The configured 1W controller identities, in YAML declaration order.
Sends 1W commands as the repeated bursts real remotes send.
void add_identity(const OneWayControllerIdentity &identity)
Register a configured controller identity.
const OneWayControllerRegistry & identities() const
Opt-in, receive-only listener that adopts an overheard 1W controller key.
bool armed() const
Whether the listener is currently armed.
void set_armed_callback(std::function< void(bool)> cb)
Register a callback invoked whenever the armed state changes (manual toggle, successful adoption,...
void set_armed(bool armed)
Arm or disarm the 1W controller-key adoption listener.
Serialized pending-operation queue with coalescing, deduplication, and two-band ordering.
const PendingOperation & front() const
void enqueue_oneway_unenroll(const std::string &controller_id)
Enqueue a 1W un-enrollment (remove-controller) for a controller identity.
void enqueue_oneway_command(const std::string &controller_id, CoverCommand cmd)
Enqueue a 1W named command for a controller identity.
void enqueue_oneway_position(const std::string &controller_id, uint8_t position)
Enqueue a 1W numeric position for a controller identity.
static bool is_background_op(PendingOperationType t)
True for background poll types (REQUEST_STATUS, REQUEST_NAME, REQUEST_LIMITATION) that yield to contr...
void enqueue_oneway_enroll(const std::string &controller_id)
Enqueue a 1W enrollment (add-controller) for a controller identity.
Owns and drives all three phases of the IO-Homecontrol device pairing flow.
Fixed-size per-attempt telemetry recorder for the pairing flow.
Abstract radio driver for IO-Homecontrol.
Per-device periodic limitation-read schedule and miss counter.
Interface for SPI bus access.
Per-hub poll scheduling and failure-backoff policy.
Per-hub device table, update-callback fan-out, and linked-remote map.
Self-contained authenticated exchange engine for IO-Homecontrol 2W.
OneWayActionEncoding encode_oneway_action(OneWayButtonAction action)
Resolve a button action to the call that sends it.
OneWayButtonAction
The command a generated 1W button sends.
Pure transition helpers for hub-owned exchange and pairing frame decisions.
Internal exchange-state model for hub-owned authenticated non‑pairing flows.
Internal pairing-state model for hub‑owned discovery and key‑exchange flows.
LR1121 transceiver-firmware-update feature — orchestration collaborator.
Hub-level management operations exposed as Home Assistant actions.
TargetEvidence target_evidence(const IoDevice &dev)
Build the exchange engine's view of a device record.
bool defer_background_poll_for_1w_activity(bool next_op_is_background, uint32_t first_1w_activity_ms, uint32_t last_1w_activity_ms, uint32_t now, uint32_t quiet_ms, uint32_t max_defer_ms)
Decide whether to hold back a queued background poll because a 1W remote is still transmitting.
RainSensorState
What the hub's latest minimum-limitation read says about a rain-protection limit.
HeatingFunction
Registers and functions of a 2W heater, one row of the descriptor table each.
FemProfile
Which RF front-end module (if any) sits between the SX1262 and the antenna.
@ NONE
No FEM, or a board with the FEM pins wired but no behaviour profile set – see the NONE-specific note ...
constexpr size_t POSITION_TEXT_BUFFER_SIZE
Buffer for formatted position strings such as "100%".
std::function< void(const std::string &device_id, const IoDevice &device)> DeviceUpdateCallback
Callback type invoked when a device's state changes.
CoverCommand
Named device commands for cover-type actuators.
DeviceType
IO-Homecontrol node types.
std::string format_position(float pos)
Format a position float as a human‑readable string (e.g.
static constexpr uint32_t PAIRING_STALE_PRESS_MS
How long after a pairing attempt ends a Discover & Pair press counts as made during it.
ExchangeOutcome
Authenticated exchange engine — outbound and inbound protocol flows.
@ FAILED
No usable reply; the device may never have heard the request.
std::function< void(const OneWayCommandReport &report)> OneWayCommandReportFn
Invoked once per attempted 1W command, successful or not.
constexpr uint8_t DEFAULT_TCXO_VOLTAGE_SETTING_1P8V
0-based TCXO voltage code for 1.8 V, passed verbatim to the SX1262/LR1121 chip.
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.
void clear_moving_evidence(IoDevice &dev)
Forget that a device was travelling: it reported itself stopped (including in the ack to a STOP),...
constexpr uint8_t DEFAULT_PA_PIN_PA_BOOST
SX1276 PA_CONFIG selector for the PA_BOOST output path.
constexpr uint8_t DEFAULT_TX_POWER_DBM
Default TX power used unless YAML overrides it.
Controller identities for the one-way (1W) protocol.
Opt-in, receive-only adoption of a 1W installation's controller key.
One-way (1W) transmit collaborator.
Pending-operation queue with per-type coalescing and deduplication.
Device discovery and key-exchange engine for IO-Homecontrol pairing.
Device-name, address-classification and 1W-frame codecs.
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
Pure codec for the private register protocol of 2W heaters (CMD_WRITE_PRIVATE 0x20).
Heating profiles: what a climate card offers for each kind of heater, and how.
Radio abstraction layer for IO-Homecontrol.
Schedule and failure bookkeeping for the opt-in rain sensor poll.
Per-device poll scheduling, failure backoff, and follow-up-poll state machine.
YAML-declared device metadata for registration; defaults match an undeclared device.
A functional parameter and its value.
Everything one execute-family operation needs beyond its own guard and frame builder.
const char * action
Verb/phrase for the "Sending ..." and rejection logs.
bool settle_as_stop
Passed through to arm_execute_confirmation_poll_().
Per-request knobs of exchange_and_record_().
uint8_t max_tries
Transmit-attempt cap forwarded to send_and_receive_().
uint32_t retry_after_fail_ms
If non-zero, drives the status-poll backoff and failure streaks.
bool warn_on_no_response
Log a warning when no response arrives.
Runtime state of a paired IO‑Homecontrol device.
bool has_system_key
YAML-declared (system_key:): this device keeps a key of its own.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
Result of a hub-level management action such as rename.
How a OneWayButtonAction reaches the wire.
bool is_position
True when the action is sent as a numeric position.
uint8_t position
Position to send when is_position.
CoverCommand command
Named command to send otherwise.
One configured 1W controller identity.
Decoded representation of a 1W remote frame.
PendingOperationType type
Operation type (determines which handler to invoke).
A 1W pairing-gesture frame observed on the hub's normal passive RX path, remembered so a fresh discov...
All runtime tunable parameters for pairing and radio diagnostics.
Key fields of the last processed 1W frame, used to collapse a remote's repeat burst.
Runtime tuning configuration for pairing and radio diagnostics.