team-3/src/c3nav/mapdata/management/commands/importpoc.py

100 lines
3.4 KiB
Python
Raw Normal View History

2024-12-28 15:57:16 +01:00
from typing import Literal
2024-12-28 14:59:09 +01:00
import requests
from django.conf import settings
from django.core.management.base import BaseCommand
from pydantic import BaseModel
2024-12-28 15:57:16 +01:00
from pydantic.type_adapter import TypeAdapter
from pydantic_extra_types.mac_address import MacAddress
2024-12-28 14:59:09 +01:00
from shapely import distance
2024-12-28 15:57:16 +01:00
from shapely.geometry import shape, Point
2024-12-28 14:59:09 +01:00
2024-12-28 15:57:16 +01:00
from c3nav.api.schema import PointSchema
from c3nav.mapdata.models import MapUpdate, Level
2024-12-28 14:59:09 +01:00
from c3nav.mapdata.models.geometry.space import RangingBeacon
from c3nav.mapdata.utils.cache.changes import changed_geometries
from c3nav.mapdata.utils.geometry import unwrap_geom
2024-12-28 15:57:16 +01:00
from c3nav.mapdata.utils.importer import PointImportHelper
2024-12-28 14:59:09 +01:00
2024-12-28 15:57:16 +01:00
class PocImportItemProperties(BaseModel):
level: str
mac: MacAddress
name: str
class PocImportItem(BaseModel):
2024-12-28 14:59:09 +01:00
"""
Something imported from the NOC
"""
2024-12-28 16:06:03 +01:00
type: Literal["Feature"] = "Feature"
2024-12-28 15:57:16 +01:00
geometry: PointSchema
properties: PocImportItemProperties
2024-12-28 14:59:09 +01:00
class Command(BaseCommand):
help = 'import APs from noc'
def handle(self, *args, **options):
2024-12-28 16:06:03 +01:00
r = requests.get(settings.POC_API_BASE+"/antenna-locations", headers={'ApiKey': settings.POC_API_SECRET})
2024-12-28 14:59:09 +01:00
r.raise_for_status()
2024-12-28 15:57:16 +01:00
items = TypeAdapter(list[PocImportItem]).validate_python(r.json())
2024-12-28 14:59:09 +01:00
with MapUpdate.lock():
changed_geometries.reset()
self.do_import(items)
MapUpdate.objects.create(type='importnoc')
2024-12-28 15:57:16 +01:00
def do_import(self, items: list[PocImportItem]):
import_helper = PointImportHelper()
2024-12-28 14:59:09 +01:00
beacons_so_far: dict[str, RangingBeacon] = {
2024-12-28 15:57:16 +01:00
**{m.import_tag: m for m in RangingBeacon.objects.filter(import_tag__startswith="poc:",
beacon_type=RangingBeacon.BeaconType.DECT)},
2024-12-28 14:59:09 +01:00
}
2024-12-28 15:57:16 +01:00
levels_by_level_index = {str(level.level_index): level for level in Level.objects.all()}
2024-12-28 14:59:09 +01:00
2024-12-28 15:57:16 +01:00
for item in items:
import_tag = f"poc:{item.properties.name}"
2024-12-28 14:59:09 +01:00
# determine geometry
2024-12-28 16:06:03 +01:00
level_id = levels_by_level_index[item.properties.level].pk
2024-12-28 14:59:09 +01:00
2024-12-28 15:57:16 +01:00
point: Point = shape(item.geometry.model_dump()) # nowa
2024-12-28 14:59:09 +01:00
2024-12-28 15:57:16 +01:00
new_space, point = import_helper.get_point_and_space(
level_id=level_id,
point=point,
name=item.properties.name,
)
if new_space is None:
continue
2024-12-28 14:59:09 +01:00
# find existing location
result = beacons_so_far.pop(import_tag, None)
# build resulting object
altitude_quest = True
if not result:
2024-12-28 17:58:28 +01:00
result = RangingBeacon(import_tag=import_tag, beacon_type=RangingBeacon.BeaconType.DECT)
2024-12-28 14:59:09 +01:00
else:
2024-12-28 15:57:16 +01:00
if result.space == new_space and distance(unwrap_geom(result.geometry), point) < 0.03:
2024-12-28 14:59:09 +01:00
continue
2024-12-28 15:57:16 +01:00
if result.space == new_space and distance(unwrap_geom(result.geometry), point) < 0.20:
2024-12-28 14:59:09 +01:00
altitude_quest = False
2024-12-28 15:57:16 +01:00
result.ap_name = item.properties.name
result.addresses = [item.properties.mac.lower()]
2024-12-28 14:59:09 +01:00
result.space = new_space
2024-12-28 15:57:16 +01:00
result.geometry = point
2024-12-28 14:59:09 +01:00
result.altitude = 0
if altitude_quest:
result.altitude_quest = True
result.save()
for import_tag, location in beacons_so_far.items():
location.delete()
print(f"NOTE: {import_tag} was deleted")