beaconmeasurement quest backened implementation
This commit is contained in:
parent
87b7f00740
commit
fd291858dd
3 changed files with 61 additions and 9 deletions
|
@ -309,13 +309,6 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
|
||||||
_('Can not add redirecting slug “%s”: it is already used elsewhere.') % slug
|
_('Can not add redirecting slug “%s”: it is already used elsewhere.') % slug
|
||||||
)
|
)
|
||||||
|
|
||||||
def clean_data(self):
|
|
||||||
data = self.cleaned_data['data']
|
|
||||||
if not data.wifi:
|
|
||||||
raise ValidationError(_('WiFi scan data is missing.'))
|
|
||||||
data.wifi = [[item for item in scan if item.ssid] for scan in data.wifi]
|
|
||||||
return data
|
|
||||||
|
|
||||||
def clean(self):
|
def clean(self):
|
||||||
if self.is_json:
|
if self.is_json:
|
||||||
for name, field in self.missing_fields:
|
for name, field in self.missing_fields:
|
||||||
|
@ -325,6 +318,15 @@ class EditorFormBase(I18nModelFormMixin, ModelForm):
|
||||||
if not self.cleaned_data.get('geometry'):
|
if not self.cleaned_data.get('geometry'):
|
||||||
raise ValidationError('Missing geometry.')
|
raise ValidationError('Missing geometry.')
|
||||||
|
|
||||||
|
data = self.cleaned_data['data']
|
||||||
|
if self.cleaned_data['fill_quest']:
|
||||||
|
if self.cleaned_data['data'].wifi:
|
||||||
|
raise ValidationError(_('Why is there WiFi scan data if this is a fill quest?'))
|
||||||
|
else:
|
||||||
|
if not self.cleaned_data['data'].wifi:
|
||||||
|
raise ValidationError(_('WiFi scan data is missing.'))
|
||||||
|
self.cleaned_data['data'].wifi = [[item for item in scan if item.ssid] for scan in data.wifi]
|
||||||
|
|
||||||
super().clean()
|
super().clean()
|
||||||
|
|
||||||
def _save_m2m(self):
|
def _save_m2m(self):
|
||||||
|
|
|
@ -6,8 +6,9 @@ from django.utils.translation import gettext_lazy as _
|
||||||
from shapely import Point
|
from shapely import Point
|
||||||
from shapely.geometry import mapping
|
from shapely.geometry import mapping
|
||||||
|
|
||||||
from c3nav.mapdata.models.geometry.space import RangingBeacon
|
from c3nav.mapdata.models.geometry.space import RangingBeacon, BeaconMeasurement
|
||||||
from c3nav.mapdata.quests.base import ChangeSetModelForm, register_quest, Quest
|
from c3nav.mapdata.quests.base import ChangeSetModelForm, register_quest, Quest
|
||||||
|
from c3nav.routing.schemas import BeaconMeasurementDataSchema
|
||||||
|
|
||||||
|
|
||||||
class RangingBeaconAltitudeQuestForm(ChangeSetModelForm):
|
class RangingBeaconAltitudeQuestForm(ChangeSetModelForm):
|
||||||
|
@ -103,3 +104,49 @@ class RangingBeaconBSSIDsQuest(Quest):
|
||||||
@classmethod
|
@classmethod
|
||||||
def _qs_for_request(cls, request):
|
def _qs_for_request(cls, request):
|
||||||
return RangingBeacon.qs_for_request(request).filter(import_tag__startswith="noc:", wifi_bssids=[])
|
return RangingBeacon.qs_for_request(request).filter(import_tag__startswith="noc:", wifi_bssids=[])
|
||||||
|
|
||||||
|
|
||||||
|
class BeaconMeasurementQuestForm(ChangeSetModelForm):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
super().__init__(*args, **kwargs)
|
||||||
|
self.fields["data"].widget = HiddenInput()
|
||||||
|
|
||||||
|
def clean_bssids(self):
|
||||||
|
data = self.cleaned_data["data"]
|
||||||
|
if not data:
|
||||||
|
raise ValidationError(_("Need at least one scan."))
|
||||||
|
return data
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = BeaconMeasurement
|
||||||
|
fields = ("data", )
|
||||||
|
|
||||||
|
@property
|
||||||
|
def changeset_title(self):
|
||||||
|
return f'Beacon Measurement Quest: {self.instance.title}'
|
||||||
|
|
||||||
|
|
||||||
|
@register_quest
|
||||||
|
@dataclass
|
||||||
|
class BeaconMeasurementQuest(Quest):
|
||||||
|
quest_type = "beacon_measurement"
|
||||||
|
quest_type_label = _('Wifi/BLE Positioning')
|
||||||
|
quest_type_icon = "wifi"
|
||||||
|
form_class = BeaconMeasurementQuestForm
|
||||||
|
obj: BeaconMeasurement
|
||||||
|
|
||||||
|
@property
|
||||||
|
def quest_description(self) -> list[str]:
|
||||||
|
return [
|
||||||
|
_("Please stand as close to the given location as possible. "
|
||||||
|
"Feel free to close this window again to double-check."),
|
||||||
|
_("When you're ready, please click the button below and wait for measurements to arrive."),
|
||||||
|
]
|
||||||
|
|
||||||
|
@property
|
||||||
|
def point(self) -> Point:
|
||||||
|
return mapping(self.obj.geometry)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _qs_for_request(cls, request):
|
||||||
|
return BeaconMeasurement.qs_for_request(request).filter(data=BeaconMeasurementDataSchema())
|
||||||
|
|
|
@ -115,3 +115,6 @@ class LocateIBeaconPeerSchema(BaseSchema):
|
||||||
class BeaconMeasurementDataSchema(BaseSchema):
|
class BeaconMeasurementDataSchema(BaseSchema):
|
||||||
wifi: list[list[LocateWifiPeerSchema]] = []
|
wifi: list[list[LocateWifiPeerSchema]] = []
|
||||||
ibeacon: list[list[LocateIBeaconPeerSchema]] = []
|
ibeacon: list[list[LocateIBeaconPeerSchema]] = []
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return bool(self.wifi or self.ibeacon)
|
Loading…
Add table
Add a link
Reference in a new issue