Yet Another VISualization for a smart home.
  • TypeScript 63.1%
  • Vue 32.5%
  • CSS 4.2%
  • JavaScript 0.1%
Find a file
2026-08-13 22:04:48 +00:00
.devcontainer Updated Devcontainer for Envbuilder 2026-08-13 22:04:48 +00:00
.vscode Initial import 2026-08-13 21:31:42 +00:00
public Initial import 2026-08-13 21:31:42 +00:00
src Initial import 2026-08-13 21:31:42 +00:00
.editorconfig Initial import 2026-08-13 21:31:42 +00:00
.gitignore Initial import 2026-08-13 21:31:42 +00:00
.prettierignore Initial import 2026-08-13 21:31:42 +00:00
.prettierrc.json Initial import 2026-08-13 21:31:42 +00:00
AGENTS.md Initial import 2026-08-13 21:31:42 +00:00
AGENTS_STYLE.md Initial import 2026-08-13 21:31:42 +00:00
Brainstorming.config.yaml Initial import 2026-08-13 21:31:42 +00:00
Brainstorming.md Initial import 2026-08-13 21:31:42 +00:00
env.d.ts Initial import 2026-08-13 21:31:42 +00:00
eslint.config.js Initial import 2026-08-13 21:31:42 +00:00
index.html Initial import 2026-08-13 21:31:42 +00:00
package-lock.json Initial import 2026-08-13 21:31:42 +00:00
package.json Initial import 2026-08-13 21:31:42 +00:00
README.md Initial import 2026-08-13 21:31:42 +00:00
tsconfig.app.json Initial import 2026-08-13 21:31:42 +00:00
tsconfig.json Initial import 2026-08-13 21:31:42 +00:00
tsconfig.node.json Initial import 2026-08-13 21:31:42 +00:00
tsconfig.vitest.json Initial import 2026-08-13 21:31:42 +00:00
vite.config.ts Initial import 2026-08-13 21:31:42 +00:00
vitest.config.ts Initial import 2026-08-13 21:31:42 +00:00

Home Automation Dashboard

A Vue 3 + TypeScript application for smart-home control, telemetry, and visualization.
This README is written for developers who need to understand the current architecture quickly and continue development safely.

Table of Contents

1. Architecture at a Glance

