377 lines
44 KiB
HTML
377 lines
44 KiB
HTML
<!doctype html>
|
||
<html lang="de">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<meta name="description" content="Enelix EMS Portal für Systeme, Lizenzen und Prognosemanager">
|
||
<title>Enelix EMS Portal</title>
|
||
<link rel="stylesheet" href="/styles.css?v=20261006-heat-pump">
|
||
<link rel="stylesheet" href="/docs-portal.css?v=20261006">
|
||
</head>
|
||
<body>
|
||
<div id="toast" class="toast" role="status"></div>
|
||
|
||
<main id="authScreen" class="auth-screen">
|
||
<section class="auth-brand">
|
||
<div class="brand-lockup"><span class="brand-mark">E</span><span><strong>enelix</strong><small>EMS Portal</small></span></div>
|
||
<div class="auth-message"><p class="eyebrow">Energiemanagement</p><h1>Systeme planen.<br>Lizenzen verbinden.</h1><p>Ein Zugang für Anlagen, Prognosemanager und Lizenzierung.</p></div>
|
||
<div class="energy-lines" aria-hidden="true"><i></i><i></i><i></i><i></i></div>
|
||
</section>
|
||
|
||
<section class="auth-workspace">
|
||
<div class="auth-box">
|
||
<nav class="public-doc-links" aria-label="Öffentliche Informationen"><a href="/docs/index.html">Dokumentation</a><a href="/docs/faq.html">FAQ</a><a href="/docs/preise.html">Preise</a></nav>
|
||
<div class="auth-tabs" id="authTabs" role="tablist" aria-label="Anmeldung">
|
||
<button class="auth-tab active" id="loginTab" type="button">Anmelden</button>
|
||
<button class="auth-tab" id="registerTab" type="button">Konto erstellen</button>
|
||
</div>
|
||
<p class="auth-notice hidden" id="authNotice" role="status"></p>
|
||
<form id="loginForm" class="auth-form">
|
||
<div><p class="eyebrow">Willkommen zurück</p><h2>Am Portal anmelden</h2></div>
|
||
<label>E-Mail-Adresse<input name="email" type="email" autocomplete="email" required></label>
|
||
<label>Passwort<input name="password" type="password" autocomplete="current-password" required></label>
|
||
<p class="form-error" id="loginError" role="alert"></p>
|
||
<button class="button primary wide" type="submit">Anmelden</button>
|
||
<button class="auth-link" id="forgotPasswordButton" type="button">Passwort vergessen?</button>
|
||
<button class="auth-link" id="resendVerificationButton" type="button">Bestätigungs-E-Mail erneut senden</button>
|
||
</form>
|
||
<form id="registerForm" class="auth-form hidden">
|
||
<div><p class="eyebrow">Offene Registrierung</p><h2>Neues Konto erstellen</h2></div>
|
||
<label>Name<input name="name" autocomplete="name" required minlength="2"></label>
|
||
<label>E-Mail-Adresse<input name="email" type="email" autocomplete="email" required></label>
|
||
<label>Passwort<input name="password" type="password" autocomplete="new-password" required minlength="10"><small>Mindestens 10 Zeichen.</small></label>
|
||
<p class="form-error" id="registerError" role="alert"></p>
|
||
<button class="button primary wide" type="submit">Konto erstellen</button>
|
||
</form>
|
||
<form id="forgotForm" class="auth-form hidden">
|
||
<div><p class="eyebrow">Kontozugang</p><h2>Passwort zurücksetzen</h2></div>
|
||
<label>E-Mail-Adresse<input name="email" type="email" required></label>
|
||
<p class="form-error" id="forgotError" role="alert"></p>
|
||
<button class="button primary wide" type="submit">Link anfordern</button>
|
||
<button class="auth-link" data-auth-login type="button">Zurück zur Anmeldung</button>
|
||
</form>
|
||
<form id="resetForm" class="auth-form hidden">
|
||
<div><p class="eyebrow">Kontozugang</p><h2>Neues Passwort</h2></div>
|
||
<label>Neues Passwort<input name="password" type="password" required minlength="10"></label>
|
||
<label>Passwort wiederholen<input name="password_repeat" type="password" required minlength="10"></label>
|
||
<p class="form-error" id="resetError" role="alert"></p>
|
||
<button class="button primary wide" type="submit">Passwort speichern</button>
|
||
<button class="auth-link" data-auth-login type="button">Zurück zur Anmeldung</button>
|
||
</form>
|
||
</div>
|
||
</section>
|
||
</main>
|
||
|
||
<div id="portalApp" class="portal hidden">
|
||
<header class="topbar">
|
||
<a class="brand" href="#overview"><span class="brand-mark">E</span><span><strong>enelix</strong><small>EMS Portal</small></span></a>
|
||
<div class="top-actions"><nav class="header-links" aria-label="Dokumentation und Preise"><a href="/docs/index.html">Dokumentation</a><a href="/docs/preise.html">Preise</a></nav><span class="environment">Entwicklung</span><button class="account-button" id="accountButton" type="button"><span id="topInitials">EN</span><strong id="topName">Konto</strong></button></div>
|
||
</header>
|
||
|
||
<div class="app-shell">
|
||
<aside class="sidebar">
|
||
<nav>
|
||
<button class="nav-item active" data-view="overview">Lizenzen</button>
|
||
<button class="nav-item" data-view="forecast">Prognose</button>
|
||
<button class="nav-item" data-view="faults">Störüberwachung</button>
|
||
<button class="nav-item" data-view="account">Konto</button>
|
||
</nav>
|
||
<div class="workspace-switcher"><label>Organisation<select id="workspaceSelect"></select></label><small id="workspaceRole">Eigentümer</small></div>
|
||
</aside>
|
||
|
||
<main class="content">
|
||
<section class="view active" id="view-overview">
|
||
<div class="page-head"><div><p class="eyebrow" id="overviewOrg">Arbeitsbereich</p><h1>Lizenzübersicht</h1><p>Gekaufte Lizenzen, Verwendung und Managerbindung auf einen Blick.</p></div><button class="button primary" type="button" data-open-new-license>Neue Lizenz</button></div>
|
||
<div class="metrics"><div><span id="metricPlants">0</span><small>Lizenzpakete</small></div><div><span id="metricManagers">0</span><small>Bezahlte Lizenzen</small></div><div><span id="metricConnected">0</span><small>Verknüpfte Manager</small></div></div>
|
||
<section class="work-section"><div class="section-head"><div><h2>Lizenzen und Manager</h2><p>Status, Verwendung und verfügbare Erweiterungen.</p></div></div><div id="overviewPlants"></div></section>
|
||
</section>
|
||
|
||
<section class="view" id="view-licenses">
|
||
<div class="page-head"><div><p class="eyebrow">Kauf · CHF netto</p><h1>Lizenz erweitern</h1><p>Vorhandene Lizenzen prüfen, zusätzliche Module ergänzen und Peak Shaving bei Bedarf upgraden.</p></div><div class="page-actions"><button class="button secondary" type="button" data-configure-current>System konfigurieren</button><span class="status" id="stripeStatus">Stripe Sandbox</span></div></div>
|
||
<div id="moduleNoPlant" class="empty-state hidden"><strong>Noch keine Lizenz vorhanden</strong><p>Lege ein Lizenzpaket direkt an oder ermittle es mit dem Systemkonfigurator.</p><button class="button primary" data-open-new-license>Neue Lizenz</button></div>
|
||
<div id="moduleConfigurator" class="config-layout">
|
||
<section class="module-panel">
|
||
<label class="select-line">System<select id="orderPlant"></select></label>
|
||
<div class="manager-summary"><div><span class="field-label">Manager</span><strong id="managerCurrentName">Noch keine bezahlte Manager-Lizenz</strong><small id="ownedManager">Der Manager wird beim Erstkauf einmalig berechnet.</small></div><label id="peakUpgradeOption" class="upgrade-option hidden"><input id="peakUpgrade" type="checkbox"><span><strong>Auf Peak Shaving upgraden</strong><small>Einmalig nur die Preisdifferenz bezahlen.</small></span></label><span><b id="managerPrice">CHF 0.00</b><small id="managerSetup">Kein weiterer Managerkauf</small></span></div>
|
||
<div class="module-list">
|
||
<div class="module-header"><span>Verbrauchermodul</span><span>Lizenz</span><span>Einrichtung</span><span>Menge</span></div>
|
||
<label class="module-row" data-key="battery" data-name="Batteriespeicher" data-price="41.95" data-setup="54.55"><span><input type="checkbox" class="module-check"><strong>Batteriespeicher</strong><small>Batterie</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 41.95</span><span>CHF 54.55</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<label class="module-row" data-key="buffer_storage" data-name="Pufferspeicher" data-price="25.15" data-setup="32.70"><span><input type="checkbox" class="module-check"><strong>Pufferspeicher</strong><small>VerbraucherPufferspeicher</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 25.15</span><span>CHF 32.70</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<label class="module-row" data-key="ev_charger" data-name="EV-Ladestation" data-price="33.65" data-setup="43.75"><span><input type="checkbox" class="module-check"><strong>EV-Ladestation</strong><small>Stand-Alone oder Gateway</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 33.65</span><span>CHF 43.75</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<label class="module-row" data-key="consumer_single" data-name="Verbraucher einstufig" data-price="20.95" data-setup="27.25"><span><input type="checkbox" class="module-check"><strong>Verbraucher einstufig</strong><small>Ein schaltbarer Verbraucher</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 20.95</span><span>CHF 27.25</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<label class="module-row" data-key="heat_pump" data-name="Wärmepumpe" data-price="20.95" data-setup="27.25"><span><input type="checkbox" class="module-check"><strong>Wärmepumpe</strong><small>Sperre / Erhöhung oder SG Ready</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 20.95</span><span>CHF 27.25</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<label class="module-row" data-key="boiler_multi" data-name="Boiler mehrstufig" data-price="25.15" data-setup="32.70"><span><input type="checkbox" class="module-check"><strong>Boiler mehrstufig</strong><small>Warmwassererwärmer</small><small class="owned-count">Vorhanden: <b>0</b></small></span><span>CHF 25.15</span><span>CHF 32.70</span><input class="qty" type="number" min="1" max="999" value="1"></label>
|
||
<div class="module-header"><span>Prognoselizenz</span><span>Jahrespreis</span><span>Einrichtung</span><span>Menge</span></div>
|
||
<label class="module-row" data-key="forecast_pv" data-name="PV-Ertragsprognose" data-price="0" data-setup="0" data-term-months="12"><span><input type="checkbox" class="module-check"><strong>PV-Ertragsprognose</strong><small>Jahreslizenz</small><small class="owned-count">Nicht aktiviert</small></span><span>CHF 0.00 / Jahr</span><span>–</span><input class="qty" type="number" min="1" max="1" value="1"></label>
|
||
<label class="module-row" data-key="forecast_load" data-name="Verbrauchsprognose" data-price="0" data-setup="0" data-term-months="12"><span><input type="checkbox" class="module-check"><strong>Verbrauchsprognose</strong><small>Jahreslizenz</small><small class="owned-count">Nicht aktiviert</small></span><span>CHF 0.00 / Jahr</span><span>–</span><input class="qty" type="number" min="1" max="1" value="1"></label>
|
||
<label class="module-row" data-key="grid_schedule" data-name="Intelligenter Netzfahrplan" data-price="50" data-setup="0" data-term-months="12"><span><input type="checkbox" class="module-check"><strong>Intelligenter Netzfahrplan</strong><small>Jahreslizenz · Manager mit Peak Shaving erforderlich</small><small class="owned-count">Nicht aktiviert</small></span><span>CHF 50.00 / Jahr</span><span>–</span><input class="qty" type="number" min="1" max="1" value="1"></label>
|
||
</div>
|
||
</section>
|
||
<aside class="order-panel"><p class="eyebrow">Bestellung</p><div id="orderItems" class="order-items"></div><dl><div><dt>Lizenzen netto</dt><dd id="moduleTotal">CHF 0.00</dd></div><div id="setupTotalRow" class="hidden"><dt>Generator / Ersteinrichtung</dt><dd id="setupTotal">CHF 0.00</dd></div><div><dt>Gesamt netto</dt><dd id="netTotal">CHF 0.00</dd></div><div><dt id="vatLabel">MwSt. 8.1 %</dt><dd id="vatTotal">CHF 0.00</dd></div><div class="grand-total"><dt>Gesamt inkl. MwSt.</dt><dd id="grandTotal">CHF 0.00</dd></div></dl><button class="button primary wide" id="checkoutButton" type="button">Mit Stripe bezahlen</button><p class="form-error" id="checkoutError"></p></aside>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="view" id="view-configurator">
|
||
<div class="page-head"><div><p class="eyebrow">Planung</p><h1>System konfigurieren</h1><p>Geräte erfassen und passende Lizenzen ermitteln.</p></div><span class="status available">Enelix EMS</span></div>
|
||
<form id="systemForm" class="system-configurator">
|
||
<section class="config-form wizard">
|
||
<header class="wizard-header">
|
||
<div><p class="eyebrow" id="wizardStepCount">Schritt 1 von 10</p><h2 id="wizardStepTitle">Anlage</h2></div>
|
||
<ol class="wizard-progress" aria-label="Fortschritt">
|
||
<li class="active" data-wizard-marker="0">Anlage</li><li data-wizard-marker="1">Energiequellen</li>
|
||
<li data-wizard-marker="2">Batterie</li><li data-wizard-marker="3">Pufferspeicher</li>
|
||
<li data-wizard-marker="4">Ladestation</li><li data-wizard-marker="5">Verbraucher</li>
|
||
<li data-wizard-marker="6">Boiler</li><li data-wizard-marker="7">Wärmepumpe</li>
|
||
<li data-wizard-marker="8">Abrechnung</li><li data-wizard-marker="9">Prüfen</li>
|
||
</ol>
|
||
</header>
|
||
<section class="wizard-step active" data-wizard-step="0">
|
||
<p class="wizard-question">Wie heisst die Anlage und wo befindet sie sich?</p>
|
||
<div class="field-grid"><label>Systemname<input name="name" required minlength="2" placeholder="z. B. Werk Zürich"></label><label>Standort<input name="location" required minlength="2" placeholder="Ort, Schweiz"></label><label>Anlagentyp<select name="siteType"><option>Gewerbe</option><option>Privat</option><option>Industrie</option></select></label></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="1">
|
||
<p class="wizard-question">Wie soll der Manager arbeiten und über welche Schnittstellen werden Energiedaten gelesen?</p>
|
||
<label class="setup-option"><input name="peakShaving" type="checkbox"><span><strong>Peak Shaving erforderlich</strong><small>Wählt die Manager-Variante mit Lastspitzenregelung.</small></span></label>
|
||
<div class="configuration-band">
|
||
<h3>Netzmessung</h3>
|
||
<div class="field-grid">
|
||
<label>Geräteprofil<select name="gridProfile" data-profile-select="energy"></select></label>
|
||
<label>IP-Adresse oder Hostname<input name="gridHost" maxlength="120" placeholder="z. B. 192.168.1.40"></label>
|
||
<label>Port<input name="gridPort" type="number" min="0" max="65535" value="0"></label>
|
||
<label>Modbus Geräte-ID<input name="gridUnitId" type="number" min="0" max="247" value="1"></label>
|
||
<label data-manual-source="grid">Bestehende Leistungsvariable<input name="gridSourceVariableId" type="number" min="0" value="0"></label>
|
||
<label>Hinweis<textarea name="gridNotes" rows="3" maxlength="300"></textarea></label>
|
||
</div>
|
||
</div>
|
||
<label class="setup-option"><input name="pvEnabled" type="checkbox"><span><strong>PV-Anlage einlesen</strong><small>Herstellerprofil und lokale Schnittstelle für die Erzeugungsmessung verwenden.</small></span></label>
|
||
<div class="configuration-band">
|
||
<h3>PV-Wechselrichter</h3>
|
||
<div class="field-grid">
|
||
<label>Bezeichnung<input name="pvName" maxlength="80" value="PV-Wechselrichter"></label>
|
||
<label>AC-Nennleistung (kW)<input name="pvAcPowerKw" type="number" min="0" step="0.1" value="0"></label>
|
||
<label>Geräteprofil<select name="pvProfile" data-profile-select="energy"></select></label>
|
||
<label>IP-Adresse oder Hostname<input name="pvHost" maxlength="120"></label>
|
||
<label>Port<input name="pvPort" type="number" min="0" max="65535" value="0"></label>
|
||
<label>Modbus Geräte-ID<input name="pvUnitId" type="number" min="0" max="247" value="1"></label>
|
||
<label data-manual-source="pv">Bestehende Leistungsvariable<input name="pvSourceVariableId" type="number" min="0" value="0"></label>
|
||
</div>
|
||
</div>
|
||
<div class="configuration-band" data-pv-topology>
|
||
<div class="structured-editor-head"><div><h3>PV-Flächen</h3><p>Dachflächen und Ausrichtung ohne JSON erfassen.</p></div></div>
|
||
<div class="quantity-line"><label>Anzahl PV-Flächen<input name="pvSurfaceQuantity" data-topology-quantity="pvSurfaces" type="number" min="0" max="50" value="0"></label><small>Bei aktivierter PV wird mindestens eine Fläche angelegt.</small></div>
|
||
<div class="device-editor" data-topology-editor="pvSurfaces"></div>
|
||
</div>
|
||
<details class="config-details"><summary>Optionale Manager-Funktionen</summary><p>Nur betriebliche Optionen. Technische Zuordnungen, Prognoseanschlüsse, Archivierung und Aufbewahrung werden automatisch gesetzt.</p><div id="managerConfigurationFields" class="schema-groups"></div></details>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="2">
|
||
<p class="wizard-question">Welche Batteriespeicher soll der Manager steuern?</p>
|
||
<div class="quantity-line"><label>Batteriespeicher<input name="batteryQuantity" data-device-quantity="battery" type="number" min="0" max="50" value="0"></label><small>Geräteprofil, Leistungsdaten und Grenzen genügen; Typ und Variablen werden automatisch zugeordnet.</small></div>
|
||
<div class="device-editor" data-device-editor="battery"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="3">
|
||
<p class="wizard-question">Welche Pufferspeicher sollen eingerichtet werden?</p>
|
||
<div class="quantity-line"><label>Pufferspeicher<input name="bufferQuantity" data-device-quantity="buffer_storage" type="number" min="0" max="50" value="0"></label><small>Fühler, Heizkurve und Leistungsstufen werden je Pufferspeicher erfasst.</small></div>
|
||
<div class="device-editor" data-device-editor="buffer_storage"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="4">
|
||
<p class="wizard-question">Welche EV-Ladestationen sollen eingerichtet werden?</p>
|
||
<div class="quantity-line"><label>Anzahl<input name="evQuantity" data-device-quantity="ev_charger" type="number" min="0" max="50" value="0"></label><small>Je Station kann zwischen direkter Anbindung und Easee Gateway gewählt werden.</small></div>
|
||
<div class="device-editor" data-device-editor="ev_charger"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="5">
|
||
<p class="wizard-question">Welche einstufigen Verbraucher sollen berücksichtigt werden?</p>
|
||
<div class="quantity-line"><label>Anzahl<input name="consumerQuantity" data-device-quantity="consumer_single" type="number" min="0" max="50" value="0"></label><small>Bei Shelly-Profilen werden Schaltkontakt und Rückmeldung automatisch verbunden.</small></div>
|
||
<div class="device-editor" data-device-editor="consumer_single"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="6">
|
||
<p class="wizard-question">Gibt es mehrstufige Boiler oder Warmwassererwärmer?</p>
|
||
<div class="quantity-line"><label>Anzahl<input name="boilerQuantity" data-device-quantity="boiler_multi" type="number" min="0" max="50" value="0"></label><small>Leistungsstufen, Zeitplan und Temperaturfühler werden als Listen konfiguriert.</small></div>
|
||
<div class="device-editor" data-device-editor="boiler_multi"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="7">
|
||
<p class="wizard-question">Welche Wärmepumpen sollen eingerichtet werden?</p>
|
||
<div class="quantity-line"><label>Anzahl<input name="heatPumpQuantity" data-device-quantity="heat_pump" type="number" min="0" max="50" value="0"></label></div>
|
||
<div class="device-editor" data-device-editor="heat_pump"></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="8">
|
||
<p class="wizard-question">Soll im selben Symcon-System ein Verbrauchskostenreport eingerichtet werden?</p>
|
||
<label class="setup-option"><input name="costReportEnabled" type="checkbox"><span><strong>Verbrauchskostenreport hinzufügen</strong><small>Wird als eigene Instanz eingerichtet und verwendet einen separaten Lizenzcode.</small></span></label>
|
||
<div class="field-grid"><label>Stromzähler<input name="costPowerMeters" type="number" min="0" max="999" value="0"></label><label>Wärme- oder Wasserzähler<input name="costAuxMeters" type="number" min="0" max="999" value="0"></label></div>
|
||
</section>
|
||
<section class="wizard-step" data-wizard-step="9">
|
||
<p class="wizard-question">Bitte prüfe die Angaben vor dem Speichern.</p>
|
||
<div id="wizardReview" class="wizard-review"></div>
|
||
</section>
|
||
<p class="form-error" id="systemError"></p>
|
||
<footer class="wizard-actions"><button class="button secondary" id="wizardBack" type="button">Zurück</button><button class="button primary" id="wizardNext" type="button">Weiter</button><button class="button primary hidden" id="wizardSubmit" type="submit">Konfiguration abschliessen</button></footer>
|
||
</section>
|
||
<aside class="recommendation-panel"><p class="eyebrow">Aktueller Vorschlag</p><h2 id="recommendManager">Manager ohne Peak Shaving</h2><div id="recommendModules" class="recommend-list"></div><p>Der Vorschlag enthält den Manager und alle gewählten Verbrauchermodule.</p><div id="packageResult" class="package-result hidden"><strong>Einrichtungspaket bereit</strong><a class="button secondary wide" id="packageDownload" href="#">Symcon-Paket herunterladen</a><button class="button primary wide" id="orderRecommendation" type="button">Lizenzen bestellen</button></div></aside>
|
||
</form>
|
||
</section>
|
||
|
||
<section class="view" id="view-forecast">
|
||
<div class="page-head"><div><p class="eyebrow">Betrieb</p><h1>Prognose</h1><p>Messwerte und berechnete Verläufe des lizenzierten Prognosemanagers.</p></div><span class="status available">Nur Anzeige</span></div>
|
||
<div id="forecastEmpty" class="empty-state hidden"><strong>Kein System verfügbar</strong></div>
|
||
<div id="forecastContent">
|
||
<section class="forecast-toolbar">
|
||
<label>System<select id="forecastPlant"></select></label>
|
||
<div class="connection-state"><span class="signal"></span><div><strong id="forecastConnection">Noch nicht verknüpft</strong><p id="forecastApiStatus">Status wird geprüft</p></div></div>
|
||
</section>
|
||
<div class="forecast-metrics">
|
||
<div><span id="forecastLastUpdated">–</span><small>Aktualisiert</small></div>
|
||
<div><span id="forecastSeriesCount">0</span><small>Datenreihen</small></div>
|
||
<div><span id="forecastWindowValue">72 h</span><small>Zeitfenster</small></div>
|
||
</div>
|
||
<section class="forecast-chart-section">
|
||
<div class="section-head"><div><h2>Leistung und Prognose</h2><p>Messwerte und Prognosen gemeinsam vergleichen. Reihen können einzeln ein- und ausgeblendet werden.</p></div></div>
|
||
<div class="forecast-series-panel">
|
||
<strong>Kurven auswählen</strong>
|
||
<div id="forecastSeriesControls" class="forecast-series-controls"></div>
|
||
</div>
|
||
<div class="forecast-chart-controls">
|
||
<label>Historie
|
||
<select id="forecastHistoryDays">
|
||
<option value="1" selected>1 Tag</option>
|
||
<option value="7">7 Tage</option>
|
||
<option value="14">14 Tage</option>
|
||
<option value="30">30 Tage</option>
|
||
<option value="90">90 Tage</option>
|
||
<option value="180">180 Tage</option>
|
||
</select>
|
||
</label>
|
||
<label>Von<input id="forecastRangeStart" type="datetime-local"></label>
|
||
<label>Bis<input id="forecastRangeEnd" type="datetime-local"></label>
|
||
<button id="forecastRangeReset" class="button secondary compact" type="button">Gesamtes Zeitfenster</button>
|
||
</div>
|
||
<div id="forecastState" class="forecast-state" role="status">Prognosedaten werden geladen.</div>
|
||
<div id="forecastLegend" class="forecast-chart-legend hidden" aria-label="Legende der angezeigten Kurven"></div>
|
||
<div class="forecast-chart-wrap">
|
||
<svg id="forecastChart" class="forecast-chart hidden" viewBox="0 0 960 320" preserveAspectRatio="none" role="img" aria-label="Zeitverlauf der Prognosedaten"></svg>
|
||
<div id="forecastTooltip" class="forecast-tooltip hidden"></div>
|
||
</div>
|
||
</section>
|
||
<section class="forecast-quality-section">
|
||
<div class="section-head"><div><h2>Prognosequalität</h2><p>Vergleich der Modellprognosen mit den tatsächlich gemessenen Werten.</p></div><span id="forecastQualityStatus" class="status review">Aufbauphase</span></div>
|
||
<div id="forecastQualityState" class="forecast-quality-state" role="status">Qualitätswerte werden gesammelt. Aussagekräftige Vergleiche entstehen mit wachsender Datenhistorie.</div>
|
||
<div id="forecastQualityTable" class="table-wrap hidden">
|
||
<table>
|
||
<thead><tr><th>Modell</th><th>Ziel</th><th>R²</th><th>MAE</th><th>RMSE</th><th>Vergleiche</th></tr></thead>
|
||
<tbody id="forecastQualityBody"></tbody>
|
||
</table>
|
||
</div>
|
||
</section>
|
||
<section id="forecastConfigSection" class="forecast-config-section hidden">
|
||
<div class="section-head">
|
||
<div><h2>Prognosekonfiguration</h2><p>Anlagenparameter für Berechnung und Tarife.</p></div>
|
||
<span id="forecastConfigStatus" class="status review">Nicht gespeichert</span>
|
||
</div>
|
||
<form id="forecastConfigForm">
|
||
<div class="forecast-config-grid">
|
||
<label>Standort<input name="standort" maxlength="120" required></label>
|
||
<label>Kanton<select name="kanton"><option>AG</option><option>AI</option><option>AR</option><option>BE</option><option>BL</option><option>BS</option><option>FR</option><option>GE</option><option>GL</option><option>GR</option><option>JU</option><option>LU</option><option>NE</option><option>NW</option><option>OW</option><option>SG</option><option>SH</option><option>SO</option><option>SZ</option><option>TG</option><option>TI</option><option>UR</option><option>VD</option><option>VS</option><option>ZG</option><option>ZH</option></select></label>
|
||
<label>PV AC-Leistung kW<input name="ac_leistung" data-technical-field type="number" min="0" max="100000" step="0.1" required></label>
|
||
<label>Batteriekapazität kWh<input name="batt_capacity_kwh" data-technical-field type="number" min="0" max="100000" step="0.1" required></label>
|
||
<label>Batterieleistung kW<input name="batt_power_kw" data-technical-field type="number" min="0" max="100000" step="0.1" required></label>
|
||
<label>Peakpreis CHF/kW<input name="tarif_peak_fest" type="number" min="0" max="100000" step="0.01" required></label>
|
||
<label>Bezug Tarifart<select name="tarif_bezug_modus"><option value="dynamisch">Dynamisch</option><option value="statisch">Statisch</option></select></label>
|
||
<label>Bezugstarif<select name="tarif_bezug"></select></label>
|
||
<label data-tariff-custom="import">Bezugspreis CHF/kWh<input name="tarif_bezug_fest" type="number" min="0" max="100" step="0.001" required></label>
|
||
<label>Einspeisung Tarifart<select name="tarif_einspeisung_modus"><option value="dynamisch">Dynamisch</option><option value="statisch">Statisch</option></select></label>
|
||
<label>Einspeisetarif<select name="tarif_einspeisung"></select></label>
|
||
<label data-tariff-custom="export">Einspeisevergütung CHF/kWh<input name="tarif_einspeisung_fest" type="number" min="0" max="100" step="0.001" required></label>
|
||
</div>
|
||
<div id="forecastTopologyBlock" class="forecast-config-block hidden">
|
||
<div class="config-block-head"><div><h3>Technische Anlagendaten</h3><p>Schreibgeschützt aus dem verbundenen Enelix Manager.</p></div><span class="status available">Manager</span></div>
|
||
<div id="forecastTopology" class="forecast-topology"></div>
|
||
</div>
|
||
<div class="forecast-config-block">
|
||
<div class="config-block-head"><div><h3>PV-Dächer</h3><p>Leistung, Neigung und Azimut je Dachfläche.</p></div><button id="forecastAddRoof" class="button secondary compact" type="button">Dach hinzufügen</button></div>
|
||
<div id="forecastRoofs" class="forecast-roofs"></div>
|
||
</div>
|
||
<div class="forecast-config-block">
|
||
<div class="config-block-head"><div><h3>Prognoseumfang</h3><p>Funktionen für diese Anlage. Der Netzfahrplan schliesst PV- und Verbrauchsprognose ein.</p></div></div>
|
||
<div class="forecast-variants">
|
||
<label><input type="checkbox" name="forecast_pv">PV-Ertragsprognose</label>
|
||
<label><input type="checkbox" name="forecast_load">Verbrauchsprognose</label>
|
||
<label><input type="checkbox" name="grid_schedule">Intelligenter Netzfahrplan</label>
|
||
</div>
|
||
</div>
|
||
<p id="forecastConfigError" class="form-error" role="alert"></p>
|
||
<div class="forecast-config-actions"><button class="button primary" type="submit">Konfiguration speichern</button></div>
|
||
</form>
|
||
</section>
|
||
<div class="forecast-layout">
|
||
<section class="manager-detail"><p class="eyebrow">Lizenzierte Variante</p><h2 id="forecastVariant">Manager</h2><div class="license-validity"><span>Lizenzdauer</span><strong>Unbeschränkt gültig</strong></div><div id="forecastOfflineWarning" class="offline-license-warning hidden" role="status"><strong id="forecastOfflineTitle">Keine Verbindung zum Lizenzserver</strong><p id="forecastOfflineText"></p></div></section>
|
||
<section class="forecast-scope"><p class="eyebrow">Datenumfang</p><h2>Live-Prognose</h2><dl class="detail-list"><div><dt>Modus</dt><dd>Konfiguration und Anzeige</dd></div><div><dt>Simulation</dt><dd>Nicht enthalten</dd></div><div><dt>Zugriff</dt><dd>Lizenzgebunden</dd></div></dl></section>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="view" id="view-faults">
|
||
<div class="page-head"><div><p class="eyebrow">Betrieb</p><h1>Störüberwachung</h1><p>Aktive und behobene Störungen der verbundenen Enelix Manager und Geräte.</p></div><span class="status neutral" id="faultConnectionStatus">Status wird geprüft</span></div>
|
||
<div id="faultEmpty" class="empty-state hidden"><strong>Kein Manager-System verfügbar</strong></div>
|
||
<div id="faultContent">
|
||
<section class="fault-toolbar">
|
||
<label>System<select id="faultPlant"></select></label>
|
||
<div class="connection-state"><span class="signal" id="faultSignal"></span><div><strong id="faultConnection">Noch nicht verknüpft</strong><p id="faultApiStatus">Status wird geprüft</p></div></div>
|
||
</section>
|
||
<div class="fault-metrics">
|
||
<div><span id="faultActiveCount">0</span><small>Aktive Störungen</small></div>
|
||
<div><span id="faultUrgentCount">0</span><small>Kritisch oder Fehler</small></div>
|
||
<div><span id="faultLastUpdated">–</span><small>Letzter Empfang</small></div>
|
||
</div>
|
||
<section class="fault-section">
|
||
<div class="section-head"><div><h2>Aktive Störungen</h2><p>Aktueller Vollsnapshot des Managers.</p></div></div>
|
||
<div id="faultState" class="fault-state" role="status">Störungsdaten werden geladen.</div>
|
||
<div id="faultActiveTable" class="table-wrap hidden"><table><thead><tr><th>Schweregrad</th><th>Quelle</th><th>Meldung</th><th>Seit</th></tr></thead><tbody id="faultActiveBody"></tbody></table></div>
|
||
</section>
|
||
<section class="fault-section">
|
||
<div class="section-head"><div><h2>Behobene Störungen</h2><p>Die letzten 100 abgeschlossenen Ereignisse.</p></div></div>
|
||
<div id="faultHistoryState" class="fault-state">Noch keine behobenen Störungen.</div>
|
||
<div id="faultHistoryTable" class="table-wrap hidden"><table><thead><tr><th>Schweregrad</th><th>Quelle</th><th>Meldung</th><th>Behoben</th></tr></thead><tbody id="faultHistoryBody"></tbody></table></div>
|
||
</section>
|
||
<section class="fault-section fault-notification-section">
|
||
<div class="section-head"><div><h2>E-Mail-Benachrichtigungen</h2><p>Empfänger für neue und behobene Störungen dieser Anlage.</p></div></div>
|
||
<form id="faultRecipientForm" class="fault-recipient-form">
|
||
<label>E-Mail-Adresse<input id="faultRecipientEmail" name="email" type="email" maxlength="254" autocomplete="email" placeholder="technik@beispiel.ch" required></label>
|
||
<button class="button secondary" type="submit">Hinzufügen</button>
|
||
</form>
|
||
<p id="faultRecipientError" class="form-error" role="alert"></p>
|
||
<div id="faultRecipientList" class="fault-recipient-list"></div>
|
||
<p id="faultRecipientStatus" class="fault-recipient-status">Empfänger werden geladen.</p>
|
||
</section>
|
||
</div>
|
||
</section>
|
||
|
||
<section class="view" id="view-account">
|
||
<div class="page-head"><div><p class="eyebrow">Einstellungen</p><h1>Konto und Abrechnung</h1><p>Zugang, Organisation, Personen und Zahlungsverlauf.</p></div><button class="button secondary" id="logoutButton" type="button">Abmelden</button></div>
|
||
<div class="account-layout">
|
||
<section><h2>Benutzerkonto</h2><dl class="detail-list"><div><dt>Name</dt><dd id="accountName">–</dd></div><div><dt>E-Mail</dt><dd id="accountEmail">–</dd></div><div><dt>Arbeitsbereich</dt><dd id="accountOrg">–</dd></div></dl><label id="accountWorkspaceLabel">Organisation<select id="accountWorkspaceSelect"></select></label></section>
|
||
<section id="organizationCreateSection"><h2>Organisation anlegen</h2><form id="organizationForm" class="compact-form"><label>Name<input name="name" required minlength="2"></label><p class="form-error" id="organizationError"></p><button class="button secondary" type="submit">Organisation erstellen</button></form></section>
|
||
<section id="invitationSection" class="hidden"><h2>Person einladen</h2><form id="invitationForm" class="compact-form"><label>E-Mail-Adresse<input name="email" type="email" required></label><label>Rolle<select name="role"><option value="operator">Operator</option><option value="admin">Administrator</option><option value="billing">Abrechnung</option><option value="viewer">Lesend</option></select></label><p class="form-error" id="invitationError"></p><button class="button secondary" type="submit">Einladung senden</button></form><div id="pendingInvitations" class="pending-list"></div></section>
|
||
<section><h2>Passwort ändern</h2><form id="passwordForm" class="compact-form"><label>Aktuelles Passwort<input name="currentPassword" type="password" autocomplete="current-password" required></label><label>Neues Passwort<input name="newPassword" type="password" autocomplete="new-password" required minlength="10"><small>Mindestens 10 Zeichen.</small></label><label>Neues Passwort wiederholen<input name="newPasswordRepeat" type="password" autocomplete="new-password" required minlength="10"></label><p class="form-error" id="passwordError"></p><button class="button secondary" type="submit">Passwort speichern</button></form></section>
|
||
</div>
|
||
<section class="work-section billing-orders"><div class="section-head"><div><h2>Abrechnung</h2><p>Zahlungen, Lizenzcodes und PDF-Belege der aktuellen Organisation.</p></div><div class="billing-summary"><span class="status review" id="billingStripeStatus">Stripe Sandbox</span><span id="billingOrg">–</span><span id="stripeProviderState">Prüfung</span></div></div><div class="table-wrap"><table><thead><tr><th>Datum</th><th>System</th><th>Lizenzen</th><th>Gesamt inkl. MwSt.</th><th>Status</th><th>Lizenzcode</th><th>Beleg</th></tr></thead><tbody id="ordersBody"></tbody></table></div></section>
|
||
</section>
|
||
</main>
|
||
</div>
|
||
</div>
|
||
|
||
<dialog id="newLicenseDialog" class="decision-dialog"><div class="dialog-body"><div class="dialog-head"><div><p class="eyebrow">Neue Lizenz</p><h2>Wie möchtest du starten?</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="purchase-paths"><button type="button" data-open-plant><span><strong>Lizenz direkt kaufen</strong><small>Lizenzpaket anlegen und benötigte Module auswählen.</small></span><b>Weiter</b></button><button type="button" data-goto="configurator"><span><strong>System mit Manager konfigurieren</strong><small>Geräte erfassen und passende Lizenzen ermitteln.</small></span><b>Konfigurieren</b></button><button type="button" data-open-billing><span><strong>Abrechnungslizenz lösen</strong><small>Abrechnungsmanager und benötigte Zähler lizenzieren.</small></span><b>Auswählen</b></button></div></div></dialog>
|
||
|
||
<dialog id="plantDialog"><form id="plantForm"><div class="dialog-head"><div><p class="eyebrow">Direkter Kauf</p><h2>Neue Lizenz vorbereiten</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="field-pair"><label>Bezeichnung<input name="name" required placeholder="z. B. Werk Zürich"></label><label>Typ<select name="type"><option>Gewerbe</option><option>Privat</option><option>Industrie</option></select></label></div><label>Standort<input name="location" required placeholder="Ort, Schweiz"></label><fieldset><legend>Prognosemanager</legend><label class="choice-row"><input type="radio" name="manager" value="manager_standard" checked><span><strong>Ohne Peak Shaving</strong><small id="plantManagerStandardPrice">CHF 308.15 netto</small></span></label><label class="choice-row"><input type="radio" name="manager" value="manager_peak"><span><strong>Mit Peak Shaving</strong><small id="plantManagerPeakPrice">CHF 329.05 netto</small></span></label></fieldset><p class="form-error" id="plantError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button primary" type="submit">Weiter zur Lizenzwahl</button></div></form></dialog>
|
||
|
||
<dialog id="billingDialog"><form id="billingForm"><div class="dialog-head"><div><p class="eyebrow">Abrechnung</p><h2>Abrechnungslizenz vorbereiten</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div id="billingIdentityFields"><div class="field-pair"><label>Bezeichnung<input name="name" required placeholder="z. B. Abrechnung Werk Zürich"></label><label>Typ<input name="type" value="Abrechnung" readonly></label></div><label>Standort<input name="location" required placeholder="Ort, Schweiz"></label></div><fieldset><legend>Zählerlizenzen</legend><div class="field-pair"><label>Stromzähler<input name="powerMeters" type="number" min="0" max="999" value="0" required><small id="billingPowerPrice">CHF 5.00 netto pro Zähler</small></label><label>Wärme- oder Wasserzähler<input name="auxMeters" type="number" min="0" max="999" value="0" required><small id="billingAuxPrice">CHF 3.00 netto pro Zähler</small></label></div></fieldset><p class="billing-base-price">Grundlizenz: <strong id="billingBasePrice">CHF 245.15 netto</strong>. Zuzüglich MwSt.</p><p class="form-error" id="billingError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button primary" type="submit">Weiter zu Stripe</button></div></form></dialog>
|
||
|
||
<dialog id="replaceCodeDialog" class="warning-dialog"><div class="dialog-body"><div class="dialog-head"><div><p class="eyebrow">Sicherheitsaktion</p><h2>Lizenzcode neu generieren</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="replacement-warning"><strong>Achtung: Der aktuelle Lizenzcode wird ungültig.</strong><p>Für <b id="replaceCodeSystem">dieses System</b> wird ein neuer Code erstellt und ausschließlich als PDF an die Konto-E-Mail-Adresse gesendet.</p><p id="replaceCodeBinding" class="hidden">Die bisherige Installationsbindung wird gelöst. Der Ersatzcode kann anschließend einmalig mit einer neuen Symcon-Installation verbunden werden.</p></div><p class="form-error" id="replaceCodeError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button danger" id="confirmReplaceCode" type="button">Alten Code ersetzen</button></div></div></dialog>
|
||
|
||
<dialog id="deleteCodeDialog" class="warning-dialog"><div class="dialog-body"><div class="dialog-head"><div><p class="eyebrow">Sicherheitsaktion</p><h2>Lizenzcode löschen?</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="replacement-warning"><strong>Sind Sie sicher?</strong><p>Der aktuelle Lizenzcode für <b id="deleteCodeSystem">dieses System</b> wird sofort und unwiderruflich ungültig.</p><p>Die bezahlte Lizenz und eine bestehende Installationsbindung bleiben erhalten. Ein neuer Code kann später wieder per E-Mail erzeugt werden.</p></div><p class="form-error" id="deleteCodeError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button danger" id="confirmDeleteCode" type="button">Lizenzcode löschen</button></div></div></dialog>
|
||
|
||
<dialog id="deletePlantDialog" class="warning-dialog"><div class="dialog-body"><div class="dialog-head"><div><p class="eyebrow">Anlage löschen</p><h2>Sind Sie sicher?</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="replacement-warning"><strong>Die Anlage wird dauerhaft entfernt.</strong><p>Möchten Sie <b id="deletePlantSystem">diese Anlage</b> wirklich löschen? Konfigurationen und noch nicht bezahlte Bestellungen dieser Anlage werden ebenfalls entfernt.</p></div><p class="form-error" id="deletePlantError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button danger" id="confirmDeletePlant" type="button">Anlage löschen</button></div></div></dialog>
|
||
|
||
<dialog id="deletePaidDialog" class="warning-dialog"><div class="dialog-body"><div class="dialog-head"><div><p class="eyebrow">Zweite Bestätigung</p><h2>Auch Lizenz löschen?</h2></div><button class="icon-button" type="button" data-close-dialog aria-label="Schließen">×</button></div><div class="replacement-warning critical-warning"><strong>Achtung: Für diese Anlage besteht eine bezahlte Lizenz.</strong><p>Sollen <b id="deletePaidSystem">die Anlage</b> und die zugehörigen Lizenzcodes, Berechtigungen, Bestellungen und Sandbox-Zahlungsdaten wirklich endgültig gelöscht werden?</p><p>Diese Aktion kann nicht rückgängig gemacht werden.</p></div><p class="form-error" id="deletePaidError"></p><div class="dialog-actions"><button class="button secondary" type="button" data-close-dialog>Abbrechen</button><button class="button danger" id="confirmDeletePaid" type="button">Anlage und Lizenz löschen</button></div></div></dialog>
|
||
|
||
<script src="/app.js?v=20261006-heat-pump"></script>
|
||
</body>
|
||
</html>
|