Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
esphome::home_io_control::OneWayTransmitter Class Reference

Sends 1W commands as the repeated bursts real remotes send. More...

#include <oneway_transmitter.h>

Collaboration diagram for esphome::home_io_control::OneWayTransmitter:

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 OneWayControllerRegistryidentities () 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.

Detailed Description

Sends 1W commands as the repeated bursts real remotes send.

Definition at line 57 of file oneway_transmitter.h.

Constructor & Destructor Documentation

◆ OneWayTransmitter()

esphome::home_io_control::OneWayTransmitter::OneWayTransmitter ( OneWayTransmitFn transmit)
inlineexplicit
Parameters
transmitHow to put a frame on air; must stay valid for this object's lifetime.

Definition at line 60 of file oneway_transmitter.h.

Member Function Documentation

◆ add_identity()

void esphome::home_io_control::OneWayTransmitter::add_identity ( const OneWayControllerIdentity & identity)
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.

Parameters
identityFully-resolved identity (address and key already decided at schema time).

Definition at line 69 of file oneway_transmitter.h.

◆ identities()

const OneWayControllerRegistry & esphome::home_io_control::OneWayTransmitter::identities ( ) const
inlinenodiscard
Returns
The configured controller identities.

Definition at line 76 of file oneway_transmitter.h.

◆ send_burst()

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.

Parameters
frameSigned 1W frame to send.
Returns
true if at least one copy reached the radio. Partial success is still reported as success because it is genuinely what the caller wants to know — with no reply frame, "some copies went out" is the most any layer here can ever establish, and a device needs only one of them.

Definition at line 245 of file oneway_transmitter.cpp.

Here is the call graph for this function:

◆ send_command()

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.

Parameters
controller_idYAML handle of the controller identity to transmit as.
cmdNamed command (STOP, FAVORITE, VENT). CoverCommand::FORCE_OPEN has no 1W encoding and cannot be built — see create_1w_execute_command() (proto_commands.h).
Returns
true if at least one copy reached the radio; false if the identity is unknown, the sequence could not be reserved, or the frame could not be built.

Definition at line 95 of file oneway_transmitter.cpp.

Here is the call graph for this function:

◆ send_enrollment()

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.

Parameters
controller_idYAML handle of the controller identity to register.
Returns
true if the credential frame(s) that actually register this identity reached the radio — the 0x30 (SOMFY) or the sweep (VELUX_KLI). The VELUX STOP+DOWN follow-up is skipped entirely if the sweep transmitted nothing; a failed 0x39 prelude, or a partial STOP/DOWN after a good sweep, only logs and does not flip this.

Definition at line 112 of file oneway_transmitter.cpp.

Here is the call graph for this function:

◆ send_position()

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.

Parameters
controller_idYAML handle of the controller identity to transmit as.
positionTarget position 0–100 (0 = fully open, 100 = fully closed).
Returns
true if at least one copy reached the radio.

Definition at line 103 of file oneway_transmitter.cpp.

Here is the call graph for this function:

◆ send_unenrollment()

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.

Warning
Unconfirmed standalone on real hardware. Firing 0x39 alone (outside the enrollment handshake) has had no observable effect on this project's test hardware; the leading hypothesis is that it needs the same association-mode window enrollment does. See ADR 0026 § Consequences.
Parameters
controller_idYAML handle of the controller identity to remove.
Returns
true if at least one copy reached the radio.

Definition at line 235 of file oneway_transmitter.cpp.

Here is the call graph for this function:

◆ set_command_report_callback()

void esphome::home_io_control::OneWayTransmitter::set_command_report_callback ( OneWayCommandReportFn callback)
inline

Register the callback that receives a report after every command attempt.

Parameters
callbackInvoked 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.

◆ setup()

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.


The documentation for this class was generated from the following files: