188 0x16, 0xAA, 0x47, 0x39, 0x49, 0x88, 0x43, 0x73};
222void init_frame(
IoFrame &f,
bool is_2w =
true,
bool start =
false,
bool end =
false,
bool low_power =
false);
237bool set_cmd(
IoFrame &f, uint8_t cmd,
const uint8_t *params =
nullptr, uint8_t params_len = 0);
261bool parse(
const uint8_t *buf, uint8_t buf_len,
IoFrame &f);
395bool hex_to_bytes(
const std::string &hex, uint8_t *out, uint8_t len);
410void decode_position_report(uint16_t target_raw, uint16_t current_raw,
bool is_stopped,
float &target,
float &position);
425uint16_t
crc_ccitt(
const uint8_t *data, uint8_t len);
bool set_cmd(IoFrame &f, uint8_t cmd, const uint8_t *params, uint8_t params_len)
Set command and payload.
static constexpr uint8_t DEVICE_NAME_BUFFER_SIZE
Device name storage including null terminator.
const char * device_operation_profile_name(DeviceType type)
Human‑readable operation profile name for a device type.
static constexpr uint8_t BITS_PER_BYTE
Number of bits in one protocol byte.
static constexpr uint8_t DEVICE_METADATA_SIZE
Packed device metadata uses two bytes where the high 8 bits carry the upper type bits and the low byt...
static constexpr float UNKNOWN_POSITION
Sentinel value meaning "position is not known yet".
static constexpr uint8_t CMD_DISCOVER_REQ
Broadcast discovery request.
static constexpr uint8_t NODE_ID_SIZE
Device/node addresses are 3 bytes (e.g., "123ABC").
static constexpr uint8_t AES_BLOCK_SIZE
AES block size.
static constexpr uint8_t CMD_SET_CONFIG1
Configure device to auto-send status updates.
static constexpr uint16_t STATUS_POS_MAX
In status responses, position is encoded as a 16-bit value where 0x0000 = fully open (0%) and 0xC800 ...
static constexpr uint8_t CMD_KEY_TRANSFER
Send encrypted system key to device.
static constexpr uint8_t FRAME_MIN_SIZE
Minimum frame: CTRL0+CTRL1+DST(3)+SRC(3)+CMD(1).
static constexpr uint8_t TRANSFER_KEY[AES_KEY_SIZE]
The transfer key is a hardcoded key used ONLY during pairing to obfuscate the system key during over-...
static constexpr uint8_t CMD_ERROR_RESP
Error response to any command.
static constexpr uint8_t CMD_GET_NAME_RESP
Device name response.
static constexpr uint8_t CMD_DISCOVER_CONFIRM_ACK
Device acknowledges confirmation.
static constexpr uint8_t DEVICE_TYPE_HIGH_BITS_SHIFT
DeviceType
Device type identifiers reported by IO‑Homecontrol products.
@ LOUVRE_BLIND
Louvre blind.
@ GATE_OPENER
Gate opener.
@ DUAL_SHUTTER
Dual-section shutter.
@ HEATING_TEMPERATURE_INTERFACE
Heating temperature interface.
@ BEACON
Beacon (unpaired/announcement).
@ EXTERNAL_VENETIAN_BLIND
External venetian blind.
@ UNKNOWN
Unknown/unspecified device.
@ INTRUSION_ALARM
Intrusion alarm.
@ WINDOW_OPENER
Window opening actuator.
@ SWINGING_SHUTTER
Swinging shutter.
@ HORIZONTAL_AWNING
Horizontal awning (open/close inverted).
@ ROLLING_DOOR_OPENER
Rolling door opener.
@ ON_OFF_SWITCH
Generic on/off switch.
@ SCREEN
Insect/privacy screen.
@ EXTERIOR_HEATING
Exterior heating.
@ VENTILATION_POINT
Ventilation point.
@ VENETIAN_BLIND
Venetian blind.
@ ROLLER_SHUTTER
Roller shutter.
@ CURTAIN_TRACK
Curtain track.
@ GARAGE_OPENER
Garage door opener.
static constexpr uint8_t CTRL0_END
Control byte 0 (CTRL0) bit definitions.
static constexpr uint8_t FRAME_MAX_DATA_SIZE
Maximum data bytes after command ID.
static constexpr uint8_t POS_UNKNOWN
Position unknown.
static constexpr uint16_t STATUS_POS_TOLERANCE_RAW
Target-reached tolerance expressed in raw IO-homecontrol position units.
DeviceCapabilityClass device_capability_class(DeviceType type)
Map a raw IO‑Homecontrol type to the closest ESPHome/Home Assistant entity family.
static constexpr uint8_t CMD_STATUS_UPDATE
Device-initiated status update (needs auth).
bool default_inverted_for_type(DeviceType type)
Determine whether a device type has inverted position mapping by default.
static constexpr uint8_t LBT_MAX_RETRIES
Max carrier-sense attempts before TX anyway.
bool is_start(const IoFrame &f)
Check START flag.
static constexpr uint32_t FREQ_CH1
The protocol uses 3 frequency channels in the 868 MHz ISM band.
bool device_supports_position_control(DeviceType type)
Does this device type support precise position control (0–100)?
static constexpr uint32_t FREQ_CH3
Channel 3: 869.85 MHz (2W only).
static constexpr uint8_t CMD_GET_NAME
Request device name.
static constexpr int32_t HOP_TIME_US
Timing constants for frequency hopping and response waiting.
static constexpr uint8_t CTRL0_PROTOCOL_1W
Bit 5: 1=OneWay protocol, 0=TwoWay protocol.
const char * device_type_name(DeviceType type)
Convert a DeviceType to a lowercase string identifier.
static constexpr uint8_t CTRL0_START
Bit 6: first frame in exchange (uses long preamble).
bool device_supports_binary_control(DeviceType type)
Does this device type support binary on/off control?
static constexpr uint8_t CMD_DISCOVER_SPE_RESP
Sub-device response.
uint16_t crc_ccitt(const uint8_t *data, uint8_t len)
CRC-CCITT used by the IO-Homecontrol protocol for frame validation.
static constexpr uint8_t HMAC_SIZE
Authentication HMAC is 6 bytes (truncated AES output).
void init_frame(IoFrame &f, bool is_2w, bool start, bool end, bool low_power)
Initialize an IoFrame header (ctrl0/ctrl1) with flags.
float decode_tilt_report(uint16_t tilt_raw)
Decode tilt angle from raw 16‑bit value.
uint8_t frame_length(const IoFrame &f)
Get total frame length from ctrl0.
static constexpr uint8_t FRAME_MAX_SIZE
Maximum frame size (9 header + 23 data).
static constexpr uint8_t CMD_KEY_CONFIRM
Device confirms key was received.
static constexpr int32_t EXCHANGE_RETRY_DELAY_MS
Gap between retries within one HA command.
static constexpr uint8_t CMD_KEY_INIT
Initiate key transfer to device.
void set_dst(IoFrame &f, const uint8_t id[NODE_ID_SIZE])
Set destination node ID.
DeviceType decode_packed_device_type(uint8_t type_msb, uint8_t type_subtype)
Decode a protocol-packed device type from two metadata bytes.
static constexpr uint8_t NODE_ID_STRING_SIZE
Uppercase hex node ID plus null terminator.
bool is_end(const IoFrame &f)
Check END flag.
static constexpr uint16_t CRC_LSB_MASK
Least-significant-bit mask for reflected CRC update.
static constexpr int32_t SX1262_EXCHANGE_RESPONSE_WAIT_SLICE_MS
SX1262-specific per-channel dwell while waiting for authenticated exchange responses.
bool parse(const uint8_t *buf, uint8_t buf_len, IoFrame &f)
Parse a wire buffer into a parsed IoFrame (validates length and CTRL0).
static constexpr uint8_t CMD_DISCOVER_SPE_REQ
Discover sub-devices (e.g., light on garage door).
static constexpr uint8_t EXCHANGE_RETRY_COUNT
Attempts per command before reporting failure.
static constexpr uint8_t CMD_EXECUTE
Set position/open/close/stop — requires authentication.
static constexpr uint8_t CMD_PRIVATE_RESP
Response to 0x00 and 0x03 (contains position data).
const char * device_capability_class_name(DeviceType type)
Get a human‑readable name for a capability class.
static constexpr uint32_t FREQ_CH2
Channel 2: 868.95 MHz (1W and 2W, TX channel).
static constexpr uint8_t CMD_CHALLENGE_REQ
Device sends 6-byte random challenge.
static constexpr uint8_t CMD_STATUS_UPDATE_RESP
Acknowledge status update.
static constexpr uint8_t CMD_SET_CONFIG1_RESP
Config response.
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.
static constexpr uint8_t CMD_DISCOVER_CONFIRM
Confirm discovery to device.
static constexpr uint8_t POS_FAVORITE
Move to favorite/"My" position.
static constexpr uint8_t STATUS_EXPECTED
Byte 1 bit 7: device will send auto status update.
uint8_t decode_packed_device_subtype(uint8_t type_subtype)
Decode a protocol-packed device subtype from the second metadata byte.
static constexpr uint8_t BROADCAST_DISCOVER[NODE_ID_SIZE]
Broadcast address for device discovery (0x00003B).
static constexpr uint8_t CMD_DISCOVER_RESP
Device responds with its ID and type.
static constexpr uint8_t STATUS_TILT_SELECTOR
Extended status payload marker for tilt-capable devices.
bool device_supports_status_requests(DeviceType type)
Does this device type support status request commands (0x03)?
static constexpr uint8_t LBT_RETRY_DELAY_MS
Backoff between LBT checks (≥ 5ms per ETSI).
static constexpr uint16_t SHORT_PREAMBLE
8 bytes for response/continuation frames
static constexpr uint8_t CMD_PRIVATE
Get device status — no authentication needed.
static constexpr uint8_t DEVICE_SUBTYPE_MASK
static constexpr uint8_t CTRL0_LENGTH_MASK
Bits [4:0]: frame length - 1.
bool has_reached_target_position(float target, float position)
Has the device reached its target within tolerance?
static constexpr uint8_t AES_KEY_SIZE
AES-128 key size.
DeviceCapabilityClass
High‑level capability class derived from DeviceType.
@ CLIMATE
Climate device (heating/cooling).
@ SWITCH
Binary on/off switch.
@ COVER
Position‑controlled cover (shutter/blind/awning).
static constexpr int32_t RESPONSE_WAIT_MS
Wait for response to non-start frame.
static constexpr uint8_t CMD_GET_INFO2_RESP
Device type/model response.
static constexpr uint8_t POS_STOP
Position values in the IO protocol.
static constexpr uint8_t DEVICE_TYPE_LOW_BITS_SHIFT
static constexpr uint8_t IV_PADDING
Padding byte used in IV construction.
static constexpr uint8_t CMD_CHALLENGE_RESP
Controller responds with HMAC proof.
static constexpr uint8_t CMD_GET_INFO2
Request device type/model info.
static constexpr uint16_t LONG_PREAMBLE
Preamble is a sequence of 0xAA bytes that precedes every frame.
void decode_position_report(uint16_t target_raw, uint16_t current_raw, bool is_stopped, float &target, float &position)
Decode target/current position values from a status frame.
static constexpr int32_t RESPONSE_AUTH_WAIT_MS
Wait for final response after challenge response.
static constexpr uint8_t CTRL1_LOW_POWER
Control byte 1 (CTRL1) bit definitions.
static constexpr uint16_t CRC_POLYNOMIAL_REVERSED
Reversed CRC-CCITT polynomial used by IO-homecontrol.
bool device_supports_tilt(DeviceType type)
Does this device type support tilt (slat angle) control?
static constexpr uint8_t STATUS_STOPPED
Status byte flags in CMD_PRIVATE_RESP and CMD_STATUS_UPDATE.
static constexpr int32_t RESPONSE_CHANNEL_WAIT_MS
Per-channel dwell while waiting for an exchange response.
bool hex_to_bytes(const std::string &hex, uint8_t *out, uint8_t len)
Convert a hex string (e.g., "123ABC") to a byte array.
static constexpr int16_t LBT_RSSI_THRESHOLD_DBM
Listen-before-talk (LBT) parameters for ETSI EN 300 220 compliance.
static constexpr uint8_t IV_SIZE
Initialization vector size for AES.
uint8_t serialize(const IoFrame &f, uint8_t *buf, uint8_t buf_size)
Serialize a parsed frame into a wire buffer (without CRC).
void set_src(IoFrame &f, const uint8_t id[NODE_ID_SIZE])
Set source node ID.
static constexpr uint16_t SX1262_AUTH_RESPONSE_PREAMBLE
SX1262-specific preamble for the outbound 0x3D challenge response.
static constexpr int32_t RESPONSE_START_WAIT_MS
Wait for response to start frame (longer).
Runtime state of a paired IO‑Homecontrol device.
float target
Target position the device is moving toward.
float tilt
Current tilt: 0=closed, 100=open, or UNKNOWN_POSITION.
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.
uint32_t last_status
millis() timestamp of last received status.
char name[DEVICE_NAME_BUFFER_SIZE]
Device name (from device, Latin‑1 encoded).
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.
bool inverted
True if open/close positions are swapped (e.g., horizontal awning).
float position
Current position: 0=open, 100=closed, or UNKNOWN_POSITION.
uint8_t subtype
Device subtype (manufacturer‑specific).
uint8_t node_id[NODE_ID_SIZE]
Device's 3‑byte radio address.
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 data[FRAME_MAX_DATA_SIZE]
Command parameters (0–23 bytes).
uint8_t ctrl0
Control byte 0: flags + length.
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.
uint8_t ctrl1
Control byte 1: low power, beacon, etc.