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 []
Exemple #2
0
def _create_event_record(status_change):
    properties = {"trip_id": status_change.get("associated_trip")}

    event_location = status_change["event_location"]
    if event_location:
        # GeoJSON Point Feature
        try:
            longitude, latitude, altitude = event_location["geometry"][
                "coordinates"]
        except ValueError:
            longitude, latitude = event_location["geometry"]["coordinates"]
            altitude = None
        point = geos.Point(longitude, latitude, altitude, srid=4326)
        properties["telemetry"] = {
            "timestamp": event_location["properties"]["timestamp"],
            "gps": {
                "lng": longitude,
                "lat": latitude
            },
            # No coordinates, no battery charge saved
            "battery_pct": status_change.get("battery_pct"),
        }
        if altitude:
            properties["telemetry"]["gps"]["altitude"] = altitude
    else:  # Spec violation!
        point = None

    return models.EventRecord(
        device_id=status_change["device_id"],
        timestamp=utils.from_mds_timestamp(status_change["event_time"]),
        point=point,
        event_type=status_change["agency_event_type"],
        properties=properties,
    )
Exemple #3
0
def _create_event_record(status_change):
    properties = {"trip_id": status_change.get("associated_trip")}

    event_location = status_change["event_location"]
    if event_location:
        # GeoJSON Point Feature
        try:
            longitude, latitude, altitude = event_location["geometry"]["coordinates"]
        except ValueError:
            longitude, latitude = event_location["geometry"]["coordinates"]
            altitude = None
        point = geos.Point(longitude, latitude, altitude, srid=4326)
        properties["telemetry"] = {
            "timestamp": event_location["properties"]["timestamp"],
            "gps": {"lng": longitude, "lat": latitude},
            # No coordinates, no battery charge saved
            "battery_pct": status_change.get("battery_pct"),
        }
        if altitude:
            properties["telemetry"]["gps"]["altitude"] = altitude
    else:  # Spec violation!
        point = None

    publication_time = None
    if status_change.get("publication_time"):
        publication_time = utils.from_mds_timestamp(status_change["publication_time"])
    # "Aggregation" providers store a recorded field, and we want to keep the same value
    # until we get the publication_time everywhere
    # Vendor only, 0.3 only, will disappear
    recorded = None
    if status_change.get("recorded"):
        recorded = utils.from_mds_timestamp(status_change["recorded"])
    if publication_time and recorded:
        difference = abs(publication_time - recorded)
        if difference > datetime.timedelta(minutes=10):
            logger.warning("publication_time and recorded differ by %s", difference)

    return models.EventRecord(
        device_id=status_change["device_id"],
        timestamp=utils.from_mds_timestamp(status_change["event_time"]),
        point=point,
        event_type=status_change["agency_event_type"],
        event_type_reason=status_change["agency_event_type_reason"],
        properties=properties,
        publication_time=publication_time or recorded,
    )
    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"])
Exemple #5
0
def _create_register_event_record(status_change):
    """
    As the goal of the poller is to catch up with the history of a provider,
    simulate the registration of a device with a fake register event.

    This fake event is flagged in its properties to tell it apart from real ones.

    Should the device be unregistered and registered again according to the specs,
    don't delete the fake events in the past.
    """
    return models.EventRecord(
        device_id=status_change["device_id"],
        # Another event for the same device with the same timestamp will be rejected
        timestamp=utils.from_mds_timestamp(status_change["event_time"]) -
        datetime.timedelta(milliseconds=1),
        event_type=enums.EVENT_TYPE.register.name,
        properties={"created_on_register": True},
        source=enums.EVENT_SOURCE.provider_api.name,
    )