Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d804ba4bc1 | ||
|
|
e7c546ff2d |
@@ -62,7 +62,7 @@ der Uebernahme in einen Freigabebranch erfolgreich sein.
|
||||
|
||||
- [Zentrale Liste offener Teamentscheidungen](docs/Offene-Punkte.md)
|
||||
- [Manager-Verbraucher-Schnittstelle](docs/Schnittstelle.md)
|
||||
- [Manager-Modul](docs/module/Manager/README.md)
|
||||
- [Manager-Modul inklusive Lizenzierung](docs/module/Manager/README.md)
|
||||
- [Warmwassererwaermer-Modul](docs/module/Wassererwaermer/README.md)
|
||||
- [Verbraucher-1-Stufig-Modul](docs/module/Verbraucher-1-Stufig/README.md)
|
||||
- [Ladestation-Stand-Alone-Modul](docs/module/Ladestation-Stand-Alone/README.md)
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
# Verbraucher 1-Stufig
|
||||
|
||||
IP-Symcon-Modul fuer einen elektrischen Verbraucher, der genau zwei
|
||||
Leistungszustaende kennt: aus (`0 W`) und ein (`Nennleistung`).
|
||||
|
||||
Das Modul ist fuer IP-Symcon ab Version 8.0 und den Enelix-Nachrichtenvertrag
|
||||
`4.0` ausgelegt. Es arbeitet ereignisbasiert und besitzt weder einen
|
||||
Regelzyklus noch eine konfigurierbare Zyklusanzahl oder Zykluszeit.
|
||||
|
||||
## Funktionen
|
||||
|
||||
- Schalten eines Boolean-Aktors auf `0 W` oder die konfigurierte Nennleistung
|
||||
- optionale separate Schaltzustands-Rueckmeldung
|
||||
- Mindest-Einschalt- und Mindest-Ausschaltdauer
|
||||
- taegliche Mindestlaufzeit
|
||||
- getrennte Prioritaeten fuer PV- und Peakbetrieb
|
||||
- ereignisbasierte Zustandsmeldung an den Enelix Manager
|
||||
- Diagnosevariablen und optionales Debug-Logging
|
||||
- sichere lokale Deaktivierung ueber die Variable `Aktiv`
|
||||
|
||||
## Installation
|
||||
|
||||
1. Im IP-Symcon Module Control die Bibliothek
|
||||
`https://git.belevo.ch/ENELIX/Enelix-EMS.git` installieren.
|
||||
2. Fuer Entwicklung und Tests den Kanal beziehungsweise Branch `develop`
|
||||
verwenden.
|
||||
3. Unter **Instanz hinzufuegen** nach **Verbraucher 1-Stufig** suchen.
|
||||
4. Eine Instanz anlegen und mindestens Nennleistung und Schaltkontakt
|
||||
konfigurieren.
|
||||
|
||||
## Konfiguration
|
||||
|
||||
| Einstellung | Standard | Beschreibung |
|
||||
| --- | ---: | --- |
|
||||
| `PrioritaetPV` | `0` | Reihenfolge bei der PV-Leistungsverteilung. |
|
||||
| `PrioritaetPeak` | `0` | Reihenfolge bei der Lastspitzenregelung. |
|
||||
| `Meldeintervall` | `10 s` | Periodische Vollmeldung an zugeordnete Manager. |
|
||||
| `VorgabeTimeout` | `120 s` | Gueltigkeitsdauer einer Manager-Vorgabe. |
|
||||
| `Mindesteinschaltdauer` | `5 s` | Mindestdauer eines bestaetigten Ein-Zustands. |
|
||||
| `Mindestausschaltdauer` | `5 s` | Mindestdauer eines bestaetigten Aus-Zustands. |
|
||||
| `Nennleistung` | `0 W` | Leistungsaufnahme im eingeschalteten Zustand. |
|
||||
| `SchaltkontaktVariableID` | `0` | Booleanvariable des zu schaltenden Aktors. |
|
||||
| `SchaltkontaktInvertiert` | `false` | Invertiert die Aktorlogik. |
|
||||
| `RueckmeldungVariableID` | `0` | Optionale Booleanvariable fuer den physischen Zustand. |
|
||||
| `Mindestlaufzeit` | `0 s` | Geforderte Laufzeit pro lokalem Kalendertag. |
|
||||
| `PeakSperreBeiMindestlaufzeitAnbieten` | `true` | Erlaubt im Peakbetrieb eine Sperre trotz faelliger Tagesmindestlaufzeit. |
|
||||
| `DiagnosevariablenAnzeigen` | `false` | Blendet technische Diagnosevariablen ein. |
|
||||
| `LoggingEin` | `false` | Aktiviert zusaetzliche Debug-Ausgaben. |
|
||||
|
||||
`Nennleistung` muss groesser als `0` sein. Der Schaltkontakt muss eine
|
||||
Booleanvariable mit funktionsfaehiger Standard- oder benutzerdefinierter
|
||||
Aktion sein. Beide Mindestzeiten duerfen auf `0` gesetzt werden.
|
||||
|
||||
Der fruehere allgemeine `Umschaltabstand` sowie Properties fuer Zyklusanzahl
|
||||
und Zykluszeit existieren nicht.
|
||||
|
||||
## Verhalten ohne separate Rueckmeldung
|
||||
|
||||
Ist keine `RueckmeldungVariableID` konfiguriert, wird die Aktorvariable als
|
||||
unmittelbare Schaltbestaetigung verwendet.
|
||||
|
||||
Nach einem erfolgreichen Schaltbefehl beginnt ab dem uebernommenen
|
||||
Aktorzustand:
|
||||
|
||||
- beim Einschalten die `Mindesteinschaltdauer`,
|
||||
- beim Ausschalten die `Mindestausschaltdauer`.
|
||||
|
||||
Uebernimmt die Aktorvariable den angeforderten Wert nicht, meldet das Modul
|
||||
einen Schaltfehler und stellt sich dem Manager nicht als schaltbereit dar.
|
||||
|
||||
## Verhalten mit separater Rueckmeldung
|
||||
|
||||
Ist eine `RueckmeldungVariableID` konfiguriert, bestimmt ausschliesslich deren
|
||||
Booleanwert den bestaetigten Schaltzustand. `true` muss dabei physisch
|
||||
eingeschaltet bedeuten.
|
||||
|
||||
Zwischen Aktorbefehl und passender Rueckmeldung meldet das Modul:
|
||||
|
||||
- den bisherigen bestaetigten Schaltzustand und die bisherige Istleistung,
|
||||
- `SchaltbefehlAusstehend=true`,
|
||||
- `Schaltbereit=false`,
|
||||
- `AenderungMoeglich=false`.
|
||||
|
||||
Die jeweilige Mindestzeit beginnt erst, sobald die Rueckmeldung den neuen
|
||||
Zustand bestaetigt. Bleibt die Rueckmeldung aus, bleibt der Schaltbefehl
|
||||
sichtbar ausstehend. Eine abweichende Rueckmeldung ohne laufenden
|
||||
Schaltvorgang wird als Rueckmeldefehler gemeldet.
|
||||
|
||||
## Mindestzeiten und Leistungsangebot
|
||||
|
||||
Waerend einer Mindest-Ein- oder Mindest-Aus-Zeit bietet das Modul nur die
|
||||
bestaetigte aktuelle Leistung an. Ein regulaerer Lastwechsel ist erst nach
|
||||
Ablauf der Mindestzeit wieder moeglich.
|
||||
|
||||
Der Manager erhaelt dazu unter anderem:
|
||||
|
||||
| Zustand | Bedeutung |
|
||||
| --- | --- |
|
||||
| `Schaltzustand` | Bestaetigter Ein-/Aus-Zustand. |
|
||||
| `SchaltbefehlAusstehend` | Aktorbefehl wartet auf physische Bestaetigung. |
|
||||
| `Schaltbereit` | Ein weiterer regulaerer Lastwechsel ist moeglich. |
|
||||
| `RestMindestzeit_s` | Verbleibende Mindestzeit in Sekunden. |
|
||||
| `Tageslaufzeit_s` | Bestaetigte Laufzeit des aktuellen Tages. |
|
||||
| `Rueckmeldefehler` | Aktor und Rueckmeldung widersprechen sich unerwartet. |
|
||||
|
||||
Die lokale Aktion `Aktiv=false` ist ein bewusster Sicherheits-Override. Sie
|
||||
schaltet den Verbraucher auch waehrend einer laufenden
|
||||
Mindesteinschaltdauer aus.
|
||||
|
||||
## Sichtbare Variablen
|
||||
|
||||
Immer vorhanden sind:
|
||||
|
||||
- `Aktiv`: lokale Freigabe fuer das Energiemanagement
|
||||
- `Schaltzustand`: bestaetigter oder aus dem Aktor abgeleiteter Zustand
|
||||
- `Tageslaufzeit`: bestaetigte Laufzeit des aktuellen Tages in Sekunden
|
||||
|
||||
Bei aktivierter Diagnose werden zusaetzlich Soll- und Istleistung,
|
||||
Verfuegbarkeit, Schaltbereitschaft, Stoerung, Rueckmeldefehler,
|
||||
ausstehender Schaltbefehl und verbleibende Mindestzeit angezeigt.
|
||||
|
||||
## Inbetriebnahme
|
||||
|
||||
1. Nennleistung und Schaltkontakt konfigurieren.
|
||||
2. Falls vorhanden, die separate Rueckmeldung auswaehlen und ihre
|
||||
`true`-Semantik pruefen.
|
||||
3. Mindest-Ein- und Mindest-Ausschaltdauer passend zum angeschlossenen
|
||||
Geraet festlegen.
|
||||
4. Den Verbraucher im Enelix Manager manuell oder automatisch aktiv
|
||||
zuordnen.
|
||||
5. Fuer die Erstpruefung Diagnosevariablen und bei Bedarf Logging aktivieren.
|
||||
6. Die Variable `Aktiv` einschalten.
|
||||
7. Unter Aufsicht je eine Ein- und Aus-Vorgabe durch den Manager ausfuehren.
|
||||
8. Kontrollieren, dass Rueckmeldung, Mindestzeiten und `Schaltbereit`
|
||||
erwartungsgemaess wechseln.
|
||||
|
||||
## Fehlersuche
|
||||
|
||||
- **Konfiguration ungueltig:** Nennleistung, Variablentyp und Aktoraktion
|
||||
pruefen.
|
||||
- **Schaltbefehl bleibt ausstehend:** Separate Rueckmeldung und deren
|
||||
`true`-Semantik pruefen.
|
||||
- **Rueckmeldefehler:** Aktor- und Rueckmeldewert stimmen ausserhalb eines
|
||||
laufenden Schaltvorgangs nicht ueberein.
|
||||
- **Kein Lastwechsel moeglich:** `RestMindestzeit`, `Aktiv`,
|
||||
`SollwertGueltig` und die Managerzuordnung kontrollieren.
|
||||
- **Keine Manager-Vorgabe akzeptiert:** Der Verbraucher muss beim sendenden
|
||||
Manager aktiv zugeordnet sein.
|
||||
|
||||
## Tests
|
||||
|
||||
Nur dieses Modul:
|
||||
|
||||
~~~bash
|
||||
composer check:verbraucher-einstufig
|
||||
~~~
|
||||
|
||||
Gesamtes Repository inklusive dieser Testsuite:
|
||||
|
||||
~~~bash
|
||||
composer check
|
||||
~~~
|
||||
|
||||
Die Modulsuite kann damit unabhaengig weiterentwickelt werden und bleibt
|
||||
gleichzeitig Bestandteil des allgemeinen Tests.
|
||||
|
||||
## Weiterfuehrende Dokumentation
|
||||
|
||||
- [Ausfuehrliche Modulbeschreibung](../docs/module/Verbraucher-1-Stufig/README.md)
|
||||
- [Manager-Verbraucher-Schnittstelle](../docs/Schnittstelle.md)
|
||||
- [Migration von Enelix 1](../docs/migration/Verbraucher-1-Stufig.md)
|
||||
- [Aufbau der separaten Testsuite](../tests/VerbraucherEinStufig/README.md)
|
||||
@@ -59,12 +59,90 @@ Manager. Im Modus `Aus` bleibt Solarladen aktiv, nur die Peak-Begrenzung entfäl
|
||||
Die Monatsgrenzen werden in den Grundeinstellungen über eine Schaltfläche
|
||||
ein- und ausgeblendet. Die automatische Verbrauchersuche kann dort erneut
|
||||
ausgeführt werden, ohne andere ungespeicherte Formulareingaben zu verlieren.
|
||||
Die Lizenzierung steht an erster Stelle des Formulars. Der Manager erzeugt dabei
|
||||
einmalig eine UUIDv4 als stabile Installations-ID. Mit "Lizenz pruefen und binden"
|
||||
wird der eingegebene Code ueber
|
||||
`POST https://license.enelix.ch/api/v1/licenses/activate` an diese Installation
|
||||
gebunden. Es werden weder Portal-Cookies noch ein CSRF-Token oder ein noch nicht
|
||||
implementierter Lizenzendpunkt verwendet.
|
||||
|
||||
## Lizenzierung
|
||||
|
||||
Der Manager arbeitet nur mit einer gueltigen Manager-Lizenz. Das Lizenzfeld steht
|
||||
zuoberst im Konfigurationsformular. Ohne Freigabe bleibt die Instanz mit Status
|
||||
`203` inaktiv und sendet keine Leistungsvorgaben.
|
||||
|
||||
### Voraussetzungen
|
||||
|
||||
- Der Auftrag im Enelix-Lizenzportal ist bezahlt und enthaelt eine aktive
|
||||
Manager-Berechtigung.
|
||||
- IP-Symcon erreicht `https://license.enelix.ch` ueber HTTPS (Port 443).
|
||||
- Der Lizenzcode liegt im Format `ENX-XXXX-XXXX-XXXX-XXXX` vor.
|
||||
|
||||
### Lizenz aktivieren
|
||||
|
||||
1. Manager-Konfiguration in IP-Symcon oeffnen.
|
||||
2. Lizenzcode im Bereich `Lizenzierung` eintragen.
|
||||
3. `Lizenz pruefen und binden` ausloesen.
|
||||
4. Die erfolgreiche Freigabe am angezeigten Lizenzstatus kontrollieren.
|
||||
5. Die Manager-Konfiguration mit `Uebernehmen` beziehungsweise `OK` speichern,
|
||||
damit der eingegebene Lizenzcode als Property erhalten bleibt.
|
||||
|
||||
Beim ersten Anlegen erzeugt die Manager-Instanz eine UUIDv4 als stabile
|
||||
Installations-ID. Die Aktivierung sendet ausschliesslich `code` und
|
||||
`installationId` per
|
||||
`POST https://license.enelix.ch/api/v1/licenses/activate`. Sie benoetigt weder
|
||||
Portal-Cookies noch einen CSRF-Token. Derselbe Code kann von derselben
|
||||
Installation erneut abgerufen werden; die Bindung an eine andere Installation
|
||||
wird vom Lizenzserver abgelehnt.
|
||||
|
||||
### Berechtigungen
|
||||
|
||||
| Berechtigung | Freigegebene Funktion |
|
||||
| --- | --- |
|
||||
| `manager_standard` | Manager-Grundregelung ohne Lastspitzenmodus. |
|
||||
| `manager_peak` | Manager-Grundregelung einschliesslich konstantem oder monatlichem Lastspitzenmodus. |
|
||||
|
||||
Wird mit `manager_standard` ein Lastspitzenmodus aktiviert, bleibt der Manager
|
||||
mit dem Hinweis `Peak Shaving ist nicht lizenziert` gesperrt. `manager_peak`
|
||||
gilt zugleich als Berechtigung fuer die Grundregelung.
|
||||
|
||||
### Erneuerung und Offline-Betrieb
|
||||
|
||||
Die erfolgreiche Serverantwort wird als Lease in der Manager-Instanz gespeichert.
|
||||
Der Manager erneuert sie ab `refreshAfter` automatisch ueber denselben
|
||||
Aktivierungsendpunkt. Schlaegt eine Erneuerung fehl, wird fruehestens nach einer
|
||||
Stunde erneut angefragt. Eine bereits bestaetigte Entwicklungsfreigabe bleibt
|
||||
bis `offlineUntil` verwendbar. Der aktuelle Entwicklungsvertrag setzt diesen
|
||||
Zeitpunkt ungefaehr 14 Tage nach Ausstellung. Danach sperrt der Manager die
|
||||
Regelung, bis der Lizenzserver wieder eine gueltige Antwort liefert.
|
||||
|
||||
Die Installations-ID und die Lease liegen in internen Instanzattributen. Bei
|
||||
einer Migration muss deshalb die vollstaendige Manager-Instanz mitsamt ihren
|
||||
Attributen uebernommen werden. Eine neu erzeugte Instanz erhaelt eine andere
|
||||
Installations-ID und kann einen bereits gebundenen Code nicht selbststaendig
|
||||
uebertragen.
|
||||
|
||||
### Status und Fehlerbehebung
|
||||
|
||||
| Anzeige / Serverstatus | Bedeutung und Massnahme |
|
||||
| --- | --- |
|
||||
| `Lizenzcode fehlt.` | Code eintragen, pruefen und die Konfiguration speichern. |
|
||||
| `Lizenzcode ist ungueltig.` | Format und Zeichen des Codes kontrollieren. |
|
||||
| HTTP `404` | Code unbekannt oder zugehoeriger Auftrag noch nicht bezahlt. |
|
||||
| HTTP `409` | Code ist bereits an eine andere Installation gebunden. |
|
||||
| HTTP `429` | Zu viele Aktivierungsversuche; vor dem naechsten Versuch warten. |
|
||||
| `Lizenzserver nicht erreichbar` | DNS, Internetzugang, HTTPS und Systemzeit des Symcon-Systems pruefen. Eine bestehende Lease gilt nur bis `offlineUntil`. |
|
||||
| `Offline-Freigabe ist abgelaufen.` | Verbindung zum Lizenzserver wiederherstellen und Lizenz erneut pruefen. |
|
||||
|
||||
Fuer eine genauere Diagnose koennen die Diagnosevariablen eingeblendet werden.
|
||||
`Lizenzstatus` zeigt dann den aktuellen Zustand. Mit aktiviertem Debug-Logging
|
||||
werden Fehlermeldungen der Lizenzpruefung ausgegeben, niemals jedoch der
|
||||
Lizenzcode selbst.
|
||||
|
||||
### Datenschutz und Entwicklungsstand
|
||||
|
||||
Der Lizenzcode wird als Manager-Property in der IP-Symcon-Konfiguration
|
||||
gespeichert. Fuer den internen Abgleich mit der Lease verwendet der Manager
|
||||
zusaetzlich nur einen SHA-256-Hash und schreibt den Code nicht ins Debug-Log.
|
||||
Die aktuelle Serverantwort ist ein Entwicklungsvertrag mit
|
||||
`development: true` und noch nicht kryptografisch signiert. Ein optionaler
|
||||
Geraete-Public-Key sowie Challenge-, Heartbeat- oder separate
|
||||
Entitlement-Endpunkte werden vom Manager derzeit bewusst nicht verwendet.
|
||||
|
||||
## Verteilalgorithmus
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ final class DokumentationsstrukturTest extends TestCase
|
||||
{
|
||||
$inhalt = file_get_contents(__DIR__ . '/../docs/module/Ladestation-Stand-Alone/README.md');
|
||||
self::assertNotFalse($inhalt);
|
||||
self::assertStringContainsString('Status: Implementiert', $inhalt);
|
||||
self::assertStringContainsStringIgnoringCase('Status: implementiert', $inhalt);
|
||||
self::assertStringContainsString('Properties', $inhalt);
|
||||
self::assertStringContainsString('Fake-HTTP-Transport', $inhalt);
|
||||
}
|
||||
@@ -65,11 +65,22 @@ final class DokumentationsstrukturTest extends TestCase
|
||||
|
||||
public function testVerbraucherEinStufigDokumentiertDenImplementiertenStand(): void
|
||||
{
|
||||
$inhalt = file_get_contents(__DIR__ . '/../docs/module/Verbraucher-1-Stufig/README.md');
|
||||
self::assertNotFalse($inhalt);
|
||||
self::assertStringContainsString('Status: implementiert', $inhalt);
|
||||
self::assertStringContainsString('Umschaltabstand', $inhalt);
|
||||
self::assertStringContainsString('Installation und Inbetriebnahme', $inhalt);
|
||||
$detailInhalt = file_get_contents(
|
||||
__DIR__ . '/../docs/module/Verbraucher-1-Stufig/README.md'
|
||||
);
|
||||
self::assertNotFalse($detailInhalt);
|
||||
self::assertStringContainsString('Status: implementiert', $detailInhalt);
|
||||
self::assertStringContainsString('Umschaltabstand', $detailInhalt);
|
||||
self::assertStringContainsString('Installation und Inbetriebnahme', $detailInhalt);
|
||||
|
||||
$modulInhalt = file_get_contents(__DIR__ . '/../VerbraucherEinStufig/README.md');
|
||||
self::assertNotFalse($modulInhalt);
|
||||
self::assertStringContainsString('Verhalten ohne separate Rueckmeldung', $modulInhalt);
|
||||
self::assertStringContainsString('Mindesteinschaltdauer', $modulInhalt);
|
||||
self::assertStringContainsString(
|
||||
'composer check:verbraucher-einstufig',
|
||||
$modulInhalt
|
||||
);
|
||||
}
|
||||
|
||||
public function testWarmwassererwaermerDokumentiertDenImplementiertenStand(): void
|
||||
|
||||
Reference in New Issue
Block a user