wifimeasurement → beaconmeasurement… and editor scancollector implementation

This commit is contained in:
Laura Klünder 2024-03-31 16:23:15 +02:00
parent 35d030a6fd
commit 20fbcc9139
13 changed files with 169 additions and 85 deletions

View file

@ -48,7 +48,7 @@ def geometrystyles(request):
'graphnode': '#009900', 'graphnode': '#009900',
'graphedge': '#00CC00', 'graphedge': '#00CC00',
'altitudemarker': '#0000FF', 'altitudemarker': '#0000FF',
'wifimeasurement': '#DDDD00', 'beaconmeasurement': '#DDDD00',
'rangingbeacon': '#CC00CC', 'rangingbeacon': '#CC00CC',
} }

View file

@ -119,7 +119,7 @@ def get_level_geometries_result(request, level_id: int, update_cache_key: str, u
Building = request.changeset.wrap_model('Building') Building = request.changeset.wrap_model('Building')
Door = request.changeset.wrap_model('Door') Door = request.changeset.wrap_model('Door')
LocationGroup = request.changeset.wrap_model('LocationGroup') LocationGroup = request.changeset.wrap_model('LocationGroup')
WifiMeasurement = request.changeset.wrap_model('WifiMeasurement') BeaconMeasurement = request.changeset.wrap_model('BeaconMeasurement')
RangingBeacon = request.changeset.wrap_model('RangingBeacon') RangingBeacon = request.changeset.wrap_model('RangingBeacon')
try: try:
@ -149,7 +149,7 @@ def get_level_geometries_result(request, level_id: int, update_cache_key: str, u
Prefetch('buildings', Building.objects.only('geometry', 'level')), Prefetch('buildings', Building.objects.only('geometry', 'level')),
Prefetch('spaces__holes', Hole.objects.only('geometry', 'space')), Prefetch('spaces__holes', Hole.objects.only('geometry', 'space')),
Prefetch('spaces__altitudemarkers', AltitudeMarker.objects.only('geometry', 'space')), Prefetch('spaces__altitudemarkers', AltitudeMarker.objects.only('geometry', 'space')),
Prefetch('spaces__wifi_measurements', WifiMeasurement.objects.only('geometry', 'space')), Prefetch('spaces__beacon_measurements', BeaconMeasurement.objects.only('geometry', 'space')),
Prefetch('spaces__ranging_beacons', RangingBeacon.objects.only('geometry', 'space')), Prefetch('spaces__ranging_beacons', RangingBeacon.objects.only('geometry', 'space')),
Prefetch('spaces__graphnodes', graphnodes_qs) Prefetch('spaces__graphnodes', graphnodes_qs)
) )
@ -184,7 +184,7 @@ def get_level_geometries_result(request, level_id: int, update_cache_key: str, u
_get_geometries_for_one_level(level), _get_geometries_for_one_level(level),
*(_get_geometries_for_one_level(level) for level in levels_on_top), *(_get_geometries_for_one_level(level) for level in levels_on_top),
*(space.altitudemarkers.all() for space in level.spaces.all()), *(space.altitudemarkers.all() for space in level.spaces.all()),
*(space.wifi_measurements.all() for space in level.spaces.all()), *(space.beacon_measurements.all() for space in level.spaces.all()),
*(space.ranging_beacons.all() for space in level.spaces.all()), *(space.ranging_beacons.all() for space in level.spaces.all()),
graphedges, graphedges,
graphnodes, graphnodes,
@ -309,7 +309,7 @@ def get_space_geometries_result(request, space_id: int, update_cache_key: str, u
space.lineobstacles.all().only('geometry', 'width', 'space').prefetch_related('group'), space.lineobstacles.all().only('geometry', 'width', 'space').prefetch_related('group'),
space.columns.all().only('geometry', 'space'), space.columns.all().only('geometry', 'space'),
space.altitudemarkers.all().only('geometry', 'space'), space.altitudemarkers.all().only('geometry', 'space'),
space.wifi_measurements.all().only('geometry', 'space'), space.beacon_measurements.all().only('geometry', 'space'),
space.ranging_beacons.all().only('geometry', 'space'), space.ranging_beacons.all().only('geometry', 'space'),
space.pois.filter(POI.q_for_request(request)).only('geometry', 'space').prefetch_related( space.pois.filter(POI.q_for_request(request)).only('geometry', 'space').prefetch_related(
Prefetch('groups', LocationGroup.objects.only( Prefetch('groups', LocationGroup.objects.only(

View file

@ -396,38 +396,41 @@ textarea.form-control {
height: 75px; height: 75px;
} }
.wificollector { .scancollector {
padding: 10px; padding: 10px;
height: auto; height: auto;
} }
body > .wificollector { body > .scancollector {
display: none; display: none;
} }
.wificollector:not(.empty) .btn.start, .scancollector:not(.empty) .btn.start,
.wificollector:not(.running) .btn.stop, .scancollector:not(.running) .btn.stop,
.wificollector:not(.done) .btn.reset, .scancollector:not(.done) .btn.reset,
.wificollector.empty .count-line, .scancollector.empty .count-line,
body:not(.mobileclient) .wificollector .btn { body:not(.mobileclient) .scancollector .btn {
display: none; display: none;
} }
.wificollector .btn { .scancollector .btn {
margin: 0 5px 0 0; margin: 0 5px 0 0;
} }
.wificollector p:first-child { .scancollector p:first-child {
height: 26px; height: 26px;
margin: 0; margin: 0;
} }
.wificollector table { .scancollector table {
width: 100%; width: 100%;
border-style: solid;
border-width: 0 0 1px;
border-color: #666666;
} }
.wificollector table td { .scancollector table td {
padding: 5px 5px 0 0; padding: 5px 5px 0 0;
} }
.wificollector table td:last-child { .scancollector table td:last-child {
padding-right: 0; padding-right: 0;
text-align: right; text-align: right;
} }
.wificollector table tr td { .scancollectorŝ table tr td {
color: #666666; color: #666666;
} }

View file

@ -71,7 +71,7 @@ editor = {
editor._sublevel_control_container = $(editor._sublevel_control._container); editor._sublevel_control_container = $(editor._sublevel_control._container);
editor.init_geometries(); editor.init_geometries();
editor.init_wificollector(); editor.init_scancollector();
editor.sidebar_content_loaded(); editor.sidebar_content_loaded();
}, },
_inform_mobile_client: function(elem) { _inform_mobile_client: function(elem) {
@ -175,7 +175,7 @@ editor = {
editor._fixed_point_layer = null; editor._fixed_point_layer = null;
} }
if (window.mobileclient && mobileclient.wificollectorStop && $('#sidebar').find('.wificollector.running').length) { if (window.mobileclient && mobileclient.wificollectorStop && $('#sidebar').find('.scancollector.running').length) {
mobileclient.wificollectorStop(); mobileclient.wificollectorStop();
} }
@ -413,13 +413,13 @@ editor = {
var data_field = $('form [name=data]'); var data_field = $('form [name=data]');
if (data_field.length) { if (data_field.length) {
data_field.hide(); data_field.hide();
var collector = $($('body .wificollector')[0].outerHTML); var collector = $($('body .scancollector')[0].outerHTML);
var existing_data = []; var existing_data = [];
if (data_field.val()) { if (data_field.val()) {
existing_data = JSON.parse(data_field.val()); existing_data = JSON.parse(data_field.val());
} }
if (existing_data.length > 0) { if (existing_data.length > 0) {
collector.removeClass('empty').addClass('done').find('.count').text(existing_data.length); collector.removeClass('empty').addClass('done').find('.wifi-count').text(existing_data.length);
} else { } else {
data_field.closest('form').addClass('scan-lock'); data_field.closest('form').addClass('scan-lock');
} }
@ -1304,50 +1304,58 @@ editor = {
} }
}, },
init_wificollector: function () { init_scancollector: function () {
// init geometries and edit listeners // init geometries and edit listeners
editor._highlight_layer = L.layerGroup().addTo(editor.map); editor._highlight_layer = L.layerGroup().addTo(editor.map);
$('#sidebar').on('click', '.wificollector .start', editor._wificollector_start) $('#sidebar').on('click', '.scancollector .start', editor._scancollector_start)
.on('click', '.wificollector .stop', editor._wificollector_stop) .on('click', '.scancollector .stop', editor._scancollector_stop)
.on('click', '.wificollector .reset', editor._wificollector_reset); .on('click', '.scancollector .reset', editor._scancollector_reset);
window.setInterval(editor._wificollector_scan_perhaps, 1000); window.setInterval(editor._scancollector_wifi_scan_perhaps, 1000);
}, },
_wificollector_data: [], _scancollector_data: {
_wificollector_start: function () { wifi: [],
var $collector = $('#sidebar').find('.wificollector'); ibeacon: [],
},
_scancollector_start: function () {
var $collector = $('#sidebar').find('.scancollector');
$collector.removeClass('empty').addClass('running'); $collector.removeClass('empty').addClass('running');
editor._wificollector_data = []; editor._scancollector_data.wifi = [];
$collector.find('.count').text(0); editor._scancollector_data.ibeacon = [];
$collector.find('.wifi-count').text(0);
$collector.find('.ibeacon-count').text(0);
if (mobileclient.wificollectorStart) mobileclient.wificollectorStart(); if (mobileclient.wificollectorStart) mobileclient.wificollectorStart();
if (mobileclient.registerBeaconUuid) mobileclient.registerBeaconUuid("a142621a-2f42-09b3-245b-e1ac6356e9b0");
}, },
_wificollector_stop: function () { _scancollector_stop: function () {
if (mobileclient.wificollectorStop) mobileclient.wificollectorStop(); if (mobileclient.wificollectorStop) mobileclient.wificollectorStop();
if (!editor._wificollector_data.length) return editor._wificollector_reset(); if (mobileclient.unregisterBeaconUuid) mobileclient.unregisterBeaconUuid("a142621a-2f42-09b3-245b-e1ac6356e9b0");
var $collector = $('#sidebar').find('.wificollector'); // todo: maybe reset if either is empty?
if (!editor._scancollector_data.wifi.length && editor._scancollector_data.ibeacon.length) return editor._scancollector_reset();
var $collector = $('#sidebar').find('.scancollector');
$collector.removeClass('running').delay(1000).queue(function(n) { $collector.removeClass('running').delay(1000).queue(function(n) {
$(this).addClass('done'); $(this).addClass('done');
n(); n();
}); });
$collector.closest('form').removeClass('scan-lock'); $collector.closest('form').removeClass('scan-lock');
}, },
_wificollector_reset: function () { _scancollector_reset: function () {
var $collector = $('#sidebar').find('.wificollector'); var $collector = $('#sidebar').find('.scancollector');
$collector.removeClass('done').removeClass('running').addClass('empty').find('table').html(''); $collector.removeClass('done').removeClass('running').addClass('empty').find('table').forEach(function(elem) {elem.html('');});
$collector.siblings('[name=data]').val(''); $collector.siblings('[name=data]').val('');
$collector.closest('form').addClass('scan-lock'); $collector.closest('form').addClass('scan-lock');
}, },
_wificollector_last_max_last: 0, _scancollector_wifi_last_max_last: 0,
_wificollector_last_result: 0, _scancollector_wifi_last_result: 0,
_wificollector_result: function(data) { _scancollector_wifi_result: function(data) {
var $collector = $('#sidebar').find('.wificollector.running'), var $collector = $('#sidebar').find('.scancollector.running'),
$table = $collector.find('table'), $table = $collector.find('.wifi-table'),
item, i, line, apid, color, max_last = 0, now = Date.now(); item, i, line, apid, color, max_last = 0, now = Date.now();
editor._scan_waits = false; editor._wifi_scan_waits = false;
if (!data.length) return; if (!data.length) return;
if (now-2000 < editor._wificollector_last_result) return; if (now-2000 < editor._scancollector_wifi_last_result) return;
editor._wificollector_last_result = now; editor._scancollector_wifi_last_result = now;
// ignore this scan? // ignore this scan?
for (i=0; i < data.length; i++) { for (i=0; i < data.length; i++) {
@ -1356,8 +1364,8 @@ editor = {
max_last = Math.max(max_last, item.last); max_last = Math.max(max_last, item.last);
} }
} }
if (max_last && editor._wificollector_last_max_last && max_last === editor._max_last_max) return; if (max_last && editor._scancollector_wifi_last_max_last && max_last === editor._max_last_max) return;
editor._wificollector_last_max_last = max_last; editor._scancollector_wifi_last_max_last = max_last;
$table.find('tr').addClass('old'); $table.find('tr').addClass('old');
for (i=0; i < data.length; i++) { for (i=0; i < data.length; i++) {
@ -1388,23 +1396,55 @@ editor = {
$table.append(line); $table.append(line);
} }
} }
editor._wificollector_data.push(data); editor._scancollector_data.wifi.push(data);
$collector.find('.count').text(editor._wificollector_data.length); $collector.find('.wifi-count').text(editor._scancollector_data.wifi.length);
$collector.siblings('[name=data]').val(JSON.stringify(editor._wificollector_data)); $collector.siblings('[name=data]').val(JSON.stringify(editor._scancollector_data));
}, },
_scan_waits: false, _scancollector_ibeacon_result: function(data) {
_wificollector_scan_perhaps: function() { var $collector = $('#sidebar').find('.scancollector.running'),
if (!editor._scan_waits && $('#sidebar').find('.wificollector.running').length) { $table = $collector.find('.ibeacon-table'),
editor._scan_waits = true; item, i, line, beaconid, color = Date.now();
if (!data.length) return;
$table.find('tr').addClass('old');
for (i=0; i < data.length; i++) {
item = data[i];
beaconid = 'beacon-'+item.uuid+'-'+item.major+'-'+item-minor;
line = $table.find('tr.'+beaconid);
color = Math.max(0, Math.min(50, item.distance));
color = 'rgb('+String(color*5)+', '+String(200-color*4)+', 0)';
if (line.length) {
line.removeClass('old').find(':last-child').text(item.distance).css('color', color);
} else {
line = $('<tr>').addClass(beaconid);
line.append($('<td>').text(item.major));
line.append($('<td>').text(item.minor));
line.append($('<td>').text(item.distance).css('color', color));
$table.append(line);
}
}
editor._scancollector_data.ibeacon.push(data);
$collector.find('.ibeacon-count').text(editor._scancollector_data.ibeacon.length);
$collector.siblings('[name=data]').val(JSON.stringify(editor._scancollector_data));
},
_wifi_scan_waits: false,
_scancollector_wifi_scan_perhaps: function() {
if (!editor._wifi_scan_waits && $('#sidebar').find('.scancollector.running').length) {
editor._wifi_scan_waits = true;
mobileclient.scanNow(); mobileclient.scanNow();
} }
} }
}; };
function nearby_stations_available() { function nearby_stations_available() {
editor._wificollector_result(JSON.parse(mobileclient.getNearbyStations())); editor._scancollector_wifi_result(JSON.parse(mobileclient.getNearbyStations()));
} }
function ibeacon_results_available() {
c3nav._scancollector_ibeacon_result(mobileclient.getNearbyBeacons());
}
LevelControl = L.Control.extend({ LevelControl = L.Control.extend({
options: { options: {

View file

@ -69,17 +69,19 @@
{% endblock %} {% endblock %}
</div> </div>
<div class="wificollector form-control empty"> <div class="scancollector form-control empty">
<p> <p>
<a class="btn btn-xs btn-primary start">{% trans 'Start scanning' %}</a> <a class="btn btn-xs btn-primary start">{% trans 'Start scanning' %}</a>
<a class="btn btn-xs btn-default stop">{% trans 'Stop scanning' %}</a> <a class="btn btn-xs btn-default stop">{% trans 'Stop scanning' %}</a>
<a class="btn btn-xs btn-danger reset">{% trans 'Reset scan results' %}</a> <a class="btn btn-xs btn-danger reset">{% trans 'Reset scan results' %}</a>
<span class="count-line"><span class="count">0</span> scans</span>
</p> </p>
<p class="nomobileclient"><em> <p class="nomobileclient"><em>
{% trans 'mobileclient not found. Please install the c3nav app for wifi scanning support.' %} {% trans 'mobileclient not found. Please install the c3nav app for wifi scanning support.' %}
</em></p> </em></p>
<table></table> <p><span class="count-line"><span class="wifi-count">0</span> WiFi scans</span></p>
<table class="wifi-table"></table>
<p><span class="count-line"><span class="ibeacon-count">0</span> iBeacon scans</span></p>
<table class="ibeacon-table"></table>
</div> </div>
<div class="theme-editor-filter"> <div class="theme-editor-filter">

View file

@ -80,5 +80,5 @@ urlpatterns.extend(add_editor_urls('POI', 'Space'))
urlpatterns.extend(add_editor_urls('AltitudeMarker', 'Space')) urlpatterns.extend(add_editor_urls('AltitudeMarker', 'Space'))
urlpatterns.extend(add_editor_urls('LeaveDescription', 'Space')) urlpatterns.extend(add_editor_urls('LeaveDescription', 'Space'))
urlpatterns.extend(add_editor_urls('CrossDescription', 'Space')) urlpatterns.extend(add_editor_urls('CrossDescription', 'Space'))
urlpatterns.extend(add_editor_urls('WifiMeasurement', 'Space')) urlpatterns.extend(add_editor_urls('BeaconMeasurement', 'Space'))
urlpatterns.extend(add_editor_urls('RangingBeacon', 'Space')) urlpatterns.extend(add_editor_urls('RangingBeacon', 'Space'))

View file

@ -108,7 +108,7 @@ def space_detail(request, level, pk):
if edit_utils.can_access_child_base_mapdata: if edit_utils.can_access_child_base_mapdata:
submodels = ('POI', 'Area', 'Obstacle', 'LineObstacle', 'Stair', 'Ramp', 'Column', submodels = ('POI', 'Area', 'Obstacle', 'LineObstacle', 'Stair', 'Ramp', 'Column',
'Hole', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription', 'Hole', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription',
'WifiMeasurement', 'RangingBeacon') 'BeaconMeasurement', 'RangingBeacon')
else: else:
submodels = ('POI', 'Area', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription') submodels = ('POI', 'Area', 'AltitudeMarker', 'LeaveDescription', 'CrossDescription')
@ -281,9 +281,9 @@ def edit(request, pk=None, model=None, level=None, space=None, on_top_of=None, e
'nozoom': True 'nozoom': True
}) })
if new and model.__name__ == 'WifiMeasurement' and not request.user.is_authenticated: if new and model.__name__ == 'BeaconMeasurement' and not request.user.is_authenticated:
return APIHybridLoginRequiredResponse(next=request.path_info, login_url='editor.login', level='info', return APIHybridLoginRequiredResponse(next=request.path_info, login_url='editor.login', level='info',
message=_('You need to log in to create Wifi Measurements.')) message=_('You need to log in to create Beacon Measurements.'))
error = None error = None
delete = getattr(request, 'is_delete', None) delete = getattr(request, 'is_delete', None)

View file

@ -12,7 +12,7 @@ class Command(BaseCommand):
def add_arguments(self, parser): def add_arguments(self, parser):
parser.add_argument('--yes', action='store_true', help='really delete it') parser.add_argument('--yes', action='store_true', help='really delete it')
parser.add_argument('--wifi-measurements', action='store_true', help='delete wifi measurements') parser.add_argument('--beacon-measurements', action='store_true', help='delete beacon measurements')
def handle(self, *args, **options): def handle(self, *args, **options):
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
@ -21,7 +21,7 @@ class Command(BaseCommand):
from c3nav.editor.models import ChangeSet from c3nav.editor.models import ChangeSet
from c3nav.mapdata.models import MapUpdate from c3nav.mapdata.models import MapUpdate
from c3nav.mapdata.models.access import AccessPermissionToken from c3nav.mapdata.models.access import AccessPermissionToken
from c3nav.mapdata.models.geometry.space import WifiMeasurement from c3nav.mapdata.models.geometry.space import BeaconMeasurement
from c3nav.site.models import Announcement from c3nav.site.models import Announcement
logger = logging.getLogger('c3nav') logger = logging.getLogger('c3nav')
@ -46,9 +46,9 @@ class Command(BaseCommand):
UserPermissions.objects.filter(user__is_superuser=False).delete() UserPermissions.objects.filter(user__is_superuser=False).delete()
logger.info('Deleted all UserPermissions not attached to a super user') logger.info('Deleted all UserPermissions not attached to a super user')
if options['wifi_measurements']: if options['beacon_measurements']:
WifiMeasurement.objects.all().delete() BeaconMeasurement.objects.all().delete()
logger.info('Deleted all WifiMeasurements') logger.info('Deleted all BeaconMeasurements')
get_user_model().objects.filter(is_superuser=False).delete() get_user_model().objects.filter(is_superuser=False).delete()
logger.info('Deleted all Users who are not a super user') logger.info('Deleted all Users who are not a super user')

View file

@ -1,7 +1,7 @@
import numpy as np import numpy as np
from django.core.management.base import BaseCommand from django.core.management.base import BaseCommand
from c3nav.mapdata.models.geometry.space import WifiMeasurement, RangingBeacon from c3nav.mapdata.models.geometry.space import BeaconMeasurement, RangingBeacon
class Command(BaseCommand): class Command(BaseCommand):
@ -10,11 +10,11 @@ class Command(BaseCommand):
def handle(self, *args, **options): def handle(self, *args, **options):
found_beacons = {} found_beacons = {}
# lets collect them # lets collect them
for wifi_measurement in WifiMeasurement.objects.select_related("space"): for beacon_measurement in BeaconMeasurement.objects.select_related("space"):
for measurement_list in wifi_measurement.data: for measurement_list in beacon_measurement.data:
for measurement in measurement_list: for measurement in measurement_list:
if measurement.get("supports80211mc", False) or measurement.get("distance", None): if measurement.get("supports80211mc", False) or measurement.get("distance", None):
found_beacons.setdefault(measurement["bssid"], []).append((wifi_measurement, measurement)) found_beacons.setdefault(measurement["bssid"], []).append((beacon_measurement, measurement))
# put in the ones we know # put in the ones we know
known = {r.wifi_bssid: r for r in RangingBeacon.objects.all()} known = {r.wifi_bssid: r for r in RangingBeacon.objects.all()}
@ -22,8 +22,8 @@ class Command(BaseCommand):
# lets go through them # lets go through them
for bssid, measurements in found_beacons.items(): for bssid, measurements in found_beacons.items():
print(bssid, measurements[0][1]["ssid"], known.get(bssid)) print(bssid, measurements[0][1]["ssid"], known.get(bssid))
points = {wifi_measurement.geometry for wifi_measurement, measurement in measurements} points = {beacon_measurement.geometry for beacon_measurement, measurement in measurements}
for wifi_measurement, measurement in measurements: for beacon_measurement, measurement in measurements:
break break
#print(f" Space={wifi_measurement.space.title!r} RSSI={measurement['rssi']} " #print(f" Space={wifi_measurement.space.title!r} RSSI={measurement['rssi']} "
# f"distance={measurement.get('distance')} distance_sd={measurement.get('distance_sd')}") # f"distance={measurement.get('distance')} distance_sd={measurement.get('distance_sd')}")

View file

@ -0,0 +1,39 @@
# Generated by Django 5.0.1 on 2024-03-31 13:58
from django.conf import settings
from django.db import migrations
def forwards_func(apps, schema_editor):
BeaconMeasurement = apps.get_model('mapdata', 'BeaconMeasurement')
for measurement in BeaconMeasurement.objects.all():
measurement.data = {"wifi": measurement.data}
measurement.save()
def backwards_func(apps, schema_editor):
BeaconMeasurement = apps.get_model('mapdata', 'BeaconMeasurement')
for measurement in BeaconMeasurement.objects.all():
measurement.data = measurement.data["wifi"]
measurement.save()
class Migration(migrations.Migration):
dependencies = [
('mapdata', '0105_alter_theme_color_background_and_more'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.RenameModel(
old_name='WifiMeasurement',
new_name='BeaconMeasurement',
),
migrations.AlterModelOptions(
name='beaconmeasurement',
options={'default_related_name': 'beacon_measurements', 'verbose_name': 'Beacon Measurement',
'verbose_name_plural': 'Beacon Measurements'},
),
migrations.RunPython(forwards_func, backwards_func),
]

View file

@ -453,20 +453,20 @@ class CrossDescription(SerializableMixin):
) )
class WifiMeasurement(SpaceGeometryMixin, models.Model): class BeaconMeasurement(SpaceGeometryMixin, models.Model):
""" """
A Wi-Fi measurement A Beacon (WiFI / iBeacon) measurement
""" """
geometry = GeometryField('point') geometry = GeometryField('point')
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True,
verbose_name=_('author')) verbose_name=_('author'))
comment = models.TextField(null=True, blank=True, verbose_name=_('comment')) comment = models.TextField(null=True, blank=True, verbose_name=_('comment'))
data = models.JSONField(_('Measurement list'), default=list) data = models.JSONField(_('Measurement list'), default=list) # would be nice if this used pydantic
class Meta: class Meta:
verbose_name = _('Wi-Fi Measurement') verbose_name = _('Beacon Measurement')
verbose_name_plural = _('Wi-Fi Measurements') verbose_name_plural = _('Beacon Measurements')
default_related_name = 'wifi_measurements' default_related_name = 'beacon_measurements'
@property @property
def all_geometry_changed(self): def all_geometry_changed(self):

View file

@ -8,7 +8,7 @@ from kombu.utils import cached_property
from c3nav.control.models import UserPermissions from c3nav.control.models import UserPermissions
from c3nav.mapdata.grid import grid from c3nav.mapdata.grid import grid
from c3nav.mapdata.models import Level, LocationGroup, LocationSlug, Space from c3nav.mapdata.models import Level, LocationGroup, LocationSlug, Space
from c3nav.mapdata.models.geometry.space import POI, Area, WifiMeasurement from c3nav.mapdata.models.geometry.space import POI, Area, BeaconMeasurement
from c3nav.mapdata.models.locations import LocationRedirect from c3nav.mapdata.models.locations import LocationRedirect
from c3nav.mapdata.utils.locations import CustomLocation, get_location_by_id_for_request from c3nav.mapdata.utils.locations import CustomLocation, get_location_by_id_for_request
@ -87,7 +87,7 @@ def convert_locate(data):
'by_level': {}, 'by_level': {},
} }
measurement_lookup = {} measurement_lookup = {}
for measurement in WifiMeasurement.objects.all().select_related('space', 'space__level'): for measurement in BeaconMeasurement.objects.all().select_related('space', 'space__level'):
pos = CustomLocation(measurement.space.level, measurement.geometry.x, measurement.geometry.y, pos = CustomLocation(measurement.space.level, measurement.geometry.x, measurement.geometry.y,
permissions=set()) permissions=set())
space_slug = measurement.space.get_slug() space_slug = measurement.space.get_slug()

View file

@ -78,16 +78,16 @@ class Locator:
) )
self.xyz = np.array(tuple(peer.xyz for peer in self.peers)) self.xyz = np.array(tuple(peer.xyz for peer in self.peers))
for space in Space.objects.prefetch_related('wifi_measurements'): for space in Space.objects.prefetch_related('beacon_measurements'):
new_space = LocatorSpace.create( new_space = LocatorSpace.create(
pk=space.pk, pk=space.pk,
points=tuple( points=tuple(
LocatorPoint( LocatorPoint(
x=measurement.geometry.x, x=measurement.geometry.x,
y=measurement.geometry.y, y=measurement.geometry.y,
values=self.convert_scans(measurement.data, create_peers=True), values=self.convert_scans(measurement.data["wifi"], create_peers=True),
) )
for measurement in space.wifi_measurements.all() for measurement in space.beacon_measurements.all()
) )
) )
if new_space.points: if new_space.points: