
Controllable
Virtual Switches with Sync Tracking for Conflict-Free Automation
A Home Assistant custom integration that creates virtual switch entities with sync status tracking to prevent automation conflicts with manual control. These sync-aware virtual switches act as proxies for real entities, tracking whether manual overrides have occurred so automations can respect human preferences instead of fighting them. Solve the frustrating problem of automations immediately undoing your manual changes.
🔗 View on GitHub • 📖 Documentation • ⬇️ Install via HACS
The Problem: Automation vs. Manual Control Conflicts
One of Home Assistant’s most frustrating problems occurs when automations conflict with manual control. Picture this scenario: your automation turns on the bedroom light at sunset. You manually turn it off because you’re watching a movie. Two minutes later, the automation runs its next check and turns the light back on because it doesn’t know you manually overrode it. You turn it off again. The automation turns it on again. This annoying battle continues until you either disable the automation, physically disconnect the light, or give up and leave it on.
This conflict arises because standard automations only look at state, not intent. The automation sees “light should be on at sunset” and enforces that rule without understanding whether the current state represents automation control or human preference. When you manually change a device, Home Assistant has no built-in way to signal “this was intentional, don’t override it” versus “this is fine for automation to manage.”
The problem manifests in countless scenarios beyond lighting. A fan automation turns on when temperature exceeds a threshold, but you manually turn it off because you’re cold. The automation immediately turns it back on. An irrigation schedule runs, but you skip it manually due to rain. The schedule triggers anyway because it doesn’t know you already made a decision. Voice assistants, wall switches, physical remotes, and mobile apps all create manual control events that automations blindly override.
Some users work around this by adding complex timing conditions, creating input booleans to track automation state, or building elaborate automation modes. These workarounds require significant configuration, are error-prone, and become unmaintainable as complexity grows. Controllable solves the problem elegantly at the architectural level rather than through configuration gymnastics.
How It Works
Sync-Aware Virtual Switches
Controllable creates virtual switch entities that act as intelligent proxies for real entities like lights, switches, or fans. These virtual switches include a critical is_synced attribute that tracks whether the virtual switch state matches the real entity state. When both states align, sync is true—meaning changes came through the virtual switch as expected. When states differ, sync becomes false—indicating someone changed the real entity without using the virtual switch, which signals a manual override occurred.
The architecture is straightforward but powerful. Your automations control the virtual switch instead of the real entity directly. The virtual switch forwards commands to the real entity while maintaining state tracking. If someone changes the real entity through a different path—wall switch, voice assistant, physical remote, another automation—the real entity state changes but the virtual switch state doesn’t. This state mismatch indicates lost sync, and the is_synced attribute becomes false.
Automations check is_synced before running their actions. If sync is true, the automation proceeds normally, controlling the virtual switch which controls the real entity. If sync is false, the automation recognizes a manual override occurred and pauses, respecting the human decision instead of fighting it. Sync automatically restores when states match again, either through manual adjustment or natural state convergence.
Event-Driven Architecture
The integration uses Home Assistant’s event system for real-time state monitoring, not polling. When the real entity state changes, an event fires immediately. Controllable receives this event, compares the new real entity state with the virtual switch state, and updates the is_synced attribute instantly if they differ. This event-driven approach means zero delay in detecting manual overrides and no performance impact from constant polling.
The system responds to state changes within milliseconds. Manual changes through wall switches, voice assistants, or other automations trigger events immediately. The sync status updates before you even notice the device state changed. This responsiveness ensures automations see accurate sync status in real time, preventing any window where automations might act on stale information.
Event subscriptions are efficient and targeted. Controllable only monitors state changes for the specific real entities it’s managing, not every entity in your Home Assistant instance. This focused monitoring keeps overhead minimal even in large installations with hundreds of entities.
Device Registry Integration
Virtual switches aren’t orphaned entities floating in your system. The integration properly associates them with their target devices in Home Assistant’s device registry. When you view a device that has a controllable virtual switch, you see the virtual switch entity right alongside the real switch, light, or fan it controls. This clear relationship makes the proxy pattern immediately obvious and keeps device organization logical.
The integration automatically identifies the appropriate device for association. When you select a device during configuration, Controllable finds the first controllable entity (switch, light, or fan) on that device and creates the virtual switch for it. The virtual switch entity inherits proper device information, maintaining clean organization throughout your entity lists and device pages.
Key Features
Universal Compatibility
Controllable works with any device that has switch, light, or fan entities supporting on/off control. This covers the vast majority of smart home devices—light bulbs and strips, wall switches and dimmers, relay switches and outlets, ceiling fans and ventilation fans, smart plugs and power strips, and motorized shades or blinds with on/off states. If it can be turned on and off through Home Assistant, Controllable can create a sync-aware virtual switch for it.
The integration automatically identifies controllable entities during configuration. When you select a device, Controllable scans for switch, light, or fan entities and uses the first one it finds. This automatic detection means minimal configuration while maintaining flexibility for various device types.
Real-Time Sync Detection
Sync status updates happen instantly when state changes occur. There’s no polling interval, no delay, no periodic checking. The moment someone flips a wall switch, presses a remote button, or issues a voice command, the real entity state changes and events propagate through Home Assistant’s event bus. Controllable receives these events immediately and updates sync status within milliseconds.
This real-time detection ensures automations always see current sync status. There’s no race condition where an automation might check sync status just before a manual override occurred. The event-driven architecture guarantees consistency between real state and sync status tracking.
Simple Automation Integration
Incorporating sync checks into automations requires just one additional condition. Check that is_synced is true before running automation actions. This single condition prevents all automation override conflicts. The syntax is straightforward and identical across different automation patterns—time-based triggers, state-based triggers, event-based triggers, and template-based triggers all use the same condition structure.
condition:
- condition: state
entity_id: switch.bedroom_controllable
attribute: is_synced
state: "true"
This condition gates automation execution based on sync status. If true, automation proceeds. If false due to manual override, automation pauses until sync restores. The approach is declarative and easy to understand—automations run when sync indicates automation control is appropriate, pause when manual control is active.
Zero Performance Overhead
Event-driven monitoring imposes no performance penalty. Unlike polling-based solutions that constantly check state even when nothing changes, event subscriptions only activate when actual state changes occur. In a typical home where lights toggle a few times per day, Controllable processes a handful of events daily rather than thousands of polling checks.
Memory usage is minimal—typically under 1MB per virtual switch entity. The integration stores only essential state information and references to monitored entities. There’s no caching of historical states, no complex data structures, no background processing threads. The lean implementation ensures Controllable scales efficiently even in large installations with dozens of virtual switches.
Flexible Sync Restoration
Sync restores automatically when states align again, but how this happens varies based on your needs. Manual sync restoration occurs when you turn the virtual switch to match the real entity state—if the real entity is off and virtual is on, turning the virtual switch off restores sync. Natural sync restoration happens when conditions change such that automation actions would produce the current state anyway—if you manually turned off a light before sunset, sync restores at sunset when the automation would have wanted it off anyway.
The system doesn’t force immediate sync restoration. If you manually turn off a light and want it to stay off despite automation schedules, sync remains false until you actively restore it or conditions naturally align. This respects human intent fully rather than assuming manual changes are temporary overrides that should eventually yield to automation control.
Use Cases & Automation Examples
Bedroom Lighting
Control bedroom lights automatically while respecting manual preferences. Turn lights on at sunset for occupied bedrooms, but pause automation if lights are manually turned off for movie watching or early sleep. Resume automation control when sync restores naturally or through manual adjustment.
automation:
- alias: "Bedroom Light at Sunset"
triggers:
- platform: sun
event: sunset
conditions:
- condition: state
entity_id: switch.bedroom_controllable
attribute: is_synced
state: "true"
actions:
- service: light.turn_on
target:
entity_id: light.bedroom
Climate Control
Manage fans automatically based on temperature while allowing manual overrides. Turn fans on when rooms exceed temperature thresholds, but respect manual shutoffs when someone feels cold despite the temperature reading. Prevent automation from repeatedly turning fans back on every check cycle.
Outdoor Lighting
Automate outdoor lighting on motion detection without overriding manual control. Trigger lights when motion detected in driveway, but don’t force them on if they were manually turned off. Allow homeowners to disable outdoor lighting temporarily without fighting automation.
Energy Saving
Implement aggressive energy-saving automations that turn off forgotten lights without preventing immediate manual override. Automation turns off lights after rooms are vacant for extended periods, but if you manually turn lights back on, automation understands the room is actually occupied and doesn’t immediately turn lights off again.
Irrigation Systems
Schedule irrigation based on weather and soil conditions while respecting manual schedule adjustments. Automation enables sprinklers during scheduled windows unless they were manually skipped due to rain, recent watering, or maintenance needs. Manual skip persists until sync restores, preventing automation from overriding your decision.
Technical Specifications
Architecture
The integration follows Home Assistant best practices with config flow for user-friendly setup, event-driven state monitoring with zero polling, proper device registry integration, entity attribute support for custom data, and comprehensive error handling. All processing happens locally with no external dependencies or cloud services.
System Requirements
Home Assistant version 2024.1.0 or higher provides the platform. Python 3.11+ serves as the runtime environment. Target devices must have at least one switch, light, or fan entity supporting on/off control. No additional hardware or external services are required.
Performance Characteristics
Event-driven monitoring imposes zero polling overhead. State updates happen instantly via Home Assistant’s event bus with millisecond-level latency. Memory usage remains minimal at approximately 1MB per virtual switch. CPU usage is negligible—only brief processing during state change events which occur infrequently in typical usage.
Compatibility
The integration works with any device or entity that uses standard Home Assistant switch, light, or fan domains. This includes Zigbee devices through ZHA or Zigbee2MQTT, Z-Wave devices through Z-Wave JS, Wi-Fi devices with native integrations, Matter devices through the Matter integration, virtual entities created by other integrations, and helper entities like input booleans configured as switches.
Advanced Usage Patterns
Conditional Automation Logic
Build sophisticated automation logic that adapts behavior based on sync status. Create automations that behave differently when sync is true versus false. For example, bedroom lighting automation might gradually increase brightness when resuming from sync, acknowledging that manual override represented a preference for darkness.
Sync Status Dashboards
Display sync status in dashboards to understand which automations are currently active versus paused due to manual overrides. Create conditional cards that show sync status with clear indicators. Use template sensors to count how many devices are currently out of sync, providing a dashboard overview of manual control activity.
Multiple Automation Coordination
Coordinate multiple automations that affect the same device through the shared sync status. If one automation pauses due to lost sync, all related automations also pause automatically since they all check the same is_synced attribute. This prevents one automation respecting manual control while another overrides it.
Temporary Manual Control
Implement patterns where manual control is explicitly temporary. Create automations that allow manual override for a specific duration, then automatically restore sync and resume automation control. For example, manually turning off a fan might pause automation for 30 minutes before automatically re-syncing and allowing automation control again.
Why Choose Controllable?
Simplicity
Solve automation conflicts with a single integration rather than complex configuration workarounds. One additional condition in automations prevents all override issues. Clean architecture with virtual switches that are easy to understand and maintain.
Reliability
Event-driven monitoring ensures real-time sync detection with zero delays. No polling intervals that might miss state changes. No race conditions where automation checks sync just before manual override. Consistent, predictable behavior across all device types.
Flexibility
Works with any switch, light, or fan entity regardless of underlying protocol or manufacturer. Scales from single device to dozens without performance impact. Supports diverse automation patterns from simple time-based schedules to complex conditional logic.
Transparency
Open source code enables community auditing and contribution. Clear documentation explains exactly how sync tracking works. Simple entity attributes make sync status visible and debuggable. No hidden behaviors or surprise functionality.