diff --git a/homeassistant/components/mqtt/alarm_control_panel.py b/homeassistant/components/mqtt/alarm_control_panel.py index b3e4d452b5c..8e1b62414b7 100644 --- a/homeassistant/components/mqtt/alarm_control_panel.py +++ b/homeassistant/components/mqtt/alarm_control_panel.py @@ -19,8 +19,8 @@ from homeassistant.components.mqtt.discovery import ( MQTT_DISCOVERY_NEW, clear_discovery_hash) from homeassistant.const import ( CONF_CODE, CONF_DEVICE, CONF_NAME, STATE_ALARM_ARMED_AWAY, - STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_ALARM_PENDING, - STATE_ALARM_TRIGGERED) + STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, STATE_ALARM_DISARMED, + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED) from homeassistant.core import callback import homeassistant.helpers.config_validation as cv from homeassistant.helpers.dispatcher import async_dispatcher_connect @@ -31,7 +31,9 @@ _LOGGER = logging.getLogger(__name__) CONF_PAYLOAD_DISARM = 'payload_disarm' CONF_PAYLOAD_ARM_HOME = 'payload_arm_home' CONF_PAYLOAD_ARM_AWAY = 'payload_arm_away' +CONF_PAYLOAD_ARM_NIGHT = 'payload_arm_night' +DEFAULT_ARM_NIGHT = 'ARM_NIGHT' DEFAULT_ARM_AWAY = 'ARM_AWAY' DEFAULT_ARM_HOME = 'ARM_HOME' DEFAULT_DISARM = 'DISARM' @@ -44,6 +46,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({ vol.Required(CONF_STATE_TOPIC): mqtt.valid_subscribe_topic, vol.Optional(CONF_CODE): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, + vol.Optional(CONF_PAYLOAD_ARM_NIGHT, default=DEFAULT_ARM_NIGHT): cv.string, vol.Optional(CONF_PAYLOAD_ARM_AWAY, default=DEFAULT_ARM_AWAY): cv.string, vol.Optional(CONF_PAYLOAD_ARM_HOME, default=DEFAULT_ARM_HOME): cv.string, vol.Optional(CONF_PAYLOAD_DISARM, default=DEFAULT_DISARM): cv.string, @@ -124,7 +127,9 @@ class MqttAlarm(MqttAttributes, MqttAvailability, MqttDiscoveryUpdate, def message_received(topic, payload, qos): """Run when new MQTT message has been received.""" if payload not in (STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, - STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING, + STATE_ALARM_ARMED_AWAY, + STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED): _LOGGER.warning("Received unexpected payload: %s", payload) return @@ -213,6 +218,19 @@ class MqttAlarm(MqttAttributes, MqttAvailability, MqttDiscoveryUpdate, self._config.get(CONF_QOS), self._config.get(CONF_RETAIN)) + async def async_alarm_arm_night(self, code=None): + """Send arm night command. + + This method is a coroutine. + """ + if not self._validate_code(code, 'arming night'): + return + mqtt.async_publish( + self.hass, self._config.get(CONF_COMMAND_TOPIC), + self._config.get(CONF_PAYLOAD_ARM_NIGHT), + self._config.get(CONF_QOS), + self._config.get(CONF_RETAIN)) + def _validate_code(self, code, state): """Validate given code.""" conf_code = self._config.get(CONF_CODE) diff --git a/tests/components/mqtt/test_alarm_control_panel.py b/tests/components/mqtt/test_alarm_control_panel.py index 572cbdb0e10..81c993ed311 100644 --- a/tests/components/mqtt/test_alarm_control_panel.py +++ b/tests/components/mqtt/test_alarm_control_panel.py @@ -6,9 +6,9 @@ from unittest.mock import ANY from homeassistant.components import alarm_control_panel, mqtt from homeassistant.components.mqtt.discovery import async_start from homeassistant.const import ( - STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, - STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, STATE_UNAVAILABLE, - STATE_UNKNOWN) + STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_DISARMED, STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED, + STATE_UNAVAILABLE, STATE_UNKNOWN) from homeassistant.setup import setup_component from tests.common import ( @@ -72,8 +72,8 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): self.hass.states.get(entity_id).state for state in (STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, - STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING, - STATE_ALARM_TRIGGERED): + STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_NIGHT, + STATE_ALARM_PENDING, STATE_ALARM_TRIGGERED): fire_mqtt_message(self.hass, 'alarm/state', state) self.hass.block_till_done() assert state == self.hass.states.get(entity_id).state @@ -164,6 +164,39 @@ class TestAlarmControlPanelMQTT(unittest.TestCase): self.hass.block_till_done() assert call_count == self.mock_publish.call_count + def test_arm_night_publishes_mqtt(self): + """Test publishing of MQTT messages while armed.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + } + }) + + common.alarm_arm_night(self.hass) + self.hass.block_till_done() + self.mock_publish.async_publish.assert_called_once_with( + 'alarm/command', 'ARM_NIGHT', 0, False) + + def test_arm_night_not_publishes_mqtt_with_invalid_code(self): + """Test not publishing of MQTT messages with invalid code.""" + assert setup_component(self.hass, alarm_control_panel.DOMAIN, { + alarm_control_panel.DOMAIN: { + 'platform': 'mqtt', + 'name': 'test', + 'state_topic': 'alarm/state', + 'command_topic': 'alarm/command', + 'code': '1234' + } + }) + + call_count = self.mock_publish.call_count + common.alarm_arm_night(self.hass, 'abcd') + self.hass.block_till_done() + assert call_count == self.mock_publish.call_count + def test_disarm_publishes_mqtt(self): """Test publishing of MQTT messages while disarmed.""" assert setup_component(self.hass, alarm_control_panel.DOMAIN, {