コード例 #1
0
async def test_openclose_cover_unknown_state(hass):
    """Test OpenClose trait support for cover domain with unknown state."""
    assert helpers.get_google_type(cover.DOMAIN, None) is not None
    assert trait.OpenCloseTrait.supported(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION, None)

    # No state
    trt = trait.OpenCloseTrait(hass, State('cover.bla', STATE_UNKNOWN, {
    }), BASIC_CONFIG)

    assert trt.sync_attributes() == {}

    with pytest.raises(helpers.SmartHomeError):
        trt.query_attributes()

    calls = async_mock_service(
        hass, cover.DOMAIN, cover.SERVICE_OPEN_COVER)
    await trt.execute(
        trait.COMMAND_OPENCLOSE, BASIC_DATA,
        {'openPercent': 100}, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'cover.bla',
    }

    assert trt.query_attributes() == {'openPercent': 100}
コード例 #2
0
async def test_openclose_binary_sensor(hass, device_class):
    """Test OpenClose trait support for binary_sensor domain."""
    assert helpers.get_google_type(binary_sensor.DOMAIN,
                                   device_class) is not None
    assert trait.OpenCloseTrait.supported(binary_sensor.DOMAIN, 0,
                                          device_class)

    trt = trait.OpenCloseTrait(
        hass,
        State('binary_sensor.test', STATE_ON, {
            ATTR_DEVICE_CLASS: device_class,
        }), BASIC_CONFIG)

    assert trt.sync_attributes() == {
        'queryOnlyOpenClose': True,
    }

    assert trt.query_attributes() == {'openPercent': 100}

    trt = trait.OpenCloseTrait(
        hass,
        State('binary_sensor.test', STATE_OFF, {
            ATTR_DEVICE_CLASS: device_class,
        }), BASIC_CONFIG)

    assert trt.sync_attributes() == {
        'queryOnlyOpenClose': True,
    }

    assert trt.query_attributes() == {'openPercent': 0}
コード例 #3
0
async def test_openclose_cover_assumed_state(hass):
    """Test OpenClose trait support for cover domain."""
    assert helpers.get_google_type(cover.DOMAIN, None) is not None
    assert trait.OpenCloseTrait.supported(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION, None)

    trt = trait.OpenCloseTrait(
        hass,
        State(
            'cover.bla', cover.STATE_OPEN, {
                ATTR_ASSUMED_STATE: True,
                ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION,
            }), BASIC_CONFIG)

    assert trt.sync_attributes() == {}

    with pytest.raises(helpers.SmartHomeError):
        trt.query_attributes()

    calls = async_mock_service(hass, cover.DOMAIN,
                               cover.SERVICE_SET_COVER_POSITION)
    await trt.execute(trait.COMMAND_OPENCLOSE, BASIC_DATA, {'openPercent': 40},
                      {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'cover.bla',
        cover.ATTR_POSITION: 40
    }

    assert trt.query_attributes() == {'openPercent': 40}
コード例 #4
0
async def test_onoff_switch(hass):
    """Test OnOff trait support for switch domain."""
    assert helpers.get_google_type(switch.DOMAIN, None) is not None
    assert trait.OnOffTrait.supported(switch.DOMAIN, 0, None)

    trt_on = trait.OnOffTrait(hass, State("switch.bla", STATE_ON),
                              BASIC_CONFIG)

    assert trt_on.sync_attributes() == {}

    assert trt_on.query_attributes() == {"on": True}

    trt_off = trait.OnOffTrait(hass, State("switch.bla", STATE_OFF),
                               BASIC_CONFIG)

    assert trt_off.query_attributes() == {"on": False}

    on_calls = async_mock_service(hass, switch.DOMAIN, SERVICE_TURN_ON)
    await trt_on.execute(trait.COMMAND_ONOFF, BASIC_DATA, {"on": True}, {})
    assert len(on_calls) == 1
    assert on_calls[0].data == {ATTR_ENTITY_ID: "switch.bla"}

    off_calls = async_mock_service(hass, switch.DOMAIN, SERVICE_TURN_OFF)
    await trt_on.execute(trait.COMMAND_ONOFF, BASIC_DATA, {"on": False}, {})
    assert len(off_calls) == 1
    assert off_calls[0].data == {ATTR_ENTITY_ID: "switch.bla"}
コード例 #5
0
async def test_volume_media_player(hass):
    """Test volume trait support for media player domain."""
    assert helpers.get_google_type(media_player.DOMAIN, None) is not None
    assert trait.VolumeTrait.supported(
        media_player.DOMAIN,
        media_player.SUPPORT_VOLUME_SET | media_player.SUPPORT_VOLUME_MUTE,
        None)

    trt = trait.VolumeTrait(
        hass,
        State(
            'media_player.bla', media_player.STATE_PLAYING, {
                media_player.ATTR_MEDIA_VOLUME_LEVEL: .3,
                media_player.ATTR_MEDIA_VOLUME_MUTED: False,
            }), BASIC_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {'currentVolume': 30, 'isMuted': False}

    calls = async_mock_service(hass, media_player.DOMAIN,
                               media_player.SERVICE_VOLUME_SET)
    await trt.execute(trait.COMMAND_SET_VOLUME, BASIC_DATA,
                      {'volumeLevel': 60}, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'media_player.bla',
        media_player.ATTR_MEDIA_VOLUME_LEVEL: .6
    }
コード例 #6
0
async def test_onoff_media_player(hass):
    """Test OnOff trait support for media_player domain."""
    assert helpers.get_google_type(media_player.DOMAIN, None) is not None
    assert trait.OnOffTrait.supported(media_player.DOMAIN, 0, None)

    trt_on = trait.OnOffTrait(hass, State('media_player.bla', STATE_ON),
                              BASIC_CONFIG)

    assert trt_on.sync_attributes() == {}

    assert trt_on.query_attributes() == {'on': True}

    trt_off = trait.OnOffTrait(hass, State('media_player.bla', STATE_OFF),
                               BASIC_CONFIG)

    assert trt_off.query_attributes() == {'on': False}

    on_calls = async_mock_service(hass, media_player.DOMAIN, SERVICE_TURN_ON)
    await trt_on.execute(trait.COMMAND_ONOFF, BASIC_DATA, {'on': True}, {})
    assert len(on_calls) == 1
    assert on_calls[0].data == {
        ATTR_ENTITY_ID: 'media_player.bla',
    }

    off_calls = async_mock_service(hass, media_player.DOMAIN, SERVICE_TURN_OFF)

    await trt_on.execute(trait.COMMAND_ONOFF, BASIC_DATA, {'on': False}, {})
    assert len(off_calls) == 1
    assert off_calls[0].data == {
        ATTR_ENTITY_ID: 'media_player.bla',
    }
コード例 #7
0
async def test_openclose_cover_secure(hass, device_class):
    """Test OpenClose trait support for cover domain."""
    assert helpers.get_google_type(cover.DOMAIN, device_class) is not None
    assert trait.OpenCloseTrait.supported(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION,
                                          device_class)
    assert trait.OpenCloseTrait.might_2fa(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION,
                                          device_class)

    trt = trait.OpenCloseTrait(
        hass,
        State(
            "cover.bla",
            cover.STATE_OPEN,
            {
                ATTR_DEVICE_CLASS: device_class,
                ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION,
                cover.ATTR_CURRENT_POSITION: 75,
            },
        ),
        PIN_CONFIG,
    )

    assert trt.sync_attributes() == {}
    assert trt.query_attributes() == {"openPercent": 75}

    calls = async_mock_service(hass, cover.DOMAIN,
                               cover.SERVICE_SET_COVER_POSITION)

    # No challenge data
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_OPENCLOSE, PIN_DATA,
                          {"openPercent": 50}, {})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_PIN_NEEDED

    # invalid pin
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_OPENCLOSE, PIN_DATA,
                          {"openPercent": 50}, {"pin": "9999"})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_FAILED_PIN_NEEDED

    await trt.execute(trait.COMMAND_OPENCLOSE, PIN_DATA, {"openPercent": 50},
                      {"pin": "1234"})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: "cover.bla",
        cover.ATTR_POSITION: 50
    }

    # no challenge on close
    calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_CLOSE_COVER)
    await trt.execute(trait.COMMAND_OPENCLOSE, PIN_DATA, {"openPercent": 0},
                      {})
    assert len(calls) == 1
    assert calls[0].data == {ATTR_ENTITY_ID: "cover.bla"}
コード例 #8
0
async def test_temperature_setting_sensor(hass):
    """Test TemperatureSetting trait support for temperature sensor."""
    assert (helpers.get_google_type(sensor.DOMAIN,
                                    sensor.DEVICE_CLASS_TEMPERATURE)
            is not None)
    assert not trait.TemperatureSettingTrait.supported(
        sensor.DOMAIN, 0, sensor.DEVICE_CLASS_HUMIDITY)
    assert trait.TemperatureSettingTrait.supported(
        sensor.DOMAIN, 0, sensor.DEVICE_CLASS_TEMPERATURE)

    hass.config.units.temperature_unit = TEMP_FAHRENHEIT

    trt = trait.TemperatureSettingTrait(
        hass,
        State("sensor.test", "70",
              {ATTR_DEVICE_CLASS: sensor.DEVICE_CLASS_TEMPERATURE}),
        BASIC_CONFIG,
    )

    assert trt.sync_attributes() == {
        "queryOnlyTemperatureSetting": True,
        "thermostatTemperatureUnit": "F",
    }

    assert trt.query_attributes() == {"thermostatTemperatureAmbient": 21.1}
    hass.config.units.temperature_unit = TEMP_CELSIUS
コード例 #9
0
async def test_lock_unlock_lock(hass):
    """Test LockUnlock trait locking support for lock domain."""
    assert helpers.get_google_type(lock.DOMAIN, None) is not None
    assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN,
                                           None)
    assert trait.LockUnlockTrait.might_2fa(lock.DOMAIN, lock.SUPPORT_OPEN,
                                           None)

    trt = trait.LockUnlockTrait(hass,
                                State('lock.front_door', lock.STATE_LOCKED),
                                PIN_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {
        'isLocked': True
    }

    assert trt.can_execute(trait.COMMAND_LOCKUNLOCK, {'lock': True})

    calls = async_mock_service(hass, lock.DOMAIN, lock.SERVICE_LOCK)

    await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {'lock': True}, {})

    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'lock.front_door'
    }
