Fleet Telemetry Analysis with Flespi's Native Tools: Panel, API, MQTT
There's one REST call every flespi fleet operator should have aliased:
curl -s "https://flespi.io/gw/devices/all/telemetry/timestamp" \
-H "Authorization: FlespiToken $TOKEN"
It returns, for every device in your account, when flespi last received a message from it. Sort that list and you have the most useful fleet telemetry view there is: every tracker, ordered by how long it has been silent. What it can't tell you is why device 8127 last spoke four days ago. SIM, protocol, channel config, or a tracker face-down in a glovebox? That question is where this whole series is headed.
Part one mapped what goes wrong in GPS fleet monitoring at scale: silent devices, parsing failures across mixed tracker fleets, stream backlogs, parameter drift and retention costs.
This part is the hands-on workflow: running fleet telemetry operations with flespi's native tools only. That means the panel, the REST API, the MQTT broker, streams and the analytics engine. Nothing to install except curl, jq and an MQTT client.
01Look
Panel
Devices, channels, streams and their logs, one entity at a time.
02Sweep
REST API
Fleet-wide questions: who is silent, what did they send, what failed.
03Watch
MQTT
Messages, state and logs live, while someone is looking.
04Forward
Streams
Telemetry out to the systems that need it, buffered on failure.
05Compute
Calculators
Trips, stops and geofence visits computed inside flespi.
Setup: one scoped token
Everything below authenticates with a flespi token. Don't reuse your master token in a cron job. Create a scoped one: flespi.io panel → Tokens → "+", set access to ACL, and grant only the URIs you need (gw/devices, gw/channels, gw/streams, gw/calcs) with GET where read-only is enough. Set an expiration. Details are in the flespi tokens guide.
export TOKEN="your-flespi-token"
The full REST surface is browsable in the flespi API reference, and every request below can be replayed there interactively.
Tool 1: the panel and Toolbox, the visual sweep
Before scripting anything, know what the panel already answers. Under Telematics hub you get four views that map directly to fleet health:
- Devices is the registry. The
connectedbadge shows which trackers hold an open TCP session right now. Click a device, then the Telemetry tab, for the last known value of every parameter, each with its own timestamp. - Channels are the ingest points, one per protocol. A channel with zero active connections but a hundred registered devices is your first red flag for a fleet-wide outage.
- Streams handle outbound forwarding. Watch the queue size: a growing queue means your downstream consumer is down and flespi is buffering.
- Logs (Toolbox) sit behind a Logs tab on every entity. On a channel, that's where protocol-level errors live: malformed frames, rejected logins from unknown idents, connection drops. On a device, it shows connection and message-receipt events.
The panel is excellent for spot checks on one device. It doesn't scale to "which 23 of my 1,400 trackers went quiet this week". That's the API's job.
Tool 2: REST API sweeps, the fleet-wide questions
Which devices are silent?
Take the opening call and make it actionable. This keeps devices whose last message is older than six hours, using the ts field (when flespi received the value) rather than the tracker's own clock:
NOW=$(date +%s)
curl -s "https://flespi.io/gw/devices/all/telemetry/timestamp" \
-H "Authorization: FlespiToken $TOKEN" |
jq --argjson now "$NOW" '
.result[]
| select((.telemetry.timestamp.ts // 0) < ($now - 21600))
| {id, last_seen: (.telemetry.timestamp.ts // 0)}'
Cross-reference the IDs against the registry to get names and connection state:
curl -s "https://flespi.io/gw/devices/all?fields=id,name,connected" \
-H "Authorization: FlespiToken $TOKEN" | jq '.result[]'
How to read it. A device that's connected: true but silent for hours is buffering or misconfigured: a live socket with no data. A device that's disconnected and silent is offline, so think SIM, power or coverage. Two different investigations, separated by one query. Pick a silence threshold per tracker class: 6 hours is reasonable for vehicles reporting every 30 to 60 seconds and far too aggressive for assets that report twice a day.
What did one device actually send?
For any suspect device, pull its stored message history (flespi keeps messages for the TTL configured on the device):
curl -s -G "https://flespi.io/gw/devices/123456/messages" \
-H "Authorization: FlespiToken $TOKEN" \
--data-urlencode 'data={"from":1752364800,"to":1752451200,"count":50,"reverse":true}'
reverse: true returns the newest messages first. Look at the gap pattern. A clean cutoff points at connectivity. Intermittent gaps with position jumps point at coverage. Messages arriving in bursts hours late mean the tracker is storing and forwarding: the device was fine, the network wasn't.
Is the channel parsing what it receives?
Mixed fleets fail at the protocol layer. Pull recent channel logs and look for parse and login failures:
curl -s -G "https://flespi.io/gw/channels/98765/logs" \
-H "Authorization: FlespiToken $TOKEN" \
--data-urlencode 'data={"count":100,"reverse":true}'
How to read it. Repeated connections from an ident that never registers as a device usually mean a tracker configured against the wrong channel (wrong protocol, wrong port). Frame errors on a channel that was healthy last week usually follow a tracker firmware update. Either way, the channel log is the ground truth. The device record can look perfectly normal while the channel rejects every byte it sends.
Tool 3: MQTT, the live view
The flespi platform is also a full MQTT broker. Connect to mqtt.flespi.io with your token as the username and subscribe to platform events in real time. With mosquitto_sub:
# Every message from every device, live
mosquitto_sub -h mqtt.flespi.io -p 8883 --capath /etc/ssl/certs \
-u "$TOKEN" -P any -t "flespi/message/gw/devices/+"
Two more subscriptions worth keeping in a tmux pane during an incident:
# Live telemetry state for one device, one parameter
mosquitto_sub -h mqtt.flespi.io -p 8883 --capath /etc/ssl/certs \
-u "$TOKEN" -P any -t "flespi/state/gw/devices/123456/telemetry/position.speed"
# Platform logs for a channel, so parse errors show up as they happen
mosquitto_sub -h mqtt.flespi.io -p 8883 --capath /etc/ssl/certs \
-u "$TOKEN" -P any -t "flespi/log/gw/channels/98765/+"
The flespi/state/... topics are retained, so a new subscriber immediately gets the last known value, which is handy for dashboards. This is the cheapest live GPS fleet monitoring rig you'll ever build: a broker you already pay for and a client from your package manager.
Tool 4: streams and webhooks, getting data out
When another system needs the telemetry (a warehouse, an alerting pipeline, a customer), don't poll. Forward. A stream pushes every message from subscribed devices to an external endpoint:
# Create an HTTP stream
curl -s -X POST "https://flespi.io/gw/streams" \
-H "Authorization: FlespiToken $TOKEN" \
-d '[{"name":"ops-forwarder","protocol_name":"http",
"configuration":{"uri":"https://ingest.example.com/telemetry"}}]'
# Subscribe every device to it (use a selector for a subset)
curl -s -X POST "https://flespi.io/gw/streams/11111/devices/all" \
-H "Authorization: FlespiToken $TOKEN"
Streams buffer when the destination is down and replay on recovery, so check the queue counter in the panel after any downstream outage. For event-shaped notifications rather than a firehose ("POST to my endpoint when a device's telemetry matches a condition"), use platform webhooks (panel → Webhooks), which trigger off the same MQTT topics you subscribed to above.
Tool 5: the analytics engine, trips and stops without code
Raw messages tell you where a vehicle was. Calculators turn them into intervals: trips, stops, geofence visits. A minimal trip detector, splitting intervals on position.speed > 0:
curl -s -X POST "https://flespi.io/gw/calcs" \
-H "Authorization: FlespiToken $TOKEN" \
-d '[{
"name": "trips",
"selectors": [{"type":"expression","expression":"position.speed > 0"}],
"counters": [
{"name":"distance","type":"expression","expression":"mileage()","method":"summary"},
{"name":"max_speed","type":"expression","expression":"position.speed","method":"maximum"}
],
"intervals_ttl": 2592000
}]'
Assign devices, then read the computed intervals:
curl -s -X POST "https://flespi.io/gw/calcs/22222/devices/123456" \
-H "Authorization: FlespiToken $TOKEN"
curl -s -G "https://flespi.io/gw/calcs/22222/devices/123456/intervals/all" \
-H "Authorization: FlespiToken $TOKEN" \
--data-urlencode 'data={"count":20,"reverse":true}'
Each interval comes back with begin, end and duration built in, plus your counters: distance from the built-in mileage() function, and the top speed. Invert the selector (speed absent or zero for N minutes) and the same machinery gives you stop detection. Intervals recalculate when late store-and-forward messages arrive, which is exactly what you want with cellular trackers. The engine runs inside flespi, so you're not hauling raw messages out just to compute mileage. The flespi knowledge base has the full counter catalog.
One silent device, investigated by hand
Back to device 8127 from the opening. Here's the investigation the tools above support, done the way an experienced fleet engineer would. The details are illustrative. Name the readings first, because each predicts different evidence:
- Parked. Predicts a clean disconnect after an ignition-off message, and nothing wrong in any log.
- Cellular. Predicts falling signal and short reconnect bursts in the hours before the silence.
- Protocol. Predicts connection attempts in the channel log that never produce messages.
- Hardware. Predicts power or GPS-fix trouble in the last messages, then nothing.
Is it connected? The registry says connected: false. That rules out protocol as the main story, since a protocol fault usually leaves the tracker connecting and failing.
What did the last messages say? Pull the final hour before silence and keep only the fields that separate the readings:
curl -s -G "https://flespi.io/gw/devices/8127/messages" \
-H "Authorization: FlespiToken $TOKEN" \
--data-urlencode 'data={"count":60,"reverse":true,"fields":"timestamp,gsm.signal.level,position.satellites,external.powersource.voltage,engine.ignition.status"}'
Ignition was on, external power steady at 13.8 V, satellites normal. Signal level, though, dropped from 24 to 3 over the last forty minutes. Parked and hardware both look unlikely.
What does the device log show? The device's Logs tab in the panel (or /gw/devices/8127/logs) shows eleven connect and disconnect events in that same forty minutes, then nothing. That's the flapping signature of a cellular problem.
Is it alone? Run the silent-device sweep again for the same four-hour window, then compare last positions. Two other trackers went quiet within the same hour, and all three were last seen on the same stretch of highway.
Conclusion. Probable coverage gap or carrier problem in one region, not three broken trackers. The right next step is a carrier check, not three technician visits. That took about thirty minutes, for one device, by someone who knew where to look.
What the native tools cover, and what they don't
| Question | Best native tool | What's left for a person |
|---|---|---|
| Which devices are silent? | REST telemetry sweep | Choosing a threshold per tracker class |
| Why did this one go silent? | Messages, device logs, channel logs | Reading all three and ruling causes out |
| Is a channel parsing correctly? | Channel logs, MQTT log topics | Linking errors to a firmware rollout |
| Is delivery working? | Stream queue in the panel, stream logs | Noticing before the "map is frozen" ticket |
| Did parameters drift? | Telemetry keys per model | Knowing which parameters reports depend on |
| Trips and stops | Calculators | Keeping the selectors right as fleets change |
The native tools are good at answering a question you already asked. Every row's right column is a judgment, and none of them runs while you're asleep.
Where the DIY toolkit stops
Run all five tools and you have a solid operations setup, better than most fleet platforms expose. Be honest about its shape, though:
01Limit 1
Snapshot or firehose
A sweep describes the moment you ran it; MQTT shows problems only while someone watches.
02Limit 2
Detection, not diagnosis
The filter says a device is silent. Working out why is 20 to 40 minutes of a person’s time.
03Limit 3
Scripts rot
Tokens expire, the author moves on, and fleet health becomes whatever the cron job last did.
Everything above is a snapshot or a firehose. The silent-device sweep describes the fleet at the moment you ran it. The MQTT pane shows problems only while someone watches it. Neither closes the loop.
Detection isn't diagnosis. Your jq filter says device 8127 has been silent for four days. It doesn't check whether the channel logged a protocol error, whether the last messages showed a dying signal, or whether nine other devices on the same channel went quiet the same hour. A person does that, 20 to 40 minutes per device, across logs, message history and channel state, exactly like the walkthrough above.
Scripts rot. The cron job that curls the telemetry endpoint was written by one engineer, alerts to one Slack channel, and silently breaks when the token expires. Six months in, "fleet health" is whatever the last person to touch the script decided it was.
Exports and dashboards tell you the fleet's pulse. They can't chase down why a device flatlined.
What comes next
Everything in this guide can run continuously instead of on demand. CloudThinker connects to the flespi API with a read-only scoped token, runs these sweeps around the clock, and does the part no script does: the investigation you just did by hand for device 8127, for every silent device, before anyone looks. Fixes go through Auto Mode, so you decide what runs on its own and what waits for approval. That's part three of this series.
Related reading
- Part one: fleet telemetry analysis on flespi, what breaks at scale
- How an Australian telematics provider automates day-to-day operations with CloudThinker
- CloudThinker Connections
Or point it at your own fleet first: try CloudThinker free with 100 premium credits and no card required.
