From a8c57bd4bdcdef41d98ad36ff0b6883791aea0fe Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sat, 13 Dec 2025 10:05:25 -0500 Subject: [PATCH 1/3] Update api.py --- pyhilo/api.py | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/pyhilo/api.py b/pyhilo/api.py index 07e4b33..8693da3 100755 --- a/pyhilo/api.py +++ b/pyhilo/api.py @@ -1,6 +1,7 @@ from __future__ import annotations import asyncio +import base64 from datetime import datetime, timedelta import json import random @@ -92,6 +93,7 @@ def __init__( self.ws_url: str = "" self.ws_token: str = "" self.endpoint: str = "" + self._urn: str | None = None @classmethod async def async_create( @@ -145,6 +147,27 @@ async def async_get_access_token(self) -> str: return str(self._oauth_session.token["access_token"]) + @property + def urn(self) -> str | None: + """Extract URN from the JWT access token.""" + try: + if not self._oauth_session.valid_token: + return None + token = self._oauth_session.token["access_token"] + payload_part = token.split(".")[1] + # Add padding if necessary + padding = 4 - len(payload_part) % 4 + if padding != 4: + payload_part += "=" * padding + + decoded = base64.urlsafe_b64decode(payload_part) + claims = json.loads(decoded) + self._urn = claims.get("urn") + return self._urn + except (IndexError, json.JSONDecodeError, KeyError): + LOG.error("Failed to extract URN from access token") + return None + def dev_atts( self, attribute: str, value_type: Union[str, None] = None ) -> Union[DeviceAttribute, str]: From 588aef0c2173c19f0f9c5606519ab35f44da744a Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sun, 14 Dec 2025 07:17:16 -0500 Subject: [PATCH 2/3] Update api.py Adding urn extraction --- pyhilo/api.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/pyhilo/api.py b/pyhilo/api.py index 8693da3..8f9fc21 100755 --- a/pyhilo/api.py +++ b/pyhilo/api.py @@ -145,6 +145,9 @@ async def async_get_access_token(self) -> str: access_token = str(self._oauth_session.token["access_token"]) LOG.debug("Websocket access token is %s", access_token) + urn = self.urn + LOG.debug("Extracted URN: %s", urn) + return str(self._oauth_session.token["access_token"]) @property @@ -162,7 +165,12 @@ def urn(self) -> str | None: decoded = base64.urlsafe_b64decode(payload_part) claims = json.loads(decoded) - self._urn = claims.get("urn") + urn_claim = claims.get("urn:com:hiloenergie:profile:location_hilo_id") + if urn_claim and isinstance(urn_claim, list) and len(urn_claim) > 0: + self._urn = urn_claim[0] # Get the first URN from the array + else: + self._urn = None + return self._urn except (IndexError, json.JSONDecodeError, KeyError): LOG.error("Failed to extract URN from access token") From 34fb4bd5bea60980e11a200e127122dfd3285d3e Mon Sep 17 00:00:00 2001 From: "Ian C." <108159253+ic-dev21@users.noreply.github.com> Date: Sun, 14 Dec 2025 11:58:28 -0500 Subject: [PATCH 3/3] Bump Bump up version --- pyhilo/const.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pyhilo/const.py b/pyhilo/const.py index 407d310..9a048f4 100755 --- a/pyhilo/const.py +++ b/pyhilo/const.py @@ -7,7 +7,7 @@ LOG: Final = logging.getLogger(__package__) DEFAULT_STATE_FILE: Final = "hilo_state.yaml" REQUEST_RETRY: Final = 9 -PYHILO_VERSION: Final = "2025.12.03" +PYHILO_VERSION: Final = "2025.12.04" # TODO: Find a way to keep previous line in sync with pyproject.toml automatically CONTENT_TYPE_FORM: Final = "application/x-www-form-urlencoded" diff --git a/pyproject.toml b/pyproject.toml index e373d6b..acefd8c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -40,7 +40,7 @@ exclude = ".venv/.*" [tool.poetry] name = "python-hilo" -version = "2025.12.3" +version = "2025.12.4" description = "A Python3, async interface to the Hilo API" readme = "README.md" authors = ["David Vallee Delisle "]