コード例 #10
0
async def test_openclose_cover(hass):
    """Test OpenClose trait support for cover domain."""
    assert helpers.get_google_type(cover.DOMAIN, None) is not None
    assert trait.OpenCloseTrait.supported(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION, None)

    trt = trait.OpenCloseTrait(
        hass,
        State(
            "cover.bla",
            cover.STATE_OPEN,
            {
                cover.ATTR_CURRENT_POSITION: 75,
                ATTR_SUPPORTED_FEATURES: cover.SUPPORT_SET_POSITION,
            },
        ),
        BASIC_CONFIG,
    )

    assert trt.sync_attributes() == {}
    assert trt.query_attributes() == {"openPercent": 75}

    calls = async_mock_service(hass, cover.DOMAIN,
                               cover.SERVICE_SET_COVER_POSITION)
    await trt.execute(trait.COMMAND_OPENCLOSE, BASIC_DATA, {"openPercent": 50},
                      {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: "cover.bla",
        cover.ATTR_POSITION: 50
    }
コード例 #11
0
async def test_color_setting_color_light(hass):
    """Test ColorSpectrum trait support for light domain."""
    assert helpers.get_google_type(light.DOMAIN, None) is not None
    assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None)
    assert trait.ColorSettingTrait.supported(light.DOMAIN,
                                             light.SUPPORT_COLOR, None)

    trt = trait.ColorSettingTrait(hass, State('light.bla', STATE_ON, {
        light.ATTR_HS_COLOR: (20, 94),
        light.ATTR_BRIGHTNESS: 200,
        ATTR_SUPPORTED_FEATURES: light.SUPPORT_COLOR,
    }), BASIC_CONFIG)

    assert trt.sync_attributes() == {
        'colorModel': 'hsv'
    }

    assert trt.query_attributes() == {
        'color': {
            'spectrumHsv': {
                'hue': 20,
                'saturation': 0.94,
                'value': 200 / 255,
            }
        }
    }

    assert trt.can_execute(trait.COMMAND_COLOR_ABSOLUTE, {
        'color': {
            'spectrumRGB': 16715792
        }
    })

    calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, BASIC_DATA, {
        'color': {
            'spectrumRGB': 1052927
        }
    }, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'light.bla',
        light.ATTR_HS_COLOR: (240, 93.725),
    }

    await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, BASIC_DATA, {
        'color': {
            'spectrumHSV': {
                'hue': 100,
                'saturation': .50,
                'value': .20,
            }
        }
    }, {})
    assert len(calls) == 2
    assert calls[1].data == {
        ATTR_ENTITY_ID: 'light.bla',
        light.ATTR_HS_COLOR: [100, 50],
        light.ATTR_BRIGHTNESS: .2 * 255,
    }
コード例 #12
0
async def test_camera_stream(hass):
    """Test camera stream trait support for camera domain."""
    hass.config.api = Mock(base_url='http://1.1.1.1:8123')
    assert helpers.get_google_type(camera.DOMAIN, None) is not None
    assert trait.CameraStreamTrait.supported(camera.DOMAIN,
                                             camera.SUPPORT_STREAM, None)

    trt = trait.CameraStreamTrait(hass,
                                  State('camera.bla', camera.STATE_IDLE, {}),
                                  BASIC_CONFIG)

    assert trt.sync_attributes() == {
        'cameraStreamSupportedProtocols': [
            "hls",
        ],
        'cameraStreamNeedAuthToken': False,
        'cameraStreamNeedDrmEncryption': False,
    }

    assert trt.query_attributes() == {}

    with patch('homeassistant.components.camera.async_request_stream',
               return_value=mock_coro('/api/streams/bla')):
        await trt.execute(trait.COMMAND_GET_CAMERA_STREAM, BASIC_DATA, {}, {})

    assert trt.query_attributes() == {
        'cameraStreamAccessUrl': 'http://1.1.1.1:8123/api/streams/bla'
    }
コード例 #13
0
async def test_lock_unlock_unlock(hass):
    """Test LockUnlock trait unlocking support for lock domain."""
    assert helpers.get_google_type(lock.DOMAIN, None) is not None
    assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN,
                                           None)

    trt = trait.LockUnlockTrait(hass,
                                State("lock.front_door", lock.STATE_LOCKED),
                                PIN_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {"isLocked": True}

    assert trt.can_execute(trait.COMMAND_LOCKUNLOCK, {"lock": False})

    calls = async_mock_service(hass, lock.DOMAIN, lock.SERVICE_UNLOCK)

    # No challenge data
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {"lock": False},
                          {})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_PIN_NEEDED

    # invalid pin
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {"lock": False},
                          {"pin": 9999})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_FAILED_PIN_NEEDED

    await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {"lock": False},
                      {"pin": "1234"})

    assert len(calls) == 1
    assert calls[0].data == {ATTR_ENTITY_ID: "lock.front_door"}

    # Test without pin
    trt = trait.LockUnlockTrait(hass,
                                State("lock.front_door", lock.STATE_LOCKED),
                                BASIC_CONFIG)

    with pytest.raises(error.SmartHomeError) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, BASIC_DATA,
                          {"lock": False}, {})
    assert len(calls) == 1
    assert err.value.code == const.ERR_CHALLENGE_NOT_SETUP

    # Test with 2FA override
    with patch(
            "homeassistant.components.google_assistant.helpers"
            ".AbstractConfig.should_2fa",
            return_value=False,
    ):
        await trt.execute(trait.COMMAND_LOCKUNLOCK, BASIC_DATA,
                          {"lock": False}, {})
    assert len(calls) == 2
