Case study
SDMIS — Emergency Operations Center
A distributed platform connecting command operators, field crews, live telemetry and automated dispatch decisions.

Developed as part of the 4IRC Scientific Project at CPE Lyon, the system is based on the operational context of the SDMIS in Lyon and Villeurbanne (France). The objective was not only to build a web interface, but to design the entire chain connecting incidents, command operators, field crews, vehicles, radio devices and automated decision-making.
Our team of four students worked across software, infrastructure and embedded systems. The result is a distributed platform composed of several applications and services, all available through the CPE-4IRC GitHub organization.

From an emergency call to a dispatched vehicle
The QG application is the main interface used by command operators. It provides a live map of Lyon, a global view of active incidents and the current location and availability of emergency vehicles.
Operators can create incidents, inspect their different operational phases and request an assignment proposal. The interface then displays the vehicles recommended by the decision engine, along with their distance, estimated arrival time and the resources that may still be missing. Proposals remain under human control and can be validated or rejected before resources are committed.
Updates are streamed to the interface using Server-Sent Events, allowing incidents, positions and assignments to evolve without requiring the page to be refreshed.
The separate field application gives firefighters access to their vehicle and current intervention. It provides navigation information, live operational updates and tools to report changes from the field.
A distributed and event-driven system
The project is split into several independent components rather than one large application.
- Two Next.js frontends provide dedicated interfaces for command operators and field crews.
- A secured FastAPI service exposes the business API, stores operational data in PostgreSQL and streams live updates to connected clients.
- RabbitMQ carries events between the API, simulators, radio gateway and decision engine.
- A standalone Java engine processes assignment requests and proposes the most suitable vehicles.
- Keycloak provides centralized authentication and role-based access control.
- Incident and vehicle simulators make it possible to test complete scenarios without real emergency resources.
- A radio chain based on micro:bit devices reproduces the transmission of vehicle telemetry from the field.
This separation was important because the simulated components had to remain replaceable. A simulated vehicle and a real radio-equipped vehicle should ultimately produce the same events without forcing the rest of the system to change.
IMAGE 2 — Complete system architecture
Connecting the field through radio telemetry
The IoT part reproduces how vehicles could send their position and operational status from the field.
Vehicle devices transmit different types of messages, including periodic GPS coordinates and on-demand status changes. A central micro:bit receiver collects the radio frames and forwards them through a Python gateway to the rest of the platform.
The communication protocol had to support several constraints at once: small payloads, unreliable radio conditions, message integrity and different transmission modes. The software architecture also had to behave identically when telemetry came from physical micro:bit devices or from the standalone vehicle simulator.
IMAGE 3 — Field application and IoT chain
Two-part visual:
- On the left, a screenshot of the Terrain application showing a selected vehicle and its current intervention.
- On the right, a photo of the micro:bit transmitter, receiver and USB-connected gateway used during the demonstration.
My contribution: the decision engine and assignment workflow
My main responsibility was the Java decision engine and its integration with the rest of the system.
I built the initial engine structure around typed environment configuration, PostgreSQL access through HikariCP and RabbitMQ messaging. I also implemented connectivity checks, structured logging, resource lifecycle management and graceful shutdown so the service could run reliably as a standalone process.
The engine listens for assignment requests and evaluates the available resources for each phase of an incident. It considers constraints such as vehicle type, availability, distance, estimated arrival time and energy level, then produces a ranked proposal while identifying any resources that are still missing.
I also worked across the FastAPI backend and the QG frontend to integrate this workflow end to end. This included adapting API routes and data structures, requesting proposals for individual incident phases and presenting the results directly inside the incident card so operators could validate or reject them without switching context.
The Java engine was containerized with Docker and packaged as a standalone executable JAR. I also added its CI/CD pipeline to automatically compile the project and run its test suite.
IMAGE 4 — Assignment proposal
Add a focused screenshot of an incident card containing a generated vehicle-assignment proposal. The image should show the recommended vehicles, their ranking or distance, and the validation controls.
If the interface does not fit cleanly in one screenshot, combine it with a small flow:
Incident → RabbitMQ → Java Engine → Proposal → Operator validation
What made the project difficult
The hardest part was not building any individual service. It was keeping the contracts between all of them consistent.
An incident created by the simulator had to be stored by the API, forwarded through RabbitMQ, processed by the Java engine, returned as an assignment proposal and displayed correctly in the QG interface. A small change to an event payload could affect several repositories at once.
This forced us to think carefully about data structures, service boundaries, failure handling and documentation. It also made integration work just as important as writing the individual components.
The project gave me practical experience with event-driven architecture, real-time interfaces, authentication, embedded communication and distributed debugging. More importantly, it showed how quickly a system becomes complex once software, infrastructure and hardware all need to agree on the same operational reality.
The complete technical and functional documentation is available in the project documentation repository.
Built with
- NextJS
- FastAPI
- MapGL
- micro:bit
- RabbitMQ
- Keycloak