e1d570992e
Drei zusammengehörige Teile in einem Repository: - homeassistant/ Das fertige, im Einsatz befindliche Home-Assistant-Panel (panel_custom Custom Element + pyscript-Backend). Echte Fahrzeug- und Personendaten (fahrzeugprofil.json, fahrten.jsonl, tankvorgaenge.jsonl, Tankbelege) bleiben per .gitignore außen vor; die anonymisierte Vorlage fahrzeugprofil.example.json ist mit dabei. - design-system/ Eigenständige React-Komponentenbibliothek (@audi-dash/ui), die die visuelle Sprache des Panels nachbildet - ohne Audi-Markenzeichen und ohne die lizenzierte Hausschrift. Dient als Grundlage für Claude Design. War bis hierher ein eigenes Repository und ist in dieses eingeschmolzen worden. - companion-app/ Datenschicht der neuen App DataMetric360 (iOS/Android via Capacitor, zusätzlich als Iframe im HA-Dashboard). Noch ohne Oberfläche: REST- und WebSocket-Zugriff auf Home Assistant plus Warteschlange für Änderungen ohne Netz. Ersetzt das eingespritzte hass-Objekt, das nur innerhalb des HA-Frontends existiert. Dazu die Projektdokumentation: SPECIFICATION.md (Ist-Stand des Panels), COMPANION_APP_ARCHITECTURE.md (Architekturentscheidungen der neuen App), AUDIT_2026-08-10.md, DESIGN_BRIEF_DATAMETRIC360.md und der ursprüngliche Bauauftrag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
104 lines
3.5 KiB
TypeScript
104 lines
3.5 KiB
TypeScript
/* ================================================================
|
|
Datenschicht DataMetric360 - Sammelexport
|
|
================================================================
|
|
Ein Zugang für die gesamte Oberfläche: REST für Lesen und Schreiben,
|
|
WebSocket für Push, Warteschlange fürs Funkloch. Welche Bildschirme es
|
|
gibt, ist hier bewusst unbekannt - diese Schicht überlebt jeden
|
|
Entwurfsdurchlauf unverändert. */
|
|
|
|
export * from "./types.ts";
|
|
export * from "./umgebung.ts";
|
|
export * from "./rest.ts";
|
|
export * from "./live.ts";
|
|
export * from "./warteschlange.ts";
|
|
|
|
import { ENTITAETEN } from "./types.ts";
|
|
import type { Fahrt, Fahrzeugstatus, Profil, Tankvorgang } from "./types.ts";
|
|
import { HassRest } from "./rest.ts";
|
|
import { HassLive } from "./live.ts";
|
|
import { Warteschlange } from "./warteschlange.ts";
|
|
|
|
/** Bündelt die drei Bausteine und bildet die Fachvorgänge ab, die das alte
|
|
Dashboard über hass.callService erledigt hat. */
|
|
export class DataMetricApi {
|
|
readonly rest: HassRest;
|
|
readonly live: HassLive;
|
|
readonly warteschlange: Warteschlange;
|
|
|
|
constructor() {
|
|
this.rest = new HassRest();
|
|
this.live = new HassLive();
|
|
this.warteschlange = new Warteschlange(this.rest);
|
|
|
|
/* Sobald die Verbindung wieder steht, wartende Änderungen nachliefern -
|
|
ohne dass die Oberfläche etwas anstoßen muss. */
|
|
this.live.aufVerbindung((zustand) => {
|
|
if (zustand === "verbunden") void this.warteschlange.abarbeiten();
|
|
});
|
|
}
|
|
|
|
/* ------------------------------------------------------------ Lesen */
|
|
|
|
profilLesen(): Promise<Profil> {
|
|
return this.rest.datenLesen<Profil>(ENTITAETEN.profil);
|
|
}
|
|
|
|
fahrtenLesen(): Promise<Fahrt[]> {
|
|
return this.rest.datenLesen<Fahrt[]>(ENTITAETEN.fahrten);
|
|
}
|
|
|
|
tankvorgaengeLesen(): Promise<Tankvorgang[]> {
|
|
return this.rest.datenLesen<Tankvorgang[]>(ENTITAETEN.tankvorgaenge);
|
|
}
|
|
|
|
fahrzeugstatusLesen(): Promise<Fahrzeugstatus> {
|
|
return this.rest.datenLesen<Fahrzeugstatus>(ENTITAETEN.fahrzeugstatus);
|
|
}
|
|
|
|
/* --------------------------------------------------------- Schreiben
|
|
Alle schreibenden Vorgänge laufen über die Warteschlange, nicht direkt
|
|
über rest.dienstAufrufen(). Damit verhält sich die App im Funkloch
|
|
genauso wie mit Netz - nur eben zeitversetzt. */
|
|
|
|
profilSchreiben(profil: Profil): Promise<unknown> {
|
|
return this.warteschlange.einreihen(
|
|
"pyscript",
|
|
"audi_dashboard_profil_schreiben",
|
|
{ profil_json: JSON.stringify(profil) },
|
|
"Fahrzeugdaten speichern",
|
|
);
|
|
}
|
|
|
|
belegHochladen(pdfBase64: string, dateiname: string, tankId?: string): Promise<unknown> {
|
|
return this.warteschlange.einreihen(
|
|
"pyscript",
|
|
"audi_dashboard_beleg_hochladen",
|
|
{ pdf_base64: pdfBase64, dateiname, ...(tankId ? { tank_id: tankId } : {}) },
|
|
`Beleg „${dateiname}" hochladen`,
|
|
);
|
|
}
|
|
|
|
fahrtLoeschen(tripId: string): Promise<unknown> {
|
|
return this.warteschlange.einreihen(
|
|
"pyscript",
|
|
"audi_dashboard_fahrt_loeschen",
|
|
{ trip_id: tripId },
|
|
"Fahrt löschen",
|
|
);
|
|
}
|
|
|
|
tankvorgangLoeschen(tankId: string): Promise<unknown> {
|
|
return this.warteschlange.einreihen(
|
|
"pyscript",
|
|
"audi_dashboard_tankvorgang_loeschen",
|
|
{ tank_id: tankId },
|
|
"Tankvorgang löschen",
|
|
);
|
|
}
|
|
|
|
/** Stößt eine sofortige Aktualisierung im Backend an (Pull-to-refresh). */
|
|
jetztAktualisieren(): Promise<unknown> {
|
|
return this.rest.dienstAufrufen("pyscript", "audi_dashboard_jetzt_aktualisieren");
|
|
}
|
|
}
|