コード例 #14
0
ファイル: test_trait.py プロジェクト: ywu093/home-assistant
async def test_brightness_media_player(hass):
    """Test brightness trait support for media player domain."""
    assert helpers.get_google_type(media_player.DOMAIN, None) is not None
    assert trait.BrightnessTrait.supported(media_player.DOMAIN,
                                           media_player.SUPPORT_VOLUME_SET,
                                           None)

    trt = trait.BrightnessTrait(hass, State(
        'media_player.bla', media_player.STATE_PLAYING, {
            media_player.ATTR_MEDIA_VOLUME_LEVEL: .3
        }), BASIC_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {
        'brightness': 30
    }

    calls = async_mock_service(
        hass, media_player.DOMAIN, media_player.SERVICE_VOLUME_SET)
    await trt.execute(
        trait.COMMAND_BRIGHTNESS_ABSOLUTE, BASIC_DATA,
        {'brightness': 60}, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'media_player.bla',
        media_player.ATTR_MEDIA_VOLUME_LEVEL: .6
    }
コード例 #15
0
async def test_color_setting_temperature_light(hass):
    """Test ColorTemperature trait support for light domain."""
    assert helpers.get_google_type(light.DOMAIN, None) is not None
    assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None)
    assert trait.ColorSettingTrait.supported(light.DOMAIN,
                                             light.SUPPORT_COLOR_TEMP, None)

    trt = trait.ColorSettingTrait(
        hass,
        State(
            "light.bla",
            STATE_ON,
            {
                light.ATTR_MIN_MIREDS: 200,
                light.ATTR_COLOR_TEMP: 300,
                light.ATTR_MAX_MIREDS: 500,
                ATTR_SUPPORTED_FEATURES: light.SUPPORT_COLOR_TEMP,
            },
        ),
        BASIC_CONFIG,
    )

    assert trt.sync_attributes() == {
        "colorTemperatureRange": {
            "temperatureMinK": 2000,
            "temperatureMaxK": 5000
        }
    }

    assert trt.query_attributes() == {"color": {"temperatureK": 3333}}

    assert trt.can_execute(trait.COMMAND_COLOR_ABSOLUTE,
                           {"color": {
                               "temperature": 400
                           }})
    calls = async_mock_service(hass, light.DOMAIN, SERVICE_TURN_ON)

    with pytest.raises(helpers.SmartHomeError) as err:
        await trt.execute(
            trait.COMMAND_COLOR_ABSOLUTE,
            BASIC_DATA,
            {"color": {
                "temperature": 5555
            }},
            {},
        )
    assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE

    await trt.execute(trait.COMMAND_COLOR_ABSOLUTE, BASIC_DATA,
                      {"color": {
                          "temperature": 2857
                      }}, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: "light.bla",
        light.ATTR_COLOR_TEMP: color.color_temperature_kelvin_to_mired(2857),
    }
コード例 #16
0
async def test_temperature_setting_climate_setpoint(hass):
    """Test TemperatureSetting trait support for climate domain - setpoint."""
    assert helpers.get_google_type(climate.DOMAIN, None) is not None
    assert not trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None)
    assert trait.TemperatureSettingTrait.supported(
        climate.DOMAIN, climate.SUPPORT_OPERATION_MODE, None)

    hass.config.units.temperature_unit = TEMP_CELSIUS

    trt = trait.TemperatureSettingTrait(
        hass,
        State(
            'climate.bla', climate.STATE_AUTO, {
                ATTR_SUPPORTED_FEATURES:
                (climate.SUPPORT_OPERATION_MODE | climate.SUPPORT_ON_OFF),
                climate.ATTR_OPERATION_MODE:
                climate.STATE_COOL,
                climate.ATTR_OPERATION_LIST: [
                    STATE_OFF,
                    climate.STATE_COOL,
                ],
                climate.ATTR_MIN_TEMP:
                10,
                climate.ATTR_MAX_TEMP:
                30,
                ATTR_TEMPERATURE:
                18,
                climate.ATTR_CURRENT_TEMPERATURE:
                20
            }), BASIC_CONFIG)
    assert trt.sync_attributes() == {
        'availableThermostatModes': 'off,on,cool',
        'thermostatTemperatureUnit': 'C',
    }
    assert trt.query_attributes() == {
        'thermostatMode': 'cool',
        'thermostatTemperatureAmbient': 20,
        'thermostatTemperatureSetpoint': 18,
    }
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {})
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {})

    calls = async_mock_service(hass, climate.DOMAIN,
                               climate.SERVICE_SET_TEMPERATURE)

    with pytest.raises(helpers.SmartHomeError):
        await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT,
                          BASIC_DATA, {'thermostatTemperatureSetpoint': -100},
                          {})

    await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT,
                      BASIC_DATA, {'thermostatTemperatureSetpoint': 19}, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'climate.bla',
        ATTR_TEMPERATURE: 19
    }
