@mytec: iter1.6.1 ready for testing
This commit is contained in:
@@ -12,6 +12,9 @@ from app.services.reflection_service import reflection_service
|
||||
from app.services.spatial_index import get_spatial_index, SpatialIndex
|
||||
from app.services.water_service import water_service, WaterBody
|
||||
from app.services.vegetation_service import vegetation_service, VegetationArea
|
||||
from app.services.weather_service import weather_service
|
||||
from app.services.indoor_service import indoor_service
|
||||
from app.services.atmospheric_service import atmospheric_service
|
||||
|
||||
|
||||
class CoveragePoint(BaseModel):
|
||||
@@ -24,6 +27,9 @@ class CoveragePoint(BaseModel):
|
||||
building_loss: float # dB
|
||||
reflection_gain: float = 0.0 # dB
|
||||
vegetation_loss: float = 0.0 # dB
|
||||
rain_loss: float = 0.0 # dB
|
||||
indoor_loss: float = 0.0 # dB
|
||||
atmospheric_loss: float = 0.0 # dB
|
||||
|
||||
|
||||
class CoverageSettings(BaseModel):
|
||||
@@ -44,6 +50,17 @@ class CoverageSettings(BaseModel):
|
||||
# Vegetation season
|
||||
season: str = "summer"
|
||||
|
||||
# Weather
|
||||
rain_rate: float = 0.0 # mm/h (0=none, 5=light, 25=heavy)
|
||||
|
||||
# Indoor
|
||||
indoor_loss_type: str = "none" # none, light, medium, heavy, vehicle
|
||||
|
||||
# Atmospheric
|
||||
use_atmospheric: bool = False
|
||||
temperature_c: float = 15.0
|
||||
humidity_percent: float = 50.0
|
||||
|
||||
# Preset
|
||||
preset: Optional[str] = None # fast, standard, detailed, full
|
||||
|
||||
@@ -419,9 +436,38 @@ class CoverageService:
|
||||
if is_over_water:
|
||||
reflection_gain = 3.0 # ~3dB boost over water
|
||||
|
||||
# Rain attenuation
|
||||
rain_loss = 0.0
|
||||
if settings.rain_rate > 0:
|
||||
rain_loss = weather_service.calculate_rain_attenuation(
|
||||
site.frequency,
|
||||
distance / 1000, # km
|
||||
settings.rain_rate
|
||||
)
|
||||
|
||||
# Indoor penetration loss
|
||||
indoor_loss = 0.0
|
||||
if settings.indoor_loss_type != "none":
|
||||
indoor_loss = indoor_service.calculate_indoor_loss(
|
||||
site.frequency,
|
||||
settings.indoor_loss_type
|
||||
)
|
||||
|
||||
# Atmospheric absorption
|
||||
atmo_loss = 0.0
|
||||
if settings.use_atmospheric:
|
||||
atmo_loss = atmospheric_service.calculate_atmospheric_loss(
|
||||
site.frequency,
|
||||
distance / 1000,
|
||||
settings.temperature_c,
|
||||
settings.humidity_percent
|
||||
)
|
||||
|
||||
# Final RSRP
|
||||
rsrp = (site.power + site.gain - path_loss - antenna_loss
|
||||
- terrain_loss - building_loss - veg_loss + reflection_gain)
|
||||
- terrain_loss - building_loss - veg_loss
|
||||
- rain_loss - indoor_loss - atmo_loss
|
||||
+ reflection_gain)
|
||||
|
||||
return CoveragePoint(
|
||||
lat=lat,
|
||||
@@ -432,7 +478,10 @@ class CoverageService:
|
||||
terrain_loss=terrain_loss,
|
||||
building_loss=building_loss,
|
||||
reflection_gain=reflection_gain,
|
||||
vegetation_loss=veg_loss
|
||||
vegetation_loss=veg_loss,
|
||||
rain_loss=rain_loss,
|
||||
indoor_loss=indoor_loss,
|
||||
atmospheric_loss=atmo_loss,
|
||||
)
|
||||
|
||||
def _okumura_hata(
|
||||
|
||||
Reference in New Issue
Block a user