mirror of https://github.com/home-assistant/core
Add separate command and state topics for mqtt lock (#29808)
* Update lock.py Allow different command and state topic + different command and state values. * Formatting updated after black run * TC updated to reflect different state & cmd values * Abbreviations for lock states added * additional non-default state test * whitespaces fixed * black formatting run
This commit is contained in:
parent
fd0375ac20
commit
1c2618d99a
|
@ -135,6 +135,8 @@ ABBREVIATIONS = {
|
||||||
"stat_off": "state_off",
|
"stat_off": "state_off",
|
||||||
"stat_on": "state_on",
|
"stat_on": "state_on",
|
||||||
"stat_open": "state_open",
|
"stat_open": "state_open",
|
||||||
|
"stat_locked": "state_locked",
|
||||||
|
"stat_unlocked": "state_unlocked",
|
||||||
"stat_t": "state_topic",
|
"stat_t": "state_topic",
|
||||||
"stat_tpl": "state_template",
|
"stat_tpl": "state_template",
|
||||||
"stat_val_tpl": "state_value_template",
|
"stat_val_tpl": "state_value_template",
|
||||||
|
|
|
@ -36,10 +36,16 @@ _LOGGER = logging.getLogger(__name__)
|
||||||
CONF_PAYLOAD_LOCK = "payload_lock"
|
CONF_PAYLOAD_LOCK = "payload_lock"
|
||||||
CONF_PAYLOAD_UNLOCK = "payload_unlock"
|
CONF_PAYLOAD_UNLOCK = "payload_unlock"
|
||||||
|
|
||||||
|
CONF_STATE_LOCKED = "state_locked"
|
||||||
|
CONF_STATE_UNLOCKED = "state_unlocked"
|
||||||
|
|
||||||
DEFAULT_NAME = "MQTT Lock"
|
DEFAULT_NAME = "MQTT Lock"
|
||||||
DEFAULT_OPTIMISTIC = False
|
DEFAULT_OPTIMISTIC = False
|
||||||
DEFAULT_PAYLOAD_LOCK = "LOCK"
|
DEFAULT_PAYLOAD_LOCK = "LOCK"
|
||||||
DEFAULT_PAYLOAD_UNLOCK = "UNLOCK"
|
DEFAULT_PAYLOAD_UNLOCK = "UNLOCK"
|
||||||
|
DEFAULT_STATE_LOCKED = "LOCKED"
|
||||||
|
DEFAULT_STATE_UNLOCKED = "UNLOCKED"
|
||||||
|
|
||||||
PLATFORM_SCHEMA = (
|
PLATFORM_SCHEMA = (
|
||||||
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
|
mqtt.MQTT_RW_PLATFORM_SCHEMA.extend(
|
||||||
{
|
{
|
||||||
|
@ -50,6 +56,10 @@ PLATFORM_SCHEMA = (
|
||||||
vol.Optional(
|
vol.Optional(
|
||||||
CONF_PAYLOAD_UNLOCK, default=DEFAULT_PAYLOAD_UNLOCK
|
CONF_PAYLOAD_UNLOCK, default=DEFAULT_PAYLOAD_UNLOCK
|
||||||
): cv.string,
|
): cv.string,
|
||||||
|
vol.Optional(CONF_STATE_LOCKED, default=DEFAULT_STATE_LOCKED): cv.string,
|
||||||
|
vol.Optional(
|
||||||
|
CONF_STATE_UNLOCKED, default=DEFAULT_STATE_UNLOCKED
|
||||||
|
): cv.string,
|
||||||
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
vol.Optional(CONF_UNIQUE_ID): cv.string,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -152,9 +162,9 @@ class MqttLock(
|
||||||
payload = msg.payload
|
payload = msg.payload
|
||||||
if value_template is not None:
|
if value_template is not None:
|
||||||
payload = value_template.async_render_with_possible_json_value(payload)
|
payload = value_template.async_render_with_possible_json_value(payload)
|
||||||
if payload == self._config[CONF_PAYLOAD_LOCK]:
|
if payload == self._config[CONF_STATE_LOCKED]:
|
||||||
self._state = True
|
self._state = True
|
||||||
elif payload == self._config[CONF_PAYLOAD_UNLOCK]:
|
elif payload == self._config[CONF_STATE_UNLOCKED]:
|
||||||
self._state = False
|
self._state = False
|
||||||
|
|
||||||
self.async_write_ha_state()
|
self.async_write_ha_state()
|
||||||
|
|
|
@ -34,6 +34,8 @@ async def test_controlling_state_via_topic(hass, mqtt_mock):
|
||||||
"command_topic": "command-topic",
|
"command_topic": "command-topic",
|
||||||
"payload_lock": "LOCK",
|
"payload_lock": "LOCK",
|
||||||
"payload_unlock": "UNLOCK",
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "LOCKED",
|
||||||
|
"state_unlocked": "UNLOCKED",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -42,12 +44,46 @@ async def test_controlling_state_via_topic(hass, mqtt_mock):
|
||||||
assert state.state is STATE_UNLOCKED
|
assert state.state is STATE_UNLOCKED
|
||||||
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "state-topic", "LOCK")
|
async_fire_mqtt_message(hass, "state-topic", "LOCKED")
|
||||||
|
|
||||||
state = hass.states.get("lock.test")
|
state = hass.states.get("lock.test")
|
||||||
assert state.state is STATE_LOCKED
|
assert state.state is STATE_LOCKED
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "state-topic", "UNLOCK")
|
async_fire_mqtt_message(hass, "state-topic", "UNLOCKED")
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_UNLOCKED
|
||||||
|
|
||||||
|
|
||||||
|
async def test_controlling_non_default_state_via_topic(hass, mqtt_mock):
|
||||||
|
"""Test the controlling state via topic."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
lock.DOMAIN,
|
||||||
|
{
|
||||||
|
lock.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"state_topic": "state-topic",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"payload_lock": "LOCK",
|
||||||
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "closed",
|
||||||
|
"state_unlocked": "open",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_UNLOCKED
|
||||||
|
assert not state.attributes.get(ATTR_ASSUMED_STATE)
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "state-topic", "closed")
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_LOCKED
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "state-topic", "open")
|
||||||
|
|
||||||
state = hass.states.get("lock.test")
|
state = hass.states.get("lock.test")
|
||||||
assert state.state is STATE_UNLOCKED
|
assert state.state is STATE_UNLOCKED
|
||||||
|
@ -66,6 +102,8 @@ async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock):
|
||||||
"command_topic": "command-topic",
|
"command_topic": "command-topic",
|
||||||
"payload_lock": "LOCK",
|
"payload_lock": "LOCK",
|
||||||
"payload_unlock": "UNLOCK",
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "LOCKED",
|
||||||
|
"state_unlocked": "UNLOCKED",
|
||||||
"value_template": "{{ value_json.val }}",
|
"value_template": "{{ value_json.val }}",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -74,12 +112,48 @@ async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock):
|
||||||
state = hass.states.get("lock.test")
|
state = hass.states.get("lock.test")
|
||||||
assert state.state is STATE_UNLOCKED
|
assert state.state is STATE_UNLOCKED
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "state-topic", '{"val":"LOCK"}')
|
async_fire_mqtt_message(hass, "state-topic", '{"val":"LOCKED"}')
|
||||||
|
|
||||||
state = hass.states.get("lock.test")
|
state = hass.states.get("lock.test")
|
||||||
assert state.state is STATE_LOCKED
|
assert state.state is STATE_LOCKED
|
||||||
|
|
||||||
async_fire_mqtt_message(hass, "state-topic", '{"val":"UNLOCK"}')
|
async_fire_mqtt_message(hass, "state-topic", '{"val":"UNLOCKED"}')
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_UNLOCKED
|
||||||
|
|
||||||
|
|
||||||
|
async def test_controlling_non_default_state_via_topic_and_json_message(
|
||||||
|
hass, mqtt_mock
|
||||||
|
):
|
||||||
|
"""Test the controlling state via topic and JSON message."""
|
||||||
|
assert await async_setup_component(
|
||||||
|
hass,
|
||||||
|
lock.DOMAIN,
|
||||||
|
{
|
||||||
|
lock.DOMAIN: {
|
||||||
|
"platform": "mqtt",
|
||||||
|
"name": "test",
|
||||||
|
"state_topic": "state-topic",
|
||||||
|
"command_topic": "command-topic",
|
||||||
|
"payload_lock": "LOCK",
|
||||||
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "closed",
|
||||||
|
"state_unlocked": "open",
|
||||||
|
"value_template": "{{ value_json.val }}",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_UNLOCKED
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "state-topic", '{"val":"closed"}')
|
||||||
|
|
||||||
|
state = hass.states.get("lock.test")
|
||||||
|
assert state.state is STATE_LOCKED
|
||||||
|
|
||||||
|
async_fire_mqtt_message(hass, "state-topic", '{"val":"open"}')
|
||||||
|
|
||||||
state = hass.states.get("lock.test")
|
state = hass.states.get("lock.test")
|
||||||
assert state.state is STATE_UNLOCKED
|
assert state.state is STATE_UNLOCKED
|
||||||
|
@ -97,6 +171,8 @@ async def test_sending_mqtt_commands_and_optimistic(hass, mqtt_mock):
|
||||||
"command_topic": "command-topic",
|
"command_topic": "command-topic",
|
||||||
"payload_lock": "LOCK",
|
"payload_lock": "LOCK",
|
||||||
"payload_unlock": "UNLOCK",
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "LOCKED",
|
||||||
|
"state_unlocked": "UNLOCKED",
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -135,6 +211,8 @@ async def test_sending_mqtt_commands_and_explicit_optimistic(hass, mqtt_mock):
|
||||||
"command_topic": "command-topic",
|
"command_topic": "command-topic",
|
||||||
"payload_lock": "LOCK",
|
"payload_lock": "LOCK",
|
||||||
"payload_unlock": "UNLOCK",
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "LOCKED",
|
||||||
|
"state_unlocked": "UNLOCKED",
|
||||||
"optimistic": True,
|
"optimistic": True,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -206,6 +284,8 @@ async def test_custom_availability_payload(hass, mqtt_mock):
|
||||||
"command_topic": "command-topic",
|
"command_topic": "command-topic",
|
||||||
"payload_lock": "LOCK",
|
"payload_lock": "LOCK",
|
||||||
"payload_unlock": "UNLOCK",
|
"payload_unlock": "UNLOCK",
|
||||||
|
"state_locked": "LOCKED",
|
||||||
|
"state_unlocked": "UNLOCKED",
|
||||||
"availability_topic": "availability-topic",
|
"availability_topic": "availability-topic",
|
||||||
"payload_available": "good",
|
"payload_available": "good",
|
||||||
"payload_not_available": "nogood",
|
"payload_not_available": "nogood",
|
||||||
|
|
Loading…
Reference in New Issue