コード例 #17
0
async def test_temperature_setting_climate_setpoint(hass):
    """Test TemperatureSetting trait support for climate domain - setpoint."""
    assert helpers.get_google_type(climate.DOMAIN, None) is not None
    assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None)

    hass.config.units.temperature_unit = TEMP_CELSIUS

    trt = trait.TemperatureSettingTrait(
        hass,
        State(
            "climate.bla",
            climate.HVAC_MODE_COOL,
            {
                climate.ATTR_HVAC_MODES: [STATE_OFF, climate.HVAC_MODE_COOL],
                climate.ATTR_MIN_TEMP: 10,
                climate.ATTR_MAX_TEMP: 30,
                ATTR_TEMPERATURE: 18,
                climate.ATTR_CURRENT_TEMPERATURE: 20,
            },
        ),
        BASIC_CONFIG,
    )
    assert trt.sync_attributes() == {
        "availableThermostatModes": "off,cool,on",
        "thermostatTemperatureUnit": "C",
    }
    assert trt.query_attributes() == {
        "thermostatMode": "cool",
        "thermostatTemperatureAmbient": 20,
        "thermostatTemperatureSetpoint": 18,
    }
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT, {})
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {})

    calls = async_mock_service(hass, climate.DOMAIN,
                               climate.SERVICE_SET_TEMPERATURE)

    with pytest.raises(helpers.SmartHomeError):
        await trt.execute(
            trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT,
            BASIC_DATA,
            {"thermostatTemperatureSetpoint": -100},
            {},
        )

    await trt.execute(
        trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT,
        BASIC_DATA,
        {"thermostatTemperatureSetpoint": 19},
        {},
    )
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: "climate.bla",
        ATTR_TEMPERATURE: 19
    }
コード例 #18
0
async def test_startstop_vacuum(hass):
    """Test startStop trait support for vacuum domain."""
    assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
    assert trait.StartStopTrait.supported(vacuum.DOMAIN, 0, None)

    trt = trait.StartStopTrait(hass, State('vacuum.bla', vacuum.STATE_PAUSED, {
        ATTR_SUPPORTED_FEATURES: vacuum.SUPPORT_PAUSE,
    }), BASIC_CONFIG)

    assert trt.sync_attributes() == {'pausable': True}

    assert trt.query_attributes() == {
        'isRunning': False,
        'isPaused': True
    }

    start_calls = async_mock_service(hass, vacuum.DOMAIN,
                                     vacuum.SERVICE_START)
    await trt.execute(trait.COMMAND_STARTSTOP, BASIC_DATA, {'start': True}, {})
    assert len(start_calls) == 1
    assert start_calls[0].data == {
        ATTR_ENTITY_ID: 'vacuum.bla',
    }

    stop_calls = async_mock_service(hass, vacuum.DOMAIN,
                                    vacuum.SERVICE_STOP)
    await trt.execute(
        trait.COMMAND_STARTSTOP, BASIC_DATA, {'start': False}, {})
    assert len(stop_calls) == 1
    assert stop_calls[0].data == {
        ATTR_ENTITY_ID: 'vacuum.bla',
    }

    pause_calls = async_mock_service(hass, vacuum.DOMAIN,
                                     vacuum.SERVICE_PAUSE)
    await trt.execute(
        trait.COMMAND_PAUSEUNPAUSE, BASIC_DATA, {'pause': True}, {})
    assert len(pause_calls) == 1
    assert pause_calls[0].data == {
        ATTR_ENTITY_ID: 'vacuum.bla',
    }

    unpause_calls = async_mock_service(hass, vacuum.DOMAIN,
                                       vacuum.SERVICE_START)
    await trt.execute(
        trait.COMMAND_PAUSEUNPAUSE, BASIC_DATA, {'pause': False}, {})
    assert len(unpause_calls) == 1
    assert unpause_calls[0].data == {
        ATTR_ENTITY_ID: 'vacuum.bla',
    }
コード例 #19
0
async def test_scene_scene(hass):
    """Test Scene trait support for scene domain."""
    assert helpers.get_google_type(scene.DOMAIN, None) is not None
    assert trait.SceneTrait.supported(scene.DOMAIN, 0, None)

    trt = trait.SceneTrait(hass, State("scene.bla", scene.STATE), BASIC_CONFIG)
    assert trt.sync_attributes() == {}
    assert trt.query_attributes() == {}
    assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {})

    calls = async_mock_service(hass, scene.DOMAIN, SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_ACTIVATE_SCENE, BASIC_DATA, {}, {})
    assert len(calls) == 1
    assert calls[0].data == {ATTR_ENTITY_ID: "scene.bla"}
コード例 #20
0
ファイル: test_trait.py プロジェクト: crazyfish1111/home
async def test_lock_unlock_unlock(hass):
    """Test LockUnlock trait unlocking support for lock domain."""
    assert helpers.get_google_type(lock.DOMAIN, None) is not None
    assert trait.LockUnlockTrait.supported(lock.DOMAIN, lock.SUPPORT_OPEN,
                                           None)

    trt = trait.LockUnlockTrait(hass,
                                State('lock.front_door', lock.STATE_LOCKED),
                                PIN_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {'isLocked': True}

    assert trt.can_execute(trait.COMMAND_LOCKUNLOCK, {'lock': False})

    calls = async_mock_service(hass, lock.DOMAIN, lock.SERVICE_UNLOCK)

    # No challenge data
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {'lock': False},
                          {})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_PIN_NEEDED

    # invalid pin
    with pytest.raises(error.ChallengeNeeded) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {'lock': False},
                          {'pin': 9999})
    assert len(calls) == 0
    assert err.value.code == const.ERR_CHALLENGE_NEEDED
    assert err.value.challenge_type == const.CHALLENGE_FAILED_PIN_NEEDED

    await trt.execute(trait.COMMAND_LOCKUNLOCK, PIN_DATA, {'lock': False},
                      {'pin': '1234'})

    assert len(calls) == 1
    assert calls[0].data == {ATTR_ENTITY_ID: 'lock.front_door'}

    # Test without pin
    trt = trait.LockUnlockTrait(hass,
                                State('lock.front_door', lock.STATE_LOCKED),
                                BASIC_CONFIG)

    with pytest.raises(error.SmartHomeError) as err:
        await trt.execute(trait.COMMAND_LOCKUNLOCK, BASIC_DATA,
                          {'lock': False}, {})
    assert len(calls) == 1
    assert err.value.code == const.ERR_CHALLENGE_NOT_SETUP
