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

[uss_qualifier/netrid/dss/isa_simple] Refactor and complete create case #204

Merged
Merged
4 changes: 3 additions & 1 deletion monitoring/mock_uss/riddp/routes_observation.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@ def riddp_display_data() -> Tuple[str, int]:

# Get ISAs in the DSS
t = arrow.utcnow().datetime
isa_list: FetchedISAs = fetch.isas(view, t, t, rid_version, utm_client)
isa_list: FetchedISAs = fetch.isas(
geo.get_latlngrect_vertices(view), t, t, rid_version, utm_client
)
if not isa_list.success:
msg = f"Error fetching ISAs from DSS: {isa_list.errors}"
logger.error(msg)
Expand Down
4 changes: 2 additions & 2 deletions monitoring/mock_uss/tracer/tracer_poll.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
from monitoring.mock_uss.tracer import context
from monitoring.monitorlib.fetch.rid import FetchedISAs
from monitoring.monitorlib.fetch.scd import FetchedEntities
from monitoring.monitorlib.geo import make_latlng_rect
from monitoring.monitorlib.geo import make_latlng_rect, get_latlngrect_vertices
from monitoring.monitorlib.infrastructure import UTMClientSession
from monitoring.monitorlib.multiprocessing import SynchronizedValue

Expand Down Expand Up @@ -97,7 +97,7 @@ def poll_observation_areas() -> None:

def poll_isas(area: ObservationArea, logger: tracerlog.Logger) -> None:
rid_client = context.get_client(area.f3411.auth_spec, area.f3411.dss_base_url)
box = make_latlng_rect(area.area.volume)
box = get_latlngrect_vertices(make_latlng_rect(area.area.volume))

log_name = "poll_isas"
t0 = datetime.datetime.utcnow()
Expand Down
16 changes: 12 additions & 4 deletions monitoring/monitorlib/fetch/rid.py
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ def has_different_content_than(self, other: Any) -> bool:


