From cfed6d9ed7d3604c4d6f207e954672d4d903759b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laura=20Kl=C3=BCnder?= Date: Sat, 28 Dec 2024 15:21:53 +0100 Subject: [PATCH] =?UTF-8?q?wifi=5Fbssids=20=E2=86=92=20addresses?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/c3nav/editor/api/endpoints.py | 2 +- src/c3nav/editor/forms.py | 12 +++--- .../management/commands/findbeacons.py | 2 +- .../mapdata/management/commands/importnoc.py | 5 ++- .../0136_wifi_bssids_to_addresses_and_more.py | 38 +++++++++++++++++++ src/c3nav/mapdata/models/geometry/space.py | 15 ++++---- src/c3nav/mapdata/quests/positioning.py | 10 ++--- src/c3nav/mesh/api.py | 2 +- src/c3nav/mesh/models.py | 4 +- src/c3nav/mesh/utils.py | 4 +- src/c3nav/routing/locator.py | 2 +- src/c3nav/site/static/site/js/c3nav.js | 4 +- 12 files changed, 70 insertions(+), 30 deletions(-) create mode 100644 src/c3nav/mapdata/migrations/0136_wifi_bssids_to_addresses_and_more.py diff --git a/src/c3nav/editor/api/endpoints.py b/src/c3nav/editor/api/endpoints.py index 75c11ca2..e9b95d3d 100644 --- a/src/c3nav/editor/api/endpoints.py +++ b/src/c3nav/editor/api/endpoints.py @@ -170,7 +170,7 @@ def beacons_lookup(request): "name": node.name if node else ("Beacon #%d" % beacon.pk), "point": mapping(beacon.geometry), } - for bssid in beacon.wifi_bssids: + for bssid in beacon.addresses: 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( diff --git a/src/c3nav/editor/forms.py b/src/c3nav/editor/forms.py index a7db5b13..1fddd69d 100644 --- a/src/c3nav/editor/forms.py +++ b/src/c3nav/editor/forms.py @@ -384,12 +384,12 @@ def create_editor_form(editor_model): 'ordering', 'category', 'width', 'groups', 'height', 'color', 'in_legend', 'priority', 'hierarchy', 'icon_name', 'base_altitude', 'intermediate', 'waytype', 'access_restriction', 'edit_access_restriction', 'default_height', 'door_height', 'outside', 'identifyable', 'can_search', 'can_describe', 'geometry', 'single', 'altitude', - 'level_index', 'short_label', 'origin_space', 'target_space', 'data', "ap_name", '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', 'min_zoom', - 'max_zoom', 'font_size', 'members', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', + "beacon_type", 'level_index', 'short_label', 'origin_space', 'target_space', 'data', "ap_name", 'comment', + 'slow_down_factor', 'groundaltitude', 'node_number', 'addresses', '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', + 'min_zoom', 'max_zoom', 'font_size', 'members', 'allow_levels', 'allow_spaces', 'allow_areas', 'allow_pois', 'allow_dynamic_locations', 'left', 'top', 'right', 'bottom', 'import_tag', 'import_block_data', 'import_block_geom', 'public', 'default', 'dark', 'high_contrast', 'funky', 'randomize_primary_color', 'color_logo', 'color_css_initial', 'color_css_primary', 'color_css_secondary', 'color_css_tertiary', diff --git a/src/c3nav/mapdata/management/commands/findbeacons.py b/src/c3nav/mapdata/management/commands/findbeacons.py index 874316e8..2ffc0c38 100644 --- a/src/c3nav/mapdata/management/commands/findbeacons.py +++ b/src/c3nav/mapdata/management/commands/findbeacons.py @@ -19,7 +19,7 @@ class Command(BaseCommand): found_beacons.setdefault(measurement["bssid"], []).append((beacon_measurement, measurement)) # put in the ones we know - known = dict(chain(*(((bssid, r) for bssid in r.wifi_bssids) for r in RangingBeacon.objects.all()))) + known = dict(chain(*(((bssid, r) for bssid in r.addresses) for r in RangingBeacon.objects.all()))) # lets go through them for bssid, measurements in found_beacons.items(): diff --git a/src/c3nav/mapdata/management/commands/importnoc.py b/src/c3nav/mapdata/management/commands/importnoc.py index b8c752b8..a7466f8a 100644 --- a/src/c3nav/mapdata/management/commands/importnoc.py +++ b/src/c3nav/mapdata/management/commands/importnoc.py @@ -48,7 +48,8 @@ class Command(BaseCommand): spaces_for_level.setdefault(space.level_id, []).append(space) beacons_so_far: dict[str, RangingBeacon] = { - **{m.import_tag: m for m in RangingBeacon.objects.filter(import_tag__startswith="noc:")}, + **{m.import_tag: m for m in RangingBeacon.objects.filter(import_tag__startswith="noc:", + beacon_type=RangingBeacon.BeaconType.EVENT_WIFI)}, } for name, item in items.items(): @@ -118,7 +119,7 @@ class Command(BaseCommand): # build resulting object altitude_quest = True if not result: - result = RangingBeacon(import_tag=import_tag) + result = RangingBeacon(import_tag=import_tag, beacon_type=RangingBeacon.BeaconType.EVENT_WIFI) else: if result.space == new_space and distance(unwrap_geom(result.geometry), new_geometry) < 0.03: continue diff --git a/src/c3nav/mapdata/migrations/0136_wifi_bssids_to_addresses_and_more.py b/src/c3nav/mapdata/migrations/0136_wifi_bssids_to_addresses_and_more.py new file mode 100644 index 00000000..e38c88c6 --- /dev/null +++ b/src/c3nav/mapdata/migrations/0136_wifi_bssids_to_addresses_and_more.py @@ -0,0 +1,38 @@ +# Generated by Django 5.0.8 on 2024-12-28 14:15 + +import django.core.serializers.json +import django_pydantic_field.compat.django +import django_pydantic_field.fields +import pydantic_extra_types.mac_address +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mapdata', '0135_rangingbeacon_beacon_type'), + ] + + operations = [ + migrations.RenameField( + model_name='rangingbeacon', + old_name='wifi_bssids', + new_name='addresses', + ), + migrations.AlterField( + model_name='rangingbeacon', + name='addresses', + field=django_pydantic_field.fields.PydanticSchemaField(config=None, default=list, + encoder=django.core.serializers.json.DjangoJSONEncoder, + help_text="uses node's value if not set", + schema=django_pydantic_field.compat.django.GenericContainer( + list, + (pydantic_extra_types.mac_address.MacAddress,)), + verbose_name='Mac Address / BSSIDs'), + ), + migrations.AlterField( + model_name='rangingbeacon', + name='ap_name', + field=models.CharField(blank=True, max_length=32, null=True, verbose_name='AP name'), + ), + ] diff --git a/src/c3nav/mapdata/models/geometry/space.py b/src/c3nav/mapdata/models/geometry/space.py index 15a7c812..fb818534 100644 --- a/src/c3nav/mapdata/models/geometry/space.py +++ b/src/c3nav/mapdata/models/geometry/space.py @@ -470,9 +470,10 @@ class BeaconMeasurement(SpaceGeometryMixin, models.Model): for peer in scan: if peer.ap_name: map_name.setdefault(peer.ap_name, []).append(peer.bssid) - for beacon in RangingBeacon.objects.filter(ap_name__in=map_name.keys()): + 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])) - beacon.wifi_bssids = list(set(beacon.wifi_bssids) | set(map_name[beacon.ap_name])) + beacon.addresses = list(set(beacon.addresses) | set(map_name[beacon.ap_name])) beacon.save() def save(self, *args, **kwargs): @@ -495,8 +496,8 @@ class RangingBeacon(SpaceGeometryMixin, models.Model): node_number = models.PositiveSmallIntegerField(_('Node Number'), unique=True, null=True, blank=True) - wifi_bssids: list[MacAddress] = SchemaField(list[MacAddress], verbose_name=_('WiFi BSSIDs'), default=list, - help_text=_("uses node's value if not set")) + addresses: list[MacAddress] = SchemaField(list[MacAddress], verbose_name=_('Mac Address / 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( @@ -522,7 +523,7 @@ class RangingBeacon(SpaceGeometryMixin, models.Model): altitude = models.DecimalField(_('altitude above ground'), max_digits=6, decimal_places=2, default=0, validators=[MinValueValidator(Decimal('0'))]) - ap_name = models.TextField(null=True, blank=True, verbose_name=_('AP name')) + ap_name = models.CharField(null=True, blank=True, verbose_name=_('AP name'), max_length=32) comment = models.TextField(null=True, blank=True, verbose_name=_('comment')) altitude_quest = models.BooleanField(_('altitude quest'), default=True) @@ -551,8 +552,8 @@ class RangingBeacon(SpaceGeometryMixin, models.Model): title = ' - '.join(segments).strip() else: title = f'#{self.pk}' - if self.wifi_bssids: - ssids = self.wifi_bssids[0] + (', …' if len(self.wifi_bssids) > 1 else '') + if self.addresses: + ssids = self.addresses[0] + (', …' if len(self.adresses) > 1 else '') title += f' ({ssids})' if self.comment: title += f' ({self.comment})' diff --git a/src/c3nav/mapdata/quests/positioning.py b/src/c3nav/mapdata/quests/positioning.py index c1b1a9c1..f3f495cd 100644 --- a/src/c3nav/mapdata/quests/positioning.py +++ b/src/c3nav/mapdata/quests/positioning.py @@ -61,17 +61,17 @@ class RangingBeaconBSSIDsQuestForm(ChangeSetModelForm): super().__init__(*args, **kwargs) self.fields["look_for_ap"] = CharField(disabled=True, initial=self.instance.import_tag[4:], widget=HiddenInput()) - self.fields["wifi_bssids"].widget = HiddenInput() + self.fields["addresses"].widget = HiddenInput() - def clean_bssids(self): - data = self.cleaned_data["wifi_bssids"] + def clean_addresses(self): + data = self.cleaned_data["addresses"] if not data: raise ValidationError(_("Need at least one bssid.")) return data class Meta: model = RangingBeacon - fields = ("wifi_bssids", ) + fields = ("addresses", ) @property def changeset_title(self): @@ -103,7 +103,7 @@ class RangingBeaconBSSIDsQuest(Quest): @classmethod def _qs_for_request(cls, request): - return RangingBeacon.qs_for_request(request).filter(ap_name__isnull=False, wifi_bssids=[]) + return RangingBeacon.qs_for_request(request).filter(ap_name__isnull=False, addresses=[]) class BeaconMeasurementQuestForm(ChangeSetModelForm): diff --git a/src/c3nav/mesh/api.py b/src/c3nav/mesh/api.py index 86a23076..47f591ea 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_bssids + [None])[0], + "wifi_bssid": (beacon.addresses + [None])[0], "comment": beacon.comment, "mesh_node": None if node is None else { "address": node.address, diff --git a/src/c3nav/mesh/models.py b/src/c3nav/mesh/models.py index b7e8c33a..3dd084b6 100644 --- a/src/c3nav/mesh/models.py +++ b/src/c3nav/mesh/models.py @@ -197,10 +197,10 @@ class MeshNodeQuerySet(models.QuerySet): for ranging_beacon in RangingBeacon.objects.filter( Q(node_number__in=nodes_by_id.keys()) ).select_related('space'): - if not (set(ranging_beacon.wifi_bssids) & nodes_by_bssid_keys): + if not (set(ranging_beacon.addresses) & nodes_by_bssid_keys): continue # noinspection PyUnresolvedReferences - for bssid in ranging_beacon.wifi_bssids: + for bssid in ranging_beacon.addresses: with suppress(KeyError): nodes_by_bssid[bssid]._ranging_beacon = ranging_beacon with suppress(KeyError): diff --git a/src/c3nav/mesh/utils.py b/src/c3nav/mesh/utils.py index 0369822b..d2d48d90 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_bssids: - ranging_beacon.wifi_bssids = [node.address] + if not ranging_beacon.addresses: + ranging_beacon.addresses = [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 a25130e9..697f1d8a 100644 --- a/src/c3nav/routing/locator.py +++ b/src/c3nav/routing/locator.py @@ -94,7 +94,7 @@ class Locator: calculated = get_nodes_and_ranging_beacons() for beacon in calculated.beacons.values(): identifiers = [] - for bssid in beacon.wifi_bssids: + for bssid in beacon.addresses: identifiers.append(TypedIdentifier(PeerType.WIFI, bssid)) if beacon.ibeacon_uuid and beacon.ibeacon_major is not None and beacon.ibeacon_minor is not None: identifiers.append( diff --git a/src/c3nav/site/static/site/js/c3nav.js b/src/c3nav/site/static/site/js/c3nav.js index 22b12eb6..248b7db5 100644 --- a/src/c3nav/site/static/site/js/c3nav.js +++ b/src/c3nav/site/static/site/js/c3nav.js @@ -1486,7 +1486,7 @@ c3nav = { const $modal = $('#modal'); const $match_ap = $modal.find('[name=look_for_ap]'); if ($match_ap.length) { - const $wifi_bssids = $('[name=wifi_bssids]'); + const $addresses = $('[name=addresses]'); const ap_name = $match_ap.val(); const found_bssids = {}; let scan_complete = false; @@ -1515,7 +1515,7 @@ c3nav = { if (scan_complete) { // todo only bssids that have count > 1 - $wifi_bssids.val(JSON.stringify(Object.keys(found_bssids))); + $addresses.val(JSON.stringify(Object.keys(found_bssids))); $('#modal button[type=submit]').show(); } }