From 7c7b73f488337a8930dd0cc982dc07db710b3505 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Thu, 26 Dec 2024 22:17:27 +0100 Subject: [PATCH] store multiple wifi bssids per beacon --- src/c3nav/editor/api/endpoints.py | 4 ++-- src/c3nav/editor/forms.py | 2 +- .../mapdata/management/commands/findbeacons.py | 4 +++- src/c3nav/mapdata/models/geometry/space.py | 17 ++++++----------- src/c3nav/mesh/api.py | 2 +- src/c3nav/mesh/utils.py | 4 ++-- src/c3nav/routing/locator.py | 4 ++-- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/c3nav/editor/api/endpoints.py b/src/c3nav/editor/api/endpoints.py index 18e1f525..75c11ca2 100644 --- a/src/c3nav/editor/api/endpoints.py +++ b/src/c3nav/editor/api/endpoints.py @@ -170,8 +170,8 @@ def beacons_lookup(request): "name": node.name if node else ("Beacon #%d" % beacon.pk), "point": mapping(beacon.geometry), } - if beacon.wifi_bssid: - wifi_beacons[beacon.wifi_bssid] = beacon_data + for bssid in beacon.wifi_bssids: + wifi_beacons[bssid] = beacon_data if beacon.ibeacon_uuid and beacon.ibeacon_major is not None and beacon.ibeacon_minor is not None: ibeacons.setdefault( str(beacon.ibeacon_uuid), {} diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index cbb6362e..d6b22f21 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -382,7 +382,7 @@ def create_editor_form(editor_model): 'base_altitude', 'intermediate', 'waytype', 'access_restriction', 'default_height', 'door_height', 'outside', "identifyable", 'can_search', 'can_describe', 'geometry', 'single', 'altitude', 'level_index', 'short_label', 'origin_space', 'target_space', 'data', - 'comment', 'slow_down_factor', 'groundaltitude', 'node_number', 'wifi_bssid', 'bluetooth_address', "group", + 'comment', 'slow_down_factor', 'groundaltitude', 'node_number', 'wifi_bssids', 'bluetooth_address', "group", 'ibeacon_uuid', 'ibeacon_major', 'ibeacon_minor', 'uwb_address', 'extra_seconds', 'speed', 'can_report_missing', "can_report_mistake", 'description', 'speed_up', 'description_up', 'avoid_by_default', 'report_help_text', 'enter_description', 'level_change_description', 'base_mapdata_accessible', 'label_settings', 'label_override', diff --git a/src/c3nav/mapdata/management/commands/findbeacons.py b/src/c3nav/mapdata/management/commands/findbeacons.py index 20c4b2a0..874316e8 100644 --- a/src/c3nav/mapdata/management/commands/findbeacons.py +++ b/src/c3nav/mapdata/management/commands/findbeacons.py @@ -1,3 +1,5 @@ +from itertools import chain + import numpy as np from django.core.management.base import BaseCommand @@ -17,7 +19,7 @@ class Command(BaseCommand): found_beacons.setdefault(measurement["bssid"], []).append((beacon_measurement, measurement)) # put in the ones we know - known = {r.wifi_bssid: r for r in RangingBeacon.objects.all()} + known = dict(chain(*(((bssid, r) for bssid in r.wifi_bssids) for r in RangingBeacon.objects.all()))) # lets go through them for bssid, measurements in found_beacons.items(): diff --git a/src/c3nav/mapdata/models/geometry/space.py b/src/c3nav/mapdata/models/geometry/space.py index 24cbeb33..9bf0aeb0 100644 --- a/src/c3nav/mapdata/models/geometry/space.py +++ b/src/c3nav/mapdata/models/geometry/space.py @@ -10,6 +10,7 @@ from django.utils.functional import cached_property from django.utils.text import format_lazy from django.utils.translation import gettext_lazy as _ from django_pydantic_field.fields import SchemaField +from pydantic_extra_types.mac_address import MacAddress from shapely.geometry import CAP_STYLE, JOIN_STYLE, mapping from c3nav.mapdata.fields import GeometryField, I18nField @@ -468,14 +469,8 @@ class RangingBeacon(SpaceGeometryMixin, models.Model): node_number = models.PositiveSmallIntegerField(_('Node Number'), unique=True, null=True, blank=True) - wifi_bssid = models.CharField(_('WiFi BSSID'), unique=True, null=True, blank=True, - max_length=17, - validators=[RegexValidator( - regex='^([a-f0-9]{2}:){5}[a-f0-9]{2}$', - message='Must be a lower-case bssid', - code='invalid_bssid' - )], - help_text=_("uses node's value if not set")) + wifi_bssids: list[MacAddress] = SchemaField(list[MacAddress], verbose_name=_('WiFi BSSIDs'), default=list, + help_text=_("uses node's value if not set")) bluetooth_address = models.CharField(_('Bluetooth Address'), unique=True, null=True, blank=True, max_length=17, validators=[RegexValidator( @@ -520,10 +515,10 @@ class RangingBeacon(SpaceGeometryMixin, models.Model): @property def title(self): - if self.node_number is not None or self.wifi_bssid is not None: + if self.node_number is not None or self.wifi_bssids: if self.comment: - return f'{self.node_number or ''} {self.wifi_bssid or ''} ({self.comment})'.strip() + return f'{self.node_number or ''} {''.join(self.wifi_bssids[:1])} ({self.comment})'.strip() else: - return f'{self.node_number or ''} {self.wifi_bssid or ''}'.strip() + return f'{self.node_number or ''} {''.join(self.wifi_bssids[:1])}'.strip() else: return self.comment diff --git a/src/c3nav/mesh/api.py b/src/c3nav/mesh/api.py index fe0d5a22..86a23076 100644 --- a/src/c3nav/mesh/api.py +++ b/src/c3nav/mesh/api.py @@ -272,7 +272,7 @@ def mesh_map(request, level_id: int): "geometry": mapping(beacon.geometry), "properties": { "node_number": beacon.node_number, - "wifi_bssid": beacon.wifi_bssid, + "wifi_bssid": (beacon.wifi_bssids + [None])[0], "comment": beacon.comment, "mesh_node": None if node is None else { "address": node.address, diff --git a/src/c3nav/mesh/utils.py b/src/c3nav/mesh/utils.py index 1a781895..0369822b 100644 --- a/src/c3nav/mesh/utils.py +++ b/src/c3nav/mesh/utils.py @@ -60,8 +60,8 @@ def get_nodes_and_ranging_beacons(): ranging_beacon = beacons[ranging_beacon_id] ranging_beacon.save = None - if not ranging_beacon.wifi_bssid: - ranging_beacon.wifi_bssid = node.address + if not ranging_beacon.wifi_bssids: + ranging_beacon.wifi_bssids = [node.address] if not ranging_beacon.bluetooth_address: ranging_beacon.bluetooth_address = node.address[:-2] + hex(int(node.address[-2:], 16)+1)[2:] diff --git a/src/c3nav/routing/locator.py b/src/c3nav/routing/locator.py index c208b0cb..525d4507 100644 --- a/src/c3nav/routing/locator.py +++ b/src/c3nav/routing/locator.py @@ -80,8 +80,8 @@ class Locator: calculated = get_nodes_and_ranging_beacons() for beacon in calculated.beacons.values(): identifiers = [] - if beacon.wifi_bssid: - identifiers.append(beacon.wifi_bssid) + for bssid in beacon.wifi_bssids: + identifiers.append(bssid) if beacon.ibeacon_uuid and beacon.ibeacon_major is not None and beacon.ibeacon_minor is not None: identifiers.append((beacon.ibeacon_uuid, beacon.ibeacon_major, beacon.ibeacon_minor)) for identifier in identifiers: