async def test_controlling_state_via_topic_and_json_message( hass, mock_publish): """Test the controlling state via topic and JSON message.""" assert await async_setup_component(hass, switch.DOMAIN, { switch.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'state-topic', 'command_topic': 'command-topic', 'payload_on': 'beer on', 'payload_off': 'beer off', 'value_template': '{{ value_json.val }}' } }) state = hass.states.get('switch.test') assert STATE_OFF == state.state async_fire_mqtt_message(hass, 'state-topic', '{"val":"beer on"}') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_ON == state.state async_fire_mqtt_message(hass, 'state-topic', '{"val":"beer off"}') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_OFF == state.state
async def test_custom_availability_payload(hass, mock_publish): """Test availability by custom payload with defined topic.""" default_config.update({ 'availability_topic': 'availability-topic', 'payload_available': 'good', 'payload_not_available': 'nogood' }) assert await async_setup_component(hass, vacuum.DOMAIN, { vacuum.DOMAIN: default_config, }) state = hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state async_fire_mqtt_message(hass, 'availability-topic', 'good') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE != state.state async_fire_mqtt_message(hass, 'availability-topic', 'nogood') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('vacuum.mqtttest') assert STATE_UNAVAILABLE == state.state
async def test_controlling_state_via_topic(hass, mock_publish): """Test the controlling state via topic.""" assert await async_setup_component(hass, switch.DOMAIN, { switch.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'state-topic', 'command_topic': 'command-topic', 'payload_on': 1, 'payload_off': 0 } }) state = hass.states.get('switch.test') assert STATE_OFF == state.state assert not state.attributes.get(ATTR_ASSUMED_STATE) async_fire_mqtt_message(hass, 'state-topic', '1') await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_ON == state.state async_fire_mqtt_message(hass, 'state-topic', '0') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_OFF == state.state
async def test_custom_state_payload(hass, mock_publish): """Test the state payload.""" assert await async_setup_component(hass, switch.DOMAIN, { switch.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'state-topic', 'command_topic': 'command-topic', 'payload_on': 1, 'payload_off': 0, 'state_on': "HIGH", 'state_off': "LOW", } }) state = hass.states.get('switch.test') assert STATE_OFF == state.state assert not state.attributes.get(ATTR_ASSUMED_STATE) async_fire_mqtt_message(hass, 'state-topic', 'HIGH') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_ON == state.state async_fire_mqtt_message(hass, 'state-topic', 'LOW') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('switch.test') assert STATE_OFF == state.state
def test_snips_call_action(hass, mqtt_mock): """Test calling action via Snips.""" calls = async_mock_service(hass, 'test', 'service') result = yield from async_setup_component(hass, "snips", { "snips": { "intents": { "Lights": { "action": { "service": "test.service", "data_template": { "color": "{{ light_color }}" } } } } } }) assert result async_fire_mqtt_message(hass, 'hermes/nlu/intentParsed', EXAMPLE_MSG) yield from hass.async_block_till_done() assert len(calls) == 1 call = calls[0] assert call.data.get('color') == 'blue'
async def test_discovery_update_vacuum(hass, mock_publish): """Test update of discovered vacuum.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, 'homeassistant', {}, entry) data1 = ( '{ "name": "Beer",' ' "command_topic": "test_topic" }' ) data2 = ( '{ "name": "Milk",' ' "command_topic": "test_topic" }' ) async_fire_mqtt_message(hass, 'homeassistant/vacuum/bla/config', data1) await hass.async_block_till_done() state = hass.states.get('vacuum.beer') assert state is not None assert state.name == 'Beer' async_fire_mqtt_message(hass, 'homeassistant/vacuum/bla/config', data2) await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('vacuum.beer') assert state is not None assert state.name == 'Milk' state = hass.states.get('vacuum.milk') assert state is None
async def test_default_availability_payload(hass, mqtt_mock): """Test availability by default payload with defined topic.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'schema': 'json', 'name': 'test', 'state_topic': 'test_light_rgb', 'command_topic': 'test_light_rgb/set', 'availability_topic': 'availability-topic' } }) state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state async_fire_mqtt_message(hass, 'availability-topic', 'online') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE != state.state async_fire_mqtt_message(hass, 'availability-topic', 'offline') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state
def test_discovery_removal(hass, mqtt_mock, caplog): """Test expansion of abbreviated discovery payload.""" yield from async_start(hass, 'homeassistant', {}) data = ( '{ "name": "Beer",' ' "status_topic": "test_topic",' ' "command_topic": "test_topic" }' ) async_fire_mqtt_message(hass, 'homeassistant/switch/bla/config', data) yield from hass.async_block_till_done() state = hass.states.get('switch.beer') assert state is not None assert state.name == 'Beer' async_fire_mqtt_message(hass, 'homeassistant/switch/bla/config', '') yield from hass.async_block_till_done() yield from hass.async_block_till_done() state = hass.states.get('switch.beer') assert state is None
async def test_custom_availability_payload(hass, mqtt_mock): """Test availability by custom payload with defined topic.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'command_topic': 'test_light/set', 'brightness_command_topic': 'test_light/bright', 'rgb_command_topic': "test_light/rgb", 'availability_topic': 'availability-topic', 'payload_available': 'good', 'payload_not_available': 'nogood' } }) state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state async_fire_mqtt_message(hass, 'availability-topic', 'good') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE != state.state async_fire_mqtt_message(hass, 'availability-topic', 'nogood') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state
async def test_no_color_brightness_color_temp_hs_white_xy_if_no_topics( hass, mqtt_mock): """Test if there is no color and brightness if no topic.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_light_rgb/status', 'command_topic': 'test_light_rgb/set', } }) state = hass.states.get('light.test') assert STATE_OFF == state.state assert state.attributes.get('rgb_color') is None assert state.attributes.get('brightness') is None assert state.attributes.get('color_temp') is None assert state.attributes.get('hs_color') is None assert state.attributes.get('white_value') is None assert state.attributes.get('xy_color') is None async_fire_mqtt_message(hass, 'test_light_rgb/status', 'ON') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_ON == state.state assert state.attributes.get('rgb_color') is None assert state.attributes.get('brightness') is None assert state.attributes.get('color_temp') is None assert state.attributes.get('hs_color') is None assert state.attributes.get('white_value') is None assert state.attributes.get('xy_color') is None
async def test_discovery_broken(hass, mqtt_mock, caplog): """Test handling of bad discovery message.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, 'homeassistant', {}, entry) data1 = ( '{ "name": "Beer" }' ) data2 = ( '{ "name": "Milk",' ' "schema": "template",' ' "state_topic": "test_topic",' ' "command_topic": "test_topic",' ' "command_on_template": "on",' ' "command_off_template": "off"}' ) async_fire_mqtt_message(hass, 'homeassistant/light/bla/config', data1) await hass.async_block_till_done() state = hass.states.get('light.beer') assert state is None async_fire_mqtt_message(hass, 'homeassistant/light/bla/config', data2) await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('light.milk') assert state is not None assert state.name == 'Milk' state = hass.states.get('light.beer') assert state is None
async def test_brightness_scale(hass, mqtt_mock): """Test for brightness scaling.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'schema': 'json', 'name': 'test', 'state_topic': 'test_light_bright_scale', 'command_topic': 'test_light_bright_scale/set', 'brightness': True, 'brightness_scale': 99 } }) state = hass.states.get('light.test') assert STATE_OFF == state.state assert state.attributes.get('brightness') is None assert not state.attributes.get(ATTR_ASSUMED_STATE) # Turn on the light async_fire_mqtt_message(hass, 'test_light_bright_scale', '{"state":"ON"}') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_ON == state.state assert 255 == state.attributes.get('brightness') # Turn on the light with brightness async_fire_mqtt_message(hass, 'test_light_bright_scale', '{"state":"ON", "brightness": 99}') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_ON == state.state assert 255 == state.attributes.get('brightness')
async def test_controlling_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', '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":"LOCK"}') await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is STATE_LOCKED async_fire_mqtt_message(hass, 'state-topic', '{"val":"UNLOCK"}') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is STATE_UNLOCKED
async def test_discovery_update_climate(hass, mqtt_mock, caplog): """Test update of discovered climate.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, 'homeassistant', {}, entry) data1 = ( '{ "name": "Beer" }' ) data2 = ( '{ "name": "Milk" }' ) async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config', data1) await hass.async_block_till_done() state = hass.states.get('climate.beer') assert state is not None assert state.name == 'Beer' async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config', data2) await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('climate.beer') assert state is not None assert state.name == 'Milk' state = hass.states.get('climate.milk') assert state is None
async def test_entity_device_info_with_identifier(hass, mqtt_mock): """Test MQTT climate device registry integration.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) entry.add_to_hass(hass) await async_start(hass, 'homeassistant', {}, entry) registry = await hass.helpers.device_registry.async_get_registry() data = json.dumps({ 'platform': 'mqtt', 'name': 'Test 1', 'device': { 'identifiers': ['helloworld'], 'connections': [ ["mac", "02:5b:26:a8:dc:12"], ], 'manufacturer': 'Whatever', 'name': 'Beer', 'model': 'Glass', 'sw_version': '0.1-beta', }, 'unique_id': 'veryunique' }) async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.identifiers == {('mqtt', 'helloworld')} assert device.connections == {('mac', "02:5b:26:a8:dc:12")} assert device.manufacturer == 'Whatever' assert device.name == 'Beer' assert device.model == 'Glass' assert device.sw_version == '0.1-beta'
async def test_discovery_removal_alarm(hass, mqtt_mock, caplog): """Test removal of discovered alarm_control_panel.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, 'homeassistant', {}, entry) data = ( '{ "name": "Beer",' ' "state_topic": "test_topic",' ' "command_topic": "test_topic" }' ) async_fire_mqtt_message(hass, 'homeassistant/alarm_control_panel/bla/config', data) await hass.async_block_till_done() state = hass.states.get('alarm_control_panel.beer') assert state is not None assert state.name == 'Beer' async_fire_mqtt_message(hass, 'homeassistant/alarm_control_panel/bla/config', '') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('alarm_control_panel.beer') assert state is None
async def test_unique_id(hass): """Test unique id option only creates one light per unique_id.""" await async_mock_mqtt_component(hass) assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: [{ 'platform': 'mqtt', 'name': 'Test 1', 'schema': 'template', 'state_topic': 'test-topic', 'command_topic': 'test_topic', 'command_on_template': 'on,{{ transition }}', 'command_off_template': 'off,{{ transition|d }}', 'unique_id': 'TOTALLY_UNIQUE' }, { 'platform': 'mqtt', 'name': 'Test 2', 'schema': 'template', 'state_topic': 'test-topic', 'command_topic': 'test_topic', 'unique_id': 'TOTALLY_UNIQUE' }] }) async_fire_mqtt_message(hass, 'test-topic', 'payload') await hass.async_block_till_done() assert len(hass.states.async_entity_ids(light.DOMAIN)) == 1
async def test_default_availability_payload(hass, mqtt_mock): """Test availability by default payload with defined 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', 'availability_topic': 'availability-topic' } }) state = hass.states.get('lock.test') assert state.state is STATE_UNAVAILABLE async_fire_mqtt_message(hass, 'availability-topic', 'online') await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is not STATE_UNAVAILABLE async_fire_mqtt_message(hass, 'availability-topic', 'offline') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is STATE_UNAVAILABLE
async def test_no_color_brightness_color_temp_white_val_if_no_topics( hass, mqtt_mock): """Test for no RGB, brightness, color temp, effect, white val or XY.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt_json', 'name': 'test', 'state_topic': 'test_light_rgb', 'command_topic': 'test_light_rgb/set', } }) state = hass.states.get('light.test') assert STATE_OFF == state.state assert 40 == state.attributes.get(ATTR_SUPPORTED_FEATURES) assert state.attributes.get('rgb_color') is None assert state.attributes.get('brightness') is None assert state.attributes.get('color_temp') is None assert state.attributes.get('effect') is None assert state.attributes.get('white_value') is None assert state.attributes.get('xy_color') is None assert state.attributes.get('hs_color') is None async_fire_mqtt_message(hass, 'test_light_rgb', '{"state":"ON"}') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_ON == state.state assert state.attributes.get('rgb_color') is None assert state.attributes.get('brightness') is None assert state.attributes.get('color_temp') is None assert state.attributes.get('effect') is None assert state.attributes.get('white_value') is None assert state.attributes.get('xy_color') is None assert state.attributes.get('hs_color') is None
async def test_if_fires_on_topic_match(hass, calls): """Test if message is fired on topic match.""" assert await async_setup_component(hass, automation.DOMAIN, { automation.DOMAIN: { 'trigger': { 'platform': 'mqtt', 'topic': 'test-topic' }, 'action': { 'service': 'test.automation', 'data_template': { 'some': '{{ trigger.platform }} - {{ trigger.topic }}' ' - {{ trigger.payload }} - ' '{{ trigger.payload_json.hello }}' }, } } }) async_fire_mqtt_message(hass, 'test-topic', '{ "hello": "world" }') await hass.async_block_till_done() assert 1 == len(calls) assert 'mqtt - test-topic - { "hello": "world" } - world' == \ calls[0].data['some'] await common.async_turn_off(hass) await hass.async_block_till_done() async_fire_mqtt_message(hass, 'test-topic', 'test_payload') await hass.async_block_till_done() assert 1 == len(calls)
async def test_entity_device_info_with_hub(hass, mqtt_mock): """Test MQTT sensor device registry integration.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) entry.add_to_hass(hass) await async_start(hass, 'homeassistant', {}, entry) registry = await hass.helpers.device_registry.async_get_registry() hub = registry.async_get_or_create( config_entry_id='123', connections=set(), identifiers={('mqtt', 'hub-id')}, manufacturer='manufacturer', model='hub' ) data = json.dumps({ 'platform': 'mqtt', 'name': 'Test 1', 'state_topic': 'test-topic', 'device': { 'identifiers': ['helloworld'], 'via_hub': 'hub-id', }, 'unique_id': 'veryunique' }) async_fire_mqtt_message(hass, 'homeassistant/sensor/bla/config', data) await hass.async_block_till_done() await hass.async_block_till_done() device = registry.async_get_device({('mqtt', 'helloworld')}, set()) assert device is not None assert device.hub_device_id == hub.id
def test_discovery_expansion(hass, mqtt_mock, caplog): """Test expansion of abbreviated discovery payload.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) yield from async_start(hass, 'homeassistant', {}, entry) data = ( '{ "~": "some/base/topic",' ' "name": "DiscoveryExpansionTest1",' ' "stat_t": "test_topic/~",' ' "cmd_t": "~/test_topic" }' ) async_fire_mqtt_message( hass, 'homeassistant/switch/bla/config', data) yield from hass.async_block_till_done() state = hass.states.get('switch.DiscoveryExpansionTest1') assert state is not None assert state.name == 'DiscoveryExpansionTest1' assert ('switch', 'bla') in hass.data[ALREADY_DISCOVERED] assert state.state == STATE_OFF async_fire_mqtt_message(hass, 'test_topic/some/base/topic', 'ON') yield from hass.async_block_till_done() yield from hass.async_block_till_done() state = hass.states.get('switch.DiscoveryExpansionTest1') assert state.state == STATE_ON
async def test_custom_availability_payload(hass, mqtt_mock): """Test availability by custom payload with defined topic.""" assert await async_setup_component(hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'schema': 'template', 'name': 'test', 'command_topic': 'test_light_rgb/set', 'command_on_template': 'on,{{ transition }}', 'command_off_template': 'off,{{ transition|d }}', 'availability_topic': 'availability-topic', 'payload_available': 'good', 'payload_not_available': 'nogood' } }) state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state async_fire_mqtt_message(hass, 'availability-topic', 'good') await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE != state.state async_fire_mqtt_message(hass, 'availability-topic', 'nogood') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('light.test') assert STATE_UNAVAILABLE == state.state
async def test_snips_intent_user(hass): """Test intentName format user_XXX__intentName.""" await async_mock_mqtt_component(hass) result = await async_setup_component(hass, "snips", { "snips": {}, }) assert result payload = """ { "input": "what to do", "intent": { "intentName": "user_ABCDEF123__Lights", "confidenceScore": 1 }, "slots": [] } """ intents = async_mock_intent(hass, 'Lights') async_fire_mqtt_message(hass, 'hermes/intent/user_ABCDEF123__Lights', payload) await hass.async_block_till_done() assert len(intents) == 1 intent = intents[0] assert intent.platform == 'snips' assert intent.intent_type == 'Lights'
async def test_discovery_update_lock(hass, mqtt_mock, caplog): """Test update of discovered lock.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, 'homeassistant', {}, entry) data1 = ( '{ "name": "Beer",' ' "state_topic": "test_topic",' ' "command_topic": "command_topic",' ' "availability_topic": "availability_topic1" }' ) data2 = ( '{ "name": "Milk",' ' "state_topic": "test_topic2",' ' "command_topic": "command_topic",' ' "availability_topic": "availability_topic2" }' ) async_fire_mqtt_message(hass, 'homeassistant/lock/bla/config', data1) await hass.async_block_till_done() state = hass.states.get('lock.beer') assert state is not None assert state.name == 'Beer' async_fire_mqtt_message(hass, 'homeassistant/lock/bla/config', data2) await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('lock.beer') assert state is not None assert state.name == 'Milk' state = hass.states.get('lock.milk') assert state is None
async def test_mqtt_ws_subscription(hass, hass_ws_client): """Test MQTT websocket subscription.""" await async_mock_mqtt_component(hass) client = await hass_ws_client(hass) await client.send_json({ 'id': 5, 'type': 'mqtt/subscribe', 'topic': 'test-topic', }) response = await client.receive_json() assert response['success'] async_fire_mqtt_message(hass, 'test-topic', 'test1') async_fire_mqtt_message(hass, 'test-topic', 'test2') response = await client.receive_json() assert response['event']['topic'] == 'test-topic' assert response['event']['payload'] == 'test1' response = await client.receive_json() assert response['event']['topic'] == 'test-topic' assert response['event']['payload'] == 'test2' # Unsubscribe await client.send_json({ 'id': 8, 'type': 'unsubscribe_events', 'subscription': 5, }) response = await client.receive_json() assert response['success']
async def test_snips_low_probability(hass, mqtt_mock, caplog): """Test intent via Snips.""" caplog.set_level(logging.WARNING) result = await async_setup_component(hass, "snips", { "snips": { "probability_threshold": 0.5 }, }) assert result payload = """ { "input": "I am not sure what to say", "intent": { "intentName": "LightsMaybe", "probability": 0.49 }, "slots": [] } """ async_mock_intent(hass, 'LightsMaybe') async_fire_mqtt_message(hass, 'hermes/intent/LightsMaybe', payload) await hass.async_block_till_done() assert 'Intent below probaility threshold 0.49 < 0.5' in caplog.text
async def test_snips_intent_username(hass, mqtt_mock): """Test intentName format username:intentName.""" result = await async_setup_component(hass, "snips", { "snips": {}, }) assert result payload = """ { "input": "what to do", "intent": { "intentName": "username:Lights", "probability": 1 }, "slots": [] } """ intents = async_mock_intent(hass, 'Lights') async_fire_mqtt_message(hass, 'hermes/intent/username:Lights', payload) await hass.async_block_till_done() assert len(intents) == 1 intent = intents[0] assert intent.platform == 'snips' assert intent.intent_type == 'Lights'
async def test_controlling_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 = 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', 'LOCK') await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is STATE_LOCKED async_fire_mqtt_message(hass, 'state-topic', 'UNLOCK') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('lock.test') assert state.state is STATE_UNLOCKED
def test_only_valid_components(mock_load_platform, hass, mqtt_mock, caplog): """Test sending in invalid JSON.""" mock_load_platform.return_value = mock_coro() async_start(hass, 'homeassistant', {}) async_fire_mqtt_message(hass, 'homeassistant/climate/bla/config', '{}') yield from hass.async_block_till_done() assert 'Component climate is not supported' in caplog.text assert not mock_load_platform.called
async def help_test_entity_disabled_by_default(opp, mqtt_mock, domain, config): """Test device registry remove.""" # Add device settings to config config = copy.deepcopy(config[domain]) config["device"] = copy.deepcopy(DEFAULT_CONFIG_DEVICE_INFO_ID) config["enabled_by_default"] = False config["unique_id"] = "veryunique1" dev_registry = dr.async_get(opp) ent_registry = er.async_get(opp) # Discover a disabled entity data = json.dumps(config) async_fire_mqtt_message(opp, f"openpeerpower/{domain}/bla1/config", data) await opp.async_block_till_done() entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique1") assert not opp.states.get(entity_id) assert dev_registry.async_get_device({("mqtt", "helloworld")}) # Discover an enabled entity, tied to the same device config["enabled_by_default"] = True config["unique_id"] = "veryunique2" data = json.dumps(config) async_fire_mqtt_message(opp, f"openpeerpower/{domain}/bla2/config", data) await opp.async_block_till_done() entity_id = ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique2") assert opp.states.get(entity_id) # Remove the enabled entity, both entities and the device should be removed async_fire_mqtt_message(opp, f"openpeerpower/{domain}/bla2/config", "") await opp.async_block_till_done() assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique1") assert not ent_registry.async_get_entity_id(domain, mqtt.DOMAIN, "veryunique2") assert not dev_registry.async_get_device({("mqtt", "helloworld")})
async def test_controlling_state_via_topic(hass, mqtt_mock): """Test the controlling state via topic.""" assert await async_setup_component( hass, switch.DOMAIN, { switch.DOMAIN: { "platform": "mqtt", "name": "test", "state_topic": "state-topic", "command_topic": "command-topic", "payload_on": 1, "payload_off": 0, "device_class": "switch", } }, ) await hass.async_block_till_done() state = hass.states.get("switch.test") assert state.state == STATE_UNKNOWN assert state.attributes.get(ATTR_DEVICE_CLASS) == "switch" assert not state.attributes.get(ATTR_ASSUMED_STATE) async_fire_mqtt_message(hass, "state-topic", "1") state = hass.states.get("switch.test") assert state.state == STATE_ON async_fire_mqtt_message(hass, "state-topic", "0") state = hass.states.get("switch.test") assert state.state == STATE_OFF async_fire_mqtt_message(hass, "state-topic", "None") state = hass.states.get("switch.test") assert state.state == STATE_UNKNOWN
async def test_value_template(hass, mqtt_mock): """Test that it fetches the given payload with a template.""" topic = "test/number" await async_setup_component( hass, "number", { "number": { "platform": "mqtt", "state_topic": topic, "command_topic": topic, "name": "Test Number", "value_template": "{{ value_json.val }}", } }, ) await hass.async_block_till_done() async_fire_mqtt_message(hass, topic, '{"val":10}') await hass.async_block_till_done() state = hass.states.get("number.test_number") assert state.state == "10" async_fire_mqtt_message(hass, topic, '{"val":20.5}') await hass.async_block_till_done() state = hass.states.get("number.test_number") assert state.state == "20.5" async_fire_mqtt_message(hass, topic, '{"val":null}') await hass.async_block_till_done() state = hass.states.get("number.test_number") assert state.state == "unknown"
async def test_not_fires_on_mqtt_message_after_remove_from_registry( hass, hass_ws_client, device_reg, mqtt_mock, tag_mock, ): """Test tag scanning after removal.""" assert await async_setup_component(hass, "config", {}) ws_client = await hass_ws_client(hass) config = copy.deepcopy(DEFAULT_CONFIG_DEVICE) async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", json.dumps(config)) await hass.async_block_till_done() device_entry = device_reg.async_get_device({("mqtt", "0AFFD2")}) # Fake tag scan. async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) await hass.async_block_till_done() tag_mock.assert_called_once_with(ANY, DEFAULT_TAG_ID, device_entry.id) # Remove MQTT from the device mqtt_config_entry = hass.config_entries.async_entries(MQTT_DOMAIN)[0] await ws_client.send_json({ "id": 6, "type": "config/device_registry/remove_config_entry", "config_entry_id": mqtt_config_entry.entry_id, "device_id": device_entry.id, }) response = await ws_client.receive_json() assert response["success"] tag_mock.reset_mock() async_fire_mqtt_message(hass, "foobar/tag_scanned", DEFAULT_TAG_SCAN) await hass.async_block_till_done() tag_mock.assert_not_called()
async def test_invalid_sensor_value_via_mqtt_message( hass, mqtt_mock_entry_with_yaml_config, caplog): """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, binary_sensor.DOMAIN, { binary_sensor.DOMAIN: { "platform": "mqtt", "name": "test", "state_topic": "test-topic", "payload_on": "ON", "payload_off": "OFF", } }, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNKNOWN async_fire_mqtt_message(hass, "test-topic", "0N") state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNKNOWN assert "No matching payload found for entity" in caplog.text caplog.clear() assert "No matching payload found for entity" not in caplog.text async_fire_mqtt_message(hass, "test-topic", "ON") state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON async_fire_mqtt_message(hass, "test-topic", "0FF") state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON assert "No matching payload found for entity" in caplog.text
async def help_test_discovery_device_remove(hass, mqtt_mock, domain, unique_id, config, sensor_config=None): """Test domain entity is removed when device is removed.""" device_reg = dr.async_get(hass) entity_reg = er.async_get(hass) config = copy.deepcopy(config) data = json.dumps(config) async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", data) await hass.async_block_till_done() if sensor_config: async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/sensors", json.dumps(sensor_config), ) await hass.async_block_till_done() device = device_reg.async_get_device( set(), {(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])}) assert device is not None assert entity_reg.async_get_entity_id(domain, "tasmota", unique_id) async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", "") await hass.async_block_till_done() device = device_reg.async_get_device( set(), {(dr.CONNECTION_NETWORK_MAC, config[CONF_MAC])}) assert device is None assert not entity_reg.async_get_entity_id(domain, "tasmota", unique_id)
async def test_setting_device_tracker_value_via_mqtt_message( hass, mqtt_mock_entry_no_yaml_config, caplog): """Test the setting of the value via MQTT.""" await mqtt_mock_entry_no_yaml_config() async_fire_mqtt_message( hass, "homeassistant/device_tracker/bla/config", '{ "name": "test", "state_topic": "test-topic" }', ) await hass.async_block_till_done() state = hass.states.get("device_tracker.test") assert state.state == STATE_UNKNOWN async_fire_mqtt_message(hass, "test-topic", "home") state = hass.states.get("device_tracker.test") assert state.state == STATE_HOME async_fire_mqtt_message(hass, "test-topic", "not_home") state = hass.states.get("device_tracker.test") assert state.state == STATE_NOT_HOME
async def test_attributes_ct(hass, mqtt_mock, setup_tasmota): """Test state update via MQTT.""" config = copy.deepcopy(DEFAULT_CONFIG) config["rl"][0] = 2 config["lt_st"] = 2 # 2 channel light (CW) mac = config["mac"] async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config), ) await hass.async_block_till_done() async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/LWT", "Online") async_fire_mqtt_message(hass, "tasmota_49A3BC/tele/STATE", '{"POWER":"ON"}') state = hass.states.get("light.test") assert state.attributes.get("effect_list") is None assert state.attributes.get("min_mireds") == 153 assert state.attributes.get("max_mireds") == 500 assert (state.attributes.get("supported_features") == SUPPORT_BRIGHTNESS | SUPPORT_COLOR_TEMP | SUPPORT_TRANSITION)
async def help_test_availability( hass, mqtt_mock, domain, config, ): """Test availability. This is a test helper for the TasmotaAvailability mixin. """ async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", json.dumps(config), ) await hass.async_block_till_done() state = hass.states.get(f"{domain}.test") assert state.state == STATE_UNAVAILABLE async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_online(config), ) state = hass.states.get(f"{domain}.test") assert state.state != STATE_UNAVAILABLE async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_offline(config), ) state = hass.states.get(f"{domain}.test") assert state.state == STATE_UNAVAILABLE
async def test_brightness_from_rgb_controlling_scale(opp, mqtt_mock): """Test the brightness controlling scale.""" with assert_setup_component(1, light.DOMAIN): assert await async_setup_component( opp, light.DOMAIN, { light.DOMAIN: { "platform": "mqtt", "name": "test", "state_topic": "test_scale_rgb/status", "command_topic": "test_scale_rgb/set", "rgb_state_topic": "test_scale_rgb/rgb/status", "rgb_command_topic": "test_scale_rgb/rgb/set", "qos": 0, "payload_on": "on", "payload_off": "off", } }, ) state = opp.states.get("light.test") assert state.state == STATE_OFF assert state.attributes.get("brightness") is None assert not state.attributes.get(ATTR_ASSUMED_STATE) async_fire_mqtt_message(opp, "test_scale_rgb/status", "on") async_fire_mqtt_message(opp, "test_scale_rgb/rgb/status", "255,0,0") state = opp.states.get("light.test") assert state.attributes.get("brightness") == 255 async_fire_mqtt_message(opp, "test_scale_rgb/rgb/status", "127,0,0") state = opp.states.get("light.test") assert state.attributes.get("brightness") == 127
async def test_entity_duplicate_removal(hass, mqtt_mock, caplog, setup_tasmota): """Test removing entity twice.""" config = copy.deepcopy(DEFAULT_CONFIG) config["rl"][0] = 1 mac = config["mac"] async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config), ) await hass.async_block_till_done() config["rl"][0] = 0 async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config)) await hass.async_block_till_done() assert f"Removing entity: switch ('{mac}', 'switch', 'relay', 0)" in caplog.text caplog.clear() async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{mac}/config", json.dumps(config)) await hass.async_block_till_done() assert "Removing entity: switch" not in caplog.text
async def test_set_aux_pessimistic(hass, mqtt_mock): """Test setting of the aux heating in pessimistic mode.""" config = copy.deepcopy(DEFAULT_CONFIG) config['climate']['aux_state_topic'] = 'aux-state' assert await async_setup_component(hass, CLIMATE_DOMAIN, config) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('aux_heat') == 'off' await common.async_set_aux_heat(hass, True, ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('aux_heat') == 'off' async_fire_mqtt_message(hass, 'aux-state', 'ON') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('aux_heat') == 'on' async_fire_mqtt_message(hass, 'aux-state', 'OFF') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('aux_heat') == 'off' async_fire_mqtt_message(hass, 'aux-state', 'nonsense') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('aux_heat') == 'off'
async def test_set_away_mode_pessimistic(hass, mqtt_mock): """Test setting of the away mode.""" config = copy.deepcopy(DEFAULT_CONFIG) config['climate']['away_mode_state_topic'] = 'away-state' assert await async_setup_component(hass, CLIMATE_DOMAIN, config) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') is None await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') is None async_fire_mqtt_message(hass, 'away-state', 'ON') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') == 'away' async_fire_mqtt_message(hass, 'away-state', 'OFF') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') is None async_fire_mqtt_message(hass, 'away-state', 'nonsense') state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get('preset_mode') is None
async def test_setting_sensor_value_via_mqtt_message_and_template2( hass, mqtt_mock_entry_with_yaml_config, caplog ): """Test the setting of the value via MQTT.""" assert await async_setup_component( hass, binary_sensor.DOMAIN, { binary_sensor.DOMAIN: { "platform": "mqtt", "name": "test", "state_topic": "test-topic", "payload_on": "ON", "payload_off": "OFF", "value_template": "{{value | upper}}", } }, ) await hass.async_block_till_done() await mqtt_mock_entry_with_yaml_config() state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNKNOWN async_fire_mqtt_message(hass, "test-topic", "on") state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON async_fire_mqtt_message(hass, "test-topic", "off") state = hass.states.get("binary_sensor.test") assert state.state == STATE_OFF async_fire_mqtt_message(hass, "test-topic", "illegal") state = hass.states.get("binary_sensor.test") assert state.state == STATE_OFF assert "template output: 'ILLEGAL'" in caplog.text
async def test_controlling_state_via_topic_and_json_message(hass, mqtt_mock): """Test the controlling state via topic and JSON message.""" assert await async_setup_component( hass, switch.DOMAIN, { switch.DOMAIN: { "platform": "mqtt", "name": "test", "state_topic": "state-topic", "command_topic": "command-topic", "payload_on": "beer on", "payload_off": "beer off", "value_template": "{{ value_json.val }}", } }, ) await hass.async_block_till_done() state = hass.states.get("switch.test") assert state.state == STATE_UNKNOWN async_fire_mqtt_message(hass, "state-topic", '{"val":"beer on"}') state = hass.states.get("switch.test") assert state.state == STATE_ON async_fire_mqtt_message(hass, "state-topic", '{"val":"beer off"}') state = hass.states.get("switch.test") assert state.state == STATE_OFF async_fire_mqtt_message(hass, "state-topic", '{"val": null}') state = hass.states.get("switch.test") assert state.state == STATE_UNKNOWN
async def test_brightness_from_rgb_controlling_scale(hass, mqtt_mock): """Test the brightness controlling scale.""" with assert_setup_component(1, light.DOMAIN): assert await async_setup_component( hass, light.DOMAIN, { light.DOMAIN: { 'platform': 'mqtt', 'name': 'test', 'state_topic': 'test_scale_rgb/status', 'command_topic': 'test_scale_rgb/set', 'rgb_state_topic': 'test_scale_rgb/rgb/status', 'rgb_command_topic': 'test_scale_rgb/rgb/set', 'qos': 0, 'payload_on': 'on', 'payload_off': 'off' } }) state = hass.states.get('light.test') assert STATE_OFF == state.state assert state.attributes.get('brightness') is None assert not state.attributes.get(ATTR_ASSUMED_STATE) async_fire_mqtt_message(hass, 'test_scale_rgb/status', 'on') async_fire_mqtt_message(hass, 'test_scale_rgb/rgb/status', '255,0,0') await hass.async_block_till_done() state = hass.states.get('light.test') assert 255 == state.attributes.get('brightness') async_fire_mqtt_message(hass, 'test_scale_rgb/rgb/status', '127,0,0') await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get('light.test') assert 127 == state.attributes.get('brightness')
async def test_setting_device_tracker_value_via_mqtt_message_and_template2( hass, mqtt_mock, caplog): """Test the setting of the value via MQTT.""" async_fire_mqtt_message( hass, "homeassistant/device_tracker/bla/config", "{" '"name": "test", ' '"state_topic": "test-topic", ' '"value_template": "{{ value | lower }}" ' "}", ) await hass.async_block_till_done() state = hass.states.get("device_tracker.test") assert state.state == STATE_UNKNOWN async_fire_mqtt_message(hass, "test-topic", "HOME") state = hass.states.get("device_Tracker.test") assert state.state == STATE_HOME async_fire_mqtt_message(hass, "test-topic", "NOT_HOME") state = hass.states.get("device_tracker.test") assert state.state == STATE_NOT_HOME
async def test_set_away_mode_pessimistic(hass, mqtt_mock): """Test setting of the away mode.""" config = copy.deepcopy(DEFAULT_CONFIG) config["climate"]["away_mode_state_topic"] = "away-state" assert await async_setup_component(hass, CLIMATE_DOMAIN, config) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("preset_mode") is None await common.async_set_preset_mode(hass, "away", ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("preset_mode") is None async_fire_mqtt_message(hass, "away-state", "ON") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("preset_mode") == "away" async_fire_mqtt_message(hass, "away-state", "OFF") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("preset_mode") is None async_fire_mqtt_message(hass, "away-state", "nonsense") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("preset_mode") is None
async def test_rediscover(hass, mqtt_mock, caplog): """Test rediscover of removed component.""" async_fire_mqtt_message( hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer", "state_topic": "test-topic" }', ) await hass.async_block_till_done() state = hass.states.get("binary_sensor.beer") assert state is not None async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla/config", "") await hass.async_block_till_done() state = hass.states.get("binary_sensor.beer") assert state is None async_fire_mqtt_message( hass, "homeassistant/binary_sensor/bla/config", '{ "name": "Beer", "state_topic": "test-topic" }', ) await hass.async_block_till_done() state = hass.states.get("binary_sensor.beer") assert state is not None
async def test_set_aux_pessimistic(hass, mqtt_mock): """Test setting of the aux heating in pessimistic mode.""" config = copy.deepcopy(DEFAULT_CONFIG) config["climate"]["aux_state_topic"] = "aux-state" assert await async_setup_component(hass, CLIMATE_DOMAIN, config) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("aux_heat") == "off" await common.async_set_aux_heat(hass, True, ENTITY_CLIMATE) state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("aux_heat") == "off" async_fire_mqtt_message(hass, "aux-state", "ON") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("aux_heat") == "on" async_fire_mqtt_message(hass, "aux-state", "OFF") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("aux_heat") == "off" async_fire_mqtt_message(hass, "aux-state", "nonsense") state = hass.states.get(ENTITY_CLIMATE) assert state.attributes.get("aux_heat") == "off"
async def help_test_availability_when_connection_lost( hass, mqtt_client_mock, mqtt_mock, domain, config, sensor_config=None, entity_id="test", ): """Test availability after MQTT disconnection. This is a test helper for the TasmotaAvailability mixin. """ async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", json.dumps(config), ) await hass.async_block_till_done() if sensor_config: async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/sensors", json.dumps(sensor_config), ) await hass.async_block_till_done() # Device online async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_online(config), ) state = hass.states.get(f"{domain}.{entity_id}") assert state.state != STATE_UNAVAILABLE # Disconnected from MQTT server -> state changed to unavailable mqtt_mock.connected = False await hass.async_add_executor_job(mqtt_client_mock.on_disconnect, None, None, 0) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE # Reconnected to MQTT server -> state still unavailable mqtt_mock.connected = True await hass.async_add_executor_job(mqtt_client_mock.on_connect, None, None, None, 0) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE # Receive LWT again async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_online(config), ) state = hass.states.get(f"{domain}.{entity_id}") assert state.state != STATE_UNAVAILABLE
async def help_test_availability_poll_state( hass, mqtt_client_mock, mqtt_mock, domain, config, poll_topic, poll_payload, sensor_config=None, ): """Test polling of state when device is available. This is a test helper for the TasmotaAvailability mixin. """ async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", json.dumps(config), ) await hass.async_block_till_done() if sensor_config: async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/sensors", json.dumps(sensor_config), ) await hass.async_block_till_done() mqtt_mock.async_publish.reset_mock() # Device online, verify poll for state async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_online(config), ) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() mqtt_mock.async_publish.assert_called_once_with(poll_topic, poll_payload, 0, False) mqtt_mock.async_publish.reset_mock() # Disconnected from MQTT server mqtt_mock.connected = False await hass.async_add_executor_job(mqtt_client_mock.on_disconnect, None, None, 0) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() assert not mqtt_mock.async_publish.called # Reconnected to MQTT server mqtt_mock.connected = True await hass.async_add_executor_job(mqtt_client_mock.on_connect, None, None, None, 0) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() assert not mqtt_mock.async_publish.called # Device online, verify poll for state async_fire_mqtt_message( hass, get_topic_tele_will(config), config_get_state_online(config), ) await hass.async_block_till_done() await hass.async_block_till_done() await hass.async_block_till_done() mqtt_mock.async_publish.assert_called_once_with(poll_topic, poll_payload, 0, False)
async def help_test_entity_id_update_discovery_update( hass, mqtt_mock, domain, config, sensor_config=None, entity_id="test" ): """Test MQTT discovery update after entity_id is updated.""" entity_reg = await hass.helpers.entity_registry.async_get_registry() config = copy.deepcopy(config) data = json.dumps(config) topic = get_topic_tele_will(config) async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", data) await hass.async_block_till_done() if sensor_config: async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/sensors", json.dumps(sensor_config), ) await hass.async_block_till_done() async_fire_mqtt_message(hass, topic, config_get_state_online(config)) state = hass.states.get(f"{domain}.{entity_id}") assert state.state != STATE_UNAVAILABLE async_fire_mqtt_message(hass, topic, config_get_state_offline(config)) state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE entity_reg.async_update_entity( f"{domain}.{entity_id}", new_entity_id=f"{domain}.milk" ) await hass.async_block_till_done() assert hass.states.get(f"{domain}.milk") assert config[CONF_PREFIX][PREFIX_TELE] != "tele2" config[CONF_PREFIX][PREFIX_TELE] = "tele2" data = json.dumps(config) async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/config", data) await hass.async_block_till_done() assert len(hass.states.async_entity_ids(domain)) == 1 topic = get_topic_tele_will(config) async_fire_mqtt_message(hass, topic, config_get_state_online(config)) state = hass.states.get(f"{domain}.milk") assert state.state != STATE_UNAVAILABLE
async def test_invalid_values(hass, mqtt_mock): """Test that invalid color/brightness/white/etc. values are ignored.""" assert await async_setup_component( hass, light.DOMAIN, { light.DOMAIN: { "platform": "mqtt", "schema": "json", "name": "test", "state_topic": "test_light_rgb", "command_topic": "test_light_rgb/set", "brightness": True, "color_temp": True, "rgb": True, "white_value": True, "qos": "0", } }, ) await hass.async_block_till_done() state = hass.states.get("light.test") assert state.state == STATE_OFF assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 187 assert state.attributes.get("rgb_color") is None assert state.attributes.get("brightness") is None assert state.attributes.get("white_value") is None assert state.attributes.get("color_temp") is None assert not state.attributes.get(ATTR_ASSUMED_STATE) # Turn on the light async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON",' '"color":{"r":255,"g":255,"b":255},' '"brightness": 255,' '"white_value": 255,' '"color_temp": 100,' '"effect": "rainbow"}', ) state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("rgb_color") == (255, 255, 255) assert state.attributes.get("brightness") == 255 assert state.attributes.get("white_value") == 255 assert state.attributes.get("color_temp") == 100 # Bad HS color values async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON",' '"color":{"h":"bad","s":"val"}}', ) # Color should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("rgb_color") == (255, 255, 255) # Bad RGB color values async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON",' '"color":{"r":"bad","g":"val","b":"test"}}', ) # Color should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("rgb_color") == (255, 255, 255) # Bad XY color values async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON",' '"color":{"x":"bad","y":"val"}}', ) # Color should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("rgb_color") == (255, 255, 255) # Bad brightness values async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON",' '"brightness": "badValue"}') # Brightness should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("brightness") == 255 # Bad white value async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON",' '"white_value": "badValue"}') # White value should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("white_value") == 255 # Bad color temperature async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON",' '"color_temp": "badValue"}') # Color temperature should not have changed state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("color_temp") == 100
async def help_test_availability_discovery_update( hass, mqtt_mock, domain, config, sensor_config=None, entity_id="test", ): """Test update of discovered TasmotaAvailability. This is a test helper for the TasmotaAvailability mixin. """ # customize availability topic config1 = copy.deepcopy(config) config1[CONF_PREFIX][PREFIX_TELE] = "tele1" config1[CONF_OFFLINE] = "offline1" config1[CONF_ONLINE] = "online1" config2 = copy.deepcopy(config) config2[CONF_PREFIX][PREFIX_TELE] = "tele2" config2[CONF_OFFLINE] = "offline2" config2[CONF_ONLINE] = "online2" data1 = json.dumps(config1) data2 = json.dumps(config2) availability_topic1 = get_topic_tele_will(config1) availability_topic2 = get_topic_tele_will(config2) assert availability_topic1 != availability_topic2 offline1 = config_get_state_offline(config1) offline2 = config_get_state_offline(config2) assert offline1 != offline2 online1 = config_get_state_online(config1) online2 = config_get_state_online(config2) assert online1 != online2 async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config1[CONF_MAC]}/config", data1) await hass.async_block_till_done() if sensor_config: async_fire_mqtt_message( hass, f"{DEFAULT_PREFIX}/{config[CONF_MAC]}/sensors", json.dumps(sensor_config), ) await hass.async_block_till_done() state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE async_fire_mqtt_message(hass, availability_topic1, online1) state = hass.states.get(f"{domain}.{entity_id}") assert state.state != STATE_UNAVAILABLE async_fire_mqtt_message(hass, availability_topic1, offline1) state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE # Change availability settings async_fire_mqtt_message(hass, f"{DEFAULT_PREFIX}/{config2[CONF_MAC]}/config", data2) await hass.async_block_till_done() # Verify we are no longer subscribing to the old topic or payload async_fire_mqtt_message(hass, availability_topic1, online1) async_fire_mqtt_message(hass, availability_topic1, online2) async_fire_mqtt_message(hass, availability_topic2, online1) state = hass.states.get(f"{domain}.{entity_id}") assert state.state == STATE_UNAVAILABLE # Verify we are subscribing to the new topic async_fire_mqtt_message(hass, availability_topic2, online2) state = hass.states.get(f"{domain}.{entity_id}") assert state.state != STATE_UNAVAILABLE
async def test_controlling_state_via_topic(hass, mqtt_mock): """Test the controlling of the state via topic.""" assert await async_setup_component( hass, light.DOMAIN, { light.DOMAIN: { "platform": "mqtt", "schema": "json", "name": "test", "state_topic": "test_light_rgb", "command_topic": "test_light_rgb/set", "brightness": True, "color_temp": True, "effect": True, "rgb": True, "white_value": True, "xy": True, "hs": True, "qos": "0", } }, ) await hass.async_block_till_done() state = hass.states.get("light.test") assert state.state == STATE_OFF assert state.attributes.get(ATTR_SUPPORTED_FEATURES) == 191 assert state.attributes.get("rgb_color") is None assert state.attributes.get("brightness") is None assert state.attributes.get("color_temp") is None assert state.attributes.get("effect") is None assert state.attributes.get("white_value") is None assert state.attributes.get("xy_color") is None assert state.attributes.get("hs_color") is None assert not state.attributes.get(ATTR_ASSUMED_STATE) # Turn on the light, full white async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON",' '"color":{"r":255,"g":255,"b":255},' '"brightness":255,' '"color_temp":155,' '"effect":"colorloop",' '"white_value":150}', ) state = hass.states.get("light.test") assert state.state == STATE_ON assert state.attributes.get("rgb_color") == (255, 255, 255) assert state.attributes.get("brightness") == 255 assert state.attributes.get("color_temp") == 155 assert state.attributes.get("effect") == "colorloop" assert state.attributes.get("white_value") == 150 assert state.attributes.get("xy_color") == (0.323, 0.329) assert state.attributes.get("hs_color") == (0.0, 0.0) # Turn the light off async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"OFF"}') state = hass.states.get("light.test") assert state.state == STATE_OFF async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "brightness":100}') light_state = hass.states.get("light.test") assert light_state.attributes["brightness"] == 100 async_fire_mqtt_message( hass, "test_light_rgb", '{"state":"ON", ' '"color":{"r":125,"g":125,"b":125}}') light_state = hass.states.get("light.test") assert light_state.attributes.get("rgb_color") == (255, 255, 255) async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color":{"x":0.135,"y":0.135}}') light_state = hass.states.get("light.test") assert light_state.attributes.get("xy_color") == (0.141, 0.14) async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color":{"h":180,"s":50}}') light_state = hass.states.get("light.test") assert light_state.attributes.get("hs_color") == (180.0, 50.0) async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "color_temp":155}') light_state = hass.states.get("light.test") assert light_state.attributes.get("color_temp") == 155 async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "effect":"colorloop"}') light_state = hass.states.get("light.test") assert light_state.attributes.get("effect") == "colorloop" async_fire_mqtt_message(hass, "test_light_rgb", '{"state":"ON", "white_value":155}') light_state = hass.states.get("light.test") assert light_state.attributes.get("white_value") == 155
async def send_message(hass, topic, message): """Test the sending of a message.""" async_fire_mqtt_message(hass, topic, json.dumps(message)) await hass.async_block_till_done() await hass.async_block_till_done()
def side_effect(*args): async_fire_mqtt_message(self.hass, 'test/state', 'online') return 0, 0
async def test_expiration_on_discovery_and_discovery_update_of_binary_sensor( hass, mqtt_mock, caplog ): """Test that binary_sensor with expire_after set behaves correctly on discovery and discovery update.""" entry = MockConfigEntry(domain=mqtt.DOMAIN) await async_start(hass, "homeassistant", entry) config = { "name": "Test", "state_topic": "test-topic", "expire_after": 4, "force_update": True, } config_msg = json.dumps(config) # Set time and publish config message to create binary_sensor via discovery with 4 s expiry now = datetime(2017, 1, 1, 1, tzinfo=dt_util.UTC) with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_time_changed(hass, now) async_fire_mqtt_message( hass, "homeassistant/binary_sensor/bla/config", config_msg ) await hass.async_block_till_done() # Test that binary_sensor is not available state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNAVAILABLE # Publish state message with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_mqtt_message(hass, "test-topic", "ON") await hass.async_block_till_done() # Test that binary_sensor has correct state state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON # Advance +3 seconds now = now + timedelta(seconds=3) with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_time_changed(hass, now) await hass.async_block_till_done() # binary_sensor is not yet expired state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON # Resend config message to update discovery with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_time_changed(hass, now) async_fire_mqtt_message( hass, "homeassistant/binary_sensor/bla/config", config_msg ) await hass.async_block_till_done() # Test that binary_sensor has not expired state = hass.states.get("binary_sensor.test") assert state.state == STATE_ON # Add +2 seconds now = now + timedelta(seconds=2) with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_time_changed(hass, now) await hass.async_block_till_done() # Test that binary_sensor has expired state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNAVAILABLE # Resend config message to update discovery with patch(("homeassistant.helpers.event.dt_util.utcnow"), return_value=now): async_fire_mqtt_message( hass, "homeassistant/binary_sensor/bla/config", config_msg ) await hass.async_block_till_done() # Test that binary_sensor is still expired state = hass.states.get("binary_sensor.test") assert state.state == STATE_UNAVAILABLE
async def test_cleanup_device_with_entity2(hass, device_reg, entity_reg, mqtt_mock): """Test removal from device registry for device with tag, entity and trigger. Trigger and entity removed first, then tag. """ config1 = { "topic": "test-topic", "device": { "identifiers": ["helloworld"] }, } config2 = { "automation_type": "trigger", "topic": "test-topic", "type": "foo", "subtype": "bar", "device": { "identifiers": ["helloworld"] }, } config3 = { "name": "test_binary_sensor", "state_topic": "test-topic", "device": { "identifiers": ["helloworld"] }, "unique_id": "veryunique", } data1 = json.dumps(config1) data2 = json.dumps(config2) data3 = json.dumps(config3) async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", data1) await hass.async_block_till_done() async_fire_mqtt_message(hass, "homeassistant/device_automation/bla2/config", data2) await hass.async_block_till_done() async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla3/config", data3) await hass.async_block_till_done() # Verify device registry entry is created device_entry = device_reg.async_get_device({("mqtt", "helloworld")}) assert device_entry is not None triggers = await async_get_device_automations(hass, "trigger", device_entry.id) assert len(triggers) == 3 # 2 binary_sensor triggers + device trigger async_fire_mqtt_message(hass, "homeassistant/device_automation/bla2/config", "") await hass.async_block_till_done() async_fire_mqtt_message(hass, "homeassistant/binary_sensor/bla3/config", "") await hass.async_block_till_done() # Verify device registry entry is not cleared device_entry = device_reg.async_get_device({("mqtt", "helloworld")}) assert device_entry is not None async_fire_mqtt_message(hass, "homeassistant/tag/bla1/config", "") await hass.async_block_till_done() # Verify device registry entry is cleared device_entry = device_reg.async_get_device({("mqtt", "helloworld")}) assert device_entry is None