Skip to content

Commit

Permalink
Feature/beacons backend (#726)
Browse files Browse the repository at this point in the history
* Beacon state database model created

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Beacons backend

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Added route to app, fixed return value as tuple

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Small fix in alerts on_next call

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Set any newly saved beacon state to next event for subscription

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Fix typo on subs call and raise HTTP exception when state is not found

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Lint

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

* Fix parameter name

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>

---------

Signed-off-by: Aaron Chong <aaronchongth@gmail.com>
  • Loading branch information
aaronchongth authored Jul 18, 2023
1 parent 4634cc5 commit fd92cb3
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 2 deletions.
3 changes: 3 additions & 0 deletions packages/api-server/api_server/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ async def on_sio_connect(sid: str, _environ: dict, auth: Optional[dict] = None):
app.include_router(
routes.alerts_router, prefix="/alerts", dependencies=[Depends(user_dep)]
)
app.include_router(
routes.beacons_router, prefix="/beacons", dependencies=[Depends(user_dep)]
)
app.include_router(
routes.building_map_router, prefix="/building_map", dependencies=[Depends(user_dep)]
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .alerts import *
from .authorization import *
from .beacons import *
from .building_map import BuildingMap
from .dispenser_state import DispenserState
from .door_state import DoorState
Expand Down
14 changes: 14 additions & 0 deletions packages/api-server/api_server/models/tortoise_models/beacons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
from tortoise.contrib.pydantic.creator import pydantic_model_creator
from tortoise.fields import BooleanField, CharField
from tortoise.models import Model


class BeaconState(Model):
id = CharField(255, pk=True)
online = BooleanField(index=True)
category = CharField(255, null=True, index=True)
activated = BooleanField(index=True)
level = CharField(255, null=True, index=True)


BeaconStatePydantic = pydantic_model_creator(BeaconState)
1 change: 1 addition & 0 deletions packages/api-server/api_server/rmf_io/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
RmfEvents,
TaskEvents,
alert_events,
beacon_events,
fleet_events,
rmf_events,
task_events,
Expand Down
8 changes: 8 additions & 0 deletions packages/api-server/api_server/rmf_io/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,11 @@ def __init__(self):


alert_events = AlertEvents()


class BeaconEvents:
def __init__(self):
self.beacons = Subject() # Beacons


beacon_events = BeaconEvents()
1 change: 1 addition & 0 deletions packages/api-server/api_server/routes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from .admin import router as admin_router
from .alerts import router as alerts_router
from .beacons import router as beacons_router
from .building_map import router as building_map_router
from .dispensers import router as dispensers_router
from .doors import router as doors_router
Expand Down
54 changes: 54 additions & 0 deletions packages/api-server/api_server/routes/beacons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
from typing import List

from fastapi import HTTPException
from rx import operators as rxops

from api_server.fast_io import FastIORouter, SubscriptionRequest
from api_server.models import tortoise_models as ttm
from api_server.rmf_io import beacon_events

router = FastIORouter(tags=["Beacons"])


@router.sub("", response_model=ttm.BeaconStatePydantic)
async def sub_beacons(_req: SubscriptionRequest):
return beacon_events.beacons.pipe(rxops.filter(lambda x: x is not None))


@router.get("", response_model=List[ttm.BeaconStatePydantic])
async def get_beacons():
beacons = await ttm.BeaconState.all()
return [await ttm.BeaconStatePydantic.from_tortoise_orm(a) for a in beacons]


@router.get("/{beacon_id}", response_model=ttm.BeaconStatePydantic)
async def get_beacon(beacon_id: str):
beacon_state = await ttm.BeaconState.get_or_none(id=beacon_id)
if beacon_state is None:
raise HTTPException(404, f"Beacon with ID {beacon_id} not found")
beacon_state_pydantic = await ttm.BeaconStatePydantic.from_tortoise_orm(
beacon_state
)
return beacon_state_pydantic


@router.post("", status_code=201, response_model=ttm.BeaconStatePydantic)
async def save_beacon_state(
beacon_id: str, online: bool, category: str, activated: bool, level: str
):
beacon_state, _ = await ttm.BeaconState.update_or_create(
{
"online": online,
"category": category,
"activated": activated,
"level": level,
},
id=beacon_id,
)
if beacon_state is None:
raise HTTPException(404, f"Could not save beacon state with ID {beacon_id}")
beacon_state_pydantic = await ttm.BeaconStatePydantic.from_tortoise_orm(
beacon_state
)
beacon_events.beacons.on_next(beacon_state_pydantic)
return beacon_state_pydantic
6 changes: 4 additions & 2 deletions packages/api-server/api_server/routes/internal.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ async def process_msg(msg: Dict[str, Any], fleet_repo: FleetRepository) -> None:

if task_state.status == mdl.Status.completed:
alert = await alert_repo.create_alert(task_state.booking.id, "task")
alert_events.alerts.on_next(alert)
if alert is not None:
alert_events.alerts.on_next(alert)

elif payload_type == "task_log_update":
task_log = mdl.TaskEventLog(**msg["data"])
Expand All @@ -68,7 +69,8 @@ async def process_msg(msg: Dict[str, Any], fleet_repo: FleetRepository) -> None:

if task_log_has_error(task_log):
alert = await alert_repo.create_alert(task_log.task_id, "task")
alert_events.alerts.on_next(alert)
if alert is not None:
alert_events.alerts.on_next(alert)

elif payload_type == "fleet_state_update":
fleet_state = mdl.FleetState(**msg["data"])
Expand Down

0 comments on commit fd92cb3

Please sign in to comment.