views.py 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. import json
  2. import gzip
  3. import pytz
  4. from datetime import datetime
  5. from django.shortcuts import render
  6. from django.http import JsonResponse, HttpResponse
  7. from django.core.serializers.json import DjangoJSONEncoder
  8. from django.views import View
  9. from django.core.cache import cache
  10. from django.contrib.auth.decorators import permission_required
  11. from django.contrib.auth.mixins import PermissionRequiredMixin
  12. from django.contrib.gis.geos import Point
  13. from django.db.models import Q
  14. from .models import *
  15. from .workers.points2trips import TripConverter
  16. def index(request):
  17. return render(request, 'gps_logger/index.html')
  18. @permission_required("gps-logger.markers.change")
  19. def upload(request):
  20. return render(request, 'gps_logger/upload.html')
  21. class MarkerCreateView(PermissionRequiredMixin, View):
  22. permission_required = ("gps-logger.markers.change")
  23. def post(self, request):
  24. utctz = pytz.timezone("UTC")
  25. insert_count = censor_count = replace_count = 0
  26. data = json.loads(request.body)
  27. minDate = datetime.utcnow().replace(tzinfo=utctz)
  28. for file in data:
  29. if len(data[file]) == 0:
  30. continue
  31. objects = [Marker(
  32. timestamp=datetime.strptime(x['timestamp'].replace("Z","-0000"), r"%Y-%m-%dT%H:%M:%S.%f%z"),
  33. location = Point(x['lng'], x['lat'], srid=4326),
  34. alt = x['alt'],
  35. hdop = x.get('hdop', None),
  36. speed = x.get('speed', None)
  37. ) for x in data[file]]
  38. start_date = objects[0].timestamp
  39. end_date = objects[-1].timestamp
  40. oldMarkers = Marker.objects.filter(timestamp__range=(start_date, end_date)).all()
  41. identical = oldMarkers.count() == len(objects)
  42. minDate = min(minDate, start_date)
  43. if identical:
  44. for i, marker in enumerate(oldMarkers):
  45. if marker.timestamp != objects[i].timestamp:
  46. identical = False
  47. break
  48. if identical:
  49. for i, marker in enumerate(oldMarkers):
  50. objects[i].id = marker.id
  51. Marker.objects.bulk_update(objects, ['location', 'alt', 'hdop', 'speed'])
  52. replace_count += oldMarkers.count()
  53. else:
  54. insert_count += len(objects) - oldMarkers.count()
  55. oldMarkers.delete()
  56. Marker.objects.bulk_create(objects)
  57. censor_count = censor()
  58. minDate = minDate.replace(hour=0, minute=0, second=0, microsecond=0)
  59. print("regenerating trips after", minDate)
  60. tc = TripConverter(minDate)
  61. tc.run()
  62. cache.delete('trips')
  63. return JsonResponse({
  64. 'markers_censored': censor_count,
  65. 'markers_replaced': replace_count,
  66. 'markers_inserted': insert_count - censor_count,
  67. 'trips_created': tc.created,
  68. 'trips_updated': tc.updated,
  69. 'trips_skipped': tc.skipped
  70. }, status=201)
  71. class CreateTripsView(PermissionRequiredMixin, View):
  72. permission_required = ("gps-logger.trips.change")
  73. def get(self, request):
  74. tc = TripConverter()
  75. tc.run()
  76. cache.delete('trips')
  77. return JsonResponse({
  78. 'created': tc.created,
  79. 'updated': tc.updated,
  80. 'skipped': tc.skipped
  81. }, status=201)
  82. def marker_view(request):
  83. data = cache.get('markers')
  84. if not data:
  85. values = list(Marker.objects.values())
  86. for marker in values:
  87. location = marker['location']
  88. if location:
  89. marker['lng'] = location.x
  90. marker['lat'] = location.y
  91. del marker['location']
  92. data = json.dumps(values, cls=DjangoJSONEncoder)
  93. cache.set('markers', data, 3600*24*30)
  94. return HttpResponse(data, content_type='application/json')
  95. def trip_view(request):
  96. data = cache.get('trips')
  97. if not data:
  98. values = list(Trip.objects.values())
  99. for trip in values:
  100. trip['path'] = json.loads(gzip.decompress(trip['path']))
  101. trip['startTime'] = trip['startTime'].timestamp()
  102. trip['endTime'] = trip['endTime'].timestamp()
  103. trip['movementTime'] = trip['movementTime'].total_seconds()
  104. trip['totalTime'] = trip['totalTime'].total_seconds()
  105. trip['center'] = {
  106. 'lng': trip['center'].x,
  107. 'lat': trip['center'].y
  108. }
  109. trip['minLng'], trip['minLat'], trip['maxLng'], trip['maxLat'] = trip['line'].extent
  110. del trip['line']
  111. data = json.dumps(values)
  112. cache.set('trips', data, 3600*24*30)
  113. return HttpResponse(data, content_type='application/json')
  114. class DeleteCensoredView(PermissionRequiredMixin, View):
  115. permission_required = ("gps-logger.markers.change",)
  116. def get(self, request):
  117. counter = censor()
  118. return JsonResponse({'censored': counter})
  119. def censor() -> int:
  120. locations = CensoredLocation.objects.all()
  121. filter = None
  122. for location in locations:
  123. f = Q(location__distance_lte=(location.location, distance_to_decimal_degrees(D(m=location.radius), location.location.y)))
  124. filter = f if filter is None else filter | f
  125. matches = Marker.objects.filter(filter)
  126. counter, _ = matches.delete()
  127. cache.delete('markers')
  128. return counter