Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Major refactor of cover platform and config flow support tweaks for cover platform #10

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*~
__pycache__
.DS_Store
9 changes: 6 additions & 3 deletions custom_components/localtuya/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,12 @@
CONF_VOLTAGE = "voltage"

# cover
CONF_OPEN_CMD = 'open_cmd'
CONF_CLOSE_CMD = 'close_cmd'
CONF_STOP_CMD = 'stop_cmd'
CONF_OPEN_CMD = "open_cmd"
CONF_CLOSE_CMD = "close_cmd"
CONF_STOP_CMD = "stop_cmd"
CONF_GET_POSITION = "get_position"
CONF_SET_POSITION = "set_position"
CONF_LAST_MOVEMENT = "last_movement"

# sensor
CONF_SCALING = "scaling"
Expand Down
175 changes: 73 additions & 102 deletions custom_components/localtuya/cover.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
"""
Simple platform to locally control Tuya-based cover devices.
Platform to locally control Tuya-based cover devices.

It is recommend to setup LocalTUya using the graphical configuration flow:
Configuration-->Integrations-->+-->LocalTuya

YAML may be used as an alternative setup method.

Sample config yaml:

cover:
- platform: localtuya #REQUIRED
host: 192.168.0.123 #REQUIRED
local_key: 1234567891234567 #REQUIRED
device_id: 123456789123456789abcd #REQUIRED
name: cover_guests #REQUIRED
friendly_name: Cover guests #REQUIRED
protocol_version: 3.3 #REQUIRED
id: 1 #OPTIONAL
icon: mdi:blinds #OPTIONAL
open_cmd: open #OPTIONAL, default is 'on'
close_cmd: close #OPTIONAL, default is 'off'
stop_cmd: stop #OPTIONAL, default is 'stop'

- platform: localtuya #REQUIRED
host: 192.168.0.123 #REQUIRED
local_key: 1234567891234567 #REQUIRED
device_id: 123456789123456789abcd #REQUIRED
friendly_name: Cover guests #REQUIRED
protocol_version: 3.3 #REQUIRED
name: cover_guests #OPTIONAL
open_cmd: open #OPTIONAL, default is 'on'
close_cmd: close #OPTIONAL, default is 'off'
stop_cmd: stop #OPTIONAL, default is 'stop'
get_position: 3 #OPTIONAL, default is 0
set_position: 2 #OPTIONAL, default is 0
last_movement: 7 #OPTIONAL, default is 0
id: 1 #OPTIONAL
icon: mdi:blinds #OPTIONAL
"""
import logging
from time import time, sleep
Expand All @@ -31,6 +38,7 @@
SUPPORT_OPEN,
SUPPORT_STOP,
SUPPORT_SET_POSITION,
ATTR_POSITION
)
from homeassistant.const import (
CONF_ID,
Expand All @@ -49,32 +57,44 @@
CONF_OPEN_CMD,
CONF_CLOSE_CMD,
CONF_STOP_CMD,
CONF_GET_POSITION,
CONF_SET_POSITION,
CONF_LAST_MOVEMENT
)
from .const import CONF_OPEN_CMD, CONF_CLOSE_CMD, CONF_STOP_CMD

from .pytuya import TuyaDevice

_LOGGER = logging.getLogger(__name__)

DEFAULT_OPEN_CMD = "on"
DEFAULT_CLOSE_CMD = "off"
DEFAULT_OPEN_CMD = "open"
DEFAULT_CLOSE_CMD = "close"
DEFAULT_STOP_CMD = "stop"

DEFAULT_SET_POSITION = 0
DEFAULT_GET_POSITION = 0
DEFAULT_LAST_MOVEMENT = 0

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(BASE_PLATFORM_SCHEMA).extend(
{
vol.Optional(CONF_OPEN_CMD, default=DEFAULT_OPEN_CMD): cv.string,
vol.Optional(CONF_CLOSE_CMD, default=DEFAULT_CLOSE_CMD): cv.string,
vol.Optional(CONF_STOP_CMD, default=DEFAULT_STOP_CMD): cv.string,
vol.Optional(CONF_SET_POSITION, default=DEFAULT_SET_POSITION): cv.positive_int,
vol.Optional(CONF_GET_POSITION, default=DEFAULT_GET_POSITION): cv.positive_int,
vol.Optional(CONF_LAST_MOVEMENT, default=DEFAULT_LAST_MOVEMENT): cv.positive_int,
}
)


def flow_schema(dps):
"""Return schema used in config flow."""
return {
vol.Optional(CONF_OPEN_CMD, default=DEFAULT_OPEN_CMD): str,
vol.Optional(CONF_CLOSE_CMD, default=DEFAULT_CLOSE_CMD): str,
vol.Optional(CONF_STOP_CMD, default=DEFAULT_STOP_CMD): str,
}
vol.Optional(CONF_OPEN_CMD, default=DEFAULT_OPEN_CMD): str,
vol.Optional(CONF_CLOSE_CMD, default=DEFAULT_CLOSE_CMD): str,
vol.Optional(CONF_STOP_CMD, default=DEFAULT_STOP_CMD): str,
vol.Optional(CONF_SET_POSITION, default=DEFAULT_SET_POSITION): cv.positive_int,
vol.Optional(CONF_GET_POSITION, default=DEFAULT_GET_POSITION): cv.positive_int,
vol.Optional(CONF_LAST_MOVEMENT, default=DEFAULT_LAST_MOVEMENT): cv.positive_int,
}


