Trips and stops
Reference for trips and stops: timelines derived from the message archive, the segmentation policy that cuts them, and the options that shape returned points.
Trips and stops derived from the message archive on read, with the segmentation policy and point options that shape them.
Queries
deviceTimeline
Trips and stops of one device over a window.
segmentation applies only to devices that carry no policy of their own; the result reports which policy actually applied.
Fails with VALIDATION_ERROR, before any data is read, when from is not before to (field to), when options.maxPoints is zero or negative (field options.maxPoints), or when segmentation holds an invalid value (TrackingSegmentationInput). The check does not depend on the device: an invalid request fails the same way for a device the caller cannot see.
deviceTimeline(
deviceId: ID!
from: DateTime!
to: DateTime!
segmentation: TrackingSegmentationInput
options: TrackingTrackOptions
): TrackingTimelineArguments
Input types:
Output types:
assetTimeline
Trips and stops of an asset over a window, per device. An asset with several devices yields one timeline per device — the same no-merge rule as state.
Validated as deviceTimeline is, including for an asset without devices, which would otherwise answer [].
Arguments
Input types:
Output types:
Objects
TrackingSegmentationApplied
The segmentation policy that actually produced the result, and where it came from.
TrackingTrack
A trip — a movement segment between two stops.
id identifies the trip within one response, nothing more. It is a hash over the device, the request's parameters and the segment's bounds, so an identical request reproduces it, and any change to the window or the segmentation policy does not. The device is part of the hash because assetTimeline returns one timeline per device from a single request: two trackers on the same vehicle, parked together, produce trips with identical bounds, and without the device in the hash a UI holding a selection by id would highlight both.
Nothing stores it, Query.node does not resolve it, and no query takes it as an argument — use it to correlate a trip with a client-side selection inside a single answer, not to link to a trip later.
endedAt is the last point's own time when the trip simply ends there — the device stopped, or the requested window ended with nothing left to cut. A server-side budget (TrackingTimeline.continueFrom) that lands inside the trip instead moves endedAt to continueFrom itself, one moment past that last point; endPoint still names the last point's own coordinates. That is what makes the next page's first trip — which starts at from, itself set to that same continueFrom — touch this one exactly, with no gap and no overlap; id differs per part because the bounds differ. The same rule, for stops, is on TrackingStop.duration.
Figures summed across pages equal a one-page answer only in two cases: the cut falls while the device is moving, or it falls inside a stop whose parts on both sides of the cut each last at least minStopDuration. When the still period that crosses the cut is shorter than minStopDuration on either side, each page classifies its part on its own: a page can end a trip at the cut that a one-page answer continues through a pause, or split a stop into parts too short to count as one, so stops, the number of trips, duration and pointCount can differ from the one-page answer. A caller that needs figures independent of paging requests windows short enough for continueFrom to stay null.
Typed String!, not ID!, and that is not cosmetic: the gateway's DGS codegen maps every ID in the schema to com.navixy.uuid.UuidV8 (api-gateway/build.gradle.kts typeMapping), a value class with a fixed layout — 48 time bits, version, counter, a four-character entity discriminator. A content hash is not expressible in it, and squeezing one into the deterministic constructor's 16-bit suffix would collide inside a single response, destroying the very distinction the device-in-the-hash rule above exists to make.
id
String!
distance
Float!
Trip length, km. Includes the leg from the last still point before the trip to its first moving point, which startedAt already dates at that still point. LAST_KNOWN repeats are excluded from the sum (STORAGE.md §Как отобрать).
maxSpeed
Float
avgSpeed
Float
pointCount
Int!
simplified
Boolean!
True when points was thinned to fit TrackingTrackOptions.maxPoints.
TrackingStop
A stop — the device stayed within stopRadius for at least minStopDuration. id is response-scoped, and String! rather than ID!, on the same terms as TrackingTrack.id.
id
String!
endedAt
When the stop ended. Null for a stop still in progress at the end of the requested window — including the current one, which is the usual case for to = now.
duration
How long the stop lasted. For a finished stop, endedAt - startedAt. For one still in progress — endedAt: null — it is measured to the end of what this answer actually covers: min(to, now), or continueFrom when a server-side budget cut the window short. That is not the same bound as to, because truncation can land inside a stop. Never past the end of the requested window and never into the future, so the same to in the past yields the same duration on every call. A stop the truncation cut continues in the next page as a stop of its own, starting where that page starts: the parts are adjacent rather than overlapping, and when each part lasts at least minStopDuration the stop time summed across pages is the total. A part shorter than that does not count as a stop on its page, so the stop can be missing there and the sum falls short; see TrackingTrack for the cases. Separately, the case that does not settle is a to in the future — the window has not closed, min(to, now) is now, and the duration grows between calls. That is the honest answer for an open window rather than a defect.
messageCount
Int!
Number of messages received during the stop.
TrackingTrackPoint
altitude
Float
speed
Float
heading
Float
satellites
Int
timeSource
Where at came from; see TrackingPosition.timeSource. A SERVER or DEVICE_CORRECTED point stands at its upload moment.
readings
[TrackingReading!]!
Readings from the message this point came from, when the query asked for them.
TrackingTimeline
Trips and stops of one device over a window, plus the policy that produced them.
totalDistance
Float!
Sum of TrackingTrack.distance, km.
totalStopTime
Sum of stop durations, an unfinished stop counted per TrackingStop.duration — which bounds it by what this answer covers, not by to, when continueFrom is set. Stable for a to in the past; grows between calls for a to in the future, for the same reason.
continueFrom
Where the answer stops when a server-side budget cut the window short — pass it back as the next call's from. Null means the whole window was covered. Figures summed across the pages of a cut window equal a one-page answer only in the cases listed on TrackingTrack; otherwise the still period crossing a cut, and the trips beside it, can be classified and measured differently. A cursor rather than a boolean flag: truncation can land inside a stop, or leave tracks empty with only stops cut, and then "continue from the last segment's end" names nothing. The budget itself exists because segmentation re-reads the window's raw points on every call.
Inputs
TrackingSegmentationInput
How a device's message stream is cut into trips and stops.
Resolution order per device: the device's own policy, else the policy supplied with the request, else the platform default. TrackingSegmentationApplied.source reports which one was used, so a caller never has to guess whether its request-level policy took effect.
The platform default is a deployment setting, the same one the live motion status is folded with (nvx4.tracking.fold.stop-radius-meters, moving-speed-threshold-kmh and min-stop-duration), so a timeline and TrackingDeviceState.motion use one stop policy unless a request overrides it.
Values are validated before any data is read: a non-positive minStopDuration, or a negative or non-finite stopRadius or movingSpeedThreshold, fails with VALIDATION_ERROR naming the field (segmentation.minStopDuration, segmentation.stopRadius, segmentation.movingSpeedThreshold). Zero is accepted for stopRadius and movingSpeedThreshold.
minStopDuration
How long a device must stay put before the pause counts as a stop and cuts the trip. A shorter pause is neither: it appears in no stops entry and the trip runs through it. Longer than the window, no pause qualifies: stops is empty and whatever movement the window holds is one trip, the shape nvx3's split: false returned. A window without movement yields no trip either way, and a server-side cut (TrackingTimeline.continueFrom) still splits the answer. Must be positive.
stopRadius
Float
Radius, metres, within which points count as the same place rather than movement. Not negative.
movingSpeedThreshold
Float
Speed at or below which the device counts as not moving, km/h. Not negative.
TrackingTrackOptions
fitness
Which points to include. Defaults to the track filter from STORAGE.md — [GNSS, NETWORK]. Adding LAST_KNOWN puts the repeated last position on the map, which is where it belongs; it never enters distance, whatever this argument says, because a stop in a tunnel would otherwise read as a trip (STORAGE.md §Как отобрать пригодные точки).
includePoints
Boolean
Return the points of each trip, not just its summary. Off by default — points dominate the payload.
maxPoints
Int
Thin each trip's polyline to at most this many points (Douglas–Peucker). Null disables thinning; zero or negative fails with VALIDATION_ERROR.
eventCodes
[Code!]
Include only these event codes on segments and points. Empty list — the default — includes none; null includes all, which is rarely what a caller wants: a level alarm re-fires in every message while it holds (SPEC §6.5), so a day of a stuck input is thousands of identical objects. The service collapses a repeated level alarm into one event with since set; this argument is the second lever.
Enums
TrackingSegmentationSource
DEVICE
The device carries its own segmentation policy, which overrides the request.
REQUEST
The policy supplied with the request applied — the device has none of its own.
PLATFORM_DEFAULT
Neither device nor request supplied one; the platform default applied. The values are TrackingWorkspaceSettings.statusThresholds (minStopDuration, stopRadius, movingSpeedThreshold).
See also
Last updated
Was this helpful?