Home IO Control
ESPHome add-on for IO-Homecontrol devices
Loading...
Searching...
No Matches
home_io_control.platform_common Namespace Reference

Functions

 companion_entity_name (config, suffix)
 companion_id_base (config, parent_id_key)
 inject_companion_sensor_ids (config, parent_id_key)
 validate_entity_name (value)
 platform_schema_extension ()
 config_model (config)
 _kind_label (device_type, subtype, model=None)
 validate_device_model (config)
 warn_if_experimental_kind (config)
 deprecated_key (key, replacement)
 declared_features (config)
 validate_register_poll_interval (config, platform)
 require_feature (config, key, active, *, required=0, forbidden=0, reason)
 wire_device_binding (var, parent, config)
 _create_companion_text_sensor (config, parent, sensor_id, name, disabled_by_default)
 _create_link_health_sensor (config, parent, sensor_id, name, **sensor_kwargs)
 create_companion_sensors (config, parent)

Variables

 _LOGGER = logging.getLogger(__name__)
tuple REPORTING_DEVICES_URL
str CONF_IO_DEVICE_ID = "io_device_id"
str CONF_LINKED_REMOTES = "linked_remotes"
str CONF_DEVICE_TYPE = "io_device_type"
str CONF_SUBTYPE = "io_subtype"
str CONF_MODEL = "io_model"
str CONF_STATUS_POLL_INTERVAL = "status_poll_interval"
str CONF_DEVICE_NAME_SENSOR_ID = "_device_name_sensor_id"
str CONF_ACTIVE_ISSUE_SENSOR_ID = "_active_issue_sensor_id"
str CONF_RSSI_SENSOR_ID = "_rssi_sensor_id"
str CONF_LAST_CONTACT_SENSOR_ID = "_last_contact_sensor_id"
str CONF_EXCHANGE_FAILURES_SENSOR_ID = "_exchange_failures_sensor_id"
str CONF_UNCONFIRMED_EXCHANGES_SENSOR_ID = "_unconfirmed_exchanges_sensor_id"
str CONF_LAST_COMMANDED_BY_SENSOR_ID = "_last_commanded_by_sensor_id"
str CONF_LAST_COMMAND_SOURCE_SENSOR_ID = "_last_command_source_sensor_id"
 IOHomeDeviceNameTextSensor
 IOHomeActiveIssueTextSensor
 IOHomeRssiSensor = home_io_control_ns.class_("IOHomeRssiSensor", sensor.Sensor, cg.Component)
 IOHomeLastContactSensor
 IOHomeExchangeFailuresSensor
 IOHomeUnconfirmedExchangesSensor
 IOHomeLastCommandedByTextSensor
 IOHomeLastCommandSourceTextSensor
tuple _COMPANION_SENSOR_IDS
dict INSTANT_LIGHT_TRANSITION
int MIN_REGISTER_POLL_INTERVAL_MS = 60000

Function Documentation

◆ _create_companion_text_sensor()

_create_companion_text_sensor ( config,
parent,
sensor_id,
name,
disabled_by_default )
protected
Shared body for the auto-generated companion `text_sensor:` entities.

Definition at line 446 of file platform_common.py.

◆ _create_link_health_sensor()

_create_link_health_sensor ( config,
parent,
sensor_id,
name,
** sensor_kwargs )
protected
Shared body for the auto-generated link-health `sensor:` companions.

All of them (RSSI, Last Contact, Exchange Failures, Unconfirmed Exchanges) are numeric,
diagnostic, and disabled by default (noise control); only the name and sensor-specific schema keys
(unit/device_class/state_class/accuracy_decimals) differ between them, so those are the
only things each call in create_companion_sensors() supplies.

Definition at line 463 of file platform_common.py.

◆ _kind_label()

_kind_label ( device_type,
subtype,
model = None )
protected
The declared kind as a user wrote it: the io_device_type name (or hex value) and, when set,
io_subtype and io_model.

Definition at line 257 of file platform_common.py.

◆ companion_entity_name()

companion_entity_name ( config,
suffix )
Derive a companion entity's name from the parent entity name and a suffix.

Definition at line 138 of file platform_common.py.

◆ companion_id_base()

companion_id_base ( config,
parent_id_key )
Return the shared ID prefix for a platform's companion entity IDs.

ESPHome 2026.x sizes its runtime component vector (StaticVector) from the number of
component IDs known at the end of schema validation — before to_code() runs.  If
companion entities are only created inside to_code(), their IDs are not counted and
the StaticVector overflows at runtime, silently dropping later components whose
setup() then never executes.  Companion IDs must therefore be declared during
validation, and they all share the prefix returned here.