async def async_setup_entry(hass, config_entry, async_add_entities):
Expand All @@ -101,116 +121,67 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up of the Tuya cover."""
return import_from_yaml(hass, config, DOMAIN)


class LocaltuyaCover(LocalTuyaEntity, CoverEntity):
"""Tuya cover devices."""

def __init__(
self,
device,
config_entry,
switchid,
coverid,
**kwargs,
):
#_LOGGER.info("running def __init__ of LocaltuyaCover(CoverEntity) with self=%s device=%s name=%s friendly_name=%s icon=%s switchid=%s open_cmd=%s close_cmd=%s stop_cmd=%s", self, device, name, friendly_name, icon, switchid, open_cmd, close_cmd, stop_cmd)
super().__init__(device, config_entry, switchid, **kwargs)
self._state = None
self._position = 50
super().__init__(device, config_entry, coverid, **kwargs)
self._position = None
self._current_cover_position = None
self._last_movement = None
self._last_position_set = None
self._last_command = None
print(
"Initialized tuya cover [{}] with switch status [{}] and state [{}]".format(
self.name, self._status, self._state
"Initialized tuya cover [{}] with switch status [{}]".format(
self.name, self._status
)
)

@property
def available(self):
"""Return if device is available or not."""
return self._available
def is_closed(self):
"""Check if the cover is fully closed."""
return self._current_cover_position == 100

@property
def supported_features(self):
"""Flag supported features."""
supported_features = (
SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION
)
return supported_features
def status_updated(self):
"""Device status was updated."""
self._last_movement = self.dps(str(self._config.get(CONF_LAST_MOVEMENT)))
self._last_position = self.dps(str(self._config.get(CONF_SET_POSITION)))
self._current_cover_position = self.dps(str(self._config.get(CONF_GET_POSITION)))
self._last_command = self.dps(str(self._dps_id))

@property
def current_cover_position(self):
# self.update()
# state = self._state
# _LOGGER.info("curr_pos() : %i", self._position)
# print('curr_pos() : state [{}]'.format(state))
return self._position

@property
def is_opening(self):
# self.update()
state = self._state
# print('is_opening() : state [{}]'.format(state))
if state == "on":
return True
return False
"""Return position of Tuya cover."""
return self._current_cover_position

@property
def is_closing(self):
# self.update()
state = self._state
# print('is_closing() : state [{}]'.format(state))
if state == "off":
return True
return False

@property
def is_closed(self):
"""Return if the cover is closed or not."""
# _LOGGER.info("running is_closed from cover")
# self.update()
state = self._state
# print('is_closed() : state [{}]'.format(state))
if state == "off":
return False
if state == "on":
return True
return None
def supported_features(self):
"""Flag supported features."""
return SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION
#TODO set supported features dynamically based on config or yaml input

def set_cover_position(self, **kwargs):
# _LOGGER.info("running set_cover_position from cover")
"""Move the cover to a specific position."""

newpos = float(kwargs["position"])
# _LOGGER.info("Set new pos: %f", newpos)

currpos = self.current_cover_position
posdiff = abs(newpos - currpos)
# 25 sec corrisponde alla chiusura/apertura completa
mydelay = posdiff / 2.0
if newpos > currpos:
# _LOGGER.info("Opening to %f: delay %f", newpos, mydelay )
self.open_cover()
else:
# _LOGGER.info("Closing to %f: delay %f", newpos, mydelay )
self.close_cover()
sleep(mydelay)
self.stop_cover()
self._position = 50 # newpos

"""Set the cover to a specific position from 0-100"""
if ATTR_POSITION in kwargs:
converted_position = int(kwargs[ATTR_POSITION])
if converted_position in range(0,101):
self._device.set_dps(converted_position, self._config[CONF_SET_POSITION])
else:

def open_cover(self, **kwargs):
"""Open the cover."""
_LOGGER.debug("Launching command %s to cover ", self._config[CONF_OPEN_CMD])
self._device.set_dps(self._config[CONF_OPEN_CMD], self._dps_id)

def close_cover(self, **kwargs):
"""Close cover."""
_LOGGER.debug("Launching command %s to cover ", self._config[CONF_CLOSE_CMD])
self._device.set_dps(self._config[CONF_CLOSE_CMD], self._dps_id)

def stop_cover(self, **kwargs):
"""Stop the cover."""
_LOGGER.debug("Laudebugching command %s to cover ", self._config[CONF_STOP_CMD])
self._device.set_dps(self._config[CONF_STOP_CMD], self._dps_id)

def status_updated(self):
"""Device status was updated. """
self._state = self.dps(self._dps_id)
self._device.set_dps(self._config[CONF_STOP_CMD], self._dps_id)
3 changes: 3 additions & 0 deletions custom_components/localtuya/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
"open_cmd": "Open Command",
"close_cmd": "Close Command",
"stop_cmd": "Stop Command",
"get_position": "Get Position",
"set_position": "Set Position",
"last_movement": "Last Movement",
"unit_of_measurement": "Unit of Measurement",
"device_class": "Device Class",
"scaling": "Scaling Factor"
Expand Down