A Home Assistant custom integration that provides virtual switch entities that proxy real entities, tracking synchronization to prevent automation overrides.
The Controllable integration solves a common Home Assistant problem: automation conflicts with manual control.
Scenario: You have a smart light controlled by both automation AND manual control
1. Automation turns light ON
2. You manually turn it OFF
3. Automation immediately turns it back ON (because the automation still thinks it should be on)
4. Frustration! 😤
Controllable creates an intermediary virtual switch that tracks whether manual changes have been made:
┌────────────────────────────────────────────────────┐
│ HOME ASSISTANT │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ YOUR AUTOMATIONS │ │
│ │ (Bedroom Light Turn On @ Sunrise) │ │
│ └──────────────────────┬───────────────────────┘ │
│ │ │
│ ▼ │
│ ┌──────────────────────────────────────────────┐ │
│ │ CONTROLLABLE VIRTUAL SWITCH (Proxy) │ │
│ │ │ │
│ │ • Passes commands to real light │ │
│ │ • Tracks sync status (is_synced) │ │
│ │ • Blocks automation if manually overridden │ │
│ └──────────────────────┬───────────────────────┘ │
│ │ │
│ ┌──────┴──────┐ │
│ ▼ ▼ │
│ ┌──────────────────────┐ ┌────────────────────┐ │
│ │ REAL LIGHT ENTITY │ │ MANUAL CONTROL │ │
│ │ (switch.bedroom) │ │ (Wall Switch) │ │
│ └──────────────────────┘ └────────────────────┘ │
│ │
└────────────────────────────────────────────────────┘
| Step | What Happens | is_synced |
|---|---|---|
| 1️⃣ Initial State | Virtual switch mirrors real entity state | true |
| 2️⃣ Automation Runs | Virtual switch controls real entity normally | true |
| 3️⃣ Manual Override | User changes real entity manually (wall switch, app, etc) | false |
| 4️⃣ Automation Blocks | Automations check is_synced attribute and pause |
false |
| 5️⃣ Sync Restored | When states match again, sync restores | true |
- ✅ Virtual Proxy Control - Switches control real entities while tracking sync status
- ✅ Sync Tracking -
is_syncedattribute shows if manual override occurred - ✅ Automation Protection - Prevents automations from overriding manual changes
- ✅ Device Integration - Virtual switch grouped with target device
- ✅ Event-Driven - Real-time sync monitoring with zero polling
- ✅ Simple Setup - User-friendly config flow in Home Assistant UI
- 🏠 Users with smart lights/fans on physical switches (hybrid control)
- 🤖 Anyone using automations + manual control on the same device
- 🎯 Users wanting automation logic respect for manual overrides
- 📱 Homes with mobile app, wall switch, and automation all controlling same device
HACS is the easiest way to install custom integrations.
- HACS installed in Home Assistant
- Home Assistant version 2024.1.0 or higher
- Open HACS: Go to HACS in your Home Assistant sidebar
- Navigate to Integrations: Click on "Integrations"
- Search and Install:
- Search for "Controllable" in HACS
- Click on it and select "Download"
- Choose the latest version
- Restart Home Assistant: Required for the integration to load
- Home Assistant version 2024.1.0 or higher
-
Download the Integration:
wget https://github.com/caplaz/home-assistant-controllable/archive/refs/tags/v1.0.1.zip unzip v1.0.1.zip
-
Copy Files:
cp -r controllable-1.0.1/custom_components/controllable /config/custom_components/
-
Restart Home Assistant:
- Go to Settings → System → Restart
- Wait for Home Assistant to restart
- Add Integration: Go to Settings → Devices & Services → Add Integration
- Search: Type "Controllable" in the search box
- Select: Click on "Controllable" from the results
- Configure:
- Name: Friendly name for the virtual switch
- Target Device: Select a device with a controllable entity (switch, light, or fan)
- Submit: The integration creates the virtual switch
The integration works with:
- ✅ Switches - Light switches, relay switches, etc.
- ✅ Lights - Smart bulbs, light strips
- ✅ Fans - Ceiling fans, ventilation fans
Note: The target device must have at least one entity in these domains (switch/light/fan) that supports on/off control.
The integration creates virtual switch entities that:
- Control Real Entities: Turning on/off controls the target entity
- Track Synchronization:
is_syncedshows if states match - Prevent Automation Conflicts: Automations can check
is_syncedbefore running - Device Grouping: Virtual switches appear in target's device
switch.bedroom_controllable:
is_synced: true/false # Sync status
target_entity: switch.bedroom # Real entity being controlled
Example: Pause automation if user manually changed the light
automation:
- alias: "Bedroom Light at Sunset"
triggers:
- platform: sun
event: sunset
conditions:
- condition: state
entity_id: switch.bedroom_controllable
attribute: is_synced
state: "true" # Only run if not manually overridden
actions:
- action: light.turn_on
target:
entity_id: light.bedroomAdd virtual switches to your dashboard like any other switch:
- Add Card: Dashboard → Add Card → Entities
- Select Entities: Choose controllable switches
- Customize: Set display options and icons
- Show Status: Display
is_syncedattribute for visibility
- Cause: Target entity changed externally
- Solution: Manually sync by turning virtual switch to match real state, or restart HA
- Cause: Target entity removed or unavailable
- Solution: Reconfigure the controllable with a valid target device
- Cause: Automation not checking
is_synced - Solution: Add condition to check
is_syncedattribute in automation
- Cause: Selected device has no switch/light/fan entities
- Solution: Select a different device, or add a controllable entity to the device
Enable debug logging to troubleshoot:
logger:
logs:
custom_components.controllable: debugThen check Settings → System → Logs for "controllable" messages.
Use the development script:
./dev.sh start # Start HA dev environment
./dev.sh test # Run pytest
./dev.sh logs # Check logs- Event-Driven: Uses Home Assistant events for real-time sync updates
- No Polling: Efficient listener-based state monitoring
- Device Registry: Virtual entities grouped with target devices
- Config Flow: Type-safe user-friendly setup
- Error Handling: Graceful recovery from entity unavailability
The integration intelligently filters devices and entities:
Device Selection:
- Only shows devices that have at least one controllable entity (switch, light, or fan)
- Automatically validates device exists before creation
Entity Selection:
- Automatically selects the first switch/light/fan entity on the chosen device
- Falls back gracefully if entity becomes unavailable
- Supports one virtual switch per device
- Home Assistant: 2024.1.0+
- Python Packages:
voluptuous>=0.13.1
- Switches: Standard switch domain entities
- Lights: Light domain entities with on/off support
- Fans: Fan domain entities with on/off support
- Internal Home Assistant APIs only
- No external API calls
- No external dependencies beyond voluptuous
- All state management is local
-
Clone the repository:
git clone https://github.com/caplaz/home-assistant-controllable.git cd controllable -
Install development dependencies:
pip install -r requirements-dev.txt
-
Run tests:
python -m pytest
- Formatting: black, isort
- Linting: flake8
- Type Checking: mypy
- Security: bandit
- Testing: pytest with comprehensive coverage
This project is licensed under the MIT License - see the LICENSE file for details.