LIFX: avoid rare NoneType errors (#9054)
* Get full multizone state during registration We used to rely on the periodic update to get the state of each zone, only establishing the number of zones during registration. This resulted in errors if the current state was needed for a partial color change before the first async_update happened. Now we do a full update before adding the light. Thus async_update can no longer assume device.color_zones to be defined and must instead use the response message to decide the total number of zones. * Insist on getting the initial state If a response to the initial state query is lost we used to just carry on. This resulted in type errors when we next tried to access the undefined state. After this commit the light is not added before we have the full state. This scenario mostly happens when something is misbehaving and the type errors were actually useful in figuring out what happend. So an error message is logged in their place. * Remove lintpull/9062/head
parent
b3d16e8f89
commit
fee89d8d16
|
@ -325,29 +325,33 @@ class LIFXManager(object):
|
|||
entity = self.entities[device.mac_addr]
|
||||
entity.registered = True
|
||||
_LOGGER.debug("%s register AGAIN", entity.who)
|
||||
yield from entity.async_update()
|
||||
yield from entity.async_update_ha_state()
|
||||
yield from entity.update_hass()
|
||||
else:
|
||||
_LOGGER.debug("%s register NEW", device.ip_addr)
|
||||
device.timeout = MESSAGE_TIMEOUT
|
||||
device.retry_count = MESSAGE_RETRIES
|
||||
device.unregister_timeout = UNAVAILABLE_GRACE
|
||||
|
||||
# Read initial state
|
||||
ack = AwaitAioLIFX().wait
|
||||
yield from ack(device.get_version)
|
||||
yield from ack(device.get_color)
|
||||
version_resp = yield from ack(device.get_version)
|
||||
if version_resp:
|
||||
color_resp = yield from ack(device.get_color)
|
||||
|
||||
if lifxwhite(device):
|
||||
entity = LIFXWhite(device, self.effects_conductor)
|
||||
elif lifxmultizone(device):
|
||||
yield from ack(partial(device.get_color_zones, start_index=0))
|
||||
entity = LIFXStrip(device, self.effects_conductor)
|
||||
if version_resp is None or color_resp is None:
|
||||
_LOGGER.error("Failed to initialize %s", device.ip_addr)
|
||||
else:
|
||||
entity = LIFXColor(device, self.effects_conductor)
|
||||
device.timeout = MESSAGE_TIMEOUT
|
||||
device.retry_count = MESSAGE_RETRIES
|
||||
device.unregister_timeout = UNAVAILABLE_GRACE
|
||||
|
||||
_LOGGER.debug("%s register READY", entity.who)
|
||||
self.entities[device.mac_addr] = entity
|
||||
self.async_add_devices([entity])
|
||||
if lifxwhite(device):
|
||||
entity = LIFXWhite(device, self.effects_conductor)
|
||||
elif lifxmultizone(device):
|
||||
entity = LIFXStrip(device, self.effects_conductor)
|
||||
else:
|
||||
entity = LIFXColor(device, self.effects_conductor)
|
||||
|
||||
_LOGGER.debug("%s register READY", entity.who)
|
||||
self.entities[device.mac_addr] = entity
|
||||
self.async_add_devices([entity], True)
|
||||
|
||||
@callback
|
||||
def unregister(self, device):
|
||||
|
@ -674,9 +678,14 @@ class LIFXStrip(LIFXColor):
|
|||
@asyncio.coroutine
|
||||
def update_color_zones(self):
|
||||
"""Get updated color information for each zone."""
|
||||
ack = AwaitAioLIFX().wait
|
||||
bulb = self.device
|
||||
|
||||
# Each get_color_zones returns the next 8 zones
|
||||
for zone in range(0, len(bulb.color_zones), 8):
|
||||
yield from ack(partial(bulb.get_color_zones, start_index=zone))
|
||||
zone = 0
|
||||
top = 1
|
||||
while self.available and zone < top:
|
||||
# Each get_color_zones can update 8 zones at once
|
||||
resp = yield from AwaitAioLIFX().wait(partial(
|
||||
self.device.get_color_zones,
|
||||
start_index=zone,
|
||||
end_index=zone+7))
|
||||
if resp:
|
||||
zone += 8
|
||||
top = resp.count
|
||||
|
|
Loading…
Reference in New Issue