``parent_id_key`` differs per platform: light reads the entity ID from
CONF_OUTPUT_ID, while cover, switch and lock read it from CONF_ID. Falls back to the
entity's CONF_ID (the sibling LightState, for light) when parent_id_key's own field wasn't
manually set, then to a sanitized form of the entity name. Raises cv.Invalid when neither an
explicit id: nor a non-empty name: is available to derive a unique prefix from — reachable via
the `name: ""`/`name: None` device-name idiom (see validate_entity_name()) without an id:.

Definition at line 146 of file platform_common.py.

◆ config_model()

config_model ( config)
The DEVICE_MODEL_OPTIONS value of the entry's io_model:, 0 when it declares none.

Definition at line 252 of file platform_common.py.

◆ create_companion_sensors()

create_companion_sensors ( config,
parent )
Create and register every auto-generated companion diagnostic sensor.

Single to_code() entry point for the device-bound platforms (the counterpart of
inject_companion_sensor_ids()), so adding a companion touches this module only:

- Device Name: disabled by default (clutter control).
- Active Issue: the one enabled-by-default companion — it is the headline diagnostic
  value that turns a silently-ignored command into a self-explained one (e.g. a
  wind/rain lockout), so users should see it without an opt-in step. Empty except while
  an issue is outstanding (a refusal, a derived rain limitation, or a radio that stopped
  responding); see IOHomeActiveIssueTextSensor.
- RSSI / Last Contact / Exchange Failures: numeric link-health diagnostics, disabled by
  default (noise control). Last Contact publishes seconds since the last frame from the
  device (an age, not a Home Assistant timestamp) and keeps counting up between frames via
  its own heartbeat; see IOHomeLastContactSensor.
- Last Commanded By / Last Command Source: who/what last commanded the device, disabled by
  default (noise control). Free — decoded from bytes already present in every status reply,
  no extra radio traffic; see IOHomeLastCommandedByTextSensor.

Definition at line 495 of file platform_common.py.

Here is the call graph for this function:

◆ declared_features()

declared_features ( config)
The capability word of the kind an entry declares (io_device_type, io_subtype, io_model).

0 when the entry declares no io_device_type: nothing at validation time says what the device is,
so it has no feature a validator may rely on.

Definition at line 353 of file platform_common.py.

Here is the call graph for this function:

◆ deprecated_key()

deprecated_key ( key,
replacement )
Build a post-validator that warns, without rejecting, about a key that is being retired.

The first stage of retiring a key: the config stays legal and behaves as before, and one
warning names the entity, says the key will become a config error, and gives the replacement.
The second stage swaps this validator for one that raises cv.Invalid with the same replacement.

@param key The YAML key being retired.
@param replacement Called with the validated config when the key is present; returns the
    sentence(s) saying what to write instead and what changes in Home Assistant.

Definition at line 317 of file platform_common.py.

◆ inject_companion_sensor_ids()

inject_companion_sensor_ids ( config,
parent_id_key )
Declare every auto-generated companion sensor ID during schema validation.

Shared post-validator body for every device-bound platform, covering all entries in
_COMPANION_SENSOR_IDS. See companion_id_base() for why the IDs must be declared at
validation time rather than in to_code().

Definition at line 196 of file platform_common.py.

Here is the call graph for this function:

◆ platform_schema_extension()

platform_schema_extension ( )
Return the shared schema keys every device-bound platform extends with.

Definition at line 232 of file platform_common.py.

◆ require_feature()

require_feature ( config,
key,
active,
* ,
required = 0,
forbidden = 0,
reason )
Reject a YAML key the declared device kind cannot use.

One gate for every feature-dependent key. It only fires when the config declares
``io_device_type`` (without a kind nothing says what the device can do), ``active`` is true
(the caller decides, because keys differ: ``silent:`` is active by presence, ``dimmable:``
only when true), and the kind's capability word lacks a ``required`` bit or has a
``forbidden`` one. ``reason`` says what to do about it.

Definition at line 386 of file platform_common.py.

Here is the call graph for this function:

◆ validate_device_model()

validate_device_model ( config)
Accept io_model: only where the declared io_device_type / io_subtype offers that model.

A post-validator for every device-bound platform. A model is a row below a (type, subtype)
(ADR 0067), so it means nothing without both keys; the error names the models the declared kind
offers, or says it offers none.

Definition at line 269 of file platform_common.py.

◆ validate_entity_name()

validate_entity_name ( value)
Validate a device-bound platform's `name:`, keeping it required but honoring ESPHome's
device-name idiom (`name: ""` or the YAML literal `name: None`/`none` — both mean "this
entity displays as just its sub-device's name", see companion_id_base()'s empty-name path).

