Skip to content

Releases: danielpetrovic/somfy-io-bridge

v2026.07.6

Choose a tag to compare

@danielpetrovic danielpetrovic released this 13 Jul 12:57

What's Changed

Fixes a real production incident where simultaneous cover commands could put motors into an error state requiring manual TaHoma intervention, and removes two diagnostic features (Target Closure/Last RSSI sensors, Get Name (2W)) that either depended on the same problematic continuous decoding or provided little real value.

Changes

  • Fixed: a burst of simultaneous 1W commands to multiple covers with no spacing could put motors into an RF error state - enforced a 500ms minimum gap between queued sends
  • Fixed: continuous passive 2W frame decoding (RSSI tracking, key sniffer, bonding frame handling) was colliding with TaHoma's own concurrent polling, contributing to the same incident - now opt-in via a "Debug Passive Decode (2W)" switch, off by default
  • Removed: Target Closure and Last RSSI sensors (passive 2W position/signal decode) - pulled out entirely rather than left half-working behind a toggle, until real 2W control exists
  • Removed: Get Name (2W) button and the automatic device-naming call during bonding - neither is part of the reference implementations' pairing flow and provided little real value
  • Changed: renamed "Channel Hop (2W)" -> "Debug Channel Hop (2W)" and "Passive Decode (2W)" -> "Debug Passive Decode (2W)" for clarity that both are diagnostic-only, not needed for normal use
  • Changed: corrected the README's comparison table against the actual current state of the three reference projects (fixed a wrong license attribution, added 1W/2W bonding/control comparison rows, added nicolas5000/io-rts-esp32 as its own column)

Upgrade Notes

  • If any automations/dashboards reference the Target Closure or Last RSSI sensors, remove them - those entities no longer exist after this update
  • Reload the device after updating (git-sourced component, refresh: 0s already pulls the latest code on next compile)

v2026.07.5

Choose a tag to compare

@danielpetrovic danielpetrovic released this 12 Jul 21:38

What's Changed

First release since this bridge was split out from the private home-assistant-config monorepo into its own standalone, public repo (full history preserved). The main functional change: components/iohc is no longer a local dependency you need to copy - it's fetched automatically via git at compile time.

