first commit
This commit is contained in:
@@ -0,0 +1,118 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
||||
|
||||
|
||||
class GeoAntenna(BaseModel):
|
||||
lat: float
|
||||
lng: float
|
||||
antenna_height_m: float = Field(default=2.0, ge=0)
|
||||
|
||||
@field_validator("lat")
|
||||
@classmethod
|
||||
def validate_lat(cls, value: float) -> float:
|
||||
if not -90 <= value <= 90:
|
||||
raise ValueError("lat must be between -90 and 90")
|
||||
return value
|
||||
|
||||
@field_validator("lng")
|
||||
@classmethod
|
||||
def validate_lng(cls, value: float) -> float:
|
||||
if not -180 <= value <= 180:
|
||||
raise ValueError("lng must be between -180 and 180")
|
||||
return value
|
||||
|
||||
|
||||
class LinkRequest(BaseModel):
|
||||
model_config = ConfigDict(populate_by_name=True)
|
||||
|
||||
from_: GeoAntenna = Field(alias="from")
|
||||
to: GeoAntenna
|
||||
frequency_mhz: float = Field(gt=0)
|
||||
fresnel_clearance: float = Field(default=0.6, ge=0, le=1)
|
||||
tx_power_dbm: float = 20.0
|
||||
rx_sensitivity_dbm: float = -137.0
|
||||
sample_step_m: float = Field(default=30.0, gt=0)
|
||||
|
||||
|
||||
class LinkBudget(BaseModel):
|
||||
tx_power_dbm: float
|
||||
rx_sensitivity_dbm: float
|
||||
margin_db: float
|
||||
status: Literal["good", "marginal", "poor"]
|
||||
|
||||
|
||||
class Obstacle(BaseModel):
|
||||
lat: float
|
||||
lng: float
|
||||
distance_from_start_m: float
|
||||
terrain_height_m: float
|
||||
canopy_height_m: float
|
||||
building_height_m: float
|
||||
total_height_m: float
|
||||
fresnel_radius_m: float
|
||||
clearance_m: float
|
||||
|
||||
|
||||
class PathProfilePoint(BaseModel):
|
||||
distance_m: float
|
||||
lat: float
|
||||
lng: float
|
||||
terrain_m: float
|
||||
canopy_m: float
|
||||
building_m: float
|
||||
total_m: float
|
||||
los_height_m: float
|
||||
fresnel_radius_m: float
|
||||
clearance_m: float
|
||||
|
||||
|
||||
class LinkResponse(BaseModel):
|
||||
distance_m: float
|
||||
los: bool
|
||||
fresnel_clear: bool
|
||||
free_space_loss_db: float
|
||||
link_budget: LinkBudget
|
||||
obstacles: list[Obstacle]
|
||||
path_profile: list[PathProfilePoint]
|
||||
|
||||
|
||||
class CoverageRequest(BaseModel):
|
||||
origin: GeoAntenna
|
||||
frequency_mhz: float = Field(gt=0)
|
||||
radius_m: float = Field(gt=0)
|
||||
resolution_m: float = Field(gt=0)
|
||||
fresnel_clearance: float = Field(default=0.6, ge=0, le=1)
|
||||
tx_power_dbm: float = 20.0
|
||||
rx_sensitivity_dbm: float = -137.0
|
||||
sample_step_m: float = Field(default=30.0, gt=0)
|
||||
|
||||
|
||||
class CoverageResponse(BaseModel):
|
||||
origin: GeoAntenna
|
||||
coverage_geojson: dict[str, Any]
|
||||
|
||||
|
||||
class ElevationProfilePoint(BaseModel):
|
||||
distance_m: float
|
||||
lat: float
|
||||
lng: float
|
||||
terrain_m: float
|
||||
|
||||
|
||||
class ElevationProfileResponse(BaseModel):
|
||||
distance_m: float
|
||||
path_profile: list[ElevationProfilePoint]
|
||||
|
||||
|
||||
class DataLayersHealth(BaseModel):
|
||||
srtm: bool
|
||||
canopy: bool
|
||||
buildings: bool
|
||||
|
||||
|
||||
class HealthResponse(BaseModel):
|
||||
status: Literal["ok", "degraded"]
|
||||
data_layers: DataLayersHealth
|
||||
Reference in New Issue
Block a user