From b623082c4aab6dde64c1f26d809713c19e17da69 Mon Sep 17 00:00:00 2001 From: lilly Date: Thu, 14 May 2026 15:36:46 +0200 Subject: [PATCH] api: refactor ccujack state keeping --- api/pyproject.toml | 1 - api/src/dooris_api/app.py | 30 ++++++++++++++++-------------- api/src/dooris_api/ccujack.py | 8 ++++++-- api/src/dooris_api/deps.py | 8 -------- api/uv.lock | 11 ----------- 5 files changed, 22 insertions(+), 36 deletions(-) diff --git a/api/pyproject.toml b/api/pyproject.toml index c382454..fe60426 100644 --- a/api/pyproject.toml +++ b/api/pyproject.toml @@ -5,7 +5,6 @@ description = "API for Dooris setup using HomeMatic." requires-python = ">=3.13" dependencies = [ "aiohttp>=3.13.5", - "cachetools>=7.1.1", "fastapi>=0.136.1", "simple-openid-connect>=2.4.0", "uvicorn>=0.46.0", diff --git a/api/src/dooris_api/app.py b/api/src/dooris_api/app.py index bb1ef02..8f4b68d 100644 --- a/api/src/dooris_api/app.py +++ b/api/src/dooris_api/app.py @@ -9,7 +9,6 @@ from fastapi.responses import RedirectResponse from contextlib import asynccontextmanager from simple_openid_connect.client import OpenidClient from simple_openid_connect.data import TokenSuccessResponse, RpInitiatedLogoutRequest -from cachetools import TTLCache from aiohttp import BasicAuth from dooris_api import deps, models, exceptions, app_config @@ -37,12 +36,11 @@ async def lifespan(app: FastAPI): scope=app_cfg.openid_scope, ) - app.extra["cache"] = TTLCache(maxsize=64, ttl=30 * 60) - app.extra["ccujack"] = CCUJackClient( "https://hmdooris-ccu.ccchh.net:2122", auth=BasicAuth("dooris", os.environ["HMDOORIS_PW"]), ) + await app.extra["ccujack"].find_locks() yield @@ -178,7 +176,10 @@ async def logout( ): deps.clear_auth_state(resp) return oidc_client.initiate_logout( - RpInitiatedLogoutRequest(id_token_hint=current_user.raw_id_token, post_logout_redirect_uri=f"{app_config.get().base_url}/") + RpInitiatedLogoutRequest( + id_token_hint=current_user.raw_id_token, + post_logout_redirect_uri=f"{app_config.get().base_url}/", + ) ) @@ -188,19 +189,11 @@ async def logout( responses={status.HTTP_401_UNAUTHORIZED: {"model": models.HttpProblemDetail}}, ) async def list_locks( - ccujack: deps.CCUJackClient, cache: deps.Cache + ccujack: deps.CCUJackClient ) -> List[models.Lock]: - # discover locks from ccujack - CACHE_KEY = "ccu-find-locks" - if CACHE_KEY in cache: - locks = cache[CACHE_KEY] - else: - locks = await ccujack.find_locks() - cache[CACHE_KEY] = locks - # assemble result objects result = [] - for i_lock, lock_channels in locks: + for i_lock, lock_channels in ccujack.locks: status_data = dict() for i_channel, channel_params in lock_channels: for i_param in channel_params: @@ -244,3 +237,12 @@ async def list_locks( ) return result + + +@app.patch( + "/api/locks/{name}", + tags=["locks"], + responses={status.HTTP_401_UNAUTHORIZED: {"model": models.HttpProblemDetail}}, +) +async def operate_lock(name: str): + pass diff --git a/api/src/dooris_api/ccujack.py b/api/src/dooris_api/ccujack.py index e9820e3..7b6091c 100644 --- a/api/src/dooris_api/ccujack.py +++ b/api/src/dooris_api/ccujack.py @@ -55,13 +55,17 @@ class CCUValue(BaseModel): v: Any +LockData = List[Tuple[CCUDeviceInfo, List[Tuple[CCUChannelInfo, List[CCUParamInfo]]]]] + class CCUJackClient: base_uri: str + locks: LockData def __init__(self, base_uri: str, auth: BasicAuth): self.http = ClientSession(base_url=base_uri, auth=auth, raise_for_status=True, connector=TCPConnector(ssl=False)) + self.locks = None - async def find_locks(self) -> List[Tuple[CCUDeviceInfo, List[Tuple[CCUChannelInfo, List[CCUParamInfo]]]]]: + async def find_locks(self): logger.debug("Inspecting lock devices present in CCUJack") async with self.http.get("/device") as resp: devices = CCUDeviceList.model_validate(await resp.json()) @@ -72,7 +76,7 @@ class CCUJackClient: if i.rel == "device" ]) - return [ + self.locks = [ i for i in device_infos if i[0].type == DEVICE_TYPE_LOCK diff --git a/api/src/dooris_api/deps.py b/api/src/dooris_api/deps.py index 30292e0..ed7625c 100644 --- a/api/src/dooris_api/deps.py +++ b/api/src/dooris_api/deps.py @@ -4,7 +4,6 @@ from datetime import datetime, UTC, timedelta from fastapi import Request, Depends, Response from simple_openid_connect.data import TokenSuccessResponse from simple_openid_connect.client import OpenidClient -from cachetools import Cache from dooris_api import models, exceptions from dooris_api.ccujack import CCUJackClient @@ -124,13 +123,6 @@ def clear_auth_state(resp: Response): CurrentUser = Annotated[Optional[models.CurrentUser], Depends(get_current_user)] -def get_cache(req: Request) -> Cache: - return req.app.extra["cache"] - - -Cache = Annotated[Cache, Depends(get_cache)] - - def get_ccujack(req: Request) -> CCUJackClient: return req.app.extra["ccujack"] diff --git a/api/uv.lock b/api/uv.lock index b2b2872..1c53fb5 100644 --- a/api/uv.lock +++ b/api/uv.lock @@ -139,15 +139,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/64/b4/17d4b0b2a2dc85a6df63d1157e028ed19f90d4cd97c36717afef2bc2f395/attrs-26.1.0-py3-none-any.whl", hash = "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", size = 67548, upload-time = "2026-03-19T14:22:23.645Z" }, ] -[[package]] -name = "cachetools" -version = "7.1.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ff/e2/85f227594656000ff4d8adadae91a21f536d4a84c6c716a86bd6685874be/cachetools-7.1.1.tar.gz", hash = "sha256:27bdf856d68fd3c71c26c01b5edc312124ed427524d1ddb31aa2b7746fe20d4b", size = 40202, upload-time = "2026-05-03T20:00:29.391Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/bf/0f/f897abe4ea0a8c408ae65c8c83bffab4936ad65d6032d4fb4cd35bbdc3ee/cachetools-7.1.1-py3-none-any.whl", hash = "sha256:0335cd7a0952d2b22327441fb0628139e234c565559eeb91a8a4ac7551c5353d", size = 16775, upload-time = "2026-05-03T20:00:27.857Z" }, -] - [[package]] name = "certifi" version = "2026.4.22" @@ -361,7 +352,6 @@ version = "0.1.0" source = { editable = "." } dependencies = [ { name = "aiohttp" }, - { name = "cachetools" }, { name = "fastapi" }, { name = "simple-openid-connect" }, { name = "uvicorn" }, @@ -375,7 +365,6 @@ dev = [ [package.metadata] requires-dist = [ { name = "aiohttp", specifier = ">=3.13.5" }, - { name = "cachetools", specifier = ">=7.1.1" }, { name = "fastapi", specifier = ">=0.136.1" }, { name = "simple-openid-connect", specifier = ">=2.4.0" }, { name = "uvicorn", specifier = ">=0.46.0" },