Energiemanager optimiert, Easee-Ladestation eingefügt.
This commit is contained in:
9
PV_Visu/form.json
Normal file
9
PV_Visu/form.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"elements": [
|
||||
{ "type": "SelectVariable", "name": "VarProduction", "caption": "Produktion (kWh)" },
|
||||
{ "type": "SelectVariable", "name": "VarConsumption", "caption": "Verbrauch (kWh)" },
|
||||
{ "type": "SelectVariable", "name": "VarFeedIn", "caption": "Einspeisung (kWh)" },
|
||||
{ "type": "SelectVariable", "name": "VarGrid", "caption": "Bezug Netz (kWh)" }
|
||||
],
|
||||
"actions": []
|
||||
}
|
||||
78
PV_Visu/module.html
Normal file
78
PV_Visu/module.html
Normal file
@@ -0,0 +1,78 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
html, body { margin: 0; padding: 8px; background: transparent; font-family: sans-serif; color: #ffffff; }
|
||||
.bar-block { margin-bottom: 20px; }
|
||||
.bar-title { font-size: 1.2em; font-weight: bold; margin-bottom: 6px; }
|
||||
.bar-container { width: 100%; background: #ddd; border-radius: 4px; overflow: hidden; height: 24px; position: relative; }
|
||||
.bar { height: 100%; float: left; position: relative; }
|
||||
.bar span { position: absolute; width: 100%; text-align: center; line-height: 24px; font-size: 0.8em; color: #fff; }
|
||||
.bar-cons { background: #4CAF50; }
|
||||
.bar-feed { background: #8BC34A; }
|
||||
.bar-pv { background: #FF9800; }
|
||||
.bar-grid { background: #FF5722; }
|
||||
.value-text { font-size: 0.95em; margin-top: 4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="pv_visu">
|
||||
<div class="bar-block">
|
||||
<div class="bar-title">Produktion (Eigenverbrauch / Einspeisung)</div>
|
||||
<div class="bar-container">
|
||||
<div class="bar bar-cons" id="barCons"><span id="barConsText"></span></div>
|
||||
<div class="bar bar-feed" id="barFeed"><span id="barFeedText"></span></div>
|
||||
</div>
|
||||
<div class="value-text" id="prodValues"></div>
|
||||
</div>
|
||||
<div class="bar-block">
|
||||
<div class="bar-title">Verbrauch (PV / Netz)</div>
|
||||
<div class="bar-container">
|
||||
<div class="bar bar-pv" id="barPV"><span id="barPVText"></span></div>
|
||||
<div class="bar bar-grid" id="barGrid"><span id="barGridText"></span></div>
|
||||
</div>
|
||||
<div class="value-text" id="consValues"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function Apply(data) {
|
||||
document.getElementById('barCons').style.width = data.prodCons + '%';
|
||||
document.getElementById('barFeed').style.width = data.prodFeed + '%';
|
||||
document.getElementById('barPV').style.width = data.consPV + '%';
|
||||
document.getElementById('barGrid').style.width = data.consGrid + '%';
|
||||
|
||||
document.getElementById('barConsText').innerText = data.prodCons + '%';
|
||||
document.getElementById('barFeedText').innerText = data.prodFeed + '%';
|
||||
document.getElementById('barPVText').innerText = data.consPV + '%';
|
||||
document.getElementById('barGridText').innerText = data.consGrid + '%';
|
||||
|
||||
document.getElementById('prodValues').innerText =
|
||||
'Gesamt: ' + data.value.prod + ' kWh, Eigenverbrauch: ' + (data.consPV/100*data.value.cons).toFixed(2) + ' kWh, Einspeisung: ' + data.value.feed + ' kWh';
|
||||
document.getElementById('consValues').innerText =
|
||||
'Gesamt: ' + data.value.cons + ' kWh, PV-Anteil: ' + (data.consPV/100*data.value.cons).toFixed(2) + ' kWh, Netz: ' + data.value.grid + ' kWh';
|
||||
}
|
||||
|
||||
function handleMessage(msg) {
|
||||
try {
|
||||
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
||||
Apply(data);
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Verarbeiten der Daten:', e, msg);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof registerMessageHandler === 'function') {
|
||||
registerMessageHandler(handleMessage);
|
||||
}
|
||||
|
||||
// Live-Aktualisierung alle 30 Sekunden
|
||||
function pollData() {
|
||||
if (typeof IPS !== 'undefined') {
|
||||
IPS.RequestAction('update', '');
|
||||
}
|
||||
}
|
||||
setInterval(pollData, 30000);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
12
PV_Visu/module.json
Normal file
12
PV_Visu/module.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"id": "{DDE89CBE-4411-5FF4-4931-14204E05CAD0}",
|
||||
"name": "PV_Visu",
|
||||
"type": 3,
|
||||
"vendor": "Belevo AG",
|
||||
"aliases": [],
|
||||
"parentRequirements": [],
|
||||
"childRequirements": [],
|
||||
"implemented": [],
|
||||
"prefix": "",
|
||||
"url": ""
|
||||
}
|
||||
99
PV_Visu/module.php
Normal file
99
PV_Visu/module.php
Normal file
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
class PV_Visu extends IPSModule
|
||||
{
|
||||
public function Create()
|
||||
{
|
||||
parent::Create();
|
||||
|
||||
$this->RegisterPropertyInteger('VarProduction', 0);
|
||||
$this->RegisterPropertyInteger('VarConsumption', 0);
|
||||
$this->RegisterPropertyInteger('VarFeedIn', 0);
|
||||
$this->RegisterPropertyInteger('VarGrid', 0);
|
||||
|
||||
$this->RegisterVariableString('JSONData', 'Visualisierungsdaten', '', 0);
|
||||
IPS_SetHidden($this->GetIDForIdent('JSONData'), true);
|
||||
|
||||
$this->SetVisualizationType(1); // HTML SDK Tile
|
||||
}
|
||||
|
||||
public function ApplyChanges()
|
||||
{
|
||||
parent::ApplyChanges();
|
||||
|
||||
foreach (['VarProduction', 'VarConsumption', 'VarFeedIn', 'VarGrid'] as $prop) {
|
||||
$vid = $this->ReadPropertyInteger($prop);
|
||||
if ($vid > 0) {
|
||||
$this->RegisterMessage($vid, VM_UPDATE);
|
||||
}
|
||||
}
|
||||
|
||||
$this->UpdateData(); // Initial
|
||||
}
|
||||
|
||||
public function MessageSink($TimeStamp, $SenderID, $Message, $Data)
|
||||
{
|
||||
if ($Message === VM_UPDATE) {
|
||||
$this->UpdateData();
|
||||
}
|
||||
}
|
||||
|
||||
public function GetVisualizationTile()
|
||||
{
|
||||
$initialData = '<script>handleMessage(' . json_encode($this->UpdateData()) . ');</script>';
|
||||
$html = file_get_contents(__DIR__ . '/module.html');
|
||||
return $html . $initialData;
|
||||
}
|
||||
|
||||
public function RequestAction($Ident, $Value)
|
||||
{
|
||||
if ($Ident === 'update') {
|
||||
return $this->UpdateData(); // Rückgabe für Visualisierung
|
||||
}
|
||||
throw new \Exception("Unknown Ident: $Ident");
|
||||
}
|
||||
|
||||
public function UpdateData()
|
||||
{
|
||||
$start = strtotime('today 00:00');
|
||||
$end = time();
|
||||
|
||||
$prod = $this->GetDailyTotal($this->ReadPropertyInteger('VarProduction'), $start, $end);
|
||||
$cons = $this->GetDailyTotal($this->ReadPropertyInteger('VarConsumption'), $start, $end);
|
||||
$feed = $this->GetDailyTotal($this->ReadPropertyInteger('VarFeedIn'), $start, $end);
|
||||
$grid = $this->GetDailyTotal($this->ReadPropertyInteger('VarGrid'), $start, $end);
|
||||
|
||||
$prodCons = $prod > 0 ? (($cons - $grid) / $prod) * 100 : 0;
|
||||
$prodFeed = $prod > 0 ? 100 - $prodCons : 0;
|
||||
$consPV = $cons > 0 ? min($prod, ($cons - $grid)) / $cons * 100 : 0;
|
||||
$consGrid = $cons > 0 ? 100 - $consPV : 0;
|
||||
|
||||
$data = [
|
||||
'prodCons' => round($prodCons, 1),
|
||||
'prodFeed' => round($prodFeed, 1),
|
||||
'consPV' => round($consPV, 1),
|
||||
'consGrid' => round($consGrid, 1),
|
||||
'value' => [
|
||||
'prod' => round($prod, 2),
|
||||
'cons' => round($cons, 2),
|
||||
'feed' => round($feed, 2),
|
||||
'grid' => round($grid, 2),
|
||||
],
|
||||
];
|
||||
|
||||
$json = json_encode($data);
|
||||
SetValueString($this->GetIDForIdent('JSONData'), $json);
|
||||
return $data;
|
||||
}
|
||||
|
||||
private function GetDailyTotal(int $varID, int $start, int $end)
|
||||
{
|
||||
if ($varID <= 0) return 0.0;
|
||||
|
||||
$archiveID = @IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0];
|
||||
if (!$archiveID) return 0.0;
|
||||
|
||||
$values = @AC_GetAggregatedValues($archiveID, $varID, 1, $start, $end, 1);
|
||||
return isset($values[0]['Avg']) ? (float)$values[0]['Avg'] : 0.0;
|
||||
}
|
||||
}
|
||||
59
PV_Visu/readme.md
Normal file
59
PV_Visu/readme.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# PV_Visu
|
||||
|
||||
Visualisierung des Eigenverbrauchs: Tages-Quoten für PV-Produktion vs. Einspeisung und Verbrauch vs. Netz-Bezug.
|
||||
|
||||
## Inhaltsverzeichnis
|
||||
|
||||
1. [Funktionsumfang](#funktionsumfang)
|
||||
2. [Voraussetzungen](#voraussetzungen)
|
||||
3. [Installation](#installation)
|
||||
4. [Instanz einrichten](#instanz-einrichten)
|
||||
5. [WebFront](#webfront)
|
||||
6. [PHP-Befehlsreferenz](#php-befehlsreferenz)
|
||||
|
||||
## Funktionsumfang
|
||||
|
||||
- Anzeige von Tages-Quoten (%)
|
||||
- Produktion: Eigenverbrauch vs. Einspeisung
|
||||
- Verbrauch: PV-Anteil vs. Netz-Anteil
|
||||
- Zwei Balkendiagramme
|
||||
- Absolute Tages-Summen (kWh)
|
||||
|
||||
## Voraussetzungen
|
||||
|
||||
- IP-Symcon ≥ 7.1
|
||||
- Archiv-Modul aktiviert
|
||||
- Vier kWh-Zähler-Variablen
|
||||
|
||||
## Installation
|
||||
|
||||
1. **Module Store** → Suche nach „PV_Visu“ und installieren
|
||||
2. **Alternativ**: Unter Module → Repositories folgende URL hinzufügen:
|
||||
```
|
||||
https://github.com/DeinRepo/PV_Visu.git
|
||||
```
|
||||
und Modul neu einlesen.
|
||||
|
||||
## Instanz einrichten
|
||||
|
||||
- **Instanz hinzufügen** → Filter: „PV_Visu“
|
||||
- Variablen zuweisen:
|
||||
|
||||
| Property | Beschreibung |
|
||||
| -------------- | -------------------------- |
|
||||
| VarProduction | PV-Produktionszähler (kWh) |
|
||||
| VarConsumption | Gesamtverbrauch (kWh) |
|
||||
| VarFeedIn | Einspeisung (kWh) |
|
||||
| VarGrid | Netz-Bezug (kWh) |
|
||||
|
||||
## WebFront
|
||||
|
||||
- **Tile-Typ:** PV_Visu
|
||||
- Balken 1 (Grün): Produktion
|
||||
- Balken 2 (Orange/Rot): Verbrauch
|
||||
|
||||
## PHP-Befehlsreferenz
|
||||
|
||||
```php
|
||||
IPS_RequestAction($InstanceID, 'update', true);
|
||||
```
|
||||
Reference in New Issue
Block a user