Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hammer/fire alarm #934

Merged
merged 8 commits into from
May 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/api-client/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
DispenserState,
DoorHealth,
DoorState,
FireAlarmTriggerState,
FleetState,
IngestorHealth,
IngestorState,
Expand Down Expand Up @@ -108,6 +109,10 @@ export class SioClient {
subscribeDeliveryAlerts(listener: Listener<DeliveryAlert>): Subscription {
return this.subscribe<DeliveryAlert>(`/delivery_alerts`, listener);
}

subscribeFireAlarmTrigger(listener: Listener<FireAlarmTriggerState>): Subscription {
return this.subscribe<FireAlarmTriggerState>('/fire_alarm_trigger', listener);
}
}

export * from './openapi';
179 changes: 175 additions & 4 deletions packages/api-client/lib/openapi/api.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/api-client/lib/version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@ import { version as rmfModelVer } from 'rmf-models';

export const version = {
rmfModels: rmfModelVer,
rmfServer: '55378951e4ae4161a348a1c106837076c4c56a72',
rmfServer: 'fd45675f94b75df6845303db4f45276d0998f3e6',
openapiGenerator: '6.2.1',
};
45 changes: 44 additions & 1 deletion packages/api-client/schema/index.ts

Large diffs are not rendered by default.

43 changes: 43 additions & 0 deletions packages/api-server/api_server/gateway.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import base64
import hashlib
import logging
from datetime import datetime
from typing import Any, List, Optional

import rclpy
Expand Down Expand Up @@ -33,13 +34,15 @@
from rmf_task_msgs.srv import CancelTask as RmfCancelTask
from rmf_task_msgs.srv import SubmitTask as RmfSubmitTask
from rosidl_runtime_py.convert import message_to_ordereddict
from std_msgs.msg import Bool as BoolMsg

from .models import (
BeaconState,
BuildingMap,
DeliveryAlert,
DispenserState,
DoorState,
FireAlarmTriggerState,
IngestorState,
LiftState,
)
Expand Down Expand Up @@ -115,6 +118,17 @@ def __init__(self, cached_files: CachedFilesRepository):
),
)

self._fire_alarm_trigger = ros_node().create_publisher(
BoolMsg,
"fire_alarm_trigger",
rclpy.qos.QoSProfile(
history=rclpy.qos.HistoryPolicy.KEEP_LAST,
depth=10,
reliability=rclpy.qos.ReliabilityPolicy.RELIABLE,
durability=rclpy.qos.DurabilityPolicy.TRANSIENT_LOCAL,
),
)

self.cached_files = cached_files
self._subscriptions: List[Subscription] = []

Expand Down Expand Up @@ -234,6 +248,30 @@ def handle_delivery_alert(delivery_alert: DeliveryAlert):
)
self._subscriptions.append(delivery_alert_request_sub)

def handle_fire_alarm_trigger(fire_alarm_trigger_msg: BoolMsg):
if fire_alarm_trigger_msg.data:
logging.info("Fire alarm triggered")
else:
logging.info("Fire alarm trigger reset")
fire_alarm_trigger_state = FireAlarmTriggerState(
unix_millis_time=round(datetime.now().timestamp() * 1000),
trigger=fire_alarm_trigger_msg.data,
)
rmf_events.fire_alarm_trigger.on_next(fire_alarm_trigger_state)

fire_alarm_trigger_sub = ros_node().create_subscription(
BoolMsg,
"fire_alarm_trigger",
handle_fire_alarm_trigger,
rclpy.qos.QoSProfile(
history=rclpy.qos.HistoryPolicy.KEEP_LAST,
depth=10,
reliability=rclpy.qos.ReliabilityPolicy.RELIABLE,
durability=rclpy.qos.DurabilityPolicy.TRANSIENT_LOCAL,
),
)
self._subscriptions.append(fire_alarm_trigger_sub)

