dolibarr.elektroplanung/tools/selektivitaet.php
data 0b5056337a feat: Elektroplanung Modul v1.0.0
Elektrotechnische Berechnungstools für Dolibarr:
- Leitungsquerschnittsrechner (DIN VDE 0100-520, DIN VDE 0298-4)
- Widerstandsrechner für Potentialausgleich (VDE 0100-534/540)
- Selektivitäts-Assistent (VDE 0100-530)

Features:
- Dark Mode Unterstützung
- Responsive Design
- PDF-Export
- Dolibarr-Berechtigungssystem

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-24 12:06:47 +01:00

1083 lines
36 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
/* Copyright (C) 2026 Eduard Wisch <data@data-it-solution.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file tools/selektivitaet.php
* \ingroup elektroplanung
* \brief Selektivitäts-Assistent nach VDE 0100-530
*/
// Load Dolibarr environment
$res = 0;
if (!$res && file_exists("../../main.inc.php")) {
$res = @include "../../main.inc.php";
}
if (!$res && file_exists("../../../main.inc.php")) {
$res = @include "../../../main.inc.php";
}
if (!$res) {
die("Include of main fails");
}
require_once DOL_DOCUMENT_ROOT.'/core/lib/functions.lib.php';
require_once DOL_DOCUMENT_ROOT.'/core/class/html.form.class.php';
// Load translation files
$langs->loadLangs(array("elektroplanung@elektroplanung"));
// Security check
if (!isModEnabled('elektroplanung')) {
accessforbidden('Module not enabled');
}
if (!$user->hasRight('elektroplanung', 'tools', 'read')) {
accessforbidden('Permission denied');
}
$form = new Form($db);
// Page header
llxHeader('', $langs->trans("ElektroplanungSelektivitaet"), '', '', 0, 0, array(
'https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js'
), array(
'/elektroplanung/css/elektroplanung.css'
), '', 'mod-elektroplanung page-selektivitaet');
// Viewport für Mobile
print '<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">';
print load_fiche_titre($langs->trans("ElektroplanungSelektivitaet"), '', 'fa-project-diagram');
print '<div class="fichecenter">';
?>
<!-- Styles sind in /elektroplanung/css/elektroplanung.css -->
<div class="ep-calculator">
<!-- TABS -->
<div class="ep-tabs">
<div class="ep-tab active" onclick="selSwitchTab('pruefen')">
<span class="fa fa-check-circle"></span> <?php echo $langs->trans("ElektroplanungSelPruefen"); ?>
</div>
<div class="ep-tab" onclick="selSwitchTab('kette')">
<span class="fa fa-link"></span> <?php echo $langs->trans("ElektroplanungSelKette"); ?>
</div>
<div class="ep-tab" onclick="selSwitchTab('tabellen')">
<span class="fa fa-table"></span> <?php echo $langs->trans("ElektroplanungSelTabellen"); ?>
</div>
<div class="ep-tab" onclick="selSwitchTab('vde')">
<span class="fa fa-book"></span> <?php echo $langs->trans("ElektroplanungSelVDE"); ?>
</div>
</div>
<!-- TAB 1: Selektivität prüfen -->
<div id="selTabPruefen" class="ep-tab-content active">
<div class="ep-toolbar">
<button class="butAction" onclick="selPruefen()">
<span class="fa fa-check"></span> <?php echo $langs->trans("ElektroplanungSelPruefenBtn"); ?>
</button>
<button class="butAction" onclick="selExportPDF()">
<span class="fa fa-file-pdf-o"></span> PDF
</button>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-arrow-up"></span> <?php echo $langs->trans("ElektroplanungSelVorsicherung"); ?>
</div>
<div class="ep-form-grid">
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelTyp"); ?>:</label>
<select id="selVorTyp" onchange="selUpdateVorWerte()">
<option value="NH">NH-Sicherung (gG/gL)</option>
<option value="D">D-Sicherung (Diazed)</option>
<option value="SLS">SLS-Schalter</option>
<option value="LS">Leitungsschutzschalter</option>
</select>
</div>
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelNennstrom"); ?> [A]:</label>
<select id="selVorWert">
<option value="63">63 A</option>
<option value="80">80 A</option>
<option value="100">100 A</option>
<option value="125">125 A</option>
<option value="160">160 A</option>
<option value="200">200 A</option>
<option value="250">250 A</option>
</select>
</div>
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelOrt"); ?>:</label>
<select id="selVorOrt">
<option value="HAK">HAK (Hausanschlusskasten)</option>
<option value="ZS">Zählerschrank</option>
<option value="HV">Hauptverteilung</option>
<option value="UV">Unterverteilung</option>
</select>
</div>
</div>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-arrow-down"></span> <?php echo $langs->trans("ElektroplanungSelNachsicherung"); ?>
</div>
<div class="ep-form-grid">
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelTyp"); ?>:</label>
<select id="selNachTyp" onchange="selUpdateNachWerte()">
<option value="SLS">SLS-Schalter</option>
<option value="LS_B">Leitungsschutzschalter Char. B</option>
<option value="LS_C">Leitungsschutzschalter Char. C</option>
<option value="NH">NH-Sicherung (gG/gL)</option>
<option value="D">D-Sicherung (Diazed)</option>
</select>
</div>
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelNennstrom"); ?> [A]:</label>
<select id="selNachWert">
<option value="35">35 A</option>
<option value="40">40 A</option>
<option value="50">50 A</option>
<option value="63">63 A</option>
</select>
</div>
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelOrt"); ?>:</label>
<select id="selNachOrt">
<option value="ZS">Zählerschrank</option>
<option value="HV">Hauptverteilung</option>
<option value="UV">Unterverteilung</option>
<option value="SK">Stromkreis</option>
</select>
</div>
</div>
</div>
<!-- Ergebnis -->
<div id="selResultBox" class="ep-result-box">
<div class="ep-result-main" id="selResultStatus">-</div>
<div class="ep-result-status" id="selResultText">-</div>
<div class="ep-result-details">
<div class="ep-result-item">
<span><?php echo $langs->trans("ElektroplanungSelVorsicherung"); ?>:</span>
<span class="ep-result-value" id="selResultVor">-</span>
</div>
<div class="ep-result-item">
<span><?php echo $langs->trans("ElektroplanungSelNachsicherung"); ?>:</span>
<span class="ep-result-value" id="selResultNach">-</span>
</div>
<div class="ep-result-item">
<span><?php echo $langs->trans("ElektroplanungSelVerhaeltnis"); ?>:</span>
<span class="ep-result-value" id="selResultVerhaeltnis">-</span>
</div>
<div class="ep-result-item">
<span><?php echo $langs->trans("ElektroplanungSelVDENorm"); ?>:</span>
<span class="ep-result-value" id="selResultVDE">-</span>
</div>
</div>
<div id="selResultHinweis" class="ep-result-hint"></div>
</div>
</div>
<!-- TAB 2: Sicherungskette -->
<div id="selTabKette" class="ep-tab-content">
<div class="ep-toolbar">
<button class="butAction" onclick="selAddKettenglied()">
<span class="fa fa-plus"></span> <?php echo $langs->trans("ElektroplanungSelHinzufuegen"); ?>
</button>
<button class="butAction" onclick="selKettePruefen()">
<span class="fa fa-check-circle"></span> <?php echo $langs->trans("ElektroplanungSelKettePruefen"); ?>
</button>
<button class="butActionDelete" onclick="selKetteLoeschen()">
<span class="fa fa-trash"></span> <?php echo $langs->trans("ElektroplanungSelKetteLoeschen"); ?>
</button>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-link"></span> <?php echo $langs->trans("ElektroplanungSelKetteConfig"); ?>
</div>
<p class="ep-hint">
<?php echo $langs->trans("ElektroplanungSelKetteInfo"); ?>
</p>
<!-- Schnellauswahl -->
<div class="ep-form-grid">
<div class="ep-form-group">
<label><?php echo $langs->trans("ElektroplanungSelVorlage"); ?>:</label>
<select id="selVorlage" onchange="selLadeVorlage()">
<option value=""><?php echo $langs->trans("ElektroplanungSelVorlageWaehlen"); ?></option>
<option value="wohnung_standard">Wohnung Standard (HAK 63A → ZS 35A → LS 16A)</option>
<option value="wohnung_gross">Wohnung Groß (HAK 63A → ZS 50A → UV 25A → LS 16A)</option>
<option value="efh">Einfamilienhaus (HAK 63A → ZS 63A → UV 35A → LS 16A)</option>
<option value="gewerbe">Gewerbe (HAK 100A → HV 63A → UV 35A → LS 16A)</option>
</select>
</div>
</div>
<div id="selKetteContainer" class="ep-chain">
<!-- Wird dynamisch gefüllt -->
<div class="ep-centered-hint">
<?php echo $langs->trans("ElektroplanungSelKetteLeer"); ?>
</div>
</div>
</div>
<!-- Ketten-Ergebnis -->
<div id="selKetteResultBox" class="ep-result-box">
<div class="ep-result-main" id="selKetteResultStatus">-</div>
<div class="ep-result-status" id="selKetteResultText">-</div>
<div id="selKetteResultDetails"></div>
</div>
</div>
<!-- TAB 3: Selektivitätstabellen -->
<div id="selTabTabellen" class="ep-tab-content">
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-table"></span> <?php echo $langs->trans("ElektroplanungSelTabelleSchmelz"); ?>
</div>
<p class="ep-hint">
<strong>VDE 0100-530:</strong> <?php echo $langs->trans("ElektroplanungSelSchmelzInfo"); ?>
</p>
<table class="ep-table">
<thead>
<tr>
<th><?php echo $langs->trans("ElektroplanungSelNachsicherung"); ?></th>
<th colspan="8"><?php echo $langs->trans("ElektroplanungSelVorsicherung"); ?> (gG/gL) - <?php echo $langs->trans("ElektroplanungSelMindestwert"); ?></th>
</tr>
<tr>
<th>gG/gL</th>
<th>25A</th>
<th>32A</th>
<th>40A</th>
<th>50A</th>
<th>63A</th>
<th>80A</th>
<th>100A</th>
<th>125A</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>16A</strong></td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>20A</strong></td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>25A</strong></td>
<td>-</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>32A</strong></td>
<td>-</td>
<td>-</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>40A</strong></td>
<td>-</td>
<td>-</td>
<td>-</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>50A</strong></td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
<tr>
<td><strong>63A</strong></td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td>-</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
</tbody>
</table>
<p class="ep-hint-small">
✓ = Selektiv | ~ = Teilselektiv (nur bei Überlast) | - = Nicht selektiv
</p>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-table"></span> <?php echo $langs->trans("ElektroplanungSelTabelleSLS"); ?>
</div>
<p class="ep-hint">
<strong>TAB 2019:</strong> <?php echo $langs->trans("ElektroplanungSelSLSInfo"); ?>
</p>
<table class="ep-table">
<thead>
<tr>
<th>SLS</th>
<th colspan="6"><?php echo $langs->trans("ElektroplanungSelNachgeschaltet"); ?> LS-Schalter (B/C)</th>
</tr>
<tr>
<th></th>
<th>B10</th>
<th>B13</th>
<th>B16</th>
<th>B20</th>
<th>B25</th>
<th>B32</th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>SLS 35A</strong></td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-warning">~</td>
<td class="ep-badge-error">✗</td>
</tr>
<tr>
<td><strong>SLS 50A</strong></td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-warning">~</td>
</tr>
<tr>
<td><strong>SLS 63A</strong></td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
<td class="ep-badge-success">✓</td>
</tr>
</tbody>
</table>
<p class="ep-hint-small">
✓ = Selektiv bis 10kA | ~ = Teilselektiv | ✗ = Nicht selektiv
</p>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-table"></span> <?php echo $langs->trans("ElektroplanungSelTabelleRCD"); ?>
</div>
<p class="ep-hint">
<strong>VDE 0100-530, 535.2.2:</strong> <?php echo $langs->trans("ElektroplanungSelRCDInfo"); ?>
</p>
<table class="ep-table">
<thead>
<tr>
<th><?php echo $langs->trans("ElektroplanungSelVorgeschaltet"); ?></th>
<th><?php echo $langs->trans("ElektroplanungSelNachgeschaltet"); ?></th>
<th><?php echo $langs->trans("ElektroplanungSelErgebnis"); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>RCD Typ S, 300mA</td>
<td>RCD 30mA</td>
<td><span class="ep-badge ep-badge-success">Selektiv (Faktor 10)</span></td>
</tr>
<tr>
<td>RCD Typ S, 100mA</td>
<td>RCD 30mA</td>
<td><span class="ep-badge ep-badge-success">Selektiv (Faktor 3,3)</span></td>
</tr>
<tr>
<td>RCD 300mA (nicht S)</td>
<td>RCD 30mA</td>
<td><span class="ep-badge ep-badge-warning">Teilselektiv</span></td>
</tr>
<tr>
<td>RCD 100mA</td>
<td>RCD 30mA</td>
<td><span class="ep-badge ep-badge-error">Nicht selektiv</span></td>
</tr>
</tbody>
</table>
<p class="ep-hint-small">
Vorgeschaltete RCD muss Typ S sein UND mindestens 3-fachen IΔn haben.
</p>
</div>
</div>
<!-- TAB 4: VDE Normen -->
<div id="selTabVde" class="ep-tab-content">
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-book"></span> <?php echo $langs->trans("ElektroplanungSelVDENormen"); ?>
</div>
<table class="ep-table">
<thead>
<tr>
<th><?php echo $langs->trans("ElektroplanungSelNorm"); ?></th>
<th><?php echo $langs->trans("ElektroplanungSelInhalt"); ?></th>
<th><?php echo $langs->trans("ElektroplanungSelPflicht"); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td><strong>VDE 0100-530</strong><br><small>535.1.2, 535.1.3, 535.2.2</small></td>
<td>
Definition Selektivität, Hinweise zur Erreichung bei Überstrom- und Fehlerstrom-Schutzeinrichtungen
</td>
<td><span class="ep-badge ep-badge-warning">Empfohlen</span><br><small>Keine explizite Forderung</small></td>
</tr>
<tr>
<td><strong>VDE 0100-560</strong><br><small>563.4</small></td>
<td>
Elektrische Anlagen für Sicherheitszwecke (Notbeleuchtung, Brandmeldeanlage etc.)
</td>
<td><span class="ep-badge ep-badge-error">Pflicht</span><br><small>Selektivität gefordert</small></td>
</tr>
<tr>
<td><strong>TAB 2019</strong><br><small>Abschnitt 7</small></td>
<td>
Selektivität zwischen Kundenanlage und Hauptstromversorgungssystem / Hausanschlusssicherung
</td>
<td><span class="ep-badge ep-badge-error">Pflicht</span><br><small>Zum Netz hin</small></td>
</tr>
<tr>
<td><strong>VDE 0100-410</strong><br><small>411.3.2</small></td>
<td>
Schutz durch automatische Abschaltung - Abschaltzeiten
</td>
<td><span class="ep-badge ep-badge-error">Pflicht</span><br><small>Personenschutz</small></td>
</tr>
</tbody>
</table>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-exclamation-triangle"></span> <?php echo $langs->trans("ElektroplanungSelWichtig"); ?>
</div>
<div class="ep-info-box">
<strong><?php echo $langs->trans("ElektroplanungSelWichtigTitel"); ?>:</strong>
<ul>
<li><strong>LS-Schalter untereinander:</strong> Grundsätzlich NICHT selektiv bei Kurzschluss! Nur bei Überlast durch Nennstromabstufung.</li>
<li><strong>Schmelzsicherungen:</strong> Selektiv bei Faktor ≥ 1,6 (2 Nennstromstufen Abstand)</li>
<li><strong>SLS vor LS:</strong> Speziell für Selektivität konstruiert - beste Lösung im Zählerbereich</li>
<li><strong>RCD:</strong> Vorgeschaltete muss Typ S sein UND IΔn ≥ 3× nachgeschaltete</li>
</ul>
</div>
</div>
<div class="ep-section">
<div class="ep-section-title">
<span class="fa fa-lightbulb-o"></span> <?php echo $langs->trans("ElektroplanungSelPraxistipps"); ?>
</div>
<table class="ep-table">
<thead>
<tr>
<th><?php echo $langs->trans("ElektroplanungSelSituation"); ?></th>
<th><?php echo $langs->trans("ElektroplanungSelEmpfehlung"); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>Wohnung mit 63A HAK</td>
<td>HAK NH 63A → SLS 35A/50A im ZS → LS B16 in UV</td>
</tr>
<tr>
<td>EFH mit Unterverteilung</td>
<td>HAK NH 63A → SLS 63A → NH/D 35A für UV → LS B16</td>
</tr>
<tr>
<td>Gewerbe mit mehreren UV</td>
<td>HAK NH 100A → NH 63A HV → NH 35A UV → LS B/C 16A</td>
</tr>
<tr>
<td>Sicherheitsbeleuchtung</td>
<td>Eigener Stromkreis mit selektiver Absicherung (VDE 0100-560)</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
// Globale Variablen
let selKette = [];
let selCalculationData = {};
// Selektivitätsdaten
const selData = {
// Faktor für Schmelzsicherungen
schmelzFaktor: 1.6,
// SLS zu LS Selektivität (vereinfacht)
slsZuLs: {
35: { max: 20, teilweise: 25 },
50: { max: 25, teilweise: 32 },
63: { max: 32, teilweise: 40 }
},
// NH zu SLS/LS
nhZuSls: {
63: { max: 50 },
80: { max: 63 },
100: { max: 80 },
125: { max: 100 }
}
};
// Tab-Wechsel
function selSwitchTab(tab) {
document.querySelectorAll('.ep-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.ep-tab-content').forEach(c => c.classList.remove('active'));
document.querySelector(`.ep-tab[onclick*="${tab}"]`).classList.add('active');
document.getElementById('selTab' + tab.charAt(0).toUpperCase() + tab.slice(1)).classList.add('active');
}
// Werte für Vorsicherung aktualisieren
function selUpdateVorWerte() {
const typ = document.getElementById('selVorTyp').value;
const select = document.getElementById('selVorWert');
select.innerHTML = '';
let werte = [];
switch(typ) {
case 'NH':
werte = [63, 80, 100, 125, 160, 200, 250, 315, 400];
break;
case 'D':
werte = [16, 20, 25, 32, 35, 40, 50, 63];
break;
case 'SLS':
werte = [35, 50, 63, 80, 100];
break;
case 'LS':
werte = [16, 20, 25, 32, 40, 50, 63];
break;
}
werte.forEach(w => {
const opt = document.createElement('option');
opt.value = w;
opt.textContent = w + ' A';
select.appendChild(opt);
});
}
// Werte für Nachsicherung aktualisieren
function selUpdateNachWerte() {
const typ = document.getElementById('selNachTyp').value;
const select = document.getElementById('selNachWert');
select.innerHTML = '';
let werte = [];
switch(typ) {
case 'SLS':
werte = [35, 50, 63];
break;
case 'LS_B':
case 'LS_C':
werte = [6, 10, 13, 16, 20, 25, 32, 40, 50, 63];
break;
case 'NH':
werte = [16, 20, 25, 32, 35, 40, 50, 63, 80, 100];
break;
case 'D':
werte = [16, 20, 25, 32, 35, 40, 50, 63];
break;
}
werte.forEach(w => {
const opt = document.createElement('option');
opt.value = w;
opt.textContent = w + ' A';
select.appendChild(opt);
});
}
// Selektivität prüfen
function selPruefen() {
const vorTyp = document.getElementById('selVorTyp').value;
const vorWert = parseInt(document.getElementById('selVorWert').value);
const vorOrt = document.getElementById('selVorOrt').value;
const nachTyp = document.getElementById('selNachTyp').value;
const nachWert = parseInt(document.getElementById('selNachWert').value);
const nachOrt = document.getElementById('selNachOrt').value;
let ergebnis = { selektiv: false, teilweise: false, vde: '', hinweis: '' };
const verhaeltnis = vorWert / nachWert;
// Prüflogik
if ((vorTyp === 'NH' || vorTyp === 'D') && (nachTyp === 'NH' || nachTyp === 'D')) {
// Schmelzsicherung zu Schmelzsicherung
if (verhaeltnis >= 1.6) {
ergebnis.selektiv = true;
ergebnis.vde = 'VDE 0100-530, 535.1.3';
ergebnis.hinweis = 'Schmelzsicherungen mit Faktor ≥ 1,6 sind selektiv.';
} else if (verhaeltnis >= 1.25) {
ergebnis.teilweise = true;
ergebnis.vde = 'VDE 0100-530, 535.1.3';
ergebnis.hinweis = 'Nur bei Überlast selektiv, bei Kurzschluss nicht garantiert.';
} else {
ergebnis.vde = 'VDE 0100-530, 535.1.3';
ergebnis.hinweis = 'Faktor < 1,25 - keine Selektivität. Mindestens 2 Stufen Abstand wählen.';
}
} else if ((vorTyp === 'NH' || vorTyp === 'D') && vorTyp !== 'SLS' && nachTyp === 'SLS') {
// NH zu SLS
if (verhaeltnis >= 1.25) {
ergebnis.selektiv = true;
ergebnis.vde = 'VDE 0100-530 / TAB 2019';
ergebnis.hinweis = 'NH-Sicherung vor SLS ist in der Regel selektiv.';
}
} else if (vorTyp === 'SLS' && (nachTyp === 'LS_B' || nachTyp === 'LS_C')) {
// SLS zu LS
const slsData = selData.slsZuLs[vorWert];
if (slsData) {
if (nachWert <= slsData.max) {
ergebnis.selektiv = true;
ergebnis.vde = 'TAB 2019, Herstellerangaben';
ergebnis.hinweis = 'SLS ist speziell für Selektivität zu LS konstruiert.';
} else if (nachWert <= slsData.teilweise) {
ergebnis.teilweise = true;
ergebnis.vde = 'TAB 2019, Herstellerangaben';
ergebnis.hinweis = 'Teilselektiv - bei hohen Kurzschlussströmen nicht garantiert.';
} else {
ergebnis.vde = 'TAB 2019';
ergebnis.hinweis = 'LS-Nennstrom zu hoch für diesen SLS. Größeren SLS oder kleineren LS wählen.';
}
}
} else if ((nachTyp === 'LS_B' || nachTyp === 'LS_C') && (vorTyp === 'LS_B' || vorTyp === 'LS_C' || vorTyp === 'LS')) {
// LS zu LS
ergebnis.vde = 'VDE 0100-530, 535.1.3';
ergebnis.hinweis = 'LS-Schalter sind untereinander grundsätzlich NICHT selektiv bei Kurzschluss! Bei Überlast ist durch Nennstromabstufung eine gewisse Staffelung möglich.';
if (verhaeltnis >= 1.6) {
ergebnis.teilweise = true;
}
} else if ((vorTyp === 'NH' || vorTyp === 'D') && (nachTyp === 'LS_B' || nachTyp === 'LS_C')) {
// Schmelzsicherung zu LS
if (vorWert >= 63 && nachWert <= 25) {
ergebnis.selektiv = true;
ergebnis.vde = 'Herstellerangaben';
ergebnis.hinweis = 'Bei großem Abstand (z.B. NH 63A zu B16) ist totale Selektivität möglich.';
} else if (verhaeltnis >= 2) {
ergebnis.teilweise = true;
ergebnis.vde = 'VDE 0100-530';
ergebnis.hinweis = 'Teilselektiv - Prüfung der Kennlinien empfohlen.';
} else {
ergebnis.vde = 'VDE 0100-530';
ergebnis.hinweis = 'Verhältnis zu gering für sichere Selektivität.';
}
}
// Daten speichern
selCalculationData = {
vorTyp, vorWert, vorOrt, nachTyp, nachWert, nachOrt,
verhaeltnis, ergebnis
};
// Ergebnis anzeigen
const resultBox = document.getElementById('selResultBox');
resultBox.classList.remove('success', 'warning', 'error');
if (ergebnis.selektiv) {
resultBox.classList.add('show', 'success');
document.getElementById('selResultStatus').textContent = '✓ SELEKTIV';
document.getElementById('selResultText').textContent = 'Die Kombination ist selektiv.';
} else if (ergebnis.teilweise) {
resultBox.classList.add('show', 'warning');
document.getElementById('selResultStatus').textContent = '~ TEILSELEKTIV';
document.getElementById('selResultText').textContent = 'Nur bei Überlast selektiv, bei Kurzschluss nicht garantiert.';
} else {
resultBox.classList.add('show', 'error');
document.getElementById('selResultStatus').textContent = '✗ NICHT SELEKTIV';
document.getElementById('selResultText').textContent = 'Diese Kombination ist nicht selektiv.';
}
document.getElementById('selResultVor').textContent = `${vorTyp} ${vorWert}A (${vorOrt})`;
document.getElementById('selResultNach').textContent = `${nachTyp.replace('_', ' ')} ${nachWert}A (${nachOrt})`;
document.getElementById('selResultVerhaeltnis').textContent = verhaeltnis.toFixed(2);
document.getElementById('selResultVDE').textContent = ergebnis.vde || '-';
document.getElementById('selResultHinweis').innerHTML = `<strong>Hinweis:</strong> ${ergebnis.hinweis}`;
resultBox.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// Ketten-Funktionen
function selAddKettenglied() {
const container = document.getElementById('selKetteContainer');
// Leere Nachricht entfernen
if (selKette.length === 0) {
container.innerHTML = '';
}
const id = Date.now();
const item = {
id: id,
typ: 'NH',
wert: 63,
ort: selKette.length === 0 ? 'HAK' : 'UV'
};
selKette.push(item);
const html = `
<div class="ep-chain-item" id="kette_${id}">
<div class="typ">
<select onchange="selUpdateKettenglied(${id}, 'typ', this.value)">
<option value="NH">NH</option>
<option value="D">Diazed</option>
<option value="SLS">SLS</option>
<option value="LS_B">LS B</option>
<option value="LS_C">LS C</option>
</select>
</div>
<div class="wert">
<select class="ep-chain-wert" onchange="selUpdateKettenglied(${id}, 'wert', this.value)">
<option value="63">63A</option>
<option value="50">50A</option>
<option value="35">35A</option>
<option value="25">25A</option>
<option value="16">16A</option>
</select>
</div>
<div class="name">
<select onchange="selUpdateKettenglied(${id}, 'ort', this.value)">
<option value="HAK">HAK</option>
<option value="ZS">ZS</option>
<option value="HV">HV</option>
<option value="UV">UV</option>
<option value="SK">SK</option>
</select>
</div>
<button class="ep-chain-delete" onclick="selEntferneKettenglied(${id})">×</button>
</div>
`;
// Pfeil hinzufügen wenn nicht erstes Element
if (selKette.length > 1) {
const arrow = document.createElement('div');
arrow.className = 'ep-chain-arrow';
arrow.id = 'arrow_' + id;
arrow.innerHTML = '→';
container.appendChild(arrow);
}
container.insertAdjacentHTML('beforeend', html);
}
function selUpdateKettenglied(id, field, value) {
const item = selKette.find(k => k.id === id);
if (item) {
item[field] = field === 'wert' ? parseInt(value) : value;
}
}
function selEntferneKettenglied(id) {
selKette = selKette.filter(k => k.id !== id);
const elem = document.getElementById('kette_' + id);
const arrow = document.getElementById('arrow_' + id);
if (elem) elem.remove();
if (arrow) arrow.remove();
if (selKette.length === 0) {
document.getElementById('selKetteContainer').innerHTML = '<div class="ep-centered-hint">Keine Sicherungen in der Kette. Fügen Sie Elemente hinzu.</div>';
}
}
function selKetteLoeschen() {
selKette = [];
document.getElementById('selKetteContainer').innerHTML = '<div class="ep-centered-hint">Keine Sicherungen in der Kette. Fügen Sie Elemente hinzu.</div>';
document.getElementById('selKetteResultBox').classList.remove('show');
}
function selLadeVorlage() {
const vorlage = document.getElementById('selVorlage').value;
if (!vorlage) return;
selKetteLoeschen();
const vorlagen = {
'wohnung_standard': [
{ typ: 'NH', wert: 63, ort: 'HAK' },
{ typ: 'SLS', wert: 35, ort: 'ZS' },
{ typ: 'LS_B', wert: 16, ort: 'SK' }
],
'wohnung_gross': [
{ typ: 'NH', wert: 63, ort: 'HAK' },
{ typ: 'SLS', wert: 50, ort: 'ZS' },
{ typ: 'LS_B', wert: 25, ort: 'UV' },
{ typ: 'LS_B', wert: 16, ort: 'SK' }
],
'efh': [
{ typ: 'NH', wert: 63, ort: 'HAK' },
{ typ: 'SLS', wert: 63, ort: 'ZS' },
{ typ: 'D', wert: 35, ort: 'UV' },
{ typ: 'LS_B', wert: 16, ort: 'SK' }
],
'gewerbe': [
{ typ: 'NH', wert: 100, ort: 'HAK' },
{ typ: 'NH', wert: 63, ort: 'HV' },
{ typ: 'D', wert: 35, ort: 'UV' },
{ typ: 'LS_C', wert: 16, ort: 'SK' }
]
};
const kette = vorlagen[vorlage];
if (kette) {
kette.forEach((item, index) => {
setTimeout(() => {
selAddKettengliedMitDaten(item);
}, index * 100);
});
}
}
function selAddKettengliedMitDaten(data) {
selAddKettenglied();
const id = selKette[selKette.length - 1].id;
selKette[selKette.length - 1] = { ...selKette[selKette.length - 1], ...data };
// UI aktualisieren
const elem = document.getElementById('kette_' + id);
if (elem) {
elem.querySelector('select:nth-of-type(1)').value = data.typ;
elem.querySelector('select:nth-of-type(2)').value = data.wert;
elem.querySelector('select:nth-of-type(3)').value = data.ort;
}
}
function selKettePruefen() {
if (selKette.length < 2) {
alert('Mindestens 2 Sicherungen in der Kette erforderlich.');
return;
}
let alleSelektiv = true;
let details = '<div class="ep-result-details">';
for (let i = 0; i < selKette.length - 1; i++) {
const vor = selKette[i];
const nach = selKette[i + 1];
const verhaeltnis = vor.wert / nach.wert;
let status = 'error';
let text = 'Nicht selektiv';
// Vereinfachte Prüfung
if ((vor.typ === 'NH' || vor.typ === 'D') && (nach.typ === 'NH' || nach.typ === 'D')) {
if (verhaeltnis >= 1.6) { status = 'success'; text = 'Selektiv'; }
else if (verhaeltnis >= 1.25) { status = 'warning'; text = 'Teilselektiv'; alleSelektiv = false; }
else { alleSelektiv = false; }
} else if (vor.typ === 'SLS' && (nach.typ === 'LS_B' || nach.typ === 'LS_C')) {
const slsData = selData.slsZuLs[vor.wert];
if (slsData && nach.wert <= slsData.max) { status = 'success'; text = 'Selektiv'; }
else if (slsData && nach.wert <= slsData.teilweise) { status = 'warning'; text = 'Teilselektiv'; alleSelektiv = false; }
else { alleSelektiv = false; }
} else if ((vor.typ === 'NH' || vor.typ === 'D') && nach.typ === 'SLS') {
if (verhaeltnis >= 1.25) { status = 'success'; text = 'Selektiv'; }
else { alleSelektiv = false; }
} else if ((vor.typ === 'LS_B' || vor.typ === 'LS_C') && (nach.typ === 'LS_B' || nach.typ === 'LS_C')) {
status = 'warning';
text = 'LS↔LS: Nur Überlast';
alleSelektiv = false;
} else if ((vor.typ === 'NH' || vor.typ === 'D') && (nach.typ === 'LS_B' || nach.typ === 'LS_C')) {
if (verhaeltnis >= 4) { status = 'success'; text = 'Selektiv'; }
else if (verhaeltnis >= 2) { status = 'warning'; text = 'Teilselektiv'; alleSelektiv = false; }
else { alleSelektiv = false; }
}
// Pfeil-Farbe aktualisieren
const arrow = document.getElementById('arrow_' + nach.id);
if (arrow) {
arrow.className = 'ep-chain-arrow ' + (status === 'success' ? 'ok' : 'nok');
}
// Element-Klasse aktualisieren
const elemVor = document.getElementById('kette_' + vor.id);
const elemNach = document.getElementById('kette_' + nach.id);
if (i === 0 && elemVor) {
elemVor.className = 'ep-chain-item';
}
if (elemNach) {
elemNach.className = 'ep-chain-item ' + (status === 'error' ? 'nicht-selektiv' : (status === 'success' ? 'selektiv' : ''));
}
const badgeClass = status === 'success' ? 'ep-badge-success' : (status === 'warning' ? 'ep-badge-warning' : 'ep-badge-error');
details += `<div class="ep-result-item">
<span>${vor.typ} ${vor.wert}A → ${nach.typ.replace('_', ' ')} ${nach.wert}A</span>
<span><span class="ep-badge ${badgeClass}">${text}</span> (${verhaeltnis.toFixed(2)})</span>
</div>`;
}
details += '</div>';
// Ergebnis anzeigen
const resultBox = document.getElementById('selKetteResultBox');
resultBox.classList.remove('success', 'warning', 'error');
if (alleSelektiv) {
resultBox.classList.add('show', 'success');
document.getElementById('selKetteResultStatus').textContent = '✓ KETTE SELEKTIV';
document.getElementById('selKetteResultText').textContent = 'Alle Übergänge sind selektiv.';
} else {
resultBox.classList.add('show', 'warning');
document.getElementById('selKetteResultStatus').textContent = '~ TEILWEISE SELEKTIV';
document.getElementById('selKetteResultText').textContent = 'Einige Übergänge sind nicht vollständig selektiv.';
}
document.getElementById('selKetteResultDetails').innerHTML = details;
resultBox.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
}
// PDF Export
function selExportPDF() {
if (!selCalculationData.vorTyp) {
alert('Bitte erst eine Prüfung durchführen!');
return;
}
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
const data = selCalculationData;
const datum = new Date().toLocaleDateString('de-DE');
let y = 20;
doc.setFontSize(18);
doc.setFont(undefined, 'bold');
doc.text('Selektivitätsprüfung', 105, y, { align: 'center' });
y += 8;
doc.setFontSize(10);
doc.setFont(undefined, 'normal');
doc.text('Nach VDE 0100-530', 105, y, { align: 'center' });
y += 5;
doc.text('Erstellt: ' + datum, 105, y, { align: 'center' });
y += 10;
doc.line(20, y, 190, y);
y += 10;
doc.setFontSize(14);
doc.setFont(undefined, 'bold');
if (data.ergebnis.selektiv) {
doc.setTextColor(16, 185, 129);
doc.text('SELEKTIV', 20, y);
} else if (data.ergebnis.teilweise) {
doc.setTextColor(245, 158, 11);
doc.text('TEILSELEKTIV', 20, y);
} else {
doc.setTextColor(239, 68, 68);
doc.text('NICHT SELEKTIV', 20, y);
}
doc.setTextColor(0, 0, 0);
y += 10;
doc.setFontSize(10);
doc.setFont(undefined, 'normal');
doc.text(`Vorsicherung: ${data.vorTyp} ${data.vorWert}A (${data.vorOrt})`, 20, y); y += 6;
doc.text(`Nachsicherung: ${data.nachTyp.replace('_', ' ')} ${data.nachWert}A (${data.nachOrt})`, 20, y); y += 6;
doc.text(`Verhältnis: ${data.verhaeltnis.toFixed(2)}`, 20, y); y += 6;
doc.text(`Norm: ${data.ergebnis.vde}`, 20, y); y += 10;
doc.text('Hinweis:', 20, y); y += 6;
const hinweisLines = doc.splitTextToSize(data.ergebnis.hinweis, 170);
doc.text(hinweisLines, 20, y);
doc.setFontSize(8);
doc.setTextColor(150);
doc.text('Elektroplanung - Selektivitätsprüfung - Alle Angaben ohne Gewähr', 105, 290, { align: 'center' });
doc.save(`Selektivitaet_${data.vorWert}A-${data.nachWert}A_${datum.replace(/\./g, '-')}.pdf`);
}
// Initial
document.addEventListener('DOMContentLoaded', function() {
selUpdateVorWerte();
selUpdateNachWerte();
});
</script>
<?php
print '</div>';
llxFooter();
$db->close();