96 lines
3.2 KiB
Markdown
96 lines
3.2 KiB
Markdown
# Architecture
|
|
|
|
## System Overview
|
|
|
|
The application is a state-driven desktop client with an event-processing pipeline:
|
|
|
|
1. ingest prediction events from MQTT,
|
|
2. persist accepted values in SQLite,
|
|
3. evaluate risk based on recent history,
|
|
4. update UI state and rendering,
|
|
5. export animation state for external consumers.
|
|
|
|
## Module Structure
|
|
|
|
- `vassistent.bootstrap`
|
|
Application startup/shutdown orchestration (`ApplicationInitializer`, `ApplicationShutdownManager`)
|
|
- `vassistent.service`
|
|
Runtime services and integrations (MQTT, persistence, statistics, evaluation, process management)
|
|
- `vassistent.model`
|
|
Core state/data objects (`AppState`, `ProblemLevel`, `DatabaseEntry`, `RatioPoint`)
|
|
- `vassistent.controller`
|
|
Connects app state/services with Swing views
|
|
- `vassistent.ui`
|
|
Window and visual components
|
|
- `vassistent.util`
|
|
Configuration loading/validation and logging
|
|
|
|
## Runtime Flow
|
|
|
|
### Startup sequence
|
|
|
|
1. `App.main` initializes look-and-feel.
|
|
2. `ApplicationInitializer.initialize()` validates config and wires all services.
|
|
3. MQTT subscription is registered on configured topic.
|
|
4. Optional external processes are started via `ProcessManagerService`.
|
|
5. UI window/controller is created on the Swing event thread.
|
|
6. JVM shutdown hook is registered through `ApplicationShutdownManager`.
|
|
|
|
### Event processing sequence
|
|
|
|
1. MQTT message arrives (`MqttClientService.messageArrived`).
|
|
2. Payload is routed to `BinaryEventService.handlePayload`.
|
|
3. Payload validation checks:
|
|
- `valid == true`
|
|
- `_id` is present
|
|
- `prediction` is `0` or `1`
|
|
- duplicate `_id` vs last processed message is rejected
|
|
4. Accepted value is stored by `DataPersistenceService`.
|
|
5. `EvaluationService` requests ratio from `StatisticsService.getRatio(20)`.
|
|
6. Ratio is mapped to a `ProblemLevel`.
|
|
7. `AppState` updates notify registered listeners.
|
|
8. `AnimationFileService` writes the corresponding animation JSON file.
|
|
|
|
## Core Domain Rules
|
|
|
|
`EvaluationService` maps ratios to levels:
|
|
|
|
- `< 0.5` -> `NONE`
|
|
- `>= 0.5` -> `WARNING`
|
|
- `>= 0.8` -> `HIGH`
|
|
- `>= 0.9` -> `DISASTER`
|
|
|
|
Persistence schema (`binary_event`):
|
|
|
|
- `id` (autoincrement primary key)
|
|
- `value` (`0`/`1`)
|
|
- `timestamp` (ISO local date-time string)
|
|
|
|
## Integration Boundaries
|
|
|
|
- **MQTT**: Eclipse Paho client, broker URL and topic from config.
|
|
- **Database**: local SQLite file (`data/health.db` by default).
|
|
- **UI streaming tab**: JCEF browser for a configured URL (`streaming.url`).
|
|
- **External processes**: optional Python simulator and Unreal launcher script.
|
|
- **Animation output**: JSON file written to `animation.output.path`.
|
|
|
|
## Shutdown Behavior
|
|
|
|
`ApplicationShutdownManager` performs:
|
|
|
|
1. MQTT disconnect,
|
|
2. managed process shutdown,
|
|
3. runtime database file deletion (`data/health.db`),
|
|
4. logger shutdown.
|
|
|
|
## Architectural Tradeoffs
|
|
|
|
- **Pros**
|
|
- Clear service boundaries and explicit startup wiring.
|
|
- Good testability for service layer and integration logic.
|
|
- Configuration validation catches many misconfigurations early.
|
|
- **Current tradeoffs**
|
|
- Local database lifecycle is ephemeral by default (deleted on shutdown).
|
|
- Startup is tightly coupled to external-process configuration when enabled.
|
|
- UI logic is mostly verified indirectly through state and service tests.
|