views.py 5.0 KB

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