mirror of
https://github.com/home-assistant/core.git
synced 2025-07-19 11:17:21 +00:00
Mqtt cover modifications (#7841)
* adding set position ability removing command_topic being required * flaking * flaking test * updating docs * requested updates * Revert "updating docs" This reverts commit 9cfc5ed7a8f5761de93d8bc7c1cfb81fa8d7ca40. * forgot to update constructor calls in tests
This commit is contained in:
parent
81b1446aad
commit
774f584ba8
@ -14,7 +14,9 @@ import homeassistant.components.mqtt as mqtt
|
|||||||
from homeassistant.components.cover import (
|
from homeassistant.components.cover import (
|
||||||
CoverDevice, ATTR_TILT_POSITION, SUPPORT_OPEN_TILT,
|
CoverDevice, ATTR_TILT_POSITION, SUPPORT_OPEN_TILT,
|
||||||
SUPPORT_CLOSE_TILT, SUPPORT_STOP_TILT, SUPPORT_SET_TILT_POSITION,
|
SUPPORT_CLOSE_TILT, SUPPORT_STOP_TILT, SUPPORT_SET_TILT_POSITION,
|
||||||
SUPPORT_OPEN, SUPPORT_CLOSE, SUPPORT_STOP, SUPPORT_SET_POSITION)
|
SUPPORT_OPEN, SUPPORT_CLOSE, SUPPORT_STOP, SUPPORT_SET_POSITION,
|
||||||
|
ATTR_POSITION)
|
||||||
|
from homeassistant.exceptions import TemplateError
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_NAME, CONF_VALUE_TEMPLATE, CONF_OPTIMISTIC, STATE_OPEN,
|
CONF_NAME, CONF_VALUE_TEMPLATE, CONF_OPTIMISTIC, STATE_OPEN,
|
||||||
STATE_CLOSED, STATE_UNKNOWN)
|
STATE_CLOSED, STATE_UNKNOWN)
|
||||||
@ -29,6 +31,8 @@ DEPENDENCIES = ['mqtt']
|
|||||||
|
|
||||||
CONF_TILT_COMMAND_TOPIC = 'tilt_command_topic'
|
CONF_TILT_COMMAND_TOPIC = 'tilt_command_topic'
|
||||||
CONF_TILT_STATUS_TOPIC = 'tilt_status_topic'
|
CONF_TILT_STATUS_TOPIC = 'tilt_status_topic'
|
||||||
|
CONF_POSITION_TOPIC = 'set_position_topic'
|
||||||
|
CONF_SET_POSITION_TEMPLATE = 'set_position_template'
|
||||||
|
|
||||||
CONF_PAYLOAD_OPEN = 'payload_open'
|
CONF_PAYLOAD_OPEN = 'payload_open'
|
||||||
CONF_PAYLOAD_CLOSE = 'payload_close'
|
CONF_PAYLOAD_CLOSE = 'payload_close'
|
||||||
@ -55,10 +59,17 @@ DEFAULT_TILT_MAX = 100
|
|||||||
DEFAULT_TILT_OPTIMISTIC = False
|
DEFAULT_TILT_OPTIMISTIC = False
|
||||||
DEFAULT_TILT_INVERT_STATE = False
|
DEFAULT_TILT_INVERT_STATE = False
|
||||||
|
|
||||||
|
OPEN_CLOSE_FEATURES = (SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP)
|
||||||
TILT_FEATURES = (SUPPORT_OPEN_TILT | SUPPORT_CLOSE_TILT | SUPPORT_STOP_TILT |
|
TILT_FEATURES = (SUPPORT_OPEN_TILT | SUPPORT_CLOSE_TILT | SUPPORT_STOP_TILT |
|
||||||
SUPPORT_SET_TILT_POSITION)
|
SUPPORT_SET_TILT_POSITION)
|
||||||
|
|
||||||
PLATFORM_SCHEMA = mqtt.MQTT_RW_PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
|
||||||
|
vol.Optional(CONF_COMMAND_TOPIC, default=None): valid_publish_topic,
|
||||||
|
vol.Optional(CONF_POSITION_TOPIC, default=None): valid_publish_topic,
|
||||||
|
vol.Optional(CONF_SET_POSITION_TEMPLATE, default=None): cv.template,
|
||||||
|
vol.Optional(CONF_RETAIN, default=DEFAULT_RETAIN): cv.boolean,
|
||||||
|
vol.Optional(CONF_STATE_TOPIC): valid_subscribe_topic,
|
||||||
|
vol.Optional(CONF_VALUE_TEMPLATE): cv.template,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_OPEN, default=DEFAULT_PAYLOAD_OPEN): cv.string,
|
vol.Optional(CONF_PAYLOAD_OPEN, default=DEFAULT_PAYLOAD_OPEN): cv.string,
|
||||||
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): cv.string,
|
vol.Optional(CONF_PAYLOAD_CLOSE, default=DEFAULT_PAYLOAD_CLOSE): cv.string,
|
||||||
@ -87,6 +98,9 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
value_template = config.get(CONF_VALUE_TEMPLATE)
|
value_template = config.get(CONF_VALUE_TEMPLATE)
|
||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
value_template.hass = hass
|
value_template.hass = hass
|
||||||
|
set_position_template = config.get(CONF_SET_POSITION_TEMPLATE)
|
||||||
|
if set_position_template is not None:
|
||||||
|
set_position_template.hass = hass
|
||||||
|
|
||||||
async_add_devices([MqttCover(
|
async_add_devices([MqttCover(
|
||||||
config.get(CONF_NAME),
|
config.get(CONF_NAME),
|
||||||
@ -109,6 +123,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
|||||||
config.get(CONF_TILT_MAX),
|
config.get(CONF_TILT_MAX),
|
||||||
config.get(CONF_TILT_STATE_OPTIMISTIC),
|
config.get(CONF_TILT_STATE_OPTIMISTIC),
|
||||||
config.get(CONF_TILT_INVERT_STATE),
|
config.get(CONF_TILT_INVERT_STATE),
|
||||||
|
config.get(CONF_POSITION_TOPIC),
|
||||||
|
set_position_template,
|
||||||
)])
|
)])
|
||||||
|
|
||||||
|
|
||||||
@ -120,7 +136,7 @@ class MqttCover(CoverDevice):
|
|||||||
payload_open, payload_close, payload_stop,
|
payload_open, payload_close, payload_stop,
|
||||||
optimistic, value_template, tilt_open_position,
|
optimistic, value_template, tilt_open_position,
|
||||||
tilt_closed_position, tilt_min, tilt_max, tilt_optimistic,
|
tilt_closed_position, tilt_min, tilt_max, tilt_optimistic,
|
||||||
tilt_invert):
|
tilt_invert, position_topic, set_position_template):
|
||||||
"""Initialize the cover."""
|
"""Initialize the cover."""
|
||||||
self._position = None
|
self._position = None
|
||||||
self._state = None
|
self._state = None
|
||||||
@ -145,6 +161,8 @@ class MqttCover(CoverDevice):
|
|||||||
self._tilt_max = tilt_max
|
self._tilt_max = tilt_max
|
||||||
self._tilt_optimistic = tilt_optimistic
|
self._tilt_optimistic = tilt_optimistic
|
||||||
self._tilt_invert = tilt_invert
|
self._tilt_invert = tilt_invert
|
||||||
|
self._position_topic = position_topic
|
||||||
|
self._set_position_template = set_position_template
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_added_to_hass(self):
|
def async_added_to_hass(self):
|
||||||
@ -233,9 +251,11 @@ class MqttCover(CoverDevice):
|
|||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Flag supported features."""
|
"""Flag supported features."""
|
||||||
supported_features = SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP
|
supported_features = 0
|
||||||
|
if self._command_topic is not None:
|
||||||
|
supported_features = OPEN_CLOSE_FEATURES
|
||||||
|
|
||||||
if self.current_cover_position is not None:
|
if self._position_topic is not None:
|
||||||
supported_features |= SUPPORT_SET_POSITION
|
supported_features |= SUPPORT_SET_POSITION
|
||||||
|
|
||||||
if self._tilt_command_topic is not None:
|
if self._tilt_command_topic is not None:
|
||||||
@ -315,6 +335,22 @@ class MqttCover(CoverDevice):
|
|||||||
mqtt.async_publish(self.hass, self._tilt_command_topic,
|
mqtt.async_publish(self.hass, self._tilt_command_topic,
|
||||||
level, self._qos, self._retain)
|
level, self._qos, self._retain)
|
||||||
|
|
||||||
|
@asyncio.coroutine
|
||||||
|
def async_set_cover_position(self, **kwargs):
|
||||||
|
"""Move the cover to a specific position."""
|
||||||
|
if ATTR_POSITION in kwargs:
|
||||||
|
position = kwargs[ATTR_POSITION]
|
||||||
|
if self._set_position_template is not None:
|
||||||
|
try:
|
||||||
|
position = self._set_position_template.async_render(
|
||||||
|
**kwargs)
|
||||||
|
except TemplateError as ex:
|
||||||
|
_LOGGER.error(ex)
|
||||||
|
self._state = None
|
||||||
|
|
||||||
|
mqtt.async_publish(self.hass, self._position_topic,
|
||||||
|
position, self._qos, self._retain)
|
||||||
|
|
||||||
def find_percentage_in_range(self, position):
|
def find_percentage_in_range(self, position):
|
||||||
"""Find the 0-100% value within the specified range."""
|
"""Find the 0-100% value within the specified range."""
|
||||||
# the range of motion as defined by the min max values
|
# the range of motion as defined by the min max values
|
||||||
|
@ -215,6 +215,8 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
'cover.test').attributes
|
'cover.test').attributes
|
||||||
self.assertFalse('current_position' in state_attributes_dict)
|
self.assertFalse('current_position' in state_attributes_dict)
|
||||||
self.assertFalse('current_tilt_position' in state_attributes_dict)
|
self.assertFalse('current_tilt_position' in state_attributes_dict)
|
||||||
|
self.assertFalse(4 & self.hass.states.get(
|
||||||
|
'cover.test').attributes['supported_features'] == 4)
|
||||||
|
|
||||||
fire_mqtt_message(self.hass, 'state-topic', '0')
|
fire_mqtt_message(self.hass, 'state-topic', '0')
|
||||||
self.hass.block_till_done()
|
self.hass.block_till_done()
|
||||||
@ -240,6 +242,119 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
'cover.test').attributes['current_position']
|
'cover.test').attributes['current_position']
|
||||||
self.assertEqual(50, current_cover_position)
|
self.assertEqual(50, current_cover_position)
|
||||||
|
|
||||||
|
def test_set_cover_position(self):
|
||||||
|
"""Test setting cover position."""
|
||||||
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
|
cover.DOMAIN: {
|
||||||
|
'platform': 'mqtt',
|
||||||
|
'name': 'test',
|
||||||
|
'state_topic': 'state-topic',
|
||||||
|
'command_topic': 'command-topic',
|
||||||
|
'set_position_topic': 'position-topic',
|
||||||
|
'payload_open': 'OPEN',
|
||||||
|
'payload_close': 'CLOSE',
|
||||||
|
'payload_stop': 'STOP'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
state_attributes_dict = self.hass.states.get(
|
||||||
|
'cover.test').attributes
|
||||||
|
self.assertFalse('current_position' in state_attributes_dict)
|
||||||
|
self.assertFalse('current_tilt_position' in state_attributes_dict)
|
||||||
|
|
||||||
|
self.assertTrue(4 & self.hass.states.get(
|
||||||
|
'cover.test').attributes['supported_features'] == 4)
|
||||||
|
|
||||||
|
fire_mqtt_message(self.hass, 'state-topic', '22')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
state_attributes_dict = self.hass.states.get(
|
||||||
|
'cover.test').attributes
|
||||||
|
self.assertTrue('current_position' in state_attributes_dict)
|
||||||
|
self.assertFalse('current_tilt_position' in state_attributes_dict)
|
||||||
|
current_cover_position = self.hass.states.get(
|
||||||
|
'cover.test').attributes['current_position']
|
||||||
|
self.assertEqual(22, current_cover_position)
|
||||||
|
|
||||||
|
def test_set_position_templated(self):
|
||||||
|
"""Test setting cover position via template."""
|
||||||
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
|
cover.DOMAIN: {
|
||||||
|
'platform': 'mqtt',
|
||||||
|
'name': 'test',
|
||||||
|
'state_topic': 'state-topic',
|
||||||
|
'command_topic': 'command-topic',
|
||||||
|
'set_position_topic': 'position-topic',
|
||||||
|
'set_position_template': '{{100-62}}',
|
||||||
|
'payload_open': 'OPEN',
|
||||||
|
'payload_close': 'CLOSE',
|
||||||
|
'payload_stop': 'STOP'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
cover.set_cover_position(self.hass, 100, 'cover.test')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(('position-topic', '38', 0, False),
|
||||||
|
self.mock_publish.mock_calls[-2][1])
|
||||||
|
|
||||||
|
def test_set_position_untemplated(self):
|
||||||
|
"""Test setting cover position via template."""
|
||||||
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
|
cover.DOMAIN: {
|
||||||
|
'platform': 'mqtt',
|
||||||
|
'name': 'test',
|
||||||
|
'state_topic': 'state-topic',
|
||||||
|
'command_topic': 'command-topic',
|
||||||
|
'set_position_topic': 'position-topic',
|
||||||
|
'payload_open': 'OPEN',
|
||||||
|
'payload_close': 'CLOSE',
|
||||||
|
'payload_stop': 'STOP'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
cover.set_cover_position(self.hass, 62, 'cover.test')
|
||||||
|
self.hass.block_till_done()
|
||||||
|
|
||||||
|
self.assertEqual(('position-topic', 62, 0, False),
|
||||||
|
self.mock_publish.mock_calls[-2][1])
|
||||||
|
|
||||||
|
def test_no_command_topic(self):
|
||||||
|
"""Test with no command topic."""
|
||||||
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
|
cover.DOMAIN: {
|
||||||
|
'platform': 'mqtt',
|
||||||
|
'name': 'test',
|
||||||
|
'qos': 0,
|
||||||
|
'payload_open': 'OPEN',
|
||||||
|
'payload_close': 'CLOSE',
|
||||||
|
'payload_stop': 'STOP',
|
||||||
|
'tilt_command_topic': 'tilt-command',
|
||||||
|
'tilt_status_topic': 'tilt-status'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
self.assertEqual(240, self.hass.states.get(
|
||||||
|
'cover.test').attributes['supported_features'])
|
||||||
|
|
||||||
|
def test_with_command_topic_and_tilt(self):
|
||||||
|
"""Test with command topic and tilt config."""
|
||||||
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
|
cover.DOMAIN: {
|
||||||
|
'command_topic': 'test',
|
||||||
|
'platform': 'mqtt',
|
||||||
|
'name': 'test',
|
||||||
|
'qos': 0,
|
||||||
|
'payload_open': 'OPEN',
|
||||||
|
'payload_close': 'CLOSE',
|
||||||
|
'payload_stop': 'STOP',
|
||||||
|
'tilt_command_topic': 'tilt-command',
|
||||||
|
'tilt_status_topic': 'tilt-status'
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
self.assertEqual(251, self.hass.states.get(
|
||||||
|
'cover.test').attributes['supported_features'])
|
||||||
|
|
||||||
def test_tilt_defaults(self):
|
def test_tilt_defaults(self):
|
||||||
"""Test the defaults."""
|
"""Test the defaults."""
|
||||||
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
self.assertTrue(setup_component(self.hass, cover.DOMAIN, {
|
||||||
@ -457,7 +572,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
100, 0, 0, 100, False, False)
|
100, 0, 0, 100, False, False, None, None)
|
||||||
|
|
||||||
self.assertEqual(44, mqtt_cover.find_percentage_in_range(44))
|
self.assertEqual(44, mqtt_cover.find_percentage_in_range(44))
|
||||||
|
|
||||||
@ -466,7 +581,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
180, 80, 80, 180, False, False)
|
180, 80, 80, 180, False, False, None, None)
|
||||||
|
|
||||||
self.assertEqual(40, mqtt_cover.find_percentage_in_range(120))
|
self.assertEqual(40, mqtt_cover.find_percentage_in_range(120))
|
||||||
|
|
||||||
@ -475,7 +590,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
100, 0, 0, 100, False, True)
|
100, 0, 0, 100, False, True, None, None)
|
||||||
|
|
||||||
self.assertEqual(56, mqtt_cover.find_percentage_in_range(44))
|
self.assertEqual(56, mqtt_cover.find_percentage_in_range(44))
|
||||||
|
|
||||||
@ -484,7 +599,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
180, 80, 80, 180, False, True)
|
180, 80, 80, 180, False, True, None, None)
|
||||||
|
|
||||||
self.assertEqual(60, mqtt_cover.find_percentage_in_range(120))
|
self.assertEqual(60, mqtt_cover.find_percentage_in_range(120))
|
||||||
|
|
||||||
@ -493,7 +608,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
100, 0, 0, 100, False, False)
|
100, 0, 0, 100, False, False, None, None)
|
||||||
|
|
||||||
self.assertEqual(44, mqtt_cover.find_in_range_from_percent(44))
|
self.assertEqual(44, mqtt_cover.find_in_range_from_percent(44))
|
||||||
|
|
||||||
@ -502,7 +617,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
180, 80, 80, 180, False, False)
|
180, 80, 80, 180, False, False, None, None)
|
||||||
|
|
||||||
self.assertEqual(120, mqtt_cover.find_in_range_from_percent(40))
|
self.assertEqual(120, mqtt_cover.find_in_range_from_percent(40))
|
||||||
|
|
||||||
@ -511,7 +626,7 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
100, 0, 0, 100, False, True)
|
100, 0, 0, 100, False, True, None, None)
|
||||||
|
|
||||||
self.assertEqual(44, mqtt_cover.find_in_range_from_percent(56))
|
self.assertEqual(44, mqtt_cover.find_in_range_from_percent(56))
|
||||||
|
|
||||||
@ -520,6 +635,6 @@ class TestCoverMQTT(unittest.TestCase):
|
|||||||
mqtt_cover = MqttCover(
|
mqtt_cover = MqttCover(
|
||||||
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
'cover.test', 'foo', 'bar', 'fooBar', "fooBarBaz", 0, False,
|
||||||
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
'OPEN', 'CLOSE', 'OPEN', 'CLOSE', 'STOP', False, None,
|
||||||
180, 80, 80, 180, False, True)
|
180, 80, 80, 180, False, True, None, None)
|
||||||
|
|
||||||
self.assertEqual(120, mqtt_cover.find_in_range_from_percent(60))
|
self.assertEqual(120, mqtt_cover.find_in_range_from_percent(60))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user