def create(self, validated_data): provider_id = self.context["request"].user.provider_id unknown_ids = [ str(id) for id in (set(t["device_id"] for t in validated_data["data"]) - set( models.Device.objects.filter( id__in=[t["device_id"] for t in validated_data["data"]]). filter(provider_id=provider_id).values_list("id", flat=True))) ] if unknown_ids: raise ValidationError( {"data.device_id": "Unknown ids: %s" % " ".join(unknown_ids)}) event_records = (models.EventRecord( timestamp=telemetry["timestamp"], point=gps_to_gis_point(telemetry.get("gps", {})), device_id=telemetry["device_id"], event_type=enums.EVENT_TYPE.telemetry.name, properties={ "telemetry": telemetry, "trip_id": None }, ) for telemetry in validated_data["data"]) db_helpers.upsert_event_records(event_records, enums.EVENT_SOURCE.agency_api.name, on_conflict_update=True) # We don't have the created event records, # but we will return an empty response anyway (cf. DeviceViewSet) return []
def _create_missing_devices(self, status_changes): """Make sure all devices mentioned exist""" with_missing_devices = [ status_change for status_change in status_changes if status_change["device_id"] not in self.device_uids ] if with_missing_devices: db_helpers.upsert_devices( (_create_device(status_change) for status_change in with_missing_devices)) # Create fake register events to simulate device registration db_helpers.upsert_event_records( (_create_register_event_record(status_change) for status_change in with_missing_devices), source=enums.EVENT_SOURCE.provider_api.name, ) devices_added = [ status_change["device_id"] for status_change in with_missing_devices ] self.device_uids.update(devices_added) logger.info("Devices created: %s", ", ".join(str(uid) for uid in devices_added))
def _create_event_records(self, status_changes): """Now record the... records""" db_helpers.upsert_event_records( (_create_event_record(status_change) for status_change in status_changes), enums.EVENT_SOURCE.provider_api.name, # Timestamps are unique per device, ignore duplicates # Events already pushed by the provider will always have precedence on_conflict_update=False, )
def create(self, validated_data): device = self.context["device"] event_record = models.EventRecord( timestamp=validated_data["timestamp"], point=gps_to_gis_point(validated_data["telemetry"].get("gps", {})), device_id=device.id, event_type=validated_data["event_type"], properties={ "telemetry": validated_data["telemetry"], "trip_id": validated_data.get("trip_id"), }, ) db_helpers.upsert_event_records([event_record], enums.EVENT_SOURCE.agency_api.name, on_conflict_update=True) # We don't get the created event record but we need to return it return models.EventRecord.objects.get( device=device, timestamp=validated_data["timestamp"])
def test_upsert_event_record(): device = factories.Device() # Same event_record = factories.EventRecord.build(device=device) db_helpers.upsert_event_records([event_record], "push") assert models.EventRecord.objects.get()