|
Home IO Control
ESPHome add-on for IO-Homecontrol devices
|
Sends 1W commands as the repeated bursts real remotes send. More...
#include <oneway_transmitter.h>
Public Member Functions | |
| OneWayTransmitter (OneWayTransmitFn transmit) | |
| void | add_identity (const OneWayControllerIdentity &identity) |
| Register a configured controller identity. | |
| void | setup () |
| Open each registered identity's persistent sequence counter. | |
| const OneWayControllerRegistry & | identities () const |
| void | set_command_report_callback (OneWayCommandReportFn callback) |
| Register the callback that receives a report after every command attempt. | |
| bool | send_command (const std::string &controller_id, CoverCommand cmd) |
| Send a named command as the identity's controller. | |
| bool | send_position (const std::string &controller_id, uint8_t position) |
| Send a numeric position as the identity's controller. | |
| bool | send_burst (const IoFrame &frame) |
| Transmit one already-built, already-signed 1W frame as a burst. | |
| bool | send_enrollment (const std::string &controller_id) |
| Register this identity as a controller on every device currently in association mode (a physical PROG hold on the receiver, ADR 0026), using the gesture its manufacturer expects (resolve_oneway_wire_profile(), ADR 0032). | |
| bool | send_unenrollment (const std::string &controller_id) |
| Un-register this identity from every device of its class currently in association mode (CMD 0x39) alone — also the prelude send_enrollment() fires before its own 0x30. | |
Sends 1W commands as the repeated bursts real remotes send.
Definition at line 57 of file oneway_transmitter.h.
|
inlineexplicit |
| transmit | How to put a frame on air; must stay valid for this object's lifetime. |
Definition at line 60 of file oneway_transmitter.h.
|
inline |
Register a configured controller identity.
Called once per oneway_controllers: entry.
Config only — it does not touch persistent storage, because generated wiring runs before preferences are usable. setup() is what opens each identity's counter.
| identity | Fully-resolved identity (address and key already decided at schema time). |
Definition at line 69 of file oneway_transmitter.h.
|
inlinenodiscard |
Definition at line 76 of file oneway_transmitter.h.
| bool esphome::home_io_control::OneWayTransmitter::send_burst | ( | const IoFrame & | frame | ) |
Transmit one already-built, already-signed 1W frame as a burst.
Sends the frame ONEWAY_BURST_REPEATS times, ONEWAY_BURST_INTERVAL_MS apart, on FREQ_CH2 with LONG_PREAMBLE — the cadence real remotes use (proto_timing.h).
It retransmits identical bytes. The sequence and the MAC were fixed by the caller before this was called, and all copies must carry them unchanged: a device treats one sequence as one command, so four copies bearing four sequences are four commands, of which it will accept one and reject three as replays. This function therefore never rebuilds a frame, never touches a sequence counter, and takes the frame by const reference so it cannot.
It blocks for the whole burst, feeding the watchdog in the gaps. The three inter-copy gaps alone are 3 * ONEWAY_BURST_INTERVAL_MS = ~120 ms of pure delay; add each of the four copies' own airtime and the wall-clock total this function blocks for is closer to ~160 ms (proto_timing.h's ONEWAY_BURST_INTERVAL_MS comment has the same two numbers). Per ADR 0013 all radio work happens on the ESPHome loop and the operation queue is the concurrency model; an authenticated 2W exchange already blocks far longer than this. Scheduling the repeats through a timeout would add a second concurrency model and would let a queued 2W exchange interleave between copies of one command.
| frame | Signed 1W frame to send. |
Definition at line 245 of file oneway_transmitter.cpp.
| bool esphome::home_io_control::OneWayTransmitter::send_command | ( | const std::string & | controller_id, |
| CoverCommand | cmd ) |
Send a named command as the identity's controller.
Resolves the identity, reserves exactly one sequence for the whole command, builds and signs the frame with that identity's key, and bursts it.
Addresses a device class, not a device. Every device of io_device_type in range that holds the signing key acts on it — that is what 1W is, not a limitation to work around. Two devices of one class are separable only if they can be given separate identities.
| controller_id | YAML handle of the controller identity to transmit as. |
| cmd | Named command (STOP, FAVORITE, VENT). CoverCommand::FORCE_OPEN has no 1W encoding and cannot be built — see create_1w_execute_command() (proto_commands.h). |
Definition at line 95 of file oneway_transmitter.cpp.
| bool esphome::home_io_control::OneWayTransmitter::send_enrollment | ( | const std::string & | controller_id | ) |
Register this identity as a controller on every device currently in association mode (a physical PROG hold on the receiver, ADR 0026), using the gesture its manufacturer expects (resolve_oneway_wire_profile(), ADR 0032).
EnrollGesture::SOMFY (somfy / unset / any unprofiled vendor): 0x39 (remove, self-directed) then 0x30 (add) — the documented 1W handshake (the iown-homecontrol link-layer notes), both to the identity's own io_device_type, one burst each, matched by a real Smoove capture landing the two 128 ms apart (tests/corpus/captures/enrollment/somfy_smoove_enrollment_add_and_remove_controller_sx1276.yaml).
EnrollGesture::VELUX_KLI (manufacturer velux): 0x39 to the all-devices address, then a 0x30 burst to each class in effective_enrollment_classes() under one shared sequence, then a STOP and a DOWN EXECUTE to the all-devices address at the VELUX ACEI — the KLI-manual "press PAIR, then STOP then DOWN within 3 seconds" registration completion. Matches the issue #74 KLI 310 capture and samr037/iohc-flipper tx_runner.c. The STOP+DOWN half is unconfirmed against a VELUX capture (tests/corpus/captures/enrollment/synthetic_enrollment_velux_kli_prog_sweep.yaml).
The 0x30's MAC trailer is configurable via enrollment_with_mac: (default false, no MAC — see create_1w_add_controller()'s @warning). Real VELUX (#74) and real Somfy captures both use the no-MAC form; a real Izymo has separately accepted the MAC-bearing form too.
Blocks for the whole gesture feeding the watchdog in the gaps — up to ~6 s for the VELUX path (6 bursts: 0x39 + 3-class 0x30 sweep + STOP + DOWN, each ~1 s with LONG_PREAMBLE on every copy). This is a user-initiated, once-per-device action, the same shape as the pairing button (pairing_discovery_wait_ms → 5000); ADR 0032 records the exemption and the risk that the sweep+follow-up may not fit the KLI manual's own 3-second window at this cadence.
| controller_id | YAML handle of the controller identity to register. |
Definition at line 112 of file oneway_transmitter.cpp.
| bool esphome::home_io_control::OneWayTransmitter::send_position | ( | const std::string & | controller_id, |
| uint8_t | position ) |
Send a numeric position as the identity's controller.
Same contract as send_command(). Every position 0–100 is ordinary; none is a special code.
| controller_id | YAML handle of the controller identity to transmit as. |
| position | Target position 0–100 (0 = fully open, 100 = fully closed). |
Definition at line 103 of file oneway_transmitter.cpp.
| bool esphome::home_io_control::OneWayTransmitter::send_unenrollment | ( | const std::string & | controller_id | ) |
Un-register this identity from every device of its class currently in association mode (CMD 0x39) alone — also the prelude send_enrollment() fires before its own 0x30.
Reachable directly through the explicitly-named oneway_remove_controller native API action, for un-enrolling without immediately re-enrolling.
| controller_id | YAML handle of the controller identity to remove. |
Definition at line 235 of file oneway_transmitter.cpp.
|
inline |
Register the callback that receives a report after every command attempt.
| callback | Invoked once per logical command, including failed ones — a command that never left the hub is exactly the case a user needs to see, and 1W will not tell them. |
Definition at line 81 of file oneway_transmitter.h.
| void esphome::home_io_control::OneWayTransmitter::setup | ( | ) |
Open each registered identity's persistent sequence counter.
Call once from the hub's setup(), never from generated wiring.
Definition at line 24 of file oneway_transmitter.cpp.