Energiemanager optimiert, Easee-Ladestation eingefügt.
This commit is contained in:
+102
-44
@@ -1,67 +1,125 @@
|
||||
# Manager_1
|
||||
Beschreibung des Moduls.
|
||||
# Belevo EMS Manager
|
||||
|
||||
### Inhaltsverzeichnis
|
||||
Dieses Modul ist das Herzstück des Belevo Energiemanagement-Systems. Es steuert in festgelegten Intervallen die Leistungsverteilung auf Ihre Verbraucher-Instanzen, trifft den Solarlade- vs. Peak-Shaving-Entscheid und verteilt entsprechend die Leistungen an die Verbraucher.
|
||||
|
||||
1. [Funktionsumfang](#1-funktionsumfang)
|
||||
2. [Voraussetzungen](#2-voraussetzungen)
|
||||
3. [Software-Installation](#3-software-installation)
|
||||
4. [Einrichten der Instanzen in IP-Symcon](#4-einrichten-der-instanzen-in-ip-symcon)
|
||||
5. [Statusvariablen und Profile](#5-statusvariablen-und-profile)
|
||||
6. [WebFront](#6-webfront)
|
||||
7. [PHP-Befehlsreferenz](#7-php-befehlsreferenz)
|
||||
---
|
||||
|
||||
### 1. Funktionsumfang
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
*
|
||||
1. [Funktionsumfang](#1-funktionsumfang)
|
||||
2. [Voraussetzungen](#2-voraussetzungen)
|
||||
3. [Installation](#3-installation)
|
||||
4. [Instanz anlegen & Konfiguration](#4-instanz-anlegen--konfiguration)
|
||||
5. [Statusvariablen & Profile](#5-statusvariablen--profile)
|
||||
6. [WebFront / Bedienung](#6-webfront--bedienung)
|
||||
7. [Mapping auf Code-Komponenten](#7-mapping-auf-code-komponenten)
|
||||
8. [Zukünftige Erweiterungen](#8-zukünftige-erweiterungen)
|
||||
|
||||
### 2. Voraussetzungen
|
||||
---
|
||||
|
||||
- IP-Symcon ab Version 7.1
|
||||
## 1. Funktionsumfang
|
||||
|
||||
### 3. Software-Installation
|
||||
- **Zyklische Steuerung**
|
||||
In konfigurierbaren Intervallen (`Interval`) wird die Methode `DistributeEnergy()` ausgelöst.
|
||||
- **Mode-Entscheid**
|
||||
Basierend auf der aktuellen Netz-Sollleistung (`Sollleistung_Max`) und der PV-Überschuss-Grenze (`Ueberschussleistung`) wählt der Manager automatisch zwischen
|
||||
- **Solarlade-Mode** (`Is_Peak_Shaving = false`)
|
||||
- **Peak-Shaving-Mode** (`Is_Peak_Shaving = true`)
|
||||
- **Leistungskonten**
|
||||
Jeder Verbraucher meldet über seine Instanzvariablen (`Power`, `Bezogene_Energie`, `PowerSteps`, `PV_Prio` / `Sperre_Prio`) seinen Bedarf bzw. Reduktions- oder Einspeise-Potential.
|
||||
- **Priorisierung & Fairness**
|
||||
1. Sortierung der Verbraucher nach Priorität (`PV_Prio` im Solarmode, `Sperre_Prio` im Shaving-Mode)
|
||||
2. Bei Gleichpriorität abwechselnde Zuteilung nach bisher bezogener Energie (`Bezogene_Energie`)
|
||||
- **Differenz-Verteilung**
|
||||
Die verbleibende Soll–Ist-Differenz D wird in Stufen (je Verbraucher aus `PowerSteps`) abgearbeitet, bis D ≃ 0.
|
||||
- **Externe Kommunikation**
|
||||
Über die Properties `DatenHoch` und `DatenZuruck` (Variable-IDs) können mehrere Manager zu einem Übergeordneten Hauptmanager zusammengefasst werden (V-ZEV, LEG).
|
||||
|
||||
* Über den Module Store das 'Manager_1'-Modul installieren.
|
||||
* Alternativ über das Module Control folgende URL hinzufügen
|
||||
---
|
||||
|
||||
### 4. Einrichten der Instanzen in IP-Symcon
|
||||
## 2. Voraussetzungen
|
||||
|
||||
Unter 'Instanz hinzufügen' kann das 'Manager_1'-Modul mithilfe des Schnellfilters gefunden werden.
|
||||
- Weitere Informationen zum Hinzufügen von Instanzen in der [Dokumentation der Instanzen](https://www.symcon.de/service/dokumentation/konzepte/instanzen/#Instanz_hinzufügen)
|
||||
- IP-Symcon **≥ 8.0**
|
||||
- Modul-URL:
|
||||
https://git.belevo.ch/dh/Symcon_Belevo_Energiemanagement_testing.git
|
||||
|
||||
__Konfigurationsseite__:
|
||||
yaml
|
||||
Kopieren
|
||||
Bearbeiten
|
||||
- Einmalige manuelle Anmeldung aller Verbraucher in `Verbraucher_Liste`
|
||||
|
||||
Name | Beschreibung
|
||||
-------- | ------------------
|
||||
|
|
||||
|
|
||||
---
|
||||
|
||||
### 5. Statusvariablen und Profile
|
||||
## 3. Installation
|
||||
|
||||
Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen.
|
||||
1. In IP-Symcon **Module Control** öffnen
|
||||
2. **Hinzufügen → Git-Repository**
|
||||
3. URL eingeben (oben) und **Installieren**
|
||||
4. IP-Symcon neu starten
|
||||
|
||||
#### Statusvariablen
|
||||
---
|
||||
|
||||
Name | Typ | Beschreibung
|
||||
------ | ------- | ------------
|
||||
| |
|
||||
| |
|
||||
## 4. Instanz anlegen & Konfiguration
|
||||
|
||||
#### Profile
|
||||
### 4.1 Instanz anlegen
|
||||
|
||||
Name | Typ
|
||||
------ | -------
|
||||
|
|
||||
|
|
||||
- Rechtsklick **Instanzen** → **Instanz hinzufügen**
|
||||
- Filter: **Belevo**
|
||||
- Auswahl: **Manager**
|
||||
|
||||
### 6. WebFront
|
||||
### 4.2 Properties
|
||||
|
||||
Die Funktionalität, die das Modul im WebFront bietet.
|
||||
| Name | Typ | Beschreibung |
|
||||
|--------------------------|-----------------|----------------------------------------------------------------------------|
|
||||
| **Peakleistung** | NumberSpinner | Sollwert-Vorgabe für Peak-Shaving (Watt) |
|
||||
| **Ueberschussleistung** | NumberSpinner | Sollwert-Vorgabe für Solarladen (Watt) |
|
||||
| **Netzbezug** | SelectVariable | Variable mit dem aktuellen Netz-Ist-Wert (Watt) |
|
||||
| **HauptmanagerAktiv** | CheckBox | Schaltet die Ünergeordnete Manager-Logik global ein/aus |
|
||||
| **ManagerID** | NumberSpinner | Eindeutige ID für externe Manager‐Kommunikation |
|
||||
| **DatenHoch** | SelectVariable | Variable, in die Manager-Statistiken oder Statusdaten geschrieben werden |
|
||||
| **DatenZuruck** | SelectVariable | Variable, aus der Verbraucherdaten importiert werden |
|
||||
| **Interval** | NumberSpinner | Intervall für Neuberechnung der Werte (Sekunden) |
|
||||
| **Verbraucher_Liste** | List | Auswahl aller Verbraucher-Instanzen, die gesteuert werden sollen |
|
||||
|
||||
### 7. PHP-Befehlsreferenz
|
||||
---
|
||||
|
||||
`boolean GEF_BeispielFunktion(integer $InstanzID);`
|
||||
Erklärung der Funktion.
|
||||
## 5. Statusvariablen & Profile
|
||||
|
||||
Beispiel:
|
||||
`GEF_BeispielFunktion(12345);`
|
||||
| Ident | Typ | Profil | Beschreibung |
|
||||
|-------------------------|------------|----------------|-------------------------------------------------------------------|
|
||||
| **Is_Peak_Shaving** | Boolean | — | Modusanzeige (false = Solarladen, true = Peak-Shaving) |
|
||||
| **LetzteBerechnung** | DateTime | — | Zeitpunkt der letzten Zyklus-Ausführung |
|
||||
| **Aktuelle_Differenz** | Float | ~Watt~~W~ | Zuletzt berechnete Soll–Ist-Differenz |
|
||||
|
||||
---
|
||||
|
||||
## 6. WebFront / Bedienung
|
||||
|
||||
Im WebFront können Sie
|
||||
- den **aktuellen Modus** (`Is_Peak_Shaving`) beobachten
|
||||
|
||||
---
|
||||
|
||||
## 7. Mapping auf Code-Komponenten
|
||||
|
||||
| Komponente | Modul-Datei | Funktion |
|
||||
|---------------------------|-----------------------------|------------------------------------------------------------|
|
||||
| **Timer-Registrierung** | `Manager/module.php` | `ApplyChanges()` → `SetTimerInterval('Interval', …)` |
|
||||
| **Zyklischer Aufruf** | `Manager/module.php` | `ManageTimer()` ruft `DistributeEnergy()` auf |
|
||||
| **Mode-Entscheidlogik** | `Manager/module.php` | Berechnung:
|
||||
```php
|
||||
$isPeak = $ist > (($peak + $solar) / 2);
|
||||
$this->SetValue('Is_Peak_Shaving', $isPeak);
|
||||
``` |
|
||||
| **Datenzugriff** | `Manager/module.php` | `$this->ReadPropertyInteger('Peakleistung')` usw. |
|
||||
| **Verbraucher-Schleife** | `Manager/module.php` | `$this->ReadPropertyArray('Verbraucher_Liste')` |
|
||||
| **Leistungszuteilung** | `Manager/module.php` | `DistributeEnergy()` → Round-Robin über `PowerSteps` |
|
||||
| **Externe Schnittstelle** | `Manager/module.php` | Verwendung von `DatenHoch` / `DatenZuruck` Variablen-IDs |
|
||||
|
||||
---
|
||||
|
||||
## 8. Zukünftige Erweiterungen
|
||||
|
||||
- **Automatische Registrierung** neuer Verbraucher (ohne manuelles Eintragen)
|
||||
|
||||
---
|
||||
+126
-42
@@ -169,12 +169,12 @@ class Manager extends IPSModule
|
||||
IPS_LogMessage("Manager", "nciht idle");
|
||||
|
||||
}
|
||||
if(in_array(0, $powerSteps, true)){
|
||||
//if(in_array(0, $powerSteps, true)){
|
||||
|
||||
// Addiere die aktuell bereits verwendete Leistung auf, um sie bei der verteilung zu berücksichtigen
|
||||
$totalAktuelle_Leistung += ($Aktuelle_Leistung-$delta);
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
}
|
||||
// Berücksichtigung der bereits verteilten Leistungen (nachher kann dafür wieder bei 0 begonnen werden zu verteilen)
|
||||
@@ -238,8 +238,15 @@ class Manager extends IPSModule
|
||||
continue;
|
||||
}
|
||||
$withZero = [];
|
||||
$withoutZero = [];
|
||||
$withoutZeroHigh = [];
|
||||
$withoutZeroLow = [];
|
||||
|
||||
// Verbraucher die nicht 0 Annhemen können, bekommen einfach den tiefsten wert
|
||||
|
||||
|
||||
|
||||
|
||||
/* Alter Verteilalgor. zu testzwecken auskommentiert, wird dann gelöscht wenns funktioniert.
|
||||
foreach ($samePriorityUsers as $entry) {
|
||||
if (min($entry["PowerSteps"]) <= 0) {
|
||||
$withZero[] = $entry;
|
||||
@@ -247,6 +254,7 @@ class Manager extends IPSModule
|
||||
$withoutZero[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
// Verbraucher die nicht 0 annhemen können erhalten nun den minimalwert
|
||||
if (!empty($withoutZero)) {
|
||||
foreach ($withoutZero as $entry) {
|
||||
@@ -257,6 +265,45 @@ class Manager extends IPSModule
|
||||
//$remainingPower -= $entry["Aktuelle_Leistung"];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/* Neuer Block */
|
||||
foreach ($samePriorityUsers as $entry) {
|
||||
$withZero[] = $entry;
|
||||
|
||||
if (min($entry["PowerSteps"]) > 0) {
|
||||
|
||||
$withoutZeroHigh[] = $entry;
|
||||
}
|
||||
if (max($entry["PowerSteps"]) < 0) {
|
||||
|
||||
$withoutZeroLow[] = $entry;
|
||||
}
|
||||
}
|
||||
|
||||
// Verbraucher die nicht 0 annhemen können erhalten nun den minimalwert
|
||||
if (!empty($withoutZeroHigh)) {
|
||||
foreach ($withoutZeroHigh as $entry) {
|
||||
$instanceID = $entry["InstanceID"];
|
||||
$minPowerStep = min($entry["PowerSteps"]);
|
||||
|
||||
$remainingPower -= $minPowerStep;
|
||||
}
|
||||
}
|
||||
// Verbraucher die nicht 0 annhemen können erhalten nun den minimalwert
|
||||
if (!empty($withoutZeroLow)) {
|
||||
foreach ($withoutZeroLow as $entry) {
|
||||
$instanceID = $entry["InstanceID"];
|
||||
$minPowerStep = max($entry["PowerSteps"]);
|
||||
|
||||
$remainingPower += $minPowerStep;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Neuer Block Ende */
|
||||
|
||||
|
||||
|
||||
|
||||
// Nun die verteilen, die 0 erhalten können.
|
||||
@@ -301,35 +348,51 @@ class Manager extends IPSModule
|
||||
|
||||
}
|
||||
|
||||
//else
|
||||
|
||||
|
||||
// mache invertierte verteilung
|
||||
|
||||
|
||||
// Prüfen, dass jeder User mindestens seinen minimalwert an Leistung bekommt
|
||||
foreach ($userEnergyProv as $userInstanceID => $leistung) {
|
||||
$minimalleitsung = min(
|
||||
// 1. Innerhalb der Schleife: alle nicht-negativen Leistungen sammeln
|
||||
$positiveValues = array_filter(
|
||||
array_column(
|
||||
array_filter($allSteps, function ($entry) use (
|
||||
$userInstanceID
|
||||
) {
|
||||
return $entry["user"] == $userInstanceID;
|
||||
}),
|
||||
"step"
|
||||
)
|
||||
$samePriorityUsers,
|
||||
'PowerSteps',
|
||||
'InstanceID'
|
||||
)[$userInstanceID],
|
||||
function ($l) {
|
||||
return $l >= 0;
|
||||
}
|
||||
);
|
||||
// 2. Falls keine Werte ≥ 0 vorhanden sind, auf 0 zurückfallen
|
||||
$fallbackMinimum = empty($positiveValues)
|
||||
? max( array_column(
|
||||
$samePriorityUsers,
|
||||
'PowerSteps',
|
||||
'InstanceID'
|
||||
)[$userInstanceID])
|
||||
: min($positiveValues);
|
||||
|
||||
// Jedem user den höheren der beiden werte aus minimalwert oder vergebenem zuteilen
|
||||
$leistung = max($leistung, $minimalleitsung);
|
||||
// 3. minimalleistung = dieser Fallback
|
||||
$minimalleistung = $fallbackMinimum;
|
||||
|
||||
// 4. den höheren Wert wählen und für IPS negativieren
|
||||
//$schreibleistung = max($leistung, $minimalleistung);
|
||||
|
||||
|
||||
// Methode SetAktuelle_Leistung für jeden Verbraucher mit der entsprechenden Energie aufrufen
|
||||
if (abs($leistung) > abs($minimalleistung)) {
|
||||
$schreibleistung = $leistung;
|
||||
} else {
|
||||
$schreibleistung = $minimalleistung;
|
||||
}
|
||||
|
||||
// 5. Aktion ausführen
|
||||
if (IPS_InstanceExists($userInstanceID)) {
|
||||
IPS_RequestAction($userInstanceID,"SetAktuelle_Leistung",$leistung);
|
||||
IPS_LogMessage("Manager", "aufgerufen setleistung if". $leistung);
|
||||
|
||||
IPS_RequestAction(
|
||||
$userInstanceID,
|
||||
"SetAktuelle_Leistung",
|
||||
$schreibleistung
|
||||
);
|
||||
IPS_LogMessage(
|
||||
"Manager",
|
||||
"aufgerufen setleistung (Berechnung in foreach): " . $schreibleistung
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -341,7 +404,7 @@ class Manager extends IPSModule
|
||||
if($step<=0){
|
||||
$allSteps[] = [
|
||||
"user" => $user["InstanceID"],
|
||||
"Leistung_Delta" => $user["Leistung_Delta"],
|
||||
//"Leistung_Delta" => $user["Leistung_Delta"],
|
||||
"step" => -1*$step,
|
||||
];}
|
||||
}
|
||||
@@ -352,7 +415,6 @@ class Manager extends IPSModule
|
||||
return $a["step"] <=> $b["step"];
|
||||
});
|
||||
|
||||
|
||||
$remainingPower = $remainingPower *-1;
|
||||
// Iteriere durch alle Schritte
|
||||
foreach ($allSteps as $entry) {
|
||||
@@ -371,28 +433,50 @@ class Manager extends IPSModule
|
||||
|
||||
|
||||
// Prüfen, dass jeder User mindestens seinen minimalwert an Leistung bekommt
|
||||
foreach ($userEnergyProv as $userInstanceID => $leistung) {
|
||||
$minimalleitsung = min(
|
||||
foreach ($userEnergyProv as $userInstanceID => $leistung) {
|
||||
// 1. Innerhalb der Schleife: alle nicht-negativen Leistungen sammeln
|
||||
$positiveValues = array_filter(
|
||||
array_column(
|
||||
array_filter($allSteps, function ($entry) use (
|
||||
$userInstanceID
|
||||
) {
|
||||
return $entry["user"] == $userInstanceID;
|
||||
}),
|
||||
"step"
|
||||
)
|
||||
$samePriorityUsers,
|
||||
'PowerSteps',
|
||||
'InstanceID'
|
||||
)[$userInstanceID],
|
||||
function ($l) {
|
||||
return $l <= 0;
|
||||
}
|
||||
);
|
||||
// 2. Falls keine Werte ≥ 0 vorhanden sind, auf 0 zurückfallen
|
||||
$fallbackMinimum = empty($positiveValues)
|
||||
? min( array_column(
|
||||
$samePriorityUsers,
|
||||
'PowerSteps',
|
||||
'InstanceID'
|
||||
)[$userInstanceID])
|
||||
: max($positiveValues);
|
||||
|
||||
// Jedem user den höheren der beiden werte aus minimalwert oder vergebenem zuteilen
|
||||
$schreibleistung = max($leistung, $minimalleitsung)*-1;
|
||||
// 3. minimalleistung = dieser Fallback
|
||||
$minimalleistung = $fallbackMinimum;
|
||||
|
||||
// 4. den höheren Wert wählen und für IPS negativieren
|
||||
//$schreibleistung = max($leistung, $minimalleistung);
|
||||
|
||||
|
||||
// Methode SetAktuelle_Leistung für jeden Verbraucher mit der entsprechenden Energie aufrufen
|
||||
if (abs($leistung) > abs($minimalleistung)) {
|
||||
$schreibleistung = $leistung*-1;
|
||||
} else {
|
||||
$schreibleistung = $minimalleistung;
|
||||
}
|
||||
|
||||
// 5. Aktion ausführen
|
||||
if (IPS_InstanceExists($userInstanceID)) {
|
||||
IPS_RequestAction($userInstanceID,"SetAktuelle_Leistung",$schreibleistung);
|
||||
IPS_LogMessage("Manager", "aufgerufen setleistung else ".$schreibleistung);
|
||||
|
||||
IPS_RequestAction(
|
||||
$userInstanceID,
|
||||
"SetAktuelle_Leistung",
|
||||
$schreibleistung
|
||||
);
|
||||
IPS_LogMessage(
|
||||
"Manager",
|
||||
"aufgerufen setleistung (Berechnung in foreach): " . $schreibleistung
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user