Skip to content

Commit

Permalink
Merge branch 'feature/add_new_entities'
Browse files Browse the repository at this point in the history
  • Loading branch information
Ivan Suazo committed Oct 9, 2023
2 parents 78d2030 + 2e0dbd0 commit 069263b
Show file tree
Hide file tree
Showing 27 changed files with 1,710 additions and 212 deletions.
18 changes: 18 additions & 0 deletions .github/workflows/validate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Validate

on:
push:
pull_request:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:

jobs:
validate-hacs:
runs-on: "ubuntu-latest"
steps:
- uses: "actions/checkout@v3"
- name: HACS validation
uses: "hacs/action@main"
with:
category: "integration"
56 changes: 55 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,61 @@ An Home Assistant Custom Integration that interact via SwitchBot API to your Swi
Supported device:

* Air Conditionair
* TV [on/off]
- Custom sensor for power status tracking
- Custom sensor for temperature status tracking
- Custom sensor for humidity status tracking
- On/Off control
- Min, Max, and Steps settings
- Temperature control
- Fan control
- A/C Modes
* TV | IPTV | Streamer | Set Top Box
- Custom sensor for power status tracking
- On/Off control
- Volume +/- and mute
- Channel up/down (prev/fowd)
- Channel number to source via service
* DVD | Speaker
- Custom sensor for power status tracking
- On/Off control
- Volume +/- and mute
- Play, Pause, Stop, Prev and Next controls
* Fan
- Custom sensor for power status tracking
- On/Off control
- Buttons ION and TIMER in device settings
- Fan Speeds (1,2,3)
* Light
- Custom sensor for power status tracking
- On/Off control
- Brightness control (+/-) in device settings
- Temperature light control (+/-) in device settings
* Air Purifier
- Custom sensor for power status tracking
- On/Off control
* Water Heater
- Custom sensor for power status tracking
- Custom sensor for temperature status tracking
- On/Off control
* Vacuum Cleaner
- Cleaning / Stop command
- Go to Dock/Charge command
* Camera Shutter
- Shutter buton
- Timer buton
- Menu buton
* Others
- Custom sensor for power status tracking
- On/Off control
- Custom On and Off separated command in device settings

_All above devices support DIY types and add custom buttons/commands in device settings_

To configure custom/learned buttonsmake sure the name of the button must be exactly as they appear in the app (case sensitive and characters like spaces).

![SwitchBot app device](./docs/app.png "SwitchBot app device")

![Home Assistant integration settings](./docs/settings.png "Home Assistant integration settings")

## Installation

Expand Down
13 changes: 12 additions & 1 deletion custom_components/switchbotremote/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,16 @@

from .const import DOMAIN

PLATFORMS: list[Platform] = [Platform.CLIMATE, Platform.REMOTE]
PLATFORMS: list[Platform] = [
Platform.CLIMATE,
Platform.MEDIA_PLAYER,
Platform.LIGHT,
Platform.FAN,
Platform.BUTTON,
Platform.VACUUM,
Platform.REMOTE,
Platform.WATER_HEATER,
]


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
Expand All @@ -25,10 +34,12 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

return True


async def update_listener(hass: HomeAssistant, entry: ConfigEntry):
"""Update listener."""
await hass.config_entries.async_reload(entry.entry_id)


async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"""Unload a config entry."""
if unload_ok := await hass.config_entries.async_unload_platforms(entry, PLATFORMS):
Expand Down
111 changes: 111 additions & 0 deletions custom_components/switchbotremote/button.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import humps
from typing import List
from homeassistant.components.button import ButtonEntity
from homeassistant.core import HomeAssistant
from homeassistant.config_entries import ConfigEntry
from homeassistant.helpers.entity import DeviceInfo
from .client.remote import SupportedRemote

from .const import (
DOMAIN,
IR_CAMERA_TYPES,
IR_FAN_TYPES,
IR_LIGHT_TYPES,
CLASS_BY_TYPE,
CONF_CUSTOMIZE_COMMANDS,
CONF_WITH_ION,
CONF_WITH_TIMER,
CONF_WITH_BRIGHTNESS,
CONF_WITH_TEMPERATURE,
)


