From 9cde3251ac7b958543164d10f653386850a6d75c Mon Sep 17 00:00:00 2001 From: Dan Trickey Date: Sun, 28 Aug 2022 13:45:33 +0100 Subject: [PATCH] WIP --- README.md | 1 + hue2mqtt/hue2mqtt.py | 41 ++++++++++++++++------------------------- poetry.lock | 31 ++++++++++++++++++++++++------- pyproject.toml | 2 +- 4 files changed, 42 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 6ff4993..c6857fc 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ Hue2MQTT lets you control your Hue setup using MQTT and publishes the current st - Control your lights using MQTT - Receive live events (i.e button pushes, motion sensors) in real-time. - No polling your Hue Bridge for changes +- Only supports Hue Bridge v2 (square-shaped). The Hue Bridge v1 is End of Life since June 2020. - IPv6 Support ## Configuration diff --git a/hue2mqtt/hue2mqtt.py b/hue2mqtt/hue2mqtt.py index fd64e7a..d57fd45 100644 --- a/hue2mqtt/hue2mqtt.py +++ b/hue2mqtt/hue2mqtt.py @@ -15,7 +15,6 @@ from typing import Match, Optional import aiohue -from aiohttp.client import ClientSession from pydantic import ValidationError from hue2mqtt import __version__ @@ -98,15 +97,16 @@ async def run(self) -> None: await self._mqtt.connect() LOGGER.info("Connected to MQTT Broker") - async with ClientSession() as websession: - try: - await self._setup_bridge(websession) - except aiohue.errors.Unauthorized: - LOGGER.error("Bridge rejected username. Please use --discover") - self.halt() - return - await self._publish_bridge_status() - await self.main(websession) + LOGGER.info(f"Connecting to Hue Bridge at {self.config.hue.ip}") + try: + async with aiohue.HueBridgeV2(self.config.hue.ip, self.config.hue.username) as bridge: + self._bridge = bridge + await self._publish_bridge_status() + await self.main() + except aiohue.errors.Unauthorized: + LOGGER.error("Bridge rejected credentials. Please use --discover") + self.halt() + return LOGGER.info("Disconnecting from MQTT Broker") await self._publish_bridge_status(online=False) @@ -116,27 +116,17 @@ def halt(self) -> None: """Stop the component.""" sys.exit(-1) - async def _setup_bridge(self, websession: ClientSession) -> None: - """Connect to the Hue Bridge.""" - self._bridge = aiohue.Bridge( - self.config.hue.ip, - websession, - username=self.config.hue.username, - ) - LOGGER.info(f"Connecting to Hue Bridge at {self.config.hue.ip}") - await self._bridge.initialize() - async def _publish_bridge_status(self, *, online: bool = True) -> None: """Publish info about the Hue Bridge.""" if online: LOGGER.info(f"Bridge Name: {self._bridge.config.name}") - LOGGER.info(f"Bridge MAC: {self._bridge.config.mac}") - LOGGER.info(f"API Version: {self._bridge.config.apiversion}") + LOGGER.info(f"Bridge MAC: {self._bridge.config.mac_address}") + LOGGER.info(f"API Version: {self._bridge.config.software_version}") info = BridgeInfo( name=self._bridge.config.name, - mac_address=self._bridge.config.mac, - api_version=self._bridge.config.apiversion, + mac_address=self._bridge.config.mac_address, + api_version=self._bridge.config.software_version, ) message = Hue2MQTTStatus(online=online, bridge=info) else: @@ -195,9 +185,10 @@ async def handle_set_group(self, match: Match[str], payload: str) -> None: except ValidationError as e: LOGGER.warning(f"Invalid light state: {e}") - async def main(self, websession: ClientSession) -> None: + async def main(self) -> None: """Main method of the data component.""" # Publish initial info about lights + breakpoint() for id, light_raw in self._bridge.lights._items.items(): light = LightInfo(id=id, **light_raw.raw) self.publish_light(light) diff --git a/poetry.lock b/poetry.lock index ba3b85f..1fe3330 100644 --- a/poetry.lock +++ b/poetry.lock @@ -20,14 +20,16 @@ speedups = ["aiodns", "brotli", "cchardet"] [[package]] name = "aiohue" -version = "2.6.3" +version = "4.5.0" description = "Python module to talk to Philips Hue." category = "main" optional = false -python-versions = "*" +python-versions = ">=3.8" [package.dependencies] aiohttp = "*" +asyncio-throttle = "*" +awesomeversion = "*" [[package]] name = "aiosignal" @@ -48,6 +50,14 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "asyncio-throttle" +version = "1.0.2" +description = "Simple, easy-to-use throttler for asyncio" +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "atomicwrites" version = "1.4.1" @@ -70,6 +80,14 @@ docs = ["furo", "sphinx", "zope.interface", "sphinx-notfound-page"] tests = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "zope.interface", "cloudpickle"] tests_no_zope = ["coverage[toml] (>=5.0.2)", "hypothesis", "pympler", "pytest (>=4.3.0)", "mypy (>=0.900,!=0.940)", "pytest-mypy-plugins", "cloudpickle"] +[[package]] +name = "awesomeversion" +version = "22.8.0" +description = "One version package to rule them all, One version package to find them, One version package to bring them all, and in the darkness bind them." +category = "main" +optional = false +python-versions = ">=3.7,<4.0" + [[package]] name = "charset-normalizer" version = "2.1.1" @@ -510,7 +528,7 @@ multidict = ">=4.0" [metadata] lock-version = "1.1" python-versions = "^3.8" -content-hash = "cdba42007d4342514170620a2ed579130c21a10317cd99547c29d7373f81a40d" +content-hash = "899d2c454112dcc56192f4922b15b3204bb84f232ed99ff84efa617fe6ecbc50" [metadata.files] aiohttp = [ @@ -587,10 +605,7 @@ aiohttp = [ {file = "aiohttp-3.8.1-cp39-cp39-win_amd64.whl", hash = "sha256:1c182cb873bc91b411e184dab7a2b664d4fea2743df0e4d57402f7f3fa644bac"}, {file = "aiohttp-3.8.1.tar.gz", hash = "sha256:fc5471e1a54de15ef71c1bc6ebe80d4dc681ea600e68bfd1cbce40427f0b7578"}, ] -aiohue = [ - {file = "aiohue-2.6.3-py3-none-any.whl", hash = "sha256:78c8d9bf7517a3a8e074a99c0327106da09a0ada75385ef98acc8e2902b721af"}, - {file = "aiohue-2.6.3.tar.gz", hash = "sha256:ce9c240ca3eb1394c56503b403589f4d0ee7f93445a578b78da8b7879a65c863"}, -] +aiohue = [] aiosignal = [ {file = "aiosignal-1.2.0-py3-none-any.whl", hash = "sha256:26e62109036cd181df6e6ad646f91f0dcfd05fe16d0cb924138ff2ab75d64e3a"}, {file = "aiosignal-1.2.0.tar.gz", hash = "sha256:78ed67db6c7b7ced4f98e495e572106d5c432a93e1ddd1bf475e1dc05f5b7df2"}, @@ -599,8 +614,10 @@ async-timeout = [ {file = "async-timeout-4.0.2.tar.gz", hash = "sha256:2163e1640ddb52b7a8c80d0a67a08587e5d245cc9c553a74a847056bc2976b15"}, {file = "async_timeout-4.0.2-py3-none-any.whl", hash = "sha256:8ca1e4fcf50d07413d66d1a5e416e42cfdf5851c981d679a09851a6853383b3c"}, ] +asyncio-throttle = [] atomicwrites = [] attrs = [] +awesomeversion = [] charset-normalizer = [] click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, diff --git a/pyproject.toml b/pyproject.toml index 1c66e7c..40a215c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -16,7 +16,7 @@ classifiers = [ [tool.poetry.dependencies] python = "^3.8" gmqtt = "^0.6.10" -aiohue = "^2.5.1" +aiohue = "^4.5.0" pydantic = "^1.9.2" click = "^8.1.3" aiohttp = "^3.8.1"