Merge pull request #30096 from home-assistant/rc

0.103.3
This commit is contained in:
Paulus Schoutsen 2019-12-20 21:28:49 +01:00 committed by GitHub
commit 3e7699b886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 103 additions and 34 deletions

View File

@ -158,12 +158,17 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
title="deCONZ-" + self.deconz_config[CONF_BRIDGEID], data=self.deconz_config title="deCONZ-" + self.deconz_config[CONF_BRIDGEID], data=self.deconz_config
) )
async def _update_entry(self, entry, host): def _update_entry(self, entry, host, port, api_key=None):
"""Update existing entry.""" """Update existing entry."""
if entry.data[CONF_HOST] == host: if entry.data[CONF_HOST] == host:
return self.async_abort(reason="already_configured") return self.async_abort(reason="already_configured")
entry.data[CONF_HOST] = host entry.data[CONF_HOST] = host
entry.data[CONF_PORT] = port
if api_key is not None:
entry.data[CONF_API_KEY] = api_key
self.hass.config_entries.async_update_entry(entry) self.hass.config_entries.async_update_entry(entry)
return self.async_abort(reason="updated_instance") return self.async_abort(reason="updated_instance")
@ -182,7 +187,9 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
for entry in self.hass.config_entries.async_entries(DOMAIN): for entry in self.hass.config_entries.async_entries(DOMAIN):
if uuid == entry.data.get(CONF_UUID): if uuid == entry.data.get(CONF_UUID):
return await self._update_entry(entry, discovery_info[CONF_HOST]) return self._update_entry(
entry, discovery_info[CONF_HOST], entry.data.get(CONF_PORT)
)
bridgeid = discovery_info[ATTR_SERIAL] bridgeid = discovery_info[ATTR_SERIAL]
if any( if any(
@ -212,7 +219,12 @@ class DeconzFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
if bridgeid in gateway_entries: if bridgeid in gateway_entries:
entry = gateway_entries[bridgeid] entry = gateway_entries[bridgeid]
return await self._update_entry(entry, user_input[CONF_HOST]) return self._update_entry(
entry,
user_input[CONF_HOST],
user_input[CONF_PORT],
user_input[CONF_API_KEY],
)
self._hassio_discovery = user_input self._hassio_discovery = user_input

View File

@ -3,7 +3,9 @@
def dsmr_transform(value): def dsmr_transform(value):
"""Transform DSMR version value to right format.""" """Transform DSMR version value to right format."""
return float(value) / 10 if value.isdigit():
return float(value) / 10
return value
def tariff_transform(value): def tariff_transform(value):

View File

@ -88,8 +88,11 @@ class Fan(HomeAccessory):
) )
if CHAR_ROTATION_SPEED in chars: if CHAR_ROTATION_SPEED in chars:
# Initial value is set to 100 because 0 is a special value (off). 100 is
# an arbitrary non-zero value. It is updated immediately by update_state
# to set to the correct initial value.
self.char_speed = serv_fan.configure_char( self.char_speed = serv_fan.configure_char(
CHAR_ROTATION_SPEED, value=0, setter_callback=self.set_speed CHAR_ROTATION_SPEED, value=100, setter_callback=self.set_speed
) )
if CHAR_SWING_MODE in chars: if CHAR_SWING_MODE in chars:
@ -156,7 +159,22 @@ class Fan(HomeAccessory):
speed = new_state.attributes.get(ATTR_SPEED) speed = new_state.attributes.get(ATTR_SPEED)
hk_speed_value = self.speed_mapping.speed_to_homekit(speed) hk_speed_value = self.speed_mapping.speed_to_homekit(speed)
if hk_speed_value is not None and self.char_speed.value != hk_speed_value: if hk_speed_value is not None and self.char_speed.value != hk_speed_value:
self.char_speed.set_value(hk_speed_value) # If the homeassistant component reports its speed as the first entry
# in its speed list but is not off, the hk_speed_value is 0. But 0
# is a special value in homekit. When you turn on a homekit accessory
# it will try to restore the last rotation speed state which will be
# the last value saved by char_speed.set_value. But if it is set to
# 0, HomeKit will update the rotation speed to 100 as it thinks 0 is
# off.
#
# Therefore, if the hk_speed_value is 0 and the device is still on,
# the rotation speed is mapped to 1 otherwise the update is ignored
# in order to avoid this incorrect behavior.
if hk_speed_value == 0:
if state == STATE_ON:
self.char_speed.set_value(1)
else:
self.char_speed.set_value(hk_speed_value)
# Handle Oscillating # Handle Oscillating
if self.char_swing is not None: if self.char_swing is not None:

View File

@ -82,8 +82,11 @@ class Light(HomeAccessory):
) )
if CHAR_BRIGHTNESS in self.chars: if CHAR_BRIGHTNESS in self.chars:
# Initial value is set to 100 because 0 is a special value (off). 100 is
# an arbitrary non-zero value. It is updated immediately by update_state
# to set to the correct initial value.
self.char_brightness = serv_light.configure_char( self.char_brightness = serv_light.configure_char(
CHAR_BRIGHTNESS, value=0, setter_callback=self.set_brightness CHAR_BRIGHTNESS, value=100, setter_callback=self.set_brightness
) )
if CHAR_COLOR_TEMPERATURE in self.chars: if CHAR_COLOR_TEMPERATURE in self.chars:
min_mireds = self.hass.states.get(self.entity_id).attributes.get( min_mireds = self.hass.states.get(self.entity_id).attributes.get(
@ -183,7 +186,21 @@ class Light(HomeAccessory):
if not self._flag[CHAR_BRIGHTNESS] and isinstance(brightness, int): if not self._flag[CHAR_BRIGHTNESS] and isinstance(brightness, int):
brightness = round(brightness / 255 * 100, 0) brightness = round(brightness / 255 * 100, 0)
if self.char_brightness.value != brightness: if self.char_brightness.value != brightness:
self.char_brightness.set_value(brightness) # The homeassistant component might report its brightness as 0 but is
# not off. But 0 is a special value in homekit. When you turn on a
# homekit accessory it will try to restore the last brightness state
# which will be the last value saved by char_brightness.set_value.
# But if it is set to 0, HomeKit will update the brightness to 100 as
# it thinks 0 is off.
#
# Therefore, if the the brighness is 0 and the device is still on,
# the brightness is mapped to 1 otherwise the update is ignored in
# order to avoid this incorrect behavior.
if brightness == 0:
if state == STATE_ON:
self.char_brightness.set_value(1)
else:
self.char_brightness.set_value(brightness)
self._flag[CHAR_BRIGHTNESS] = False self._flag[CHAR_BRIGHTNESS] = False
# Handle color temperature # Handle color temperature

View File

@ -63,7 +63,7 @@ class RachioControllerBinarySensor(BinarySensorDevice):
return return
# For this device # For this device
self._handle_update() self._handle_update(args, kwargs)
@abstractmethod @abstractmethod
def _poll_update(self, data=None) -> bool: def _poll_update(self, data=None) -> bool:
@ -119,9 +119,9 @@ class RachioControllerOnlineBinarySensor(RachioControllerBinarySensor):
def _handle_update(self, *args, **kwargs) -> None: def _handle_update(self, *args, **kwargs) -> None:
"""Handle an update to the state of this sensor.""" """Handle an update to the state of this sensor."""
if args[0][KEY_SUBTYPE] == SUBTYPE_ONLINE: if args[0][0][KEY_SUBTYPE] == SUBTYPE_ONLINE:
self._state = True self._state = True
elif args[0][KEY_SUBTYPE] == SUBTYPE_OFFLINE: elif args[0][0][KEY_SUBTYPE] == SUBTYPE_OFFLINE:
self._state = False self._state = False
self.schedule_update_ha_state() self.schedule_update_ha_state()

View File

@ -107,7 +107,7 @@ class RachioStandbySwitch(RachioSwitch):
dispatcher_connect( dispatcher_connect(
hass, SIGNAL_RACHIO_CONTROLLER_UPDATE, self._handle_any_update hass, SIGNAL_RACHIO_CONTROLLER_UPDATE, self._handle_any_update
) )
super().__init__(controller, poll=False) super().__init__(controller, poll=True)
self._poll_update(controller.init_data) self._poll_update(controller.init_data)
@property @property
@ -134,9 +134,9 @@ class RachioStandbySwitch(RachioSwitch):
def _handle_update(self, *args, **kwargs) -> None: def _handle_update(self, *args, **kwargs) -> None:
"""Update the state using webhook data.""" """Update the state using webhook data."""
if args[0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_ON: if args[0][0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_ON:
self._state = True self._state = True
elif args[0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_OFF: elif args[0][0][KEY_SUBTYPE] == SUBTYPE_SLEEP_MODE_OFF:
self._state = False self._state = False
self.schedule_update_ha_state() self.schedule_update_ha_state()

View File

@ -2,11 +2,7 @@
"domain": "ring", "domain": "ring",
"name": "Ring", "name": "Ring",
"documentation": "https://www.home-assistant.io/integrations/ring", "documentation": "https://www.home-assistant.io/integrations/ring",
"requirements": [ "requirements": ["ring_doorbell==0.2.5"],
"ring_doorbell==0.2.3" "dependencies": ["ffmpeg"],
],
"dependencies": [
"ffmpeg"
],
"codeowners": [] "codeowners": []
} }

View File

@ -2,9 +2,7 @@
"domain": "starlingbank", "domain": "starlingbank",
"name": "Starlingbank", "name": "Starlingbank",
"documentation": "https://www.home-assistant.io/integrations/starlingbank", "documentation": "https://www.home-assistant.io/integrations/starlingbank",
"requirements": [ "requirements": ["starlingbank==3.2"],
"starlingbank==3.1"
],
"dependencies": [], "dependencies": [],
"codeowners": [] "codeowners": []
} }

View File

@ -1,7 +1,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 103 MINOR_VERSION = 103
PATCH_VERSION = "2" PATCH_VERSION = "3"
__short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION) __short_version__ = "{}.{}".format(MAJOR_VERSION, MINOR_VERSION)
__version__ = "{}.{}".format(__short_version__, PATCH_VERSION) __version__ = "{}.{}".format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 6, 1) REQUIRED_PYTHON_VER = (3, 6, 1)

View File

@ -1730,7 +1730,7 @@ rfk101py==0.0.1
rflink==0.0.46 rflink==0.0.46
# homeassistant.components.ring # homeassistant.components.ring
ring_doorbell==0.2.3 ring_doorbell==0.2.5
# homeassistant.components.fleetgo # homeassistant.components.fleetgo
ritassist==0.9.2 ritassist==0.9.2
@ -1868,7 +1868,7 @@ sqlalchemy==1.3.11
starline==0.1.3 starline==0.1.3
# homeassistant.components.starlingbank # homeassistant.components.starlingbank
starlingbank==3.1 starlingbank==3.2
# homeassistant.components.statsd # homeassistant.components.statsd
statsd==3.2.1 statsd==3.2.1

View File

@ -549,7 +549,7 @@ restrictedpython==5.0
rflink==0.0.46 rflink==0.0.46
# homeassistant.components.ring # homeassistant.components.ring
ring_doorbell==0.2.3 ring_doorbell==0.2.5
# homeassistant.components.yamaha # homeassistant.components.yamaha
rxv==0.6.0 rxv==0.6.0

View File

@ -323,32 +323,53 @@ async def test_hassio_update_instance(hass):
"""Test we can update an existing config entry.""" """Test we can update an existing config entry."""
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, domain=config_flow.DOMAIN,
data={config_flow.CONF_BRIDGEID: "id", config_flow.CONF_HOST: "1.2.3.4"}, data={
config_flow.CONF_BRIDGEID: "id",
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 40850,
config_flow.CONF_API_KEY: "secret",
},
) )
entry.add_to_hass(hass) entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
data={config_flow.CONF_HOST: "mock-deconz", config_flow.CONF_SERIAL: "id"}, data={
config_flow.CONF_HOST: "mock-deconz",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "updated",
config_flow.CONF_SERIAL: "id",
},
context={"source": "hassio"}, context={"source": "hassio"},
) )
assert result["type"] == "abort" assert result["type"] == "abort"
assert result["reason"] == "updated_instance" assert result["reason"] == "updated_instance"
assert entry.data[config_flow.CONF_HOST] == "mock-deconz" assert entry.data[config_flow.CONF_HOST] == "mock-deconz"
assert entry.data[config_flow.CONF_PORT] == 8080
assert entry.data[config_flow.CONF_API_KEY] == "updated"
async def test_hassio_dont_update_instance(hass): async def test_hassio_dont_update_instance(hass):
"""Test we can update an existing config entry.""" """Test we can update an existing config entry."""
entry = MockConfigEntry( entry = MockConfigEntry(
domain=config_flow.DOMAIN, domain=config_flow.DOMAIN,
data={config_flow.CONF_BRIDGEID: "id", config_flow.CONF_HOST: "1.2.3.4"}, data={
config_flow.CONF_BRIDGEID: "id",
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "secret",
},
) )
entry.add_to_hass(hass) entry.add_to_hass(hass)
result = await hass.config_entries.flow.async_init( result = await hass.config_entries.flow.async_init(
config_flow.DOMAIN, config_flow.DOMAIN,
data={config_flow.CONF_HOST: "1.2.3.4", config_flow.CONF_SERIAL: "id"}, data={
config_flow.CONF_HOST: "1.2.3.4",
config_flow.CONF_PORT: 8080,
config_flow.CONF_API_KEY: "secret",
config_flow.CONF_SERIAL: "id",
},
context={"source": "hassio"}, context={"source": "hassio"},
) )

View File

@ -197,7 +197,10 @@ async def test_fan_speed(hass, hk_driver, cls, events):
) )
await hass.async_block_till_done() await hass.async_block_till_done()
acc = cls.fan(hass, hk_driver, "Fan", entity_id, 2, None) acc = cls.fan(hass, hk_driver, "Fan", entity_id, 2, None)
assert acc.char_speed.value == 0
# Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the
# speed to 100 when turning on a fan on a freshly booted up server.
assert acc.char_speed.value != 0
await hass.async_add_job(acc.run) await hass.async_add_job(acc.run)
assert ( assert (

View File

@ -101,7 +101,9 @@ async def test_light_brightness(hass, hk_driver, cls, events):
await hass.async_block_till_done() await hass.async_block_till_done()
acc = cls.light(hass, hk_driver, "Light", entity_id, 2, None) acc = cls.light(hass, hk_driver, "Light", entity_id, 2, None)
assert acc.char_brightness.value == 0 # Initial value can be anything but 0. If it is 0, it might cause HomeKit to set the
# brightness to 100 when turning on a light on a freshly booted up server.
assert acc.char_brightness.value != 0
await hass.async_add_job(acc.run) await hass.async_add_job(acc.run)
await hass.async_block_till_done() await hass.async_block_till_done()