Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Hue: phue -> aiohue #13043

Merged
merged 23 commits into from Mar 17, 2018
Merged

Refactor Hue: phue -> aiohue #13043

merged 23 commits into from Mar 17, 2018

Conversation

balloob
Copy link
Member

@balloob balloob commented Mar 10, 2018

Description:

Hue is going async! 🎉

We used to use phue. It was a sync library and it only allowed to store auth on disk. It could not work with auth that was passed in. So for config entries I decided to roll aiohue to manage linking and getting basic info.

Since then aiohue has matured, 1.0.0 has been released and so I decided to migrate our hue component from phue to aiohue.

This is a backwards compatible change for the auth files. The Hue component will consume and generate the silly config files from phue.

Breaking change: If you specify a bridge in your config, the host key is now required and needs to be a valid ip address. Option allow_in_emulated_hue has been removed. Components should not be aware nor care about other components. Exclude the lights via the emulated hue config.

Example entry for configuration.yaml (if applicable):

hue:

Checklist:

  • The code change is tested and works locally.
  • Local tests pass with tox. Your PR cannot be merged unless tests pass

If the code does not interact with devices:

  • Tests have been added to verify that the new code works.

allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE)
allow_in_emulated_hue = bridge.get(CONF_ALLOW_IN_EMULATED_HUE)
allow_hue_groups = bridge.get(CONF_ALLOW_HUE_GROUPS)
allow_unreachable = bridge.get(CONF_ALLOW_UNREACHABLE,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass defaults because when discovering bridges via nupnp, we don't go through config schema.

ATTR_IS_HUE_GROUP = 'is_hue_group'

# Legacy configuration, will be removed in 0.60
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of this wasn't used and could be removed.

"""Store config."""
with open(hass.config.path(filename), 'w') as outp:
json.dump({
host: {'username': bridge.username}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'bridge'

Copy link
Member

@OttoWinter OttoWinter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Awesome 🎉 I don't have any Hue lights so I can't test it, but the code looks good to me 👍

self.host)
self.request_configuration()
except aiohue.AiohueException:
_LOGGER.exception('Uknown Hue linking error occurred')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo. _LOGGER.exception("Unknown Hue linking error occurred")

if not isinstance(api_groups, dict):
_LOGGER.error('Got unexpected result from Hue API')
return []
if not allow_groups:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe also check if new_lights is truthy?

allow_in_emulated_hue, allow_hue_groups)
bridge.setup()
allow_hue_groups)
hass.async_add_job(bridge.async_setup())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hass.add_job

@point-4ward
Copy link
Contributor

Any chance of an official integration of the Hue sensors? I'm using @robmarkcole 's custom component atm and it's ace, and I use the readings from the motion sensors for automations (and I have a couple that react to long presses on dimmer switches too)

Obviously this PR is going to throw a spanner in the works somewhere along the line, would be good to get an official integration for the other hue devices at the same time, or at least 'around the corner'.

@balloob
Copy link
Member Author

balloob commented Mar 12, 2018

@mf-social yes, sensors are on the roadmap after this PR lands.

@point-4ward
Copy link
Contributor

@balloob - excellent 🙏


class BoolProxy:
"""Proxy value for a boolean."""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this requires a longer explanation. What does this solve?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I'll remove it and just pass bridge object through like the old implementation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What it was solving btw was that we're sharing a boolean value with all the light objects and are able to change it without having to update each light object individually.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

update_lights_cb=None,
allow_in_emulated_hue=False,
bridge=Mock(allow_unreachable=False),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'Mock'


light_id=None,
bridge=mock.Mock(),
light=Mock(state={'reachable': False}),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'Mock'

update_lights_cb=None,
allow_in_emulated_hue=False,
bridge=Mock(allow_unreachable=False),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'Mock'


light_id=None,
bridge=mock.Mock(),
light=Mock(state={'reachable': False}),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undefined name 'Mock'

@balloob
Copy link
Member Author

balloob commented Mar 13, 2018

Alright updated the code, we're no longer updating things twice. It's lean and efficient.

@MartinHjelmare
Copy link
Member

Logic looks good to me.

import unittest
import unittest.mock as mock
from unittest.mock import call, MagicMock, patch
from unittest.mock import patch, Mock

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'unittest.mock.patch' imported but unused


import asyncio
from collections import deque
from copy import deepcopy

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'copy.deepcopy' imported but unused

"""Mock the HueBridge from initializing."""
patch('homeassistant.components.hue._find_username_from_config',
return_value=None), \
patch('homeassistant.components.hue.HueBridge') as mock_bridge:

This comment was marked as resolved.

@balloob balloob requested a review from a team as a code owner March 14, 2018 07:20
@@ -203,8 +203,7 @@ def get_config_value(node, value_index, tries=5):
return None


@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
async def async_setup_platform(hass, config, async_add_devices, discovery_info=None):

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (85 > 79 characters)

@balloob
Copy link
Member Author

balloob commented Mar 14, 2018

PyLint sometimes gets confused when mixing async/await with coroutine, hence I had to include some extra async/await conversions to satisfy pylint: 9e07108

@mcfarlde
Copy link

mcfarlde commented Apr 2, 2018

This refactor caused the connections to tasmota ESP 8266s using HUe emulation to be lost. They are not discovered and the config that used to work with them no longer works. It would have been good to leave backwards compatibility so that existing devices would not be lost. I think I can either wait until arendst updates the tasmota firmware or move the device to MQTT which I do not currently use. Itchy finger on that update button burned me again!

@balloob
Copy link
Member Author

balloob commented Apr 2, 2018

If Tasmota does not work with this integration, it's the problem in their emulation layer. This integration is made for Philips Hue.

@mcfarlde
Copy link

mcfarlde commented Apr 2, 2018

Ya, figured that. Theo Arends suggests moving to MQTT as there is no room in the firmware for a full HUE emulation. I guess I was lucky to have it working for the year prior to this integration.

@home-assistant home-assistant locked and limited conversation to collaborators Jul 26, 2018
@ghost ghost removed the platform: light.hue label Mar 21, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants