Skip to content

Commit

Permalink
Merge pull request #506 from rikman122/vacuum_platform_new
Browse files Browse the repository at this point in the history
Vacuum platform new
  • Loading branch information
rospogrigio committed Jan 24, 2022
2 parents c66135c + 12bea16 commit 2688a17
Show file tree
Hide file tree
Showing 4 changed files with 326 additions and 0 deletions.
14 changes: 14 additions & 0 deletions custom_components/localtuya/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,20 @@
current: 18 # Optional
current_consumption: 19 # Optional
voltage: 20 # Optional
- platform: vacuum
friendly_name: Vacuum
id: 28
idle_status_value: "standby,sleep"
returning_status_value: "docking"
docked_status_value: "charging,chargecompleted"
battery_dp: 14
mode_dp: 27
modes: "smart,standby,chargego,wall_follow,spiral,single"
fan_speed_dp: 30
fan_speeds: "low,normal,high"
clean_time_dp: 33
clean_area_dp: 32
"""
import asyncio
import logging
Expand Down
20 changes: 20 additions & 0 deletions custom_components/localtuya/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,25 @@
CONF_ECO_DP = "eco_dp"
CONF_ECO_VALUE = "eco_value"

# vacuum
CONF_POWERGO_DP = "powergo_dp"
CONF_IDLE_STATUS_VALUE = "idle_status_value"
CONF_RETURNING_STATUS_VALUE = "returning_status_value"
CONF_DOCKED_STATUS_VALUE = "docked_status_value"
CONF_BATTERY_DP = "battery_dp"
CONF_MODE_DP = "mode_dp"
CONF_MODES = "modes"
CONF_FAN_SPEED_DP = "fan_speed_dp"
CONF_FAN_SPEEDS = "fan_speeds"
CONF_CLEAN_TIME_DP = "clean_time_dp"
CONF_CLEAN_AREA_DP = "clean_area_dp"
CONF_CLEAN_RECORD_DP = "clean_record_dp"
CONF_LOCATE_DP = "locate_dp"
CONF_FAULT_DP = "fault_dp"
CONF_PAUSED_STATE = "paused_state"
CONF_RETURN_MODE = "return_mode"
CONF_STOP_STATUS = "stop_status"

DATA_DISCOVERY = "discovery"

DOMAIN = "localtuya"
Expand All @@ -78,6 +97,7 @@
"select",
"sensor",
"switch",
"vacuum",
]

TUYA_DEVICE = "tuya_device"
34 changes: 34 additions & 0 deletions custom_components/localtuya/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,23 @@
"scaling": "Scaling Factor",
"state_on": "On Value",
"state_off": "Off Value",
"powergo_dp": "Power DP (Usually 25 or 2)",
"idle_status_value": "Idle Status (comma-separated)",
"returning_status_value": "Returning Status",
"docked_status_value": "Docked Status (comma-separated)",
"fault_dp": "Fault DP (Usually 11)",
"battery_dp": "Battery status DP (Usually 14)",
"mode_dp": "Mode DP (Usually 27)",
"modes": "Modes list",
"return_mode": "Return home mode",
"fan_speed_dp": "Fan speeds DP (Usually 30)",
"fan_speeds": "Fan speeds list (comma-separated)",
"clean_time_dp": "Clean Time DP (Usually 33)",
"clean_area_dp": "Clean Area DP (Usually 32)",
"clean_record_dp": "Clean Record DP (Usually 34)",
"locate_dp": "Locate DP (Usually 31)",
"paused_state": "Pause state (pause, paused, etc)",
"stop_status": "Stop status",
"brightness": "Brightness (only for white color)",
"brightness_lower": "Brightness Lower Value",
"brightness_upper": "Brightness Upper Value",
Expand Down Expand Up @@ -135,6 +152,23 @@
"scaling": "Scaling Factor",
"state_on": "On Value",
"state_off": "Off Value",
"powergo_dp": "Power DP (Usually 25 or 2)",
"idle_status_value": "Idle Status (comma-separated)",
"returning_status_value": "Returning Status",
"docked_status_value": "Docked Status (comma-separated)",
"fault_dp": "Fault DP (Usually 11)",
"battery_dp": "Battery status DP (Usually 14)",
"mode_dp": "Mode DP (Usually 27)",
"modes": "Modes list",
"return_mode": "Return home mode",
"fan_speed_dp": "Fan speeds DP (Usually 30)",
"fan_speeds": "Fan speeds list (comma-separated)",
"clean_time_dp": "Clean Time DP (Usually 33)",
"clean_area_dp": "Clean Area DP (Usually 32)",
"clean_record_dp": "Clean Record DP (Usually 34)",
"locate_dp": "Locate DP (Usually 31)",
"paused_state": "Pause state (pause, paused, etc)",
"stop_status": "Stop status",
"brightness": "Brightness (only for white color)",
"brightness_lower": "Brightness Lower Value",
"brightness_upper": "Brightness Upper Value",
Expand Down
258 changes: 258 additions & 0 deletions custom_components/localtuya/vacuum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
"""Platform to locally control Tuya-based vacuum devices."""
import logging
from functools import partial

import voluptuous as vol
from homeassistant.components.vacuum import (
DOMAIN,
STATE_CLEANING,
STATE_DOCKED,
STATE_IDLE,
STATE_RETURNING,
STATE_PAUSED,
STATE_ERROR,
SUPPORT_BATTERY,
SUPPORT_FAN_SPEED,
SUPPORT_PAUSE,
SUPPORT_RETURN_HOME,
SUPPORT_START,
SUPPORT_STATE,
SUPPORT_STATUS,
SUPPORT_STOP,
SUPPORT_LOCATE,
StateVacuumEntity,
)

from .common import LocalTuyaEntity, async_setup_entry

from .const import (
CONF_POWERGO_DP,
CONF_IDLE_STATUS_VALUE,
CONF_RETURNING_STATUS_VALUE,
CONF_DOCKED_STATUS_VALUE,
CONF_BATTERY_DP,
CONF_MODE_DP,
CONF_MODES,
CONF_FAN_SPEED_DP,
CONF_FAN_SPEEDS,
CONF_CLEAN_TIME_DP,
CONF_CLEAN_AREA_DP,
CONF_CLEAN_RECORD_DP,
CONF_LOCATE_DP,
CONF_FAULT_DP,
CONF_PAUSED_STATE,
CONF_RETURN_MODE,
CONF_STOP_STATUS,
)

_LOGGER = logging.getLogger(__name__)

CLEAN_TIME = "clean_time"
CLEAN_AREA = "clean_area"
CLEAN_RECORD = "clean_record"
MODES_LIST = "cleaning_mode_list"
MODE = "cleaning_mode"
FAULT = "fault"

DEFAULT_IDLE_STATUS = "standby,sleep"
DEFAULT_RETURNING_STATUS = "docking"
DEFAULT_DOCKED_STATUS = "charging,chargecompleted"
DEFAULT_MODES = "smart,wall_follow,spiral,single"
DEFAULT_FAN_SPEEDS = "low,normal,high"
DEFAULT_PAUSED_STATE = "paused"
DEFAULT_RETURN_MODE = "chargego"
DEFAULT_STOP_STATUS = "standby"


def flow_schema(dps):
"""Return schema used in config flow."""
return {
vol.Required(CONF_IDLE_STATUS_VALUE, default=DEFAULT_IDLE_STATUS): str,
vol.Required(CONF_POWERGO_DP): vol.In(dps),
vol.Required(CONF_DOCKED_STATUS_VALUE, default=DEFAULT_DOCKED_STATUS): str,
vol.Optional(
CONF_RETURNING_STATUS_VALUE, default=DEFAULT_RETURNING_STATUS
): str,
vol.Optional(CONF_BATTERY_DP): vol.In(dps),
vol.Optional(CONF_MODE_DP): vol.In(dps),
vol.Optional(CONF_MODES, default=DEFAULT_MODES): str,
vol.Optional(CONF_RETURN_MODE, default=DEFAULT_RETURN_MODE): str,
vol.Optional(CONF_FAN_SPEED_DP): vol.In(dps),
vol.Optional(CONF_FAN_SPEEDS, default=DEFAULT_FAN_SPEEDS): str,
vol.Optional(CONF_CLEAN_TIME_DP): vol.In(dps),
vol.Optional(CONF_CLEAN_AREA_DP): vol.In(dps),
vol.Optional(CONF_CLEAN_RECORD_DP): vol.In(dps),
vol.Optional(CONF_LOCATE_DP): vol.In(dps),
vol.Optional(CONF_FAULT_DP): vol.In(dps),
vol.Optional(CONF_PAUSED_STATE, default=DEFAULT_PAUSED_STATE): str,
vol.Optional(CONF_STOP_STATUS, default=DEFAULT_STOP_STATUS): str,
}


class LocaltuyaVacuum(LocalTuyaEntity, StateVacuumEntity):
"""Tuya vacuum device."""

def __init__(self, device, config_entry, switchid, **kwargs):
"""Initialize a new LocaltuyaVacuum."""
super().__init__(device, config_entry, switchid, _LOGGER, **kwargs)
self._state = None
self._battery_level = None
self._attrs = {}

self._idle_status_list = []
if self.has_config(CONF_IDLE_STATUS_VALUE):
self._idle_status_list = self._config[CONF_IDLE_STATUS_VALUE].split(",")

self._modes_list = []
if self.has_config(CONF_MODES):
self._modes_list = self._config[CONF_MODES].split(",")
self._attrs[MODES_LIST] = self._modes_list

self._docked_status_list = []
if self.has_config(CONF_DOCKED_STATUS_VALUE):
self._docked_status_list = self._config[CONF_DOCKED_STATUS_VALUE].split(",")

self._fan_speed_list = []
if self.has_config(CONF_FAN_SPEEDS):
self._fan_speed_list = self._config[CONF_FAN_SPEEDS].split(",")

self._fan_speed = ""
self._cleaning_mode = ""

print("Initialized vacuum [{}]".format(self.name))

@property
def supported_features(self):
"""Flag supported features."""
supported_features = (
SUPPORT_START
| SUPPORT_PAUSE
| SUPPORT_STOP
| SUPPORT_STATUS
| SUPPORT_STATE
)

if self.has_config(CONF_RETURN_MODE):
supported_features = supported_features | SUPPORT_RETURN_HOME
if self.has_config(CONF_FAN_SPEED_DP):
supported_features = supported_features | SUPPORT_FAN_SPEED
if self.has_config(CONF_BATTERY_DP):
supported_features = supported_features | SUPPORT_BATTERY
if self.has_config(CONF_LOCATE_DP):
supported_features = supported_features | SUPPORT_LOCATE

return supported_features

@property
def state(self):
"""Return the vacuum state."""
return self._state

@property
def battery_level(self):
"""Return the current battery level."""
return self._battery_level

@property
def extra_state_attributes(self):
"""Return the specific state attributes of this vacuum cleaner."""
return self._attrs

@property
def fan_speed(self):
"""Return the current fan speed."""
return self._fan_speed

@property
def fan_speed_list(self) -> list:
"""Return the list of available fan speeds."""
return self._fan_speed_list

async def async_start(self, **kwargs):
"""Turn the vacuum on and start cleaning."""
await self._device.set_dp(True, self._config[CONF_POWERGO_DP])

async def async_pause(self, **kwargs):
"""Stop the vacuum cleaner, do not return to base."""
await self._device.set_dp(False, self._config[CONF_POWERGO_DP])

async def async_return_to_base(self, **kwargs):
"""Set the vacuum cleaner to return to the dock."""
if self.has_config(CONF_RETURN_MODE):
await self._device.set_dp(
self._config[CONF_RETURN_MODE], self._config[CONF_MODE_DP]
)
else:
_LOGGER.error("Missing command for return home in commands set.")

async def async_stop(self, **kwargs):
"""Turn the vacuum off stopping the cleaning."""
if self.has_config(CONF_STOP_STATUS):
await self._device.set_dp(
self._config[CONF_STOP_STATUS], self._config[CONF_MODE_DP]
)
else:
_LOGGER.error("Missing command for stop in commands set.")

async def async_clean_spot(self, **kwargs):
"""Perform a spot clean-up."""
return None

async def async_locate(self, **kwargs):
"""Locate the vacuum cleaner."""
if self.has_config(CONF_LOCATE_DP):
await self._device.set_dp("", self._config[CONF_LOCATE_DP])

async def async_set_fan_speed(self, fan_speed, **kwargs):
"""Set the fan speed."""
await self._device.set_dp(fan_speed, self._config[CONF_FAN_SPEED_DP])

async def async_send_command(self, command, params=None, **kwargs):
"""Send a command to a vacuum cleaner."""
if command == "set_mode" and "mode" in params:
mode = params["mode"]
await self._device.set_dp(mode, self._config[CONF_MODE_DP])

def status_updated(self):
"""Device status was updated."""
state_value = str(self.dps(self._dp_id))

if state_value in self._idle_status_list:
self._state = STATE_IDLE
elif state_value in self._docked_status_list:
self._state = STATE_DOCKED
elif state_value == self._config[CONF_RETURNING_STATUS_VALUE]:
self._state = STATE_RETURNING
elif state_value == self._config[CONF_PAUSED_STATE]:
self._state = STATE_PAUSED
else:
self._state = STATE_CLEANING

if self.has_config(CONF_BATTERY_DP):
self._battery_level = self.dps_conf(CONF_BATTERY_DP)

self._cleaning_mode = ""
if self.has_config(CONF_MODES):
self._cleaning_mode = self.dps_conf(CONF_MODE_DP)
self._attrs[MODE] = self._cleaning_mode

self._fan_speed = ""
if self.has_config(CONF_FAN_SPEEDS):
self._fan_speed = self.dps_conf(CONF_FAN_SPEED_DP)

if self.has_config(CONF_CLEAN_TIME_DP):
self._attrs[CLEAN_TIME] = self.dps_conf(CONF_CLEAN_TIME_DP)

if self.has_config(CONF_CLEAN_AREA_DP):
self._attrs[CLEAN_AREA] = self.dps_conf(CONF_CLEAN_AREA_DP)

if self.has_config(CONF_CLEAN_RECORD_DP):
self._attrs[CLEAN_RECORD] = self.dps_conf(CONF_CLEAN_RECORD_DP)

if self.has_config(CONF_FAULT_DP):
self._attrs[FAULT] = self.dps_conf(CONF_FAULT_DP)
if self._attrs[FAULT] != 0:
self._state = STATE_ERROR


async_setup_entry = partial(async_setup_entry, DOMAIN, LocaltuyaVacuum, flow_schema)

0 comments on commit 2688a17

Please sign in to comment.