Skip to content

Commit

Permalink
HueV2 connection and API version check
Browse files Browse the repository at this point in the history
  • Loading branch information
zim514 committed Nov 5, 2023
1 parent 9893e3e commit 1136277
Show file tree
Hide file tree
Showing 3 changed files with 139 additions and 13 deletions.
19 changes: 6 additions & 13 deletions script.service.hue/addon.xml
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<addon id="script.service.hue" name="Hue Service" provider-name="zim514" version="1.4.18">
<addon id="script.service.hue" name="Hue Service" provider-name="zim514" version="2.0~alpha1">

<requires>
<import addon="xbmc.python" version="3.0.0"/>
<import addon="script.module.requests" version="2.27.1"/>
<import addon="script.module.pil"/>
<import addon="script.module.pyrollbar" version="0.15.2"/>
<import addon="script.module.qhue" version="2.0.1"/>
<import addon="script.module.simplejson" version="3.19.1"/>
</requires>
<extension point="xbmc.service" name="service.hue" library="service.py"/>
<extension point="xbmc.python.pluginsource" library="plugin.py">
Expand All @@ -21,18 +22,10 @@
</assets>
<source>https://github.com/zim514/script.service.hue</source>
<forum>https://forum.kodi.tv/showthread.php?tid=344886</forum>
<news>v1.4.17
- Fix ambilight crash on sunset / activation when no video is playing
- Ignore Bridge throttle errors during discovery

v1.4.16
- Translations updates from Weblate

v1.4.15
- Fix 'disable during daylight' option
- Localisation updates from Weblate
- Improved connection error handling
- Fix crash on ambilight initialization and settings changes
<news>v2.0
- Initial support for Hue API V2
- Support for dynamic and gradient scenes, but require reconfiguration
- Rewrote sunset check
</news>
<summary lang="ca_ES">Automatitza les llums Hue amb la reproducció de Kodi</summary>
<summary lang="cs_CZ">Automatizace Hue světel s přehráváním Kodi</summary>
Expand Down
8 changes: 8 additions & 0 deletions script.service.hue/resources/lib/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .hueconnection import HueConnection
from .kodiutils import validate_settings, notification, cache_set, cache_get
from .language import get_string as _
from .huev2 import HueAPIv2


def core():
Expand Down Expand Up @@ -86,6 +87,13 @@ def _service(monitor):
hue_connection = HueConnection(monitor, silent=ADDON.getSettingBool("disableConnectionMessage"), discover=False)
service_enabled = cache_get("service_enabled")

#### V2 Connection

Check notice on line 90 in script.service.hue/resources/lib/core.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E266 too many leading '#' for block comment
bridge2 = HueAPIv2(ip=ADDON.getSetting("bridgeIP"), key=ADDON.getSetting("bridgeUser"))

Check notice on line 91 in script.service.hue/resources/lib/core.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

Unused local symbols

Local variable 'bridge2' value is not used


#################

Check notice on line 94 in script.service.hue/resources/lib/core.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E303 too many blank lines (2)


if hue_connection.connected:

Check notice on line 97 in script.service.hue/resources/lib/core.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E303 too many blank lines (2)
light_groups = [lightgroup.LightGroup(0, hue_connection, lightgroup.VIDEO),
lightgroup.LightGroup(1, hue_connection, lightgroup.AUDIO),
Expand Down
125 changes: 125 additions & 0 deletions script.service.hue/resources/lib/huev2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Copyright (C) 2023 Kodi Hue Service (script.service.hue)
# This file is part of script.service.hue
# SPDX-License-Identifier: MIT
# See LICENSE.TXT for more information.

import requests
import simplejson as json

Check notice on line 7 in script.service.hue/resources/lib/huev2.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

Unsatisfied package requirements

Package containing module 'simplejson' is not listed in the project requirements

import xbmc
import xbmcgui

from .kodiutils import notification
from .language import get_string as _


class HueAPIv2(object):
def __init__(self, ip=None, key=None, discover=False):

Check notice on line 17 in script.service.hue/resources/lib/huev2.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

Unused local symbols

Parameter 'discover' value is not used
self.session = requests.Session()
self.session.verify = False
# session.headers.update({'hue-application-key': hue_application_key})

self.connected = False
self.retries = 0
self.max_retries = 5
self.max_timeout = 5
self.ip = ip
self.key = key
self.base_url = None

if ip is not None and key is not None:
self.connected = self.connect()
elif self.discover:
self.discover()
else:
raise ValueError("ip and key must be provided or discover must be True")

def connect(self):
xbmc.log(f"[script.service.hue] v2 connect() ip: {self.ip}, key: {self.key}")
self.base_url = f"https://{self.ip}/clip/v2/resource/"
self.session.headers.update({'hue-application-key': self.key})

devices = self.get("device")
device_id = self.get_device_by_archetype(devices, 'bridge_v2')
software_version = self.get_attribute_value(devices, device_id, ['product_data', 'software_version'])
# Check that software_version is at least 1.60, by properly parsing it as a version number

api_split = software_version.split(".")

if software_version and int(api_split[0]) >= 1 and int(api_split[1]) >= 38: # minimum bridge version 1.38
xbmc.log(f"[script.service.hue] v2 connect() software version: {software_version}")
return True

notification(_("Hue Service"), _("Bridge outdated. Please update your bridge."), icon=xbmcgui.NOTIFICATION_ERROR)

Check notice on line 53 in script.service.hue/resources/lib/huev2.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

PEP 8 coding style violation

PEP 8: E501 line too long (121 \> 120 characters)
xbmc.log(f"[script.service.hue] v2 connect(): Connected! Bridge API too old: {software_version}")
return False

xbmc.log(f"[script.service.hue] v2 connect() software version: {software_version}")

Check warning on line 57 in script.service.hue/resources/lib/huev2.py

View workflow job for this annotation

GitHub Actions / Qodana Community for Python

Unreachable code

This code is unreachable

def discover(self):
pass

def get(self, resource):
url = f"{self.base_url}/{resource}"

try:
response = self.session.get(url)

if response.status_code == 200:
try:
data = json.loads(response.text)
return data
except json.JSONDecodeError as x:
xbmc.log(f"[script.service.hue] v2 get() JSONDecodeError: {x}")
raise

elif response.status_code in [401, 403]:
xbmc.log(f"[script.service.hue] v2 get() Auth error: {response.status_code}")
raise requests.RequestException
elif response.status_code in [500, 502, 503, 504]:
xbmc.log(f"[script.service.hue] v2 get() Server error: {response.status_code}")
raise requests.RequestException
elif response.status_code in [400, 404]:
xbmc.log(f"[script.service.hue] v2 get() Client error: {response.status_code}")
raise requests.RequestException
elif response.status_code == 429:
xbmc.log(f"[script.service.hue] v2 get() Too many requests: {response.status_code}")
raise requests.RequestException

except requests.RequestException as x:
xbmc.log(f"[script.service.hue] v2 get() RequestException: {x}")
raise

@staticmethod
def get_device_by_archetype(json_data, archetype):
for device in json_data['data']:
if device['product_data']['product_archetype'] == archetype:
return device['id']
return None

@staticmethod
def get_attribute_value(json_data, device_id, attribute_path):
for device in json_data['data']:
if device['id'] == device_id:
value = device
for key in attribute_path:
value = value.get(key)
if value is None:
return None
return value
return None

def search_dict(self, d, key):
if key in d:
return d[key]
for k, v in d.items():
if isinstance(v, dict):
item = self.search_dict(v, key)
if item is not None:
return item
elif isinstance(v, list):
for d in v:
if isinstance(d, dict):
item = self.search_dict(d, key)
if item is not None:
return item

0 comments on commit 1136277

Please sign in to comment.