Add basic location tracking
This commit is contained in:
88
vrobbler/apps/locations/models.py
Normal file
88
vrobbler/apps/locations/models.py
Normal file
@ -0,0 +1,88 @@
|
||||
import logging
|
||||
from typing import Dict
|
||||
from uuid import uuid4
|
||||
|
||||
from django.contrib.auth import get_user_model
|
||||
from django.conf import settings
|
||||
from django.db import models
|
||||
from django.urls import reverse
|
||||
from django_extensions.db.models import TimeStampedModel
|
||||
from scrobbles.mixins import ScrobblableMixin
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
BNULL = {"blank": True, "null": True}
|
||||
User = get_user_model()
|
||||
|
||||
|
||||
class GeoLocation(ScrobblableMixin):
|
||||
COMPLETION_PERCENT = getattr(settings, "LOCATION_COMPLETION_PERCENT", 100)
|
||||
|
||||
uuid = models.UUIDField(default=uuid4, editable=False, **BNULL)
|
||||
lat = models.FloatField()
|
||||
lon = models.FloatField()
|
||||
altitude = models.FloatField(**BNULL)
|
||||
|
||||
class Meta:
|
||||
unique_together = [["lat", "lon", "altitude"]]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.lat} x {self.lon}"
|
||||
|
||||
def get_absolute_url(self):
|
||||
return reverse(
|
||||
"locations:geo_location_detail", kwargs={"slug": self.uuid}
|
||||
)
|
||||
|
||||
@property
|
||||
def truncated_lat(self):
|
||||
return float(str(self.lat)[:-3])
|
||||
|
||||
@property
|
||||
def truncated_lan(self):
|
||||
return float(str(self.lon)[:-3])
|
||||
|
||||
@classmethod
|
||||
def find_or_create(cls, data_dict: Dict) -> "GeoLocation":
|
||||
"""Given a data dict from GPSLogger, does the heavy lifting of looking up
|
||||
the location, creating if if doesn't exist yet.
|
||||
|
||||
"""
|
||||
# TODO Add constants for all these data keys
|
||||
if "lat" not in data_dict.keys() or "lon" not in data_dict.keys():
|
||||
logger.error("No lat or lon keys in data dict")
|
||||
return
|
||||
|
||||
lat_int, lat_places = data_dict.get("lat", "").split(".")
|
||||
lon_int, lon_places = data_dict.get("lon", "").split(".")
|
||||
alt_int, alt_places = data_dict.get("alt", "").split(".")
|
||||
|
||||
truncated_lat = lat_places[0:4]
|
||||
truncated_lon = lon_places[0:4]
|
||||
truncated_alt = alt_places[0:3]
|
||||
|
||||
data_dict["lat"] = float(".".join([lat_int, truncated_lat]))
|
||||
data_dict["lon"] = float(".".join([lon_int, truncated_lon]))
|
||||
data_dict["altitude"] = float(".".join([alt_int, truncated_alt]))
|
||||
|
||||
location = cls.objects.filter(
|
||||
lat=data_dict.get("lat"),
|
||||
lon=data_dict.get("lon"),
|
||||
altitude=data_dict.get("alt"),
|
||||
).first()
|
||||
|
||||
if not location:
|
||||
location = cls.objects.create(
|
||||
lat=data_dict.get("lat"),
|
||||
lon=data_dict.get("lon"),
|
||||
altitude=data_dict.get("alt"),
|
||||
)
|
||||
return location
|
||||
|
||||
|
||||
class RawGeoLocation(TimeStampedModel):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
lat = models.FloatField()
|
||||
lon = models.FloatField()
|
||||
altitude = models.FloatField(**BNULL)
|
||||
speed = models.FloatField(**BNULL)
|
||||
timestamp = models.DateTimeField(**BNULL)
|
||||
Reference in New Issue
Block a user