EH/KIM/fr-a2-mqtt-event-handling - #961
Open
kimmynoto wants to merge 6 commits into
Open
Conversation
- Build MQTT client service that connects to broker and subscribes to live event topics - Add graceful startup handling so a failed connection retries in background instead of crashing the API - Implement reconnect-with-backoff - Add /mqtt/connection-state endpoint to expose live connection status - Normalize incoming vocalization event payloads into a consistent shape - Add frontend polling + page banner/toast notifications showing connection state (connected/reconnecting/disconnected) and alerting users on connection loss/recovery
AnDo081105
reviewed
Aug 8, 2026
AnDo081105
left a comment
Contributor
There was a problem hiding this comment.
P1 findings from the FR-A2 review.
- Subscribe to the correct live-event topic (MQTT_PUBLISH_URL / projectecho/engine/2) instead of the wrong hardcoded topic, and make broker/topic config env-var driven in docker-compose - Store normalized events (keyed by sensorId) and expose them via a new /mqtt/latest-events endpoint, so the frontend/dashboard can actually consume live data - Fix frontend polling: a failed connection-state request now shows an unavailable banner instead of silently logging to console
AnDo081105
reviewed
Aug 9, 2026
AnDo081105
left a comment
Contributor
There was a problem hiding this comment.
Additional FR-A2 review findings.
- /mqtt/latest-events now sources data from the Backend/DB (Events collection) instead of the raw MQTT topic, matching the architecture: Engine prediction -> Backend/DB -> /mqtt/latest-events -> HMI -> map - Added show_latest_events() in hmi.py, reusing the same aggregate + species pattern already used by /events_time, so commonName/type/status/diet are real enriched values instead of placeholders - Restored the /mqtt/connection-state endpoint, which was accidentally dropped while cleaning up a duplicate route earlier - Verified end-to-end against real inserted test data: species metadata correctly enriched, events reaching and rendering on the map with no errors
AnDo081105
reviewed
Aug 21, 2026
| @app.get("/mqtt/latest-events", tags=["mqtt"]) | ||
| def mqtt_latest_events(): | ||
| from app.routers.hmi import show_latest_events | ||
| return {"events": show_latest_events(limit=20)} |
Contributor
There was a problem hiding this comment.
Suggested change
| return {"events": show_latest_events(limit=20)} | |
| @app.get("/mqtt/latest-events", tags=["mqtt"]) | |
| def mqtt_latest_events(): | |
| from app.routers.hmi import show_latest_events | |
| events = [ | |
| {"eventType": "vocalization", **event} | |
| for event in show_latest_events(limit=20) | |
| ] | |
| events += [ | |
| event for event in get_latest_events() | |
| if event.get("eventType") != "vocalization" | |
| ] | |
| return {"events": events} |
AnDo081105
reviewed
Aug 21, 2026
|
|
||
| MQTT_BROKER_URL = os.environ.get("MQTT_BROKER_URL", "ts-mqtt-server-cont") | ||
| MQTT_BROKER_PORT = int(os.environ.get("MQTT_BROKER_PORT", 1883)) | ||
| MQTT_TOPIC = os.environ.get("MQTT_PUBLISH_URL", "projectecho/engine/2") |
Contributor
There was a problem hiding this comment.
Suggested change
| MQTT_TOPIC = os.environ.get("MQTT_PUBLISH_URL", "projectecho/engine/2") | |
| MQTT_TOPICS = os.environ.get( | |
| "MQTT_TOPICS", | |
| "projectecho/engine/2,projectecho/movement,iot/data/test", | |
| ).split(",") | |
| def on_connect(client, userdata, flags, rc): | |
| global connection_state | |
| connection_state = "connected" | |
| for topic in MQTT_TOPICS: | |
| client.subscribe(topic.strip()) |
Contributor
|
Code suggestion: publish movement events to the MQTT feed. GitHub cannot attach this inline because This keeps the existing HTTP persistence and adds the MQTT-derived movement event required by FR-A2. |
AnDo081105
reviewed
Aug 21, 2026
AnDo081105
left a comment
Contributor
There was a problem hiding this comment.
I have made some suggestions based on my findings. Have a look and re-check to see whether I missed anything. Thank you so much:D
- Merge database-sourced (enriched vocalization) events and in-memory MQTT-derived events (movement, sensor-health, IoT-node) into a single /mqtt/latest-events response - Subscribe to multiple MQTT topics (vocalization, movement, IoT) via a comma-separated MQTT_TOPICS env var, instead of a single hardcoded topic - Simulator now also publishes movement events to MQTT (projectecho/movement), alongside its existing HTTP persistence, so movement data is actually available on the live feed - Frontend now dispatches a mqtt:<eventType> custom event for sensor_health/iot_node instead of silently dropping them, so future rendering code can listen for them - Fixed a bug this introduced: added placeholder type/status/diet fields to normalized movement events, since the existing convertJSONtoAnimalMovementEvent function required them and was throwing on undefined values
AnDo081105
approved these changes
Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
This implements FR-A2 (Live MQTT Event Handling). There wasn't actually any MQTT connection in the codebase before this just a placeholder variable waiting for a handler that never got built. So this PR builds that whole piece from scratch such as connecting to the broker, tracking connection state, cleaning up incoming data, and letting users know when the connection drops or comes back.
What's in this PR
How I tested it