def isas(
box: s2sphere.LatLngRect,
area: List[s2sphere.LatLng],
start_time: datetime.datetime,
end_time: datetime.datetime,
rid_version: RIDVersion,
Expand All @@ -862,7 +862,7 @@ def isas(
t1 = rid_version.format_time(end_time)
if rid_version == RIDVersion.f3411_19:
op = v19.api.OPERATIONS[v19.api.OperationID.SearchIdentificationServiceAreas]
area = rid_v1.geo_polygon_string_from_s2(geo.get_latlngrect_vertices(box))
area = rid_v1.geo_polygon_string_from_s2(area)
url = f"{dss_base_url}{op.path}?area={area}&earliest_time={t0}&latest_time={t1}"
return FetchedISAs(
v19_query=fetch.query_and_describe(
Expand All @@ -875,7 +875,7 @@ def isas(
)
elif rid_version == RIDVersion.f3411_22a:
op = v22a.api.OPERATIONS[v22a.api.OperationID.SearchIdentificationServiceAreas]
area = rid_v2.geo_polygon_string_from_s2(geo.get_latlngrect_vertices(box))
area = rid_v2.geo_polygon_string_from_s2(area)
url = f"{dss_base_url}{op.path}?area={area}&earliest_time={t0}&latest_time={t1}"
return FetchedISAs(
v22a_query=fetch.query_and_describe(
Expand Down Expand Up @@ -1162,7 +1162,15 @@ def all_flights(
server_id: Optional[str] = None,
) -> FetchedFlights:
t = datetime.datetime.utcnow()
isa_list = isas(area, t, t, rid_version, session, dss_base_url, server_id=server_id)
isa_list = isas(
geo.get_latlngrect_vertices(area),
t,
t,
rid_version,
session,
dss_base_url,
server_id=server_id,
)

uss_flight_queries: Dict[str, FetchedUSSFlights] = {}
uss_flight_details_queries: Dict[str, FetchedUSSFlightDetails] = {}
Expand Down
8 changes: 8 additions & 0 deletions monitoring/monitorlib/geo.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ class DistanceUnits(str, Enum):


class LatLngPoint(ImplicitDict):
"""Vertex in latitude and longitude"""

lat: float
"""Latitude (degrees)"""

lng: float
"""Longitude (degrees)"""

def as_s2sphere(self) -> s2sphere.LatLng:
return s2sphere.LatLng.from_degrees(self.lat, self.lng)


class Radius(ImplicitDict):
Expand Down
13 changes: 11 additions & 2 deletions monitoring/monitorlib/mutate/rid.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,12 @@
import yaml
from yaml.representer import Representer

from monitoring.monitorlib import fetch, infrastructure, rid_v1, rid_v2
from monitoring.monitorlib import (
fetch,
infrastructure,
rid_v1,
rid_v2,
)


class ChangedSubscription(RIDQuery):
Expand Down Expand Up @@ -327,7 +332,11 @@ def _v22a_response(

@property
def errors(self) -> List[str]:
if self.status_code != 200:
# Tolerate reasonable-but-technically-incorrect code 201
if not (
self.status_code == 200
or (self.mutation == "create" and self.status_code == 201)
):
return ["Failed to mutate ISA ({})".format(self.status_code)]
if self.query.response.json is None:
return ["ISA response did not include valid JSON"]
Expand Down
4 changes: 3 additions & 1 deletion monitoring/monitorlib/rid.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from monitoring.monitorlib import schema_validation
from uas_standards.astm.f3411 import v19, v22a
import uas_standards.astm.f3411.v19.api
import uas_standards.astm.f3411.v19.constants
import uas_standards.astm.f3411.v22a.api
import uas_standards.astm.f3411.v22a.constants
Expand Down Expand Up @@ -202,7 +203,8 @@ def dss_max_subscriptions_per_area(self) -> int:

def flights_url_of(self, base_url: str) -> str:
if self == RIDVersion.f3411_19:
return base_url
flights_path = v19.api.OPERATIONS[v19.api.OperationID.SearchFlights].path
return base_url + flights_path
elif self == RIDVersion.f3411_22a:
flights_path = v22a.api.OPERATIONS[v22a.api.OperationID.SearchFlights].path
return base_url + flights_path
Expand Down
15 changes: 11 additions & 4 deletions monitoring/uss_qualifier/configurations/dev/library/resources.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,19 @@ net_rid:
specification:
base_url: https://uss_qualifier.test.utm/dummy_base_url
footprint:
lat_min: 37.1853
lng_min: -80.6140
lat_max: 37.2148
lng_max: -80.5440
- lat: 37.1853
lng: -80.6140
- lat: 37.2148
lng: -80.6140
- lat: 37.2148
lng: -80.5440
- lat: 37.1853
lng: -80.5440
Comment on lines +35 to +42
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a particular benefit to using a polygon rather than a bounding box?

(I can think of a few: I was just wondering what the benefit is regarding to the tests we do)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes my implementation life easier, and the resource more flexible (notably it would be nice to use it in the DSS interoperability scenario, where specifying the polygon would be needed)

altitude_min: 0
altitude_max: 3048
reference_time: '2023-01-10T00:00:00.123456+00:00'
time_start: '2023-01-10T00:00:01.123456+00:00'
time_end: '2023-01-10T01:00:01.123456+00:00'

net_rid_sims:
adjacent_circular_flights_data:
Expand Down
30 changes: 27 additions & 3 deletions monitoring/uss_qualifier/resources/netrid/service_area.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
from implicitdict import ImplicitDict
from monitoring.monitorlib.geo import LatLngBoundingBox
import datetime
from typing import List

from implicitdict import ImplicitDict, StringBasedDateTime
from monitoring.monitorlib.geo import LatLngPoint

from monitoring.uss_qualifier.resources.resource import Resource

Expand All @@ -12,7 +15,7 @@ class ServiceAreaSpecification(ImplicitDict):

This URL will probably not identify a real resource in tests."""

footprint: LatLngBoundingBox
footprint: List[LatLngPoint]
"""2D outline of service area"""

altitude_min: float = 0
Expand All @@ -21,6 +24,27 @@ class ServiceAreaSpecification(ImplicitDict):
altitude_max: float = 3048
"""Upper altitude bound of service area, meters above WGS84 ellipsoid"""

reference_time: StringBasedDateTime
"""Reference time used to adjust start and end times at runtime"""

time_start: StringBasedDateTime
"""Start time of service area (relative to reference_time)"""

time_end: StringBasedDateTime
"""End time of service area (relative to reference_time)"""

def shifted_time_start(
self, new_reference_time: datetime.datetime
) -> datetime.datetime:
dt = new_reference_time - self.reference_time.datetime
return self.time_start.datetime + dt

def shifted_time_end(
self, new_reference_time: datetime.datetime
) -> datetime.datetime:
dt = new_reference_time - self.reference_time.datetime
return self.time_end.datetime + dt


class ServiceAreaResource(Resource[ServiceAreaSpecification]):
specification: ServiceAreaSpecification
Expand Down
Loading