Home IO Control
ESPHome add-on for IO-Homecontrol devices
Toggle main menu visibility
Loading...
Searching...
No Matches
oneway_key_adoption.h
Go to the documentation of this file.
1
#pragma once
2
3
/// @file oneway_key_adoption.h
4
/// @brief Opt-in, receive-only adoption of a 1W installation's controller key.
5
/// @ingroup hioc_hub
6
///
7
/// See oneway_key_adoption.cpp for the security framing. This header carries only the collaborator
8
/// class; IOHomeControlComponent owns one instance (hub_core.h) and forwards the three public
9
/// entry points to it.
10
11
#include "
hub_hooks.h
"
12
#include "
proto_codecs.h
"
13
#include "
proto_device_model.h
"
14
#include "
proto_frame.h
"
15
16
#include <cstdint>
17
#include <string>
18
19
namespace
esphome
{
20
namespace
home_io_control
{
21
22
/// @brief Opt-in, receive-only listener that adopts an overheard 1W controller key.
23
///
24
/// Receive-only: nothing here transmits. While armed, an overheard CMD_ONEWAY_ADD_CONTROLLER
25
/// broadcast is decrypted and reported once, after which the listener disarms itself — one
26
/// adoption per arm. Constructed once by IOHomeControlComponent; non-copyable because it is wired
27
/// with an injected scheduling callback.
28
/// @ingroup hioc_hub
29
class
OnewayKeyAdoption
{
30
public
:
31
/// @param schedule_auto_off Named-timeout scheduler for the 10-minute arm window (see NamedTimeoutFn).
32
explicit
OnewayKeyAdoption
(
NamedTimeoutFn
schedule_auto_off) : schedule_auto_off_(std::move(schedule_auto_off)) {}
33
34
/// Non-copyable — holds an injected callback and is owned by the hub.
35
OnewayKeyAdoption
(
const
OnewayKeyAdoption
&) =
delete
;
36
OnewayKeyAdoption
&
operator=
(
const
OnewayKeyAdoption
&) =
delete
;
37
38
/// @brief Arm or disarm the 1W controller-key adoption listener.
39
///
40
/// Arming resets any class observed in an earlier window and schedules a 10-minute auto-off.
41
/// Disarming — manual, on successful adoption, or on auto-off — is immediate. See the class doc
42
/// comment; this is the body that was IOHomeControlComponent::set_oneway_key_adoption_armed().
43
/// @param armed Desired state.
44
void
set_armed
(
bool
armed
);
45
46
/// @brief Whether the listener is currently armed.
47
[[nodiscard]]
bool
armed
()
const
{
return
this->armed_; }
48
49
/// Register a callback invoked whenever the armed state changes (manual toggle, successful
50
/// adoption, or auto-off), so the switch entity stays in sync when the listener disarms itself.
51
/// @param cb Callable receiving the new armed state.
52
void
set_armed_callback
(std::function<
void
(
bool
)> cb) { this->armed_callback_ = std::move(cb); }
53
54
/// Remember the most recent 1W target device class observed from `info.src`, for the adoption
55
/// report's `io_device_type` prefill. No-op unless armed and `info.target_type` is a real class.
56
/// @param info Already-decoded 1W frame info (see decode_1w_frame()).
57
void
record_observed_class
(
const
OneWayFrameInfo
&info);
58
59
/// Decode an inbound CMD_ONEWAY_ADD_CONTROLLER (0x30) while armed, report the result, and
60
/// disarm. Returns nothing and never consumes the frame — the caller still runs it through the
61
/// normal 1W logging path.
62
/// @param frame Parsed inbound 1W frame.
63
void
try_adopt
(
const
IoFrame
&frame);
64
65
/// Most recent 1W target device class observed while armed. Single-slot — this is a one-gesture
66
/// flow, not a per-node registry — and reset on every arm so a stale observation from an earlier
67
/// window never leaks into the next one. Feeds the `io_device_type` prefill in the report.
68
struct
ObservedClass
{
69
uint8_t
node
[NODE_ID_SIZE]{};
70
DeviceType
type
{
DeviceType::UNKNOWN
};
71
bool
valid
{
false
};
72
};
73
/// @return The most recent observed class (see ObservedClass).
74
[[nodiscard]]
const
ObservedClass
&
last_observed_class
()
const
{
return
this->observed_class_; }
75
76
private
:
77
NamedTimeoutFn
schedule_auto_off_;
78
bool
armed_{
false
};
79
std::function<void(
bool
)> armed_callback_;
80
ObservedClass observed_class_{};
81
};
82
83
namespace
detail
{
84
85
/// @brief Build the full 1W controller-key-adoption report: MAC-verification status, the
86
/// own-address transmission rationale, and the ready-to-paste `oneway_controllers:` YAML block.
87
///
88
/// Pure — takes already-decoded values, performs no I/O — so it is directly unit-testable
89
/// without a live radio or a captured log line (ESP_LOG's host stub discards its arguments).
90
/// This is the single intentional place `adopted.system_key` is formatted for display (via
91
/// format_key_hex(), log_helpers.h); the caller (OnewayKeyAdoption::try_adopt()) logs the returned
92
/// text through log_multiline_result() and nowhere else.
93
///
94
/// `node_id` is deliberately never mentioned as something to fill in — a later step derives one
95
/// from the hub's own node ID, and the report says so rather than asking the user to invent a
96
/// 3-byte address. The report also explains that the hub always transmits under its own address:
97
/// impersonating the sender would hijack that remote's rolling sequence counter and break it.
98
///
99
/// The emitted keys must track `ONEWAY_CONTROLLER_SCHEMA` (`oneway_controllers.py`) by hand — a newly
100
/// required schema key needs a matching line here too. `make yaml-emitter-sync`
101
/// (scripts/check-yaml-emitters.py) catches drift between the two statically; it does not tell
102
/// you what to add here.
103
///
104
/// @param adopted Decoded controller identity from decode_1w_add_controller() (proto_codecs.h).
105
/// @param observed_type_known True if this sender's other 1W traffic was observed while armed
106
/// (see OnewayKeyAdoption::record_observed_class()); false prints a commented-out
107
/// fallback pointing at the DEBUG log line that would reveal it instead.
108
/// @param observed_type The observed target class; only meaningful when observed_type_known.
109
/// @return Multi-line report text, ready to pass to log_multiline_result().
110
std::string
build_oneway_adoption_report
(
const
OneWayAdoptedKey &adopted,
bool
observed_type_known,
111
DeviceType
observed_type);
112
113
}
// namespace detail
114
115
}
// namespace home_io_control
116
}
// namespace esphome
esphome::home_io_control::OnewayKeyAdoption::OnewayKeyAdoption
OnewayKeyAdoption(NamedTimeoutFn schedule_auto_off)
Definition
oneway_key_adoption.h:32
esphome::home_io_control::OnewayKeyAdoption::try_adopt
void try_adopt(const IoFrame &frame)
Decode an inbound CMD_ONEWAY_ADD_CONTROLLER (0x30) while armed, report the result,...
Definition
oneway_key_adoption.cpp:155
esphome::home_io_control::OnewayKeyAdoption::armed
bool armed() const
Whether the listener is currently armed.
Definition
oneway_key_adoption.h:47
esphome::home_io_control::OnewayKeyAdoption::set_armed_callback
void set_armed_callback(std::function< void(bool)> cb)
Register a callback invoked whenever the armed state changes (manual toggle, successful adoption,...
Definition
oneway_key_adoption.h:52
esphome::home_io_control::OnewayKeyAdoption::last_observed_class
const ObservedClass & last_observed_class() const
Definition
oneway_key_adoption.h:74
esphome::home_io_control::OnewayKeyAdoption::operator=
OnewayKeyAdoption & operator=(const OnewayKeyAdoption &)=delete
esphome::home_io_control::OnewayKeyAdoption::OnewayKeyAdoption
OnewayKeyAdoption(const OnewayKeyAdoption &)=delete
Non-copyable — holds an injected callback and is owned by the hub.
esphome::home_io_control::OnewayKeyAdoption::set_armed
void set_armed(bool armed)
Arm or disarm the 1W controller-key adoption listener.
Definition
oneway_key_adoption.cpp:107
esphome::home_io_control::OnewayKeyAdoption::record_observed_class
void record_observed_class(const OneWayFrameInfo &info)
Remember the most recent 1W target device class observed from info.src, for the adoption report's io_...
Definition
oneway_key_adoption.cpp:142
hub_hooks.h
Injected-capability callback aliases shared by the hub's collaborator objects.
esphome::home_io_control::detail
Definition
entity_helpers.h:23
esphome::home_io_control::detail::build_oneway_adoption_report
std::string build_oneway_adoption_report(const OneWayAdoptedKey &adopted, bool observed_type_known, DeviceType observed_type)
Build the full 1W controller-key-adoption report: MAC-verification status, the own-address transmissi...
Definition
oneway_key_adoption.cpp:55
esphome::home_io_control
Definition
device_registry.cpp:13
esphome::home_io_control::DeviceType
DeviceType
Device type identifiers reported by IO‑Homecontrol products.
Definition
proto_device_model.h:25
esphome::home_io_control::DeviceType::UNKNOWN
@ UNKNOWN
Unknown/unspecified device.
Definition
proto_device_model.h:26
esphome::home_io_control::NamedTimeoutFn
std::function< void(const char *name, uint32_t delay_ms, std::function< void()> callback)> NamedTimeoutFn
Schedules a named, replace-on-same-name timeout on the hub's ESPHome scheduler.
Definition
hub_hooks.h:27
esphome
Definition
device_registry.cpp:12
proto_codecs.h
Device-name, address-classification and 1W-frame codecs.
proto_device_model.h
IO-Homecontrol device-type model, capabilities and runtime device state.
proto_frame.h
IO-Homecontrol 2W frame container: control bytes, IoFrame and (de)serialization.
esphome::home_io_control::IoFrame
Parsed IO‑Homecontrol frame (CTRL0/1 + addresses + command + data).
Definition
proto_frame.h:93
esphome::home_io_control::OneWayFrameInfo
Decoded representation of a 1W remote frame.
Definition
proto_codecs.h:174
esphome::home_io_control::OnewayKeyAdoption::ObservedClass
Most recent 1W target device class observed while armed.
Definition
oneway_key_adoption.h:68
esphome::home_io_control::OnewayKeyAdoption::ObservedClass::valid
bool valid
Definition
oneway_key_adoption.h:71
esphome::home_io_control::OnewayKeyAdoption::ObservedClass::node
uint8_t node[NODE_ID_SIZE]
Definition
oneway_key_adoption.h:69
esphome::home_io_control::OnewayKeyAdoption::ObservedClass::type
DeviceType type
Definition
oneway_key_adoption.h:70
components
home_io_control
oneway_key_adoption.h
Generated by
1.18.0