@staticmethod
def now() -> Optional[RosTime]:
"""
Expand Down Expand Up @@ -304,6 +342,11 @@ def manual_release_mutex_groups(
msg.robot = robot
self._mutex_group_release.publish(msg)

def reset_fire_alarm_trigger(self):
reset_msg = BoolMsg()
reset_msg.data = False
self._fire_alarm_trigger.publish(reset_msg)


_rmf_gateway: RmfGateway

Expand Down
7 changes: 7 additions & 0 deletions packages/api-server/api_server/models/building_map.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import List

from pydantic import BaseModel

from . import tortoise_models as ttm
from .ros_pydantic import rmf_building_map_msgs

Expand All @@ -25,3 +27,8 @@ async def save(self) -> None:
if m.id_ != self.name:
await m.delete()
await ttm.BuildingMap.update_or_create({"data": self.dict()}, id_=self.name)


class FireAlarmTriggerState(BaseModel):
unix_millis_time: int
trigger: bool
3 changes: 3 additions & 0 deletions packages/api-server/api_server/rmf_io/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ def __init__(self):
self.building_map = BehaviorSubject(None) # Optional[BuildingMap]
self.beacons = Subject() # BeaconState
self.delivery_alerts = Subject() # ttm.DeliveryAlertPydantic
self.fire_alarm_trigger = BehaviorSubject(
None
) # Optional[FireAlarmTriggerState]


rmf_events = RmfEvents()
Expand Down
32 changes: 31 additions & 1 deletion packages/api-server/api_server/routes/building_map.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
from datetime import datetime

from fastapi import Depends, HTTPException
from rx import operators as rxops

from api_server.fast_io import FastIORouter, SubscriptionRequest
from api_server.models import BuildingMap
from api_server.gateway import rmf_gateway
from api_server.logging import LoggerAdapter, get_logger
from api_server.models import BuildingMap, FireAlarmTriggerState
from api_server.repositories import RmfRepository
from api_server.rmf_io import rmf_events

Expand All @@ -23,3 +27,29 @@ async def get_building_map(rmf_repo: RmfRepository = Depends(RmfRepository)):
@router.sub("", response_model=BuildingMap)
def sub_building_map(_req: SubscriptionRequest):
return rmf_events.building_map.pipe(rxops.filter(lambda x: x is not None))


@router.sub("/fire_alarm_trigger", response_model=FireAlarmTriggerState)
async def sub_fire_alarm_trigger(_req: SubscriptionRequest):
return rmf_events.fire_alarm_trigger.pipe(rxops.filter(lambda x: x is not None))


@router.get("/previous_fire_alarm_trigger", response_model=FireAlarmTriggerState)
async def get_previous_fire_alarm_trigger():
previous_trigger = rmf_events.fire_alarm_trigger.value
if previous_trigger is None:
raise HTTPException(404, "previous fire alarm trigger not available")
return previous_trigger


@router.post("/reset_fire_alarm_trigger", response_model=FireAlarmTriggerState)
async def reset_fire_alarm_trigger(
logger: LoggerAdapter = Depends(get_logger),
):
# TODO: enforce with authz
logger.info("Fire alarm trigger reset requested")
rmf_gateway().reset_fire_alarm_trigger()
fire_alarm_trigger_state = FireAlarmTriggerState(
unix_millis_time=round(datetime.now().timestamp() * 1000), trigger=False
)
return fire_alarm_trigger_state
35 changes: 34 additions & 1 deletion packages/api-server/api_server/routes/test_building_map.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
from api_server.rmf_io import rmf_events
from api_server.test import AppFixture, make_building_map, try_until
from api_server.test import (
AppFixture,
make_building_map,
make_fire_alarm_trigger,
try_until,
)


class TestBuildingMapRoute(AppFixture):
Expand All @@ -13,3 +18,31 @@ def test_get_building_map(self):
self.assertEqual(200, resp.status_code)
result_map = resp.json()
self.assertEqual(building_map.name, result_map["name"])

def test_get_previous_fire_alarm_trigger(self):
true_trigger = make_fire_alarm_trigger(True)
rmf_events.fire_alarm_trigger.on_next(true_trigger)
resp = self.client.get("/building_map/previous_fire_alarm_trigger")
self.assertEqual(200, resp.status_code)
result = resp.json()
self.assertTrue(result["trigger"])

false_trigger = make_fire_alarm_trigger(False)
rmf_events.fire_alarm_trigger.on_next(false_trigger)
resp = self.client.get("/building_map/previous_fire_alarm_trigger")
self.assertEqual(200, resp.status_code)
result = resp.json()
self.assertFalse(result["trigger"])

def test_reset_fire_alarm_trigger(self):
true_trigger = make_fire_alarm_trigger(True)
rmf_events.fire_alarm_trigger.on_next(true_trigger)
resp = self.client.get("/building_map/previous_fire_alarm_trigger")
self.assertEqual(200, resp.status_code)
result = resp.json()
self.assertTrue(result["trigger"])

resp = self.client.post("/building_map/reset_fire_alarm_trigger")
self.assertEqual(200, resp.status_code)
result = resp.json()
self.assertFalse(result["trigger"])
5 changes: 5 additions & 0 deletions packages/api-server/api_server/test/test_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
Door,
DoorMode,
DoorState,
FireAlarmTriggerState,
FleetLog,
FleetState,
IngestorState,
Expand Down Expand Up @@ -67,6 +68,10 @@ def make_building_map():
)


def make_fire_alarm_trigger(trigger: bool = True):
return FireAlarmTriggerState(unix_millis_time=1000, trigger=trigger)


def make_door_state(name: str, mode: int = RmfDoorMode.MODE_CLOSED) -> DoorState:
return DoorState(
door_name=name,
Expand Down
Loading
Loading