|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
Owns the per-hub device table, update callbacks, and linked-remote associations. More...
#include <device_registry.h>
Public Member Functions | |
| void | add (const std::string &device_id) |
| Register a device by ID with default metadata (UNKNOWN type, subtype 0, no overrides). | |
| void | add (const std::string &device_id, const DeviceConfig &cfg) |
| Register a device with full YAML-derived metadata. | |
| void | put (const std::string &device_id, IoDevice device) |
| Insert or overwrite a device entry without deduplication or hex-validation checks. | |
| IoDevice * | get (const std::string &device_id) |
| Retrieve a registered device by ID. | |
| IoDevice * | get_declared (const std::string &device_id) |
| Retrieve a device the YAML declares, ignoring one a pairing added in this boot. | |
| bool | remove_registered_by_pairing (const std::string &device_id) |
| Remove a device a pairing added in this boot. | |
| void | set_travel_speed (const std::string &device_id, TravelSpeed speed) |
| Select a device's travel speed. | |
| void | subscribe (DeviceUpdateCallback cb) |
| Register a callback that fires whenever a device's state changes. | |
| void | notify (const std::string &device_id) |
Invoke all registered callbacks for device_id. | |
| void | add_linked_remote (const std::string &remote_id, const std::string &device_id) |
| Record that a remote node controls a registered device. | |
| const std::vector< std::string > * | linked_devices (const std::string &remote_id) const |
| Retrieve the list of device IDs linked to a remote. | |
| void | add_linked_remote_class (DeviceType type, const std::string &device_id) |
| Record that a remote's typed-broadcast presses (e.g. | |
| const std::vector< std::string > * | linked_devices_for_class (DeviceType type) const |
| Retrieve the list of device IDs linked to a device class. | |
| std::vector< std::string > | all_linked_devices () const |
| Every device with a linked_remotes entry, by remote id or by class:, once each, sorted. | |
| bool | apply_optimistic_target (const std::string &device_id, float target_io_position) |
| Set an optimistic target position ahead of a confirming poll/response, and notify. | |
| bool | apply_optimistic_stop (const std::string &device_id, bool restorable=false) |
| Predict that a device has stopped (e.g. | |
| bool | apply_optimistic_tilt (const std::string &device_id, float tilt_percent) |
| Set an optimistic slat angle ahead of a confirming poll, and notify. | |
| bool | rollback_optimistic (const std::string &device_id, bool failed_stop=false) |
| Withdraw every prediction for a device after the command that produced them failed, and notify. | |
| void | confirm_optimistic_stop (const std::string &device_id) |
| Mark a device's STOP as delivered: a later rollback must not restore the movement it replaced. | |
| size_t | size () const |
| size_t | linked_remote_count () const |
| void | for_each_linked_remote (const std::function< void(const std::string &, const std::vector< std::string > &)> &fn) const |
Invoke fn(remote_id, device_id_list) for every linked-remote entry. | |
| std::map< std::string, IoDevice >::iterator | begin () |
| Mutable begin iterator over (device_id, IoDevice) pairs (supports range-for in the poll loop). | |
| std::map< std::string, IoDevice >::iterator | end () |
| Mutable end iterator over (device_id, IoDevice) pairs. | |
Owns the per-hub device table, update callbacks, and linked-remote associations.
All of the hub's add/get/subscribe/notify operations go through this class — IOHomeControlComponent holds no device state of its own. The class has no ESPHome dependencies beyond logging and is directly host-testable.
Definition at line 53 of file device_registry.h.
| void esphome::home_io_control::DeviceRegistry::add | ( | const std::string & | device_id | ) |
Register a device by ID with default metadata (UNKNOWN type, subtype 0, no overrides).
No-op when device_id is already registered. Warns and returns when the hex string is invalid.
| device_id | Hexadecimal node ID string (e.g. "ABC123"). |
Definition at line 20 of file device_registry.cpp.
| void esphome::home_io_control::DeviceRegistry::add | ( | const std::string & | device_id, |
| const DeviceConfig & | cfg ) |
Register a device with full YAML-derived metadata.
No-op when device_id is already registered. Warns and returns when the hex string is invalid.
| device_id | Hexadecimal node ID string. The record's features are resolved from the declared kind and overrides (resolve_device_features()). |
| cfg | Device type/subtype/overrides/optimistic-state metadata. |
Definition at line 22 of file device_registry.cpp.
| void esphome::home_io_control::DeviceRegistry::add_linked_remote | ( | const std::string & | remote_id, |
| const std::string & | device_id ) |
Record that a remote node controls a registered device.
When activity from the remote is overheard, a status poll is scheduled for the linked device.
| remote_id | Node ID of the remote control. |
| device_id | Node ID of the device it controls. |
Definition at line 92 of file device_registry.cpp.
| void esphome::home_io_control::DeviceRegistry::add_linked_remote_class | ( | DeviceType | type, |
| const std::string & | device_id ) |
Record that a remote's typed-broadcast presses (e.g.
"all awnings") should also apply to device_id, matching how 1W remotes address a device class rather than a single node. Independent of add_linked_remote()'s id-keyed map — a device may be linked both ways; callers dedup (see IOHomeControlComponent's 1W dispatch) so it is only touched once per press.
| type | Device class the broadcast targets. |
| device_id | Node ID of the device to add to that class. |
Definition at line 101 of file device_registry.cpp.
|
nodiscard |
Every device with a linked_remotes entry, by remote id or by class:, once each, sorted.
Definition at line 197 of file device_registry.cpp.
| bool esphome::home_io_control::DeviceRegistry::apply_optimistic_stop | ( | const std::string & | device_id, |
| bool | restorable = false ) |
Predict that a device has stopped (e.g.
on STOP), and notify.
No-op (and returns false) when the device is unknown or has optimistic_state == false. Records a Motion::STOPPED prediction rather than merely withdrawing the position prediction: a bare withdrawal would fall back to an observed is_stopped == false and keep the HA cover animating. The prediction is superseded by the next decoded status.
| device_id | Device to update. |
| restorable | True for a STOP this hub is about to send: a movement prediction it replaces is kept so rollback_optimistic() can bring it back if the STOP fails. False for a stop that cannot fail from the hub's side (an overheard remote's STOP). |
Definition at line 131 of file device_registry.cpp.
| bool esphome::home_io_control::DeviceRegistry::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.
No-op (and returns false) when the device is unknown or has optimistic_state == false. Never touches position — only the caller's later poll/response settles that. Used by both the 1W linked-remote path and HA-issued 2W cover commands so the entity shows movement direction immediately instead of only after the confirming update arrives.
| device_id | Device to update. |
| target_io_position | Target position in IO units (0=open, 100=closed). |
Definition at line 110 of file device_registry.cpp.
| bool esphome::home_io_control::DeviceRegistry::apply_optimistic_tilt | ( | const std::string & | device_id, |
| float | tilt_percent ) |
Set an optimistic slat angle ahead of a confirming poll, and notify.
No-op (and returns false) when the device is unknown, has optimistic_state == false, or is not a tilt-capable type. Nothing else can fill the gap: unlike a position command, a tilt command's own reply carries no slat angle this hub can use. The EXECUTE ack lays its payload out differently from a status reply and is not decoded for tilt at all (see the offset constants in hub_status.cpp and tests/corpus/captures/exchange/tilt_cover_exchange_ack_tilt_block*.yaml), so without this the entity would keep showing the pre-command angle until the next status poll seconds later.
Deliberately records no movement prediction, unlike apply_optimistic_target(): the HA movement animation is derived from main-position delta, and a tilt-only command does not move the main position — predicting motion would animate an open/close that is not happening. The EXECUTE ack settles is_stopped from the wire a fraction of a second later.
| device_id | Device to update. |
| tilt_percent | Slat angle in the same percent scale as IoDevice::tilt (0-100). |
Definition at line 150 of file device_registry.cpp.
|
inline |
Mutable begin iterator over (device_id, IoDevice) pairs (supports range-for in the poll loop).
Definition at line 211 of file device_registry.h.
| void esphome::home_io_control::DeviceRegistry::confirm_optimistic_stop | ( | const std::string & | device_id | ) |
Mark a device's STOP as delivered: a later rollback must not restore the movement it replaced.
Leaves every prediction in place. No-op for an unknown device.
| device_id | Device that accepted the STOP. |
Definition at line 191 of file device_registry.cpp.
|
inline |
Mutable end iterator over (device_id, IoDevice) pairs.
Definition at line 213 of file device_registry.h.
| void esphome::home_io_control::DeviceRegistry::for_each_linked_remote | ( | const std::function< void(const std::string &, const std::vector< std::string > &)> & | fn | ) | const |
Invoke fn(remote_id, device_id_list) for every linked-remote entry.
| fn | Callable receiving the remote ID and its associated device ID list. |
Definition at line 206 of file device_registry.cpp.
|
nodiscard |
Retrieve a registered device by ID.
Definition at line 59 of file device_registry.cpp.
|
nodiscard |
Retrieve a device the YAML declares, ignoring one a pairing added in this boot.
A device a pairing registered (IoDevice::registered_by_pairing) is controllable until reboot but still needs its YAML block, so roll-call reports treat it as unknown and a later pairing may replace its record.
Definition at line 64 of file device_registry.cpp.
|
nodiscard |
Retrieve the list of device IDs linked to a remote.
Definition at line 96 of file device_registry.cpp.
|
nodiscard |
Retrieve the list of device IDs linked to a device class.
Definition at line 105 of file device_registry.cpp.
|
inlinenodiscard |
Definition at line 203 of file device_registry.h.
| void esphome::home_io_control::DeviceRegistry::notify | ( | const std::string & | device_id | ) |
Invoke all registered callbacks for device_id.
No-op when device_id is not in the registry.
| device_id | Device whose state just changed. |
Definition at line 84 of file device_registry.cpp.
| void esphome::home_io_control::DeviceRegistry::put | ( | const std::string & | device_id, |
| IoDevice | device ) |
Insert or overwrite a device entry without deduplication or hex-validation checks.
Used by the pairing flow which already validated the device during discovery. A record already stored under the ID hands its YAML overrides (entity class, invert_position:, dimmable:, io_model:) to the new one, and the new record's features are resolved before it is stored.
| device_id | Hexadecimal node ID string. |
| device | Fully-built device to store. |
Definition at line 47 of file device_registry.cpp.
| bool esphome::home_io_control::DeviceRegistry::remove_registered_by_pairing | ( | const std::string & | device_id | ) |
Remove a device a pairing added in this boot.
A device the YAML declares is never removed.
| device_id | Hexadecimal node ID string. |
Definition at line 69 of file device_registry.cpp.
| bool esphome::home_io_control::DeviceRegistry::rollback_optimistic | ( | const std::string & | device_id, |
| bool | failed_stop = false ) |
Withdraw every prediction for a device after the command that produced them failed, and notify.
Self-guarding: an empty overlay means nothing was predicted (including every device configured optimistic_state: false, whose apply_* calls all no-op), so there is nothing to withdraw and no reason to republish. Never touches an observed field — the device did not move, so its last reported position remains correct and stays on display.
A failed restorable STOP (apply_optimistic_stop()) is the exception: the device keeps doing what it was doing, so the movement prediction the STOP replaced comes back, and every other prediction is withdrawn as usual. Without that the entity would fall back to an observation that, on a device reporting nothing mid-travel, reads "moving, target = position" and shows as idle.
| device_id | Device whose failed command's predictions should be withdrawn. |
| failed_stop | True when the failed command is a STOP. Only then does the replaced movement come back; any other failed command (e.g. a tilt run ahead of a still-queued STOP) withdraws everything. |
Definition at line 171 of file device_registry.cpp.
| void esphome::home_io_control::DeviceRegistry::set_travel_speed | ( | const std::string & | device_id, |
| TravelSpeed | speed ) |
Select a device's travel speed.
A declared preference with no protocol readback — nothing on the wire reports which speed a device is moved with.
| device_id | Hexadecimal node ID string. |
| speed | Speed profile of the device's position moves. |
Definition at line 77 of file device_registry.cpp.
|
inlinenodiscard |
Definition at line 200 of file device_registry.h.
| void esphome::home_io_control::DeviceRegistry::subscribe | ( | DeviceUpdateCallback | cb | ) |
Register a callback that fires whenever a device's state changes.
| cb | Callable with signature void(const std::string &device_id, const IoDevice &device). |
Definition at line 82 of file device_registry.cpp.