Changes

  • Changed: components/iohc now sourced via external_components: type: git (github://danielpetrovic/somfy-io-bridge) instead of a local type: local path - no more manual copying of the components folder into your own esphome/ directory, ESPHome fetches it straight from this repo at compile time
  • Changed: Setup instructions and Files section updated to match - step 2 now only asks for the two YAML files
  • Added: comparison table (README) extended to cover laberning/home_io_control alongside rspaargaren/iohomecontrol, including a dedicated note on 2W bonding status
  • Fixed: the in-YAML project: version: field, which had drifted stale across the last two releases (dashboard/HA device info was showing an outdated version number) - now correctly tracks the actual release

Upgrade Notes

  • Reflash somfy-io-bridge.yaml to pick up the git-source change - if you have a local components/iohc/ folder from before, you can safely delete it, it's no longer read
  • No other config changes required

v2026.07.4

Choose a tag to compare

@danielpetrovic danielpetrovic released this 12 Jul 20:30

What's Changed

Continued work on this bridge's own 2W bonding (still not achieving a real bond against real hardware, but substantially more complete and better-understood), plus new 2W diagnostics, a persistent 2W identity option, two real bug fixes, a new Last RSSI sensor, and entity organization cleanup.

Changes

  • Added: 2W bonding state machine (Program (2W) button) - redesigned mid-development after discovering the original directionality assumption was backwards (the controller must broadcast DISCOVER, not the motor) and a crypto bug (wrong key used for ongoing challenge/response). Both fixes verified byte-for-byte against two independent working reference implementations. Bonding has still never succeeded against real hardware - see README's "2W bonding: current status and open problem" section for the full investigation.
  • Added: DISCOVER_CONFIRMATION (0x2C/0x2D) bonding step
  • Added: Listen-Before-Talk RF collision avoidance and an opt-in fast 3-channel RX hop ("Channel Hop (2W)" switch, or automatic during an active bonding attempt) - confirmed an always-on hop breaks ordinary 1W reception, so it stays off by default
  • Added: passive key sniffer, watching all traffic for a real key-transfer exchange to recover an already-established key
  • Added: Get Name (2W) diagnostic button, and automatic motor naming (Set Name) on a successful bond
  • Added: persistent 2W controller identity (controller_address/system_key), mirroring each cover's existing per-motor node/key pattern, so a board replacement can reproduce the same 2W identity
  • Added: Last RSSI sensor per cover - this bridge's own signal strength for a motor, independent of Overkiz's own RSSI sensors
  • Fixed: RemoteButton::Add previously only sent the bare Add frame instead of the full 4-step ceremony a real remote uses, so a fresh 1W pairing never fully registered with the motor - confirmed fixed on real hardware
  • Fixed: passive 2W position decode could be corrupted by a Stop/Vent command's echoed sentinel being misread as a position - now range-checked before decoding
  • Fixed: 1W transmit call sites now explicitly retune to CH2 before sending, preventing a possible wrong-channel transmission now that the radio can be hopping in the background
  • Changed: mode select's "Two-Way (Soon)" renamed to "Two-Way (Experimental)" now that the control path is real, even though bonding itself doesn't yet work
  • Changed: entity categories reorganized (Program buttons/Identify/Get Name now categorized; Debug Logging and the new Channel Hop switch stay in Controls)

Upgrade Notes

  • Reflash somfy-io-bridge.yaml to pick up all of the above
  • 2W bonding remains non-functional - Position/Open-My-Close modes are unaffected and continue to work as before
  • Recommended: remove and re-add the integration after flashing, so entity categories cleanly populate across all pages - entity_category only applies to newly-registered entities, so an existing install won't reflect the new Controls/Configuration/Diagnostic grouping otherwise

v2026.07.3

Choose a tag to compare

@danielpetrovic danielpetrovic released this 12 Jul 20:30

What's Changed

Fixes a real bug where the Position command sent the wrong target byte to the motor - unlike RTS (which has no percentage command and must fake intermediate positions via open-loop timing), IO has always sent a genuine target-percentage command that the motor executes on its own. That command was carrying the wrong value, so the motor would land at roughly half the requested closure instead of the actual target. Also adds real position feedback via passive 2W decode - the first step past pure local estimation.

Changes

  • Fixed: Position command sent main[0]=(100-p) instead of (100-p)*2 - confirmed via a clean hardware test that the motor reads main[0] on the same raw/2=percent scale its own status reports use. Verified fixed on two independent physical motors.
  • Changed: mode renamed from 1W Timed/1W My/2W to Position/Open-My-Close/Two-Way (Soon), with Position now the default (was My). Travel Time Open/Close removed as a user-configurable setting - fixed at 25s, since the local estimate is cosmetic and never affects where the motor actually ends up.
  • Added: real position feedback via passive 2W decode - a standalone Target Closure sensor per cover (motor_address config) populated whenever an existing 2W-bonded controller (e.g. TaHoma) is overheard talking to the motor. Deliberately never touches the cover's own position/state, only the sensor - an earlier version that did backfired when a garbled reception corrupted the real control entity.
  • Fixed: cover position and Target Closure sensor now persist across reboots (NVS-backed) - previously Position mode silently reset the displayed position to 0% (closed) on every reboot regardless of the real physical state.
  • Fixed: local position estimate only publishes/logs on whole-percent changes now, instead of spamming on every ~0.1% tick.
  • Fixed: constant "IO 26/32 is not set as GPIO" warnings (missing pinMode() before attachInterrupt() on the radio's DIO pins).
  • Fixed: unconditional ets_printf() radio-level tracing spamming the log regardless of logger setting - removed ISR-context call sites, converted the rest to ESP_LOGV under "iohc.radio".
  • Fixed: cover's key config field (AES pairing key) now wrapped in cv.sensitive() for deterministic redaction.
  • Removed: experimental "Test 2W Query" diagnostic button, its purpose was answered.
  • Also included (from the preceding commit in this release): motor_address wiring for all 14 covers, Target Closure sensor replacing per-cover Travel Time number entities, Debug Logging switch, Display on/off switch, Display Brightness and Display Page Interval controls.

Not Yet Implemented

  • 2W active bonding/query (real position feedback currently requires an existing 2W-bonded controller like TaHoma to be overheard - see README's "Real position feedback" section for the caveat)

Upgrade Notes

  • Reflash somfy-io-bridge.yaml to pick up the Position fix - if you were using Position mode before this release, positions sent were landing wrong and should be reissued after upgrading
  • To get real position feedback, set motor_address per cover (see README) - requires an existing 2W-bonded controller (e.g. TaHoma/Overkiz) already active on the installation

v2026.07.2

Choose a tag to compare

@danielpetrovic danielpetrovic released this 12 Jul 20:29

What's Changed

Confirms full 1W functionality against real hardware: pairing/unpairing, Open/Close/Stop/My/Position, and Identify all now working end-to-end, and expands from 3 covers to all 14 real IO shutters.

Changes

  • Fixed: My (favorite position) was sending the wrong second byte (0x03 instead of 0x00), copied from upstream without cross-checking a real capture - now confirmed working, distinct from Stop
  • Fixed: Program (pairing) now decides Add vs Remove from its own persisted bonding record instead of assuming the motor toggles on a shared signal - confirmed working, including successful pairing and unpairing across multiple real shutters
  • Added: Identify / Start Identify / Stop Identify buttons per cover - confirmed working, jogs the motor to help visually locate it
  • Added: dedicated My button per cover (previously only reachable via the position slider)
  • Added: all 14 real IO shutters, each with a fixed node/key identity from the start (previously only 3 covers, one on a random identity)
  • Added: OLED page cycling (one page per cover, matching the RTS bridge) instead of a single static status page
  • Added: diagnostic entities (WiFi Signal, Uptime, Loop Time, Restart Reason, Restart)

Not Yet Implemented

  • 2W (real position feedback)

Upgrade Notes

  • Reflash somfy-io-bridge.yaml to pick up the My/Program/Identify fixes and new covers
  • New covers should be given a fixed node/key from the start (see README's Board-independent identity section) rather than the random default

v2026.07.1

Choose a tag to compare

@danielpetrovic danielpetrovic released this 12 Jul 20:29

What's Changed

Initial release of the Somfy IO Bridge - local, cloud-free ESPHome control of io-homecontrol (Somfy IO) covers, complementing the Somfy RTS Bridge. 1W (one-way) command support only; 2W (real position feedback) is a known future effort.

Changes

  • Added: Real-time passive reception/decode of io-homecontrol traffic (RSSI per source address, logged)
  • Added: Pairing (Add) and unpairing (Remove) of a virtual remote identity against a real motor, alongside any existing remote
  • Added: Open/Close/Stop and absolute Position (0-100%) commands, confirmed working against real hardware
  • Added: Per-cover "Mode" select - "1W My" (default, matches the RTS bridge's 3-state model) / "1W Timed" (travel-time position estimate) / "2W" (placeholder, not implemented)
  • Added: per-cover "Travel Time Open"/"Travel Time Close" number entities for Timed mode, adjustable live from Home Assistant, persists across reboots
  • Added: Board-independent bonded identity - optional fixed node/key via secrets.yaml so a board replacement doesn't require re-pairing every motor
  • Added: Each cover exposed as its own Home Assistant device, grouped by Area (matching the RTS bridge's own pattern)
  • Added: Onboard SSD1306 OLED status display (packet count, RSSI, IP address)

Known Issues

  • "My" (go to favorite position) doesn't reliably work while the cover is idle, even though the identical byte sequence from a real Situo remote does. Open/Close/Stop all work correctly. Leading theory: our transmissions aren't repeating like a real remote's (4x + a follow-up frame); needs a live serial session to chase further.
  • 2W (two-way, real position feedback) is not implemented - status frames are logged but not decrypted.

Planned Next

  • Get the 1W modes (My/Timed) fully reliable first, starting with the idle-My issue above
  • 2W after that - a larger, separate effort since upstream's own reference implementation describes 2W as unstable even in their hands; no firm timeline

Upgrade Notes

  • First release - flash somfy-io-bridge.yaml via the ESPHome dashboard (USB for the first flash)
  • See the README for full setup instructions, including secrets.yaml, per-cover area/device configuration, and the optional board-independent identity setup