working get_load endpoint

This commit is contained in:
Laura Klünder 2024-12-29 20:01:53 +01:00
parent c2a7a4a451
commit a2f1296bd5
3 changed files with 83 additions and 4 deletions

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-12-29 18:36
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('api', '0004_alter_secret_name'),
]
operations = [
migrations.AddField(
model_name='secret',
name='scope_load',
field=models.BooleanField(default=False, verbose_name='load write access'),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 5.0.8 on 2024-12-29 18:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('control', '0019_userpermissions_passive_ap_name_scanning'),
]
operations = [
migrations.AddField(
model_name='userpermissions',
name='can_write_laod_data',
field=models.BooleanField(default=False, verbose_name='write load data'),
),
]

View file

@ -3,7 +3,7 @@ from typing import Annotated, Union, Optional
from celery import chain from celery import chain
from django.core.serializers.json import DjangoJSONEncoder from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Prefetch from django.db.models import Prefetch, Q
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils import timezone from django.utils import timezone
from ninja import Query from ninja import Query
@ -30,6 +30,7 @@ from c3nav.mapdata.schemas.models import (AnyPositionStatusSchema, FullListableL
SlimListableLocationSchema, SlimLocationSchema, all_location_definitions, SlimListableLocationSchema, SlimLocationSchema, all_location_definitions,
listable_location_definitions, LegendSchema, LegendItemSchema) listable_location_definitions, LegendSchema, LegendItemSchema)
from c3nav.mapdata.schemas.responses import LocationGeometry, WithBoundsSchema, MapSettingsSchema from c3nav.mapdata.schemas.responses import LocationGeometry, WithBoundsSchema, MapSettingsSchema
from c3nav.mapdata.utils.geometry import unwrap_geom
from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request, from c3nav.mapdata.utils.locations import (get_location_by_id_for_request, get_location_by_slug_for_request,
searchable_locations_for_request, visible_locations_for_request) searchable_locations_for_request, visible_locations_for_request)
from c3nav.mapdata.utils.user import can_access_editor from c3nav.mapdata.utils.user import can_access_editor
@ -443,14 +444,56 @@ Room load
@map_api_router.get('/load/', summary="get load group loads", @map_api_router.get('/load/', summary="get load group loads",
response={200: dict[PositiveInt, float], **auth_responses}) response={200: dict[PositiveInt, float], **auth_responses})
def get_load(request): def get_load(request):
# todo: cache load_groups = {g.pk: g for g in LoadGroup.objects.all()}
import random
return {pk: random.randrange(0, 100)/100 for pk in LoadGroup.objects.values_list("pk", flat=True)} # per group
max_values: dict[int, int] = {pk: 0 for pk in load_groups.keys()}
current_values: dict[int, int] = {pk: 0 for pk in load_groups.keys()}
beacons_by_space = {}
for beacon in RangingBeacon.objects.filter(max_observed_num_clients__gt=0):
beacons_by_space.setdefault(beacon.space_id, {})[beacon.pk] = beacon
locationgroups_contribute_to = dict(
LocationGroup.objects.filter(load_contribute_to__isnull=False).values_list("pk", "load_contribute_to")
)
for area in Area.objects.filter((Q(load_contribute_to__isnull=False)
| Q(groups__in=locationgroups_contribute_to.keys()))).prefetch_related("groups"):
contribute_to = set()
if area.load_contribute_to_id:
contribute_to.add(area.load_contribute_to_id)
for group in area.groups.all():
if group.load_contribute_to_id:
contribute_to.add(group.load_contribute_to_id)
for beacon in beacons_by_space.get(area.space_id, {}).values():
if area.geometry.intersects(unwrap_geom(beacon.geometry)):
for load_group_id in contribute_to:
max_values[load_group_id] += beacon.max_observed_num_clients
current_values[load_group_id] += beacon.num_clients
for space in Space.objects.filter((Q(load_contribute_to__isnull=False)
| Q(groups__in=locationgroups_contribute_to.keys()))).prefetch_related("groups"):
contribute_to = set()
if space.load_contribute_to_id:
contribute_to.add(space.load_contribute_to_id)
for group in space.groups.all():
if group.load_contribute_to_id:
contribute_to.add(group.load_contribute_to_id)
for beacon in beacons_by_space.get(space.pk, {}).values():
for load_group_id in contribute_to:
max_values[load_group_id] += beacon.max_observed_num_clients
current_values[load_group_id] += beacon.num_clients
return {
pk: (min(1.0, current_values[pk] / (max_value*0.9)) if max_value else 0)
for pk, max_value in max_values.items()
}
class ApLoadSchema(BaseSchema): class ApLoadSchema(BaseSchema):
aps: dict[str, int] aps: dict[str, int]
@map_api_router.post('/load/', summary="update current load data", response={204: None, **auth_responses}) @map_api_router.post('/load/', summary="update current load data", response={204: None, **auth_responses})
def post_load(request, parameters: ApLoadSchema): def post_load(request, parameters: ApLoadSchema):
# TODO: check if user has permission # TODO: check if user has permission