api: implement ccu querying
This commit is contained in:
parent
745dfaf19f
commit
c1a78e4dc9
6 changed files with 628 additions and 22 deletions
|
|
@ -1,16 +1,20 @@
|
|||
from typing import Optional, List
|
||||
from typing import Optional, List, Any
|
||||
import logging
|
||||
import secrets
|
||||
import sys
|
||||
import os
|
||||
from datetime import datetime, UTC
|
||||
from fastapi import FastAPI, Request, Response, HTTPException, status
|
||||
from fastapi import FastAPI, Request, Response, status
|
||||
from fastapi.responses import RedirectResponse
|
||||
from contextlib import asynccontextmanager
|
||||
from simple_openid_connect.client import OpenidClient
|
||||
from simple_openid_connect.data import TokenSuccessResponse
|
||||
from cachetools import TTLCache
|
||||
from aiohttp import BasicAuth
|
||||
import asyncio
|
||||
|
||||
from dooris_api import deps, models, exceptions
|
||||
from dooris_api.ccujack import CCUJackClient
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
|
@ -32,6 +36,8 @@ async def lifespan(app: FastAPI):
|
|||
)
|
||||
|
||||
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"]))
|
||||
|
||||
yield
|
||||
|
||||
|
|
@ -106,19 +112,64 @@ async def login_callback(req: Request, resp: Response, oidc_client: deps.OpenidC
|
|||
logger.debug("successfully authenticated user")
|
||||
return str(req.url_for("get-user-info"))
|
||||
else:
|
||||
logger.debu("could not authenticate user because of OIDC error; redirecting to error page with error messages intact")
|
||||
logger.debug("could not authenticate user because of OIDC error; redirecting to error page with error messages intact")
|
||||
return f"/auth/login-error?{req.query_params}"
|
||||
|
||||
|
||||
@app.get("/api/doors/", tags=["doors"], responses={status.HTTP_401_UNAUTHORIZED: {"model": models.HttpProblemDetail}})
|
||||
async def list_doors(cache: deps.Cache, _user: deps.CurrentUser) -> List[models.Door]:
|
||||
return [
|
||||
models.Door(name="door1", description="A static door for testing", status="unknown"),
|
||||
models.Door(name="door2", description="another static door for testing", status="unknown"),
|
||||
]
|
||||
@app.get("/api/locks/", tags=["locks"], responses={status.HTTP_401_UNAUTHORIZED: {"model": models.HttpProblemDetail}})
|
||||
async def list_locks(ccujack: deps.CCUJackClient) -> List[models.Lock]:
|
||||
locks = await ccujack.find_locks()
|
||||
|
||||
# TODO: Properly associate parameters with their values
|
||||
# values = await asyncio.gather(*[
|
||||
# ccujack.query_param_value(f"{i_lock.address}/{i_channel.index}/{i_param.id}/~pv")
|
||||
# for i_lock, lock_channels in locks
|
||||
# for i_channel, channel_params in lock_channels
|
||||
# for i_param in channel_params
|
||||
# ])
|
||||
|
||||
# assemble result objects
|
||||
result = []
|
||||
for i_lock, lock_channels in locks:
|
||||
status_data = dict()
|
||||
for i_channel, channel_params in lock_channels:
|
||||
for i_param in channel_params:
|
||||
value = await ccujack.query_param_value(f"{i_lock.address}/{i_channel.index}/{i_param.id}")
|
||||
match i_param.id:
|
||||
case "LOCK_STATE":
|
||||
match value.v:
|
||||
case 0:
|
||||
status_data["lock_state"] = "unknown"
|
||||
case 1:
|
||||
status_data["lock_state"] = "locked"
|
||||
case 2:
|
||||
status_data["lock_state"] = "unlocked"
|
||||
case "ACTIVITY_STATE":
|
||||
match value.v:
|
||||
case 1:
|
||||
status_data["activity_state"] = "unlocking"
|
||||
case 2:
|
||||
status_data["activity_state"] = "locking"
|
||||
case 3:
|
||||
status_data["activity_state"] = "stable"
|
||||
case "LOCK_TARGET_LEVEL":
|
||||
match value.v:
|
||||
case 0:
|
||||
status_data["lock_target_level"] = "locked"
|
||||
case 1:
|
||||
status_data["lock_target_level"] = "unlocked"
|
||||
case 2:
|
||||
status_data["lock_target_level"] = "open"
|
||||
case "LOW_BAT":
|
||||
status_data["is_low_battery"] = value.v
|
||||
case "ERROR_JAMMED":
|
||||
status_data["is_error_jammed"] = value.v
|
||||
case "UNREACH":
|
||||
status_data["is_unreachable"] = value.v
|
||||
|
||||
result.append(models.Lock(name=i_lock.title, status=models.LockStatus(**status_data)))
|
||||
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@app.get("/api/doors/{name}", tags=["doors"], responses={status.HTTP_404_NOT_FOUND: {"model": models.HttpProblemDetail}, status.HTTP_401_UNAUTHORIZED: {"model": models.HttpProblemDetail}})
|
||||
async def get_door(name: str, req: Request, cache: deps.Cache, _user: deps.CurrentUser) -> Optional[models.Door]:
|
||||
raise exceptions.HttpProblemException(models.HttpProblemDetail.new_door_not_found(name, req.url))
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue