Fleet Telemetry Analysis with Flespi's Native Tools: Panel, API, MQTT
There is 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, the timestamp of the last message flespi received from it. Sort that list and you have the single most useful fleet telemetry analysis view that exists: every tracker, ordered by how long it has been silent. What it cannot 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.
In part one we mapped what goes wrong in GPS fleet monitoring at scale: silent devices, parsing failures across mixed tracker fleets, parameter drift, retention costs. This article is the hands-on workflow — running fleet telemetry operations with flespi's native tools only: the panel, the REST API, the MQTT broker, streams, and the analytics engine. Nothing to install except curl, jq, and an MQTT client.
Setup: one scoped token
Everything below authenticates with a flespi token. Don't reuse your master token from 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/calcs) with GET where read-only is enough. Set an expiration. Details in the flespi tokens guide.
export TOKEN="your-flespi-token"
The full REST surface is browsable at the flespi API reference — 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 entity lists that map directly to fleet health:
- Devices — the registry. The
connectedbadge tells you which trackers hold an open TCP session right now. Click a device → Telemetry tab for the last known value of every parameter, each with its own timestamp. - Channels — the ingest points, one per protocol. A channel with zero active connections but a hundred registered devices is your first red flag on a fleet-wide outage.
- Streams — outbound forwarding. Watch the queue size: a growing queue means your downstream consumer is down and flespi is buffering.
- Logs (Toolbox) — every entity has a Logs tab powered by Toolbox. On a channel, this is where protocol-level errors live: malformed frames, rejected logins from unknown idents, connection drops. On a device, it shows registration and message-receipt events.
The panel is excellent for spot checks on one device. It does not 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 filters to devices whose last message is older than six hours:
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 is connected: true but silent for hours is buffering or misconfigured (alive socket, no data). A device that is disconnected and silent is offline — SIM, power, or coverage. Two different investigations; one query separates them. Pick a silence threshold per tracker class: 6 hours is reasonable for vehicles reporting every 30–60 seconds, 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 you 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 gives you 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 store-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 means 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 API 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 — parse errors 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 — handy for dashboards. This is the cheapest live GPS fleet monitoring rig you will 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 — check the queue counter in the panel after any downstream outage. For event-shaped notifications rather than firehose forwarding (e.g., “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": [
{"type":"mileage","name":"distance"},
{"type":"datetime","name":"started"},
{"type":"duration","name":"seconds"}
],
"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 your counters computed — distance, start time, duration. Invert the selector logic (speed absent or zero for N minutes) and the same machinery gives you stop detection. Intervals recalculate automatically when late store-and-forward messages arrive, which is exactly the behavior you want with cellular trackers. The engine runs inside flespi, so you are not hauling raw messages out just to compute mileage — see the flespi knowledge base for the full counter catalog.
Where the DIY toolkit stops
Run all five of these and you have a genuinely solid operations setup — better than most fleet platforms expose. But be honest about its shape:
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 you problems only while someone is watching it. Neither closes the loop.
Detection is not diagnosis. Your jq filter says device 8127 has been silent for four days. It does not check whether the channel logged a protocol error, whether the last messages showed a dying battery voltage, or whether nine other devices on the same channel went quiet the same hour. A human does that — 20 to 40 minutes per device, across logs, message history, and channel state.
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 can tell you the fleet's pulse. They cannot chase down why a device flatlined.
What comes next
Everything in this guide can run continuously instead of on demand. CloudThinker agents connect to the flespi API with a read-only scoped token, run these sweeps around the clock, and — the part no script does — investigate: correlating device silence with channel logs, message history, and fleet-wide patterns before proposing a fix for your approval. That's part three of this series.
Or point it at your own fleet first: Try CloudThinker free — 100 premium credits, no card required.