ENTITY_BASE_SCHEMA's own Optional(CONF_NAME) validator (`esphome.config_validation
._validate_entity_name`) never runs for these platforms — platform_schema_extension()
overrides that key with a Required one — so its None -> "" conversion, its NAME_MAX_LENGTH
check, and its '/' handling all have to be reapplied here. Delegating rather than
reimplementing keeps `name: ""` / `name: None` behaving exactly as they do in every other
ESPHome component, including upstream's own asymmetry: `name: None` additionally requires
`esphome: friendly_name:` to be set (matching Home Assistant's own null-name convention),
while `name: ""` does not.

Definition at line 211 of file platform_common.py.

◆ validate_register_poll_interval()

validate_register_poll_interval ( config,
platform )
Raise the status_poll_interval floor to one minute on a platform whose poll reads registers.

A post-validator for climate and water_heater, bound to the platform name with functools.partial so the
message says which one. The key itself is accepted by the shared platform schema.

Definition at line 370 of file platform_common.py.

◆ warn_if_experimental_kind()

warn_if_experimental_kind ( config)
Warn, without rejecting, that the declared kind is not yet confirmed on a real device.

A post-validator for every device-bound platform. The config is legal and still transmits, so
this logs one warning (the pattern of the other warn-only validators) that names the kind and
points at the page for reporting a result. A config that declares no kind passes silently.

Definition at line 297 of file platform_common.py.

Here is the call graph for this function:

◆ wire_device_binding()

wire_device_binding ( var,
parent,
config )
Emit the shared to_code() wiring that binds an entity to its hub device.

Covers set_parent / set_device_id, the optional device type / subtype / model / status
poll interval / low-power class, and the linked-remotes registration loop —
identical across all four device-bound platforms.

Definition at line 404 of file platform_common.py.

Here is the call graph for this function:

Variable Documentation

◆ _COMPANION_SENSOR_IDS

tuple home_io_control.platform_common._COMPANION_SENSOR_IDS
protected
Initial value:
= (
(CONF_DEVICE_NAME_SENSOR_ID, "device_name_sensor", IOHomeDeviceNameTextSensor),
(CONF_ACTIVE_ISSUE_SENSOR_ID, "active_issue_sensor", IOHomeActiveIssueTextSensor),
(CONF_RSSI_SENSOR_ID, "rssi_sensor", IOHomeRssiSensor),
(CONF_LAST_CONTACT_SENSOR_ID, "last_contact_sensor", IOHomeLastContactSensor),
(CONF_EXCHANGE_FAILURES_SENSOR_ID, "exchange_failures_sensor", IOHomeExchangeFailuresSensor),
(
CONF_UNCONFIRMED_EXCHANGES_SENSOR_ID,
"unconfirmed_exchanges_sensor",
IOHomeUnconfirmedExchangesSensor,
),
(CONF_LAST_COMMANDED_BY_SENSOR_ID, "last_commanded_by_sensor", IOHomeLastCommandedByTextSensor),
(CONF_LAST_COMMAND_SOURCE_SENSOR_ID, "last_command_source_sensor", IOHomeLastCommandSourceTextSensor),
)

Definition at line 122 of file platform_common.py.

◆ _LOGGER

home_io_control.platform_common._LOGGER = logging.getLogger(__name__)
protected

Definition at line 63 of file platform_common.py.

◆ CONF_ACTIVE_ISSUE_SENSOR_ID

str home_io_control.platform_common.CONF_ACTIVE_ISSUE_SENSOR_ID = "_active_issue_sensor_id"

Definition at line 87 of file platform_common.py.

◆ CONF_DEVICE_NAME_SENSOR_ID

str home_io_control.platform_common.CONF_DEVICE_NAME_SENSOR_ID = "_device_name_sensor_id"

Definition at line 85 of file platform_common.py.

◆ CONF_DEVICE_TYPE

str home_io_control.platform_common.CONF_DEVICE_TYPE = "io_device_type"

Definition at line 77 of file platform_common.py.

◆ CONF_EXCHANGE_FAILURES_SENSOR_ID

str home_io_control.platform_common.CONF_EXCHANGE_FAILURES_SENSOR_ID = "_exchange_failures_sensor_id"

Definition at line 91 of file platform_common.py.

◆ CONF_IO_DEVICE_ID

str home_io_control.platform_common.CONF_IO_DEVICE_ID = "io_device_id"

Definition at line 75 of file platform_common.py.

◆ CONF_LAST_COMMAND_SOURCE_SENSOR_ID

str home_io_control.platform_common.CONF_LAST_COMMAND_SOURCE_SENSOR_ID = "_last_command_source_sensor_id"

Definition at line 95 of file platform_common.py.

◆ CONF_LAST_COMMANDED_BY_SENSOR_ID

str home_io_control.platform_common.CONF_LAST_COMMANDED_BY_SENSOR_ID = "_last_commanded_by_sensor_id"

Definition at line 94 of file platform_common.py.

◆ CONF_LAST_CONTACT_SENSOR_ID

str home_io_control.platform_common.CONF_LAST_CONTACT_SENSOR_ID = "_last_contact_sensor_id"

Definition at line 90 of file platform_common.py.

◆ CONF_LINKED_REMOTES

str home_io_control.platform_common.CONF_LINKED_REMOTES = "linked_remotes"

Definition at line 76 of file platform_common.py.

◆ CONF_MODEL

str home_io_control.platform_common.CONF_MODEL = "io_model"

Definition at line 81 of file platform_common.py.

◆ CONF_RSSI_SENSOR_ID

str home_io_control.platform_common.CONF_RSSI_SENSOR_ID = "_rssi_sensor_id"

Definition at line 89 of file platform_common.py.

◆ CONF_STATUS_POLL_INTERVAL

str home_io_control.platform_common.CONF_STATUS_POLL_INTERVAL = "status_poll_interval"

Definition at line 82 of file platform_common.py.

◆ CONF_SUBTYPE

str home_io_control.platform_common.CONF_SUBTYPE = "io_subtype"

Definition at line 78 of file platform_common.py.

◆ CONF_UNCONFIRMED_EXCHANGES_SENSOR_ID

str home_io_control.platform_common.CONF_UNCONFIRMED_EXCHANGES_SENSOR_ID = "_unconfirmed_exchanges_sensor_id"

Definition at line 92 of file platform_common.py.

◆ INSTANT_LIGHT_TRANSITION

dict home_io_control.platform_common.INSTANT_LIGHT_TRANSITION
Initial value:
= {
cv.Optional(CONF_DEFAULT_TRANSITION_LENGTH, default="0s"): cv.positive_time_period_milliseconds
}

Definition at line 348 of file platform_common.py.

◆ IOHomeActiveIssueTextSensor

home_io_control.platform_common.IOHomeActiveIssueTextSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeActiveIssueTextSensor", text_sensor.TextSensor, cg.Component
)

Definition at line 100 of file platform_common.py.

◆ IOHomeDeviceNameTextSensor

home_io_control.platform_common.IOHomeDeviceNameTextSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeDeviceNameTextSensor", text_sensor.TextSensor, cg.Component
)

Definition at line 97 of file platform_common.py.

◆ IOHomeExchangeFailuresSensor

home_io_control.platform_common.IOHomeExchangeFailuresSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeExchangeFailuresSensor", sensor.Sensor, cg.Component
)

Definition at line 107 of file platform_common.py.

◆ IOHomeLastCommandedByTextSensor

home_io_control.platform_common.IOHomeLastCommandedByTextSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeLastCommandedByTextSensor", text_sensor.TextSensor, cg.Component
)

Definition at line 113 of file platform_common.py.

◆ IOHomeLastCommandSourceTextSensor

home_io_control.platform_common.IOHomeLastCommandSourceTextSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeLastCommandSourceTextSensor", text_sensor.TextSensor, cg.Component
)

Definition at line 116 of file platform_common.py.

◆ IOHomeLastContactSensor

home_io_control.platform_common.IOHomeLastContactSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeLastContactSensor", sensor.Sensor, cg.Component
)

Definition at line 104 of file platform_common.py.

◆ IOHomeRssiSensor

home_io_control.platform_common.IOHomeRssiSensor = home_io_control_ns.class_("IOHomeRssiSensor", sensor.Sensor, cg.Component)

Definition at line 103 of file platform_common.py.

◆ IOHomeUnconfirmedExchangesSensor

home_io_control.platform_common.IOHomeUnconfirmedExchangesSensor
Initial value:
= home_io_control_ns.class_(
"IOHomeUnconfirmedExchangesSensor", sensor.Sensor, cg.Component
)

Definition at line 110 of file platform_common.py.

◆ MIN_REGISTER_POLL_INTERVAL_MS

int home_io_control.platform_common.MIN_REGISTER_POLL_INTERVAL_MS = 60000

Definition at line 367 of file platform_common.py.

◆ REPORTING_DEVICES_URL

tuple home_io_control.platform_common.REPORTING_DEVICES_URL
Initial value:
= (
"https://laberning.github.io/home_io_control/contributing.html#reporting-unsupported-devices"
)

Definition at line 67 of file platform_common.py.