|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
The main IO-Homecontrol component. More...
#include <hub_core.h>
Classes | |
| struct | RequestOptions |
| Per-request knobs of exchange_and_record_(). More... | |
| struct | ExecuteRequestSpec |
| Everything one execute-family operation needs beyond its own guard and frame builder. More... | |
Public Types | |
| using | ManagementActionResult = esphome::home_io_control::ManagementActionResult |
| Result payload used by hub-level management actions such as rename. | |
Public Member Functions | |
| IOHomeControlComponent () | |
| Initialize ExchangeEngine, PairingEngine, and ManagementActions with double-pointer/ reference indirection so that test assignments (comp.radio_ = &mock) propagate through all collaborators without calling setup(). | |
| void | setup () override |
| Initialize hardware (radio and device registry). | |
| void | loop () override |
| Main loop: process pending operations and drive radio state machine. | |
| void | dump_config () override |
| Dump configuration and radio debug info to the log. | |
| float | get_setup_priority () const override |
| Get setup priority (HARDWARE to initialize early). | |
| void | spi_enable () override |
| Enable the SPI bus. | |
| void | spi_disable () override |
| Disable the SPI bus. | |
| uint8_t | spi_transfer (uint8_t data) override |
| Transfer one byte full‑duplex. | |
| void | spi_write (uint8_t data) override |
| Write one byte (MOSI only). | |
| uint8_t | spi_read () override |
| Read one byte (MISO only). | |
| void | set_radio_test_mode (bool active) |
| Suspend the hub's normal loop (packet processing, hopping, polling). | |
| RadioDriver * | get_radio () const |
| Get the underlying radio driver (for diagnostics and test tooling). | |
| void | set_rst_pin (InternalGPIOPin *pin) |
| Set the radio reset pin. | |
| void | set_dio0_pin (InternalGPIOPin *pin) |
| Set the DIO0 interrupt pin (SX1276). | |
| void | set_dio4_pin (InternalGPIOPin *pin) |
| Set the DIO4 preamble‑detect pin (SX1276, optional). | |
| void | set_dio1_pin (InternalGPIOPin *pin) |
| Set the DIO1 interrupt pin (SX1262; also carries the LR1121's DIO9 IRQ line). | |
| void | set_busy_pin (InternalGPIOPin *pin) |
| Set the BUSY pin (SX1262/LR1121). | |
| void | set_fem_en_pin (InternalGPIOPin *pin) |
| Set the front‑end module enable pin. | |
| void | set_vfem_pin (InternalGPIOPin *pin) |
| Set the VFEM power pin. | |
| void | set_fem_pa_pin (InternalGPIOPin *pin) |
| Set the FEM PA switch pin. | |
| 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 that pin per-transmission (GC1109/KCT8103L/XY16P35) or leaves it static-HIGH (NONE, the legacy raw-pin behaviour). | |
| void | set_node_id (const std::string &id) |
| Set the controller's node ID (hex string). | |
| void | set_system_key (const std::string &key) |
| Set the system key (hex string). | |
| void | set_tx_power (uint8_t power) |
| Set transmit power (dBm). | |
| void | set_pa_pin (uint8_t pa_pin) |
| Set PA boost pin configuration. | |
| void | set_radio_type (const std::string &type) |
| Set radio type ("sx1276", "sx1262", or "lr1121"); required by the YAML schema. | |
| void | set_tcxo_voltage (uint8_t voltage) |
| Set the SX1262/LR1121 TCXO control-voltage code (0-based, TCXO_VOLTAGE_OPTIONS in hub_validators.py: 1_6V=0x00 . | |
| void | set_tuning_config (const TuningConfig &config) |
| Apply the tuning configuration generated from YAML / UI entities. | |
| void | update_tuning_number (const std::string &name, float value) |
| Receive a numeric tuning update from a HA number entity. | |
| void | update_tuning_select (const std::string &name, const std::string &value) |
| Receive a select tuning update from a HA select entity. | |
| 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. | |
| 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. | |
| 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 | 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. | |
| void | add_linked_remote_class (DeviceType type, const std::string &device_id) |
| Declare that a device class's typed 1W broadcasts (e.g. | |
| 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. | |
| virtual bool | apply_optimistic_stop (const std::string &device_id) |
| Predict that a device has stopped (e.g. | |
| 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. | |
| 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 to Home Assistant. | |
| void | add_oneway_controller (const OneWayControllerIdentity &identity) |
| Register a configured 1W controller identity (see oneway_controller.h). | |
| const OneWayControllerRegistry & | oneway_controllers () const |
| void | send_oneway_command (const std::string &controller_id, CoverCommand cmd) |
| Queue a 1W named command, sent as the given controller identity. | |
| void | send_oneway_position (const std::string &controller_id, uint8_t position) |
| Queue a 1W numeric position, sent as the given controller identity. | |
| void | send_oneway_action (const std::string &controller_id, OneWayButtonAction action) |
| Queue whichever of position/command a generated button's action resolves to. | |
| void | send_oneway_enroll (const std::string &controller_id) |
| Queue a 1W enrollment for the given controller identity — the enroll button's press handler. | |
| void | send_oneway_unenroll (const std::string &controller_id) |
| Queue a standalone 1W un-enrollment (remove-controller) for the given controller identity, reached only through the explicitly-named oneway_remove_controller native API action — the same 0x39 send_oneway_enroll() also fires as its own prelude, but here alone. | |
| void | add_oneway_command_report_callback (OneWayCommandReportFn callback) |
| Subscribe to the report emitted after every 1W command attempt. | |
| OneWayTransmitter & | oneway_transmitter () |
| const PairingTelemetry & | pairing_telemetry () const |
| void | set_pairing_result_callback (std::function< void()> cb) |
| Register a callback invoked once, right after every discover_and_pair() attempt completes — used by the "Last Pairing Result" text sensor to publish a fresh value. | |
| virtual void | set_key_extraction_armed (bool armed) |
| Arm or disarm the "Recover System Key" (key extraction) responder. | |
| void | set_key_extraction_armed_callback (std::function< void(bool)> cb) |
| Register a callback invoked whenever the key-extraction armed state changes — manual toggle, successful extraction, or auto-off timeout — so the switch entity can keep its displayed state in sync when the hub disarms itself rather than the user. | |
| virtual void | set_oneway_key_adoption_armed (bool armed) |
| Arm or disarm the 1W controller-key adoption listener. | |
| 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, successful adoption, or auto-off timeout — so the switch entity stays in sync when the hub disarms itself rather than the user. | |
| bool | oneway_key_adoption_armed () const |
| Whether the 1W key-adoption listener is currently armed. | |
| void | set_diagnostic_probes_enabled (bool enabled) |
| Set whether ManagementActions::probe_device()/probe_sweep() are allowed to run. | |
| bool | diagnostic_probes_enabled () const |
| Whether diagnostic probes are enabled for this build. | |
| virtual void | add_device (const std::string &device_id) |
| Add a device to the registry by device ID only (undeclared/legacy path). | |
| virtual void | add_device (const std::string &device_id, const DeviceConfig &cfg) |
| Add a device to the registry with full metadata from a YAML declaration. | |
| virtual IoDevice * | get_device (const std::string &device_id) |
| Retrieve a device by ID; returns nullptr if not found. | |
| virtual void | set_device_dimmable (const std::string &device_id, bool dimmable) |
| Set a device's dimmable flag (see IoDevice::dimmable). | |
| virtual void | set_device_silent (const std::string &device_id, bool silent) |
| Select a device's travel profile at runtime (see IOHomeCoverSilentSwitch). | |
| virtual void | register_device_callback (DeviceUpdateCallback cb) |
| Register a callback invoked when any device updates. | |
| 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. | |
| 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). | |
| virtual bool | set_device_position (const std::string &device_id, uint8_t position) |
| Send a position command to a device. | |
| virtual bool | set_device_tilt (const std::string &device_id, uint8_t tilt_percent) |
| Send a tilt command to a tilt‑capable cover. | |
| 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. | |
| virtual bool | request_device_status (const std::string &device_id) |
| Request current status from a device. | |
| 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. | |
| virtual bool | request_device_name (const std::string &device_id) |
| Request the stored device name from a device. | |
| 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. | |
| 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 device ID maps to. | |
| 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. | |
| virtual ManagementActionResult | scan_paired_devices () |
| Broadcast a roll-call and report every device that answers (see ManagementActions::scan_paired_devices() for the full contract: only key-holding devices answer, DeviceRegistry is never written, and zero replies is a successful result). | |
| 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 ManagementActions::probe_device() for the full contract, argument formats, and safety gating). | |
| 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()). | |
| 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 — the heating_control hub action. | |
| virtual bool | discover_and_pair () |
| Discover and pair a device that is in pairing mode. | |
| virtual bool | set_light_position (const std::string &device_id, uint8_t position) |
| Send an arbitrary IO position (0-100) to a light entity. | |
| 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. | |
| virtual bool | set_light_state (const std::string &device_id, bool on) |
| Semantic binary helper for light entities. | |
| virtual bool | set_switch_state (const std::string &device_id, bool on) |
| Semantic binary helper for switch entities. | |
| virtual bool | set_lock_state (const std::string &device_id, bool locked) |
| Semantic lock helper for lock entities. | |
| 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 for a settable register, a read for a read-only one (power_on, midnight_sync). | |
| 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). | |
| 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 temperature interface and the heat pump). | |
| 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 min_temperature: / max_temperature:). | |
| 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. | |
| 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 bool | queue_device_command (const std::string &device_id, CoverCommand cmd) |
| Queue an async named command (STOP, FAVORITE, VENT, FORCE_OPEN); returns immediately, executed in loop(). | |
| 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(). | |
| 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(). | |
| virtual void | queue_request_device_status (const std::string &device_id) |
| Queue an async status 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 operation (yields to commands and 1W activity). | |
| 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_discover_and_pair () |
| Queue a pairing operation; executed in loop() when radio idle. | |
| void | trigger_scan_paired_devices () |
| Entry point for the "Scan Paired Devices" button: run the roll-call and publish its report to the log and the Home Assistant result event, exactly as the native API action does. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| 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. | |
| Public Member Functions inherited from esphome::home_io_control::SpiAccess | |
| virtual | ~SpiAccess ()=default |
Protected Types | |
| enum class | RequestResult : uint8_t { FAILED , UNCONFIRMED , ERROR_REPLY , REPLY } |
| What exchange_and_record_() found. More... | |
Protected Member Functions | |
| bool | transmit_frame_ (const IoFrame &frame, uint32_t freq, uint16_t preamble) |
| Transmit a raw IoFrame on the current frequency with given preamble length. | |
| 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. | |
| bool | authenticate_request_ (const IoFrame &request, uint32_t freq) |
| Handle an inbound authenticated command from a device (status updates, etc.). | |
| void | process_received_packet_ (const RadioRxPacket &packet) |
| Parse a received frame, merge supported device state or metadata, and notify callbacks. | |
| bool | key_extraction_awaiting_reply_ () const |
| True while the key-extraction responder is mid-attempt and still within its bounded CH2-hold window. | |
| 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 | 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_activity_ms_ and — when this frame starts a new burst (see decisions::oneway_burst_started_fresh()) — first_1w_activity_ms_. | |
| 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()), remember it (src/dst/cmd plus the radio's last-capture RSSI) in recent_oneway_pairing_sighting_ so a fresh discover_and_pair() attempt can seed its telemetry with it — see RecentOneWayPairingSighting's doc comment (issue #27/#65). | |
| 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 | schedule_heating_poll_ (const std::string &device_id, uint32_t delay_ms) |
| Arm the heater's regular-cadence poll timer. | |
| 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 | 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 position (see update_device_status_()'s trust_position parameter) and therefore leaves the hub with no idea where the device actually is. | |
| 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, and by schedule_linked_remote_polls_()). | |
| bool | defer_background_poll_ () const |
| Whether loop() should skip dispatching the queue this iteration because the pending work is a background poll and either a 1W remote transmitted very recently, or a key-extraction attempt is mid-flight. | |
| 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. | |
| 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, plus — when the frame targets a typed broadcast (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 resolvable intent. | |
| 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. | |
| 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, stamp link health, and schedule the poll backoff. | |
| 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. | |
| 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 outcome: exchange-outcome and timeout counters, link health, challenge-seen handling, CMD_ERROR_RESP handling, debug logs and (when requested) the status-poll backoff. | |
| 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_status_() on a reply. | |
| 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 (the command will not reach the device), withdraws the optimistic prediction the entity applied at control() time via DeviceRegistry::rollback_optimistic(). | |
| 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, position+tilt): device lookup + initialized guard, capability guard, poll-tracking start, "Sending ..." log, frame build, exchange, failure backoff, and the settle poll. | |
| 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. | |
| template<typename F> | |
| void | execute_oneway_ (F &&send) |
| Shared bookkeeping for every 1W transmit: mark the radio busy for the duration of send, then record it as 1W activity so background polls back off for it exactly as they do for a remote's burst — the radio is equally busy either way. | |
| void | execute_oneway_command_ (const std::string &controller_id, CoverCommand cmd) |
| Send a queued 1W named command. | |
| void | execute_oneway_position_ (const std::string &controller_id, uint8_t position) |
| Send a queued 1W numeric position. | |
| void | execute_oneway_enroll_ (const std::string &controller_id) |
| Send a queued 1W enrollment (add-controller). | |
| void | execute_oneway_unenroll_ (const std::string &controller_id) |
| Send a queued 1W un-enrollment (remove-controller). | |
| void | notify_device_update_ (const std::string &id) |
| Fire all registered device update callbacks for the given device ID. | |
| 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. | |
| 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 counters, link health, error result code), notify the entities and report whether the device answered with CMD_WRITE_PRIVATE_ACK. | |
| 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 failure), plus its maximum setpoint until that has been read once. | |
| void | process_pending_operation_ () |
| Pop next pending operation from the queue and execute it (set position, request status, discover). | |
| void | log_exchange_debug_ (const char *device_id) const |
| Log the last exchange debug snapshot (delegates to exchange_engine_). | |
| void | log_exchange_unconfirmed_debug_ (const char *device_id) const |
| Log the last exchange debug snapshot for an accepted-but-unconfirmed exchange, at INFO. | |
| void | apply_tuning_to_radio_ () |
| Apply the current tuning configuration to the active radio driver. | |
| void | resolve_start_preamble_default_ () |
| Resolve normal_start_preamble from the driver when YAML did not set it (ADR 0042). | |
| void | register_management_actions_ () |
| Register hub-level Home Assistant actions; called from setup(). | |
| void | api_rename_device_ (const std::string &device_id, const std::string &new_name) |
| Native API callback: rename a registered device. | |
| void | api_identify_device_ (const std::string &device_id) |
| Native API callback: trigger a registered device's physical identify. | |
| void | api_force_open_device_ (const std::string &device_id) |
| Native API callback: force-open a registered cover device. | |
| void | api_scan_paired_devices_ () |
| Native API callback: broadcast a roll-call scan of already-paired devices. | |
| 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. | |
| void | api_oneway_remove_controller_ (const std::string &controller_id) |
| Native API callback: queue a 1W un-enrollment (remove-controller) for a controller identity. | |
| 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 | 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 | 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 climate device. | |
| void | hop_frequency_ () |
| Delegate channel hop to ExchangeEngine (which owns last_hop_us_). | |
| RadioDriver * | select_and_construct_radio_ (const char **chip_name_out) |
| Select and construct the radio driver named by the required radio_type config field. | |
| void | dump_oneway_controllers_config_ () const |
| Emit the 1W controller identities to the config dump — node, class, and the resolved ACEI / broadcast (ADR 0031). | |
Protected Attributes | |
| RadioDriver * | radio_ {nullptr} |
| InternalGPIOPin * | rst_pin_ {nullptr} |
| InternalGPIOPin * | dio0_pin_ {nullptr} |
| SX1276 DIO0 interrupt. | |
| InternalGPIOPin * | dio4_pin_ {nullptr} |
| SX1276 DIO4 preamble detect (optional). | |
| InternalGPIOPin * | dio1_pin_ {nullptr} |
| SX1262 DIO1 interrupt; also carries the LR1121's DIO9 IRQ line. | |
| InternalGPIOPin * | busy_pin_ {nullptr} |
| SX1262/LR1121 BUSY pin. | |
| InternalGPIOPin * | fem_en_pin_ {nullptr} |
| Front-end module enable. | |
| InternalGPIOPin * | vfem_pin_ {nullptr} |
| Front-end module power. | |
| InternalGPIOPin * | fem_pa_pin_ {nullptr} |
| Front-end module PA switch. | |
| FemProfile | fem_profile_ {FemProfile::NONE} |
| Which FEM part fem_pa_pin_ belongs to, if any. | |
| std::string | node_id_str_ |
| std::string | system_key_str_ |
| std::string | radio_type_ |
| "sx1276", "sx1262", or "lr1121"; required by the YAML schema. | |
| std::string | radio_failure_reason_ |
| Why setup() gave up on the radio, or empty. | |
| uint8_t | node_id_ [NODE_ID_SIZE] {} |
| uint8_t | system_key_ [AES_KEY_SIZE] {} |
| uint8_t | tx_power_ {DEFAULT_TX_POWER_DBM} |
| uint8_t | pa_pin_ {DEFAULT_PA_PIN_PA_BOOST} |
| uint8_t | tcxo_voltage_ {DEFAULT_TCXO_VOLTAGE_SETTING_1P8V} |
| SX1262/LR1121 TCXO voltage setting (default 1.8 V). | |
| bool | initialized_ {false} |
| bool | busy_ {false} |
| uint32_t | last_pairing_end_ms_ {0} |
| millis() when the last pairing attempt ended; 0 before the first one (see queue_discover_and_pair()). | |
| bool | radio_test_mode_ {false} |
| When true, loop() is suspended for loopback testing. | |
| TuningConfig | tuning_ {} |
| Runtime tuning overrides. | |
| DeviceRegistry | registry_ |
| std::vector< std::string > | exposed_senders_ |
| 1W sender node IDs (remotes or sensors) allowed to fire the sender HA event (add_exposed_sender). | |
| std::function< void()> | pairing_result_callback_ |
| Invoked once after every pairing attempt completes; see set_pairing_result_callback(). | |
| bool | diagnostic_probes_enabled_ {false} |
| Whether diagnostic probes (ManagementActions::probe_device()/probe_sweep()) are enabled. | |
| StatusPollPolicy | poll_policy_ |
| RainPollPolicy | rain_poll_policy_ |
| Schedule of the opt-in rain sensor poll. | |
| OperationQueue | op_queue_ |
| PairingTelemetry | pairing_telemetry_ |
| Per-attempt pairing telemetry. | |
| RecentOneWayPairingSighting | recent_oneway_pairing_sighting_ {} |
| Most recent 1W pairing-gesture frame seen on the hub's normal passive RX path (e.g. | |
| ExchangeEngine | exchange_engine_ |
| Owns all authenticated exchange and LBT/hop logic. | |
| PairingEngine | pairing_engine_ |
| Owns the three-phase device pairing flow. | |
| ManagementActions | management_actions_ |
| Owns rename, identify, force-open, scan_paired_devices, and other hub-level HA actions. | |
| OneWayTransmitter | oneway_transmitter_ |
| Owns the 1W controller identities, their rolling-sequence counters and the transmit burst. | |
| OnewayKeyAdoption | oneway_key_adoption_ |
| Opt-in, receive-only 1W controller-key adoption listener (oneway_key_adoption.cpp). | |
| KeyExtractionResponder | key_extraction_ |
| Device-role responder for the "Recover System Key" feature (key_extraction_responder.cpp). | |
| std::vector< OneWayCommandReportFn > | oneway_report_callbacks_ |
| Subscribers to the per-command 1W report; one per "Last 1W Command" sensor. | |
| decisions::OneWayDedupState | last_1w_logged_ {} |
| Identity of the last processed 1W frame, for burst suppression; see decisions::is_duplicate_1w_frame() for why the intent bytes are part of the key. | |
| uint32_t | last_1w_activity_ms_ {0} |
| millis() of the most recent 1W frame of any kind, including ones dropped as duplicates — a repeat still means the remote is transmitting. | |
| uint32_t | first_1w_activity_ms_ {0} |
| millis() of the first 1W frame in the current burst. | |
The main IO-Homecontrol component.
Manages the protocol layer and delegates radio operations to a RadioDriver instance.
Inherits SPIDevice so that ESPHome's Python codegen can configure SPI pins. Implements SpiAccess to provide the radio driver with SPI bus access.
Definition at line 96 of file hub_core.h.
| using esphome::home_io_control::IOHomeControlComponent::ManagementActionResult = esphome::home_io_control::ManagementActionResult |
Result payload used by hub-level management actions such as rename.
Alias of the standalone esphome::home_io_control::ManagementActionResult struct so that callers using the nested name IOHomeControlComponent::ManagementActionResult continue to work.
Definition at line 167 of file hub_core.h.
|
strongprotected |
What exchange_and_record_() found.
| Enumerator | |
|---|---|
| FAILED | No usable reply (silence, or an unconfirmed acceptance of a request that needs a payload). |
| UNCONFIRMED | A CMD_EXECUTE the device accepted but never closed; counted as success, no reply frame. |
| ERROR_REPLY | The device refused with CMD_ERROR_RESP; handle_error_response_() has recorded it. |
| REPLY | The device answered; the caller interprets the reply frame. |
Definition at line 993 of file hub_core.h.
|
inline |
Initialize ExchangeEngine, PairingEngine, and ManagementActions with double-pointer/ reference indirection so that test assignments (comp.radio_ = &mock) propagate through all collaborators without calling setup().
Definition at line 105 of file hub_core.h.
|
virtual |
Add a device to the registry by device ID only (undeclared/legacy path).
Type, subtype, inverted, and optimistic_state default to UNKNOWN / 0 / false / true; use the DeviceConfig overload when metadata comes from a YAML declaration.
| device_id | Hexadecimal node ID string. |
Definition at line 344 of file hub_core.cpp.
|
virtual |
Add a device to the registry with full metadata from a YAML declaration.
| device_id | Hexadecimal node ID string. |
| cfg | Device type/subtype/inversion/optimistic-state metadata. |
Definition at line 346 of file hub_core.cpp.
|
inline |
Allow a 1W sender (identified by its node ID) to fire the esphome.home_io_control_sender_event event to Home Assistant.
"Sender" is deliberately broader than "remote": the same 1W broadcast mechanism carries handheld/wall remotes and wind/rain sensors alike (they differ only in the originator byte inside the payload, not in how they address the radio) — see decode_1w_frame(). Overheard 1W traffic is always DEBUG-logged regardless of this list; this only controls which senders are allowed to reach Home Assistant as an event, independent of whether the sender is also linked to a device via add_linked_remote. Empty by default — a sender must be explicitly opted in.
| sender_id | Node ID of the 1W sender (remote or sensor). |
Definition at line 323 of file hub_core.h.
|
inline |
Declare that a remote (identified by its node ID) controls a registered device.
When activity from this remote is overheard, a status poll is scheduled for the device. This is needed for 1W remotes whose destination address differs from the device's 2W ID.
| remote_id | Node ID of the remote control. |
| device_id | Node ID of the device it controls. |
Definition at line 266 of file hub_core.h.
|
inline |
Declare that a device class's typed 1W broadcasts (e.g.
"all awnings") also apply to device_id, matching how 1W remotes address a device class rather than a single node.
| type | Device class the broadcast targets. |
| device_id | Node ID of the device to add to that class. |
Definition at line 274 of file hub_core.h.
|
inline |
Subscribe to the report emitted after every 1W command attempt.
A list rather than a single slot: each identity gets its own "Last 1W Command" sensor, and each filters the reports down to its own handle.
| callback | Invoked for every attempt, successful or not. |
Definition at line 401 of file hub_core.h.
|
inline |
Register a configured 1W controller identity (see oneway_controller.h).
Called once per oneway_controllers: entry from generated code. Both the source address and the key are already resolved at schema time — a derived address is computed there so a collision with the hub's own address or another identity fails the build rather than silently desyncing a transmitter at runtime.
| identity | Fully-resolved controller identity. |
Definition at line 331 of file hub_core.h.
|
inlineprotected |
Native API callback: force-open a registered cover device.
Definition at line 1154 of file hub_core.h.
|
inlineprotected |
Native API callback: run a heating/climate function (CMD_WRITE_PRIVATE 0x20) against a registered climate device.
Definition at line 1178 of file hub_core.h.
|
inlineprotected |
Native API callback: trigger a registered device's physical identify.
Definition at line 1152 of file hub_core.h.
|
inlineprotected |
Native API callback: queue a 1W un-enrollment (remove-controller) for a controller identity.
Definition at line 1164 of file hub_core.h.
|
inlineprotected |
Native API callback: queue a 1W position for a controller identity.
Definition at line 1160 of file hub_core.h.
|
inlineprotected |
Native API callback: run a single diagnostic probe against a registered device.
Definition at line 1168 of file hub_core.h.
|
inlineprotected |
Native API callback: run a bounded diagnostic probe sweep against a registered device.
Definition at line 1172 of file hub_core.h.
|
inlineprotected |
Native API callback: rename a registered device.
Definition at line 1148 of file hub_core.h.
|
inlineprotected |
Native API callback: broadcast a roll-call scan of already-paired devices.
Definition at line 1158 of file hub_core.h.
|
protected |
Apply optimistic target state to every device in device_ids, when the decoded frame carries a resolvable intent.
Skips devices whose known type doesn't match the frame's typed-broadcast target (an "all awnings" press must not optimistically move a linked shutter — it is still polled by schedule_device_polls_()). No-op per device when that device has optimistic_state == false (see DeviceRegistry::apply_optimistic_target()).
| info | Already-decoded 1W frame info (see decode_1w_frame()). |
| device_ids | Devices to apply optimistic state to (see resolve_1w_target_devices_()). |
Definition at line 359 of file hub_status.cpp.
|
inlinevirtual |
Predict that a device has stopped (e.g.
on STOP), and notify. No-op when the device is unknown or has optimistic_state == false. See DeviceRegistry::apply_optimistic_stop() for why this records a prediction rather than a clear. Restorable: if the STOP then fails, the movement prediction it replaced comes back. Virtual (like add_device/get_device) so platform unit tests can substitute a mock registry.
| device_id | Target device ID. |
Definition at line 296 of file hub_core.h.
|
inlinevirtual |
Set an optimistic target position ahead of a confirming poll/response, and notify.
No-op when the device is unknown or has optimistic_state == false. See DeviceRegistry::apply_optimistic_target() for the full contract. Virtual (like add_device/get_device) so platform unit tests can substitute a mock registry.
| device_id | Target device ID. |
| target_io_position | Target position in IO units (0=open, 100=closed). |
Definition at line 285 of file hub_core.h.
|
inlinevirtual |
Set an optimistic slat angle ahead of a confirming status poll, and notify.
No-op when the device is unknown, has optimistic_state == false, or is not tilt-capable. See DeviceRegistry::apply_optimistic_tilt() for the full contract and for why a tilt command cannot rely on its own reply the way a position command can. Virtual like the other device-registry accessors so a test double can override it if it needs to; MockPlatformHubBase deliberately does not, and exercises the real registry.
| device_id | Target device ID. |
| tilt_percent | Slat angle in the same percent scale as IoDevice::tilt (0-100). |
Definition at line 310 of file hub_core.h.
|
protected |
Fold one rain poll outcome into the device's rain sensor state and tell subscribers.
| device_id | Target device ID. |
| reading | DRY or RAIN for an answered poll, UNKNOWN for a miss. |
| limit_text | Rendering of the reported limit for the state-change log, empty for a miss. |
Definition at line 528 of file hub_operations.cpp.
|
protected |
Apply the current tuning configuration to the active radio driver.
Only chip-specific parameters are forwarded; the rest are consumed by the pairing flow and LBT logic. This is called once at the end of setup() and again whenever a UI-driven change modifies a radio parameter.
Definition at line 207 of file hub_core.cpp.
|
protected |
Arm the confirming poll that follows a command, because a CMD_EXECUTE reply is never trusted for position (see update_device_status_()'s trust_position parameter) and therefore leaves the hub with no idea where the device actually is.
Re-arms the bounded tracking window rather than only setting a due time: the same untrusted reply clears that window whenever it claims the device is stopped, and pop_due_device() discards a due poll that has no active window. An already-scheduled earlier poll wins.
| device_id | Device the command was sent to. |
| for_stop | True for STOP (and position POS_STOP), which settles under STOP_SETTLE_POLL_CAP_MS instead of the normal settle cadence. |
Definition at line 149 of file hub_operations.cpp.
|
protected |
Handle an inbound authenticated command from a device (status updates, etc.).
Delegate inbound authentication to ExchangeEngine.
| request | Inbound authenticated request (e.g., CMD_STATUS_UPDATE). |
| freq | RF frequency the packet arrived on. |
Definition at line 312 of file hub_core.cpp.
|
protected |
Begin bounded follow-up polling for a device after a command or overheard remote activity.
| device_id | ID of the device to poll. |
| initial_delay_ms | Delay before the first follow-up poll. |
Definition at line 301 of file hub_status.cpp.
|
inlinenodiscardprotected |
Whether loop() should skip dispatching the queue this iteration because the pending work is a background poll and either a 1W remote transmitted very recently, or a key-extraction attempt is mid-flight.
Thin wrapper binding the component's state to decisions::defer_background_poll_for_1w_activity(), plus a second, independent yield condition: a background poll is a blocking exchange that owns the radio for 1-3 s, and dispatching one while the key-extraction responder is holding CH2 for an expected CMD_KEY_TRANSFER (0x32) would swallow it just as thoroughly as a mistimed hop — see loop()'s hop branch (hub_core.cpp) for the other half of that hold. Only background polls yield here, same as the 1W rule: a user command must never wait on either kind of background activity.
Definition at line 934 of file hub_core.h.
|
nodiscard |
Render a device's "last commanded by" string, resolving this hub's own node ID.
Thin wrapper over detail::describe_last_commander() (entity_helpers.h); exists because the hub's node ID is not reachable from a companion entity.
| dev | Device record to read. |
Definition at line 961 of file hub_operations.cpp.
|
inlinenodiscard |
Whether diagnostic probes are enabled for this build.
Definition at line 472 of file hub_core.h.
|
virtual |
Discover and pair a device that is in pairing mode.
Discover and pair a device in pairing mode.
The hub wrapper manages the busy_ flag so loop() stops hopping and polling while the blocking pairing exchange is in progress. All protocol logic is in PairingEngine::discover_and_pair().
Definition at line 22 of file hub_pairing.cpp.
|
override |
Dump configuration and radio debug info to the log.
Definition at line 434 of file hub_core.cpp.
|
protected |
Emit the 1W controller identities to the config dump — node, class, and the resolved ACEI / broadcast (ADR 0031).
Factored out of dump_config() to keep its cognitive complexity under the clang-tidy threshold.
Definition at line 496 of file hub_core.cpp.
|
protected |
Run one authenticated request/response exchange on the standard command channel and record its outcome: exchange-outcome and timeout counters, link health, challenge-seen handling, CMD_ERROR_RESP handling, debug logs and (when requested) the status-poll backoff.
It does not interpret a reply — callers decide what a REPLY means.
| device_id | Target device ID. | |
| request | Outbound request frame. | |
| [out] | response | The device's reply, valid for RequestResult::REPLY and ERROR_REPLY. |
| options | See RequestOptions. |
Definition at line 161 of file hub_operations.cpp.
|
protected |
The exchange every heating frame shares: send on the command channel, record the outcome (exchange counters, link health, error result code), notify the entities and report whether the device answered with CMD_WRITE_PRIVATE_ACK.
| device_id | Target device ID. | |
| label | What was sent, for the log ("set_temperature", "read room_temperature"). | |
| request | The framed CMD_WRITE_PRIVATE request. | |
| [out] | response | The device's reply; valid when true is returned. |
| max_tries | Transmit-attempt cap forwarded to send_and_receive_(). |
Definition at line 664 of file hub_operations.cpp.
|
protected |
Execute a named device command (STOP, FAVORITE, VENT, FORCE_OPEN) via the authenticated exchange.
| device_id | Target device ID. |
| cmd | Named command to execute. |
Definition at line 373 of file hub_operations.cpp.
|
inlineprotected |
Shared bookkeeping for every 1W transmit: mark the radio busy for the duration of send, then record it as 1W activity so background polls back off for it exactly as they do for a remote's burst — the radio is equally busy either way.
Every 1W execute must go through this; a future one that skips it would compile, pass, and silently break poll-deferral.
| send | Callable that performs the actual transmit; takes no arguments. |
Definition at line 1077 of file hub_core.h.
|
protected |
Send a queued 1W named command.
Unlike its 2W sibling this returns nothing: there is no acknowledgement to report, and success here would only mean "bytes left the radio".
| controller_id | Controller-identity handle. |
| cmd | Named command to send. |
Definition at line 1010 of file hub_operations.cpp.
|
protected |
Send a queued 1W enrollment (add-controller).
See execute_oneway_command_().
| controller_id | Controller-identity handle. |
Definition at line 1018 of file hub_operations.cpp.
|
protected |
Send a queued 1W numeric position.
See execute_oneway_command_().
| controller_id | Controller-identity handle. |
| position | Target position 0–100. |
Definition at line 1014 of file hub_operations.cpp.
|
protected |
Send a queued 1W un-enrollment (remove-controller).
See execute_oneway_command_().
| controller_id | Controller-identity handle. |
Definition at line 1022 of file hub_operations.cpp.
|
protected |
Shared request/response helper for high-level operations: exchange_and_record_() plus update_device_status_() on a reply.
| device_id | Target device ID. |
| request | Outbound request frame. |
| warn_on_no_response | If true, logs a warning when no response is received. |
| retry_after_fail_ms | If non-zero, schedules next status poll after this delay on failure. |
| max_tries | Transmit-attempt cap, forwarded to send_and_receive_(). Defaults to the full EXCHANGE_RETRY_COUNT; a scheduler-owned poll passes SCHEDULED_POLL_MAX_TRIES. |
Definition at line 248 of file hub_operations.cpp.
|
inlinevirtual |
Move a cover device to fully open at elevated priority, intended to bypass wind/rain soft locks.
Safety-sensitive: queues CoverCommand::FORCE_OPEN through the normal cover-command dispatch path. Only confirms the command was queued; the movement outcome arrives later via the device's normal cover-state/polling pipeline, so verified is always false. The lock-bypass behavior itself is experimental and unconfirmed against an active lock — see ManagementActions::force_open_device()'s doxygen for details.
| device_id | Target device ID. |
Definition at line 571 of file hub_core.h.
|
virtual |
Retrieve a device by ID; returns nullptr if not found.
| device_id | Hexadecimal node ID. |
Definition at line 350 of file hub_core.cpp.
|
inlinenodiscard |
Get the underlying radio driver (for diagnostics and test tooling).
Definition at line 200 of file hub_core.h.
|
inlinenodiscardoverride |
Get setup priority (HARDWARE to initialize early).
Definition at line 177 of file hub_core.h.
|
nodiscard |
Current value of a numeric tuning parameter, used to seed a HA number entity on boot.
Return the current value of a numeric tuning parameter.
| name | YAML key of the parameter. |
Mirror of update_tuning_number(); used by IOHomeTuningNumber::setup() to publish the boot-time value so the Home Assistant slider reflects the active configuration (default or YAML override) without restating any default on the Python side.
Definition at line 268 of file hub_core.cpp.
|
nodiscard |
Current option string of a select tuning parameter, used to seed a HA select entity on boot.
Return the current option string of a select tuning parameter.
| name | YAML key of the parameter. |
Mirror of update_tuning_select(); used by IOHomeTuningSelect::setup() to publish the boot-time option so the Home Assistant dropdown reflects the active configuration. The returned strings match the YAML/UI option labels exactly. The command list is returned as a comma-separated preset string (e.g. "0x28,0x2E") matching the dropdown options.
Definition at line 283 of file hub_core.cpp.
|
protected |
Handle an explicit CMD_ERROR_RESP refusal from the device: record the result code, stamp link health, and schedule the poll backoff.
Split out of exchange_and_record_() to keep that function's outcome dispatch readable — a refusal is a distinct concern from "what did the exchange achieve".
| device_id | Target device ID. |
| request | Outbound request frame that drew the refusal. |
| response | The CMD_ERROR_RESP frame. |
| retry_after_fail_ms | If non-zero, schedules next status poll after this delay. |
Definition at line 271 of file hub_operations.cpp.
|
inlinevirtual |
Run one 2W heating/climate function (CMD_WRITE_PRIVATE 0x20) against a registered climate device — the heating_control hub action.
Experimental: the register protocol is unvalidated on real Atlantic/Thermor/Sauter hardware. A write is reported as acknowledged by the device, never as confirmed; the register reads (window_open) put the decoded value into the result message, and power_on / midnight_sync log their ACK payload at DEBUG. See ManagementActions::heating_control() for argument formats.
| device_id | Target device ID. |
| function | Heating function name. |
| value | Function-specific value string. |
Definition at line 615 of file hub_core.h.
|
protected |
Delegate channel hop to ExchangeEngine (which owns last_hop_us_).
Definition at line 295 of file hub_core.cpp.
|
inlinevirtual |
Trigger a device's physical identify (brief jog/flash) so a user can confirm which physical motor a device ID maps to.
| device_id | Target device ID. |
Definition at line 558 of file hub_core.h.
|
inlinenodiscardprotected |
True while the key-extraction responder is mid-attempt and still within its bounded CH2-hold window.
Thin forwarder to KeyExtractionResponder::awaiting_reply() (key_extraction_responder.h) — kept on the hub because defer_background_poll_() and tests/hub/hub_core_test.cpp reach it here, mirroring the two set_key_extraction_armed* bindings.
Definition at line 862 of file hub_core.h.
|
inlineprotected |
Log the last exchange debug snapshot (delegates to exchange_engine_).
Definition at line 1131 of file hub_core.h.
|
inlineprotected |
Log the last exchange debug snapshot for an accepted-but-unconfirmed exchange, at INFO.
Definition at line 1134 of file hub_core.h.
|
override |
Main loop: process pending operations and drive radio state machine.
Definition at line 362 of file hub_core.cpp.
|
protected |
Fire the sender HA event for a decoded 1W frame, if the sender is exposed.
DEBUG-logs the reason when it does not fire (API disconnected / sender not exposed) so a live log capture can distinguish "never reached this check" from "reached it and skipped".
| info | Already-decoded 1W frame info (see decode_1w_frame()). |
| linked | True if the sender is linked to at least one registered device. |
| src_id | Sender's node ID as a string (already computed by the caller). |
Definition at line 390 of file hub_status.cpp.
|
protected |
Fire all registered device update callbacks for the given device ID.
| id | Device ID that updated. |
Definition at line 316 of file hub_core.cpp.
|
inlinenodiscard |
Definition at line 336 of file hub_core.h.
|
inlinenodiscard |
Whether the 1W key-adoption listener is currently armed.
Definition at line 460 of file hub_core.h.
|
inlinenodiscard |
Definition at line 406 of file hub_core.h.
|
inlinenodiscard |
Definition at line 409 of file hub_core.h.
|
protected |
Poll a heater: read its room temperature, setpoint, mode and regulator state (stopping at the first failure), plus its maximum setpoint until that has been read once.
A failure moves the retry onto the StatusPollPolicy ladder; either way the next regular poll is armed one interval out (the device's status_poll_interval, else HEATING_POLL_DEFAULT_INTERVAL_MS). Called from request_device_status() for climate devices.
| device_id | Target device ID. |
Definition at line 801 of file hub_operations.cpp.
|
inlinevirtual |
Send a single diagnostic probe frame to a registered device and report the raw reply (see ManagementActions::probe_device() for the full contract, argument formats, and safety gating).
Protocol-research instrumentation for opcodes this codebase has not decoded — see docs/diagnostic-probes.md and ADR 0024.
| device_id | Target device ID. |
| probe | Probe name ("private_fn", "status_ext", "general_info3", "private2", "private2_short", "status_mp_fp", or "limitation"). |
| index | Function ID / selector block / modifier, as a decimal or 0x-prefixed hex string; ignored for "general_info3" and "status_mp_fp"; 0 (minimum) or 1 (maximum) for "limitation". |
Definition at line 589 of file hub_core.h.
|
inlinevirtual |
Walk a bounded index range, one probe_device() call per index (see ManagementActions::probe_sweep()).
| device_id | Target device ID. |
| probe | Probe name, same as probe_device(). |
| first_index | First index in the sweep (inclusive). |
| last_index | Last index in the sweep (inclusive). |
Definition at line 600 of file hub_core.h.
|
protected |
Pop next pending operation from the queue and execute it (set position, request status, discover).
Definition at line 1026 of file hub_operations.cpp.
|
protected |
Parse a received frame, merge supported device state or metadata, and notify callbacks.
| packet | Raw radio packet containing a parsed IoFrame. |
Definition at line 563 of file hub_status.cpp.
|
virtual |
Queue an async named command (STOP, FAVORITE, VENT, FORCE_OPEN); returns immediately, executed in loop().
Existing entity/button callers (cover, favorite button, vent button) intentionally ignore the return value — they always target a known, already-registered device. It exists so force_open_device() can report enqueue rejection distinctly from a queued-but-not-yet-run command.
| device_id | Target device ID. |
| cmd | Named command to send. |
Definition at line 874 of file hub_operations.cpp.
|
virtual |
Queue a pairing operation; executed in loop() when radio idle.
Queue a discovery-and-pair request with elevated priority.
A press handled within PAIRING_STALE_PRESS_MS of the end of an attempt is dropped with a log line: pairing blocks loop(), so a press made while it ran is only handled once it ends, when the device has usually left its pairing mode.
Flushes any pending status/name poll operations (which would consume time during the device's limited pairing window) and pushes discovery to the front of the queue. Duplicate requests are suppressed.
Definition at line 952 of file hub_operations.cpp.
|
virtual |
Queue an async minimum-limitation read for the rain sensor poll; executed in loop() as a background operation (yields to commands and 1W activity).
| device_id | Target device ID. |
Definition at line 935 of file hub_operations.cpp.
|
virtual |
Queue an async device-name request; returns immediately, executed in loop().
| device_id | Target device ID. |
Definition at line 941 of file hub_operations.cpp.
|
virtual |
Queue an async status request; returns immediately, executed in loop().
| device_id | Target device ID. |
Definition at line 927 of file hub_operations.cpp.
|
virtual |
Queue an async position update; returns immediately, executed in loop().
If a pending SET_TILT operation for the same device is already in the queue, the two are coalesced into a single SET_POSITION_AND_TILT command to avoid two radio exchanges. This transparently handles Home Assistant sending cover.set_cover_position and cover.set_cover_tilt_position as separate rapid calls.
| device_id | Target device ID. |
| position | Desired position (0–100). |
Definition at line 849 of file hub_operations.cpp.
|
virtual |
Queue an async combined position+tilt update; returns immediately, executed in loop().
| device_id | Target device ID. |
| position | Desired position (0–100). |
| tilt_percent | Desired tilt (0–100). |
Definition at line 917 of file hub_operations.cpp.
|
virtual |
Queue an async tilt update; returns immediately, executed in loop().
If a pending SET_POSITION operation for the same device is already in the queue, the two are coalesced into a single SET_POSITION_AND_TILT command to avoid two radio exchanges. This transparently handles Home Assistant sending cover.set_cover_position and cover.set_cover_tilt_position as separate rapid calls.
| device_id | Target device ID. |
| tilt_percent | Desired tilt (0–100). |
Definition at line 894 of file hub_operations.cpp.
|
virtual |
Async form of set_fan_position() that keeps radio work serialized on the main loop.
| device_id | Target device ID. |
| position | Desired IO position (0-100). |
Definition at line 986 of file hub_operations.cpp.
|
virtual |
Async form of set_light_position() that keeps radio work serialized on the main loop.
queue_set_light_state() is a thin binary-position wrapper around this.
| device_id | Target device ID. |
| position | Desired IO position (0-100). |
Definition at line 980 of file hub_operations.cpp.
|
virtual |
Async form of set_light_state() that keeps radio work serialized on the main loop.
| device_id | Target device ID. |
| on | Desired on/off state. |
Definition at line 992 of file hub_operations.cpp.
|
virtual |
Async form of set_lock_state() that keeps radio work serialized on the main loop.
| device_id | Target device ID. |
| locked | Desired locked/unlocked state. |
Definition at line 996 of file hub_operations.cpp.
|
virtual |
Async form of set_switch_state() that keeps radio work serialized on the main loop.
| device_id | Target device ID. |
| on | Desired on/off state. |
Definition at line 1002 of file hub_operations.cpp.
|
virtual |
Read one register of a heater and fold the decoded value into IoDevice::heating.
Same gate, frame builder and exchange bookkeeping as send_heating_command(); a reply that decodes (decode_heating_reply()) updates the device record and notifies the entity callbacks, so what an entity shows is what the heater reported.
| device_id | Target device ID (hex string). | |
| fn | Register to read; must be readable (see heating_function_is_readable()). | |
| [out] | value_out | Decoded value (NaN for a room-temperature sensor fault); pass nullptr when only the stored reading is wanted. |
| max_tries | Transmit-attempt cap: EXCHANGE_RETRY_COUNT for a read the user waits on (the action, the read-back of a write), the scheduled-poll band for the background poll. |
Definition at line 750 of file hub_operations.cpp.
|
protected |
Record that a 1W frame just went out on the radio — ours or someone else's — updating last_1w_activity_ms_ and — when this frame starts a new burst (see decisions::oneway_burst_started_fresh()) — first_1w_activity_ms_.
Called both from process_received_packet_() for an overheard remote's frame and from execute_oneway_command_()/execute_oneway_position_() (hub_operations.cpp) for a frame this hub just transmitted itself. That second case is deliberate, not a misuse of a receive-path hook: our own burst should defer background polls exactly like a remote's does, because it puts the same 1W traffic on the same shared channel the polls would otherwise use, and the devices it targets need the same settling time either way.
| now | millis() at which this frame was seen or sent. |
Definition at line 535 of file hub_status.cpp.
|
protected |
If frame matches a 1W remote's pairing gesture (decisions::is_one_way_pairing_gesture()), remember it (src/dst/cmd plus the radio's last-capture RSSI) in recent_oneway_pairing_sighting_ so a fresh discover_and_pair() attempt can seed its telemetry with it — see RecentOneWayPairingSighting's doc comment (issue #27/#65).
A no-op for any other frame. Called from process_received_packet_()'s 1W-frame path, unconditionally (before the burst-dedup check, like record_1w_activity_()) so a repeated gesture frame still refreshes the timestamp (and RSSI).
| frame | Parsed 1W frame (CTRL0 1W bit already confirmed set by the caller). |
| now | millis() at which this frame was seen. |
Definition at line 544 of file hub_status.cpp.
|
inlinevirtual |
Register a callback invoked when any device updates.
| cb | Callable with signature void(const std::string&, const IoDevice&). |
Definition at line 502 of file hub_core.h.
|
inlineprotected |
Register hub-level Home Assistant actions; called from setup().
Definition at line 1146 of file hub_core.h.
|
inlinevirtual |
Rename a device and verify the result by reading the name back.
| device_id | Target device ID. |
| new_name | Requested UTF-8 device name. |
Definition at line 550 of file hub_core.h.
|
virtual |
Read the device's minimum limitation and derive its rain sensor state from the reply.
Unauthenticated read (CMD_LIMITATION_STATUS_REQ); the reply is accepted only inside this exchange (ADR 0022) and never reaches update_device_status_(), so a poll cannot move the device's position or target. A moving device is not asked: the poll is deferred instead.
| device_id | Target device ID. |
Definition at line 477 of file hub_operations.cpp.
|
virtual |
Request the stored device name from a device.
| device_id | Target device ID. |
Definition at line 550 of file hub_operations.cpp.
|
virtual |
Request current status from a device.
| device_id | Target device ID. |
Definition at line 428 of file hub_operations.cpp.
|
nodiscardprotected |
Resolve the set of devices a 1W frame should affect: devices linked to the sending remote by node ID, plus — when the frame targets a typed broadcast (e.g.
"all awnings") — devices linked to that device class, deduplicated so a device linked both ways is touched once.
| info | Already-decoded 1W frame info (see decode_1w_frame()). |
| src_id | Sender's node ID as a string (already computed by the caller). |
Definition at line 342 of file hub_status.cpp.
|
protected |
Resolve normal_start_preamble from the driver when YAML did not set it (ADR 0042).
Take the directed start preamble from the driver when YAML did not choose one.
Runs once, after the radio exists and before the first transmit. How much preamble a start frame needs depends on what the driver actually puts on air, so the default is the driver's to give (ADR 0042); an explicit normal_start_preamble: always wins, including a shorter value. The resolved value is reported by dump_config(), not from here — see the note in its body.
Definition at line 219 of file hub_core.cpp.
|
protected |
Funnel for the four execute-family operations: runs try_execute_operation_() and, on any false return (the command will not reach the device), withdraws the optimistic prediction the entity applied at control() time via DeviceRegistry::rollback_optimistic().
Wrapping rather than inlining the rollback keeps every current and future failure exit covered by one call.
| device_id | Target device ID. |
| spec | Pre-formatted action phrase and the settle-as-stop flag. |
| accepts | Capability guard; returns false to reject the operation for this device. |
| rejection_profile | Expected-profile label for the rejection log. |
| build | Fills the request frame from the resolved device; returns false on failure. |
Definition at line 293 of file hub_operations.cpp.
|
inlinevirtual |
Broadcast a roll-call and report every device that answers (see ManagementActions::scan_paired_devices() for the full contract: only key-holding devices answer, DeviceRegistry is never written, and zero replies is a successful result).
Definition at line 578 of file hub_core.h.
|
protected |
Apply backoff after a failed background status poll and log the result.
| device_id | Target device ID. |
| auth_like | True when the failed exchange saw a 0x3C challenge. |
Definition at line 332 of file hub_core.cpp.
|
protected |
Schedule status polls for a fixed list of devices (shared by the id-linked and class-linked 1W paths, and by schedule_linked_remote_polls_()).
| device_ids | Devices to poll. |
| delay_ms | Poll delay in milliseconds. |
Definition at line 328 of file hub_status.cpp.
|
protected |
Arm the heater's regular-cadence poll timer.
Own timer id (decisions::heating_poll_timer_id()), so remote-activity polls scheduled by schedule_status_poll_() never replace it.
| device_id | ID of the heater. |
| delay_ms | Delay in milliseconds before the poll is queued. |
Definition at line 320 of file hub_status.cpp.
|
protected |
Schedule status polls for all devices associated with a linked remote.
| remote_id | Source node ID of the remote. |
| delay_ms | Poll delay; default REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS. A STOP intent passes 0 (position settles immediately, no need to wait out the usual travel-time assumption behind the default delay). |
Definition at line 335 of file hub_status.cpp.
|
protected |
Schedule a delayed status poll for a registered device using the Component timeout API.
| device_id | ID of the device to poll. |
| delay_ms | Delay in milliseconds before polling. |
Definition at line 307 of file hub_status.cpp.
|
protected |
Select and construct the radio driver named by the required radio_type config field.
Kept as its own method rather than inlined into setup(): the three-way chip branch (SX1276/SX1262/LR1121) is enough logic on its own that folding it into setup() pushes that function's cognitive complexity past clang-tidy's threshold. Validates the pins each driver needs and logs a clear error (without calling mark_failed() itself — the caller decides how to react) when a required pin is missing. On success, *chip_name_out is set to a static string naming the selected chip (used for logging), and the returned pointer is the heap-allocated (not yet initialized) driver instance.
| chip_name_out | Output: human-readable chip name for logging (always set, even on failure, to the best-known name for error messages). |
Definition at line 154 of file hub_core.cpp.
|
protected |
Main request/response exchange with retry and automatic authentication.
Delegate outbound exchange to ExchangeEngine and manage the busy_ flag.
| request | Outbound request IoFrame. |
| response | Output: received response IoFrame. |
| freq | RF frequency in Hz. |
| max_tries | Transmit-attempt cap, forwarded to ExchangeEngine::send_and_receive(). |
Definition at line 303 of file hub_core.cpp.
|
virtual |
Run one heating function on the heater's private register protocol (CMD_WRITE_PRIVATE 0x20): a write for a settable register, a read for a read-only one (power_on, midnight_sync).
Both the heating_control hub action and the climate entity's writes call this; together with read_heating_register() it is the only place heating frames are built and sent, through one shared exchange helper.
Flow: registry lookup -> device_supports_climate_control() gate (rejected via detail::log_rejected_operation()) -> encode_heating_payload() -> create_write_private() (with the device's low_power flag) -> a plain send_and_receive_(). Deliberately NOT routed through execute_request_and_update_(): that helper is cover/position-shaped (status decode, poll backoff). A CMD_WRITE_PRIVATE_ACK (0x21) reply is success; anything else (including CMD_ERROR_RESP) is failure. The exchange still feeds the device-agnostic Last Contact / Exchange Failures link-health sensors. The ack carries no state: a caller that wants the value the heater now holds reads it back with read_heating_register(). An acknowledged write also moves the heater's next poll to HEATING_POST_WRITE_POLL_DELAY_MS from now, so the regulator state (heating / idle) follows the change.
| device_id | Target device ID (hex string). |
| fn | Heating function to send. |
| value | Function-specific value (degrees C, a HeatingMode as float, 0/1, or ignored) — see encode_heating_payload(). |
Definition at line 714 of file hub_operations.cpp.
|
inline |
Queue whichever of position/command a generated button's action resolves to.
The mapping is applied here, at enqueue time, so the queue only ever holds concrete operations — OPEN and CLOSE are positions on the wire, not commands, and nothing downstream should have to know that twice.
| controller_id | Controller-identity handle from oneway_controllers:. |
| action | Button action to send. |
Definition at line 367 of file hub_core.h.
|
inline |
Queue a 1W named command, sent as the given controller identity.
Goes through the operation queue like every other radio operation (ADR 0013), so a 1W burst can never interleave with a 2W exchange. Unlike a 2W command this reports nothing back: 1W has no reply, so a queued command that a device ignores is indistinguishable from one it obeyed. The "Last 1W Command" diagnostic reports what was transmitted, which is the only half of that the hub can know.
| controller_id | Controller-identity handle from oneway_controllers:. |
| cmd | Named command (STOP, FAVORITE, VENT, FORCE_OPEN). |
Definition at line 349 of file hub_core.h.
|
inline |
Queue a 1W enrollment for the given controller identity — the enroll button's press handler.
Sends 0x39 (self-directed) then 0x30, back to back — see OneWayTransmitter::send_enrollment().
| controller_id | Controller-identity handle from oneway_controllers:. |
Definition at line 382 of file hub_core.h.
|
inline |
Queue a 1W numeric position, sent as the given controller identity.
| controller_id | Controller-identity handle from oneway_controllers:. |
| position | Target position 0–100 (0 = fully open, 100 = fully closed). |
Definition at line 356 of file hub_core.h.
|
inline |
Queue a standalone 1W un-enrollment (remove-controller) for the given controller identity, reached only through the explicitly-named oneway_remove_controller native API action — the same 0x39 send_oneway_enroll() also fires as its own prelude, but here alone.
| controller_id | Controller-identity handle from oneway_controllers:. |
Definition at line 392 of file hub_core.h.
|
inline |
Set the BUSY pin (SX1262/LR1121).
Definition at line 212 of file hub_core.h.
|
virtual |
Set a device's dimmable flag (see IoDevice::dimmable).
Called by platform_light.cpp's setup(), not folded into add_device() since it's a light-only YAML choice. No-op if the device isn't registered.
| device_id | Hexadecimal node ID string. |
| dimmable | New value for IoDevice::dimmable. |
Definition at line 352 of file hub_core.cpp.
|
virtual |
Send a position command to a device.
| device_id | Target device ID. |
| position | Desired position, 0–100 (open→closed). Named commands (STOP, FAVORITE, VENT) go through execute_device_command_()/create_execute_command() instead. |
Definition at line 356 of file hub_operations.cpp.
|
virtual |
Set both position and tilt of a tilt-capable cover in one atomic command.
| device_id | Target device ID. |
| position | Desired position (0–100, open→closed). |
| tilt_percent | Desired tilt (0–100). |
Definition at line 415 of file hub_operations.cpp.
|
virtual |
Opt a registered device into the periodic rain sensor poll (a read of its minimum limitation).
| device_id | Target device ID. |
| interval_ms | Poll interval in milliseconds; zero removes the device from the schedule. |
Definition at line 326 of file hub_core.cpp.
|
virtual |
Select a device's travel profile at runtime (see IOHomeCoverSilentSwitch).
Virtual for the same reason as set_device_dimmable: platform tests substitute a mock registry.
| device_id | Hexadecimal node ID string. |
| silent | True to send position moves in "silent operation" (slower) mode. |
Definition at line 356 of file hub_core.cpp.
|
virtual |
Configure the optional follow-up polling interval for a registered device.
| device_id | Target device ID. |
| poll_interval_ms | Poll interval in milliseconds; zero keeps the legacy one-shot settle poll only. |
Definition at line 320 of file hub_core.cpp.
|
virtual |
Set the temperature encoding range of a heater that carries a temperature in its main parameter (YAML min_temperature: / max_temperature:).
| device_id | Target device ID. |
| min_c | Lower end of the range in degrees Celsius. |
| max_c | Upper end; must exceed min_c. |
Definition at line 656 of file hub_operations.cpp.
|
virtual |
Send a tilt command to a tilt‑capable cover.
| device_id | Target device ID. |
| tilt_percent | Desired tilt (0–100). |
Definition at line 404 of file hub_operations.cpp.
|
inline |
Set whether ManagementActions::probe_device()/probe_sweep() are allowed to run.
Set once from the diagnostic_probes: YAML boolean (__init__.py); off by default, so a build that doesn't opt in never sends an undecoded probe opcode. Not a runtime toggle: there is no entity and nothing else calls this after setup — the gate is "was this build configured with `diagnostic_probes: true`", not a state a user flips per session.
| enabled | Desired state. |
Definition at line 469 of file hub_core.h.
|
inline |
Set the DIO0 interrupt pin (SX1276).
Definition at line 206 of file hub_core.h.
|
inline |
Set the DIO1 interrupt pin (SX1262; also carries the LR1121's DIO9 IRQ line).
Definition at line 210 of file hub_core.h.
|
inline |
Set the DIO4 preamble‑detect pin (SX1276, optional).
Definition at line 208 of file hub_core.h.
|
virtual |
Send a heat level to an exterior heater (a fan entity) as an IO position.
Mapped to the shared execute path, like set_light_position().
| device_id | Target device ID. |
| position | Desired IO position (0-100): 0 = full heat, 100 = off (the KLF 200 exterior heating mapping, MP = position x 0x200). |
Definition at line 576 of file hub_operations.cpp.
|
inline |
Set the front‑end module enable pin.
Definition at line 214 of file hub_core.h.
|
inline |
Set the FEM PA switch pin.
Definition at line 218 of file hub_core.h.
|
inline |
Set which FEM part fem_pa_pin is wired to (fem: in YAML) — selects whether the SX1262 driver drives that pin per-transmission (GC1109/KCT8103L/XY16P35) or leaves it static-HIGH (NONE, the legacy raw-pin behaviour).
Definition at line 222 of file hub_core.h.
|
virtual |
Set the heating level of a heater that is commanded with levels (the plain electrical heater).
A main-parameter-only EXECUTE through the execute-family funnel; the settle poll that follows reads the level back with the ordinary status read, and the climate entity shows that reading. Experimental: unconfirmed on hardware.
| device_id | Target device ID (hex string). |
| level | Heating level low byte (heating_level::*). |
Definition at line 624 of file hub_operations.cpp.
|
virtual |
Command a heater that carries a temperature or an alias in its main parameter (the heating temperature interface and the heat pump).
A main-parameter-only EXECUTE, or one that also carries functional parameter 9 when the profile sends mode flags, through the execute-family funnel; the settle poll that follows reads the state back with the ordinary status read. Experimental: unconfirmed on hardware.
| device_id | Target device ID (hex string). |
| main_parameter | The 16-bit main parameter (encode_temperature_main_parameter() or an alias). |
| fp | The functional parameter that accompanies it, if any (kind NONE sends a main-parameter-only EXECUTE). |
Definition at line 635 of file hub_operations.cpp.
|
inlinevirtual |
Arm or disarm the "Recover System Key" (key extraction) responder.
Thin forwarder to the KeyExtractionResponder collaborator (key_extraction_responder.h). Arming picks a fresh throwaway node ID, resets the pairing_responder state machine to ARMED_IDLE, and schedules a 10-minute auto-off. While armed, the 0x28/0x2C/0x31/0x32 branches in process_received_packet_() emulate an unpaired device so a user's existing hub can pair to it and hand over its node_id/system_key (see pairing_responder.h). Disarming — manual, via the HA switch, on successful extraction, or on auto-off — immediately stops those branches from responding; it never touches the real device registry or the hub's own node_id_/ system_key_. Virtual so platform unit tests can substitute a mock hub, matching every other queue_*/set_* entry point on this component.
| armed | Desired state. |
Definition at line 429 of file hub_core.h.
|
inline |
Register a callback invoked whenever the key-extraction armed state changes — manual toggle, successful extraction, or auto-off timeout — so the switch entity can keep its displayed state in sync when the hub disarms itself rather than the user.
Single-slot, mirrors set_pairing_result_callback().
| cb | Callable receiving the new armed state. |
Definition at line 436 of file hub_core.h.
|
virtual |
Send an arbitrary IO position (0-100) to a light entity.
Internally mapped to the shared execute path. set_light_state() is a thin binary-position wrapper around this, used by dimmable lights to send anything other than the two binary extremes.
| device_id | Target device ID. |
| position | Desired IO position (0-100); this device family's convention maps 0 to full brightness and 100 to off, the same 0-100 scale platform_cover.cpp uses. |
Definition at line 561 of file hub_operations.cpp.
|
virtual |
Semantic binary helper for light entities.
Internally mapped to the shared execute path.
| device_id | Target device ID. |
| on | Desired on/off state. |
Definition at line 591 of file hub_operations.cpp.
|
virtual |
Semantic lock helper for lock entities.
Internally mapped to the shared execute path.
| device_id | Target device ID. |
| locked | Desired locked/unlocked state. |
Definition at line 609 of file hub_operations.cpp.
|
inline |
Set the controller's node ID (hex string).
Definition at line 224 of file hub_core.h.
|
inlinevirtual |
Arm or disarm the 1W controller-key adoption listener.
Thin forwarder to the OnewayKeyAdoption collaborator (oneway_key_adoption.h) — while armed, an overheard CMD_ONEWAY_ADD_CONTROLLER broadcast is decrypted and reported once, after which the listener disarms itself (one adoption per arm). Receive-only: unlike 2W key extraction this never transmits, it only listens for a frame a 1W device broadcasts of its own accord. Virtual so platform unit tests can substitute a mock hub, matching every other queue_*/set_* entry point on this component.
| armed | Desired state. |
Definition at line 447 of file hub_core.h.
|
inline |
Register a callback invoked whenever the 1W key-adoption armed state changes — manual toggle, successful adoption, or auto-off timeout — so the switch entity stays in sync when the hub disarms itself rather than the user.
Single-slot, mirrors set_key_extraction_armed_callback().
| cb | Callable receiving the new armed state. |
Definition at line 454 of file hub_core.h.
|
inline |
Set PA boost pin configuration.
Definition at line 230 of file hub_core.h.
|
inline |
Register a callback invoked once, right after every discover_and_pair() attempt completes — used by the "Last Pairing Result" text sensor to publish a fresh value.
Single-slot: only one platform instance is expected per hub.
| cb | Callable with no arguments. |
Definition at line 415 of file hub_core.h.
|
inline |
Suspend the hub's normal loop (packet processing, hopping, polling).
Used by loopback test configs to take exclusive control of the radio.
Definition at line 197 of file hub_core.h.
|
inline |
Set radio type ("sx1276", "sx1262", or "lr1121"); required by the YAML schema.
Definition at line 232 of file hub_core.h.
|
inline |
Set the radio reset pin.
Definition at line 204 of file hub_core.h.
|
virtual |
Semantic binary helper for switch entities.
Internally mapped to the shared execute path.
| device_id | Target device ID. |
| on | Desired on/off state. |
Definition at line 595 of file hub_operations.cpp.
|
inline |
Set the system key (hex string).
Definition at line 226 of file hub_core.h.
|
inline |
Set the SX1262/LR1121 TCXO control-voltage code (0-based, TCXO_VOLTAGE_OPTIONS in hub_validators.py: 1_6V=0x00 .
. 3_3V=0x07), or TCXO_VOLTAGE_NONE (0xFF) for a board with a bare crystal and no DIO3-controlled TCXO.
Definition at line 236 of file hub_core.h.
|
inline |
Apply the tuning configuration generated from YAML / UI entities.
Definition at line 239 of file hub_core.h.
|
inline |
Set transmit power (dBm).
Definition at line 228 of file hub_core.h.
|
inline |
Set the VFEM power pin.
Definition at line 216 of file hub_core.h.
|
override |
Initialize hardware (radio and device registry).
Initialize the IO‑Homecontrol component and radio hardware.
This is the main setup entry point called by ESPHome during startup. The sequence:
Definition at line 67 of file hub_core.cpp.
|
inlineoverridevirtual |
Disable the SPI bus.
Implements esphome::home_io_control::SpiAccess.
Definition at line 183 of file hub_core.h.
|
inlineoverridevirtual |
Enable the SPI bus.
Implements esphome::home_io_control::SpiAccess.
Definition at line 181 of file hub_core.h.
|
inlineoverridevirtual |
Read one byte (MISO only).
Implements esphome::home_io_control::SpiAccess.
Definition at line 193 of file hub_core.h.
|
inlineoverridevirtual |
Transfer one byte full‑duplex.
| data | Byte to send. |
Implements esphome::home_io_control::SpiAccess.
Definition at line 187 of file hub_core.h.
|
inlineoverridevirtual |
Write one byte (MOSI only).
| data | Byte to send. |
Implements esphome::home_io_control::SpiAccess.
Definition at line 190 of file hub_core.h.
|
protected |
Transmit a raw IoFrame on the current frequency with given preamble length.
Delegate LBT transmit to ExchangeEngine.
| frame | IoFrame to transmit. |
| freq | RF frequency in Hz. |
| preamble | Preamble length in bytes (e.g. LONG_PREAMBLE, SHORT_PREAMBLE, or a tuning-configured value such as normal_start_preamble). |
Definition at line 298 of file hub_core.cpp.
| void esphome::home_io_control::IOHomeControlComponent::trigger_scan_paired_devices | ( | ) |
Entry point for the "Scan Paired Devices" button: run the roll-call and publish its report to the log and the Home Assistant result event, exactly as the native API action does.
Deliberately not queued through OperationQueue, unlike queue_discover_and_pair(): the roll-call has no priority, coalescing or dedup semantics to preserve, and it already runs this way from the native API action. What it is guarded on is busy_ — a button, unlike an API action, is also reachable from an ESPHome automation, which can fire from inside a blocking exchange (an entity callback -> on_value: -> button.press: chain) and would otherwise re-enter ExchangeEngine mid-exchange. See ADR 0013 for why one blocking radio operation at a time is the whole concurrency model. A press while busy_ still fires the log/event pair (a failed result), matching every other rejected management action rather than going silent.
Blocks the ESPHome loop for up to roughly 6 × pairing_discovery_wait_ms (both power-class passes, three channels each; fewer if scan_power_classes narrows the sweep) and will log the "operation took a long time" warning, same as the action — see docs/pairing.md.
Definition at line 965 of file hub_operations.cpp.
|
protected |
Shared skeleton for the four execute-family operations (position, named command, tilt, position+tilt): device lookup + initialized guard, capability guard, poll-tracking start, "Sending ..." log, frame build, exchange, failure backoff, and the settle poll.
The four public methods supply only their guard predicate, rejection profile label, and frame builder. Called only through run_execute_operation_(), which owns the failure rollback.
| device_id | Target device ID. |
| spec | Pre-formatted action phrase and the settle-as-stop flag. |
| accepts | Capability guard; returns false to reject the operation for this device. |
| rejection_profile | Expected-profile label for the rejection log. |
| build | Fills the request frame from the resolved device; returns false on failure. |
Definition at line 322 of file hub_operations.cpp.
|
protected |
Extract supported position or metadata info from a response frame and merge it into the device record.
| frame | IoFrame containing a supported inbound command such as CMD_PRIVATE_RESP, CMD_STATUS_UPDATE, CMD_GET_NAME_RESP, or CMD_GET_INFO2_RESP. |
| trust_position | False to apply is_stopped but skip target/position decode for a CMD_PRIVATE_RESP — the immediate reply to our own just-sent CMD_EXECUTE echoes stale pre-command target/current values on at least some devices (see tests/corpus/captures/exchange/somfy_awning_exchange_ack_reports_stale_target_*.yaml), so execute_request_and_update_() passes false there; every other caller trusts as before. |
Definition at line 413 of file hub_status.cpp.
| void esphome::home_io_control::IOHomeControlComponent::update_tuning_number | ( | const std::string & | name, |
| float | value ) |
Receive a numeric tuning update from a HA number entity.
Update a numeric tuning parameter from a Home Assistant number entity.
Parses the parameter name and applies the new value to the in-memory tuning configuration. Radio-affecting parameters are forwarded to the active driver immediately; the change is logged in YAML-compatible form so it can be copied back into the configuration file.
Definition at line 233 of file hub_core.cpp.
| void esphome::home_io_control::IOHomeControlComponent::update_tuning_select | ( | const std::string & | name, |
| const std::string & | value ) |
Receive a select tuning update from a HA select entity.
Update a select tuning parameter from a Home Assistant select entity.
Parses the selected option string and applies it to the in-memory tuning configuration. Radio-affecting parameters are forwarded to the active driver immediately; the change is logged in YAML-compatible form.
Definition at line 250 of file hub_core.cpp.
|
protected |
Definition at line 1251 of file hub_core.h.
|
protected |
SX1262/LR1121 BUSY pin.
Definition at line 1230 of file hub_core.h.
|
protected |
Whether diagnostic probes (ManagementActions::probe_device()/probe_sweep()) are enabled.
False by default so a build that didn't opt in via diagnostic_probes: true never sends an undecoded probe opcode. See set_diagnostic_probes_enabled().
Definition at line 1265 of file hub_core.h.
|
protected |
SX1276 DIO0 interrupt.
Definition at line 1227 of file hub_core.h.
|
protected |
SX1262 DIO1 interrupt; also carries the LR1121's DIO9 IRQ line.
Definition at line 1229 of file hub_core.h.
|
protected |
SX1276 DIO4 preamble detect (optional).
Definition at line 1228 of file hub_core.h.
|
protected |
Owns all authenticated exchange and LBT/hop logic.
Definition at line 1278 of file hub_core.h.
|
protected |
1W sender node IDs (remotes or sensors) allowed to fire the sender HA event (add_exposed_sender).
Config-time list (populated once from YAML), not a per-frame allocation.
Definition at line 1259 of file hub_core.h.
|
protected |
Front-end module enable.
Definition at line 1231 of file hub_core.h.
|
protected |
Front-end module PA switch.
Definition at line 1233 of file hub_core.h.
|
protected |
Which FEM part fem_pa_pin_ belongs to, if any.
Definition at line 1234 of file hub_core.h.
|
protected |
millis() of the first 1W frame in the current burst.
Advances to the new frame's timestamp whenever the gap since last_1w_activity_ms_ reaches ONEWAY_QUIET_PERIOD_MS (the previous burst has already released any deferred poll, so this one starts fresh); otherwise holds at the burst's start. Bounds defer_background_poll_() via ONEWAY_POLL_DEFER_CAP_MS.
Definition at line 1319 of file hub_core.h.
|
protected |
Definition at line 1250 of file hub_core.h.
|
protected |
Device-role responder for the "Recover System Key" feature (key_extraction_responder.cpp).
Owns the pairing_responder::ResponderContext, the throwaway-ID/auto-off/grace-window machinery, and the device-role reply TX. Declared after registry_/radio_/tuning_/node_id_ (which it references) and after oneway_key_adoption_ so member-init order matches the initializer list.
Definition at line 1296 of file hub_core.h.
|
protected |
millis() of the most recent 1W frame of any kind, including ones dropped as duplicates — a repeat still means the remote is transmitting.
0 until the first is seen. Gates background polls in loop(); see decisions::defer_background_poll_for_1w_activity().
Definition at line 1314 of file hub_core.h.
|
protected |
Identity of the last processed 1W frame, for burst suppression; see decisions::is_duplicate_1w_frame() for why the intent bytes are part of the key.
Definition at line 1310 of file hub_core.h.
|
protected |
millis() when the last pairing attempt ended; 0 before the first one (see queue_discover_and_pair()).
Definition at line 1253 of file hub_core.h.
|
protected |
Owns rename, identify, force-open, scan_paired_devices, and other hub-level HA actions.
Definition at line 1280 of file hub_core.h.
|
protected |
Definition at line 1243 of file hub_core.h.
|
protected |
Definition at line 1237 of file hub_core.h.
|
protected |
Opt-in, receive-only 1W controller-key adoption listener (oneway_key_adoption.cpp).
Armed via the "Recover 1W Controller Key" switch; observes an overheard CMD_ONEWAY_ADD_CONTROLLER and reports the key once, then disarms. Declared after oneway_transmitter_ so member-init order matches the initializer list.
Definition at line 1290 of file hub_core.h.
|
protected |
Subscribers to the per-command 1W report; one per "Last 1W Command" sensor.
Definition at line 1306 of file hub_core.h.
|
protected |
Owns the 1W controller identities, their rolling-sequence counters and the transmit burst.
The third collaborator that drives the radio (ADR 0004), and the only one that awaits nothing — 1W has no reply to wait for.
Definition at line 1285 of file hub_core.h.
|
protected |
Definition at line 1268 of file hub_core.h.
|
protected |
Definition at line 1246 of file hub_core.h.
|
protected |
Owns the three-phase device pairing flow.
Definition at line 1279 of file hub_core.h.
|
protected |
Invoked once after every pairing attempt completes; see set_pairing_result_callback().
Definition at line 1261 of file hub_core.h.
|
protected |
Per-attempt pairing telemetry.
PairingEngine records into it and, during an attempt, attaches it to ExchangeEngine as its TransmitObserver.
Definition at line 1271 of file hub_core.h.
|
protected |
Definition at line 1266 of file hub_core.h.
|
protected |
Definition at line 1223 of file hub_core.h.
|
protected |
Why setup() gave up on the radio, or empty.
Printed by dump_config so log clients that connect after boot see the cause, not only ESPHome's generic "marked FAILED" line.
Definition at line 1242 of file hub_core.h.
|
protected |
When true, loop() is suspended for loopback testing.
Definition at line 1254 of file hub_core.h.
|
protected |
"sx1276", "sx1262", or "lr1121"; required by the YAML schema.
Definition at line 1239 of file hub_core.h.
|
protected |
Schedule of the opt-in rain sensor poll.
Definition at line 1267 of file hub_core.h.
|
protected |
Most recent 1W pairing-gesture frame seen on the hub's normal passive RX path (e.g.
a PROG press's WRITE_PRIVATE/1W-remove/discover-alt broadcast), remembered so PairingEngine can seed a fresh discover_and_pair() attempt's telemetry with it — see record_oneway_pairing_gesture_() and RecentOneWayPairingSighting's doc comment (issue #27/#65). Declared before pairing_engine_, which holds a reference to it, so member-init order matches the initializer list.
Definition at line 1277 of file hub_core.h.
|
protected |
Definition at line 1256 of file hub_core.h.
|
protected |
Definition at line 1226 of file hub_core.h.
|
protected |
Definition at line 1244 of file hub_core.h.
|
protected |
Definition at line 1238 of file hub_core.h.
|
protected |
SX1262/LR1121 TCXO voltage setting (default 1.8 V).
Definition at line 1247 of file hub_core.h.
|
protected |
Runtime tuning overrides.
Definition at line 1255 of file hub_core.h.
|
protected |
Definition at line 1245 of file hub_core.h.
|
protected |
Front-end module power.
Definition at line 1232 of file hub_core.h.