DEV Community

Anhaj Uwaisulkarni
Anhaj Uwaisulkarni

Posted on Fully Autonomous

BusLink Design Review: Five Failure Cases Between an ESP32 Camera and a Live Dashboard

An ESP32-CAM, a GPS receiver and a cloud backend can demonstrate live transit tracking. The harder question is what the dashboard should show when one stage fails.

This review revisits the architecture in my two BusLink articles. It describes improvements to evaluate, not completed field tests or measured production results.

1. The sender and receiver disagree about the image format

Part 1 describes multipart uploads, while the FastAPI example in Part 2 reads raw request-body bytes. Those examples need a shared contract before they can be combined.

Choose either a raw JPEG body with the appropriate content type, or a multipart image field parsed by the server. If the server treats multipart boundaries as image bytes, image decoding can fail even though the HTTP request arrived.

2. A socket accepts only part of a chunk

The hardware example sends images in 1,024-byte pieces. That keeps transmission incremental, but a chunk size does not prove delivery. The sender needs to check the byte count returned by each write, advance by that count and handle timeouts. It also needs to inspect the final HTTP response.

Test a connection that drops halfway through an image. The expected result should be a rejected incomplete upload and a bounded recovery attempt, rather than a valid-looking observation with missing data.

3. Zero passengers and a failed model look identical

The earlier cloud example initializes counts to zero and chooses a fallback based on whether counts are positive. That makes an empty bus hard to distinguish from an unavailable model.

Use separate fields for the estimate and its state. For example, a result can have status "ok" and count 0, or status "timeout" and count null. Combining estimates should consider only successful results. If both fail, show "crowd estimate unavailable."

Running two model calls concurrently can reduce waiting compared with sequential execution. It does not guarantee either service will respond or that the counts will be accurate.

4. Slow inference holds up location updates

Position telemetry and camera analysis have different costs. A bus can send fresh coordinates even when an AI service is slow. A useful next iteration would publish validated location telemetry independently, then attach a crowd estimate when analysis completes.

Associate both results with an observation identifier and capture time so a late model response cannot silently replace a newer estimate.

5. Old data still looks live

A dashboard needs to communicate freshness. Store capture time as well as server receipt time, and display the age of the latest observation. After a connection outage, an old GPS position should be labeled as last known.

Freshness thresholds depend on the expected update interval. Decide those thresholds during field testing, then make the stale state understandable without relying only on color.

A small evaluation plan

Start with controlled failure cases: incomplete uploads, missing GPS, one model timeout, both models unavailable and delayed observations arriving out of order. Check the resulting database state and the passenger-facing display.

Then measure upload latency and compare crowd estimates with labeled samples. Set image access and retention rules before collecting passenger imagery. These steps would produce evidence for reliability and accuracy claims; the original architectural examples alone do not establish them.

Project links

About the author: Anhaj Uwaisulkarni is a computer vision and full-stack engineer based in Colombo and Founder of AstriX.

Top comments (1)

Collapse
 
raknaos profile image
Raknaos

"Zero passengers and a failed model look identical" is the bug every pipeline that summarizes model output eventually grows. Separating value from state — ok with 0 versus timeout with null — and only combining successful results is the honest fix, and it generalizes way beyond transit: most dashboards render an empty list and an error the same way.

On the incremental send: was the weak link the embedded HTTP client returning success on a short write, or the TLS session dropping mid-image? I ask because I keep seeing "sent N bytes" treated as "the server accepted N bytes" in device stacks — those are two different claims, and only the response code proves the second one.