diff --git a/src/c3nav/control/models.py b/src/c3nav/control/models.py index 856e25aa..9549d18c 100644 --- a/src/c3nav/control/models.py +++ b/src/c3nav/control/models.py @@ -44,6 +44,7 @@ class UserPermissions(models.Model): nonpublic_themes = models.BooleanField(default=False, verbose_name=_('show non-public themes in theme selector')) quests: list[str] = SchemaField(schema=list[str], default=list) impolite_quests = models.BooleanField(default=False, verbose_name=_('dont say thanks after completing a quest')) + passive_ap_name_scanning = models.BooleanField(default=False, verbose_name=_('passive ap name scanning')) class Meta: verbose_name = _('User Permissions') diff --git a/src/c3nav/mapdata/tasks.py b/src/c3nav/mapdata/tasks.py index f264d9ab..8e1aa185 100644 --- a/src/c3nav/mapdata/tasks.py +++ b/src/c3nav/mapdata/tasks.py @@ -54,3 +54,27 @@ def delete_map_cache_key(self, cache_key): if hasattr(cache, 'keys'): for key in cache.keys(f'*{cache_key}*'): cache.delete(key) + + +@app.task(bind=True, max_retries=10) +def update_ap_names_bssid_mapping(self, map_name, user): + from c3nav.mapdata.models.geometry.space import RangingBeacon + todo = [] + for beacon in RangingBeacon.objects.filter(ap_name__in=map_name.keys(), + beacon_type=RangingBeacon.BeaconType.EVENT_WIFI): + print(beacon, "add ssids", set(map_name[beacon.ap_name])) + if set(map_name[beacon.ap_name]) - set(beacon.addresses): + todo.append((beacon, list(set(beacon.addresses) | set(map_name[beacon.ap_name])))) + + if todo: + from c3nav.editor.models import ChangeSet + from c3nav.editor.views.base import within_changeset + changeset = ChangeSet() + changeset.author = user + with within_changeset(changeset=changeset, user=user) as locked_changeset: + for beacon, addresses in todo: + beacon.addresses = addresses + beacon.save() + with changeset.lock_to_edit() as locked_changeset: + locked_changeset.title = 'passive update bssids' + locked_changeset.apply(user) diff --git a/src/c3nav/routing/api/positioning.py b/src/c3nav/routing/api/positioning.py index 017a4283..31827c44 100644 --- a/src/c3nav/routing/api/positioning.py +++ b/src/c3nav/routing/api/positioning.py @@ -8,6 +8,7 @@ from pydantic_extra_types.mac_address import MacAddress from c3nav.api.auth import auth_responses from c3nav.api.schema import BaseSchema +from c3nav.editor.models import ChangeSet from c3nav.mapdata.models.access import AccessPermission from c3nav.mapdata.schemas.models import CustomLocationSchema from c3nav.mapdata.utils.cache.stats import increment_cache_key @@ -40,7 +41,7 @@ class PositioningResult(BaseSchema): description="determine position based on wireless measurements " "(including ranging, if available)", response={200: PositioningResult, **auth_responses}) -def get_position(request, parameters: LocateRequestSchema): +def get_position(request, parameters: LocateRequestSchema, update_ap_names_bssid_mapping=None): try: location = Locator.load().locate(parameters.wifi_peers, permissions=AccessPermission.get_for_request(request)) @@ -51,6 +52,15 @@ def get_position(request, parameters: LocateRequestSchema): # todo: validation error, seriously? this shouldn't happen anyways raise + if request.user_permissions.passive_ap_name_scanning: + bssid_mapping = {} + for peer in parameters.wifi_peers: + if not peer.ap_name: + continue + bssid_mapping.setdefault(peer.ap_name, set()).add(peer.bssid) + if bssid_mapping: + update_ap_names_bssid_mapping.delay(map_name=bssid_mapping, user=request.user) + return { "location": location }