コード例 #21
0
async def test_color_light_temperature_light_bad_temp(hass):
    """Test ColorTemperature trait support for light domain."""
    assert helpers.get_google_type(light.DOMAIN, None) is not None
    assert not trait.ColorSettingTrait.supported(light.DOMAIN, 0, None)
    assert trait.ColorSettingTrait.supported(light.DOMAIN,
                                             light.SUPPORT_COLOR_TEMP, None)

    trt = trait.ColorSettingTrait(hass, State('light.bla', STATE_ON, {
        light.ATTR_MIN_MIREDS: 200,
        light.ATTR_COLOR_TEMP: 0,
        light.ATTR_MAX_MIREDS: 500,
    }), BASIC_CONFIG)

    assert trt.query_attributes() == {
    }
コード例 #22
0
async def test_temperature_setting_climate_onoff(hass):
    """Test TemperatureSetting trait support for climate domain - range."""
    assert helpers.get_google_type(climate.DOMAIN, None) is not None
    assert not trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None)
    assert trait.TemperatureSettingTrait.supported(
        climate.DOMAIN, climate.SUPPORT_OPERATION_MODE, None)

    hass.config.units.temperature_unit = TEMP_FAHRENHEIT

    trt = trait.TemperatureSettingTrait(
        hass,
        State(
            'climate.bla', climate.STATE_AUTO, {
                ATTR_SUPPORTED_FEATURES:
                (climate.SUPPORT_OPERATION_MODE | climate.SUPPORT_ON_OFF
                 | climate.SUPPORT_TARGET_TEMPERATURE_HIGH
                 | climate.SUPPORT_TARGET_TEMPERATURE_LOW),
                climate.ATTR_OPERATION_MODE:
                climate.STATE_COOL,
                climate.ATTR_OPERATION_LIST: [
                    climate.STATE_COOL,
                    climate.STATE_HEAT,
                    climate.STATE_AUTO,
                ],
                climate.ATTR_MIN_TEMP:
                None,
                climate.ATTR_MAX_TEMP:
                None,
            }), BASIC_CONFIG)
    assert trt.sync_attributes() == {
        'availableThermostatModes': 'off,on,cool,heat,heatcool',
        'thermostatTemperatureUnit': 'F',
    }
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {})

    calls = async_mock_service(hass, climate.DOMAIN, SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, BASIC_DATA, {
        'thermostatMode': 'on',
    }, {})
    assert len(calls) == 1

    calls = async_mock_service(hass, climate.DOMAIN, SERVICE_TURN_OFF)
    await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, BASIC_DATA, {
        'thermostatMode': 'off',
    }, {})
    assert len(calls) == 1
コード例 #23
0
async def test_dock_vacuum(hass):
    """Test dock trait support for vacuum domain."""
    assert helpers.get_google_type(vacuum.DOMAIN, None) is not None
    assert trait.DockTrait.supported(vacuum.DOMAIN, 0, None)

    trt = trait.DockTrait(hass, State("vacuum.bla", vacuum.STATE_IDLE),
                          BASIC_CONFIG)

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {"isDocked": False}

    calls = async_mock_service(hass, vacuum.DOMAIN,
                               vacuum.SERVICE_RETURN_TO_BASE)
    await trt.execute(trait.COMMAND_DOCK, BASIC_DATA, {}, {})
    assert len(calls) == 1
    assert calls[0].data == {ATTR_ENTITY_ID: "vacuum.bla"}
コード例 #24
0
async def test_temperature_setting_climate_onoff(hass):
    """Test TemperatureSetting trait support for climate domain - range."""
    assert helpers.get_google_type(climate.DOMAIN, None) is not None
    assert trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None)

    hass.config.units.temperature_unit = TEMP_FAHRENHEIT

    trt = trait.TemperatureSettingTrait(
        hass,
        State(
            "climate.bla",
            climate.HVAC_MODE_AUTO,
            {
                ATTR_SUPPORTED_FEATURES:
                climate.SUPPORT_TARGET_TEMPERATURE_RANGE,
                climate.ATTR_HVAC_MODES: [
                    climate.HVAC_MODE_OFF,
                    climate.HVAC_MODE_COOL,
                    climate.HVAC_MODE_HEAT,
                    climate.HVAC_MODE_HEAT_COOL,
                ],
                climate.ATTR_MIN_TEMP:
                None,
                climate.ATTR_MAX_TEMP:
                None,
            },
        ),
        BASIC_CONFIG,
    )
    assert trt.sync_attributes() == {
        "availableThermostatModes": "off,cool,heat,heatcool,on",
        "thermostatTemperatureUnit": "F",
    }
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {})

    calls = async_mock_service(hass, climate.DOMAIN, SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, BASIC_DATA,
                      {"thermostatMode": "on"}, {})
    assert len(calls) == 1

    calls = async_mock_service(hass, climate.DOMAIN, SERVICE_TURN_OFF)
    await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, BASIC_DATA,
                      {"thermostatMode": "off"}, {})
    assert len(calls) == 1
