Files
localthings/custom_components/localthings/const.py
T
Marc Billow 037dc9722f feat: add options flow to bypass the remote-control write block per device (issue #54)
The remote-control-off write block was device-wide and unconditional:
whenever a device reports remote control off, every write is rejected
with a user-facing error, on the assumption the device would reject it
anyway. Issue #54 reports a washer where that assumption doesn't hold --
default detergent/softener dosing writes through even with remote
control off, since they apply to the built-in programs too, not just a
custom remote-controlled cycle.

Add a per-device options flow (Settings > Devices & Services > this
device > Configure) with a single toggle, stored in entry.options (not
entry.data) so it doesn't affect the device's identity/unique_id.
coordinator.async_send_command reads it ahead of the existing
remote_control_enabled() check; defaults to False everywhere, so devices
that don't touch this option see no change in behavior.
2026-07-24 03:32:49 +00:00

50 lines
2.1 KiB
Python

DOMAIN = "localthings"
PLATFORMS = [
"sensor", "binary_sensor", "switch", "number", "select", "button",
"time", "climate", "fan",
]
CONF_HOST = "host"
CONF_PORT = "port"
CONF_CA_CERT_PEM = "ca_cert_pem"
CONF_CA_KEY_PEM = "ca_key_pem"
CONF_LEAF_CERT_PEM = "leaf_cert_pem"
CONF_LEAF_KEY_PEM = "leaf_key_pem"
# Options-flow key (entry.options, not entry.data): lets a user override the
# device-wide remote-control-off write block for a specific device (issue
# #54). Some devices report remote control off yet still accept certain
# writes (e.g. default detergent/softener dosing on a washer, applied even
# to the built-in programs) -- the block exists to give a clear error
# instead of a silent device-side rejection, but that assumption doesn't
# hold for every model. Defaults to False (block stays on) everywhere it's
# read, so devices this doesn't apply to see no behavior change.
CONF_BYPASS_REMOTE_CONTROL = "bypass_remote_control_lock"
# The DTLS/CoAP local API binds somewhere in this ephemeral range; which port
# depends on firmware. Newer builds answer on 49154/49155, but older ones have
# been seen as low as 49153, so we sweep the whole range for a live UDP port
# before attempting the (expensive) DTLS handshake.
PROBE_PORT_RANGE = list(range(49152, 49161))
# Ports we've historically seen complete a DTLS handshake. When more than one
# port in the range looks live, these are tried first.
PREFERRED_PROBE_PORTS = [49154, 49155]
# Per-port timeout for the cheap UDP liveness sweep. Closed ports return an
# ICMP port-unreachable almost immediately; a live-but-silent port is only
# detected by this timeout elapsing, so keep it short.
LIVENESS_PROBE_TIMEOUT_S = 1.5
# Deadline for the blockwise /device/0 GET during the config-flow probe. The
# slowest device observed returns a full dump in ~8s, so 10s leaves headroom
# without stalling setup; it matches the per-resource read timeout elsewhere.
PROBE_GET_TIMEOUT_S = 10.0
SUMMARY_INTERVAL_S = 30.0
DEVICE_SUPPORT_ISSUE_URL = (
"https://github.com/mbillow/localthings/issues/new?template=device-support.yml"
)