The app follows a layered architecture:

  1. UI/Feature Layer (src/*/views, src/app/components) renders screens and dispatches user intents.
  2. Store Layer (src/app/stores) holds reactive state and adapts service events to UI-friendly data.
  3. Service Layer (src/app/services) implements integration logic (OIDC auth, config loading, MQTT, storage, telemetry).
  4. Infrastructure Utilities (src/app/utilities) provide generic helpers (promises, result wrappers, object merge, topic handling).

Primary runtime context:

  • Vue app (createApp)
  • Pinia store container
  • Vue Router
  • Services container (provided/injected)

2. Repository Structure

src/
  main.ts                    # App entrypoint and bootstrap execution
  App.vue                    # Root shell (RouterView + Screensaver)
  routes.ts                  # Route composition

  auth/                      # OIDC callback routes/views
  home/                      # Home module
  rooms/                     # Main smart-home module (areas, rooms, groups)
  map/                       # Map module (MapLibre marker/track visualization)
  settings/                  # Settings module
  testarea/                  # Manual integration playground
  floorplan/                 # Floorplan module (large inline SVG)

  app/
    bootstrap/               # App bootstrap orchestration
    services/                # Service layer + service bootstrap + MQTT client
    stores/                  # Pinia stores + store bootstrap
    components/              # Reusable UI controls/indicators/elements
    composables/             # Shared composition logic (e.g. TOC navigation)
    types/                   # Domain config types
    assets/css/              # Layered global styling and theme variables
    utilities/               # Current utility helpers
    utilities.old/           # Legacy utility helpers still used by indicators

public/
  config/                    # Static config examples / fixtures
  map.json                   # Map style
  img/                       # UI assets

Additional folders:

  • trash/: archive/legacy snapshots, not active runtime code.

3. Runtime Flow

3.1 Startup and Bootstrap

Main entrypoint: src/main.ts.

Sequence:

  1. Create Vue app (createApp(App)).
  2. Install Pinia.
  3. Build router from merged route table.
  4. Execute bootstrap(config, { app, pinia, router }).
  5. Install router.
  6. Log successful bootstrap.
  7. Mount to #App.

Core bootstrap files:

  • src/app/bootstrap/bootstrap.ts
  • src/app/services/services.bootstrap.ts
  • src/app/stores/stores.bootstrap.ts

3.2 Dependency Injection

Service DI is intentionally centralized:

  • Services are created in bootstrapServices(...).
  • Services are provided globally via app.provide(SERVICES, services).
  • Pinia gets $services via plugin: pinia.use(() => ({ $services: services })).

Usage patterns:

  • Stores call useXStore().$services.
  • Views/components can inject the container via inject(SERVICES) (used in auth callback views).

This keeps feature modules independent from service constructors.

3.3 Cross-Cutting Watchers

bootstrap(...) creates an effectScope with 3 important watchers:

  1. Entities connection watcher
    Rebuilds GatewayService MQTT connection when app/site MQTT config changes.
  2. Device service watcher
    Starts/stops DeviceService telemetry and MQTT depending on runtime config.
  3. Role-to-config watcher
    Loads config as soon as auth status is ready; role fallback chain:
    • unauthenticated -> guest
    • authenticated without roles -> default
    • authenticated with roles -> user roles

bootstrap(...) returns stopWatchers() for cleanup.

4. Routing and Feature Modules

Route composition happens in src/routes.ts by combining each feature module route array.

Defined routes:

  • / -> home
  • /rooms/, /rooms/:areaId/, /rooms/:areaId/:roomId/, /rooms/:areaId/:roomId/:groupId/
  • /map/
  • /settings/
  • /testarea/
  • /floorplan/
  • /auth/callbacks/login (public)
  • /auth/callbacks/logout (public)
  • catch-all -> redirect to /

Notes:

  • settings route has meta.requiresAuth, but a global auth guard is currently commented out in main.ts.

4.1 Feature Module Responsibilities

home/

  • MainHome.vue: auth-aware switch between guest and authenticated home view.
  • HomeGuest.vue / HomeAuthenticated.vue: user/status rendering and welcome header.

rooms/ (primary business module)

  • MainSite.vue: renders site area overview and room cards.
  • MainRoom.vue: renders room-level groups/modes/sensors.
  • MainGroup.vue: type-specific group detail (lights, shutters, climate).
  • Group*.vue: group-specific composition (scenes/entities/climate control).
  • Uses tocNavigation(...) for synchronized scroll-section navigation.

map/

  • Main.vue: map screen using Indicators.Map.
  • Combines static demo markers with entity-driven track data (gatewayStore.getData(...)).

settings/

  • Settings sections + logout action (authStore.signout()).
  • Uses TOC-style section navigation.

testarea/

  • Manual integration playground for auth/config/entities interactions.
  • Useful for smoke testing without full UI navigation flows.

auth/

  • Callback-only module for OIDC redirects.
  • MainLogInCallback.vue and MainLogOutCallback.vue process provider callbacks and redirect home.

floorplan/

  • Main.vue currently contains a very large inline SVG floorplan representation.

5. Configuration Model

Two config layers exist:

  1. Bootstrap config (src/config.ts)
    Static startup config for logger/auth/config endpoints/storage/l10n.
  2. Runtime app config (loaded remotely by ConfigService)
    Typed in src/app/types/types.config*.ts.

Runtime config root shape:

  • app: global connections/device settings
  • sites[]: site/area/room/group/entity tree
  • users[]: user metadata mapping (OIDC subject, symbols/images)

Key MQTT-related config nodes:

  • app.connections.mqtt.defaults
  • app.connections.mqtt.general.root_topic
  • app.device.connections.mqtt
  • site.connections.mqtt

6. Authorization (OIDC)

AuthService wraps oidc-client-ts.

Flow:

  1. signin() redirects to OIDC provider.
  2. Provider returns to /auth/callbacks/login.
  3. MainLogInCallback.vue calls auth.handleLogInCallback() then redirects to /.
  4. Auth events update AuthStore and downstream config loading.

Sign-out flow mirrors login via /auth/callbacks/logout.

Important behavior:

  • Service readiness is promise-based (whenReady()), accounting for redirect callbacks.
  • getToken(renew=true) can trigger silent renew.

7. MQTT Communication Model

See also 8. Service Layer Reference.

7.1 MqttClient (low-level)

src/app/services/clients/mqtt/mqtt.ts wraps mqtt library and exposes:

  • connection lifecycle events (connected, disconnected, reconnected)
  • topic subscribe/unsubscribe
  • publish
  • message event dispatch with optional topic-filtered listener objects

7.2 Entities pipeline

  • GatewayService manages one MQTT client for site/entity states.
  • Incoming messages become gatewayStore.data[topic].
  • gatewayStore.publish(topic, value) writes to topic + '/write'.

7.3 Device telemetry pipeline

DeviceService publishes telemetry to a device-scoped root topic:

  • user auth state
  • browser metadata
  • geolocation updates

Remote control channel is scaffolded but not implemented yet.

8. Service Layer Reference

8.1 LoggerService

File: src/app/services/logger/logger.ts

Purpose:

  • centralized logging/event bus
  • leveled logging (trace, debug, info, success, warn, error, fatal)
  • optional deduplication (dedupeMs)
  • pluggable sink (console sink in dev by default)

Core methods:

  • init(config)
  • scope(defaults) / withCorrelation(correlationId)
  • emit(event)
  • addEventListener, removeEventListener

Bootstrap hooks (logger.bootstrap.ts):

  • registers window error/unhandledrejection handlers
  • wires Vue/Pinia/Router error reporting

8.2 StorageService

File: src/app/services/storage/storage.ts

Purpose:

  • namespaced persistence abstraction (namespace::key)
  • backend selection: localStorage / sessionStorage / in-memory fallback

Core methods:

  • set, get, delete, has, keys, clear
  • addEventListener for set|delete|clear|backend_changed

8.3 AuthService

File: src/app/services/auth/auth.ts

Purpose:

  • OIDC login/logout/token handling
  • auth lifecycle event dispatch

Core methods:

  • signin, signout, refresh
  • handleLogInCallback, handleLogOutCallback
  • getUser, getToken, isTokenExpired, whenReady

Events:

  • user_loaded, user_unloaded, token_expiring, token_expired, ready

8.4 GeolocationService

File: src/app/services/geolocation/geolocation.ts

Purpose:

  • wraps browser geolocation API in interval/watch modes
  • emits normalized positions

Core methods:

  • getPosition
  • startIntervall (spelling kept from code), startWatch
  • stopInterval, stopWatch, stopAll
  • getPermissionState

Events:

  • position, error, started, stopped

8.5 ConfigService

File: src/app/services/config/config.ts

Purpose:

  • role-aware config loading from endpoint lists
  • optional auth header injection
  • reload support

Core methods:

  • load(scopes, options?)
  • reload()
  • addEventListener('loaded', ...)

Load strategy:

  • selects first matching configured scope
  • tries endpoints for that scope in order until one succeeds
  • emits loaded with parsed configuration

8.6 MqttClient

File: src/app/services/clients/mqtt/mqtt.ts

Purpose:

  • MQTT connectivity abstraction for higher-level services.

Core methods:

  • init, end
  • subscribe, unsubscribe
  • publish
  • addEventListener, removeEventListener

8.7 DeviceService

File: src/app/services/device/device.ts

Purpose:

  • device identity + telemetry publishing over MQTT
  • auth/geolocation integration

Core methods:

  • start(runtimeConfig), stop()
  • getDeviceId() (stored under device.id)
  • getBrowser()
  • telemetry handlers: eventlistenerUser, eventlistenerBrowser, eventlistenerGeolocation

8.8 GatewayService

File: src/app/services/entities/entities.ts

Purpose:

  • entity-state MQTT transport
  • publish helpers with root topic handling

Core methods:

  • connect(connectionRequest)
  • publish(topic, message, options?)
  • addEventListener, removeEventListener

9. Store Layer Reference

9.1 bootstrapStores

File: src/app/stores/stores.bootstrap.ts

Initialization order:

  1. authStore.init()
  2. configStore.init()
  3. gatewayStore.init()
  4. preferencesStore.init()

9.2 AuthStore (useAuthStore)

Purpose:

  • reactive user/status facade over AuthService

Public methods:

  • init, signin, signout, refresh, getToken, $reset

State:

  • user
  • status.ready, status.authenticated, status.expired

9.3 ConfigStore (useConfigStore)

Purpose:

  • active runtime config projection for UI

Public methods:

  • init, reload, setActiveSite, $reset

State/computed:

  • app, sites, users
  • activeSite, activeAreas, activeUser

9.4 gatewayStore (useGatewayStore)

Purpose:

  • reactive MQTT value cache and publish adapter

Public methods:

  • init, connect, disconnect
  • getData, getValue, getValueAsNumber, getValueAsBoolean, getUnit
  • publish, $reset

Behavior:

  • parses incoming MQTT payload as JSON
  • ignores topics ending in /write

9.5 PreferencesStore (usePreferencesStore)

Purpose:

  • user preference persistence via StorageService

Public methods:

  • init, setPreferences, $reset

Default key:

  • preferences

10. UI Layer and Component Patterns

10.1 App-Level Views

  • src/app/views/Navigation.vue: primary navigation + sidebar + site switching.
  • src/app/composables/toc-navigation.ts: section/button sync for in-page navigation.

10.2 UI Component Families

  • controls/*: low-level interactive controls (Panel, Icon, Slider, Switch)
  • ui-elements/*: domain widgets (Room, Groups, Modes, Entities, Glance)
  • indicators/*: data visualizations (Chart, Map, Value)

Interaction pattern:

  • UI components call gatewayStore.publish(...) for MQTT actions.
  • display state derives from gatewayStore.getValue*.

10.3 Styling System

src/app/assets/css/app.css uses CSS layers:

  • reset
  • defaults
  • layout
  • components
  • media
  • theme

Theme variables are defined in theme.definitions.css and applied in theme.default.css.

11. Utilities

Current utility layer (src/app/utilities):

  • promises.createPromise() for externally resolvable readiness promises
  • results module (ok/error/fromPromise) for explicit async error handling
  • objects module for deep merge/clone/compare operations
  • mqtt.mergeTopics(...) for robust topic concatenation
  • parsers / typechecks helpers

Legacy utility layer (src/app/utilities.old) is still used by chart/value/list sensor components.

12. Development Workflow

12.1 Commands

  • npm install -> install dependencies
  • npm run dev -> local dev server (host enabled)
  • npm run build -> type-check + production build
  • npm run preview -> preview production build
  • npm run type-check -> vue-tsc --build
  • npm run lint -> ESLint with auto-fix
  • npm run format / npm run format:check -> Prettier on src/
  • npm run test:unit -> Vitest runner

12.2 Conventions

  • indentation: tabs, size 4 (.editorconfig)
  • Prettier: no semicolons, single quotes, print width 100
  • alias: @/* -> src/*

13. Testing and Quality Status

  • Vitest is configured (vitest.config.ts, jsdom environment).
  • ESLint includes Vitest rules for src/**/__tests__/*.
  • No active test files are currently present in this snapshot.

14. Known Gaps and Extension Points

  1. Auth route guard is prepared but commented out in main.ts.
  2. Device remote control path in DeviceService is marked TODO.
  3. Config examples in public/config are mostly YAML fixtures, while runtime loader currently expects JSON from configured endpoints.
  4. utilities.old dependencies remain in indicator/UI code and can be migrated to src/app/utilities incrementally.
  5. Floorplan view (src/floorplan/views/Main.vue) is a very large static SVG and should likely be decomposed for maintainability.

If you add new behavior, update this README in the same PR with:

  • affected service/store/module,
  • new events and public methods,
  • required config schema changes,
  • routing or MQTT topic contract changes.