コード例 #25
0
async def test_openclose_cover_no_position(hass):
    """Test OpenClose trait support for cover domain."""
    assert helpers.get_google_type(cover.DOMAIN, None) is not None
    assert trait.OpenCloseTrait.supported(cover.DOMAIN,
                                          cover.SUPPORT_SET_POSITION, None)

    trt = trait.OpenCloseTrait(hass, State('cover.bla', cover.STATE_OPEN, {}),
                               BASIC_CONFIG)

    assert trt.sync_attributes() == {}
    assert trt.query_attributes() == {'openPercent': 100}

    calls = async_mock_service(hass, cover.DOMAIN, cover.SERVICE_CLOSE_COVER)
    await trt.execute(trait.COMMAND_OPENCLOSE, BASIC_DATA, {'openPercent': 0},
                      {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'cover.bla',
    }
コード例 #26
0
async def test_scene_script(hass):
    """Test Scene trait support for script domain."""
    assert helpers.get_google_type(script.DOMAIN, None) is not None
    assert trait.SceneTrait.supported(script.DOMAIN, 0, None)

    trt = trait.SceneTrait(hass, State('script.bla', STATE_OFF), BASIC_CONFIG)
    assert trt.sync_attributes() == {}
    assert trt.query_attributes() == {}
    assert trt.can_execute(trait.COMMAND_ACTIVATE_SCENE, {})

    calls = async_mock_service(hass, script.DOMAIN, SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_ACTIVATE_SCENE, BASIC_DATA, {}, {})

    # We don't wait till script execution is done.
    await hass.async_block_till_done()

    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'script.bla',
    }
コード例 #27
0
async def test_brightness_light(hass):
    """Test brightness trait support for light domain."""
    assert helpers.get_google_type(light.DOMAIN, None) is not None
    assert trait.BrightnessTrait.supported(light.DOMAIN,
                                           light.SUPPORT_BRIGHTNESS, None)

    trt = trait.BrightnessTrait(
        hass,
        State("light.bla", light.STATE_ON, {light.ATTR_BRIGHTNESS: 243}),
        BASIC_CONFIG,
    )

    assert trt.sync_attributes() == {}

    assert trt.query_attributes() == {"brightness": 95}

    events = []
    hass.bus.async_listen(EVENT_CALL_SERVICE, events.append)

    calls = async_mock_service(hass, light.DOMAIN, light.SERVICE_TURN_ON)
    await trt.execute(trait.COMMAND_BRIGHTNESS_ABSOLUTE, BASIC_DATA,
                      {"brightness": 50}, {})
    await hass.async_block_till_done()

    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: "light.bla",
        light.ATTR_BRIGHTNESS_PCT: 50
    }

    assert len(events) == 1
    assert events[0].data == {
        "domain": "light",
        "service": "turn_on",
        "service_data": {
            "brightness_pct": 50,
            "entity_id": "light.bla"
        },
    }
コード例 #28
0
async def test_modes(hass):
    """Test Mode trait."""
    assert helpers.get_google_type(media_player.DOMAIN, None) is not None
    assert trait.ModesTrait.supported(media_player.DOMAIN,
                                      media_player.SUPPORT_SELECT_SOURCE, None)

    trt = trait.ModesTrait(
        hass,
        State('media_player.living_room',
              media_player.STATE_PLAYING,
              attributes={
                  media_player.ATTR_INPUT_SOURCE_LIST:
                  ['media', 'game', 'chromecast', 'plex'],
                  media_player.ATTR_INPUT_SOURCE:
                  'game'
              }), BASIC_CONFIG)

    attribs = trt.sync_attributes()
    assert attribs == {
        'availableModes': [{
            'name':
            'input source',
            'name_values': [{
                'name_synonym': ['input source'],
                'lang': 'en'
            }],
            'settings': [{
                'setting_name':
                'media',
                'setting_values': [{
                    'setting_synonym': ['media', 'media mode'],
                    'lang': 'en'
                }]
            }, {
                'setting_name':
                'game',
                'setting_values': [{
                    'setting_synonym': ['game', 'game mode'],
                    'lang': 'en'
                }]
            }, {
                'setting_name':
                'chromecast',
                'setting_values': [{
                    'setting_synonym': ['chromecast'],
                    'lang': 'en'
                }]
            }],
            'ordered':
            False
        }]
    }

    assert trt.query_attributes() == {
        'currentModeSettings': {
            'source': 'game'
        },
        'on': True,
        'online': True
    }

    assert trt.can_execute(
        trait.COMMAND_MODES,
        params={
            'updateModeSettings': {
                trt.HA_TO_GOOGLE.get(media_player.ATTR_INPUT_SOURCE): 'media'
            }
        })

    calls = async_mock_service(hass, media_player.DOMAIN,
                               media_player.SERVICE_SELECT_SOURCE)
    await trt.execute(
        trait.COMMAND_MODES, BASIC_DATA, {
            'updateModeSettings': {
                trt.HA_TO_GOOGLE.get(media_player.ATTR_INPUT_SOURCE): 'media'
            }
        }, {})

    assert len(calls) == 1
    assert calls[0].data == {
        'entity_id': 'media_player.living_room',
        'source': 'media'
    }
