Updated README and docs/

This commit is contained in:
Niklas Aumueller 2026-03-23 14:41:18 +01:00
parent 1baee83263
commit 3b0fa54026
10 changed files with 600 additions and 375 deletions

164
README.md Normal file
View File

@ -0,0 +1,164 @@
# Virtueller Gesundheitsassistent
A Java 17 desktop application that ingests binary health predictions over MQTT, stores them in SQLite, computes rolling risk levels, and visualizes the result in a dashboard with optional avatar/Unreal integration.
## Contents
- [Features](#features)
- [Architecture Overview](#architecture-overview)
- [Tech Stack](#tech-stack)
- [Getting Started](#getting-started)
- [Configuration](#configuration)
- [Testing](#testing)
- [Project Structure](#project-structure)
- [Documentation](#documentation)
- [Known Limitations](#known-limitations)
## Features
- Swing desktop UI with:
- `Avatar Streaming` tab (embedded JCEF browser)
- `Dashboard` tab (risk time-series chart + level bar)
- MQTT subscription to prediction events (`PREDICTION` by default)
- SQLite persistence (`data/health.db`)
- Threshold-based risk classification from the latest 20 values:
- `NONE` for ratio `< 0.5`
- `WARNING` for ratio `>= 0.5`
- `HIGH` for ratio `>= 0.8`
- `DISASTER` for ratio `>= 0.9`
- Animation state JSON export (`animation.output.path`)
- Optional startup/shutdown management for:
- Python MQTT simulator
- Unreal/Pixel Streaming startup script
- Asynchronous logger with optional file output and rotation
## Architecture Overview
Runtime flow:
1. The app initializes UI and services.
2. MQTT messages are received on a configured topic.
3. Incoming JSON payloads are validated.
4. Accepted predictions are persisted in SQLite.
5. Risk ratio and level are re-evaluated.
6. App state notifies UI controllers.
7. Dashboard widgets and chart update.
8. Animation JSON is written for external consumers.
## Tech Stack
- Java 17
- Maven
- Swing + FlatLaf + JFreeChart
- Eclipse Paho MQTT client
- SQLite JDBC
- JCEF (`jcefmaven`)
- JUnit 5 + Mockito
## Getting Started
### Prerequisites
- JDK 17
- Maven 3.9+
- MQTT broker running at `localhost:1883` (or adjust config)
- Windows for bundled PowerShell/BAT integration scripts
- Optional: Python for simulator support
- Optional: Unreal/Pixel Streaming environment
### 1) Configure a minimal local run
In `src/main/resources/config/application.properties`, disable optional external integrations if they are not available on your machine:
```properties
mqtt_sim.enabled=false
unreal.enabled=false
```
### 2) Build and run
```powershell
mvn clean compile
mvn org.codehaus.mojo:exec-maven-plugin:3.5.0:java -Dexec.mainClass=vassistent.App
```
You can also run `vassistent.App` directly from an IDE.
### 3) Send test data
Publish to topic `PREDICTION` with payload format:
```json
{
"valid": true,
"_id": 1,
"prediction": 0
}
```
Validation rules:
- `valid` must be `true`
- `_id` must exist
- `prediction` must be `0` or `1`
## Configuration
Main config: `src/main/resources/config/application.properties`
Logger config: `src/main/resources/config/logger.properties`
High-impact keys:
- `mqtt.broker.url`, `mqtt.client.id`, `mqtt.topic`
- `streaming.url`
- `animation.output.path`
- `mqtt_sim.enabled`, `python.path`, `mqtt_sim.script`
- `unreal.enabled`, `unreal.executable`, `unreal.signalling_server.script`
A full key-by-key reference is available in [`docs/CONFIGURATION.md`](docs/CONFIGURATION.md).
## Testing
Run tests with:
```powershell
mvn test
```
The suite includes unit and integration tests for state changes, payload validation, threshold evaluation, persistence behavior, process management, MQTT behavior, and animation output.
## Project Structure
```text
src/main/java/vassistent
App.java
bootstrap/ # startup wiring + shutdown sequencing
controller/ # UI orchestration
model/ # app state + value objects
service/ # MQTT, DB, stats, evaluation, processes
ui/ # Swing views/components
util/ # config loading/validation + logging
src/main/resources
config/application.properties
config/logger.properties
scripts/mqtt_simulator.py
scripts/start_avatar.ps1
```
## Documentation
- [Documentation Index](docs/INDEX.md)
- [Project Review](docs/PROJECT_REVIEW.md)
- [Architecture](docs/ARCHITECTURE.md)
- [Setup and Run](docs/SETUP_AND_RUN.md)
- [Configuration](docs/CONFIGURATION.md)
- [Testing](docs/TESTING.md)
- [Source Map](docs/SOURCE_MAP.md)
- [Known Issues](docs/KNOWN_ISSUES.md)
## Known Limitations
- The runtime database (`data/health.db`) is currently deleted on application shutdown.
- Default Unreal-related paths in `application.properties` are machine-specific and require adaptation on other systems.
- Enabling optional external integrations without valid local paths causes startup validation to fail.

View File

@ -1,62 +1,95 @@
# Architecture
## High-Level Overview
## System Overview
The application is a Java Swing desktop client that:
The application is a state-driven desktop client with an event-processing pipeline:
1. subscribes to MQTT prediction events,
2. stores accepted events in SQLite,
3. computes risk ratios,
4. updates UI state and visualization,
5. exports animation state for Unreal integration.
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.
## Layers
## Module Structure
- `bootstrap`
- builds and wires all services in `ApplicationInitializer`
- handles orderly shutdown in `ApplicationShutdownManager`
- `service`
- integration and business logic (MQTT, DB, stats, evaluation, external processes)
- `model`
- simple state and value objects (`AppState`, `ProblemLevel`, `DatabaseEntry`, `RatioPoint`)
- `controller`
- UI orchestration between state/services and Swing views
- `ui`
- window and visual components (tabs, chart, browser, status widgets)
- `util`
- shared helpers for config and logging
- `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 Data Flow
## Runtime Flow
1. `App.main` initializes look-and-feel and context.
2. `MqttClientService` connects to `tcp://localhost:1883`.
3. Subscription on configured topic routes payloads into `BinaryEventService`.
4. `BinaryEventService` validates JSON and stores `prediction` values.
5. `EvaluationService` gets ratio from `StatisticsService`.
6. `AppState` is updated with the new `ProblemLevel`.
7. Controllers listen to `AppState` and refresh UI (`DashboardView`, status bar).
8. `AnimationFileService` writes the animation JSON consumed by Unreal side logic.
### Startup sequence
## Main Components
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`.
- `vassistent.App`
- process entry point and shutdown hook registration
- `ApplicationContext`
- in-memory service container
- `DataPersistenceService`
- SQLite schema init and data access
- `MqttClientService`
- MQTT connect/subscribe/publish callbacks
- `StatisticsService`
- ratio and rolling-average computations
- `EvaluationService`
- ratio-to-level mapping
- `ProcessManagerService`
- optional startup/shutdown of simulator/Unreal helper processes
### Event processing sequence
## UI Structure
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.
- Main window: `AppWindow`
- Tab 1: `PixelStreamingView` (JCEF browser)
- Tab 2: `DashboardView` (JFreeChart + `ProblemLevelBar`)
- Footer status bar: MQTT status + current level
## 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.

View File

@ -1,82 +1,125 @@
# Configuration
Application settings are loaded from classpath properties files in `src/main/resources/config`.
Configuration is loaded from classpath properties files in `src/main/resources/config`:
- `application.properties` for runtime behavior
- `logger.properties` for logging behavior
`AppConfigValidator` performs startup validation and fails fast on invalid settings.
## `application.properties`
| Key | Purpose | Current Default |
### Core runtime keys
| Key | Required | Description |
|---|---|---|
| `app.mode` | Generic mode flag | `test` |
| `streaming.url` | Initial URL for pixel streaming view | `http://localhost` |
| `python.path` | Python interpreter for simulator process | `C:\\Program Files\\PyManager\\python.exe` |
| `mqtt.broker.url` | MQTT broker connection URL | `tcp://localhost:1883` |
| `mqtt.client.id` | MQTT client identifier | `JavaClientPublisherSubscriber` |
| `mqtt.topic` | MQTT topic to subscribe to | `PREDICTION` |
| `mqtt_sim.enabled` | Enables simulator startup | `false` |
| `mqtt_sim.script` | Simulator script path | `src/main/resources/scripts/mqtt_simulator.py` |
| `mqtt_sim.broker` | Simulator broker override (env passthrough) | `localhost` |
| `mqtt_sim.port` | Simulator broker port override | `1883` |
| `mqtt_sim.topic` | Simulator publish topic override | `PREDICTION` |
| `mqtt_sim.qos` | Simulator QoS override | `0` |
| `mqtt_sim.interval_seconds` | Simulator publish interval override | `5` |
| `mqtt_sim.username` | Optional simulator auth username | empty |
| `mqtt_sim.password` | Optional simulator auth password | empty |
| `mqtt_sim.start_id` | Optional simulator initial payload id | `1` |
| `mqtt_sim.client_id` | Optional simulator MQTT client id | `mqtt-simulator` |
| `mqtt_sim.log_file` | Optional simulator log file path | `logs/mqtt_simulator.log` |
| `animation.output.path` | Generated animation state file path | `data/animation.json` |
| `unreal.enabled` | Enables Unreal startup flow | `true` |
| `unreal.executable` | PowerShell script to start Unreal process | absolute path |
| `unreal.signalling_server.script` | Signalling server BAT file path | absolute path |
| `unreal.pid.file` | Unreal PID file for shutdown cleanup | absolute path |
| `unreal.signalling.pid.file` | Signalling PID file for shutdown cleanup | absolute path |
| `unreal.pid.dir` | Script-side PID directory override | absolute path |
| `unreal.target.executable` | Script-side Unreal executable override | absolute path |
| `unreal.target.args` | Script-side Unreal argument string override | command string |
| `unreal.target.working_dir` | Script-side Unreal working dir override | absolute path |
| `unreal.startup.delay.seconds` | Script-side signalling warmup delay override | `5` |
| `mqtt.broker.url` | yes | MQTT broker URI (`tcp://...`, `ssl://...`, `ws://...`, `wss://...`) |
| `mqtt.client.id` | yes | MQTT client ID |
| `mqtt.topic` | yes | MQTT topic to subscribe to |
| `streaming.url` | yes | URL for embedded streaming view (`http`/`https`) |
| `animation.output.path` | yes | Target path for animation JSON output |
| `app.mode` | no | Generic runtime mode flag |
Notes:
### Optional simulator keys (`mqtt_sim.*`)
- Paths can be provided with or without wrapping quotes; startup sanitizes surrounding quotes.
- Unreal-related defaults are environment-specific and should be replaced per machine.
- `mqtt_sim.*` overrides are forwarded as environment variables to `mqtt_simulator.py`.
- `unreal.target.*` and `unreal.pid.dir` are forwarded as environment variables to `start_avatar.ps1`.
These become required/validated when `mqtt_sim.enabled=true`.
| Key | Description |
|---|---|
| `mqtt_sim.enabled` | Enable Python simulator startup |
| `python.path` | Python executable path |
| `mqtt_sim.script` | Simulator script path |
| `mqtt_sim.broker` | Broker host passed to simulator |
| `mqtt_sim.port` | Broker port passed to simulator |
| `mqtt_sim.topic` | Simulator publish topic |
| `mqtt_sim.qos` | QoS (`0-2`) |
| `mqtt_sim.interval_seconds` | Publish interval in seconds |
| `mqtt_sim.username` / `mqtt_sim.password` | Optional broker auth |
| `mqtt_sim.start_id` | Optional starting `_id` |
| `mqtt_sim.client_id` | Optional simulator client id |
| `mqtt_sim.log_file` | Optional simulator log path |
### Optional Unreal keys (`unreal.*`)
These become required/validated when `unreal.enabled=true`.
| Key | Description |
|---|---|
| `unreal.enabled` | Enable Unreal startup flow |
| `unreal.executable` | PowerShell launcher script path |
| `unreal.signalling_server.script` | Signalling server BAT path |
| `unreal.target.executable` | Unreal executable path passed to script |
| `unreal.target.working_dir` | Unreal working directory passed to script |
| `unreal.target.args` | Unreal launch arguments |
| `unreal.pid.dir` | Optional PID output directory for script |
| `unreal.pid.file` | PID file used for shutdown cleanup |
| `unreal.signalling.pid.file` | Signalling PID file used for cleanup |
| `unreal.startup.delay.seconds` | Delay before Unreal launch in script |
### Process startup health checks
| Key | Description | Default |
|---|---|---|
| `process.startup.healthcheck.enabled` | Enable startup health checks for managed processes | `true` |
| `process.startup.healthcheck.timeout.millis` | Health-check timeout | `10000` |
| `process.startup.healthcheck.poll.millis` | Poll interval | `250` |
## `logger.properties`
| Key | Purpose | Current Default |
| Key | Description | Typical value |
|---|---|---|
| `logger.level` | Minimum log level | `DEBUG` |
| `logger.file.enabled` | Enables file logging | `true` |
| `logger.file` | Log output file | `logs/application.log` |
| `logger.max.size.mb` | Rotation threshold | `10` |
| `logger.file.enabled` | Toggle file logging | `true` |
| `logger.file` | Log file path | `logs/application.log` |
| `logger.max.size.mb` | Rotation threshold in MB | `10` |
## Related Script Files
## Validation Behavior
- `src/main/resources/scripts/mqtt_simulator.py`
- `src/main/resources/scripts/start_avatar.ps1`
The validator checks:
## Script Runtime Inputs
- URI format and scheme for MQTT broker URL
- non-empty required keys
- numeric ranges (`port`, QoS, timeout/poll values, delays)
- file/directory existence for enabled integrations
- optional quote handling and invalid path syntax
`mqtt_simulator.py` supports CLI options and equivalent env vars:
Any validation errors are grouped and thrown as a single startup exception.
- `--broker` / `MQTT_SIM_BROKER`
- `--port` / `MQTT_SIM_PORT`
- `--topic` / `MQTT_SIM_TOPIC`
- `--username` / `MQTT_SIM_USERNAME`
- `--password` / `MQTT_SIM_PASSWORD`
- `--qos` / `MQTT_SIM_QOS`
- `--interval-seconds` / `MQTT_SIM_INTERVAL_SECONDS`
- `--start-id` / `MQTT_SIM_START_ID`
- `--client-id` / `MQTT_SIM_CLIENT_ID`
- `--log-file` / `MQTT_SIM_LOG_FILE`
## Script Environment Mapping
`start_avatar.ps1` supports parameters and equivalent env vars:
### `mqtt_simulator.py`
- `-PidDir` / `VGA_PID_DIR`
- `-UeExe` / `VGA_UE_EXE`
- `-UeArgs` / `VGA_UE_ARGS`
- `-SignallingBat` / `VGA_SIGNALLING_BAT`
- `-UeWorkingDir` / `VGA_UE_WORKDIR`
- `-SignallingStartupDelaySeconds` / `VGA_SIGNALLING_DELAY`
App config keys are forwarded as environment variables:
- `mqtt_sim.broker` -> `MQTT_SIM_BROKER`
- `mqtt_sim.port` -> `MQTT_SIM_PORT`
- `mqtt_sim.topic` -> `MQTT_SIM_TOPIC`
- `mqtt_sim.username` -> `MQTT_SIM_USERNAME`
- `mqtt_sim.password` -> `MQTT_SIM_PASSWORD`
- `mqtt_sim.qos` -> `MQTT_SIM_QOS`
- `mqtt_sim.interval_seconds` -> `MQTT_SIM_INTERVAL_SECONDS`
- `mqtt_sim.start_id` -> `MQTT_SIM_START_ID`
- `mqtt_sim.client_id` -> `MQTT_SIM_CLIENT_ID`
- `mqtt_sim.log_file` -> `MQTT_SIM_LOG_FILE`
### `start_avatar.ps1`
App config keys are forwarded as environment variables:
- `unreal.target.executable` -> `VGA_UE_EXE`
- `unreal.target.args` -> `VGA_UE_ARGS`
- `unreal.target.working_dir` -> `VGA_UE_WORKDIR`
- `unreal.signalling_server.script` -> `VGA_SIGNALLING_BAT`
- `unreal.startup.delay.seconds` -> `VGA_SIGNALLING_DELAY`
- `unreal.pid.dir` (or PID parent fallback) -> `VGA_PID_DIR`
## Practical Recommendation
For first-time local runs, keep:
```properties
mqtt_sim.enabled=false
unreal.enabled=false
```
Then enable integrations incrementally after validating local paths and dependencies.

View File

@ -1,20 +1,30 @@
# Documentation Index
This folder contains project-level documentation for the virtual health assistant.
This folder contains detailed technical documentation for the project.
## Contents
## Suggested Reading Order
- [Architecture](ARCHITECTURE.md)
- [Setup and Run](SETUP_AND_RUN.md)
- [Configuration](CONFIGURATION.md)
- [Source Map](SOURCE_MAP.md)
- [Testing](TESTING.md)
- [Known Issues](KNOWN_ISSUES.md)
1. [Project Review](PROJECT_REVIEW.md)
2. [Architecture](ARCHITECTURE.md)
3. [Setup and Run](SETUP_AND_RUN.md)
4. [Configuration](CONFIGURATION.md)
5. [Testing](TESTING.md)
6. [Known Issues](KNOWN_ISSUES.md)
7. [Source Map](SOURCE_MAP.md)
## Recommended Reading Order
## Document Guide
1. [Architecture](ARCHITECTURE.md)
2. [Setup and Run](SETUP_AND_RUN.md)
3. [Configuration](CONFIGURATION.md)
4. [Testing](TESTING.md)
5. [Known Issues](KNOWN_ISSUES.md)
- [Project Review](PROJECT_REVIEW.md)
End-to-end implementation summary, design decisions, quality checks, and roadmap.
- [Architecture](ARCHITECTURE.md)
Component responsibilities, runtime data flow, and integration boundaries.
- [Setup and Run](SETUP_AND_RUN.md)
Reproducible setup for minimal and full integration modes.
- [Configuration](CONFIGURATION.md)
Complete key reference, validation behavior, and script environment mapping.
- [Testing](TESTING.md)
Test strategy, inventory, execution, and remaining gaps.
- [Known Issues](KNOWN_ISSUES.md)
Active limitations and impact.
- [Source Map](SOURCE_MAP.md)
Package-level map for fast code navigation.

View File

@ -2,35 +2,32 @@
## 1. Environment-Specific Defaults
Configuration is now path-driven, but several default values in `application.properties` are still machine-specific:
- Unreal startup script paths
- Unreal/signalling PID file paths
`application.properties` contains machine-specific Unreal paths and currently enables optional integrations by default.
Impact:
- configuration updates are required before first run on a different machine
- first run on a different machine can fail at startup validation unless values are adapted.
## 2. Database Deleted on Shutdown
## 2. Database Is Deleted on Shutdown
`App.deleteDatabase()` deletes `data/health.db` on app exit.
`ApplicationShutdownManager` deletes `data/health.db` during shutdown.
Impact:
- historical data is lost every run unless behavior is changed
- historical event data is not retained across sessions.
## 3. Signalling Process Startup Incomplete
## 3. Duplicate Filtering Is Limited to Last Seen `_id`
In `ProcessManagerService.startSignallingServer()`, process creation is currently prepared but not started (`pb.start()` is commented).
`BinaryEventService` only rejects a duplicate when it equals the immediate previous `_id`.
Impact:
- log output may indicate startup intent, but process is not actually launched via that path
- non-consecutive duplicate IDs can still be persisted.
## 4. Encoding Artifacts in Logs/Strings
## 4. Startup Coupling to Optional Integrations
Some source/log text contains mojibake characters in comments/messages.
When `mqtt_sim.enabled=true` or `unreal.enabled=true`, startup is blocked if related files/paths are invalid.
Impact:
- readability and consistency issues in logs and source text
- optional integrations can prevent the core app from launching.

74
docs/PROJECT_REVIEW.md Normal file
View File

@ -0,0 +1,74 @@
# Project Review
## Purpose
The virtual health assistant is built as an event-driven desktop system that converts binary health predictions into a continuously updated risk visualization.
Primary goals:
1. receive predictions in near real time via MQTT,
2. persist events locally,
3. compute rolling risk levels,
4. provide immediate visual feedback in the UI,
5. export machine-readable state for external avatar integration.
## End-to-End Pipeline
1. `MqttClientService` subscribes to the configured topic.
2. Payloads are forwarded to `BinaryEventService`.
3. Payloads are validated (`valid`, `_id`, `prediction`).
4. Accepted predictions are stored by `DataPersistenceService`.
5. `StatisticsService` computes the current ratio from the latest 20 entries.
6. `EvaluationService` maps ratio to `ProblemLevel`.
7. `AppState` notifies UI controllers and views.
8. `AnimationFileService` writes `animation.json`.
## Functional Scope
- Desktop monitoring UI with two views (stream + dashboard)
- MQTT-driven event ingestion
- SQLite event persistence
- Rolling ratio analytics
- Level classification (`NONE`, `WARNING`, `HIGH`, `DISASTER`)
- Optional external process orchestration (simulator + Unreal launcher)
- Startup configuration validation and structured logging
## Design Highlights
- **Separation of concerns**
Startup/shutdown orchestration lives in `bootstrap`; business logic in `service`; view orchestration in `controller`.
- **Config-first runtime behavior**
MQTT, simulator, Unreal, and animation output are controlled via properties.
- **Fail-fast startup validation**
`AppConfigValidator` blocks startup when enabled integrations are misconfigured.
- **Testability by construction**
Multiple services support dependency injection in tests (for example process launchers and MQTT client instances).
## Quality and Verification
Automated tests cover:
- App state transitions and listener notifications
- Payload validation and duplicate-id handling
- Ratio and threshold evaluation behavior
- SQLite persistence integration behavior
- MQTT subscribe/publish/callback flow
- Process startup/shutdown command sequencing and startup report behavior
- Animation file mapping and overwrite behavior
See [Testing](TESTING.md) for details and command examples.
## Current Limitations
- Runtime database is deleted on shutdown (`ApplicationShutdownManager`), so historical data is not retained.
- Default Unreal-related paths are machine-specific and must be adapted for new environments.
- UI behavior is not covered by end-to-end GUI tests.
- Duplicate payload protection is based on the last seen `_id` only (consecutive duplicates).
## Improvement Roadmap
1. Make database cleanup optional through configuration.
2. Add profile-based configuration (local/dev/demo) to reduce machine-specific defaults.
3. Add UI-level automated checks (or contract tests around controller/view boundaries).
4. Improve duplicate handling (e.g., bounded cache of recent IDs).
5. Add metrics/telemetry for startup health and message throughput.

View File

@ -4,13 +4,30 @@
- Java 17 (JDK)
- Maven 3.9+
- MQTT broker reachable at `localhost:1883`
- Windows environment for bundled PowerShell/BAT process scripts
- MQTT broker reachable at `localhost:1883` (or custom broker in config)
- Windows for bundled PowerShell/BAT process scripts
Optional:
- Python (for MQTT simulator startup)
- Unreal + Pixel Streaming environment (if enabled in config)
- Python (for automatic MQTT simulator startup)
- Unreal + Pixel Streaming setup (for avatar integration)
## Recommended Startup Modes
### Mode A: Minimal local run (recommended first)
Use this mode to run only the Java application and MQTT pipeline.
In `src/main/resources/config/application.properties`:
```properties
mqtt_sim.enabled=false
unreal.enabled=false
```
### Mode B: Full integration run
Enable simulator and/or Unreal startup only after all referenced paths are valid on your machine.
## Build
@ -18,21 +35,21 @@ Optional:
mvn clean compile
```
## Run (CLI)
## Run from CLI
```powershell
mvn org.codehaus.mojo:exec-maven-plugin:3.5.0:java -Dexec.mainClass=vassistent.App
```
## Run (IDE)
## Run from IDE
Run the class:
Start class:
- `vassistent.App`
## MQTT Payload Format
## Send Test Messages
Publish payloads to configured topic (default `PREDICTION`) in this format:
Publish payloads to configured topic (default: `PREDICTION`) in this format:
```json
{
@ -42,17 +59,25 @@ Publish payloads to configured topic (default `PREDICTION`) in this format:
}
```
Rules:
Validation rules:
- `valid` must be `true`
- `_id` must exist
- `prediction` must be `0` or `1`
## Startup Validation Notes
The app validates configuration at startup (`AppConfigValidator`):
- if simulator is enabled, Python executable/script and simulator settings are validated;
- if Unreal integration is enabled, script/executable paths and related directories are validated;
- invalid configuration throws an `IllegalStateException` before UI startup.
## Shutdown Behavior
On shutdown, the app:
- disconnects MQTT
- stops managed external processes
- flushes logger queue
- deletes `data/health.db` (current implementation)
1. disconnects MQTT,
2. stops managed external processes,
3. deletes `data/health.db` (current behavior),
4. flushes and closes the logger.

View File

@ -1,53 +1,86 @@
# Source Map
Package-level map of all Java source files in `src/main/java` and tests in `src/test/java`.
Package-level source overview for `src/main/java` and `src/test/java`.
## Main Sources
### `vassistent`
- `App.java`: application entry point and shutdown hook logic
- `App.java`
Application entry point.
### `vassistent.bootstrap`
- `ApplicationContext.java`: container for shared services/state
- `ApplicationInitializer.java`: wiring and startup sequence
- `ApplicationShutdownManager.java`: managed shutdown sequence
- `ApplicationContext.java`
In-memory container for shared services/state.
- `ApplicationInitializer.java`
Service wiring, startup orchestration, process startup reporting.
- `ApplicationShutdownManager.java`
Graceful shutdown: MQTT disconnect, process stop, DB cleanup, logger shutdown.
### `vassistent.controller`
- `AppWindowController.java`: main window lifecycle and state-driven UI updates
- `DashboardController.java`: chart and level updates on state changes
- `StreamingController.java`: stream view actions (reload/focus)
- `AppWindowController.java`
Main window lifecycle and cross-view coordination.
- `DashboardController.java`
Updates chart/level view from app state.
- `StreamingController.java`
Controls stream view actions.
### `vassistent.model`
- `AppState.java`: observable app state
- `DatabaseEntry.java`: persisted event value + timestamp
- `ProblemLevel.java`: risk level enum
- `RatioPoint.java`: chart point model
- `AppState.java`
Observable application state.
- `DatabaseEntry.java`
Persisted event value + timestamp.
- `ProblemLevel.java`
Risk-level enum.
- `RatioPoint.java`
Time-series point for chart data.
### `vassistent.service`
- `AnimationFileService.java`: writes animation state JSON file
- `BinaryEventService.java`: payload validation + dispatch
- `DataPersistenceService.java`: SQLite init and CRUD-like methods
- `EvaluationService.java`: ratio-to-problem-level mapping
- `MqttClientService.java`: MQTT connectivity and callbacks
- `ProcessManagerService.java`: optional process startup/shutdown
- `StatisticsService.java`: ratio and rolling-avg computations
- `AnimationFileService.java`
Writes current animation state JSON.
- `BinaryEventService.java`
Validates payloads and triggers persistence/evaluation.
- `DataPersistenceService.java`
SQLite schema setup and event read/write methods.
- `EvaluationService.java`
Ratio-to-level mapping and state update.
- `MqttClientService.java`
MQTT connect/subscribe/publish and callback routing.
- `ProcessManagerService.java`
Optional simulator/Unreal process startup, health checks, shutdown.
- `StatisticsService.java`
Ratio and rolling-average calculations from persisted events.
### `vassistent.ui`
- `AppWindow.java`: root frame with tabbed layout
- `DashboardView.java`: chart + threshold markers + level display
- `PixelStreamingView.java`: JCEF browser panel for stream
- `ProblemLevelBar.java`: custom level visualization widget
- `AppWindow.java`
Root frame with tabbed layout.
- `DashboardView.java`
Chart and current-level visualization.
- `PixelStreamingView.java`
JCEF browser panel for stream URL.
- `ProblemLevelBar.java`
Custom UI component for level display.
### `vassistent.util`
- `ConfigLoader.java`: classpath properties loader
- `Logger.java`: async logger with file rotation
- `AppConfigValidator.java`
Startup configuration validation.
- `ConfigLoader.java`
Classpath properties loading.
- `Logger.java`
Asynchronous logger with file rotation support.
## Resource Files
- `src/main/resources/config/application.properties`
- `src/main/resources/config/logger.properties`
- `src/main/resources/scripts/mqtt_simulator.py`
- `src/main/resources/scripts/start_avatar.ps1`
## Test Sources

View File

@ -1,43 +1,57 @@
# Testing
## Run Tests
## Run the Test Suite
```powershell
mvn test
```
## Current Test Suite
## Test Strategy
Located in:
The project uses a mix of unit and integration tests:
- `src/test/java/vassistent/model/AppStateTest`
- `src/test/java/vassistent/service/AnimationFileServiceTest`
- `src/test/java/vassistent/service/BinaryEventServiceTest`
- `src/test/java/vassistent/service/DataPersistenceServiceTest`
- `src/test/java/vassistent/service/EvaluationServiceTest`
- `src/test/java/vassistent/service/MqttClientServiceTest`
- `src/test/java/vassistent/service/ProcessManagerServiceTest`
- `src/test/java/vassistent/service/StatisticsServiceTest`
- **Unit tests** for isolated business logic and service behavior
- **Integration tests** for filesystem/SQLite behavior and output artifacts
- **Mock-based tests** for MQTT and process-launch behavior
Coverage focus:
Frameworks:
- state change notifications
- payload validation and processing flow
- level evaluation thresholds
- MQTT lifecycle and topic routing
- process launch/shutdown command sequencing
- animation file output mapping
- SQLite persistence behavior
- rolling averages and ratio calculations
- JUnit Jupiter
- Mockito JUnit Jupiter
## Current Status (Java 17)
## Test Inventory
- full suite passes with `mvn test`
- test stack:
- `org.junit.jupiter:junit-jupiter`
- `org.mockito:mockito-junit-jupiter`
| Test Class | Type | Main Focus |
|---|---|---|
| `AppStateTest` | Unit | state defaults and listener notifications |
| `BinaryEventServiceTest` | Unit | payload validation and duplicate handling |
| `EvaluationServiceTest` | Unit | ratio-threshold mapping and animation side effect |
| `StatisticsServiceTest` | Unit + Integration | rolling averages and ratio calculation |
| `DataPersistenceServiceTest` | Integration | SQLite persistence and retrieval ordering |
| `MqttClientServiceTest` | Unit (mocked client) | MQTT connect/subscribe/publish callbacks |
| `ProcessManagerServiceTest` | Unit (injected launcher) | process startup/shutdown and healthcheck reporting |
| `AnimationFileServiceTest` | Integration | JSON output mapping and overwrite behavior |
## Notes
## What Is Covered Well
- some tests are integration-style and use temporary SQLite databases
- test output may include logger lines because services log during execution
- Core event pipeline behavior
- Threshold logic and level transitions
- Persistence query correctness
- Managed process command generation and reporting
- Animation output mapping to domain levels
## Known Testing Gaps
- No full end-to-end GUI automation (Swing/JCEF interaction)
- No performance/load tests for high MQTT throughput
- No integration tests for real external Unreal processes in CI
- No property-based or fuzz testing for malformed payload variants
## Manual Verification Checklist
After a successful run, verify:
1. MQTT status in the UI changes to connected.
2. New payloads affect chart and level bar.
3. `animation.output.path` file is updated when level changes.
4. Shutdown stops optional processes and closes the application cleanly.

168
readme.md
View File

@ -1,168 +0,0 @@
# Virtueller Gesundheitsassistent
Java desktop application that receives binary health predictions via MQTT, stores them in SQLite, computes rolling risk ratios, and visualizes the result in a dashboard with an avatar streaming view.
## Documentation
- [Docs Index](docs/INDEX.md)
- [Architecture](docs/ARCHITECTURE.md)
- [Setup and Run](docs/SETUP_AND_RUN.md)
- [Configuration](docs/CONFIGURATION.md)
- [Source Map](docs/SOURCE_MAP.md)
- [Testing](docs/TESTING.md)
- [Known Issues](docs/KNOWN_ISSUES.md)
## Features
- Swing desktop UI with two tabs:
- `Avatar Streaming` (embedded JCEF browser, default `http://localhost`)
- `Dashboard` (time series chart + problem level bar)
- MQTT client subscriber (`tcp://localhost:1883`) for prediction events
- SQLite persistence (`data/health.db`)
- Rolling ratio evaluation and automatic risk level classification:
- `NONE` for `< 0.5`
- `WARNING` for `>= 0.5`
- `HIGH` for `>= 0.8`
- `DISASTER` for `>= 0.9`
- Writes animation state JSON for Unreal integration
- Optional external process startup:
- Python MQTT simulator
- Unreal/Pixel Streaming scripts
- Custom async logger with file output + rotation
## Tech Stack
- Java 17
- Maven
- Swing + FlatLaf
- JFreeChart
- Eclipse Paho MQTT
- SQLite JDBC
- JCEF (`jcefmaven`)
- JUnit 5 + Mockito (tests)
## Runtime Flow
1. App initializes look and feel and services.
2. MQTT subscriber listens on topic from config (`mqtt.topic`).
3. Incoming JSON payloads are validated in `BinaryEventService`.
4. `prediction` (`0`/`1`) is stored in SQLite.
5. `EvaluationService` computes ratio over last 20 values.
6. `AppState` updates notify UI controllers.
7. Dashboard chart and status bar refresh.
8. Animation state file is written for Unreal consumption.
## Payload Format
Incoming MQTT payload must be JSON like:
```json
{
"valid": true,
"_id": 123,
"prediction": 0
}
```
## Prerequisites
- JDK 17
- Maven 3.9+
- Local MQTT broker on `localhost:1883` (or adjust code/config)
- Windows environment if using bundled process scripts/paths
- Optional: Python (if MQTT simulator should be auto-started)
- Optional: Unreal + Pixel Streaming setup (path-based integration)
## Configuration
Main config: `src/main/resources/config/application.properties`
- `app.mode`: current mode flag (`test`)
- `streaming.url`: initial URL for embedded stream browser
- `python.path`: Python executable for simulator startup
- `mqtt.broker.url`: MQTT broker URL
- `mqtt.client.id`: MQTT client id
- `mqtt.topic`: subscribed topic (default `PREDICTION`)
- `mqtt_sim.enabled`: start simulator process on app startup
- `mqtt_sim.script`: simulator script path
- `mqtt_sim.broker` / `mqtt_sim.port` / `mqtt_sim.topic`: simulator runtime overrides
- `animation.output.path`: path for generated animation JSON file
- `unreal.enabled`: start Unreal-related processes
- `unreal.executable`: PowerShell script path for Unreal start
- `unreal.signalling_server.script`: signalling server batch path
- `unreal.pid.file`: PID file used for Unreal shutdown cleanup
- `unreal.signalling.pid.file`: PID file used for signalling shutdown cleanup
- `unreal.target.executable` / `unreal.target.args` / `unreal.target.working_dir`: optional overrides passed into `start_avatar.ps1`
Logger config: `src/main/resources/config/logger.properties`
- `logger.level`
- `logger.file.enabled`
- `logger.file`
- `logger.max.size.mb`
## Run
### 1) Start MQTT Broker
Start a broker on `localhost:1883` (for example Mosquitto).
### 2) Start the App
```powershell
mvn clean compile
mvn org.codehaus.mojo:exec-maven-plugin:3.5.0:java -Dexec.mainClass=vassistent.App
```
Or run `vassistent.App` directly from IntelliJ.
### 3) Send Test Data
Option A: enable simulator in `application.properties`:
- set `mqtt_sim.enabled=true`
- verify `python.path` and `mqtt_sim.script`
Option B: publish messages manually to topic `PREDICTION`.
## Tests
Run:
```powershell
mvn test
```
Current state in this repository on Java 17:
- unit and integration tests are available for state, event processing, evaluation, persistence, and statistics
- test stack uses JUnit 5 + Mockito JUnit Jupiter
- full suite runs successfully with `mvn test`
## Project Structure
```text
src/main/java/vassistent
App.java
bootstrap/ # wiring, context, shutdown sequencing
controller/ # Swing controllers
model/ # state + data types
service/ # MQTT, DB, stats, evaluation, processes
ui/ # App window, dashboard, streaming, widgets
util/ # config + logger
src/main/resources
config/application.properties
config/logger.properties
scripts/mqtt_simulator.py
scripts/start_avatar.ps1
```
## Important Notes
- Animation output path is now config-driven (`animation.output.path`).
- MQTT broker URL/client id are config-driven (`mqtt.broker.url`, `mqtt.client.id`).
- Unreal PID cleanup paths are config-driven (`unreal.pid.file`, `unreal.signalling.pid.file`).
- Script runtime values can be passed from config into `mqtt_simulator.py` and `start_avatar.ps1`.
- On app shutdown, `data/health.db` is deleted by `App.deleteDatabase()`.
- The signalling server process startup in `ProcessManagerService` is prepared but currently not launched (`pb.start()` commented).