Skip to content

Instantly share code, notes, and snippets.

@knabben
Last active August 25, 2019 01:17
Show Gist options
  • Select an option

  • Save knabben/c48bcd60b8442714a30e2285cd5c6022 to your computer and use it in GitHub Desktop.

Select an option

Save knabben/c48bcd60b8442714a30e2285cd5c6022 to your computer and use it in GitHub Desktop.
Real time tracking
import json
from channels import Group
from ws.models import LocateObject, LocatePath
from django.core.serializers import serialize
def ws_add(message):
message.reply_channel.send({'accept': True})
Group("path").add(message.reply_channel)
multi_point = serialize(
'geojson', LocatePath.objects.all(),
geometry_field='path', fields=('locate',)
)
Group("path").send({'text': json.dumps(multi_point)})
class LocateObject(models.Model):
name = models.CharField(max_length=30)
start_point = models.PointField()
end_point = models.PointField()
@transaction.atomic
def save(self, *args, **kwargs):
super(LocateObject, self).save(*args, **kwargs)
self.save_legs_path()
def save_legs_path(self):
for direction in self.get_directions():
path = LocatePath.objects.create_path(self, direction)
for step in direction['legs'][0]['steps']:
LocateLegs.objects.create_leg(self, path, step)
def get_directions(self):
gmaps = googlemaps.Client(key=settings.GOOGLE_MAPS_API)
directions_result = gmaps.directions(
self.start_point.get_coords()[::-1], self.end_point.get_coords()[::-1],
mode='driving', departure_time=datetime.now())
return directions_result
def __str__(self):
return "{} - {} && {}".format(
self.name, self.start_point, self.end_point)
class LocateMixin(object):
@staticmethod
def create_line_string(points):
return LineString(
map(lambda coords: Point(coords[::-1]), polyline.decode(points)))
class LocatePathManager(LocateMixin, models.Manager):
def create_path(self, locate, direction):
points = direction['overview_polyline']['points']
path, created = self.get_or_create(
path=LocatePathManager.create_line_string(points), locate=locate)
return path
class LocatePath(models.Model):
locate = models.ForeignKey(LocateObject, related_name='paths')
path = models.LineStringField()
objects = LocatePathManager()
def __str__(self):
return "Path for {}".format(self.locate.id)
class LocateLegManager(LocateMixin, models.Manager):
def create_leg(self, locate, path, step):
distance = float(step['distance']['text'].split(' ')[0])
points = LocateLegManager.create_line_string(step['polyline']['points'])
duration = step['duration']['text']
leg, created = LocateLegs.objects.get_or_create(
locate=locate,
locate_path=path,
distance=distance,
duration=duration,
leg_point=points)
return leg
class LocateLegs(models.Model):
locate = models.ForeignKey(LocateObject, related_name='legs')
locate_path = models.ForeignKey(LocatePath)
leg_point = models.LineStringField()
distance = models.FloatField()
duration = models.CharField(max_length=30)
objects = LocateLegManager()
from channels.routing import route
from ws.consumers import ws_message, ws_add, ws_disconnect
channel_routing = [
route("websocket.connect", ws_add),
]
def handle(self, *args, **kwargs):
from collections import defaultdict
features = defaultdict(list)
for locate in LocateObject.objects.all():
features[locate.name] = map(
lambda x: json.loads(x.geojson)['coordinates'],
list(locate.legs.all().values_list('leg_point', flat=True))
)
def geo_transform(item):
obj_name, coords = item
return {
"type": "Feature",
"geometry": json.loads(Point(coords).geojson),
"properties": {
"title": obj_name,
"icon": "car"
}
}
legs = min([len(n) for n in features.values()])
for leg in range(0, legs):
points = map(geo_transform, [
(k_obj, features[k_obj][leg].pop()) for k_obj in features.keys()
])
data = {
"type": "geojson",
"data": {
"type": "FeatureCollection",
"features": points
}
}
Group("path").send({'text': json.dumps(data)})
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment