From 24864523a9f48ff699f85ec04ee8265462b7614e Mon Sep 17 00:00:00 2001 From: Mahyar Date: Mon, 11 Aug 2025 13:58:49 +0200 Subject: [PATCH] feat: extend webapp endpoints --- contrib/README.rst | 11 +++++++++++ contrib/labgrid-webapp | 44 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/contrib/README.rst b/contrib/README.rst index d770cdebd..b7349833e 100644 --- a/contrib/README.rst +++ b/contrib/README.rst @@ -27,6 +27,10 @@ Quick Start venv $ ./contrib/labgrid-webapp INFO: Available routes: INFO: - /labgrid/graph + INFO: - /labgrid/resources + INFO: - /labgrid/places + INFO: - /labgrid/places/{name}/acquire + INFO: - /labgrid/places/{name}/release INFO: Started server process [2378028] INFO: Waiting for application startup. INFO: Application startup complete. @@ -40,4 +44,11 @@ By default the application will start on port 8800. To see the graph, go to http://0.0.0.0:8800/labgrid/graph +Other endpoints provide coordinator data and basic control: + +- http://0.0.0.0:8800/labgrid/resources +- http://0.0.0.0:8800/labgrid/places +- POST http://0.0.0.0:8800/labgrid/places/{name}/acquire +- POST http://0.0.0.0:8800/labgrid/places/{name}/release + See http://0.0.0.0:8800/docs for more information on available endpoints. diff --git a/contrib/labgrid-webapp b/contrib/labgrid-webapp index e78976ad1..302b90ff1 100755 --- a/contrib/labgrid-webapp +++ b/contrib/labgrid-webapp @@ -7,12 +7,14 @@ import sys from typing import Dict import graphviz +import grpc import uvicorn -from fastapi import FastAPI +from fastapi import FastAPI, HTTPException from fastapi.responses import Response from labgrid.remote.client import ClientSession, start_session from labgrid.remote.common import Place +from labgrid.remote.generated import labgrid_coordinator_pb2 from labgrid.resource import Resource from labgrid.util.proxy import proxymanager @@ -114,6 +116,46 @@ def main(): svg = await do_graph(session) return Response(content=svg, media_type='image/svg+xml') + @app.get('/labgrid/resources') + async def list_resources() -> Dict[str, Dict]: + '''Return all resources known to the coordinator.''' + await session.sync_with_coordinator() + return session.resources + + @app.get('/labgrid/places') + async def list_places() -> Dict[str, Dict]: + '''Return all places known to the coordinator.''' + await session.sync_with_coordinator() + return { + name: { + 'acquired': place.acquired, + 'tags': place.tags, + } + for name, place in session.places.items() + } + + @app.post('/labgrid/places/{name}/acquire') + async def acquire_place(name: str): + '''Acquire the specified place.''' + request = labgrid_coordinator_pb2.AcquirePlaceRequest(placename=name) + try: + await session.stub.AcquirePlace(request) + await session.sync_with_coordinator() + except grpc.aio.AioRpcError as exc: + raise HTTPException(status_code=400, detail=exc.details()) from exc + return {'status': 'acquired', 'place': name} + + @app.post('/labgrid/places/{name}/release') + async def release_place(name: str): + '''Release the specified place.''' + request = labgrid_coordinator_pb2.ReleasePlaceRequest(placename=name) + try: + await session.stub.ReleasePlace(request) + await session.sync_with_coordinator() + except grpc.aio.AioRpcError as exc: + raise HTTPException(status_code=400, detail=exc.details()) from exc + return {'status': 'released', 'place': name} + parser = argparse.ArgumentParser( description='Labgrid webapp', formatter_class=argparse.RawDescriptionHelpFormatter,