A Hacky Way to Add Drift Mode Support to HomeAssistant for SwitchBot Curtains 3

As of Home Assistant 2023.12.1, drift mode isn’t supported for the new switchbot curtain version 3. I saw there was some work being started on adding support but wanted to add a quick and dirty way to get drift mode right now.

Prerequisites

Before we start, ensure you have the following:

  • Docker and Docker Compose installed
  • HomeAssistant running on Docker
  • Git installed on your system

Step-by-Step Guide

Step 1: Cloning Necessary Repositories

Start by cloning the required repositories into a projects folder:

git clone git@github.com:Danielhiversen/pySwitchbot.git
git clone git@github.com:home-assistant/core.git

Step 2: Checking Out the Correct Version

In the core directory, check out the version of HomeAssistant you are running. As of now, it’s 2023.12.1:

cd core
git checkout 2023.12.1

Step 3: Configuring Docker Compose

Set the cloned files as volumes in your Docker Compose configuration for HomeAssistant:

volumes:
  - ./projects/hass/core/homeassistant/components/switchbot:/usr/src/homeassistant/homeassistant/components/switchbot
  - ./projects/pySwitchbot/switchbot:/usr/local/lib/python3.11/site-packages/switchbot

Step 4: Modifying the Switchbot Component

Navigate to the switchbot component directory:

cd ./projects/hass/core/homeassistant/components/switchbot/cover

Add the following lines to specify the MAC addresses of the SwitchBot Curtain 3 devices for which you want to enable drift mode. I wanted to seperate when dirft mode was activiated when opening and closing but you can add each MAC address to both to simulate the Switchbot app:

drift_mode_open_addresses = [
    'xx:xx:xx:xx:xx:xx' # add your mac addresses for v3 curtains to open here
]

drift_mode_close_addresses = [
    'xx:xx:xx:xx:xx:xx' # add your mac addresses for v3 curtains to close here
]

Replace the async_open_cover and async_close_cover functions with the updated code to incorporate drift mode:

async def async_open_cover(self, **kwargs: Any) -> None:
    """Open the curtain."""

    _LOGGER.debug("Switchbot to open curtain %s", self._address)
    drift_mode = self._address in drift_mode_open_addresses
    self._last_run_success = bool(await self._device.open(drift_mode))
    self.async_write_ha_state()

async def async_close_cover(self, **kwargs: Any) -> None:
    """Close the curtain."""

    drift_mode = self._address in drift_mode_close_addresses
    _LOGGER.debug("Switchbot to close the curtain %s", self._address)
    self._last_run_success = bool(await self._device.close(drift_mode))
    self.async_write_ha_state()

Step 5: Updating pySwitchbot

Navigate to the pySwitchbot project and modify the curtain.py file:

cd ../../pySwitchbot/switchbot/devices

Add new key variables for drift mode:

OPEN_KEYS_DRIFT = [
    f"{REQ_HEADER}{CURTAIN_COMMAND}010100",
    f"{REQ_HEADER}{CURTAIN_COMMAND}050100",
] 

CLOSE_KEYS_DRIFT = [
    f"{REQ_HEADER}{CURTAIN_COMMAND}010164",
    f"{REQ_HEADER}{CURTAIN_COMMAND}050164",
]

Replace the open and close functions with the updated code to handle drift mode:

@update_after_operation
async def open(self, drift_mode = False) -> bool:
    """Send open command."""
    return await self._send_multiple_commands(OPEN_KEYS_DRIFT if drift_mode else OPEN_KEYS)

@update_after_operation
async def close(self, drift_mode = False) -> bool:
    """Send close command."""
    return await self._send_multiple_commands(CLOSE_KEYS_DRIFT if drift_mode else CLOSE_KEYS)

Conclusion

Restart your HomeAssistant to apply these changes. Now, your SwitchBot Curtains 3 should support drift mode, allowing for more nuanced control. I’m certain drift mode will be supported in Home Assistant although I doubt you would be able to control drift mode in open/close mode. Hopefully, Switchbot supports setting the speed later on since the hex values for enabling drift mode are ff and 01 so adding hex values in between in the future would control the speed hypothetically.

Leave a Reply

Your email address will not be published. Required fields are marked *