"""The tests for the Demo vacuum platform.""" import unittest from homeassistant.components import vacuum from homeassistant.components.vacuum import ( ATTR_BATTERY_LEVEL, ATTR_BATTERY_ICON, ATTR_STATUS, ATTR_FAN_SPEED, mqtt) from homeassistant.components.mqtt import CONF_COMMAND_TOPIC from homeassistant.const import ( CONF_PLATFORM, STATE_OFF, STATE_ON, STATE_UNAVAILABLE, CONF_NAME) from homeassistant.setup import setup_component from tests.common import ( fire_mqtt_message, get_test_home_assistant, mock_mqtt_component) from tests.components.vacuum import common class TestVacuumMQTT(unittest.TestCase): """MQTT vacuum component test class.""" def setUp(self): # pylint: disable=invalid-name """Set up things to be run when tests are started.""" self.hass = get_test_home_assistant() self.mock_publish = mock_mqtt_component(self.hass) self.default_config = { CONF_PLATFORM: 'mqtt', CONF_NAME: 'mqtttest', CONF_COMMAND_TOPIC: 'vacuum/command', mqtt.CONF_SEND_COMMAND_TOPIC: 'vacuum/send_command', mqtt.CONF_BATTERY_LEVEL_TOPIC: 'vacuum/state', mqtt.CONF_BATTERY_LEVEL_TEMPLATE: '{{ value_json.battery_level }}', mqtt.CONF_CHARGING_TOPIC: 'vacuum/state', mqtt.CONF_CHARGING_TEMPLATE: '{{ value_json.charging }}', mqtt.CONF_CLEANING_TOPIC: 'vacuum/state', mqtt.CONF_CLEANING_TEMPLATE: '{{ value_json.cleaning }}', mqtt.CONF_DOCKED_TOPIC: 'vacuum/state', mqtt.CONF_DOCKED_TEMPLATE: '{{ value_json.docked }}', mqtt.CONF_STATE_TOPIC: 'vacuum/state', mqtt.CONF_STATE_TEMPLATE: '{{ value_json.state }}', mqtt.CONF_FAN_SPEED_TOPIC: 'vacuum/state', mqtt.CONF_FAN_SPEED_TEMPLATE: '{{ value_json.fan_speed }}', mqtt.CONF_SET_FAN_SPEED_TOPIC: 'vacuum/set_fan_speed', mqtt.CONF_FAN_SPEED_LIST: ['min', 'medium', 'high', 'max'], } def tearDown(self): # pylint: disable=invalid-name """Stop down everything that was started.""" self.hass.stop() def test_default_supported_features(self): """Test that the correct supported features.""" assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) entity = self.hass.states.get('vacuum.mqtttest') entity_features = \ entity.attributes.get(mqtt.CONF_SUPPORTED_FEATURES, 0) assert sorted(mqtt.services_to_strings(entity_features)) == \ sorted(['turn_on', 'turn_off', 'stop', 'return_home', 'battery', 'status', 'clean_spot']) def test_all_commands(self): """Test simple commands to the vacuum.""" self.default_config[mqtt.CONF_SUPPORTED_FEATURES] = \ mqtt.services_to_strings(mqtt.ALL_SERVICES) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) common.turn_on(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'turn_on', 0, False) self.mock_publish.async_publish.reset_mock() common.turn_off(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'turn_off', 0, False) self.mock_publish.async_publish.reset_mock() common.stop(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'stop', 0, False) self.mock_publish.async_publish.reset_mock() common.clean_spot(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'clean_spot', 0, False) self.mock_publish.async_publish.reset_mock() common.locate(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'locate', 0, False) self.mock_publish.async_publish.reset_mock() common.start_pause(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'start_pause', 0, False) self.mock_publish.async_publish.reset_mock() common.return_to_base(self.hass, 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/command', 'return_to_base', 0, False) self.mock_publish.async_publish.reset_mock() common.set_fan_speed(self.hass, 'high', 'vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/set_fan_speed', 'high', 0, False) self.mock_publish.async_publish.reset_mock() common.send_command(self.hass, '44 FE 93', entity_id='vacuum.mqtttest') self.hass.block_till_done() self.mock_publish.async_publish.assert_called_once_with( 'vacuum/send_command', '44 FE 93', 0, False) def test_status(self): """Test status updates from the vacuum.""" self.default_config[mqtt.CONF_SUPPORTED_FEATURES] = \ mqtt.services_to_strings(mqtt.ALL_SERVICES) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) message = """{ "battery_level": 54, "cleaning": true, "docked": false, "charging": false, "fan_speed": "max" }""" fire_mqtt_message(self.hass, 'vacuum/state', message) self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_ON == state.state assert 'mdi:battery-50' == \ state.attributes.get(ATTR_BATTERY_ICON) assert 54 == state.attributes.get(ATTR_BATTERY_LEVEL) assert 'max' == state.attributes.get(ATTR_FAN_SPEED) message = """{ "battery_level": 61, "docked": true, "cleaning": false, "charging": true, "fan_speed": "min" }""" fire_mqtt_message(self.hass, 'vacuum/state', message) self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_OFF == state.state assert 'mdi:battery-charging-60' == \ state.attributes.get(ATTR_BATTERY_ICON) assert 61 == state.attributes.get(ATTR_BATTERY_LEVEL) assert 'min' == state.attributes.get(ATTR_FAN_SPEED) def test_battery_template(self): """Test that you can use non-default templates for battery_level.""" self.default_config.update({ mqtt.CONF_SUPPORTED_FEATURES: mqtt.services_to_strings(mqtt.ALL_SERVICES), mqtt.CONF_BATTERY_LEVEL_TOPIC: "retroroomba/battery_level", mqtt.CONF_BATTERY_LEVEL_TEMPLATE: "{{ value }}" }) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) fire_mqtt_message(self.hass, 'retroroomba/battery_level', '54') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert 54 == state.attributes.get(ATTR_BATTERY_LEVEL) assert state.attributes.get(ATTR_BATTERY_ICON) == \ 'mdi:battery-50' def test_status_invalid_json(self): """Test to make sure nothing breaks if the vacuum sends bad JSON.""" self.default_config[mqtt.CONF_SUPPORTED_FEATURES] = \ mqtt.services_to_strings(mqtt.ALL_SERVICES) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) fire_mqtt_message(self.hass, 'vacuum/state', '{"asdfasas false}') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_OFF == state.state assert "Stopped" == state.attributes.get(ATTR_STATUS) def test_default_availability_payload(self): """Test availability by default payload with defined topic.""" self.default_config.update({ 'availability_topic': 'availability-topic' }) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state fire_mqtt_message(self.hass, 'availability-topic', 'online') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE != state.state fire_mqtt_message(self.hass, 'availability-topic', 'offline') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state def test_custom_availability_payload(self): """Test availability by custom payload with defined topic.""" self.default_config.update({ 'availability_topic': 'availability-topic', 'payload_available': 'good', 'payload_not_available': 'nogood' }) assert setup_component(self.hass, vacuum.DOMAIN, { vacuum.DOMAIN: self.default_config, }) state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state fire_mqtt_message(self.hass, 'availability-topic', 'good') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE != state.state fire_mqtt_message(self.hass, 'availability-topic', 'nogood') self.hass.block_till_done() state = self.hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state