diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml new file mode 100644 index 0000000..3713f68 --- /dev/null +++ b/.github/workflows/style.yml @@ -0,0 +1,13 @@ +name: Check Style + +on: [push, pull_request] + +jobs: + + style: + runs-on: ubuntu-latest + steps: + - name: Checkout module + uses: actions/checkout@master + - name: Check style + uses: symcon/action-style@v3 \ No newline at end of file diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..1c9d116 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,15 @@ +name: Run Tests + +on: [push, pull_request] + +jobs: + + test: + runs-on: ubuntu-latest + steps: + - name: Checkout module + uses: actions/checkout@master + with: + submodules: true + - name: Run tests + uses: symcon/action-tests@master \ No newline at end of file diff --git a/.gitignore b/.gitignore index 723ef36..df90c89 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,5 @@ -.idea \ No newline at end of file +.DS_Store +.idea/ +.phpunit.* +.php_cs.cache +.php-cs-fixer.cache \ No newline at end of file diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..8f49adc --- /dev/null +++ b/.gitmodules @@ -0,0 +1,6 @@ +[submodule ".style"] + path = .style + url = https://github.com/symcon/StylePHP +[submodule "tests/stubs"] + path = tests/stubs + url = https://github.com/symcon/SymconStubs diff --git a/.style b/.style new file mode 160000 index 0000000..ec73bf7 --- /dev/null +++ b/.style @@ -0,0 +1 @@ +Subproject commit ec73bf742e18b049ad5c90de09033987d3ce671e diff --git a/ConsumptionCosts/README.md b/ConsumptionCosts/README.md new file mode 100644 index 0000000..737bbf7 --- /dev/null +++ b/ConsumptionCosts/README.md @@ -0,0 +1,5 @@ +# VerbrauchKosten + +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/verbrauch-kosten/) + +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/consumption-costs/) \ No newline at end of file diff --git a/ConsumptionCosts/form.json b/ConsumptionCosts/form.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/ConsumptionCosts/form.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/VerbrauchKosten/locale.json b/ConsumptionCosts/locale.json similarity index 58% rename from VerbrauchKosten/locale.json rename to ConsumptionCosts/locale.json index eb08533..ec688c1 100644 --- a/VerbrauchKosten/locale.json +++ b/ConsumptionCosts/locale.json @@ -3,7 +3,8 @@ "de": { "StandBy Consumption": "StandBy Verbrauch", "Cost per kWh": "Kosten pro kWh", - "Total cost per year": "Gesamtkosten pro Jahr" + "Total cost per year": "Gesamtkosten pro Jahr", + "Consumption/Costs": "Verbrauch/Kosten" } } } \ No newline at end of file diff --git a/VerbrauchKosten/module.json b/ConsumptionCosts/module.json similarity index 73% rename from VerbrauchKosten/module.json rename to ConsumptionCosts/module.json index 7a45c1c..783969a 100644 --- a/VerbrauchKosten/module.json +++ b/ConsumptionCosts/module.json @@ -1,14 +1,14 @@ { "id": "{554BC118-FACE-A8BB-63B2-6BDD1B41A8F9}", - "name": "VerbrauchKosten", + "name": "Consumption Costs", "type": 3, "vendor": "", "aliases": [ - "Verbrauch/Kosten" + "Consumption/Costs" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/ConsumptionCosts/module.php b/ConsumptionCosts/module.php new file mode 100644 index 0000000..3c58d82 --- /dev/null +++ b/ConsumptionCosts/module.php @@ -0,0 +1,42 @@ +RegisterVariableFloat('Consumption', $this->Translate('StandBy Consumption'), $profileName, 0); + $this->EnableAction('Consumption'); + + $profileName = 'EuroCent'; + if (!IPS_VariableProfileExists($profileName)) { + IPS_CreateVariableProfile($profileName, VARIABLETYPE_FLOAT); + IPS_SetVariableProfileText($profileName, '', ' €'); + IPS_SetVariableProfileValues($profileName, 0, 10, 0.01); + IPS_SetVariableProfileDigits($profileName, 2); + IPS_SetVariableProfileIcon($profileName, 'Repeat'); + } + + $this->RegisterVariableFloat('CostPerKiloWatt', $this->Translate('Cost per kWh'), 'EuroCent', 1); + $this->EnableAction('CostPerKiloWatt'); + + $this->RegisterVariableFloat('TotalCostPerYear', $this->Translate('Total cost per year'), '~Euro', 2); + } + + public function RequestAction($Ident, $Value) + { + $this->SetValue($Ident, $Value); + $this->SetValue('TotalCostPerYear', $this->GetValue('Consumption') / 1000 * $this->GetValue('CostPerKiloWatt') * 24 * 365); + } +} \ No newline at end of file diff --git a/E-Auto/README.md b/E-Auto/README.md deleted file mode 100644 index ab29a43..0000000 --- a/E-Auto/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Heizstab -Beschreibung des Moduls. - -### Inhaltsverzeichnis - -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'Heizstab'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'Heizstab'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file diff --git a/E-Auto/locale.json b/E-Auto/locale.json deleted file mode 100644 index cee8b17..0000000 --- a/E-Auto/locale.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "translations": { - "de": { - "Capacity": "Leistung", - "Variance": "Varianz", - "Interval": "Intervall", - "seconds": "Sekunden" - } - } -} \ No newline at end of file diff --git a/E-Auto/module.php b/E-Auto/module.php deleted file mode 100644 index a26493e..0000000 --- a/E-Auto/module.php +++ /dev/null @@ -1,293 +0,0 @@ -RegisterPropertyInteger("Mode", 0); // 0 = Simple, 1 = Wallbox - - // Simple - $this->RegisterPropertyFloat("Capacity", 6000); - - // Wallbox - $this->RegisterPropertyInteger("Phases", 1); - $this->RegisterPropertyBoolean("Switching", false); - $this->RegisterPropertyFloat("MinCurrent", 6); - $this->RegisterPropertyFloat("MaxCurrent", 16); - $this->RegisterPropertyBoolean("SplitPhases", false); - - $this->RegisterPropertyInteger("Variance", 3); - $this->RegisterPropertyInteger("Interval", 3); - - $this->RegisterVariableFloat("Consumption", "Verbrauch", "~Watt", 2); - - $this->RegisterVariableInteger("SoC", "SoC (Ist)", "~Intensity.100", 3); - $this->EnableAction("SoC"); - - $this->RegisterTimer("Update", 0, "VM_Update(\$_IPS[\"TARGET\"]);"); - $this->RegisterTimer("Increase", 1000, "VM_Increase(\$_IPS[\"TARGET\"]);"); - } - - public function ApplyChanges() - { - parent::ApplyChanges(); - - $simpleMode = $this->ReadPropertyInteger("Mode") == 0; - - // Use/load the car like a dimmable device - $this->MaintainVariable("Status", "Status", VARIABLETYPE_BOOLEAN, "~Switch", 0, $simpleMode); - if ($simpleMode) { - $this->EnableAction("Status"); - } - $this->MaintainVariable("Intensity", "Intensität", VARIABLETYPE_INTEGER, "~Intensity.100", 1, $simpleMode); - if ($simpleMode) { - $this->EnableAction("Intensity"); - } - - // Use/load the car through a wallbox - $profileNameAmpere = "AmpereSlider_" . $this->ReadPropertyFloat("MinCurrent") . "_" . $this->ReadPropertyFloat("MaxCurrent"); - if (!$simpleMode && !IPS_VariableProfileExists($profileNameAmpere)) { - IPS_CreateVariableProfile($profileNameAmpere, VARIABLETYPE_FLOAT); - IPS_SetVariableProfileText($profileNameAmpere, "", " A"); - IPS_SetVariableProfileValues($profileNameAmpere, $this->ReadPropertyFloat("MinCurrent"),$this->ReadPropertyFloat("MaxCurrent"), .1); - IPS_SetVariableProfileDigits($profileNameAmpere, 1); - } - - $profileNamePower = "PowerSlider_" . $this->ReadPropertyFloat("MinCurrent") . "_" . $this->ReadPropertyFloat("MaxCurrent"); - if (!$simpleMode && !IPS_VariableProfileExists($profileNamePower)) { - IPS_CreateVariableProfile($profileNamePower, VARIABLETYPE_FLOAT); - IPS_SetVariableProfileText($profileNamePower, "", " W"); - IPS_SetVariableProfileValues($profileNamePower, 0,$this->ReadPropertyFloat("MaxCurrent") * 3 * 230, 100); - IPS_SetVariableProfileDigits($profileNamePower, 0); - } - - $numberPhases = $this->ReadPropertyInteger("Phases"); - $splitPhases = $this->ReadPropertyBoolean("SplitPhases"); - $switchPhase = $this->ReadPropertyBoolean("Switching"); - - $profileNamePhases = "PhaseState_" . $numberPhases; - if (!$simpleMode && ($numberPhases > 1) && !IPS_VariableProfileExists($profileNamePhases)) { - IPS_CreateVariableProfile($profileNamePhases, VARIABLETYPE_INTEGER); - IPS_SetVariableProfileValues($profileNamePhases, 1,3, 0); - IPS_SetVariableProfileAssociation($profileNamePhases, 1, "1-phased", "", -1); - if ($numberPhases == 2) { - IPS_SetVariableProfileAssociation($profileNamePhases, 2, "2-phased", "", -1); - } - else { - IPS_SetVariableProfileAssociation($profileNamePhases, 3, "3-phased", "", -1); - } - } - - $this->MaintainVariable("Power", "Power (Target)", VARIABLETYPE_FLOAT, $profileNamePower, 0, !$simpleMode); - if (!$simpleMode) { - $this->EnableAction("Power"); - } - - $this->MaintainVariable("Phases", "Phases", VARIABLETYPE_INTEGER, $profileNamePhases, 1, !$simpleMode && $numberPhases > 1 && $switchPhase); - if (!$simpleMode && $numberPhases > 1 && $switchPhase) { - $this->EnableAction("Phases"); - if ($this->GetValue("Phases") == 0) { - $this->SetValue("Phases", $numberPhases); - } - } - - $this->MaintainVariable("Current", "Current", VARIABLETYPE_FLOAT, $profileNameAmpere, 2, !$simpleMode && $numberPhases == 1); - if (!$simpleMode && $numberPhases == 1) { - $this->EnableAction("Current"); - } - $this->MaintainVariable("CurrentL123", "Current (L1/L2/L3)", VARIABLETYPE_FLOAT, $profileNameAmpere, 3, !$simpleMode && !$splitPhases && $numberPhases == 3); - if (!$simpleMode && !$splitPhases && $numberPhases == 3) { - $this->EnableAction("CurrentL123"); - } - $this->MaintainVariable("CurrentL12", "Current (L1/L2)", VARIABLETYPE_FLOAT, $profileNameAmpere, 3, !$simpleMode && !$splitPhases && $numberPhases == 2); - if (!$simpleMode && !$splitPhases && $numberPhases == 2) { - $this->EnableAction("CurrentL12"); - } - $this->MaintainVariable("CurrentL1", "Current (L1)", VARIABLETYPE_FLOAT, $profileNameAmpere, 4, !$simpleMode && $splitPhases && $numberPhases > 1); - if (!$simpleMode && $splitPhases && $numberPhases > 1) { - $this->EnableAction("CurrentL1"); - } - $this->MaintainVariable("CurrentL2", "Current (L2)", VARIABLETYPE_FLOAT, $profileNameAmpere, 5, !$simpleMode && $splitPhases && $numberPhases >= 2); - if (!$simpleMode && $splitPhases && $numberPhases >= 2) { - $this->EnableAction("CurrentL2"); - } - $this->MaintainVariable("CurrentL3", "Current (L3)", VARIABLETYPE_FLOAT, $profileNameAmpere, 6, !$simpleMode && $splitPhases && $numberPhases >= 3); - if (!$simpleMode && $splitPhases && $numberPhases >= 3) { - $this->EnableAction("CurrentL3"); - } - - $this->SetTimerInterval("Update", $this->ReadPropertyInteger("Interval") * 1000); - } - - public function RequestAction($Ident, $Value) - { - switch ($Ident) { - case "Status": - $this->SetValue("Status", $Value); - $this->SetValue("Intensity", $Value ? 100 : 0); - break; - case "Intensity": - $this->SetValue("Status", $Value); - $this->SetValue("Intensity", $Value); - break; - case "Current": - $this->SetValue("Current", $Value); - break; - case "Phases": - $this->SetValue("Phases", $Value); - $this->SetValue("CurrentL2", 0); - $this->SetValue("CurrentL3", 0); - break; - case "CurrentL1": - $this->SetValue("CurrentL1", $Value); - break; - case "CurrentL2": - if ($this->GetValue("Phases") != 3) { - die("Cannot set L2 when in 1 phase mode"); - } - $this->SetValue("CurrentL2", $Value); - break; - case "CurrentL3": - if ($this->GetValue("Phases") != 3) { - die("Cannot set L3 when in 1 phase mode"); - } - $this->SetValue("CurrentL3", $Value); - break; - case "CurrentL12": - $this->SetValue("CurrentL12", $Value); - break; - case "CurrentL123": - $this->SetValue("CurrentL123", $Value); - break; - case "SoC": - $this->SetValue("SoC", $Value); - break; - case "Power": - $current = $Value / 230 / $this->ReadPropertyInteger("Phases"); - if ($current < $this->ReadPropertyFloat("MinCurrent")) { - $current = 0; - } - if ($current > $this->ReadPropertyFloat("MaxCurrent")) { - $current = $this->ReadPropertyFloat("MaxCurrent"); - } - $onePhaseCurrent = $Value / 230; - if ($onePhaseCurrent < $this->ReadPropertyFloat("MinCurrent")) { - $onePhaseCurrent = 0; - } - if ($onePhaseCurrent > $this->ReadPropertyFloat("MaxCurrent")) { - $onePhaseCurrent = $this->ReadPropertyFloat("MaxCurrent"); - } - - switch($this->ReadPropertyInteger("Phases")) { - case 1: - $this->SetValue("Current", $current); - break; - case 2: - if ($current == 0 && $this->ReadPropertyBoolean("Switching")) { - $this->SetValue("Phases", 1); - if ($this->ReadPropertyBoolean("SplitPhases")) { - $this->SetValue("CurrentL1", $onePhaseCurrent); - $this->SetValue("CurrentL2", 0); - } - else { - $this->SetValue("CurrentL12", $onePhaseCurrent); - } - } - else { - if ($this->ReadPropertyBoolean("Switching")) { - $this->SetValue("Phases", 2); - } - if ($this->ReadPropertyBoolean("SplitPhases")) { - $total = $current * 2; - $this->SetValue("CurrentL1", floor($current)); - $this->SetValue("CurrentL2", $total - floor($current)); - } - else { - $this->SetValue("CurrentL12", $current); - } - } - break; - case 3: - if ($current == 0 && $this->ReadPropertyBoolean("Switching")) { - $this->SetValue("Phases", 1); - if ($this->ReadPropertyBoolean("SplitPhases")) { - $this->SetValue("CurrentL1", $onePhaseCurrent); - $this->SetValue("CurrentL2", 0); - $this->SetValue("CurrentL3", 0); - } - else { - $this->SetValue("CurrentL123", $onePhaseCurrent); - } - } - else { - if ($this->ReadPropertyBoolean("Switching")) { - $this->SetValue("Phases", 3); - } - if ($this->ReadPropertyBoolean("SplitPhases")) { - $total = $current * 3; - $this->SetValue("CurrentL1", floor($current)); - $this->SetValue("CurrentL2", floor($current)); - $this->SetValue("CurrentL3", $total - floor($current) * 2); - } else { - $this->SetValue("CurrentL123", $current); - } - } - break; - } - - $this->SetValue("Power", $Value); - break; - } - if (!$this->ReadPropertyInteger("Interval")) { - $this->Update(); - } - } - - public function Update() - { - $volt = 230; - $value = 0; - switch($this->ReadPropertyInteger("Mode")) { - case 0: // Simple Mode - $value = $this->ReadPropertyFloat("Capacity") * ($this->GetValue("Intensity") / 100); - break; - case 1: //Wallbox Mode - switch($this->ReadPropertyInteger("Phases")) { - case 1: - $value = $this->GetValue("Current") * $volt; - break; - case 2: - if (!$this->ReadPropertyBoolean("SplitPhases")) { - $value = $this->GetValue("CurrentL12") * $volt * $this->GetValue("Phases"); - } else if ($this->ReadPropertyBoolean("SplitPhases")) { - $value += $this->GetValue("CurrentL1") * $volt; - $value += $this->GetValue("CurrentL2") * $volt; - } - break; - case 3: - if (!$this->ReadPropertyBoolean("SplitPhases")) { - $value = $this->GetValue("CurrentL123") * $volt * $this->GetValue("Phases"); - } else if ($this->ReadPropertyBoolean("SplitPhases")) { - $value += $this->GetValue("CurrentL1") * $volt; - $value += $this->GetValue("CurrentL2") * $volt; - $value += $this->GetValue("CurrentL3") * $volt; - } - break; - } - $this->SetValue("Power", $value); - break; - } - // Write value with variance - $this->SetValue("Consumption", $value * ((100 + (rand(0, $this->ReadPropertyInteger("Variance") * 100)/100) - ($this->ReadPropertyInteger("Variance")/2)) / 100)); - } - - public function Increase() - { - if ($this->GetValue("Consumption")) { - $this->SetValue("SoC", min(100, $this->GetValue("SoC")+1)); - } - } - } \ No newline at end of file diff --git a/E-Car/README.md b/E-Car/README.md new file mode 100644 index 0000000..d575927 --- /dev/null +++ b/E-Car/README.md @@ -0,0 +1,5 @@ +# E-Auto + +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/e-auto-simulation/) + +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/e-car-simulation/) \ No newline at end of file diff --git a/E-Auto/form.json b/E-Car/form.json similarity index 66% rename from E-Auto/form.json rename to E-Car/form.json index 0e9b8b7..82a6ac4 100644 --- a/E-Auto/form.json +++ b/E-Car/form.json @@ -45,36 +45,66 @@ { "caption": "1-phased", "value": [ - {"name": "Phases", "value": 1}, - {"name": "Switching", "value": false} + { + "name": "Phases", + "value": 1 + }, + { + "name": "Switching", + "value": false + } ] }, { "caption": "2-phased", "value": [ - {"name": "Phases", "value": 2}, - {"name": "Switching", "value": false} + { + "name": "Phases", + "value": 2 + }, + { + "name": "Switching", + "value": false + } ] }, { "caption": "3-phased", "value": [ - {"name": "Phases", "value": 3}, - {"name": "Switching", "value": false} + { + "name": "Phases", + "value": 3 + }, + { + "name": "Switching", + "value": false + } ] }, { "caption": "1 and 2-phased (automatic switching)", "value": [ - {"name": "Phases", "value": 2}, - {"name": "Switching", "value": true} + { + "name": "Phases", + "value": 2 + }, + { + "name": "Switching", + "value": true + } ] }, { "caption": "1 and 3-phased (automatic switching)", "value": [ - {"name": "Phases", "value": 3}, - {"name": "Switching", "value": true} + { + "name": "Phases", + "value": 3 + }, + { + "name": "Switching", + "value": true + } ] } ] diff --git a/E-Car/locale.json b/E-Car/locale.json new file mode 100644 index 0000000..15f157c --- /dev/null +++ b/E-Car/locale.json @@ -0,0 +1,34 @@ +{ + "translations": { + "de": { + "Capacity": "Leistung", + "Variance": "Varianz", + "Interval": "Intervall", + "seconds": "Sekunden", + "Simple": "Simpel", + "This parameter only applies to 'Simple' mode": "Dieser Parameter wird nur im 'Simpel'-Modus gesetzt", + "There parameters only applies to 'Wallbox' mode": "Diese Parameter werden nur im 'Wallbox'-Modus gesetzt", + "Phases": "Phasen", + "1-phased": "1-phasig", + "2-phased": "2-phasig", + "3-phased": "3-phasig", + "1 and 2-phased (automatic switching)": "1 und 2-phasig (automatisches umschalten)", + "1 and 3-phased (automatic switching)": "1 und 3-phasig (automatisches umschalten)", + "Split phases to own variables (Simulate the Alfen Wallbox)": "Teile die Phasen auf einzelne Variablen auf (Simuliert die Alfen Wallbox)", + "Min Current (per Phase)": "Minimale Stromstärke (pro Phase)", + "Max Current (per Phase)": "Maximale Stromstärke (pro Phase)", + "These parameters apply to all modes": "Diese Parameter werden in allen Modi gesetzt", + "E-Car (Simulation)": "E-Auto (Simulation)", + "Current": "Stromstärke", + "Current (L1/L2/L3)": "Stromstärke (L1/L2/L3)", + "Current (L1/L2)": "Stromstärke (L1/L2)", + "Current (L1)": "Stromstärke (L1)", + "Current (L2)": "Stromstärke (L2)", + "Current (L3)": "Stromstärke (L3)", + "SoC (Ist)": "Akkuladestand (Ist)", + "Power (Target)": "Leistung (Soll)", + "Consumption": "Verbrauch", + "Intensity": "Intensität" + } + } +} \ No newline at end of file diff --git a/E-Auto/module.json b/E-Car/module.json similarity index 76% rename from E-Auto/module.json rename to E-Car/module.json index 4b6e190..973562d 100644 --- a/E-Auto/module.json +++ b/E-Car/module.json @@ -1,14 +1,14 @@ { "id": "{6BF11B43-77F7-8ACE-DF27-E5921360F7ED}", - "name": "EAuto", + "name": "ECar", "type": 3, "vendor": "", "aliases": [ - "E-Auto (Simulation)" + "E-Car (Simulation)" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/E-Car/module.php b/E-Car/module.php new file mode 100644 index 0000000..2c84485 --- /dev/null +++ b/E-Car/module.php @@ -0,0 +1,287 @@ +RegisterPropertyInteger('Mode', 0); // 0 = Simple, 1 = Wallbox + + // Simple + $this->RegisterPropertyFloat('Capacity', 6000); + + // Wallbox + $this->RegisterPropertyInteger('Phases', 1); + $this->RegisterPropertyBoolean('Switching', false); + $this->RegisterPropertyFloat('MinCurrent', 6); + $this->RegisterPropertyFloat('MaxCurrent', 16); + $this->RegisterPropertyBoolean('SplitPhases', false); + + $this->RegisterPropertyInteger('Variance', 3); + $this->RegisterPropertyInteger('Interval', 3); + + $this->RegisterVariableFloat('Consumption', $this->Translate('Consumption'), '~Watt', 2); + + $this->RegisterVariableInteger('SoC', $this->Translate('SoC (Ist)'), '~Intensity.100', 3); + $this->EnableAction('SoC'); + + $this->RegisterTimer('Update', 0, 'VG_Update($_IPS["TARGET"]);'); + $this->RegisterTimer('Increase', 1000, 'VG_Increase($_IPS["TARGET"]);'); + } + + public function ApplyChanges() + { + parent::ApplyChanges(); + + $simpleMode = $this->ReadPropertyInteger('Mode') == 0; + + // Use/load the car like a dimmable device + $this->MaintainVariable('Status', $this->Translate('Status'), VARIABLETYPE_BOOLEAN, '~Switch', 0, $simpleMode); + if ($simpleMode) { + $this->EnableAction('Status'); + } + $this->MaintainVariable('Intensity', $this->Translate('Intensity'), VARIABLETYPE_INTEGER, '~Intensity.100', 1, $simpleMode); + if ($simpleMode) { + $this->EnableAction('Intensity'); + } + + // Use/load the car through a wallbox + $profileNameAmpere = 'AmpereSlider_' . $this->ReadPropertyFloat('MinCurrent') . '_' . $this->ReadPropertyFloat('MaxCurrent'); + if (!$simpleMode && !IPS_VariableProfileExists($profileNameAmpere)) { + IPS_CreateVariableProfile($profileNameAmpere, VARIABLETYPE_FLOAT); + IPS_SetVariableProfileText($profileNameAmpere, '', ' A'); + IPS_SetVariableProfileValues($profileNameAmpere, $this->ReadPropertyFloat('MinCurrent'), $this->ReadPropertyFloat('MaxCurrent'), .1); + IPS_SetVariableProfileDigits($profileNameAmpere, 1); + } + + $profileNamePower = 'PowerSlider_' . $this->ReadPropertyFloat('MinCurrent') . '_' . $this->ReadPropertyFloat('MaxCurrent'); + if (!$simpleMode && !IPS_VariableProfileExists($profileNamePower)) { + IPS_CreateVariableProfile($profileNamePower, VARIABLETYPE_FLOAT); + IPS_SetVariableProfileText($profileNamePower, '', ' W'); + IPS_SetVariableProfileValues($profileNamePower, 0, $this->ReadPropertyFloat('MaxCurrent') * 3 * 230, 100); + IPS_SetVariableProfileDigits($profileNamePower, 0); + } + + $numberPhases = $this->ReadPropertyInteger('Phases'); + $splitPhases = $this->ReadPropertyBoolean('SplitPhases'); + $switchPhase = $this->ReadPropertyBoolean('Switching'); + + $profileNamePhases = 'PhaseState_' . $numberPhases; + if (!$simpleMode && ($numberPhases > 1) && !IPS_VariableProfileExists($profileNamePhases)) { + IPS_CreateVariableProfile($profileNamePhases, VARIABLETYPE_INTEGER); + IPS_SetVariableProfileValues($profileNamePhases, 1, 3, 0); + IPS_SetVariableProfileAssociation($profileNamePhases, 1, '1-phased', '', -1); + if ($numberPhases == 2) { + IPS_SetVariableProfileAssociation($profileNamePhases, 2, '2-phased', '', -1); + } else { + IPS_SetVariableProfileAssociation($profileNamePhases, 3, '3-phased', '', -1); + } + } + + $this->MaintainVariable('Power', $this->Translate('Power (Target)'), VARIABLETYPE_FLOAT, $profileNamePower, 0, !$simpleMode); + if (!$simpleMode) { + $this->EnableAction('Power'); + } + + $this->MaintainVariable('Phases', $this->Translate('Phases'), VARIABLETYPE_INTEGER, $profileNamePhases, 1, !$simpleMode && $numberPhases > 1 && $switchPhase); + if (!$simpleMode && $numberPhases > 1 && $switchPhase) { + $this->EnableAction('Phases'); + if ($this->GetValue('Phases') == 0) { + $this->SetValue('Phases', $numberPhases); + } + } + + $this->MaintainVariable('Current', $this->Translate('Current'), VARIABLETYPE_FLOAT, $profileNameAmpere, 2, !$simpleMode && $numberPhases == 1); + if (!$simpleMode && $numberPhases == 1) { + $this->EnableAction('Current'); + } + $this->MaintainVariable('CurrentL123', $this->Translate('Current (L1/L2/L3)'), VARIABLETYPE_FLOAT, $profileNameAmpere, 3, !$simpleMode && !$splitPhases && $numberPhases == 3); + if (!$simpleMode && !$splitPhases && $numberPhases == 3) { + $this->EnableAction('CurrentL123'); + } + $this->MaintainVariable('CurrentL12', $this->Translate('Current (L1/L2)'), VARIABLETYPE_FLOAT, $profileNameAmpere, 3, !$simpleMode && !$splitPhases && $numberPhases == 2); + if (!$simpleMode && !$splitPhases && $numberPhases == 2) { + $this->EnableAction('CurrentL12'); + } + $this->MaintainVariable('CurrentL1', $this->Translate('Current (L1)'), VARIABLETYPE_FLOAT, $profileNameAmpere, 4, !$simpleMode && $splitPhases && $numberPhases > 1); + if (!$simpleMode && $splitPhases && $numberPhases > 1) { + $this->EnableAction('CurrentL1'); + } + $this->MaintainVariable('CurrentL2', $this->Translate('Current (L2)'), VARIABLETYPE_FLOAT, $profileNameAmpere, 5, !$simpleMode && $splitPhases && $numberPhases >= 2); + if (!$simpleMode && $splitPhases && $numberPhases >= 2) { + $this->EnableAction('CurrentL2'); + } + $this->MaintainVariable('CurrentL3', $this->Translate('Current (L3)'), VARIABLETYPE_FLOAT, $profileNameAmpere, 6, !$simpleMode && $splitPhases && $numberPhases >= 3); + if (!$simpleMode && $splitPhases && $numberPhases >= 3) { + $this->EnableAction('CurrentL3'); + } + + $this->SetTimerInterval('Update', $this->ReadPropertyInteger('Interval') * 1000); + } + + public function RequestAction($Ident, $Value) + { + switch ($Ident) { + case 'Status': + $this->SetValue('Status', $Value); + $this->SetValue('Intensity', $Value ? 100 : 0); + break; + case 'Intensity': + $this->SetValue('Status', $Value); + $this->SetValue('Intensity', $Value); + break; + case 'Current': + $this->SetValue('Current', $Value); + break; + case 'Phases': + $this->SetValue('Phases', $Value); + $this->SetValue('CurrentL2', 0); + $this->SetValue('CurrentL3', 0); + break; + case 'CurrentL1': + $this->SetValue('CurrentL1', $Value); + break; + case 'CurrentL2': + if ($this->GetValue('Phases') != 3) { + die('Cannot set L2 when in 1 phase mode'); + } + $this->SetValue('CurrentL2', $Value); + break; + case 'CurrentL3': + if ($this->GetValue('Phases') != 3) { + die('Cannot set L3 when in 1 phase mode'); + } + $this->SetValue('CurrentL3', $Value); + break; + case 'CurrentL12': + $this->SetValue('CurrentL12', $Value); + break; + case 'CurrentL123': + $this->SetValue('CurrentL123', $Value); + break; + case 'SoC': + $this->SetValue('SoC', $Value); + break; + case 'Power': + $current = $Value / 230 / $this->ReadPropertyInteger('Phases'); + if ($current < $this->ReadPropertyFloat('MinCurrent')) { + $current = 0; + } + if ($current > $this->ReadPropertyFloat('MaxCurrent')) { + $current = $this->ReadPropertyFloat('MaxCurrent'); + } + $onePhaseCurrent = $Value / 230; + if ($onePhaseCurrent < $this->ReadPropertyFloat('MinCurrent')) { + $onePhaseCurrent = 0; + } + if ($onePhaseCurrent > $this->ReadPropertyFloat('MaxCurrent')) { + $onePhaseCurrent = $this->ReadPropertyFloat('MaxCurrent'); + } + + switch ($this->ReadPropertyInteger('Phases')) { + case 1: + $this->SetValue('Current', $current); + break; + case 2: + if ($current == 0 && $this->ReadPropertyBoolean('Switching')) { + $this->SetValue('Phases', 1); + if ($this->ReadPropertyBoolean('SplitPhases')) { + $this->SetValue('CurrentL1', $onePhaseCurrent); + $this->SetValue('CurrentL2', 0); + } else { + $this->SetValue('CurrentL12', $onePhaseCurrent); + } + } else { + if ($this->ReadPropertyBoolean('Switching')) { + $this->SetValue('Phases', 2); + } + if ($this->ReadPropertyBoolean('SplitPhases')) { + $total = $current * 2; + $this->SetValue('CurrentL1', floor($current)); + $this->SetValue('CurrentL2', $total - floor($current)); + } else { + $this->SetValue('CurrentL12', $current); + } + } + break; + case 3: + if ($current == 0 && $this->ReadPropertyBoolean('Switching')) { + $this->SetValue('Phases', 1); + if ($this->ReadPropertyBoolean('SplitPhases')) { + $this->SetValue('CurrentL1', $onePhaseCurrent); + $this->SetValue('CurrentL2', 0); + $this->SetValue('CurrentL3', 0); + } else { + $this->SetValue('CurrentL123', $onePhaseCurrent); + } + } else { + if ($this->ReadPropertyBoolean('Switching')) { + $this->SetValue('Phases', 3); + } + if ($this->ReadPropertyBoolean('SplitPhases')) { + $total = $current * 3; + $this->SetValue('CurrentL1', floor($current)); + $this->SetValue('CurrentL2', floor($current)); + $this->SetValue('CurrentL3', $total - floor($current) * 2); + } else { + $this->SetValue('CurrentL123', $current); + } + } + break; + } + + $this->SetValue('Power', $Value); + break; + } + if (!$this->ReadPropertyInteger('Interval')) { + $this->Update(); + } + } + + public function Update() + { + $volt = 230; + $value = 0; + switch ($this->ReadPropertyInteger('Mode')) { + case 0: // Simple Mode + $value = $this->ReadPropertyFloat('Capacity') * ($this->GetValue('Intensity') / 100); + break; + case 1: //Wallbox Mode + switch ($this->ReadPropertyInteger('Phases')) { + case 1: + $value = $this->GetValue('Current') * $volt; + break; + case 2: + if (!$this->ReadPropertyBoolean('SplitPhases')) { + $value = $this->GetValue('CurrentL12') * $volt * $this->GetValue('Phases'); + } elseif ($this->ReadPropertyBoolean('SplitPhases')) { + $value += $this->GetValue('CurrentL1') * $volt; + $value += $this->GetValue('CurrentL2') * $volt; + } + break; + case 3: + if (!$this->ReadPropertyBoolean('SplitPhases')) { + $value = $this->GetValue('CurrentL123') * $volt * $this->GetValue('Phases'); + } elseif ($this->ReadPropertyBoolean('SplitPhases')) { + $value += $this->GetValue('CurrentL1') * $volt; + $value += $this->GetValue('CurrentL2') * $volt; + $value += $this->GetValue('CurrentL3') * $volt; + } + break; + } + $this->SetValue('Power', $value); + break; + } + // Write value with variance + $this->SetValue('Consumption', $value * ((100 + (rand(0, $this->ReadPropertyInteger('Variance') * 100) / 100) - ($this->ReadPropertyInteger('Variance') / 2)) / 100)); + } + + public function Increase() + { + if ($this->GetValue('Consumption')) { + $this->SetValue('SoC', min(100, $this->GetValue('SoC') + 1)); + } + } +} diff --git a/Heater/README.md b/Heater/README.md new file mode 100644 index 0000000..b52413b --- /dev/null +++ b/Heater/README.md @@ -0,0 +1,5 @@ +# Heizstab Simulation + +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/heizstab-simulation/) + +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/heater-simulation/) \ No newline at end of file diff --git a/Heizstab/form.json b/Heater/form.json similarity index 100% rename from Heizstab/form.json rename to Heater/form.json diff --git a/Heater/locale.json b/Heater/locale.json new file mode 100644 index 0000000..1f31661 --- /dev/null +++ b/Heater/locale.json @@ -0,0 +1,13 @@ +{ + "translations": { + "de": { + "Capacity": "Leistung", + "Variance": "Varianz", + "Interval": "Intervall", + "seconds": "Sekunden", + "Heater (Simulation)": "Heizstab (Simulation)", + "Consumption": "Verbrauch", + "Intensity": "Intensität" + } + } +} \ No newline at end of file diff --git a/Heizstab/module.json b/Heater/module.json similarity index 74% rename from Heizstab/module.json rename to Heater/module.json index 13f0090..8cbbb48 100644 --- a/Heizstab/module.json +++ b/Heater/module.json @@ -1,14 +1,14 @@ { "id": "{F4F4F985-47AC-8091-8A4A-53180EB38746}", - "name": "Heizstab", + "name": "Virtual Heater", "type": 3, "vendor": "", "aliases": [ - "Heizstab (Simulation)" + "Heater (Simulation)" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/Heater/module.php b/Heater/module.php new file mode 100644 index 0000000..b5d5da0 --- /dev/null +++ b/Heater/module.php @@ -0,0 +1,55 @@ +RegisterPropertyFloat('Capacity', 500); + $this->RegisterPropertyInteger('Variance', 6); + $this->RegisterPropertyInteger('Interval', 3); + + $this->RegisterVariableBoolean('Status', 'Status', '~Switch', 0); + $this->EnableAction('Status'); + $this->RegisterVariableInteger('Intensity', $this->Translate('Intensity'), '~Intensity.100', 1); + $this->EnableAction('Intensity'); + $this->RegisterVariableFloat('Consumption', $this->Translate('Consumption'), '~Watt', 2); + + $this->RegisterTimer('Update', 0, 'VG_Update($_IPS["TARGET"]);'); + } + + public function ApplyChanges() + { + parent::ApplyChanges(); + + $this->SetTimerInterval('Update', $this->ReadPropertyInteger('Interval') * 1000); + } + + public function RequestAction($Ident, $Value) + { + switch ($Ident) { + case 'Status': + $this->SetValue('Status', $Value); + $this->SetValue('Intensity', $Value ? 100 : 0); + break; + case 'Intensity': + $this->SetValue('Status', $Value); + $this->SetValue('Intensity', $Value); + break; + } + if (!$this->ReadPropertyInteger('Interval')) { + $this->Update(); + } + } + + public function Update() + { + if (!$this->GetValue('Intensity')) { + $this->SetValue('Consumption', 0); + } else { + $this->SetValue('Consumption', $this->ReadPropertyFloat('Capacity') * ($this->GetValue('Intensity') / 100) * ((100 + (rand(0, $this->ReadPropertyInteger('Variance') * 100) / 100) - ($this->ReadPropertyInteger('Variance') / 2)) / 100)); + } + } +} diff --git a/Heizstab/README.md b/Heizstab/README.md deleted file mode 100644 index ab29a43..0000000 --- a/Heizstab/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# Heizstab -Beschreibung des Moduls. - -### Inhaltsverzeichnis - -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'Heizstab'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'Heizstab'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file diff --git a/Heizstab/locale.json b/Heizstab/locale.json deleted file mode 100644 index cee8b17..0000000 --- a/Heizstab/locale.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "translations": { - "de": { - "Capacity": "Leistung", - "Variance": "Varianz", - "Interval": "Intervall", - "seconds": "Sekunden" - } - } -} \ No newline at end of file diff --git a/Heizstab/module.php b/Heizstab/module.php deleted file mode 100644 index ac98efd..0000000 --- a/Heizstab/module.php +++ /dev/null @@ -1,56 +0,0 @@ -RegisterPropertyFloat("Capacity", 500); - $this->RegisterPropertyInteger("Variance", 6); - $this->RegisterPropertyInteger("Interval", 3); - - $this->RegisterVariableBoolean("Status", "Status", "~Switch", 0); - $this->EnableAction("Status"); - $this->RegisterVariableInteger("Intensity", "Intensität", "~Intensity.100", 1); - $this->EnableAction("Intensity"); - $this->RegisterVariableFloat("Consumption", "Verbrauch", "~Watt", 2); - - $this->RegisterTimer("Update", 0, "VM_Update(\$_IPS[\"TARGET\"]);"); - } - - public function ApplyChanges() - { - parent::ApplyChanges(); - - $this->SetTimerInterval("Update", $this->ReadPropertyInteger("Interval") * 1000); - } - - public function RequestAction($Ident, $Value) - { - switch ($Ident) { - case "Status": - $this->SetValue("Status", $Value); - $this->SetValue("Intensity", $Value ? 100 : 0); - break; - case "Intensity": - $this->SetValue("Status", $Value); - $this->SetValue("Intensity", $Value); - break; - } - if (!$this->ReadPropertyInteger("Interval")) { - $this->Update(); - } - } - - public function Update() - { - if (!$this->GetValue("Intensity")) { - $this->SetValue("Consumption", 0); - } - else { - $this->SetValue("Consumption", $this->ReadPropertyFloat("Capacity") * ($this->GetValue("Intensity") / 100) * ((100 + (rand(0, $this->ReadPropertyInteger("Variance") * 100)/100) - ($this->ReadPropertyInteger("Variance")/2)) / 100)); - } - } - } \ No newline at end of file diff --git a/Licht/README.md b/Licht/README.md deleted file mode 100644 index aeaa413..0000000 --- a/Licht/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# VirtualLight -Beschreibung des Moduls. - -### Inhaltsverzeichnis - -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'VirtualLight'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VirtualLight'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file diff --git a/Licht/form.json b/Licht/form.json deleted file mode 100644 index 7a73a41..0000000 --- a/Licht/form.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/Licht/module.php b/Licht/module.php deleted file mode 100644 index aaab546..0000000 --- a/Licht/module.php +++ /dev/null @@ -1,36 +0,0 @@ -RegisterVariableBoolean("Status", $this->Translate("Status"), "~Switch", 0); - $this->EnableAction("Status"); - $this->RegisterVariableInteger("Intensity", $this->Translate("Intensity"), "~Intensity.100", 1); - $this->EnableAction("Intensity"); - $this->RegisterVariableInteger("Color", $this->Translate("Color"), "~HexColor", 2); - $this->EnableAction("Color"); - $this->RegisterVariableInteger("Temperature", $this->Translate("Temperature"), "~TWColor", 2); - $this->EnableAction("Temperature"); - } - - public function ApplyChanges() - { - parent::ApplyChanges(); - //Set default values - if ($this->GetValue('Color') == 0) { - $this->SetValue('Color', 3328428); - $this->SetValue('Intensity', 40); - $this->SetValue('Temperature',3408); - } - } - - public function RequestAction($Ident, $Value) - { - $this->SetValue($Ident, $Value); - } - } \ No newline at end of file diff --git a/Mediaplayer/README.md b/Mediaplayer/README.md index 84f519c..04cf8c9 100644 --- a/Mediaplayer/README.md +++ b/Mediaplayer/README.md @@ -1,67 +1,5 @@ # VirtualMediaplayer -Beschreibung des Moduls. -### Inhaltsverzeichnis +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/mediaplayer-simulation/) -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 5.5 - -### 3. Software-Installation - -* Über den Module Store das 'VirtualMediaPlayer'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VirtualMediaPlayer'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean MPS_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`MPS_BeispielFunktion(12345);` \ No newline at end of file +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/mediaplayer-simulation/) \ No newline at end of file diff --git a/Mediaplayer/form.json b/Mediaplayer/form.json index c382337..9e26dfe 100644 --- a/Mediaplayer/form.json +++ b/Mediaplayer/form.json @@ -1,5 +1 @@ -{ - "elements": [], - "actions": [], - "status": [] -} \ No newline at end of file +{} \ No newline at end of file diff --git a/Mediaplayer/module.json b/Mediaplayer/module.json index c5da7f1..ea65167 100644 --- a/Mediaplayer/module.json +++ b/Mediaplayer/module.json @@ -9,6 +9,6 @@ "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/Mediaplayer/module.php b/Mediaplayer/module.php index 9fc5652..735630d 100644 --- a/Mediaplayer/module.php +++ b/Mediaplayer/module.php @@ -1,191 +1,197 @@ RegisterVariableInteger('Playback', $this->Translate('Playback'), '~PlaybackPreviousNext', 0); - $this->EnableAction('Playback'); - $this->RegisterVariableFloat('Progress', $this->Translate('Progress'), '~Progress', 0); - $this->EnableAction('Progress'); - $this->RegisterVariableString('Playlist', $this->Translate('Playlist'), '~Playlist', 0); - $this->EnableAction('Playlist'); - $this->RegisterVariableString('Artist', $this->Translate('Artist'), '~Artist', 0); - $this->RegisterVariableString('Song', $this->Translate('Song'), '~Song', 0); - $this->RegisterVariableInteger('Volume', $this->Translate('Volume'), '~Volume', 0); - $this->EnableAction('Volume'); - $this->RegisterVariableInteger('Repeat', $this->Translate('Repeat'), '~Repeat', 0); - $this->EnableAction('Repeat'); - $this->RegisterVariableBoolean('Mute', $this->Translate('Mute'), '~Mute', 0); - $this->EnableAction('Mute'); - $this->RegisterVariableBoolean('Shuffle', $this->Translate('Shuffle'), '~Shuffle', 0); - $this->EnableAction('Shuffle'); - $this->RegisterTimer('ProgressTimer', 0, 'VM_UpdateProgress($_IPS[\'TARGET\']);'); - if (@!IPS_GetObjectIDByIdent('Cover', $this->InstanceID)) { - $mediaID = IPS_CreateMedia(1); - $image = __DIR__ . '/cover.jpg'; - IPS_SetMediaFile($mediaID, 'file.png', false); - IPS_SetMediaContent($mediaID, base64_encode((file_get_contents($image)))); - IPS_SetName($mediaID, 'Cover'); - IPS_SetParent($mediaID, $this->InstanceID); - IPS_SetIdent($mediaID, 'Cover'); - } - } - - public function RequestAction($Ident, $Value) - { - - switch($Ident) { - case 'Playback': - switch($Value) { - case self::PREVIOUS: - $this->changeTitle(self::PREVIOUS); - $this->startPlayback(); - return; - - case self::STOP: - $this->stopPlayback(); - return; - - case self::PLAY: - $this->startPlayback(); - $playlist = json_decode($this->GetValue('Playlist'), true); - $this->updateTitle($playlist['entries'], $playlist['current']); - return; - - case self::PAUSE: - $this->stopPlayback(); - return; - - case self::NEXT: - $this->changeTitle(self::NEXT); - $this->startPlayback(); - return; - } - break; - - case 'Playlist': - $oldIndex = json_decode($this->GetValue('Playlist'), true)['current']; - $newPlaylist = json_decode($Value, true); - $newIndex = $newPlaylist['current']; - if ($oldIndex != $newIndex) { - $this->SetValue('Progress', 0); - $this->updateTitle($newPlaylist['entries'], $newIndex); - } - - default: - break; - } - - $this->SetValue($Ident, $Value); +class VirtualMediaPlayer extends IPSModule +{ + public const PREVIOUS = 0; + public const STOP = 1; + public const PLAY = 2; + public const PAUSE = 3; + public const NEXT = 4; + + public const REPEAT_OFF = 0; + public const REPEAT_CONTEXT = 1; + public const REPEAT_TRACK = 2; + + public const PLACEHOLDER_NONE = '-'; + + public function Create() + { + //Never delete this line! + parent::Create(); + $this->RegisterVariableInteger('Playback', $this->Translate('Playback'), '~PlaybackPreviousNext', 0); + $this->EnableAction('Playback'); + $this->RegisterVariableFloat('Progress', $this->Translate('Progress'), '~Progress', 0); + $this->EnableAction('Progress'); + $this->RegisterVariableString('Playlist', $this->Translate('Playlist'), '~Playlist', 0); + $this->EnableAction('Playlist'); + $this->RegisterVariableString('Artist', $this->Translate('Artist'), '~Artist', 0); + $this->RegisterVariableString('Song', $this->Translate('Song'), '~Song', 0); + $this->RegisterVariableInteger('Volume', $this->Translate('Volume'), '~Volume', 0); + $this->EnableAction('Volume'); + $this->RegisterVariableInteger('Repeat', $this->Translate('Repeat'), '~Repeat', 0); + $this->EnableAction('Repeat'); + $this->RegisterVariableBoolean('Mute', $this->Translate('Mute'), '~Mute', 0); + $this->EnableAction('Mute'); + $this->RegisterVariableBoolean('Shuffle', $this->Translate('Shuffle'), '~Shuffle', 0); + $this->EnableAction('Shuffle'); + $this->RegisterTimer('ProgressTimer', 0, 'VG_UpdateProgress($_IPS[\'TARGET\']);'); + if (@!IPS_GetObjectIDByIdent('Cover', $this->InstanceID)) { + $mediaID = IPS_CreateMedia(1); + $image = __DIR__ . '/cover.jpg'; + IPS_SetMediaFile($mediaID, 'file.png', false); + IPS_SetMediaContent($mediaID, base64_encode((file_get_contents($image)))); + IPS_SetName($mediaID, 'Cover'); + IPS_SetParent($mediaID, $this->InstanceID); + IPS_SetIdent($mediaID, 'Cover'); + } + } + + public function RequestAction($Ident, $Value) + { + + switch ($Ident) { + case 'Playback': + switch ($Value) { + case self::PREVIOUS: + $this->changeTitle(self::PREVIOUS); + $this->startPlayback(); + return; + + case self::STOP: + $this->stopPlayback(); + return; + + case self::PLAY: + $this->startPlayback(); + $playlist = json_decode($this->GetValue('Playlist'), true); + $this->updateTitle($playlist['entries'], $playlist['current']); + return; + + case self::PAUSE: + $this->stopPlayback(); + return; + + case self::NEXT: + $this->changeTitle(self::NEXT); + $this->startPlayback(); + return; + } + break; + + case 'Playlist': + $oldIndex = json_decode($this->GetValue('Playlist'), true)['current']; + $newPlaylist = json_decode($Value, true); + $newIndex = $newPlaylist['current']; + if ($oldIndex != $newIndex) { + $this->SetValue('Progress', 0); + $this->updateTitle($newPlaylist['entries'], $newIndex); + } + + // No break. Add additional comment above this line if intentional + default: + break; } - public function Destroy() - { - //Never delete this line! - parent::Destroy(); - } - - public function ApplyChanges() - { - //Never delete this line! - parent::ApplyChanges(); - - //Set default values - if($this->GetValue('Playlist') == '') { - $this->SetValue('Playlist', file_get_contents(__DIR__ . '/playlist.json')); - $this->SetValue('Playback', self::PAUSE); - $this->SetValue('Repeat', self::REPEAT_CONTEXT); - $this->SetValue('Volume', 60); - } - } - - public function UpdateProgress() { - $this->SetValue('Progress', $this->GetValue('Progress') ); - $playlist = json_decode($this->GetValue('Playlist'), true); - $index = $playlist['current']; - $duration = $playlist['entries'][$index]['duration']; - $newValue = $this->GetValue('Progress') + 100 / $duration; - if ($newValue > 100) { - $this->changeTitle(self::NEXT); - } else { - $this->RequestAction('Progress', $newValue); - } - } - - private function startPlayback() { - $this->SetTimerInterval('ProgressTimer', 1000); - $this->SetValue('Playback', self::PLAY); - } - - private function stopPlayback() { - $this->SetTimerInterval('ProgressTimer', 0); - $this->SetValue('Playback', self::PAUSE); - } - - private function changeTitle($direction) { - $playlist = json_decode($this->GetValue('Playlist'), true); - $repeat = $this->GetValue('Repeat'); - $length = count($playlist['entries']); - if ($repeat == self::REPEAT_TRACK) { - $newIndex = $playlist['current']; - } else if ($this->GetValue('Shuffle')) { - $newIndex = random_int(0, $length-1); - } else { - $currentIndex = $playlist['current']; - if ($direction == self::NEXT) { - $newIndex = $currentIndex + 1; - } else { - $newIndex = $currentIndex - 1; - } - if ($newIndex > $length -1) { - switch($repeat) { - case self::REPEAT_OFF: - $this->RequestAction('Playback', self::PAUSE); - $newIndex = 0; - break; - - case self::REPEAT_CONTEXT: - $newIndex = 0; - break; - - case self::REPEAT_TRACK: - $newIndex = $currentIndex; - break; - } - } - if ($newIndex < 0) { - $newIndex = $length - 1; - } - }; - $this->updateTitleProgress($playlist, $newIndex); - } - - private function updateTitleProgress($playlist, $index) { - $playlist['current'] = $index; - $this->SetValue('Progress', 0); - $this->RequestAction('Playlist', json_encode($playlist)); - $this->updateTitle($playlist['entries'], $index); - } - - private function updateTitle($entries, $index) { - $this->SetValue('Artist', $entries[$index]['artist']); - $this->SetValue('Song', $entries[$index]['song']); - } - } \ No newline at end of file + $this->SetValue($Ident, $Value); + } + + public function Destroy() + { + //Never delete this line! + parent::Destroy(); + } + + public function ApplyChanges() + { + //Never delete this line! + parent::ApplyChanges(); + + //Set default values + if ($this->GetValue('Playlist') == '') { + $this->SetValue('Playlist', file_get_contents(__DIR__ . '/playlist.json')); + $this->SetValue('Playback', self::PAUSE); + $this->SetValue('Repeat', self::REPEAT_CONTEXT); + $this->SetValue('Volume', 60); + } + } + + public function UpdateProgress() + { + $this->SetValue('Progress', $this->GetValue('Progress')); + $playlist = json_decode($this->GetValue('Playlist'), true); + $index = $playlist['current']; + $duration = $playlist['entries'][$index]['duration']; + $newValue = $this->GetValue('Progress') + 100 / $duration; + if ($newValue > 100) { + $this->changeTitle(self::NEXT); + } else { + $this->RequestAction('Progress', $newValue); + } + } + + private function startPlayback() + { + $this->SetTimerInterval('ProgressTimer', 1000); + $this->SetValue('Playback', self::PLAY); + } + + private function stopPlayback() + { + $this->SetTimerInterval('ProgressTimer', 0); + $this->SetValue('Playback', self::PAUSE); + } + + private function changeTitle($direction) + { + $playlist = json_decode($this->GetValue('Playlist'), true); + $repeat = $this->GetValue('Repeat'); + $length = count($playlist['entries']); + if ($repeat == self::REPEAT_TRACK) { + $newIndex = $playlist['current']; + } elseif ($this->GetValue('Shuffle')) { + $newIndex = random_int(0, $length - 1); + } else { + $currentIndex = $playlist['current']; + if ($direction == self::NEXT) { + $newIndex = $currentIndex + 1; + } else { + $newIndex = $currentIndex - 1; + } + if ($newIndex > $length - 1) { + switch ($repeat) { + case self::REPEAT_OFF: + $this->RequestAction('Playback', self::PAUSE); + $newIndex = 0; + break; + + case self::REPEAT_CONTEXT: + $newIndex = 0; + break; + + case self::REPEAT_TRACK: + $newIndex = $currentIndex; + break; + } + } + if ($newIndex < 0) { + $newIndex = $length - 1; + } + } + $this->updateTitleProgress($playlist, $newIndex); + } + + private function updateTitleProgress($playlist, $index) + { + $playlist['current'] = $index; + $this->SetValue('Progress', 0); + $this->RequestAction('Playlist', json_encode($playlist)); + $this->updateTitle($playlist['entries'], $index); + } + + private function updateTitle($entries, $index) + { + $this->SetValue('Artist', $entries[$index]['artist']); + $this->SetValue('Song', $entries[$index]['song']); + } +} \ No newline at end of file diff --git a/Mediaplayer/playlist.json b/Mediaplayer/playlist.json index 564fee4..235487b 100644 --- a/Mediaplayer/playlist.json +++ b/Mediaplayer/playlist.json @@ -1 +1,107 @@ -{"current":6,"entries":[{"artist":"The Beatles","song":"Come Together - Remastered 2009","duration":259,"uri":"spotify:track:2EqlS6tkEnglzr7tkKAAYD"},{"artist":"The Beatles","song":"Something - Remastered 2009","duration":182,"uri":"spotify:track:0pNeVovbiZHkulpGeOx1Gj"},{"artist":"The Beatles","song":"Maxwell's Silver Hammer - Remastered 2009","duration":207,"uri":"spotify:track:2S8xyNRJX1XQdo3qnTuovI"},{"artist":"The Beatles","song":"Oh! Darling - Remastered 2009","duration":207,"uri":"spotify:track:2mxByJWOajjiVsLWjNXvDJ"},{"artist":"The Beatles","song":"Octopus's Garden - Remastered 2009","duration":170,"uri":"spotify:track:0suLngfo7rJoetk7Ub6N8l"},{"artist":"The Beatles","song":"I Want You (She's So Heavy) - Remastered 2009","duration":467,"uri":"spotify:track:3Z25k4ZF6QENy2d9YatsM5"},{"artist":"The Beatles","song":"Here Comes The Sun - Remastered 2009","duration":185,"uri":"spotify:track:6dGnYIeXmHdcikdzNNDMm2"},{"artist":"The Beatles","song":"Because - Remastered 2009","duration":165,"uri":"spotify:track:1rxoyGj1QuPoVi8fOft1Kt"},{"artist":"The Beatles","song":"You Never Give Me Your Money - Remastered 2009","duration":242,"uri":"spotify:track:1jOLTO379yIu9aMnCkpMQl"},{"artist":"The Beatles","song":"Sun King - Remastered 2009","duration":146,"uri":"spotify:track:4nwKdZID1ht0lDBJ5h2p87"},{"artist":"The Beatles","song":"Mean Mr Mustard - Remastered 2009","duration":66,"uri":"spotify:track:4JOyMhad5dD81uGYLGgKrS"},{"artist":"The Beatles","song":"Polythene Pam - Remastered 2009","duration":72,"uri":"spotify:track:1FTCA6wQwulQFokDddKE68"},{"artist":"The Beatles","song":"She Came In Through The Bathroom Window - Remastered 2009","duration":118,"uri":"spotify:track:2jtUGFsqanQ82zqDlhiKIp"},{"artist":"The Beatles","song":"Golden Slumbers - Remastered 2009","duration":91,"uri":"spotify:track:01SfTM5nfCou5gQL70r6gs"},{"artist":"The Beatles","song":"Carry That Weight - Remastered 2009","duration":96,"uri":"spotify:track:5eZrW59C3UgBhkqNlowEID"},{"artist":"The Beatles","song":"The End - Remastered 2009","duration":141,"uri":"spotify:track:5aHHf6jrqDRb1fcBmue2kn"},{"artist":"The Beatles","song":"Her Majesty - Remastered 2009","duration":25,"uri":"spotify:track:6UCFZ9ZOFRxK8oak7MdPZu"}]} \ No newline at end of file +{ + "current": 6, + "entries": [ + { + "artist": "The Beatles", + "song": "Come Together - Remastered 2009", + "duration": 259, + "uri": "spotify:track:2EqlS6tkEnglzr7tkKAAYD" + }, + { + "artist": "The Beatles", + "song": "Something - Remastered 2009", + "duration": 182, + "uri": "spotify:track:0pNeVovbiZHkulpGeOx1Gj" + }, + { + "artist": "The Beatles", + "song": "Maxwell's Silver Hammer - Remastered 2009", + "duration": 207, + "uri": "spotify:track:2S8xyNRJX1XQdo3qnTuovI" + }, + { + "artist": "The Beatles", + "song": "Oh! Darling - Remastered 2009", + "duration": 207, + "uri": "spotify:track:2mxByJWOajjiVsLWjNXvDJ" + }, + { + "artist": "The Beatles", + "song": "Octopus's Garden - Remastered 2009", + "duration": 170, + "uri": "spotify:track:0suLngfo7rJoetk7Ub6N8l" + }, + { + "artist": "The Beatles", + "song": "I Want You (She's So Heavy) - Remastered 2009", + "duration": 467, + "uri": "spotify:track:3Z25k4ZF6QENy2d9YatsM5" + }, + { + "artist": "The Beatles", + "song": "Here Comes The Sun - Remastered 2009", + "duration": 185, + "uri": "spotify:track:6dGnYIeXmHdcikdzNNDMm2" + }, + { + "artist": "The Beatles", + "song": "Because - Remastered 2009", + "duration": 165, + "uri": "spotify:track:1rxoyGj1QuPoVi8fOft1Kt" + }, + { + "artist": "The Beatles", + "song": "You Never Give Me Your Money - Remastered 2009", + "duration": 242, + "uri": "spotify:track:1jOLTO379yIu9aMnCkpMQl" + }, + { + "artist": "The Beatles", + "song": "Sun King - Remastered 2009", + "duration": 146, + "uri": "spotify:track:4nwKdZID1ht0lDBJ5h2p87" + }, + { + "artist": "The Beatles", + "song": "Mean Mr Mustard - Remastered 2009", + "duration": 66, + "uri": "spotify:track:4JOyMhad5dD81uGYLGgKrS" + }, + { + "artist": "The Beatles", + "song": "Polythene Pam - Remastered 2009", + "duration": 72, + "uri": "spotify:track:1FTCA6wQwulQFokDddKE68" + }, + { + "artist": "The Beatles", + "song": "She Came In Through The Bathroom Window - Remastered 2009", + "duration": 118, + "uri": "spotify:track:2jtUGFsqanQ82zqDlhiKIp" + }, + { + "artist": "The Beatles", + "song": "Golden Slumbers - Remastered 2009", + "duration": 91, + "uri": "spotify:track:01SfTM5nfCou5gQL70r6gs" + }, + { + "artist": "The Beatles", + "song": "Carry That Weight - Remastered 2009", + "duration": 96, + "uri": "spotify:track:5eZrW59C3UgBhkqNlowEID" + }, + { + "artist": "The Beatles", + "song": "The End - Remastered 2009", + "duration": 141, + "uri": "spotify:track:5aHHf6jrqDRb1fcBmue2kn" + }, + { + "artist": "The Beatles", + "song": "Her Majesty - Remastered 2009", + "duration": 25, + "uri": "spotify:track:6UCFZ9ZOFRxK8oak7MdPZu" + } + ] +} \ No newline at end of file diff --git a/PVAnlage/README.md b/PVAnlage/README.md deleted file mode 100644 index 16d350a..0000000 --- a/PVAnlage/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# PVAnlage -Beschreibung des Moduls. - -### Inhaltsverzeichnis - -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'PVAnlage'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'PVAnlage'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file diff --git a/PVAnlage/locale.json b/PVAnlage/locale.json deleted file mode 100644 index 20e897f..0000000 --- a/PVAnlage/locale.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "translations": { - "de": { - "Capacity": "Leistung", - "Production": "Erzeugung" - } - } -} \ No newline at end of file diff --git a/PVAnlage/module.php b/PVAnlage/module.php deleted file mode 100644 index bc13147..0000000 --- a/PVAnlage/module.php +++ /dev/null @@ -1,31 +0,0 @@ -RegisterPropertyInteger("Capacity", 10); - } - - public function ApplyChanges() - { - $profileName = "WattSlider" . $this->ReadPropertyInteger("Capacity"); - if (!IPS_VariableProfileExists($profileName)) { - IPS_CreateVariableProfile($profileName, VARIABLETYPE_FLOAT); - IPS_SetVariableProfileText($profileName, "", " W"); - IPS_SetVariableProfileValues($profileName, 0,$this->ReadPropertyInteger("Capacity") * 1000, 50); - IPS_SetVariableProfileDigits($profileName, 1); - } - - $this->RegisterVariableFloat("Production", $this->Translate("Production"), $profileName, 0); - $this->EnableAction("Production"); - } - - public function RequestAction($Ident, $Value) - { - $this->SetValue($Ident, $Value); - } - } \ No newline at end of file diff --git a/PVSystem/README.md b/PVSystem/README.md new file mode 100644 index 0000000..06d3fa1 --- /dev/null +++ b/PVSystem/README.md @@ -0,0 +1,5 @@ +# PV-Anlage + +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/pv-anlage-simulation/) + +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/pv-system-simulation/) \ No newline at end of file diff --git a/PVAnlage/form.json b/PVSystem/form.json similarity index 100% rename from PVAnlage/form.json rename to PVSystem/form.json diff --git a/PVSystem/locale.json b/PVSystem/locale.json new file mode 100644 index 0000000..4faac88 --- /dev/null +++ b/PVSystem/locale.json @@ -0,0 +1,9 @@ +{ + "translations": { + "de": { + "Capacity": "Leistung", + "Production": "Erzeugung", + "PV-System (Simulation)": "PV-Anlage (Simulation)" + } + } +} \ No newline at end of file diff --git a/PVAnlage/module.json b/PVSystem/module.json similarity index 74% rename from PVAnlage/module.json rename to PVSystem/module.json index 3ee5123..ea9ba40 100644 --- a/PVAnlage/module.json +++ b/PVSystem/module.json @@ -1,14 +1,14 @@ { "id": "{8CCD3592-047A-FE04-1EF2-2884BD90E575}", - "name": "PVAnlage", + "name": "PVSystem", "type": 3, "vendor": "", "aliases": [ - "PV-Anlage (Simulation)" + "PV-System (Simulation)" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/PVSystem/module.php b/PVSystem/module.php new file mode 100644 index 0000000..6aaa2d4 --- /dev/null +++ b/PVSystem/module.php @@ -0,0 +1,31 @@ +RegisterPropertyInteger('Capacity', 10); + } + + public function ApplyChanges() + { + $profileName = 'WattSlider' . $this->ReadPropertyInteger('Capacity'); + if (!IPS_VariableProfileExists($profileName)) { + IPS_CreateVariableProfile($profileName, VARIABLETYPE_FLOAT); + IPS_SetVariableProfileText($profileName, '', ' W'); + IPS_SetVariableProfileValues($profileName, 0, $this->ReadPropertyInteger('Capacity') * 1000, 50); + IPS_SetVariableProfileDigits($profileName, 1); + } + + $this->RegisterVariableFloat('Production', $this->Translate('Production'), $profileName, 0); + $this->EnableAction('Production'); + } + + public function RequestAction($Ident, $Value) + { + $this->SetValue($Ident, $Value); + } +} \ No newline at end of file diff --git a/README.md b/README.md index a7fbf8d..8db25f8 100644 --- a/README.md +++ b/README.md @@ -2,23 +2,23 @@ Folgende Module beinhaltet das VirtuelleModule Repository: -- __PVAnlage__ ([Dokumentation](PVAnlage)) - Kurze Beschreibung des Moduls. +- __PVAnlage__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/pv-anlage-simulation/)) + Simulation einer PV-Anlage. -- __Heizstab__ ([Dokumentation](Heizstab)) - Kurze Beschreibung des Moduls. +- __Heizstab__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/heizstab-simulation/)) + Simulation eines Heizstabes. -- __VerbrauchKosten__ ([Dokumentation](VerbrauchKosten)) - Kurze Beschreibung des Moduls. +- __VerbrauchKosten__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/verbrauch-kosten/)) + Berechnet die Kosten anhand des Verbrauchs -- __Licht__ ([Dokumentation](Licht)) - Kurze Beschreibung des Moduls. +- __Licht__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/licht-simulation/)) + Simuliert ein Licht. -- __Mediaplayer__ ([Dokumentation](Mediaplayer)) - Kurze Beschreibung des Moduls. +- __Mediaplayer__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/mediaplayer-simulation/)) + Simuliert einen Mediaplayer. -- __Thermostat__ ([Dokumentation](Thermostat)) - Kurze Beschreibung des Moduls. +- __Thermostat__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/thermostat-simulation/)) + Simuliert ein Thermostat. -- __Shutter__ ([Dokumentation](Shutter)) - Kurze Beschreibung des Moduls. \ No newline at end of file +- __Shutter__ ([Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/rollladen-simulation/)) + Simmuliert ein Rollladen. \ No newline at end of file diff --git a/Shutter/README.md b/Shutter/README.md index 6d268aa..fb72423 100644 --- a/Shutter/README.md +++ b/Shutter/README.md @@ -1,67 +1,5 @@ # VirtualShutter -Beschreibung des Moduls. -### Inhaltsverzeichnis +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/rollladen-simulation/) -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'VirtualShutter'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VirtualShutter'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/shutter-simulation/) \ No newline at end of file diff --git a/Shutter/form.json b/Shutter/form.json index 7a73a41..9e26dfe 100644 --- a/Shutter/form.json +++ b/Shutter/form.json @@ -1,2 +1 @@ -{ -} \ No newline at end of file +{} \ No newline at end of file diff --git a/Shutter/locale.json b/Shutter/locale.json index 6c83d1e..94c0de9 100644 --- a/Shutter/locale.json +++ b/Shutter/locale.json @@ -2,7 +2,8 @@ "translations": { "de": { "Shutter": "Jalousie", - "Lamella": "Lamelle" + "Lamella": "Lamelle", + "Shutter (Simulation)": "Rollladen (Simulation)" } } } \ No newline at end of file diff --git a/Shutter/module.json b/Shutter/module.json index 384f3b1..2411f08 100644 --- a/Shutter/module.json +++ b/Shutter/module.json @@ -4,11 +4,11 @@ "type": 3, "vendor": "", "aliases": [ - "Rollo (Simulation)" + "Shutter (Simulation)" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/Shutter/module.php b/Shutter/module.php index 378719f..db28c8b 100644 --- a/Shutter/module.php +++ b/Shutter/module.php @@ -1,26 +1,25 @@ RegisterVariableInteger("Shutter", $this->Translate("Shutter"), "~Shutter", 0); - $this->EnableAction("Shutter"); - $this->RegisterVariableInteger("Lamella", $this->Translate("Lamella"), "~Lamella", 1); - $this->EnableAction("Lamella"); - } + $this->RegisterVariableInteger('Shutter', $this->Translate('Shutter'), '~Shutter', 0); + $this->EnableAction('Shutter'); + $this->RegisterVariableInteger('Lamella', $this->Translate('Lamella'), '~Lamella', 1); + $this->EnableAction('Lamella'); + } - public function ApplyChanges() - { - parent::ApplyChanges(); - } + public function ApplyChanges() + { + parent::ApplyChanges(); + } - public function RequestAction($Ident, $Value) - { - $this->SetValue($Ident, $Value); - } - } \ No newline at end of file + public function RequestAction($Ident, $Value) + { + $this->SetValue($Ident, $Value); + } +} \ No newline at end of file diff --git a/Thermostat/README.md b/Thermostat/README.md index e181136..2b85627 100644 --- a/Thermostat/README.md +++ b/Thermostat/README.md @@ -1,67 +1,5 @@ # VirtualThermostat -Beschreibung des Moduls. -### Inhaltsverzeichnis +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/thermostat-simulation/) -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'VirtualThermostat'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VirtualThermostat'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/thermostat-simulation/) \ No newline at end of file diff --git a/Thermostat/locale.json b/Thermostat/locale.json index 5b439ac..1f032b3 100644 --- a/Thermostat/locale.json +++ b/Thermostat/locale.json @@ -2,7 +2,10 @@ "translations": { "de": { "Set Point Temperature": "Soll Temperatur", - "Current Temperature": "Ist Temperatur" + "Current Temperature": "Ist Temperatur", + "Create logged values for current temperature": "Erstelle geloggte Werte für die aktuelle Temperatur", + "Hour": "Stunde", + "Value": "Wert" } } } \ No newline at end of file diff --git a/Thermostat/module.json b/Thermostat/module.json index c654d65..dad3085 100644 --- a/Thermostat/module.json +++ b/Thermostat/module.json @@ -9,6 +9,6 @@ "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/Thermostat/module.php b/Thermostat/module.php index c2c542c..b39d088 100644 --- a/Thermostat/module.php +++ b/Thermostat/module.php @@ -1,150 +1,150 @@ RegisterVariableFloat('SetPoint', $this->Translate('Set Point Temprature'), '~Temperature.Room', 0); - $this->EnableAction('SetPoint'); - $this->RegisterVariableFloat('Current', $this->Translate('Current Temperature'), '~Temperature.Room', 1); + $this->RegisterVariableFloat('SetPoint', $this->Translate('Set Point Temperature'), '~Temperature.Room', 0); + $this->EnableAction('SetPoint'); + $this->RegisterVariableFloat('Current', $this->Translate('Current Temperature'), '~Temperature.Room', 1); - $this->RegisterPropertyBoolean('LogCurrentTemperature', false); - // Default values based on 16th October 2023, measured by WebFront Demo - $this->RegisterPropertyString('HourValues', json_encode([ - [ - 'value' => 4.9 - ], - [ - 'value' => 4.9 - ], - [ - 'value' => 4.6 - ], - [ - 'value' => 4.5 - ], - [ - 'value' => 4.4 - ], - [ - 'value' => 4.5 - ], - [ - 'value' => 4.8 - ], - [ - 'value' => 5.3 - ], - [ - 'value' => 5.2 - ], - [ - 'value' => 6.0 - ], - [ - 'value' => 7.3 - ], - [ - 'value' => 8.3 - ], - [ - 'value' => 8.7 - ], - [ - 'value' => 9.4 - ], - [ - 'value' => 10.1 - ], - [ - 'value' => 10.1 - ], - [ - 'value' => 9.9 - ], - [ - 'value' => 9.5 - ], - [ - 'value' => 8.5 - ], - [ - 'value' => 7.7 - ], - [ - 'value' => 7.2 - ], - [ - 'value' => 6.0 - ], - [ - 'value' => 5.7 - ], - [ - 'value' => 5.2 - ], - ])); - $this->RegisterTimer('AddValues', 0, 'VM_AddValues(' . $this->InstanceID . ');'); - } - - public function ApplyChanges() - { - parent::ApplyChanges(); - if ($this->GetValue('Current') == 0) { - $this->SetValue('Current', 19.5); - $this->SetValue('SetPoint', 22.0); - } + $this->RegisterPropertyBoolean('LogCurrentTemperature', false); + // Default values based on 16th October 2023, measured by WebFront Demo + $this->RegisterPropertyString('HourValues', json_encode([ + [ + 'value' => 4.9 + ], + [ + 'value' => 4.9 + ], + [ + 'value' => 4.6 + ], + [ + 'value' => 4.5 + ], + [ + 'value' => 4.4 + ], + [ + 'value' => 4.5 + ], + [ + 'value' => 4.8 + ], + [ + 'value' => 5.3 + ], + [ + 'value' => 5.2 + ], + [ + 'value' => 6.0 + ], + [ + 'value' => 7.3 + ], + [ + 'value' => 8.3 + ], + [ + 'value' => 8.7 + ], + [ + 'value' => 9.4 + ], + [ + 'value' => 10.1 + ], + [ + 'value' => 10.1 + ], + [ + 'value' => 9.9 + ], + [ + 'value' => 9.5 + ], + [ + 'value' => 8.5 + ], + [ + 'value' => 7.7 + ], + [ + 'value' => 7.2 + ], + [ + 'value' => 6.0 + ], + [ + 'value' => 5.7 + ], + [ + 'value' => 5.2 + ], + ])); + $this->RegisterTimer('AddValues', 0, 'VG_AddValues(' . $this->InstanceID . ');'); + } - $logTemperature = $this->ReadPropertyBoolean('LogCurrentTemperature'); - $this->SetTimerInterval('AddValues', $logTemperature ? 60 * 60 * 1000 : 0); - if ($logTemperature) { - $this->AddValues(); - } + public function ApplyChanges() + { + parent::ApplyChanges(); + if ($this->GetValue('Current') == 0) { + $this->SetValue('Current', 19.5); + $this->SetValue('SetPoint', 22.0); } - public function RequestAction($Ident, $Value) - { - $this->SetValue($Ident, $Value); + $logTemperature = $this->ReadPropertyBoolean('LogCurrentTemperature'); + $this->SetTimerInterval('AddValues', $logTemperature ? 60 * 60 * 1000 : 0); + if ($logTemperature) { + $this->AddValues(); } + } + + public function RequestAction($Ident, $Value) + { + $this->SetValue($Ident, $Value); + } - public function AddValues() { - if (!$this->ReadPropertyBoolean('LogCurrentTemperature')) { - return; - } - $now = time(); - $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; - $variableID = $this->GetIDForIdent('Current'); - if (!AC_GetLoggingStatus($archiveID, $variableID)) { - AC_SetLoggingStatus($archiveID, $variableID, true); - AC_SetAggregationType($archiveID, $variableID, 0); - // Delete initially logged value, so we can properly fill with dummy values - AC_DeleteVariableData($archiveID, $variableID, $now - (24 * 60 * 60), 0); - } - // Check for previous values within the last 30 days - $lastLoggedTimestamp = $now - (30 * 24 * 60 * 60); - $lastLoggedValues = AC_GetLoggedValues($archiveID, $variableID, $lastLoggedTimestamp, 0, 1); - if (count($lastLoggedValues) > 0) { - $lastLoggedTimestamp = $lastLoggedValues[0]['TimeStamp']; - } - $values = []; - $lastLoggedTimestamp -= $lastLoggedTimestamp % 3600; - $lastLoggedTimestamp+= (60*60); - $hourValues = json_decode($this->ReadPropertyString('HourValues'), true); - $dateTime = new DateTime(); - while($lastLoggedTimestamp < $now) { - $dateTime->setTimestamp($lastLoggedTimestamp); - $nextValue = $hourValues[intval($dateTime->format('G'))]['value']; - $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => $nextValue]; - $lastLoggedTimestamp+= (60*60); - } - if (count($values) > 0) { - AC_AddLoggedValues($archiveID, $variableID, $values); - AC_ReAggregateVariable($archiveID, $variableID); - $this->SetValue('Current', $values[count($values) - 1]['Value']); - } + public function AddValues() + { + if (!$this->ReadPropertyBoolean('LogCurrentTemperature')) { + return; + } + $now = time(); + $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; + $variableID = $this->GetIDForIdent('Current'); + if (!AC_GetLoggingStatus($archiveID, $variableID)) { + AC_SetLoggingStatus($archiveID, $variableID, true); + AC_SetAggregationType($archiveID, $variableID, 0); + // Delete initially logged value, so we can properly fill with dummy values + AC_DeleteVariableData($archiveID, $variableID, $now - (24 * 60 * 60), 0); + } + // Check for previous values within the last 30 days + $lastLoggedTimestamp = $now - (30 * 24 * 60 * 60); + $lastLoggedValues = AC_GetLoggedValues($archiveID, $variableID, $lastLoggedTimestamp, 0, 1); + if (count($lastLoggedValues) > 0) { + $lastLoggedTimestamp = $lastLoggedValues[0]['TimeStamp']; + } + $values = []; + $lastLoggedTimestamp -= $lastLoggedTimestamp % 3600; + $lastLoggedTimestamp += (60 * 60); + $hourValues = json_decode($this->ReadPropertyString('HourValues'), true); + $dateTime = new DateTime(); + while ($lastLoggedTimestamp < $now) { + $dateTime->setTimestamp($lastLoggedTimestamp); + $nextValue = $hourValues[intval($dateTime->format('G'))]['value']; + $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => $nextValue]; + $lastLoggedTimestamp += (60 * 60); + } + if (count($values) > 0) { + AC_AddLoggedValues($archiveID, $variableID, $values); + AC_ReAggregateVariable($archiveID, $variableID); + $this->SetValue('Current', $values[count($values) - 1]['Value']); } - } \ No newline at end of file + } +} diff --git a/VerbrauchKosten/README.md b/VerbrauchKosten/README.md deleted file mode 100644 index 70fc8aa..0000000 --- a/VerbrauchKosten/README.md +++ /dev/null @@ -1,67 +0,0 @@ -# VerbrauchKosten -Beschreibung des Moduls. - -### Inhaltsverzeichnis - -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'VerbrauchKosten'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VerbrauchKosten'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file diff --git a/VerbrauchKosten/form.json b/VerbrauchKosten/form.json deleted file mode 100644 index 7a73a41..0000000 --- a/VerbrauchKosten/form.json +++ /dev/null @@ -1,2 +0,0 @@ -{ -} \ No newline at end of file diff --git a/VerbrauchKosten/module.php b/VerbrauchKosten/module.php deleted file mode 100644 index af9fb03..0000000 --- a/VerbrauchKosten/module.php +++ /dev/null @@ -1,42 +0,0 @@ -RegisterVariableFloat("Consumption", $this->Translate("StandBy Consumption"), $profileName, 0); - $this->EnableAction("Consumption"); - - $profileName = "EuroCent"; - if (!IPS_VariableProfileExists($profileName)) { - IPS_CreateVariableProfile($profileName, VARIABLETYPE_FLOAT); - IPS_SetVariableProfileText($profileName, "", " €"); - IPS_SetVariableProfileValues($profileName, 0,10, 0.01); - IPS_SetVariableProfileDigits($profileName, 2); - IPS_SetVariableProfileIcon($profileName, "Repeat"); - } - - $this->RegisterVariableFloat("CostPerKiloWatt", $this->Translate("Cost per kWh"), "EuroCent", 1); - $this->EnableAction("CostPerKiloWatt"); - - $this->RegisterVariableFloat("TotalCostPerYear", $this->Translate("Total cost per year"), "~Euro", 2); - } - - public function RequestAction($Ident, $Value) - { - $this->SetValue($Ident, $Value); - $this->SetValue("TotalCostPerYear", $this->GetValue("Consumption")/1000*$this->GetValue("CostPerKiloWatt")*24*365); - } - } \ No newline at end of file diff --git a/Virtual Counter/README.md b/Virtual Counter/README.md index 0540cae..ffee051 100644 --- a/Virtual Counter/README.md +++ b/Virtual Counter/README.md @@ -1,67 +1,5 @@ # VirtualCounter -Beschreibung des Moduls. -### Inhaltsverzeichnis +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/zaehler-simulation/) -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 - -* - -### 2. Voraussetzungen - -- IP-Symcon ab Version 6.0 - -### 3. Software-Installation - -* Über den Module Store das 'VirtualCounter'-Modul installieren. -* Alternativ über das Module Control folgende URL hinzufügen - -### 4. Einrichten der Instanzen in IP-Symcon - - Unter 'Instanz hinzufügen' kann das 'VirtualCounter'-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) - -__Konfigurationsseite__: - -Name | Beschreibung --------- | ------------------ - | - | - -### 5. Statusvariablen und Profile - -Die Statusvariablen/Kategorien werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen. - -#### Statusvariablen - -Name | Typ | Beschreibung ------- | ------- | ------------ - | | - | | - -#### Profile - -Name | Typ ------- | ------- - | - | - -### 6. WebFront - -Die Funktionalität, die das Modul im WebFront bietet. - -### 7. PHP-Befehlsreferenz - -`boolean VM_BeispielFunktion(integer $InstanzID);` -Erklärung der Funktion. - -Beispiel: -`VM_BeispielFunktion(12345);` \ No newline at end of file +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/counter-simulation/) \ No newline at end of file diff --git a/Virtual Counter/locale.json b/Virtual Counter/locale.json index 4ab597a..6c42f5e 100644 --- a/Virtual Counter/locale.json +++ b/Virtual Counter/locale.json @@ -8,7 +8,8 @@ "Max Value per hour": "Maximaler Wert pro Stunde", "Maximum Distance between two following values": "Maximaler Abstand zwischen zwei folgenden Werten", "Create Chart": "Erstelle Graphen", - "Use a different profile for each variable": "Verwende für jede Variable ein anderes Profil" + "Use a different profile for each variable": "Verwende für jede Variable ein anderes Profil", + "Counter (Simulation)": "Zähler (Simulation)" } } } \ No newline at end of file diff --git a/Virtual Counter/module.php b/Virtual Counter/module.php index d7bde23..831e290 100644 --- a/Virtual Counter/module.php +++ b/Virtual Counter/module.php @@ -1,128 +1,131 @@ RegisterPropertyInteger('NumberOfCounters', 50); - $this->RegisterPropertyFloat('MaxHourValue', 30); - $this->RegisterPropertyFloat('MinHourValue', 10); - $this->RegisterPropertyFloat('MaxDistanceToNextValue', 5); - $this->RegisterPropertyBoolean('DifferentProfiles', false); + $this->RegisterPropertyInteger('NumberOfCounters', 50); + $this->RegisterPropertyFloat('MaxHourValue', 30); + $this->RegisterPropertyFloat('MinHourValue', 10); + $this->RegisterPropertyFloat('MaxDistanceToNextValue', 5); + $this->RegisterPropertyBoolean('DifferentProfiles', false); - $this->RegisterTimer('AddValues', 1000 * 60 * 60, 'VC_AddValues(' . $this->InstanceID . ');'); - } + $this->RegisterTimer('AddValues', 1000 * 60 * 60, 'VC_AddValues(' . $this->InstanceID . ');'); + } - public function ApplyChanges() - { - parent::ApplyChanges(); + public function ApplyChanges() + { + parent::ApplyChanges(); - for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { - $profile = '~Electricity'; - $individualProfileName = 'VirtualCounter' . $this->InstanceID . '-' . $i; - if ($this->ReadPropertyBoolean('DifferentProfiles')) { - $profile = $individualProfileName; - if (!IPS_VariableProfileExists($profile)) { - IPS_CreateVariableProfile($profile, 2); - IPS_SetVariableProfileDigits($profile, 2); - IPS_SetVariableProfileIcon($profile, 'Electricity'); - IPS_SetVariableProfileText($profile, '', 'kWh'); - } - } - else if (IPS_VariableProfileExists($individualProfileName)) { - IPS_DeleteVariableProfile($individualProfileName); + for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { + $profile = '~Electricity'; + $individualProfileName = 'VirtualCounter' . $this->InstanceID . '-' . $i; + if ($this->ReadPropertyBoolean('DifferentProfiles')) { + $profile = $individualProfileName; + if (!IPS_VariableProfileExists($profile)) { + IPS_CreateVariableProfile($profile, 2); + IPS_SetVariableProfileDigits($profile, 2); + IPS_SetVariableProfileIcon($profile, 'Electricity'); + IPS_SetVariableProfileText($profile, '', 'kWh'); } - $this->RegisterVariableFloat('Counter' . $i, $this->Translate('Counter') . ' ' . $i, $profile, 0); } + elseif (IPS_VariableProfileExists($individualProfileName)) { + IPS_DeleteVariableProfile($individualProfileName); + } + $this->RegisterVariableFloat('Counter' . $i, $this->Translate('Counter') . ' ' . $i, $profile, 0); + } - $i = $this->ReadPropertyInteger('NumberOfCounters') + 1; - while(@$this->GetIDForIdent('Counter' . $i) !== false) { - $this->UnregisterVariable('Counter' . $i); - - $individualProfileName = 'VirtualCounter' . $this->InstanceID . '-' . $i; - if (IPS_VariableProfileExists($individualProfileName)) { - IPS_DeleteVariableProfile($individualProfileName); - } + $i = $this->ReadPropertyInteger('NumberOfCounters') + 1; + while (@$this->GetIDForIdent('Counter' . $i) !== false) { + $this->UnregisterVariable('Counter' . $i); - $i++; + $individualProfileName = 'VirtualCounter' . $this->InstanceID . '-' . $i; + if (IPS_VariableProfileExists($individualProfileName)) { + IPS_DeleteVariableProfile($individualProfileName); } - $this->AddValues(); + $i++; } - public function AddValues() { - $now = time(); - $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; - for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { - $counterID = $this->GetIDForIdent('Counter' . $i); - if (!AC_GetLoggingStatus($archiveID, $counterID)) { - AC_SetLoggingStatus($archiveID, $counterID, true); - AC_SetAggregationType($archiveID, $counterID, 1); - // Delete initially logged value, so we can properly fill with dummy values - AC_DeleteVariableData($archiveID, $counterID, $now - (24 * 60 * 60), 0); - } - // Check for previous values within the last 30 days - $lastLoggedTimestamp = $now - (30 * 24 * 60 * 60); - $lastLoggedValue = 0; - $lastLoggedDiff = $this->GetRandomFloat($this->ReadPropertyFloat('MinHourValue'), $this->ReadPropertyFloat('MaxHourValue')); - $lastLoggedValues = AC_GetLoggedValues($archiveID, $counterID, $lastLoggedTimestamp, 0, 2); - if (count($lastLoggedValues) > 0) { - $lastLoggedTimestamp = $lastLoggedValues[0]['TimeStamp']; - $lastLoggedValue = $lastLoggedValues[0]['Value']; - if (count($lastLoggedValues) > 1) { - $lastLoggedDiff = $lastLoggedValues[1]['Value'] - $lastLoggedValues[0]['Value']; - } - } - else { - $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => 0]; - } - $values = []; - $lastLoggedTimestamp+= (60*60); - while($lastLoggedTimestamp < $now) { - $nextValue = $lastLoggedValue + $this->GetRandomFloat( - max( - $this->ReadPropertyFloat('MinHourValue'), - $lastLoggedDiff - $this->ReadPropertyFloat('MaxDistanceToNextValue') - ), - min( - $this->ReadPropertyFloat('MaxHourValue'), - $lastLoggedDiff + $this->ReadPropertyFloat('MaxDistanceToNextValue') - ) - ); - $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => $nextValue]; - $lastLoggedTimestamp+= (60*60); - $lastLoggedDiff = $nextValue - $lastLoggedValue; - $lastLoggedValue = $nextValue; + $this->AddValues(); + } + + public function AddValues() + { + $now = time(); + $archiveID = IPS_GetInstanceListByModuleID('{43192F0B-135B-4CE7-A0A7-1475603F3060}')[0]; + for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { + $counterID = $this->GetIDForIdent('Counter' . $i); + if (!AC_GetLoggingStatus($archiveID, $counterID)) { + AC_SetLoggingStatus($archiveID, $counterID, true); + AC_SetAggregationType($archiveID, $counterID, 1); + // Delete initially logged value, so we can properly fill with dummy values + AC_DeleteVariableData($archiveID, $counterID, $now - (24 * 60 * 60), 0); + } + // Check for previous values within the last 30 days + $lastLoggedTimestamp = $now - (30 * 24 * 60 * 60); + $lastLoggedValue = 0; + $lastLoggedDiff = $this->GetRandomFloat($this->ReadPropertyFloat('MinHourValue'), $this->ReadPropertyFloat('MaxHourValue')); + $lastLoggedValues = AC_GetLoggedValues($archiveID, $counterID, $lastLoggedTimestamp, 0, 2); + if (count($lastLoggedValues) > 0) { + $lastLoggedTimestamp = $lastLoggedValues[0]['TimeStamp']; + $lastLoggedValue = $lastLoggedValues[0]['Value']; + if (count($lastLoggedValues) > 1) { + $lastLoggedDiff = $lastLoggedValues[1]['Value'] - $lastLoggedValues[0]['Value']; } - AC_AddLoggedValues($archiveID, $counterID, $values); - AC_ReAggregateVariable($archiveID, $counterID); - $this->SetValue('Counter' . $i, $lastLoggedValue); } - } - - public function CreateChart() { - $mediaID = IPS_CreateMedia(4); - IPS_SetParent($mediaID, $this->InstanceID); - IPS_SetName($mediaID, $this->Translate('Chart')); - IPS_SetMediaFile($mediaID, "media/$mediaID.chart", false); - $datasets = []; - for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { - $color = '#' . str_pad(dechex(rand(0, 0xffffff)), 6, '0', STR_PAD_LEFT); - $datasets[] = [ - 'variableID' => $this->GetIDForIdent('Counter' . $i), - 'fillColor' => $color, - 'strokeColor' => $color, - 'timeOffset' => 0, - 'side' => 'left', - ]; + else { + $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => 0]; } - IPS_SetMediaContent($mediaID, base64_encode(json_encode([ 'datasets' => $datasets ]))); + $values = []; + $lastLoggedTimestamp += (60 * 60); + while ($lastLoggedTimestamp < $now) { + $nextValue = $lastLoggedValue + $this->GetRandomFloat( + max( + $this->ReadPropertyFloat('MinHourValue'), + $lastLoggedDiff - $this->ReadPropertyFloat('MaxDistanceToNextValue') + ), + min( + $this->ReadPropertyFloat('MaxHourValue'), + $lastLoggedDiff + $this->ReadPropertyFloat('MaxDistanceToNextValue') + ) + ); + $values[] = ['TimeStamp' => $lastLoggedTimestamp, 'Value' => $nextValue]; + $lastLoggedTimestamp += (60 * 60); + $lastLoggedDiff = $nextValue - $lastLoggedValue; + $lastLoggedValue = $nextValue; + } + AC_AddLoggedValues($archiveID, $counterID, $values); + AC_ReAggregateVariable($archiveID, $counterID); + $this->SetValue('Counter' . $i, $lastLoggedValue); } + } - private function GetRandomFloat($min, $max) { - return $min + ($max - $min) * lcg_value(); + public function CreateChart() + { + $mediaID = IPS_CreateMedia(4); + IPS_SetParent($mediaID, $this->InstanceID); + IPS_SetName($mediaID, $this->Translate('Chart')); + IPS_SetMediaFile($mediaID, "media/$mediaID.chart", false); + $datasets = []; + for ($i = 1; $i <= $this->ReadPropertyInteger('NumberOfCounters'); $i++) { + $color = '#' . str_pad(dechex(rand(0, 0xffffff)), 6, '0', STR_PAD_LEFT); + $datasets[] = [ + 'variableID' => $this->GetIDForIdent('Counter' . $i), + 'fillColor' => $color, + 'strokeColor' => $color, + 'timeOffset' => 0, + 'side' => 'left', + ]; } - } \ No newline at end of file + IPS_SetMediaContent($mediaID, base64_encode(json_encode(['datasets' => $datasets]))); + } + + private function GetRandomFloat($min, $max) + { + return $min + ($max - $min) * lcg_value(); + } +} \ No newline at end of file diff --git a/Virtual Light/README.md b/Virtual Light/README.md new file mode 100644 index 0000000..94cb115 --- /dev/null +++ b/Virtual Light/README.md @@ -0,0 +1,5 @@ +# VirtualLight + +[Link zur deutschen Dokumentation](https://www.symcon.de/de/service/dokumentation/modulreferenz/virtuelle-geraete/licht-simulation/) + +[Link to the english documentation](https://www.symcon.de/en/service/documentation/module-reference/virtual-devices/light-simulation/) \ No newline at end of file diff --git a/Virtual Light/form.json b/Virtual Light/form.json new file mode 100644 index 0000000..9e26dfe --- /dev/null +++ b/Virtual Light/form.json @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/Licht/locale.json b/Virtual Light/locale.json similarity index 61% rename from Licht/locale.json rename to Virtual Light/locale.json index 8289941..563e36c 100644 --- a/Licht/locale.json +++ b/Virtual Light/locale.json @@ -4,7 +4,8 @@ "Status": "Status", "Intensity": "Helligkeit", "Color": "Farbe", - "Temperature": "Farbtemperatur" + "Temperature": "Farbtemperatur", + "Light (Simulation)": "Licht (Simulation)" } } } \ No newline at end of file diff --git a/Licht/module.json b/Virtual Light/module.json similarity index 84% rename from Licht/module.json rename to Virtual Light/module.json index 64d4d13..f7d5b43 100644 --- a/Licht/module.json +++ b/Virtual Light/module.json @@ -4,11 +4,11 @@ "type": 3, "vendor": "", "aliases": [ - "Licht (Simulation)" + "Light (Simulation)" ], "parentRequirements": [], "childRequirements": [], "implemented": [], - "prefix": "VM", + "prefix": "VG", "url": "https://www.symcon.de" } \ No newline at end of file diff --git a/Virtual Light/module.php b/Virtual Light/module.php new file mode 100644 index 0000000..692abf5 --- /dev/null +++ b/Virtual Light/module.php @@ -0,0 +1,35 @@ +RegisterVariableBoolean('Status', $this->Translate('Status'), '~Switch', 0); + $this->EnableAction('Status'); + $this->RegisterVariableInteger('Intensity', $this->Translate('Intensity'), '~Intensity.100', 1); + $this->EnableAction('Intensity'); + $this->RegisterVariableInteger('Color', $this->Translate('Color'), '~HexColor', 2); + $this->EnableAction('Color'); + $this->RegisterVariableInteger('Temperature', $this->Translate('Temperature'), '~TWColor', 2); + $this->EnableAction('Temperature'); + } + + public function ApplyChanges() + { + parent::ApplyChanges(); + //Set default values + if ($this->GetValue('Color') == 0) { + $this->SetValue('Color', 3328428); + $this->SetValue('Intensity', 40); + $this->SetValue('Temperature', 3408); + } + } + + public function RequestAction($Ident, $Value) + { + $this->SetValue($Ident, $Value); + } +} \ No newline at end of file diff --git a/tests/VirtuelleModuleValidationTest.php b/tests/VirtuelleModuleValidationTest.php new file mode 100644 index 0000000..0f818f0 --- /dev/null +++ b/tests/VirtuelleModuleValidationTest.php @@ -0,0 +1,48 @@ +validateLibrary(__DIR__ . '/..'); + } + public function testValidateECarModule(): void + { + $this->validateModule(__DIR__ . '/../E-Car'); + } + public function testValidateHeaterModule(): void + { + $this->validateModule(__DIR__ . '/../Heater'); + } + public function testValidateLightModule(): void + { + $this->validateModule(__DIR__ . '/../Virtual Light'); + } + public function testValidateMediaplayerModule(): void + { + $this->validateModule(__DIR__ . '/../Mediaplayer'); + } + public function testValidatePVSystemModule(): void + { + $this->validateModule(__DIR__ . '/../PVSystem'); + } + public function testValidateShutterModule(): void + { + $this->validateModule(__DIR__ . '/../Shutter'); + } + public function testValidateThermostatModule(): void + { + $this->validateModule(__DIR__ . '/../Thermostat'); + } + public function testValidateConsumptionCostsModule(): void + { + $this->validateModule(__DIR__ . '/../ConsumptionCosts'); + } + public function testValidateVirtualCounterModule(): void + { + $this->validateModule(__DIR__ . '/../Virtual Counter'); + } + +} \ No newline at end of file diff --git a/tests/phpunit.xml b/tests/phpunit.xml new file mode 100644 index 0000000..b737b8d --- /dev/null +++ b/tests/phpunit.xml @@ -0,0 +1,20 @@ + + + + + + + + + ../E-Car + ../Heater + ../Virtual Light + ../Mediaplayer + ../PVSystem + ../Shutter + ../Thermostat + ../ConsumptionCosts + ../Virtual Counter + + + diff --git a/tests/stubs b/tests/stubs new file mode 160000 index 0000000..858e2b2 --- /dev/null +++ b/tests/stubs @@ -0,0 +1 @@ +Subproject commit 858e2b224485b1b4eb18875a54d07ef17c0f6d76