コード例 #29
0
async def test_fan_speed(hass):
    """Test FanSpeed trait speed control support for fan domain."""
    assert helpers.get_google_type(fan.DOMAIN, None) is not None
    assert trait.FanSpeedTrait.supported(fan.DOMAIN, fan.SUPPORT_SET_SPEED,
                                         None)

    trt = trait.FanSpeedTrait(
        hass,
        State('fan.living_room_fan',
              fan.SPEED_HIGH,
              attributes={
                  'speed_list': [
                      fan.SPEED_OFF, fan.SPEED_LOW, fan.SPEED_MEDIUM,
                      fan.SPEED_HIGH
                  ],
                  'speed':
                  'low'
              }), BASIC_CONFIG)

    assert trt.sync_attributes() == {
        'availableFanSpeeds': {
            'ordered':
            True,
            'speeds': [{
                'speed_name':
                'off',
                'speed_values': [{
                    'speed_synonym': ['stop', 'off'],
                    'lang': 'en'
                }]
            }, {
                'speed_name':
                'low',
                'speed_values': [{
                    'speed_synonym': ['slow', 'low', 'slowest', 'lowest'],
                    'lang':
                    'en'
                }]
            }, {
                'speed_name':
                'medium',
                'speed_values': [{
                    'speed_synonym': ['medium', 'mid', 'middle'],
                    'lang': 'en'
                }]
            }, {
                'speed_name':
                'high',
                'speed_values': [{
                    'speed_synonym':
                    ['high', 'max', 'fast', 'highest', 'fastest', 'maximum'],
                    'lang':
                    'en'
                }]
            }]
        },
        'reversible': False
    }

    assert trt.query_attributes() == {
        'currentFanSpeedSetting': 'low',
        'on': True,
        'online': True
    }

    assert trt.can_execute(trait.COMMAND_FANSPEED,
                           params={'fanSpeed': 'medium'})

    calls = async_mock_service(hass, fan.DOMAIN, fan.SERVICE_SET_SPEED)
    await trt.execute(trait.COMMAND_FANSPEED, BASIC_DATA,
                      {'fanSpeed': 'medium'}, {})

    assert len(calls) == 1
    assert calls[0].data == {
        'entity_id': 'fan.living_room_fan',
        'speed': 'medium'
    }
コード例 #30
0
async def test_temperature_setting_climate_range(hass):
    """Test TemperatureSetting trait support for climate domain - range."""
    assert helpers.get_google_type(climate.DOMAIN, None) is not None
    assert not trait.TemperatureSettingTrait.supported(climate.DOMAIN, 0, None)
    assert trait.TemperatureSettingTrait.supported(
        climate.DOMAIN, climate.SUPPORT_OPERATION_MODE, None)

    hass.config.units.temperature_unit = TEMP_FAHRENHEIT

    trt = trait.TemperatureSettingTrait(
        hass,
        State(
            'climate.bla', climate.STATE_AUTO, {
                climate.ATTR_CURRENT_TEMPERATURE:
                70,
                climate.ATTR_CURRENT_HUMIDITY:
                25,
                ATTR_SUPPORTED_FEATURES:
                climate.SUPPORT_OPERATION_MODE
                | climate.SUPPORT_TARGET_TEMPERATURE_HIGH
                | climate.SUPPORT_TARGET_TEMPERATURE_LOW,
                climate.ATTR_OPERATION_MODE:
                climate.STATE_AUTO,
                climate.ATTR_OPERATION_LIST: [
                    STATE_OFF,
                    climate.STATE_COOL,
                    climate.STATE_HEAT,
                    climate.STATE_AUTO,
                ],
                climate.ATTR_TARGET_TEMP_HIGH:
                75,
                climate.ATTR_TARGET_TEMP_LOW:
                65,
                climate.ATTR_MIN_TEMP:
                50,
                climate.ATTR_MAX_TEMP:
                80
            }), BASIC_CONFIG)
    assert trt.sync_attributes() == {
        'availableThermostatModes': 'off,cool,heat,heatcool',
        'thermostatTemperatureUnit': 'F',
    }
    assert trt.query_attributes() == {
        'thermostatMode': 'heatcool',
        'thermostatTemperatureAmbient': 21.1,
        'thermostatHumidityAmbient': 25,
        'thermostatTemperatureSetpointLow': 18.3,
        'thermostatTemperatureSetpointHigh': 23.9,
    }
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, {})
    assert trt.can_execute(trait.COMMAND_THERMOSTAT_SET_MODE, {})

    calls = async_mock_service(hass, climate.DOMAIN,
                               climate.SERVICE_SET_TEMPERATURE)
    await trt.execute(
        trait.COMMAND_THERMOSTAT_TEMPERATURE_SET_RANGE, BASIC_DATA, {
            'thermostatTemperatureSetpointHigh': 25,
            'thermostatTemperatureSetpointLow': 20,
        }, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'climate.bla',
        climate.ATTR_TARGET_TEMP_HIGH: 77,
        climate.ATTR_TARGET_TEMP_LOW: 68,
    }

    calls = async_mock_service(hass, climate.DOMAIN,
                               climate.SERVICE_SET_OPERATION_MODE)
    await trt.execute(trait.COMMAND_THERMOSTAT_SET_MODE, BASIC_DATA, {
        'thermostatMode': 'heatcool',
    }, {})
    assert len(calls) == 1
    assert calls[0].data == {
        ATTR_ENTITY_ID: 'climate.bla',
        climate.ATTR_OPERATION_MODE: climate.STATE_AUTO,
    }

    with pytest.raises(helpers.SmartHomeError) as err:
        await trt.execute(trait.COMMAND_THERMOSTAT_TEMPERATURE_SETPOINT,
                          BASIC_DATA, {'thermostatTemperatureSetpoint': -100},
                          {})
    assert err.value.code == const.ERR_VALUE_OUT_OF_RANGE
    hass.config.units.temperature_unit = TEMP_CELSIUS