class SwitchBotRemoteButton(ButtonEntity):
_attr_has_entity_name = False

def __init__(self, hass: HomeAssistant, sb: SupportedRemote, command_name: str, command_icon: str) -> None:
super().__init__()
self.sb = sb
self._hass = hass
self._unique_id = sb.id
self._device_name = sb.name
self._command_name = command_name
self._command_icon = command_icon

async def send_command(self, *args):
await self._hass.async_add_executor_job(self.sb.command, *args)

@property
def device_info(self):
return DeviceInfo(
identifiers={(DOMAIN, self._unique_id)},
manufacturer="SwitchBot",
name=self._device_name,
model=CLASS_BY_TYPE[self.sb.type] + " Remote",
)

@property
def unique_id(self):
"""Return a unique ID."""
return self._unique_id + "_" + humps.decamelize(self._command_name)

@property
def name(self) -> str:
"""Return the display name of this button."""
return self._device_name + " " + self._command_name.capitalize()

@property
def icon(self) -> str:
"""Return the icon of this button."""
return self._command_icon

async def async_press(self) -> None:
"""Handle the button press."""
await self.send_command(self._command_name, None, True)


async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry, async_add_entities) -> bool:
remotes: List[SupportedRemote] = hass.data[DOMAIN][entry.entry_id]
entities = []

for remote in remotes:
options = entry.data.get(remote.id, {})
customize_commands = options.get(CONF_CUSTOMIZE_COMMANDS, [])

if (remote.type in IR_CAMERA_TYPES):
entities.append(SwitchBotRemoteButton(
hass, remote, "SHUTTER", "mdi:camera-iris"))
entities.append(SwitchBotRemoteButton(
hass, remote, "MENU", "mdi:menu"))
entities.append(SwitchBotRemoteButton(
hass, remote, "TIMER", "mdi:timer"))

if (remote.type in IR_FAN_TYPES):
if (options.get(CONF_WITH_ION, False)):
entities.append(SwitchBotRemoteButton(
hass, remote, "ION", "mdi:air-filter"))
if (options.get(CONF_WITH_TIMER, False)):
entities.append(SwitchBotRemoteButton(
hass, remote, "TIMER", "mdi:timer"))

if (remote.type in IR_LIGHT_TYPES):
if (options.get(CONF_WITH_BRIGHTNESS, False)):
entities.append(SwitchBotRemoteButton(
hass, remote, "DARKER", "mdi:brightness-4"))
entities.append(SwitchBotRemoteButton(
hass, remote, "BRIGHTER", "mdi:brightness-6"))

if (options.get(CONF_WITH_TEMPERATURE, False)):
entities.append(SwitchBotRemoteButton(
hass, remote, "WARM", "mdi:octagram-minus"))
entities.append(SwitchBotRemoteButton(
hass, remote, "WHITE", "mdi:octagram-plus"))

for command in customize_commands:
if (command and command.strip()):
entities.append(SwitchBotRemoteButton(
hass, remote, command, "mdi:remote"))

async_add_entities(entities)

return True
2 changes: 1 addition & 1 deletion custom_components/switchbotremote/client/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,4 @@ def put(self, path: str, **kwargs) -> Any:
return self.request("PUT", path, **kwargs)

def delete(self, path: str, **kwargs) -> Any:
return self.request("DELETE", path, **kwargs)
return self.request("DELETE", path, **kwargs)
6 changes: 3 additions & 3 deletions custom_components/switchbotremote/client/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def command(
payload = humps.camelize(
{
"command_type": command_type,
"command": action if customize else humps.camelize(action),
"command": action,
"parameter": parameter,
}
)
Expand All @@ -60,11 +60,11 @@ class SupportedRemote(Remote):
def turn(self, state: str):
state = state.lower()
assert state in ("on", "off")
self.command(f"turn_{state}")
self.command(humps.camelize(f"turn_{state}"))


class OtherRemote(Remote):
remote_type_for = "Others"

def command(self, action: str, parameter: Optional[str] = None):
super().command(action, parameter, True)
super().command(action, parameter, True)
Loading

0 comments on commit 069263b

Please sign in to comment.