13#include "esphome/core/log.h"
25inline constexpr const char *
TAG =
"home_io_control";
133 if (auth_like_failure) {
134 if (consecutive_failures <= 1)
136 if (consecutive_failures == 2)
141 if (consecutive_failures <= 1)
143 if (consecutive_failures == 2)
145 if (consecutive_failures == 3)
147 if (consecutive_failures == 4)
162 const char *expected) {
163 ESP_LOGW(
TAG,
"Rejecting %s for device %s: type=%s (%u) class=%s profile=%s expected=%s", operation,
176 const IoFrame *frame =
nullptr) {
179 bytes_to_hex(buf, len, payload_hex,
sizeof(payload_hex));
180 if (frame !=
nullptr) {
183 "chip=%s phase=component stage=%s freq=%u ts=%u len=%u cmd=0x%02X src=%02X%02X%02X dst=%02X%02X%02X payload=%s",
185 frame->src[2], frame->dst[0], frame->dst[1], frame->dst[2], payload_hex);
188 ESP_LOGD(
"io_capture",
"chip=%s phase=component stage=%s freq=%u ts=%u len=%u payload=%s", radio->
chip_name(), stage,
199 const IoFrame &frame, uint8_t len) {
202 const bool src_registered = component->
get_device(src_id) !=
nullptr;
203 const bool dst_registered = component->
get_device(dst_id) !=
nullptr;
205 if (src_registered || dst_registered) {
206 ESP_LOGW(
TAG,
"%s issue=%s cmd=0x%02X src=%s%s dst=%s%s len=%u data_len=%u", direction, reason, frame.
cmd,
207 src_id.c_str(), src_registered ?
" (registered)" :
"", dst_id.c_str(),
208 dst_registered ?
" (registered)" :
"", len, frame.
data_len);
212 ESP_LOGD(
TAG,
"%s issue=%s cmd=0x%02X src=%s dst=%s len=%u data_len=%u", direction, reason, frame.
cmd, src_id.c_str(),
213 dst_id.c_str(), len, frame.
data_len);
The main IO-Homecontrol component.
virtual IoDevice * get_device(const std::string &device_id)
Retrieve a device by ID; returns nullptr if not found.
Abstract radio driver for IO-Homecontrol.
const RadioCaptureInfo & get_last_capture() const
Get the most recent radio capture info.
virtual const char * chip_name() const =0
Get a human‑readable chip name.
IO-Homecontrol ESPHome component — protocol controller.
Shared frame logging helpers for IO-Homecontrol.
bool known_device_accepts_execute_tilt(const IoDevice &dev)
Can this device accept a tilt command?
constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_STEP2_MS
Second retry after a challenge-seen auth-like failure.
bool known_device_matches_entity_class(const IoDevice &dev, DeviceCapabilityClass expected)
Does the device's type match the expected HA entity class?
constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP4_MS
Fourth retry after a silent status-poll failure.
void log_rejected_operation(const std::string &device_id, const IoDevice &dev, const char *operation, const char *expected)
Log a rejected operation with capability mismatch details.
bool known_device_accepts_execute_position(const IoDevice &dev, uint8_t position)
Can this device accept an execute (position) command?
constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MS
First retry after a silent status-poll failure.
constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MAX_MS
Steady-state backoff after repeated auth-like failures.
constexpr const char * TAG
Shared log tag for hub-level messages.
constexpr uint32_t INITIAL_STATUS_REQUEST_DELAY_MS
Delay before the first post-boot status request from an entity.
constexpr float BINARY_ENTITY_ON_POSITION_THRESHOLD
Shared 0-100 cutoff: values below this mean binary "on".
bool known_device_supports_status_requests(const IoDevice &dev)
Does the device support status requests?
void log_component_capture(const RadioDriver *radio, const char *stage, const uint8_t *buf, uint8_t len, const IoFrame *frame=nullptr)
Log a frame at the "io_capture" tag with structured fields.
constexpr uint32_t PAIRING_DISCOVERY_RESPONSE_TIMEOUT_MS
Discovery wait window after sending 0x28.
constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP2_MS
Second retry after a silent status-poll failure.
constexpr uint32_t PAIRING_KEY_CHALLENGE_TIMEOUT_MS
Wait window for the device's 0x3C challenge.
constexpr uint8_t BINARY_ENTITY_ON_POSITION
constexpr uint32_t STATUS_RETRY_AFTER_FAIL_MAX_MS
Steady-state backoff for repeated silent status-poll failures.
constexpr uint8_t BINARY_ENTITY_OFF_POSITION
void normalize_stopped_state(IoDevice &dev)
Normalize stopped state: some devices briefly report stopped before target/current converge.
bool is_binary_entity_position(uint8_t position)
Is the given position value an on/off binary encoding?
void log_status_update(const std::string &id, const IoDevice &dev, const char *suffix="")
Log a concise status‑update line used by inbound handlers.
constexpr uint32_t REMOTE_ACTIVITY_STATUS_POLL_DELAY_MS
Delay before polling after overheard remote traffic.
constexpr uint32_t STATUS_RETRY_AFTER_FAIL_STEP3_MS
Third retry after a silent status-poll failure.
constexpr uint32_t MAX_TRACKED_STATUS_POLL_WINDOW_MS
Hard stop for follow-up polling after a command or remote activity.
uint32_t status_poll_retry_delay_ms(uint8_t consecutive_failures, bool auth_like_failure)
Compute the next background status-poll retry delay after a failed exchange.
void clear_status_poll_tracking(IoDevice &dev)
Clear all bounded follow-up polling state for a device.
bool status_poll_tracking_active(const IoDevice &dev, uint32_t now)
Check whether a device remains inside its bounded follow-up polling window.
void log_frame_issue(IOHomeControlComponent *component, const char *direction, const char *reason, const IoFrame &frame, uint8_t len)
Log a frame‑level issue (unregistered endpoints, unsupported commands).
constexpr uint32_t STATUS_AUTH_RETRY_AFTER_FAIL_MS
First retry after a challenge-seen auth-like failure.
const char * device_operation_profile_name(DeviceType type)
Human‑readable operation profile name for a device type.
void bytes_to_hex(const uint8_t *data, uint8_t len, char *out, size_t out_size)
static constexpr float UNKNOWN_POSITION
Sentinel value meaning "position is not known yet".
@ UNKNOWN
Unknown/unspecified device.
DeviceCapabilityClass device_capability_class(DeviceType type)
Map a raw IO‑Homecontrol type to the closest ESPHome/Home Assistant entity family.
bool device_supports_position_control(DeviceType type)
Does this device type support precise position control (0–100)?
const char * device_type_name(DeviceType type)
Convert a DeviceType to a lowercase string identifier.
bool device_supports_binary_control(DeviceType type)
Does this device type support binary on/off control?
std::string format_position(float pos)
Format a position float as a human‑readable string (e.g.
constexpr size_t FRAME_LOG_HEX_BUFFER_SIZE
Fits a full 32-byte frame rendered as spaced hex text.
const char * device_capability_class_name(DeviceType type)
Get a human‑readable name for a capability class.
std::string node_id_to_string(const uint8_t id[NODE_ID_SIZE])
Format a 3‑byte node ID as a 6‑character uppercase hex string.
bool device_supports_status_requests(DeviceType type)
Does this device type support status request commands (0x03)?
bool has_reached_target_position(float target, float position)
Has the device reached its target within tolerance?
DeviceCapabilityClass
High‑level capability class derived from DeviceType.
bool device_supports_tilt(DeviceType type)
Does this device type support tilt (slat angle) control?
Runtime state of a paired IO‑Homecontrol device.
float target
Target position the device is moving toward.
uint32_t status_poll_interval_ms
Configured follow-up poll interval while a state change is expected.
uint32_t next_update
millis() timestamp when we should poll for status next.
uint8_t status_poll_failures
Consecutive background status-poll failures without a valid reply.
uint8_t auth_poll_failures
Consecutive background poll failures that reached 0x3C auth challenge.
float position
Current position: 0=open, 100=closed, or UNKNOWN_POSITION.
bool single_follow_up_poll_pending
True when one legacy settle poll should still be scheduled.
DeviceType type
Device type (shutter, awning, etc.).
bool is_stopped
True if device is not moving.
uint32_t poll_deadline
Hard stop for bounded follow-up polling after a command or remote activity.
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
uint8_t src[NODE_ID_SIZE]
Source node ID (3 bytes).
uint8_t dst[NODE_ID_SIZE]
Destination node ID (3 bytes).
uint8_t data_len
Actual length of data.
Diagnostic capture from a radio operation.
uint32_t timestamp_ms
Timestamp of capture (millis).
uint32_t freq_hz
RF frequency of capture (Hz).