256 bool metadata_complete,
bool low_power,
257 const std::string &system_key_hex = std::string());
588 std::optional<uint16_t>
597 HEATING_TEMPERATURE_RANGE_MIN_C};
600 HEATING_TEMPERATURE_RANGE_MAX_C};
679 return static_cast<int16_t
>((scaled + (scaled >= 0 ? half : -half)) /
RSSI_EMA_SCALE);
725void decode_position_report(uint16_t target_raw, uint16_t current_raw,
bool is_stopped,
float &target,
float &position);
@ FAVORITE
CoverCommand::FAVORITE.
@ STOP
CoverCommand::STOP.
@ VENT
CoverCommand::VENT.
static constexpr uint8_t DEVICE_NAME_BUFFER_SIZE
Device name storage including null terminator.
void encode_packed_device_type(DeviceType type, uint8_t subtype, uint8_t &type_msb, uint8_t &type_subtype)
Encode a DeviceType/subtype pair into the two-byte packed metadata format used by discovery responses...
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".
ExecutionState execution_state_of(uint8_t status_byte)
Read the execution state out of byte 0 of a status reply.
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 ...
const char * travel_speed_name(TravelSpeed speed)
Get the name a travel speed is configured and published under.
std::string format_device_type_for_yaml(DeviceType type)
Build the YAML value for a device's io_device_type key.
RainSensorState
What the hub's latest minimum-limitation read says about a rain-protection limit.
@ UNKNOWN
No usable reading: never read, or the last reads went unanswered.
@ DRY
The device answered and reports no rain-sized opening limit.
@ RAIN
The device answered and reports an opening limit of rain size.
static constexpr uint8_t DEVICE_TYPE_HIGH_BITS_SHIFT
const char * rain_sensor_state_name(RainSensorState state)
Get a human-readable name for a RainSensorState.
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.
float effective_target(const IoDevice &dev)
The main-position target a consumer should act on: the prediction when one stands,...
CoverCommand
Named device commands for cover-type actuators.
@ FORCE_OPEN
Move to fully open at elevated priority; intended to bypass soft locks and environmental limits (conf...
@ PEDESTRIAN
Move to the pedestrian position (gate openers); experimental.
@ PARTIAL
Move to the stored partial position (garage openers; issue #163).
bool device_supports_position_control(DeviceType type)
Does this device type support precise position control (0–100)?
DeviceModel
A product model below a (node type, subtype): for products that report the same wire type but need di...
@ HEATER_WITH_LIGHT
Heater with a night light under the electrical heater with an adjustable setpoint (52/1).
@ NONE
No model: the (type, subtype) row.
@ TOWEL_DRYER
Towel dryer under the electrical heater with an adjustable setpoint (52/1).
void resolve_device_features(IoDevice &dev)
Resolve a device's capability bits and inversion from its kind and its YAML overrides.
const char * execution_state_name(ExecutionState state)
Get a human-readable name for an ExecutionState.
int16_t rssi_scaled_to_dbm(int16_t scaled)
Convert an rssi_ema_scaled fixed-point value to whole dBm (round half away from zero).
const char * device_type_name(DeviceType type)
Convert a DeviceType to a lowercase string identifier.
DeviceType
IO-Homecontrol node types.
@ LOUVRE_BLIND
Louvre blind.
@ SLIDING_WINDOW
Sliding window.
@ EXTERIOR_VENETIAN_BLIND
Exterior venetian blind.
@ VERTICAL_INTERIOR_BLIND
Vertical interior blind.
@ CENTRAL_HOUSE_CONTROL
Central house control.
@ GATE_OPENER
Gate opener.
@ ELECTRICAL_HEATER
Electrical heater.
@ VERTICAL_EXTERIOR_AWNING
Vertical exterior awning.
@ HEATING_TEMPERATURE_INTERFACE
Heating temperature interface.
@ BEACON
Beacon (unpaired/announcement).
@ SECURE_CONFIGURATION_DEVICE
Secure configuration device (a commissioning tool, not an actuator).
@ INTERIOR_VENETIAN_BLIND
Interior venetian blind.
@ UNKNOWN
Unknown/unspecified device.
@ DOMESTIC_HOT_WATER
Domestic hot water.
@ ZONE_CONTROL
Zone control.
@ INTRUSION_ALARM
Intrusion alarm.
@ WINDOW_OPENER
Window opening actuator.
@ SWINGING_SHUTTER
Swinging shutter.
@ HEAT_RECOVERY_VENTILATION
Heat recovery ventilation.
@ HORIZONTAL_AWNING
Horizontal awning (open/close inverted).
@ ROLLING_DOOR_OPENER
Rolling door opener.
@ ON_OFF_SWITCH
Generic on/off switch.
@ EXTERIOR_HEATING
Exterior heating.
@ TEST_AND_EVALUATION
Test and evaluation equipment.
@ DUAL_ROLLER_SHUTTER
Dual-section roller shutter.
@ VENTILATION_POINT
Ventilation point.
@ ROLLER_SHUTTER
Roller shutter.
@ REMOTE_CONTROLLER
Remote controller (all ten type bits set, packed bytes FF C0).
@ CURTAIN_TRACK
Curtain track.
@ BIOCLIMATIC_PERGOLA
Bioclimatic pergola (louvre opening as the position).
@ GARAGE_OPENER
Garage door opener.
bool device_supports_binary_control(DeviceType type)
Does this device type support binary on/off control?
float decode_tilt_report(uint16_t tilt_raw)
Decode tilt angle from raw 16‑bit value.
const char * device_operation_profile_name(DeviceType type, uint8_t subtype)
Human‑readable operation profile name for a device kind.
bool device_supports_lock_control(DeviceType type)
Does this device type support binary lock/unlock control via execute commands?
bool parse_travel_speed(const std::string &name, TravelSpeed &speed)
Look up a travel speed by the name travel_speed_name() gives it.
bool device_supports_climate_control(DeviceType type, uint8_t subtype)
Can a climate entity drive this device?
DeviceType decode_packed_device_type(uint8_t type_msb, uint8_t type_subtype)
Decode the 10-bit node type from two packed metadata bytes.
BatteryState
A device's coarse battery level, as it reports it in byte 1 of its status payload.
@ FULL_CHARGE
Battery full.
@ NORMAL_CHARGE
Battery neither low nor full.
@ NOT_REPORTED
The device does not report a battery (mains powered), or no status was read yet.
const char * cover_command_name(CoverCommand cmd)
Get a human-readable name for a CoverCommand.
bool device_supports_heat_level_control(DeviceType type)
Does this device take a heat level as its position (exterior heating)?
std::string build_device_yaml_snippet(DeviceType type, uint8_t subtype, const std::string &device_id, bool metadata_complete, bool low_power, const std::string &system_key_hex)
Build the ready-to-paste YAML block describing a device, for both a fully-decoded device and one whos...
const char * device_capability_class_name(DeviceType type)
Get a human‑readable name for a capability class.
bool effective_is_stopped(const IoDevice &dev)
Whether a consumer should treat the device as at rest, prediction first.
ExecutionState
What a device says it is doing, from bits [2:0] of byte 0 of a status reply (CMD_PRIVATE_RESP,...
@ WAITING_FOR_POWER
Accepted, waiting for power (queued behind another device on a shared supply).
@ UNDEFINED
Bits [2:0] hold 6 or 7, which no source defines.
@ DONE
Not executing, no error, ready.
@ NON_EXECUTING
Unable to execute under the given conditions (example: temperature too high).
@ WAITING_FOR_EXECUTING
Accepted, waiting for its turn to run.
@ EXECUTION_ERROR
An error occurred during the previous execution; cleared when the next starts.
float effective_tilt(const IoDevice &dev)
The slat angle a consumer should act on, prediction first.
bool is_known_device_type(uint16_t raw)
True when a raw 10-bit device-type value is a named DeviceType enumerator.
uint16_t DeviceFeatures
Capability bits of a device kind; see device_feature.
void note_moving_evidence(IoDevice &dev, uint32_t now_ms)
Record that a device is (believed to be) travelling right now.
static constexpr int16_t RSSI_EMA_SCALE
EMA weight denominator and fixed-point scale for IoDevice::rssi_ema_scaled.
void note_moving_until(IoDevice &dev, uint32_t until_ms)
Record when the travel the device is reporting should be over, from its own remaining time.
uint8_t decode_packed_device_subtype(uint8_t type_subtype)
Decode a protocol-packed device subtype from the second metadata byte.
bool device_supports_status_requests(DeviceType type)
Does this device type support status request commands (0x03)?
bool device_has_no_motion(DeviceType type, uint8_t subtype)
Does this device never move, so a status reply must not start the movement settle loop?
static constexpr uint16_t DEVICE_TYPE_WIRE_MASK
The node-type wire field is ten bits wide.
static constexpr uint8_t DEVICE_SUBTYPE_MASK
bool has_reached_target_position(float target, float position)
Has the device reached its target within tolerance?
const char * yaml_device_type_name(DeviceType type)
Return the YAML-friendly device-type name for types exposed in the Python schema.
DeviceCapabilityClass
High‑level capability class derived from DeviceType.
@ CLIMATE
Climate device (heating/cooling).
@ SWITCH
Binary on/off switch.
@ UNKNOWN
Unknown capability.
@ HEATER_LEVEL
Heater with a heat level in the position field (exterior heating).
@ COVER
Position‑controlled cover (shutter/blind/awning).
@ WATER_HEATER
Domestic hot water heater (device_feature::WATER_HEATER).
bool device_takes_execute_position(DeviceType type)
Does this device type take position EXECUTEs (a percent, on / off, or stop in the main parameter)?
int16_t device_rssi_ema_dbm(const IoDevice &dev)
A device's smoothed RSSI in whole dBm.
BatteryState decode_battery_state(uint8_t status_byte)
Decode the coarse battery level from byte 1 of a status payload (CMD_PRIVATE_RESP to a status poll,...
static constexpr int16_t RSSI_UNKNOWN_DBM
Sentinel value meaning "no RSSI sample recorded yet" for last_rssi_dbm/rssi_ema_scaled.
static constexpr uint8_t DEVICE_TYPE_LOW_BITS_SHIFT
const char * battery_state_name(BatteryState state)
Get the name a battery level is published under.
TravelSpeed
The speed a cover's position moves ask the motor for (ADR 0065).
@ SILENT
Profile 0x05, the manufacturer app's silent operation: slower than the motor's own.
@ MOTOR_DEFAULT
The 6-byte frame with no profile: the motor's own speed, as its wall pad moves it.
@ FAST
Profile 0x06, what the hub sends unless a cover says otherwise.
std::string format_device_type_diagnostic(DeviceType type)
Human-readable device type string for diagnostics, including the raw numeric value.
void clear_moving_evidence(IoDevice &dev)
Forget that a device was travelling: it reported itself stopped (including in the ack to a STOP),...
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.
Capability bits of a device kind: what a (node type, subtype) can do.
Pure codec for a domestic hot water heater: its family-0x00 registers and its target temperature.
Pure codec for the private register protocol of 2W heaters (CMD_WRITE_PRIVATE 0x20).
Fundamental IO-Homecontrol frame and crypto size constants.
What the hub has read from a domestic hot water heater.
What the hub has read from one heater so far.
Runtime state of a paired IO‑Homecontrol device.
uint8_t model_check_attempts
Runs of the hub's one-off model check (a heater kind with model rows: model name read,...
uint32_t last_result_at_ms
millis() timestamp of last_result_code, 0 when none recorded.
DeviceCapabilityClass entity_class
Class of the entity that declared the device; UNKNOWN for a device no entity declared (the type's cla...
float target
Target position the device is moving toward.
uint16_t exchange_attempt_count
Cumulative attempts (ExchangeEngine::DebugInfo::tries, 1-based per exchange) across those timed-out e...
float tilt
Current tilt: 0=closed, 100=open, or UNKNOWN_POSITION.
float temperature_range_min_c
Lower end of the temperature encoding range of a heater that carries a temperature in its main parame...
DeviceFeatures features
What this device can do, resolved by resolve_device_features().
uint16_t exchange_unconfirmed_count
Cumulative count of exchanges this device authenticated and then never closed: it answered with a 0x3...
uint32_t moving_until_ms
millis() at which the remaining time of the last trusted moving report has run out (plus PREDICTED_EN...
ExecutionState execution_state
Execution state of the last status report that carried one; UNDEFINED until then, and for a device th...
std::optional< bool > invert_override
YAML invert_position: when declared; wins over the kind's default.
uint8_t last_result_code
Last CMD_ERROR_RESP result byte (0 = none recorded).
HeatingReadings heating
What the hub has read from a heater over the private register protocol (room temperature,...
uint32_t last_status
millis() timestamp of last received status.
uint8_t last_commander[NODE_ID_SIZE]
Node ID of the controller that last commanded this device, as reported verbatim by the device in its ...
std::optional< uint16_t > sun_level
Raw sun value from the opt-in EVENT_LOCAL_SENSOR poll.
uint8_t last_command_originator
That command's Command Originator byte (ORIGINATOR_* in proto_constants.h).
char name[DEVICE_NAME_BUFFER_SIZE]
Cached UTF-8 device name decoded from Latin-1 wire payloads.
uint32_t last_moving_evidence_ms
millis() of the last sign this device is travelling (see note_moving_evidence(), clear_moving_evidenc...
OptimisticState optimistic
Hub-side predictions; see OptimisticState. Never observation.
bool inverted
True if open/close positions are swapped (e.g., horizontal awning).
int16_t last_rssi_dbm
Most recent raw RSSI sample (dBm), or RSSI_UNKNOWN_DBM.
bool limited_by_rain
Derived from observed status replies, never from a prediction (decisions::is_rain_limited(); ADR 0030...
bool reports_remaining_time
The device has sent a nonzero remaining time in a status reply, so its zero means "about to stop" rat...
bool low_power
YAML-declared: this target is a low-power / duty-cycled receiver, so directed frames set CTRL1_LOW_PO...
bool registered_by_pairing
Added by a pairing in this boot, not declared in YAML.
float position
Current position: 0=open, 100=closed, or UNKNOWN_POSITION.
std::optional< uint16_t > battery_level
Battery level in percent (0-100) from the opt-in EVENT_BATTERY_LEVEL_CHANGE poll (decode_battery_leve...
uint8_t subtype
Device subtype (manufacturer‑specific).
uint32_t last_seen_ms
millis() of the last frame received from this device (any command), 0 = never.
bool battery_entities
YAML-declared (battery: true): the battery entities exist, so the status log line names the level eve...
DeviceModel model
YAML-declared product model below the subtype (io_model:); never on the wire.
int16_t rssi_ema_scaled
Smoothed RSSI as fixed point in 1/RSSI_EMA_SCALE dBm — read through device_rssi_ema_dbm(),...
float temperature_range_max_c
Upper end of that range (YAML max_temperature:).
uint8_t node_id[NODE_ID_SIZE]
Device's 3‑byte radio address.
bool dimmable
YAML-declared dimmable: true of a LIGHT entity.
uint8_t system_key[AES_KEY_SIZE]
The device's own key; meaningful only when has_system_key.
DhwReadings dhw
What the hub has read from a water heater (device_feature::WATER_HEATER): family-0x00 registers and t...
bool has_last_command
True once a status reply carried a well-formed last-command record.
bool has_system_key
YAML-declared (system_key:): this device keeps a key of its own.
uint32_t last_rain_evidence_ms
millis() of the last status reply that named the rain sensor as the last commander; 0 = never.
RainSensorState rain_sensor
Rain state from the opt-in minimum-limitation poll.
bool optimistic_state
True if target may be set ahead of a confirming poll/response.
bool model_checked
The model check completed: both of its reads were answered.
DeviceType type
Device type (shutter, awning, etc.).
uint16_t exchange_timeout_count
Cumulative count of outbound exchanges to this device with no valid response (see detail::record_exch...
BatteryState battery
Coarse battery level from byte 1 of the device's own status: a reply to a status poll or an authentic...
bool is_stopped
True if device is not moving.
bool confirms_execute
True once this device has answered a CMD_EXECUTE with a reply that closed the exchange (a status,...
TravelSpeed travel_speed
Speed profile of position moves.
StopCandidate stop_candidate
Last off-target "stopped" report, to confirm the next one.
What the hub predicted ahead of confirmation, kept apart from what the device reported.
Motion
Predicted movement.
@ STOPPED
Predicted to be at rest (a STOP was issued).
@ MOVING
Predicted to be travelling (a position command was issued).
@ NONE
No movement prediction; the observed is_stopped decides.
void clear()
Withdraw every prediction.
float stop_replaced_target
The replaced target; meaningful only with the flag.
Motion motion
Predicted movement state.
void clear_tilt()
Withdraw the tilt prediction; call when a decoded tilt observation supersedes it.
bool stop_replaced_movement
True while a pending STOP replaced a Motion::MOVING prediction that a failed STOP should bring back (...
void forget_replaced_movement()
Drop the movement a STOP replaced, once nothing can roll the STOP back any more.
void clear_position()
Withdraw the position prediction; call when a decoded position observation supersedes it.
float tilt
Predicted slat angle, or UNKNOWN_POSITION.
float target
Predicted main-position target, or UNKNOWN_POSITION.
The last "stopped" report a device sent away from its own target, kept to confirm the next.
void clear()
Forget the remembered report.
float position
Current position it reported with it.
bool armed() const
True when a report is remembered.
float target
Target the device reported with the off-target "stopped".