diff --git a/.style b/.style
index ea67b89..fe04d92 160000
--- a/.style
+++ b/.style
@@ -1 +1 @@
-Subproject commit ea67b8910400936a6445e27f40d7e60ca79dc069
+Subproject commit fe04d922f53d36e19d91a7f8dfe4ca7c66ed62a4
diff --git a/AbfallNavi/README.md b/AbfallNavi/README.md
index a1c878e..c6d09b8 100644
--- a/AbfallNavi/README.md
+++ b/AbfallNavi/README.md
@@ -1,10 +1,10 @@
# AbfallNavi
[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
-[![Version](https://img.shields.io/badge/Modul%20Version-1.0.20221020-orange.svg)](https://github.com/Wilkware/IPSymconAwido)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-2.0.20231119-orange.svg)](https://github.com/Wilkware/WasteManagement)
[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-[![Actions](https://github.com/Wilkware/IPSymconAwido/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconAwido/actions)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
IP-Symcon Modul für die Visualisierung von Entsorgungsterminen.
@@ -27,13 +27,13 @@ Derzeit unterstützt das Modul rund 20 verschiedene Regionen. Wenn jemand noch w
### 2. Voraussetzungen
-* IP-Symcon ab Version 6.0
+* IP-Symcon ab Version 6.4
### 3. Installation
* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
* Alternativ Über das Modul-Control folgende URL hinzufügen.
-`https://github.com/Wilkware/IPSymconAwido` oder `git://github.com/Wilkware/IPSymconAwido.git`
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
### 4. Einrichten der Instanzen in IP-Symcon
@@ -108,6 +108,12 @@ __Beispiel__: `REGIO_Update(12345);`
### 8. Versionshistorie
+v2.0.20231119
+
+* _NEU_: Kompatibilität auf IPS 6.4 hoch gesetzt
+* _NEU_: Support für v7 Visualisierung
+* _FIX_: Sortierreihenfolge der Daten korriegiert
+
v1.0.20221020
* _NEU_: Initialversion
diff --git a/AbfallNavi/form.json b/AbfallNavi/form.json
index 672ab08..3545fbe 100644
--- a/AbfallNavi/form.json
+++ b/AbfallNavi/form.json
@@ -287,6 +287,27 @@
"name": "settingsVariables",
"caption": "Create variables for non-selected disposals?"
},
+ {
+ "type": "CheckBox",
+ "name": "settingsTileVisu",
+ "caption": "Activate support for Tile Visu?"
+ },
+ {
+ "type": "Select",
+ "name": "settingsTileSkin",
+ "caption": "Theme to be used (design):",
+ "width": "450px",
+ "options": [
+ {
+ "label": "Light Skin",
+ "value": "light"
+ },
+ {
+ "label": "Dark Skin",
+ "value": "dark"
+ }
+ ]
+ },
{
"type": "SelectScript",
"name": "settingsScript",
diff --git a/AbfallNavi/locale.json b/AbfallNavi/locale.json
index 9f12f25..0915e6a 100644
--- a/AbfallNavi/locale.json
+++ b/AbfallNavi/locale.json
@@ -19,6 +19,27 @@
"... call the following scipt after update the dates:": "... nach Aktualisierung der Werte folgendes Script aufrufen:",
"Subsequent execution of a script:": "Anschließendes Ausführen eines Skriptes:",
"Script:": "Script:",
+ "Activate support for Tile Visu?": "Unterstützung für Tile Visu aktivieren?",
+ "Theme to be used (design):": "Zu verwendendes Theme (Design):",
+ "Dark": "Dunkel",
+ "Light": "Hell",
+ "Waste": "Abfall",
+ "Pickup": "Abholung",
+ "Removal": "Abfuhr",
+ "Date": "Termin",
+ "Today": "Heute",
+ "Tomorrow": "Morgen",
+ "days": "Tage",
+ "day": "Tag",
+ "Next pickup:": "Nächste Abholung:",
+ "on": "am",
+ "Monday": "Montag",
+ "Tuesday": "Dienstag",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Sunday": "Sonntag",
"Disposal data ...": "Entsorgungsdaten ...",
"Update": "Aktualisieren",
"Creating instance.": "Die Instanz wird erstellt.",
diff --git a/AbfallNavi/module.php b/AbfallNavi/module.php
index 436f625..4490551 100644
--- a/AbfallNavi/module.php
+++ b/AbfallNavi/module.php
@@ -12,6 +12,7 @@ class AbfallNavi extends IPSModule
use DebugHelper;
use ServiceHelper;
use VariableHelper;
+ use VisualisationHelper;
// Service Provider
private const SERVICE_PROVIDER = 'regio';
@@ -76,6 +77,8 @@ public function Create()
$this->RegisterPropertyBoolean('settingsActivate', true);
$this->RegisterPropertyBoolean('settingsVariables', false);
$this->RegisterPropertyInteger('settingsScript', 0);
+ $this->RegisterPropertyBoolean('settingsTileVisu', false);
+ $this->RegisterPropertyString('settingsTileSkin', 'dark');
// Attributes for dynamic configuration forms (> v3.0)
$this->RegisterAttributeString('io', serialize($this->PrepareIO()));
// Register daily update timer
@@ -268,9 +271,12 @@ public function ApplyChanges()
$sId = $this->ReadPropertyString('streetID');
$aId = $this->ReadPropertyString('addonID');
$activate = $this->ReadPropertyBoolean('settingsActivate');
+ $tilevisu = $this->ReadPropertyBoolean('settingsTileVisu');
$this->SendDebug(__FUNCTION__, 'clientID=' . $cId . ', placeId=' . $pId . ', streetId=' . $sId . ', addonId=' . $aId);
// Safty default
$this->SetTimerInterval('UpdateTimer', 0);
+ // Support for Tile Viso (v7.x)
+ $this->MaintainVariable('Widget', $this->Translate('Pickup'), vtString, '~HTMLBox', 0, $tilevisu);
// Set status
$io = unserialize($this->ReadAttributeString('io'));
$this->SendDebug(__FUNCTION__, $io);
@@ -335,12 +341,12 @@ public function Update()
return;
}
// fractions convert to name => ident
- $vars = [];
+ $waste = [];
foreach ($io[self::IO_NAMES] as $ident => $name) {
$this->SendDebug(__FUNCTION__, 'Fraction ident: ' . $ident . ', Name: ' . $name);
- $vars[$ident] = '';
+ $waste[$ident] = ['ident' => $ident, 'date' => ''];
}
- $this->SendDebug(__FUNCTION__, $vars);
+ $this->SendDebug(__FUNCTION__, $waste);
// Build timestamp
$today = mktime(0, 0, 0);
// Iterate dates
@@ -350,19 +356,27 @@ public function Update()
continue;
}
// find out disposal type
- foreach ($vars as $key => $time) {
+ foreach ($waste as $key => $time) {
if ($key == $day['id']) {
- if ($time == '') {
- $vars[$key] = date('d.m.Y', strtotime($day['date']));
+ if ($time['date'] == '') {
+ $waste[$key]['date'] = date('d.m.Y', strtotime($day['date']));
}
break;
}
}
}
- $this->SendDebug(__FUNCTION__, $vars);
+ $this->SendDebug(__FUNCTION__, $waste);
// write data to variable
- foreach ($vars as $key => $time) {
- $this->SetValueString((string) $key, $time);
+ foreach ($waste as $key => $var) {
+ $this->SetValueString((string) $var['ident'], $var['date']);
+ }
+
+ // build tile widget
+ $btw = $this->ReadPropertyBoolean('settingsTileVisu');
+ $skin = $this->ReadPropertyString('settingsTileSkin');
+ $this->SendDebug(__FUNCTION__, 'TileVisu: ' . $btw . '(' . $skin . ')');
+ if ($btw == true) {
+ $this->BuildWidget($waste, $skin);
}
// execute Script
@@ -861,6 +875,7 @@ protected function ExecuteAction(&$io)
foreach ($json as $date) {
$data[] = ['id' => $date['bezirk']['fraktionId'], 'date' => $date['datum']];
}
+ $data = $this->OrderData($data, 'date');
$io[self::IO_ACTION] = self::ACTION_DATES;
}
break;
diff --git a/Abfall_IO/README.md b/Abfall_IO/README.md
index 2a8c80a..1a2baa0 100644
--- a/Abfall_IO/README.md
+++ b/Abfall_IO/README.md
@@ -1,10 +1,10 @@
# Abfall.IO
[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
-[![Version](https://img.shields.io/badge/Modul%20Version-1.5.20221020-orange.svg)](https://github.com/Wilkware/IPSymconAwido)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-2.0.2023119-orange.svg)](https://github.com/Wilkware/WasteManagement)
[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-[![Actions](https://github.com/Wilkware/IPSymconAwido/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconAwido/actions)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
IP-Symcon Modul für die Visualisierung von Entsorgungsterminen.
@@ -27,13 +27,13 @@ Derzeit unterstützt das Modul über 60 verschiedene Landkreise und Großstädte
### 2. Voraussetzungen
-* IP-Symcon ab Version 6.0
+* IP-Symcon ab Version 6.4
### 3. Installation
* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
* Alternativ Über das Modul-Control folgende URL hinzufügen.
-`https://github.com/Wilkware/IPSymconAwido` oder `git://github.com/Wilkware/IPSymconAwido.git`
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
### 4. Einrichten der Instanzen in IP-Symcon
@@ -118,6 +118,13 @@ __Beispiel__: `ABPIO_FixWasteName(12345, 'Hausmüll', 'Hausmüll (2 wöchentlich
### 8. Versionshistorie
+v2.0.20231119
+
+* _NEU_: Kompatibilität auf IPS 6.4 hoch gesetzt
+* _NEU_: Support für v7 Visualisierung
+* _FIX_: Übersetzungsfehler korrigiert
+* _FIX_: PHP Syle Check korrigiert
+
v1.5.20221020
* _FIX_: Code bereinigt (ungenutzte Funktionen entfernt)
diff --git a/Abfall_IO/form.json b/Abfall_IO/form.json
index 4a7df89..6d2b936 100644
--- a/Abfall_IO/form.json
+++ b/Abfall_IO/form.json
@@ -301,6 +301,27 @@
"name": "settingsVariables",
"caption": "Create variables for non-selected disposals?"
},
+ {
+ "type": "CheckBox",
+ "name": "settingsTileVisu",
+ "caption": "Activate support for Tile Visu?"
+ },
+ {
+ "type": "Select",
+ "name": "settingsTileSkin",
+ "caption": "Theme to be used (design):",
+ "width": "450px",
+ "options": [
+ {
+ "label": "Light Skin",
+ "value": "light"
+ },
+ {
+ "label": "Dark Skin",
+ "value": "dark"
+ }
+ ]
+ },
{
"type": "CheckBox",
"name": "settingsStartsWith",
@@ -309,7 +330,7 @@
{
"type": "Select",
"name": "settingsFormat",
- "caption": "Format, in welchem die Daten abgeholt werden:",
+ "caption": "Format in which the data is collected:",
"width": "450px",
"options": [
{
diff --git a/Abfall_IO/locale.json b/Abfall_IO/locale.json
index bee3290..e7cc1ee 100644
--- a/Abfall_IO/locale.json
+++ b/Abfall_IO/locale.json
@@ -24,6 +24,27 @@
"Comma Separated Values file (CSV)": "Trennzeichengetrennte Datei (CSV)",
"Subsequent execution of a script:": "Anschließendes Ausführen eines Skriptes:",
"Script:": "Script:",
+ "Activate support for Tile Visu?": "Unterstützung für Tile Visu aktivieren?",
+ "Theme to be used (design):": "Zu verwendendes Theme (Design):",
+ "Dark": "Dunkel",
+ "Light": "Hell",
+ "Waste": "Abfall",
+ "Pickup": "Abholung",
+ "Removal": "Abfuhr",
+ "Date": "Termin",
+ "Today": "Heute",
+ "Tomorrow": "Morgen",
+ "days": "Tage",
+ "day": "Tag",
+ "Next pickup:": "Nächste Abholung:",
+ "on": "am",
+ "Monday": "Montag",
+ "Tuesday": "Dienstag",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Sunday": "Sonntag",
"Disposal data ...": "Entsorgungsdaten ...",
"Update": "Aktualisieren",
"Creating instance.": "Die Instanz wird erstellt.",
diff --git a/Abfall_IO/module.php b/Abfall_IO/module.php
index 728084f..1161edc 100644
--- a/Abfall_IO/module.php
+++ b/Abfall_IO/module.php
@@ -17,6 +17,7 @@ class Abfall_IO extends IPSModule
use DebugHelper;
use ServiceHelper;
use VariableHelper;
+ use VisualisationHelper;
// Service Provider
private const SERVICE_PROVIDER = 'abpio';
@@ -73,6 +74,8 @@ public function Create()
$this->RegisterPropertyBoolean('settingsStartsWith', false);
$this->RegisterPropertyInteger('settingsScript', 0);
$this->RegisterPropertyString('settingsFormat', 'ics');
+ $this->RegisterPropertyBoolean('settingsTileVisu', false);
+ $this->RegisterPropertyString('settingsTileSkin', 'dark');
// Attributes for dynamic configuration forms (> v3.0)
$this->RegisterAttributeString('io', serialize($this->PrepareIO()));
// Register daily update timer
@@ -289,9 +292,12 @@ public function ApplyChanges()
$sId = $this->ReadPropertyString('streetID');
$aId = $this->ReadPropertyString('addonID');
$activate = $this->ReadPropertyBoolean('settingsActivate');
+ $tilevisu = $this->ReadPropertyBoolean('settingsTileVisu');
$this->SendDebug(__FUNCTION__, 'clientID=' . $cId . ', placeId=' . $pId . ', districtId=' . $dId . ', streetId=' . $sId . ', addonId=' . $aId);
// Safty default
$this->SetTimerInterval('UpdateTimer', 0);
+ // Support for Tile Viso (v7.x)
+ $this->MaintainVariable('Widget', $this->Translate('Pickup'), vtString, '~HTMLBox', 0, $tilevisu);
// Set status
if ($cId == 'null') {
$status = 201;
@@ -416,10 +422,10 @@ public function Update()
}
// fractions convert to name => ident
- $vars = [];
+ $waste = [];
foreach ($io[self::IO_NAMES] as $ident => $name) {
$this->SendDebug(__FUNCTION__, 'Fraction ident: ' . $ident . ', Name: ' . $name);
- $vars[$name] = ['ident' => $ident, 'date' => ''];
+ $waste[$name] = ['ident' => $ident, 'date' => ''];
}
// ICS format
@@ -456,7 +462,7 @@ public function Update()
// Update fraction
$name = $event->summary;
if ($ssw == true) {
- foreach ($vars as $key => $var) {
+ foreach ($waste as $key => $var) {
if ($this->StartsWith($name, $key)) {
$this->SendDebug(__FUNCTION__, 'StartWith: ' . $name . ' = ' . $key);
$name = $key;
@@ -464,16 +470,15 @@ public function Update()
}
}
}
- if (isset($vars[$name]) && $vars[$name]['date'] == '') {
- $vars[$name]['date'] = $day;
+ if (isset($waste[$name]) && $waste[$name]['date'] == '') {
+ $waste[$name]['date'] = $day;
$this->SendDebug(__FUNCTION__, 'Fraction date: ' . $name . ' = ' . $day);
}
}
}
// CSV format
else {
- $csv = array_map(function ($v)
- {
+ $csv = array_map(function ($v) {
$data = str_getcsv($v, ';');
return $data;
}, explode("\n", $res));
@@ -495,7 +500,7 @@ public function Update()
}
// Update fraction
if ($ssw == true) {
- foreach ($vars as $key => $var) {
+ foreach ($waste as $key => $var) {
if ($this->StartsWith($name, $key)) {
$this->SendDebug(__FUNCTION__, 'StartWith: ' . $name . ' = ' . $key);
$name = $key;
@@ -503,8 +508,8 @@ public function Update()
}
}
}
- if (isset($vars[$name]) && $vars[$name]['date'] == '') {
- $vars[$name]['date'] = $waste[$i];
+ if (isset($waste[$name]) && $waste[$name]['date'] == '') {
+ $waste[$name]['date'] = $waste[$i];
$this->SendDebug(__FUNCTION__, 'Fraction date: ' . $name . ' = ' . $waste[$i]);
}
}
@@ -512,10 +517,18 @@ public function Update()
}
// write data to variable
- foreach ($vars as $key => $var) {
+ foreach ($waste as $key => $var) {
$this->SetValueString((string) $var['ident'], $var['date']);
}
+ // build tile widget
+ $btw = $this->ReadPropertyBoolean('settingsTileVisu');
+ $skin = $this->ReadPropertyString('settingsTileSkin');
+ $this->SendDebug(__FUNCTION__, 'TileVisu: ' . $btw . '(' . $skin . ')');
+ if ($btw == true) {
+ $this->BuildWidget($waste, $skin);
+ }
+
// execute Script
$script = $this->ReadPropertyInteger('settingsScript');
if ($script != 0) {
diff --git a/Awido/README.md b/Awido/README.md
index 6e10e7e..888dc65 100644
--- a/Awido/README.md
+++ b/Awido/README.md
@@ -1,10 +1,10 @@
# Awido
[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
-[![Version](https://img.shields.io/badge/Modul%20Version-3.4.20230124-orange.svg)](https://github.com/Wilkware/IPSymconAwido)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-4.0.20231119-orange.svg)](https://github.com/Wilkware/WasteManagement)
[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-[![Actions](https://github.com/Wilkware/IPSymconAwido/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconAwido/actions)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
IP-Symcon Modul für die Visualisierung von Entsorgungsterminen.
@@ -45,13 +45,13 @@ Wenn jemand noch weitere kennt, bitte einfach bei mir melden!
### 2. Voraussetzungen
-* IP-Symcon ab Version 6.0
+* IP-Symcon ab Version 6.4
### 3. Installation
* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
* Alternativ Über das Modul-Control folgende URL hinzufügen.
-`https://github.com/Wilkware/IPSymconAwido` oder `git://github.com/Wilkware/IPSymconAwido.git`
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
### 4. Einrichten der Instanzen in IP-Symcon
@@ -126,6 +126,11 @@ __Beispiel__: `AWIDO_Update(12345);`
### 8. Versionshistorie
+v4.0.20231119
+
+* _NEU_: Kompatibilität auf IPS 6.4 hoch gesetzt
+* _NEU_: Support für v7 Visualisierung
+
v3.4.20230124
* _FIX_: Skripte in den erweiterten Einstellungen werden wieder gespeichert
diff --git a/Awido/form.json b/Awido/form.json
index 3e977e2..cffc315 100644
--- a/Awido/form.json
+++ b/Awido/form.json
@@ -286,6 +286,27 @@
"name": "createVariables",
"caption": "Create variables for non-selected disposals?"
},
+ {
+ "type": "CheckBox",
+ "name": "settingsTileVisu",
+ "caption": "Activate support for Tile Visu?"
+ },
+ {
+ "type": "Select",
+ "name": "settingsTileSkin",
+ "caption": "Theme to be used (design):",
+ "width": "450px",
+ "options": [
+ {
+ "label": "Light Skin",
+ "value": "light"
+ },
+ {
+ "label": "Dark Skin",
+ "value": "dark"
+ }
+ ]
+ },
{
"type": "SelectScript",
"name": "settingsScript",
diff --git a/Awido/locale.json b/Awido/locale.json
index 2e6aef2..3fd10c3 100644
--- a/Awido/locale.json
+++ b/Awido/locale.json
@@ -19,6 +19,27 @@
"... call the following scipt after update the dates:": "... nach Aktualisierung der Werte folgendes Script aufrufen:",
"Subsequent execution of a script:": "Anschließendes Ausführen eines Skriptes:",
"Script:": "Script:",
+ "Activate support for Tile Visu?": "Unterstützung für Tile Visu aktivieren?",
+ "Theme to be used (design):": "Zu verwendendes Theme (Design):",
+ "Dark": "Dunkel",
+ "Light": "Hell",
+ "Waste": "Abfall",
+ "Pickup": "Abholung",
+ "Removal": "Abfuhr",
+ "Date": "Termin",
+ "Today": "Heute",
+ "Tomorrow": "Morgen",
+ "days": "Tage",
+ "day": "Tag",
+ "Next pickup:": "Nächste Abholung:",
+ "on": "am",
+ "Monday": "Montag",
+ "Tuesday": "Dienstag",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Sunday": "Sonntag",
"Disposal data ...": "Entsorgungsdaten ...",
"Update": "Aktualisieren",
"Creating instance.": "Die Instanz wird erstellt.",
diff --git a/Awido/module.php b/Awido/module.php
index 9f4ce5f..49da07f 100644
--- a/Awido/module.php
+++ b/Awido/module.php
@@ -12,6 +12,7 @@ class Awido extends IPSModule
use DebugHelper;
use ServiceHelper;
use VariableHelper;
+ use VisualisationHelper;
// Service Provider
private const SERVICE_PROVIDER = 'awido';
@@ -43,6 +44,8 @@ public function Create()
$this->RegisterPropertyBoolean('createVariables', false);
$this->RegisterPropertyBoolean('activateAWIDO', true);
$this->RegisterPropertyInteger('settingsScript', 0);
+ $this->RegisterPropertyBoolean('settingsTileVisu', false);
+ $this->RegisterPropertyString('settingsTileSkin', 'dark');
// Attributes for dynamic configuration forms (> v2.0)
$this->RegisterAttributeString('cID', 'null');
$this->RegisterAttributeString('pID', 'null');
@@ -143,6 +146,7 @@ public function ApplyChanges()
$streetId = $this->ReadPropertyString('streetGUID');
$addonId = $this->ReadPropertyString('addonGUID');
$activate = $this->ReadPropertyBoolean('activateAWIDO');
+ $tilevisu = $this->ReadPropertyBoolean('settingsTileVisu');
$fractions = [];
for ($i = 1; $i <= static::$FRACTIONS; $i++) {
if ($this->ReadPropertyBoolean('fractionID' . $i)) {
@@ -153,6 +157,8 @@ public function ApplyChanges()
$this->SendDebug(__FUNCTION__, 'clientID=' . $clientId . ', placeId=' . $placeId . ', streetId=' . $streetId . ', addonId=' . $addonId . ', fractIds=' . $fractIds);
// Safty default
$this->SetTimerInterval('UpdateTimer', 0);
+ // Support for Tile Viso (v7.x)
+ $this->MaintainVariable('Widget', $this->Translate('Pickup'), vtString, '~HTMLBox', 0, $tilevisu);
//$status = 102;
if ($clientId == 'null') {
$status = 201;
@@ -224,10 +230,10 @@ public function Update()
$data = json_decode($json);
// Fractions mit Kurzzeichen(Short Name)) in Array konvertieren
- $array = [];
+ $waste = [];
foreach ($data as $fract) {
$fractID = $this->ReadPropertyBoolean('fractionID' . $fract->id);
- $array[$fract->snm] = ['ident' => $fract->snm, 'value' => '', 'exist' => $fractID];
+ $waste[$fract->snm] = ['ident' => $fract->snm, 'date' => '', 'exist' => $fractID];
}
// update data
@@ -249,20 +255,27 @@ public function Update()
$tag = substr($day->dt, 6) . '.' . substr($day->dt, 4, 2) . '.' . substr($day->dt, 0, 4);
// Entsorgungsart herausfinden
foreach ($day->fr as $snm) {
- if ($array[$snm]['value'] == '') {
- $array[$snm]['value'] = $tag;
+ if ($waste[$snm]['date'] == '') {
+ $waste[$snm]['date'] = $tag;
}
}
}
// write data to variable
- foreach ($array as $line) {
- if ($line['exist'] == true) {
- // falls haendich geloescht, dann eben nicht!
- $this->SetValueString((string) $line['ident'], $line['value']);
+ foreach ($waste as $key => $var) {
+ if ($var['exist'] == true) {
+ $this->SetValueString((string) $var['ident'], $var['date']);
}
}
+ // build tile widget
+ $btw = $this->ReadPropertyBoolean('settingsTileVisu');
+ $skin = $this->ReadPropertyString('settingsTileSkin');
+ $this->SendDebug(__FUNCTION__, 'TileVisu: ' . $btw . '(' . $skin . ')');
+ if ($btw == true) {
+ $this->BuildWidget($waste, $skin);
+ }
+
// execute Script
if ($scriptId != 0) {
if (IPS_ScriptExists($scriptId)) {
diff --git a/MuellMax/README.md b/MuellMax/README.md
new file mode 100644
index 0000000..3f68a3a
--- /dev/null
+++ b/MuellMax/README.md
@@ -0,0 +1,131 @@
+# MüllMax
+
+[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-1.0.20231119-orange.svg)](https://github.com/Wilkware/WasteManagement)
+[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
+
+IP-Symcon Modul für die Visualisierung von Entsorgungsterminen.
+
+## Inhaltverzeichnis
+
+1. [Funktionsumfang](#user-content-1-funktionsumfang)
+2. [Voraussetzungen](#user-content-2-voraussetzungen)
+3. [Installation](#user-content-3-installation)
+4. [Einrichten der Instanzen in IP-Symcon](#user-content-4-einrichten-der-instanzen-in-ip-symcon)
+5. [Statusvariablen und Profile](#user-content-5-statusvariablen-und-profile)
+6. [WebFront](#user-content-6-webfront)
+7. [PHP-Befehlsreferenz](#user-content-7-php-befehlsreferenz)
+8. [Versionshistorie](#user-content-8-versionshistorie)
+
+### 1. Funktionsumfang
+
+Das Modul nutzt die von MüllMax (www.muellmax.de) bereitgestellten Daten zur Berechnung der bevorstehenden Entsorgungstermine (Abfallentsorgung).
+
+Derzeit unterstützt das Modul 15 verschiedene Landkreise und Großstädte. Wenn jemand noch weitere kennt, bitte einfach bei mir melden!
+
+### 2. Voraussetzungen
+
+* IP-Symcon ab Version 6.4
+
+### 3. Installation
+
+* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
+* Alternativ Über das Modul-Control folgende URL hinzufügen.
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
+
+### 4. Einrichten der Instanzen in IP-Symcon
+
+* Unter "Instanz hinzufügen" ist das _'MuellMax'_-Modul (Alias: _'Abfallwirtschaft (MüllMax)'_ oder _'Entsorgungskalender (MüllMax)'_) unter dem Hersteller _'(Geräte)'_ aufgeführt.
+
+__Konfigurationsseite__:
+
+Entsprechend der gewählten Auswahl verändert sich das Formular dynamisch.
+Eine komplette Neuauswahl erreicht man durch Auswahl "Bitte wählen ..." an der gewünschten Stelle.
+
+VORSTICHT: eine Änderung der Auswahl bedingt ein Update bzw. ein Neuanlegen der Statusvariablen!!!
+Alte Variablen, welche es im anderen Landkreis gab werden nicht gelöscht! Hat man diese in einem WF verlinkt muss man danach
+selber aufräumen. Ich denke aber mal das ein Umzug nicht so häufig vorkommt ;-)
+
+_Einstellungsbereich:_
+
+> Online Dienste ...
+
+Name | Beschreibung
+----------------------- | ----------------------------------
+Anbieter | 'MüllMax (muellmax.de)'
+
+> Abfallwirtschaft ...
+
+Name | Beschreibung
+----------------------- | ---------------------------------
+Entsorgungsgebiet | Liste der verfügbaren Gebiete (siehe oben)
+Stadt | Ort im Entsorgungsgebiet (kann identisch zum Gebiet sein)
+Straße | Strasse im gewählten Ort
+Hausnummer | Hausnummer in gewählter Strasse
+Entsorgungen | Entsorgungsarten, d.h. was wird im Gebiet an Entsorgung angeboten
+
+> Erweiterte Einstellungen ...
+
+Name | Beschreibung
+------------------------------------------------------- | ---------------------------------
+Tägliche Aktualisierung aktivieren? | Status, ob das tägliche Update aktiv oder inaktiv ist
+Variablen für nicht ausgewählte Entsorgungen erstellen? | Status, ob für nicht genutzte Entsorgungen auch Variablen angelegt werden sollen, standardmäßig nein
+Skript | Skript, welches nach dem Update der Termine ausgeführt wird, z.B. für Sortierung usw.
+
+_Aktionsbereich:_
+
+Aktion | Beschreibung
+----------------------- | ---------------------------------
+AKTUALISEREN | Werte werden neu ermittelt und geschrieben
+
+### 5. Statusvariablen und Profile
+
+Die Statusvariablen/Timer werden automatisch angelegt. Das Löschen einzelner kann zu Fehlfunktionen führen.
+
+Name | Typ | Beschreibung
+-------------------| --------- | ----------------
+Entsorgungsart(en) | String | Abhängig vom Entsorgungsgebiet und den angebotenem Service mehrere Variablen, z.B.: Restmüll, Biotonne usw.
+
+Es werden keine zusätzlichen Profile benötigt.
+
+### 6. WebFront
+
+Man kann die Statusvariablen(Strings) direkt im WF verlinken.
+Aber wie bei der Konfiguration beschrieben, muss man aufpassen wenn die Konfiguration geändert wird. Dann müssen gegebenenfalls die Links neu eingerichtet werden.
+
+### 7. PHP-Befehlsreferenz
+
+```php
+void MAXDE_Update(int $InstanzID);
+```
+
+Holt die nächsten anstehenden Entsorgungstermine für die gewählten Entsorgungsarten.
+Die Funktion liefert keinerlei Rückgabewert.
+
+__Beispiel__: `MAXDE_Update(12345);`
+
+### 8. Versionshistorie
+
+v1.0.20231119
+
+* _NEU_: Initialversion
+
+## Entwickler
+
+Seit nunmehr über 10 Jahren fasziniert mich das Thema Haussteuerung. In den letzten Jahren betätige ich mich auch intensiv in der IP-Symcon Community und steuere dort verschiedenste Skript und Module bei. Ihr findet mich dort unter dem Namen @pitti ;-)
+
+[![GitHub](https://img.shields.io/badge/GitHub-@wilkware-181717.svg?style=for-the-badge&logo=github)](https://wilkware.github.io/)
+
+## Spenden
+
+Die Software ist für die nicht kommerzielle Nutzung kostenlos, über eine Spende bei Gefallen des Moduls würde ich mich freuen.
+
+[![PayPal](https://img.shields.io/badge/PayPal-spenden-00457C.svg?style=for-the-badge&logo=paypal)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8816166)
+
+## Lizenz
+
+Namensnennung - Nicht-kommerziell - Weitergabe unter gleichen Bedingungen 4.0 International
+
+[![Licence](https://img.shields.io/badge/License-CC_BY--NC--SA_4.0-EF9421.svg?style=for-the-badge&logo=creativecommons)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
diff --git a/MuellMax/form.json b/MuellMax/form.json
new file mode 100644
index 0000000..906c688
--- /dev/null
+++ b/MuellMax/form.json
@@ -0,0 +1,397 @@
+{
+ "elements": [
+ {
+ "type": "RowLayout",
+ "items": [
+ {
+ "type": "Image",
+ "image": "data:image/png;base64,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",
+ "link": true,
+ "onClick": "echo 'https://wilkware.de';"
+ },
+ {
+ "type": "Label",
+ "label": "\nMuellMax – Disposal calendar\n ",
+ "link": false,
+ "bold": true
+ }
+ ]
+ },
+ {
+ "type": "Label",
+ "label": "This module uses the data provided by the MuellMax online service to display upcoming disposal dates.",
+ "link": false
+ },
+ {
+ "type": "ExpansionPanel",
+ "caption": "Online service ...",
+ "items": [
+ {
+ "type": "Select",
+ "name": "serviceProvider",
+ "caption": "Provider:",
+ "width": "450px",
+ "enabled": false,
+ "options": [
+ {
+ "label": "Please select ...",
+ "value": "null"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "ExpansionPanel",
+ "caption": "Waste management ...",
+ "items": [
+ {
+ "type": "RowLayout",
+ "items": [
+ {
+ "type": "Select",
+ "name": "disposalID",
+ "caption": "Disposal area:",
+ "width": "450px",
+ "onChange": "IPS_RequestAction($id,'OnChangeDisposal',$disposalID);",
+ "options": [
+ {
+ "label": "Please select ...",
+ "value": "null"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "RowLayout",
+ "items": [
+ {
+ "type": "Select",
+ "name": "cityID",
+ "caption": "City:",
+ "width": "450px",
+ "visible": false,
+ "onChange": "IPS_RequestAction($id,'OnChangeCity',$cityID);",
+ "options": [
+ {
+ "label": "Please select ...",
+ "value": "null"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "RowLayout",
+ "items": [
+ {
+ "type": "Select",
+ "name": "streetID",
+ "caption": "Street:",
+ "width": "450px",
+ "visible": false,
+ "onChange": "IPS_RequestAction($id,'OnChangeStreet',$streetID);",
+ "options": [
+ {
+ "label": "Please select ...",
+ "value": "null"
+ }
+ ]
+ },
+ {
+ "type": "Select",
+ "name": "addonID",
+ "caption": "Number:",
+ "width": "450px",
+ "visible": false,
+ "onChange": "IPS_RequestAction($id,'OnChangeAddon',$addonID);",
+ "options": [
+ {
+ "label": "Please select ...",
+ "value": "null"
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "type": "Label",
+ "name": "fractionLabel",
+ "caption": "The following disposals are offered:",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID1",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID2",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID3",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID4",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID5",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID6",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID7",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID8",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID9",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID10",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID11",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID12",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID13",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID14",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID15",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID16",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID17",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID18",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID19",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID20",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID21",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID22",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID23",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID24",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID25",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID26",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID27",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID28",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID29",
+ "visible": false
+ },
+ {
+ "type": "CheckBox",
+ "name": "fractionID30",
+ "visible": false
+ }
+ ]
+ },
+ {
+ "type": "ExpansionPanel",
+ "caption": "Advanced settings ...",
+ "items": [
+ {
+ "type": "CheckBox",
+ "name": "settingsActivate",
+ "caption": "Activate daily update?"
+ },
+ {
+ "type": "CheckBox",
+ "name": "settingsVariables",
+ "caption": "Create variables for non-selected disposals?"
+ },
+ {
+ "type": "CheckBox",
+ "name": "settingsTileVisu",
+ "caption": "Activate support for Tile Visu?"
+ },
+ {
+ "type": "Select",
+ "name": "settingsTileSkin",
+ "caption": "Theme to be used (design):",
+ "width": "450px",
+ "options": [
+ {
+ "label": "Light Skin",
+ "value": "light"
+ },
+ {
+ "label": "Dark Skin",
+ "value": "dark"
+ }
+ ]
+ },
+ {
+ "type": "SelectScript",
+ "name": "settingsScript",
+ "caption": "Subsequent execution of a script:",
+ "width": "450px"
+ }
+ ]
+ }
+ ],
+ "actions": [
+ {
+ "type": "Label",
+ "name": "updateLabel",
+ "caption": "Disposal data ...",
+ "visible": true
+ },
+ {
+ "type": "Button",
+ "name": "updateButton",
+ "caption": "Update",
+ "onClick": "MAXDE_Update($id);",
+ "visible": true
+ },
+ {
+ "type": "Label",
+ "caption": ""
+ },
+ {
+ "type": "ExpansionPanel",
+ "caption": "Source code, donation and licence ...",
+ "items": [
+ {
+ "type": "Label",
+ "caption": "The software is free of charge for non-commercial use, I would appreciate a donation if you like the module.",
+ "bold": true
+ },
+ {
+ "type": "RowLayout",
+ "items": [
+ {
+ "type": "Image",
+ "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTk2Ljc1IiBoZWlnaHQ9IjI4IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IkdJVEhVQjogQFdJTEtXQVJFIj48dGl0bGU+R0lUSFVCOiBAV0lMS1dBUkU8L3RpdGxlPjxnIHNoYXBlLXJlbmRlcmluZz0iY3Jpc3BFZGdlcyI+PHJlY3Qgd2lkdGg9Ijg3LjUiIGhlaWdodD0iMjgiIGZpbGw9IiM1NTUiLz48cmVjdCB4PSI4Ny41IiB3aWR0aD0iMTA5LjI1IiBoZWlnaHQ9IjI4IiBmaWxsPSIjMTgxNzE3Ii8+PC9nPjxnIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJWZXJkYW5hLEdlbmV2YSxEZWphVnUgU2FucyxzYW5zLXNlcmlmIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiBmb250LXNpemU9IjEwMCI+PGltYWdlIHg9IjkiIHk9IjciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCbWFXeHNQU0ozYUdsMFpYTnRiMnRsSWlCeWIyeGxQU0pwYldjaUlIWnBaWGRDYjNnOUlqQWdNQ0F5TkNBeU5DSWdlRzFzYm5NOUltaDBkSEE2THk5M2QzY3Vkek11YjNKbkx6SXdNREF2YzNabklqNDhkR2wwYkdVK1IybDBTSFZpUEM5MGFYUnNaVDQ4Y0dGMGFDQmtQU0pOTVRJZ0xqSTVOMk10Tmk0Mk15QXdMVEV5SURVdU16Y3pMVEV5SURFeUlEQWdOUzR6TURNZ015NDBNemdnT1M0NElEZ3VNakExSURFeExqTTROUzQyTGpFeE15NDRNaTB1TWpVNExqZ3lMUzQxTnpjZ01DMHVNamcxTFM0d01TMHhMakEwTFM0d01UVXRNaTR3TkMwekxqTXpPQzQzTWpRdE5DNHdOREl0TVM0Mk1TMDBMakEwTWkweExqWXhRelF1TkRJeUlERTRMakEzSURNdU5qTXpJREUzTGpjZ015NDJNek1nTVRjdU4yTXRNUzR3T0RjdExqYzBOQzR3T0RRdExqY3lPUzR3T0RRdExqY3lPU0F4TGpJd05TNHdPRFFnTVM0NE16Z2dNUzR5TXpZZ01TNDRNemdnTVM0eU16WWdNUzR3TnlBeExqZ3pOU0F5TGpnd09TQXhMak13TlNBekxqUTVOUzQ1T1RndU1UQTRMUzQzTnpZdU5ERTNMVEV1TXpBMUxqYzJMVEV1TmpBMUxUSXVOalkxTFM0ekxUVXVORFkyTFRFdU16TXlMVFV1TkRZMkxUVXVPVE1nTUMweExqTXhMalEyTlMweUxqTTRJREV1TWpNMUxUTXVNakl0TGpFek5TMHVNekF6TFM0MU5DMHhMalV5TXk0eE1EVXRNeTR4TnpZZ01DQXdJREV1TURBMUxTNHpNaklnTXk0eklERXVNak11T1RZdExqSTJOeUF4TGprNExTNHpPVGtnTXkwdU5EQTFJREV1TURJdU1EQTJJREl1TURRdU1UTTRJRE1nTGpRd05TQXlMakk0TFRFdU5UVXlJRE11TWpnMUxURXVNak1nTXk0eU9EVXRNUzR5TXk0Mk5EVWdNUzQyTlRNdU1qUWdNaTQ0TnpNdU1USWdNeTR4TnpZdU56WTFMamcwSURFdU1qTWdNUzQ1TVNBeExqSXpJRE11TWpJZ01DQTBMall4TFRJdU9EQTFJRFV1TmpJMUxUVXVORGMxSURVdU9USXVOREl1TXpZdU9ERWdNUzR3T1RZdU9ERWdNaTR5TWlBd0lERXVOakEyTFM0d01UVWdNaTQ0T1RZdExqQXhOU0F6TGpJNE5pQXdJQzR6TVRVdU1qRXVOamt1T0RJMUxqVTNRekl3TGpVMk5TQXlNaTR3T1RJZ01qUWdNVGN1TlRreUlESTBJREV5TGpJNU4yTXdMVFl1TmpJM0xUVXVNemN6TFRFeUxURXlMVEV5SWk4K1BDOXpkbWMrIi8+PHRleHQgdHJhbnNmb3JtPSJzY2FsZSguMSkiIHg9IjUyMi41IiB5PSIxNzUiIHRleHRMZW5ndGg9IjQ2NSIgZmlsbD0iI2ZmZiI+R0lUSFVCPC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSIxNDIxLjI1IiB5PSIxNzUiIHRleHRMZW5ndGg9Ijg1Mi41IiBmaWxsPSIjZmZmIiBmb250LXdlaWdodD0iYm9sZCI+QFdJTEtXQVJFPC90ZXh0PjwvZz48L3N2Zz4=",
+ "onClick": "echo 'https://wilkware.github.io/';"
+ },
+ {
+ "type": "Image",
+ "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMTcxLjI1IiBoZWlnaHQ9IjI4IiByb2xlPSJpbWciIGFyaWEtbGFiZWw9IlBBWVBBTDogU1BFTkRFTiI+PHRpdGxlPlBBWVBBTDogU1BFTkRFTjwvdGl0bGU+PGcgc2hhcGUtcmVuZGVyaW5nPSJjcmlzcEVkZ2VzIj48cmVjdCB3aWR0aD0iODUuNSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzU1NSIvPjxyZWN0IHg9Ijg1LjUiIHdpZHRoPSI4NS43NSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzAwNDU3YyIvPjwvZz48ZyBmaWxsPSIjZmZmIiB0ZXh0LWFuY2hvcj0ibWlkZGxlIiBmb250LWZhbWlseT0iVmVyZGFuYSxHZW5ldmEsRGVqYVZ1IFNhbnMsc2Fucy1zZXJpZiIgdGV4dC1yZW5kZXJpbmc9Imdlb21ldHJpY1ByZWNpc2lvbiIgZm9udC1zaXplPSIxMDAiPjxpbWFnZSB4PSI5IiB5PSI3IiB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHhsaW5rOmhyZWY9ImRhdGE6aW1hZ2Uvc3ZnK3htbDtiYXNlNjQsUEhOMlp5QjJhV1YzUW05NFBTSXdJREFnTWpRZ01qUWlJSGh0Ykc1elBTSm9kSFJ3T2k4dmQzZDNMbmN6TG05eVp5OHlNREF3TDNOMlp5SStQSEJoZEdnZ1pEMGlUVEU1TGpjeE5TQTJMakV6TTJNdU1qUTVMVEV1T0RZMklEQXRNeTR4TVMwdU9UazVMVFF1TWpZMlF6RTNMall6TkM0Mk1qSWdNVFV1TnpJeElEQWdNVE11TXpBM0lEQklOaTR5TXpWakxTNDBNVGdnTUMwdU9URTJMalEwTkMweElDNDRPRGxNTWk0ek1qTWdNakF1TmpJeVl6QWdMak0xTmk0eU5TNDRMalkyTlM0NGFEUXVNekk0YkMwdU1qVWdNUzQ1TlRaakxTNHdPRFF1TXpVMUxqRTJOaTQyTWpJdU5EazRMall5TW1nekxqWTJNMk11TkRFM0lEQWdMamd6TWkwdU1qWTNMamt4TlMwdU56RXhkaTB1TWpZM2JDNDNORGt0TkM0Mk1qSjJMUzR4TnpoakxqQTRNeTB1TkRRMExqVXRMamd1T1RFMUxTNDRhQzQxWXpNdU5UYzRJREFnTmk0ek1qVXRNUzQxTVNBM0xqRTFOaTAxTGprMU5TNDBNVGd0TVM0NE5qY3VNalV5TFRNdU16YzRMUzQzTkRjdE5DNDBORFV0TGpJMUxTNHpOVFV0TGpZMk5pMHVOakl5TFRFdExqZzRPU0lnWm1sc2JEMGlJekF3T1dOa1pTSXZQanh3WVhSb0lHUTlJazB4T1M0M01UVWdOaTR4TXpOakxqSTBPUzB4TGpnMk5pQXdMVE11TVRFdExqazVPUzAwTGpJMk5rTXhOeTQyTXpRdU5qSXlJREUxTGpjeU1TQXdJREV6TGpNd055QXdTRFl1TWpNMVl5MHVOREU0SURBdExqa3hOaTQwTkRRdE1TQXVPRGc1VERJdU16SXpJREl3TGpZeU1tTXdJQzR6TlRZdU1qVXVPQzQyTmpVdU9HZzBMak15T0d3eExqRTJOQzAzTGpNM09DMHVNRGd6TGpJMk4yTXVNRGcwTFM0MU16TXVOUzB1T0RnNUxqazVPQzB1T0RnNWFESXVNRGhqTkM0d056a2dNQ0EzTGpJME1TMHhMamMzT0NBNExqSTBMVFl1TnpVMUxTNHdPRE10TGpJMk55QXdMUzR6TlRZZ01DMHVOVE0wSWlCbWFXeHNQU0lqTURFeU1UWTVJaTgrUEhCaGRHZ2daRDBpVFRrdU5UWXpJRFl1TVRNell5NHdPREl0TGpJMk5pNHlOUzB1TlRNekxqUTVPQzB1TnpFdU1UWTJJREFnTGpJMUxTNHdPUzQwTVRZdExqQTVhRFV1TkRrMFl5NDJOallnTUNBeExqTXpMakE1SURFdU9ETXVNVGM0TGpFMk5pQXdJQzR6TXpNZ01DQXVORGs0TGpBNE9TNHhOamd1TURnNUxqTXpOQzR3T0RrdU5ERTRMakUzT0dndU1qVmpMakkwT0M0d09Ea3VORGszTGpJMk5pNDNORGd1TXpVMUxqSTBPQzB4TGpnMk5pQXdMVE11TVRFdExqazVPUzAwTGpNMU5VTXhOeTQzTVRjdU5UTXpJREUxTGpnd05DQXdJREV6TGpNNUlEQklOaTR5TXpWakxTNDBNVGdnTUMwdU9URTJMak0xTmkweElDNDRPRGxNTWk0ek1qTWdNakF1TmpJeVl6QWdMak0xTmk0eU5TNDRMalkyTlM0NGFEUXVNekk0YkRFdU1UWTBMVGN1TXpjNElERXVNRGcwTFRjdU9URjZJaUJtYVd4c1BTSWpNREF6TURnM0lpOCtQQzl6ZG1jKyIvPjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSI1MTIuNSIgeT0iMTc1IiB0ZXh0TGVuZ3RoPSI0NDUiIGZpbGw9IiNmZmYiPlBBWVBBTDwvdGV4dD48dGV4dCB0cmFuc2Zvcm09InNjYWxlKC4xKSIgeD0iMTI4My43NSIgeT0iMTc1IiB0ZXh0TGVuZ3RoPSI2MTcuNSIgZmlsbD0iI2ZmZiIgZm9udC13ZWlnaHQ9ImJvbGQiPlNQRU5ERU48L3RleHQ+PC9nPjwvc3ZnPg==",
+ "onClick": "echo 'https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=8816166';"
+ },
+ {
+ "type": "Image",
+ "image": "data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB3aWR0aD0iMjI5LjUiIGhlaWdodD0iMjgiIHJvbGU9ImltZyIgYXJpYS1sYWJlbD0iTElDRU5TRTogQ0MgQlktTkMtU0EgNC4wIj48dGl0bGU+TElDRU5TRTogQ0MgQlktTkMtU0EgNC4wPC90aXRsZT48ZyBzaGFwZS1yZW5kZXJpbmc9ImNyaXNwRWRnZXMiPjxyZWN0IHdpZHRoPSI5Mi43NSIgaGVpZ2h0PSIyOCIgZmlsbD0iIzU1NSIvPjxyZWN0IHg9IjkyLjc1IiB3aWR0aD0iMTM2Ljc1IiBoZWlnaHQ9IjI4IiBmaWxsPSIjZWY5NDIxIi8+PC9nPjxnIGZpbGw9IiNmZmYiIHRleHQtYW5jaG9yPSJtaWRkbGUiIGZvbnQtZmFtaWx5PSJWZXJkYW5hLEdlbmV2YSxEZWphVnUgU2FucyxzYW5zLXNlcmlmIiB0ZXh0LXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIiBmb250LXNpemU9IjEwMCI+PGltYWdlIHg9IjkiIHk9IjciIHdpZHRoPSIxNCIgaGVpZ2h0PSIxNCIgeGxpbms6aHJlZj0iZGF0YTppbWFnZS9zdmcreG1sO2Jhc2U2NCxQSE4yWnlCbWFXeHNQU0lqUlVZNU5ESXhJaUJ5YjJ4bFBTSnBiV2NpSUhacFpYZENiM2c5SWpBZ01DQXlOQ0F5TkNJZ2VHMXNibk05SW1oMGRIQTZMeTkzZDNjdWR6TXViM0puTHpJd01EQXZjM1puSWo0OGRHbDBiR1UrUTNKbFlYUnBkbVVnUTI5dGJXOXVjend2ZEdsMGJHVStQSEJoZEdnZ1pEMGlUVEV4TGprNE15QXdZeTB6TGpJNU1pQXdMVFl1TVRrZ01TNHlNVGN0T0M0ME1qZ2dNeTQwT0RWRE1TNHlOU0ExTGpneE9TQXdJRGd1T0RRMElEQWdNVEpqTUNBekxqRTRPU0F4TGpJeE55QTJMakUwT0NBekxqVXlNaUE0TGpRMVF6VXVPREkzSURJeUxqYzFJRGd1T0RJeUlESTBJREV4TGprNE15QXlOR016TGpFMklEQWdOaTR5TWpJdE1TNHlOU0E0TGpVNU15MHpMalU0TTBNeU1pNDRNVFVnTVRndU1qRTBJREkwSURFMUxqSTROeUF5TkNBeE1tTXdMVE11TWpVMUxURXVNVGcyTFRZdU1qRTBMVE11TkRVNExUZ3VORGd6UXpFNExqSXpPQ0F4TGpJeE55QXhOUzR5TnpVZ01DQXhNUzQ1T0RNZ01IcHRMakF6TXlBeUxqRTNZekl1TnlBd0lEVXVNVEF6SURFdU1ESWdOaTQ1T0NBeUxqZzVNeUF4TGpnME15QXhMamcwTVNBeUxqZ3pJRFF1TWpjMElESXVPRE1nTmk0NU16Y2dNQ0F5TGpZNU5pMHVPVFUwSURVdU1EWXpMVEl1TnprNElEWXVPRGN5TFRFdU9UUXpJREV1T1RBMkxUUXVORFEwSURJdU9USTJMVGN1TURFeUlESXVPVEkyTFRJdU5qQXhJREF0TlM0d016Z3RNUzR3TVRrdE5pNDVNVFF0TWk0NE9UTXRNUzQ0TnpjdE1TNDROelV0TWk0NU15MDBMak0wTFRJdU9UTXROaTQ1TURVZ01DMHlMalU1TnlBeExqQTFNeTAxTGpBMk15QXlMamt6TFRZdU9UY2dNUzQ0TkRRdE1TNDROelFnTkM0eU1UUXRNaTQ0TmlBMkxqa3hOQzB5TGpnMmVrMDRMalk0SURndU1qYzRRell1TnpJeklEZ3VNamM0SURVdU1UWTFJRGt1TmpZZ05TNHhOalVnTVRKak1DQXlMak00SURFdU5EWTFJRE11TnpJeUlETXVOVGd4SURNdU56SXlJREV1TXpVNElEQWdNaTQxTVRZdExqYzBOQ0F6TGpFMU5TMHhMamczTkd3dE1TNDBPVEV0TGpjMU9HTXRMak16TXk0M09UZ3RMamd6T1NBeExqQXpOeTB4TGpRM09DQXhMakF6TnkweExqRXdOU0F3TFRFdU5qRXRMamt4TnkweExqWXhMVEl1TVRJMklEQXRNUzR5TVM0ME1qWXRNaTR4TWpjZ01TNDJNUzB5TGpFeU55NHpNaUF3SUM0NU5pNHhOek1nTVM0ek16SXVPVGRzTVM0MU9UY3RMamd6T0dNdExqWTRMVEV1TWpNMkxURXVPRE0zTFRFdU56STRMVE11TVRneExURXVOekk0ZW0wMkxqa3pNaUF3WXkweExqazFOeUF3TFRNdU5URTBJREV1TXpneUxUTXVOVEUwSURNdU56SXlJREFnTWk0ek9DQXhMalEyTkNBekxqY3lNaUF6TGpVNElETXVOekl5SURFdU16VTVJREFnTWk0MU1UWXRMamMwTkNBekxqRTFOUzB4TGpnM05Hd3RNUzQwT1MwdU56VTRZeTB1TXpNekxqYzVPQzB1T0RRZ01TNHdNemN0TVM0ME56Z2dNUzR3TXpjdE1TNHhNRFVnTUMweExqWXhNUzB1T1RFM0xURXVOakV4TFRJdU1USTJJREF0TVM0eU1TNDBNall0TWk0eE1qY2dNUzQyTVMweUxqRXlOeTR6TWlBd0lDNDVOaTR4TnpNZ01TNHpNekl1T1Rkc01TNDFPVGN0TGpnek9HTXRMalk0TFRFdU1qTTJMVEV1T0RNM0xURXVOekk0TFRNdU1UZ3hMVEV1TnpJNGVpSXZQand2YzNablBnPT0iLz48dGV4dCB0cmFuc2Zvcm09InNjYWxlKC4xKSIgeD0iNTQ4Ljc1IiB5PSIxNzUiIHRleHRMZW5ndGg9IjUxNy41IiBmaWxsPSIjZmZmIj5MSUNFTlNFPC90ZXh0Pjx0ZXh0IHRyYW5zZm9ybT0ic2NhbGUoLjEpIiB4PSIxNjExLjI1IiB5PSIxNzUiIHRleHRMZW5ndGg9IjExMjcuNSIgZmlsbD0iI2ZmZiIgZm9udC13ZWlnaHQ9ImJvbGQiPkNDIEJZLU5DLVNBIDQuMDwvdGV4dD48L2c+PC9zdmc+",
+ "onClick": "echo 'https://creativecommons.org/licenses/by-nc-sa/4.0/';"
+ }
+ ]
+ }
+ ]
+ }
+ ],
+ "status": [
+ {
+ "code": 101,
+ "icon": "inactive",
+ "caption": "Creating instance."
+ },
+ {
+ "code": 102,
+ "icon": "active",
+ "caption": "Instance active."
+ },
+ {
+ "code": 104,
+ "icon": "inactive",
+ "caption": "Instance inactive."
+ },
+ {
+ "code": 201,
+ "icon": "inactive",
+ "caption": "Please select a valid refuse management!"
+ },
+ {
+ "code": 202,
+ "icon": "inactive",
+ "caption": "Please select a offered disposals!"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/MuellMax/locale.json b/MuellMax/locale.json
new file mode 100644
index 0000000..e8ebc02
--- /dev/null
+++ b/MuellMax/locale.json
@@ -0,0 +1,56 @@
+{
+ "translations": {
+ "de": {
+ "\nMuellMax – Disposal calendar\n ": "\nMüllMax – Entsorgungskalender\n ",
+ "This module uses the data provided by the MuellMax online service to display upcoming disposal dates.": "Dieses Modul nutzt die vom Online-Dienst MüllMax bereitgestellten Daten zur Darstellung der bevorstehenden Entsorgungstermine.",
+ "Online service ...": "Online Dienst ...",
+ "Provider:": "Anbieter:",
+ "Waste management ...": "Abfallwirtschaft ...",
+ "Please select ...": "Bitte wählen ...",
+ "Disposal area:": "Entsorgungsgebiet:",
+ "City:": "Stadt:",
+ "Street:": "Straße:",
+ "Number:": "Hausnummer:",
+ "All": "Alle",
+ "The following disposals are offered:": "Folgende Entsorgungen werden angeboten:",
+ "Advanced settings ...": "Erweiterte Einstellungen ...",
+ "Create variables for non-selected disposals?": "Variablen für nicht ausgewählte Entsorgungen erstellen?",
+ "Activate daily update?": "Tägliche Aktualisierung aktivieren?",
+ "... call the following scipt after update the dates:": "... nach Aktualisierung der Werte folgendes Script aufrufen:",
+ "Subsequent execution of a script:": "Anschließendes Ausführen eines Skriptes:",
+ "Script:": "Script:",
+ "Activate support for Tile Visu?": "Unterstützung für Tile Visu aktivieren?",
+ "Theme to be used (design):": "Zu verwendendes Theme (Design):",
+ "Dark": "Dunkel",
+ "Light": "Hell",
+ "Waste": "Abfall",
+ "Pickup": "Abholung",
+ "Removal": "Abfuhr",
+ "Date": "Termin",
+ "Today": "Heute",
+ "Tomorrow": "Morgen",
+ "days": "Tage",
+ "day": "Tag",
+ "Next pickup:": "Nächste Abholung:",
+ "on": "am",
+ "Monday": "Montag",
+ "Tuesday": "Dienstag",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Sunday": "Sonntag",
+ "Disposal data ...": "Entsorgungsdaten ...",
+ "Update": "Aktualisieren",
+ "Creating instance.": "Die Instanz wird erstellt.",
+ "Instance active.": "Instanz ist aktiv.",
+ "Instance inactive.": "Instanz ist inaktiv.",
+ "Please select a valid refuse management!": "Bitte eine Abfallwirtschaft auswählen!",
+ "Please select a correct configuration!": "Bitte wählen Sie ein korrekte Konfiguration aus!",
+ "Please select a offered disposals!": "Bitte die angebotenen Entsorgungen auswählen!",
+ "Could not load json data!": "Konnte JSON Daten nicht laden!",
+ "Source code, donation and licence ...": "Quellcode, Spende und Lizenz ...",
+ "The software is free of charge for non-commercial use, I would appreciate a donation if you like the module.": "Die Software ist für die nicht kommzerielle Nutzung kostenlos, über eine Spende bei Gefallen des Moduls würde ich mich sehr freuen."
+ }
+ }
+}
\ No newline at end of file
diff --git a/MuellMax/module.json b/MuellMax/module.json
new file mode 100644
index 0000000..ceac3a2
--- /dev/null
+++ b/MuellMax/module.json
@@ -0,0 +1,15 @@
+{
+ "id": "{2EC7DFA0-62D9-2E92-ADB1-6B8201D142FA}",
+ "name": "MuellMax",
+ "type": 3,
+ "vendor": "",
+ "aliases": [
+ "Abfallwirtschaft (MüllMax)",
+ "Entsorgungskalender (MüllMax)"
+ ],
+ "url": "https://wilkware.de/ip-symcon-module/abfallwirtschaft/",
+ "parentRequirements": [],
+ "childRequirements": [],
+ "implemented": [],
+ "prefix": "MAXDE"
+}
\ No newline at end of file
diff --git a/MuellMax/module.php b/MuellMax/module.php
new file mode 100644
index 0000000..4869ed3
--- /dev/null
+++ b/MuellMax/module.php
@@ -0,0 +1,1059 @@
+RegisterPropertyString('serviceProvider', self::SERVICE_PROVIDER);
+ // Waste Management
+ $this->RegisterPropertyString('disposalID', 'null');
+ $this->RegisterPropertyString('cityID', 'null');
+ $this->RegisterPropertyString('streetID', 'null');
+ $this->RegisterPropertyString('addonID', 'null');
+ for ($i = 1; $i <= static::$FRACTIONS; $i++) {
+ $this->RegisterPropertyBoolean('fractionID' . $i, false);
+ }
+ // Advanced Settings
+ $this->RegisterPropertyBoolean('settingsActivate', true);
+ $this->RegisterPropertyBoolean('settingsVariables', false);
+ $this->RegisterPropertyInteger('settingsScript', 0);
+ $this->RegisterPropertyBoolean('settingsTileVisu', false);
+ $this->RegisterPropertyString('settingsTileSkin', 'dark');
+ // Attributes for dynamic configuration forms (> v3.0)
+ $this->RegisterAttributeString('io', serialize($this->PrepareIO()));
+ // Register daily update timer
+ $this->RegisterTimer('UpdateTimer', 0, 'MAXDE_Update(' . $this->InstanceID . ');');
+ }
+
+ /**
+ * Configuration Form.
+ *
+ * @return JSON configuration string.
+ */
+ public function GetConfigurationForm()
+ {
+ // Settings
+ $activate = $this->ReadPropertyBoolean('settingsActivate');
+ // IO Values
+ $dId = $this->ReadPropertyString('disposalID');
+ $cId = $this->ReadPropertyString('cityID');
+ $sId = $this->ReadPropertyString('streetID');
+ $aId = $this->ReadPropertyString('addonID');
+ // Debug output
+ $this->SendDebug(__FUNCTION__, 'disposalID=' . $dId . ', cityID=' . $cId . ', streetId=' . $sId . ', addonId=' . $aId);
+
+ // Get Basic Form
+ $jsonForm = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
+ // Service Provider
+ $jsonForm['elements'][self::ELEM_PROVI]['items'][0]['options'] = $this->GetProviderOptions();
+ // Waste Management
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][0]['items'][0]['options'] = $this->GetClientOptions(self::SERVICE_PROVIDER);
+
+ // Prompt
+ $prompt = ['caption' => $this->Translate('Please select ...') . str_repeat(' ', 79), 'value' => 'null'];
+ // go throw the whole way
+ $args = [];
+ $next = true;
+ // Build io array
+ $io = $this->PrepareIO();
+ // Disposal
+ if ($dId != 'null') {
+ $io[self::IO_DISPOSAL] = $dId;
+ $this->SendDebug(__FUNCTION__, 'ACTION: Init Disposl!');
+ $this->ExecuteAction($io);
+ if ($io[self::IO_SECURE] == '') {
+ $this->SendDebug(__FUNCTION__, 'Init secure token failed!');
+ $next = false;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ // City or Streets
+ if ($next) {
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'mm_aus_ort.x=1';
+ $args[] = 'mm_aus_ort.y=1';
+ $this->SendDebug(__FUNCTION__, 'ACTION: City or Street!');
+ $options = $this->ExecuteAction($io, $args);
+ // no city only streets
+ if ($io[self::IO_ACTION] != self::ACTION_CITY) {
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_name=';
+ $args[] = 'mm_aus_str_txt_submit=suchen';
+ $this->SendDebug(__FUNCTION__, 'ACTION: No city only streets!');
+ $options = $this->ExecuteAction($io, $args);
+ }
+ if (($io[self::IO_ACTION] != self::ACTION_CITY) && ($io[self::IO_ACTION] != self::ACTION_STREET)) {
+ $this->SendDebug(__FUNCTION__, 'No city or street received: ' . $io[self::IO_ACTION]);
+ $next = false;
+ }
+ }
+ // City
+ if ($next) {
+ if ($io[self::IO_ACTION] == self::ACTION_CITY) {
+ if ($options != null) {
+ // Always add the selection prompt
+ array_unshift($options, $prompt);
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][1]['items'][0]['options'] = $options;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][1]['items'][0]['visible'] = true;
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ if ($cId != 'null') {
+ $io[self::IO_CITY] = $cId;
+ // than prepeare the next
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_ort_sel=' . $io[self::IO_CITY];
+ $args[] = 'mm_aus_ort_submit=weiter';
+ $this->SendDebug(__FUNCTION__, 'ACTION: City and now streets!');
+ $options = $this->ExecuteAction($io, $args);
+ // prepeare street ?
+ if ($io[self::IO_ACTION] != self::ACTION_STREET) {
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_name=';
+ $args[] = 'mm_aus_str_txt_submit=suchen';
+ $options = $this->ExecuteAction($io, $args);
+ }
+ if ($options == null) {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $data[] = ['caption' => $this->Translate('Please select ...') . str_repeat(' ', 79), 'value' => $cId];
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][1]['items'][0]['options'] = $data;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][1]['items'][0]['visible'] = false;
+ }
+ }
+ // Street
+ if ($next) {
+ if ($io[self::IO_ACTION] == self::ACTION_STREET) {
+ if ($options != null) {
+ // Always add the selection prompt
+ array_unshift($options, $prompt);
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][0]['options'] = $options;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][0]['visible'] = true;
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ if ($sId != 'null') {
+ $io[self::IO_STREET] = $sId;
+ // than prepeare the next
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_sel=' . $io[self::IO_STREET];
+ $args[] = 'mm_aus_str_sel_submit=weiter';
+ $this->SendDebug(__FUNCTION__, 'ACTION: Street selected!');
+ $options = $this->ExecuteAction($io, $args);
+ // Get Fractions ?
+ if ($io[self::IO_ACTION] != self::ACTION_ADDON) {
+ $io[self::IO_ACTION] = self::ACTION_FRACTIONS;
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_ica_auswahl=iCalendar-Datei';
+ $this->SendDebug(__FUNCTION__, 'ACTION: No Addon - get fractions!');
+ $options = $this->ExecuteAction($io, $args);
+ }
+ if ($options == null) {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $data[] = ['caption' => $this->Translate('Please select ...') . str_repeat(' ', 79), 'value' => $sId];
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][0]['options'] = $data;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][0]['visible'] = false;
+ }
+ }
+ // Addon
+ if ($next) {
+ if ($io[self::IO_ACTION] == self::ACTION_ADDON) {
+ $this->SendDebug(__FUNCTION__, 'ADDON');
+ if ($options != null) {
+ // Always add the selection prompt
+ array_unshift($options, $prompt);
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][1]['options'] = $options;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][1]['visible'] = true;
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ if ($aId != 'null') {
+ $io[self::IO_ADDON] = $aId;
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_hnr_sel=' . $io[self::IO_ADDON];
+ $args[] = 'mm_aus_hnr_sel_submit=weiter';
+ $this->SendDebug(__FUNCTION__, 'ACTION: Addon selected!');
+ $options = $this->ExecuteAction($io, $args);
+ // Get Fractions
+ $io[self::IO_ACTION] = self::ACTION_FRACTIONS;
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_ica_auswahl=iCalendar-Datei';
+ $this->SendDebug(__FUNCTION__, 'ACTION: And now fractions!');
+ $options = $this->ExecuteAction($io, $args);
+ if ($options == null) {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $data[] = ['caption' => $this->Translate('Please select ...') . str_repeat(' ', 79), 'value' => $aId];
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][1]['options'] = $data;
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][2]['items'][1]['visible'] = false;
+ }
+ }
+ // Fractions
+ if ($next) {
+ if ($io[self::IO_ACTION] == self::ACTION_FRACTIONS) {
+ if ($options != null) {
+ // Label
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][3]['visible'] = true;
+ $i = 1;
+ foreach ($options as $fract) {
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][$i + 3]['caption'] = $fract['caption'];
+ $jsonForm['elements'][self::ELEM_WASTE]['items'][$i + 3]['visible'] = true;
+ $i++;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ } else {
+ $this->SendDebug(__FUNCTION__, __LINE__);
+ $next = false;
+ }
+ }
+
+ // Write IO array
+ $this->WriteAttributeString('io', serialize($io));
+
+ // Debug output
+ $this->SendDebug(__FUNCTION__, $io);
+ // Return Form
+ return json_encode($jsonForm);
+ }
+
+ public function ApplyChanges()
+ {
+ //Never delete this line!
+ parent::ApplyChanges();
+ $dId = $this->ReadPropertyString('disposalID');
+ $cId = $this->ReadPropertyString('cityID');
+ $sId = $this->ReadPropertyString('streetID');
+ $aId = $this->ReadPropertyString('addonID');
+ $activate = $this->ReadPropertyBoolean('settingsActivate');
+ $tilevisu = $this->ReadPropertyBoolean('settingsTileVisu');
+ $this->SendDebug(__FUNCTION__, 'disposalID=' . $dId . ', cityID=' . $cId . ', streetId=' . $sId . ', addonId=' . $aId);
+ // Safty default
+ $this->SetTimerInterval('UpdateTimer', 0);
+ // Support for Tile Viso (v7.x)
+ $this->MaintainVariable('Widget', $this->Translate('Pickup'), vtString, '~HTMLBox', 0, $tilevisu);
+ // Set status
+ if ($dId == 'null') {
+ $status = 201;
+ } elseif (($cId == 'null') && ($sId == 'null') && ($aId == 'null')) {
+ $status = 202;
+ } else {
+ $status = 102;
+ }
+ // All okay
+ if ($status == 102) {
+ $this->CreateVariables();
+ if ($activate == true) {
+ // Time neu berechnen
+ $this->UpdateTimerInterval('UpdateTimer', 0, 10, 0);
+ $this->SendDebug(__FUNCTION__, 'Timer aktiviert!');
+ } else {
+ $status = 104;
+ }
+ }
+ $this->SetStatus($status);
+ }
+
+ /**
+ * RequestAction.
+ *
+ * @param string $ident Ident (function name).
+ * @param string $value Value.
+ */
+ public function RequestAction($ident, $value)
+ {
+ // Debug output
+ $this->SendDebug(__FUNCTION__, $ident . ' => ' . $value);
+ eval('$this->' . $ident . '(\'' . $value . '\');');
+ return true;
+ }
+
+ /**
+ * This function will be available automatically after the module is imported with the module control.
+ * Using the custom prefix this function will be callable from PHP and JSON-RPC through:.
+ *
+ * MAXDE_Update($id);
+ */
+ public function Update()
+ {
+ // Check instance state
+ if ($this->GetStatus() != 102) {
+ $this->SendDebug(__FUNCTION__, 'Status: Instance is not active.');
+ return;
+ }
+ $io = unserialize($this->ReadAttributeString('io'));
+ $this->SendDebug(__FUNCTION__, $io);
+
+ // (1) Build io array & init
+ $uio = $this->PrepareIO();
+ $uio[self::IO_DISPOSAL] = $io[self::IO_DISPOSAL];
+ $this->ExecuteAction($uio);
+ if ($uio[self::IO_SECURE] == '') {
+ $this->SendDebug(__FUNCTION__, 'Init secure token failed!');
+ return;
+ }
+ // (2) Request city or an empty street search field
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'mm_aus_ort.x=1';
+ $args[] = 'mm_aus_ort.y=1';
+ $this->ExecuteAction($uio, $args);
+ // (3) We have a city - select it
+ if ($io[self::IO_CITY] != '') {
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_ort_sel=' . $io[self::IO_CITY];
+ $args[] = 'mm_aus_ort_submit=weiter';
+ $options = $this->ExecuteAction($uio, $args);
+ }
+ // (4) Select street
+ if ($io[self::IO_STREET] != '') {
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_name=';
+ $args[] = 'mm_aus_str_txt_submit=suchen';
+ $this->ExecuteAction($uio, $args);
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_sel=' . $io[self::IO_STREET];
+ $args[] = 'mm_aus_str_sel_submit=weiter';
+ $this->ExecuteAction($uio, $args);
+ }
+ // (5) Select street addon
+ if ($io[self::IO_ADDON] != '') {
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_hnr_sel=' . $io[self::IO_ADDON];
+ $args[] = 'mm_aus_hnr_sel_submit=weiter';
+ $this->ExecuteAction($uio, $args);
+ }
+ // (6) Get Fractions
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_ica_auswahl=iCalendar-Datei';
+ $this->ExecuteAction($uio, $args);
+ // (7) Get ics file
+ unset($args);
+ $args[] = 'mm_ses=' . $uio[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_type=termine';
+ // fractions convert to name => ident
+ $waste = [];
+ foreach ($io[self::IO_NAMES] as $ident => $name) {
+ $this->SendDebug(__FUNCTION__, 'Fraction ident: ' . $ident . ', Name: ' . $name);
+ $waste[$name] = ['ident' => $ident, 'date' => ''];
+ $args[] = 'mm_frm_fra_' . $ident . '=' . $ident;
+ }
+ $args[] = 'mm_ica_gen=iCalendar-Datei laden';
+ // service request
+ $url = $this->BuildURL($io['key']);
+ $request = implode('&', $args);
+ $response = $this->ServiceRequest($url, $request);
+ try {
+ $ical = new ICal(false, [
+ 'defaultSpan' => 2, // Default value
+ 'defaultTimeZone' => 'UTC',
+ 'defaultWeekStart' => 'MO', // Default value
+ 'disableCharacterReplacement' => false, // Default value
+ 'filterDaysAfter' => null, // Default value
+ 'filterDaysBefore' => null, // Default value
+ 'skipRecurrence' => false, // Default value
+ ]);
+ $ical->initString($response);
+ } catch (Exception $e) {
+ $this->SendDebug(__FUNCTION__, 'initICS: ' . $e);
+ return;
+ }
+ // get all events
+ $events = $ical->events();
+ // go throw all events
+ $this->SendDebug(__FUNCTION__, 'ICS Events: ' . $ical->eventCount);
+ foreach ($events as $event) {
+ $this->SendDebug(__FUNCTION__, 'Event: ' . $event->summary . ' = ' . $event->dtstart);
+ // echo $event->printData('%s: %s'.PHP_EOL);
+ if ($event->dtstart < date('Ymd')) {
+ continue;
+ }
+ // YYYYMMDD umwandeln in DD.MM.YYYY
+ $day = substr($event->dtstart, 6) . '.' . substr($event->dtstart, 4, 2) . '.' . substr($event->dtstart, 0, 4);
+ // Update fraction
+ $name = $event->summary;
+ // Name could be prefix/suffix :(
+ foreach ($io[self::IO_NAMES] as $ident => $fname) {
+ if (strstr($name, $fname) !== false) {
+ $name = $fname;
+ break;
+ }
+ }
+ if (isset($waste[$name]) && $waste[$name]['date'] == '') {
+ $waste[$name]['date'] = $day;
+ $this->SendDebug(__FUNCTION__, 'Fraction date: ' . $name . ' = ' . $day);
+ }
+ }
+
+ // write data to variable
+ foreach ($waste as $key => $var) {
+ $this->SetValueString((string) $var['ident'], $var['date']);
+ }
+
+ // build tile widget
+ $btw = $this->ReadPropertyBoolean('settingsTileVisu');
+ $skin = $this->ReadPropertyString('settingsTileSkin');
+ $this->SendDebug(__FUNCTION__, 'TileVisu: ' . $btw . '(' . $skin . ')');
+ if ($btw == true) {
+ $this->BuildWidget($waste, $skin);
+ }
+
+ // execute Script
+ $script = $this->ReadPropertyInteger('settingsScript');
+ if ($script != 0) {
+ if (IPS_ScriptExists($script)) {
+ $rs = IPS_RunScript($script);
+ $this->SendDebug(__FUNCTION__, 'Script Execute (Return Value): ' . $rs, 0);
+ } else {
+ $this->SendDebug(__FUNCTION__, 'Update: Script #' . $script . ' existiert nicht!');
+ }
+ }
+
+ // calculate next update interval
+ $activate = $this->ReadPropertyBoolean('settingsActivate');
+ if ($activate == true) {
+ $this->UpdateTimerInterval('UpdateTimer', 0, 10, 0);
+ }
+ }
+
+ /**
+ * User has selected a new waste management.
+ *
+ * @param string $id Disposal ID .
+ */
+ protected function OnChangeDisposal($id)
+ {
+ // ACTION: 'init', KEY: $id
+ $io = $this->PrepareIO(self::ACTION_INIT, $id);
+ $this->SendDebug(__FUNCTION__, $io);
+ $data = null;
+ if ($id != 'null') {
+ // Init
+ $data = $this->ExecuteAction($io);
+ }
+ // City or Streets
+ $args = [];
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'mm_aus_ort.x=1';
+ $args[] = 'mm_aus_ort.y=1';
+ $data = $this->ExecuteAction($io, $args);
+ // no city only streets
+ if ($io[self::IO_ACTION] != 'city') {
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_name=';
+ $args[] = 'mm_aus_str_txt_submit=suchen';
+ $data = $this->ExecuteAction($io, $args);
+ }
+ $this->SendDebug(__FUNCTION__, $io);
+ // Hide or Unhide properties
+ $this->UpdateForm($io, $data);
+ // Update attribute
+ $this->WriteAttributeString('io', serialize($io));
+ }
+
+ /**
+ * User has selected a new city.
+ *
+ * @param string $id City ID .
+ */
+ protected function OnChangeCity($id)
+ {
+ $this->SendDebug(__FUNCTION__, $id);
+ $io = unserialize($this->ReadAttributeString('io'));
+ $this->UpdateIO($io, self::ACTION_CITY, $id);
+ $data = null;
+ if ($id != 'null') {
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_ort_sel=' . $io[self::IO_CITY];
+ $args[] = 'mm_aus_ort_submit=weiter';
+ $data = $this->ExecuteAction($io, $args);
+ }
+ if ($io[self::IO_ACTION] != self::ACTION_STREET) {
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_name=';
+ $args[] = 'mm_aus_str_txt_submit=suchen';
+ $data = $this->ExecuteAction($io, $args);
+ } else {
+ $this->SendDebug(__FUNCTION__, 'No street for city!');
+ $this->SendDebug(__FUNCTION__, $io);
+ }
+ // Hide or Unhide properties
+ $this->UpdateForm($io, $data);
+ // Update attribute
+ $this->WriteAttributeString('io', serialize($io));
+ }
+
+ /**
+ * Benutzer hat eine neue Straße ausgewählt.
+ *
+ * @param string $id Street ID .
+ */
+ protected function OnChangeStreet($id)
+ {
+ $this->SendDebug(__FUNCTION__, $id);
+ $io = unserialize($this->ReadAttributeString('io'));
+ $this->UpdateIO($io, self::ACTION_STREET, $id);
+ $data = null;
+ if ($id != 'null') {
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_str_sel=' . $io[self::IO_STREET];
+ $args[] = 'mm_aus_str_sel_submit=weiter';
+ $data = $this->ExecuteAction($io, $args);
+ // Get Fractions ?
+ if ($io[self::IO_ACTION] != self::ACTION_ADDON) {
+ $io[self::IO_ACTION] = self::ACTION_FRACTIONS;
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_ica_auswahl=iCalendar-Datei';
+ $data = $this->ExecuteAction($io, $args);
+ }
+ }
+ // Hide or Unhide properties
+ $this->UpdateForm($io, $data);
+ // Update attribute
+ $this->WriteAttributeString('io', serialize($io));
+ }
+
+ /**
+ * Benutzer hat eine neue Hausnummer ausgewählt.
+ *
+ * @param string $id Addon ID .
+ */
+ protected function OnChangeAddon($id)
+ {
+ $this->SendDebug(__FUNCTION__, $id);
+ $io = unserialize($this->ReadAttributeString('io'));
+ $this->UpdateIO($io, self::ACTION_ADDON, $id);
+ $data = null;
+ if ($id != 'null') {
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_frm_hnr_sel=' . $io[self::IO_ADDON];
+ $args[] = 'mm_aus_hnr_sel_submit=weiter';
+ $data = $this->ExecuteAction($io, $args);
+ // Get Fractions
+ $io[self::IO_ACTION] = self::ACTION_FRACTIONS;
+ unset($args);
+ $args[] = 'mm_ses=' . $io[self::IO_SECURE];
+ $args[] = 'xxx=1';
+ $args[] = 'mm_ica_auswahl=iCalendar-Datei';
+ $data = $this->ExecuteAction($io, $args);
+ }
+ $this->SendDebug(__FUNCTION__, $data);
+ // Hide or Unhide properties
+ $this->UpdateForm($io, $data);
+ // Update attribute
+ $this->WriteAttributeString('io', serialize($io));
+ }
+
+ /**
+ * Hide/unhide form fields.
+ *
+ */
+ protected function UpdateForm($io, $options)
+ {
+ $this->SendDebug(__FUNCTION__, $io);
+ $this->SendDebug(__FUNCTION__, $options);
+ if (($options != null) && ($io[self::IO_ACTION] != self::ACTION_FRACTIONS)) {
+ // Always add the selection prompt
+ $prompt = ['caption' => $this->Translate('Please select ...') . str_repeat(' ', 79), 'value' => 'null'];
+ array_unshift($options, $prompt);
+ }
+ switch ($io[self::IO_ACTION]) {
+ // Disposal selected
+ case self::ACTION_INIT:
+ $this->UpdateFormField('cityID', 'visible', false);
+ $this->UpdateFormField('streetID', 'visible', false);
+ $this->UpdateFormField('addonID', 'visible', false);
+ $this->UpdateFormField('cityID', 'value', 'null');
+ $this->UpdateFormField('streetID', 'value', 'null');
+ $this->UpdateFormField('addonID', 'value', 'null');
+ // Fraction Checkboxes
+ $this->UpdateFormField('fractionLabel', 'visible', false);
+ for ($i = 1; $i <= static::$FRACTIONS; $i++) {
+ $this->UpdateFormField('fractionID' . $i, 'visible', false);
+ $this->UpdateFormField('fractionID' . $i, 'value', false);
+ }
+ break;
+ // City selected
+ case self::ACTION_CITY:
+ $this->UpdateFormField('cityID', 'visible', true);
+ $this->UpdateFormField('cityID', 'value', 'null');
+ if ($options != null) {
+ $this->UpdateFormField('cityID', 'options', json_encode($options));
+ }
+ // Elements below
+ $this->UpdateFormField('streetID', 'visible', false);
+ $this->UpdateFormField('addonID', 'visible', false);
+ $this->UpdateFormField('streetID', 'value', 'null');
+ $this->UpdateFormField('addonID', 'value', 'null');
+ // Fraction Checkboxes
+ $this->UpdateFormField('fractionLabel', 'visible', false);
+ for ($i = 1; $i <= static::$FRACTIONS; $i++) {
+ $this->UpdateFormField('fractionID' . $i, 'visible', false);
+ $this->UpdateFormField('fractionID' . $i, 'value', false);
+ }
+ break;
+ // Street selected
+ case self::ACTION_STREET:
+ if ($io['mm_city'] == '') {
+ $this->UpdateFormField('cityID', 'visible', false);
+ $this->UpdateFormField('cityID', 'value', 'null');
+ }
+ $this->UpdateFormField('streetID', 'visible', true);
+ $this->UpdateFormField('streetID', 'value', 'null');
+ if ($options != null) {
+ $this->UpdateFormField('streetID', 'options', json_encode($options));
+ }
+ // Elements below
+ $this->UpdateFormField('addonID', 'visible', false);
+ $this->UpdateFormField('addonID', 'value', 'null');
+ // Fraction Checkboxes
+ $this->UpdateFormField('fractionLabel', 'visible', false);
+ for ($i = 1; $i <= static::$FRACTIONS; $i++) {
+ $this->UpdateFormField('fractionID' . $i, 'visible', false);
+ $this->UpdateFormField('fractionID' . $i, 'value', false);
+ }
+ break;
+ // Addon number selected
+ case self::ACTION_ADDON:
+ $this->UpdateFormField('addonID', 'visible', true);
+ $this->UpdateFormField('addonID', 'value', 'null');
+ if ($options != null) {
+ $this->UpdateFormField('addonID', 'options', json_encode($options));
+ }
+ // Fraction Checkboxes
+ $this->UpdateFormField('fractionLabel', 'visible', false);
+ for ($i = 1; $i <= static::$FRACTIONS; $i++) {
+ $this->UpdateFormField('fractionID' . $i, 'visible', false);
+ $this->UpdateFormField('fractionID' . $i, 'value', false);
+ }
+ break;
+ // Fractions selected
+ case self::ACTION_FRACTIONS:
+ $this->UpdateFormField('labelFraction', 'visible', true);
+ $f = 1;
+ foreach ($options as $fract) {
+ $this->UpdateFormField('fractionID' . $f, 'visible', true);
+ $this->UpdateFormField('fractionID' . $f, 'caption', $fract['caption']);
+ $f++;
+ }
+ // hide all others
+ for ($i = $f; $i <= static::$FRACTIONS; $i++) {
+ $this->UpdateFormField('fractionID' . $i, 'visible', false);
+ $this->UpdateFormField('fractionID' . $i, 'value', false);
+ }
+ break;
+ }
+ }
+
+ /**
+ * Create the variables for the fractions.
+ *
+ */
+ protected function CreateVariables()
+ {
+ $io = unserialize($this->ReadAttributeString('io'));
+ $this->SendDebug(__FUNCTION__, $io);
+ if (empty($io[self::IO_NAMES])) {
+ return;
+ }
+ // how to maintain?
+ $variable = $this->ReadPropertyBoolean('settingsVariables');
+ $i = 1;
+ $ids = explode(',', $io[self::IO_FRACTIONS]);
+ foreach ($ids as $fract) {
+ if ($i <= static::$FRACTIONS) {
+ $enabled = $this->ReadPropertyBoolean('fractionID' . $i);
+ $this->MaintainVariable($fract, $io[self::IO_NAMES][$fract], vtString, '', $i, $enabled || $variable);
+ }
+ $i++;
+ }
+ }
+
+ /**
+ * Serialize properties to IO interface array
+ *
+ * @param string $n next from action
+ * @param string $d disposal id value
+ * @param string $c city id value
+ * @param string $s street id value
+ * @param string $a addon id value
+ * @param string $f fraction id value
+ * @return array IO interface
+ */
+ protected function PrepareIO($n = null, $d = 'null', $c = 'null', $s = 'null', $a = 'null', $f = 'null')
+ {
+ $io[self::IO_ACTION] = ($n != null) ? $n : self::ACTION_INIT;
+ $io[self::IO_DISPOSAL] = ($d != 'null') ? $d : '';
+ $io[self::IO_CITY] = ($c != 'null') ? $c : '';
+ $io[self::IO_STREET] = ($s != 'null') ? $s : '';
+ $io[self::IO_ADDON] = ($a != 'null') ? $a : '';
+ $io[self::IO_FRACTIONS] = ($f != 'null') ? $f : '';
+ $io[self::IO_SECURE] = '';
+ $io[self::IO_NAMES] = [];
+ // data2array
+ return $io;
+ }
+
+ /**
+ * Everthing has changed - update the IO array
+ *
+ * @param array $io IO interface array
+ * @param string $action new form action
+ * @param string $id new selected form value
+ */
+ protected function UpdateIO(&$io, $action, $id)
+ {
+ $this->SendDebug(__FUNCTION__, $action);
+ $this->SendDebug(__FUNCTION__, $id);
+ // tage over the action
+ $io[self::IO_ACTION] = $action;
+
+ if ($action == self::ACTION_ADDON) {
+ $io[self::IO_ADDON] = ($id != 'null') ? $id : '';
+ return;
+ } else {
+ $io[self::IO_ADDON] = '';
+ $io[self::IO_FRACTIONS] = '';
+ $io[self::IO_NAMES] = [];
+ }
+
+ if ($action == self::ACTION_STREET) {
+ $io[self::IO_STREET] = ($id != 'null') ? $id : '';
+ return;
+ } else {
+ $io[self::IO_STREET] = '';
+ }
+
+ if ($action == self::ACTION_CITY) {
+ $io[self::IO_CITY] = ($id != 'null') ? $id : '';
+ return;
+ } else {
+ $io[self::IO_CITY] = '';
+ }
+
+ if ($action == self::ACTION_INIT) {
+ $io[self::IO_DISPOSAL] = ($id != 'null') ? $id : '';
+ return;
+ } else {
+ $io[self::IO_DISPOSAL] = '';
+ }
+ }
+
+ /**
+ * Builds the POST/GET Url for the API CALLS
+ *
+ * @param string $key Disposal ID
+ * @param string $action Get parameter action.
+ */
+ protected function BuildURL($key)
+ {
+ $url = '{{base}}{{key}}/res/{{start}}Start.php';
+ $str = ['base' => self::SERVICE_BASEURL, 'key' => strtolower($key), 'start' => $key];
+ // replace all
+ if (preg_match_all('/{{(.*?)}}/', $url, $m)) {
+ foreach ($m[1] as $i => $varname) {
+ $url = str_replace($m[0][$i], sprintf('%s', $str[$varname]), $url);
+ }
+ }
+ $this->SendDebug(__FUNCTION__, $url);
+ return $url;
+ }
+
+ /**
+ * Sends the action url and data to the service provider
+ *
+ * @param $io service array
+ * @param $args forms array
+ * @return array New selecteable options or null.
+ */
+ protected function ExecuteAction(&$io, $args = [])
+ {
+ $this->SendDebug(__FUNCTION__, $io);
+ // Build URL data
+ $url = $this->BuildURL($io['key']);
+ // GET or POST data
+ $request = null;
+ if (!empty($args)) {
+ $request = implode('&', $args);
+ }
+ $this->SendDebug(__FUNCTION__, 'Rerquest: ' . $request);
+ // Request FORM (xpath)
+ $res = $this->GetDocument($url, $request);
+ $data = null;
+ // Collect DATA
+ if ($res !== false) {
+ // INIT and all following
+ $inputs = $res->query("//input[@type='hidden']");
+ foreach ($inputs as $input) {
+ $name = $input->getAttribute('name');
+ $value = $input->getAttribute('value');
+ if (array_key_exists($name, $io)) {
+ $io[$name] = $value;
+ }
+ $this->SendDebug(__FUNCTION__, 'Hidden: ' . $name . ':' . $value);
+ }
+ // INIT and disposal has cities
+ $select = $res->query("//select[@name='mm_frm_ort_sel']");
+ if ($select->length > 0) {
+ $io[self::IO_ACTION] = 'city';
+ $options = $res->query('.//option', $select[0]);
+ if ($options->length > 0) {
+ foreach ($options as $option) {
+ $value = $option->getAttribute('value');
+ $name = $option->nodeValue;
+ if ($value == 0) {
+ continue;
+ }
+ $data[] = ['caption' => $name, 'value' => $value];
+ //$this->SendDebug(__FUNCTION__, 'City: ' . $name . ':' . $value);
+ }
+ $this->SendDebug(__FUNCTION__, 'RETURN : City');
+ return $data;
+ }
+ }
+ // streets
+ $select = $res->query("//select[@name='mm_frm_str_sel']");
+ if ($select->length > 0) {
+ $io[self::IO_ACTION] = 'street';
+ $options = $res->query('.//option', $select[0]);
+ if ($options->length > 0) {
+ foreach ($options as $option) {
+ $value = $option->getAttribute('value');
+ $name = $option->nodeValue;
+ if ($value == 0) {
+ continue;
+ }
+ $data[] = ['caption' => $name, 'value' => $value];
+ //$this->SendDebug(__FUNCTION__, 'Street: ' . $name . ':' . $value);
+ }
+ $this->SendDebug(__FUNCTION__, 'RETURN : Street');
+ return $data;
+ }
+ }
+ // addon
+ $select = $res->query("//select[@name='mm_frm_hnr_sel']");
+ if ($select->length > 0) {
+ $io[self::IO_ACTION] = 'addon';
+ $options = $res->query('.//option', $select[0]);
+ if ($options->length > 0) {
+ foreach ($options as $option) {
+ $value = $option->getAttribute('value');
+ $name = $option->nodeValue;
+ if ($value == 0) {
+ continue;
+ }
+ $data[] = ['caption' => $name, 'value' => $value];
+ //$this->SendDebug(__FUNCTION__, 'Addon: ' . $name . ':' . $value);
+ }
+ $this->SendDebug(__FUNCTION__, 'RETURN : Addon');
+ return $data;
+ }
+ }
+ // fraction
+
+ $divs = $res->query("//div[@class='m_artsel_ical']");
+ if ($divs->length > 0) {
+ $this->SendDebug(__FUNCTION__, 'Fractions: YES');
+ $fractions = [];
+ $name = [];
+ foreach ($divs as $div) {
+ $inputs = $res->query(".//input[@type='checkbox']", $div);
+ $spans = $res->query(".//span[@class='m_artsel_text']/text()", $div);
+ $name = $spans->item(0)->nodeValue; // clear name
+ $value = $inputs->item(0)->getAttribute('value'); // value
+ // store
+ $data[] = ['caption' => $name, 'value' => $inputs->item(0)->getAttribute('value')];
+ $fractions[] = $value;
+ $names[$value] = $name;
+ $this->SendDebug(__FUNCTION__, 'Fraction: ' . $name . ':' . $value);
+ }
+ $io[self::IO_FRACTIONS] = implode(',', array_unique($fractions));
+ $io[self::IO_NAMES] = $names;
+ }
+ }
+ $this->SendDebug(__FUNCTION__, 'RETURN : Last');
+ return $data;
+ }
+
+ /**
+ * Sends the API call and transform it to a XPath Document
+ *
+ * @param string $url Request URL
+ * @param string $request Request parameters
+ * @return mixed DOM document
+ */
+ protected function GetDocument($url, $request)
+ {
+ $response = $this->ServiceRequest($url, $request);
+ if ($response !== false) {
+ //$this->SendDebug(__FUNCTION__, $response);
+ $dom = new DOMDocument();
+ // disable libxml errors
+ libxml_use_internal_errors(true);
+ $dom->loadHTML(mb_convert_encoding($response, 'HTML-ENTITIES', 'UTF-8'));
+ // remove errors for yucky html
+ libxml_clear_errors();
+ $xpath = new DOMXpath($dom);
+ return $xpath;
+ }
+ return $response;
+ }
+
+ /**
+ * Sends the API call
+ *
+ * @param string $url Rewquest URL
+ * @param string $request If $request not null, we will send a POST request, else a GET request.
+ * @param string $method Over the $method parameter can we force a POST or GET request!
+ * @return mixed False if the response is null, otherwise the response
+ */
+ protected function ServiceRequest($url, $request, $method = 'GET')
+ {
+ // Return
+ $ret = false;
+ // CURL
+ $curl = curl_init();
+ curl_setopt($curl, CURLOPT_URL, $url);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
+ curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
+ curl_setopt($curl, CURLOPT_USERAGENT, self::SERVICE_USERAGENT);
+ if ($request != null) {
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST');
+ curl_setopt($curl, CURLOPT_POSTFIELDS, $request);
+ } else {
+ curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $method);
+ }
+ curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
+ $response = curl_exec($curl);
+ curl_close($curl);
+ //$this->SendDebug(__FUNCTION__, $response);
+ if ($response != null) {
+ return $response;
+ }
+ return $ret;
+ }
+
+ /**
+ * Checks if a string starts with a given substring
+ *
+ * @param string $haystack The string to search in.
+ * @param string $needle The substring to search for in the haystack.
+ * @param bool Returns true if haystack begins with needle, false otherwise.
+ */
+ private function StartsWith($haystack, $needle)
+ {
+ return (string) $needle !== '' && strncmp($haystack, $needle, strlen($needle)) === 0;
+ }
+}
diff --git a/MyMuell/README.md b/MyMuell/README.md
index 320ea87..e5a359b 100644
--- a/MyMuell/README.md
+++ b/MyMuell/README.md
@@ -1,10 +1,10 @@
# MyMüll
[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
-[![Version](https://img.shields.io/badge/Modul%20Version-2.0.20230102-orange.svg)](https://github.com/Wilkware/IPSymconAwido)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-3.0.20231119-orange.svg)](https://github.com/Wilkware/WasteManagement)
[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-[![Actions](https://github.com/Wilkware/IPSymconAwido/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconAwido/actions)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
IP-Symcon Modul für die Visualisierung von Entsorgungsterminen.
@@ -27,13 +27,13 @@ Derzeit unterstützt das Modul über 400 verschiedene Gebiete. Wenn jemand noch
### 2. Voraussetzungen
-* IP-Symcon ab Version 6.0
+* IP-Symcon ab Version 6.4
### 3. Installation
* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
* Alternativ Über das Modul-Control folgende URL hinzufügen.
-`https://github.com/Wilkware/IPSymconAwido` oder `git://github.com/Wilkware/IPSymconAwido.git`
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
### 4. Einrichten der Instanzen in IP-Symcon
@@ -106,6 +106,11 @@ __Beispiel__: `MYMDE_Update(12345);`
### 8. Versionshistorie
+v3.0.20231119
+
+* _NEU_: Kompatibilität auf IPS 6.4 hoch gesetzt
+* _NEU_: Support für v7 Visualisierung
+
v2.0.20230102
* _FIX_: Komplette Konfigurationsumstellung wegen wechselnden IDs
diff --git a/MyMuell/form.json b/MyMuell/form.json
index d3766e1..e192b12 100644
--- a/MyMuell/form.json
+++ b/MyMuell/form.json
@@ -254,6 +254,27 @@
"name": "settingsVariables",
"caption": "Create variables for non-selected disposals?"
},
+ {
+ "type": "CheckBox",
+ "name": "settingsTileVisu",
+ "caption": "Activate support for Tile Visu?"
+ },
+ {
+ "type": "Select",
+ "name": "settingsTileSkin",
+ "caption": "Theme to be used (design):",
+ "width": "450px",
+ "options": [
+ {
+ "label": "Light Skin",
+ "value": "light"
+ },
+ {
+ "label": "Dark Skin",
+ "value": "dark"
+ }
+ ]
+ },
{
"type": "SelectScript",
"name": "settingsScript",
diff --git a/MyMuell/locale.json b/MyMuell/locale.json
index b9d1892..446bb4a 100644
--- a/MyMuell/locale.json
+++ b/MyMuell/locale.json
@@ -17,6 +17,27 @@
"... call the following scipt after update the dates:": "... nach Aktualisierung der Werte folgendes Script aufrufen:",
"Subsequent execution of a script:": "Anschließendes Ausführen eines Skriptes:",
"Script:": "Script:",
+ "Activate support for Tile Visu?": "Unterstützung für Tile Visu aktivieren?",
+ "Theme to be used (design):": "Zu verwendendes Theme (Design):",
+ "Dark": "Dunkel",
+ "Light": "Hell",
+ "Waste": "Abfall",
+ "Pickup": "Abholung",
+ "Removal": "Abfuhr",
+ "Date": "Termin",
+ "Today": "Heute",
+ "Tomorrow": "Morgen",
+ "days": "Tage",
+ "day": "Tag",
+ "Next pickup:": "Nächste Abholung:",
+ "on": "am",
+ "Monday": "Montag",
+ "Tuesday": "Dienstag",
+ "Wednesday": "Mittwoch",
+ "Thursday": "Donnerstag",
+ "Friday": "Freitag",
+ "Saturday": "Samstag",
+ "Sunday": "Sonntag",
"Disposal data ...": "Entsorgungsdaten ...",
"Update": "Aktualisieren",
"Creating instance.": "Die Instanz wird erstellt.",
diff --git a/MyMuell/module.php b/MyMuell/module.php
index 5ed5f87..4846df8 100644
--- a/MyMuell/module.php
+++ b/MyMuell/module.php
@@ -12,6 +12,7 @@ class MyMuell extends IPSModule
use DebugHelper;
use ServiceHelper;
use VariableHelper;
+ use VisualisationHelper;
// Service Provider
private const SERVICE_PROVIDER = 'mymde';
@@ -42,6 +43,8 @@ public function Create()
$this->RegisterPropertyBoolean('settingsActivate', true);
$this->RegisterPropertyBoolean('settingsVariables', false);
$this->RegisterPropertyInteger('settingsScript', 0);
+ $this->RegisterPropertyBoolean('settingsTileVisu', false);
+ $this->RegisterPropertyString('settingsTileSkin', 'dark');
// Register daily update timer
$this->RegisterTimer('UpdateTimer', 0, 'MYMDE_Update(' . $this->InstanceID . ');');
}
@@ -113,9 +116,12 @@ public function ApplyChanges()
$cId = $this->ReadPropertyString('cityID');
$aId = $this->ReadPropertyString('areaID');
$activate = $this->ReadPropertyBoolean('settingsActivate');
+ $tilevisu = $this->ReadPropertyBoolean('settingsTileVisu');
$this->SendDebug(__FUNCTION__, 'cityID=' . ', areaID=' . $aId);
// Safty default
$this->SetTimerInterval('UpdateTimer', 0);
+ // Support for Tile Viso (v7.x)
+ $this->MaintainVariable('Widget', $this->Translate('Pickup'), vtString, '~HTMLBox', 0, $tilevisu);
// Set status
if ($cId == 'null') {
$status = 201;
@@ -178,7 +184,7 @@ public function Update()
$data = json_decode($json, true);
foreach ($data as $entry) {
if (!isset($waste[$entry['trash_name']])) {
- $waste[$entry['trash_name']] = ['title' => $entry['title'], 'date' => strtotime($entry['day'])];
+ $waste[$entry['trash_name']] = ['ident' => $entry['trash_name'], 'date' => date('d.m.Y', strtotime($entry['day'])), 'title' => $entry['title']];
}
}
} else {
@@ -189,7 +195,15 @@ public function Update()
// write data to variable
foreach ($waste as $key => $var) {
- $this->SetValueString((string) $key, date('d.m.Y', $var['date']));
+ $this->SetValueString((string) $key, $var['date']);
+ }
+
+ // build tile widget
+ $btw = $this->ReadPropertyBoolean('settingsTileVisu');
+ $skin = $this->ReadPropertyString('settingsTileSkin');
+ $this->SendDebug(__FUNCTION__, 'TileVisu: ' . $btw . '(' . $skin . ')');
+ if ($btw == true) {
+ $this->BuildWidget($waste, $skin);
}
// execute Script
diff --git a/README.md b/README.md
index a6d5df6..e59b591 100644
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
# Abfallwirtschaft
[![Version](https://img.shields.io/badge/Symcon-PHP--Bibliothek-purple.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
[![Licence](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
IP-Symcon Modulbibliothek für die Visualisierung von Entsorgungsterminen.
@@ -21,15 +21,21 @@ Folgende Module beinhaltet diese Bibliothek:
- __Awido__ ([Dokumentation](Awido))
Der AWIDO (Alle wichtigen Daten online) - Service.
+- __MuellMax__ ([Dokumentation](MuellMax))
+ Müllmax Abfallkalender – barrierefrei online und gedruckt.
+
- __MyMuell__ ([Dokumentation](MyMuell))
MyMüll.de für die saubere Organisierung von Abfall und Wertstoffe.
+__HINWEIS:__ Über diese [Suchseite](https://asmium.de) kann man ganz schnell herausfinden ob die eigene Stadt/Gemeinde von einem der aufgelisteten Dienste unterstützt wird! :+1:
+
## Historie
+- 2023-11-19: Modul MuellMax (MüllMax DE)
- 2023-01-24: Modul Awido (Script-Fix)
- 2022-10-20: Modul AbfallNavi (Regio IT)
- 2022-03-09: Modul MyMuell Multi-Domain-Fähigkeit
-- 2021-11-09: Modul MyMuell (MyMüll.de)
+- 2021-11-09: Modul MyMuell (mymüll.de)
- 2021-04-06: Modul Abfall_IO (Abfall+)
- 2021-04-04: Modul Abfallwirtschaft Konfigurator (Waste Management Configurator)
- 2017-01-03: Modul Awido
diff --git a/WasteManagementConfigurator/README.md b/WasteManagementConfigurator/README.md
index 7cc1e9a..7486ed8 100644
--- a/WasteManagementConfigurator/README.md
+++ b/WasteManagementConfigurator/README.md
@@ -1,10 +1,10 @@
# Abfallwirtschafts-Konfigurator (Waste Management Configutrator)
[![Version](https://img.shields.io/badge/Symcon-PHP--Modul-red.svg)](https://www.symcon.de/service/dokumentation/entwicklerbereich/sdk-tools/sdk-php/)
-[![Product](https://img.shields.io/badge/Symcon%20Version-6.0-blue.svg)](https://www.symcon.de/produkt/)
-[![Version](https://img.shields.io/badge/Modul%20Version-1.3.20220309-orange.svg)](https://github.com/Wilkware/IPSymconAwido)
+[![Product](https://img.shields.io/badge/Symcon%20Version-6.4-blue.svg)](https://www.symcon.de/produkt/)
+[![Version](https://img.shields.io/badge/Modul%20Version-2.0.20231119-orange.svg)](https://github.com/Wilkware/WasteManagement)
[![License](https://img.shields.io/badge/License-CC%20BY--NC--SA%204.0-green.svg)](https://creativecommons.org/licenses/by-nc-sa/4.0/)
-[![Actions](https://github.com/Wilkware/IPSymconAwido/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/IPSymconAwido/actions)
+[![Actions](https://github.com/Wilkware/WasteManagement/workflows/Check%20Style/badge.svg)](https://github.com/Wilkware/WasteManagement/actions)
IP-Symcon Modul für die Verwaltung von Online Diensten zur Bestimmung von Entsorgungsterminen.
@@ -29,18 +29,21 @@ Derzeit unterstützt der Konfigurator folgende Anbieter:
* [Abfall+](https://abfallplus.de) - "Die Gesamtlösung für elektronische Bürgerdienste in der Abfallwirtschaft!"
* [MyMüll.de](https://mymuell.de) - "Abfall und Wertstoffe sauber organisiert!"
* [AbfallNavi](https://regioit.de) - "Der digitale Abfallkalender der regio IT für die Abfallentsorgung!"
+* [MyMuell](https://muellmax.de) - Müllmax Abfallkalender – barrierefrei online und gedruckt.
+
+__HINWEIS:__ Über diese [Suchseite](https://asmium.de) kann man ganz schnell herausfinden ob die eigene Stadt/Gemeinde von einem der aufgelisteten Dienste unterstützt wird! :+1:
Wenn jemand noch weitere kennt, bitte einfach bei mir melden!
### 2. Voraussetzungen
-* IP-Symcon ab Version 6.0
+* IP-Symcon ab Version 6.4
### 3. Installation
* Über den Modul Store das Modul Abfallwirtschaft (ehem. Awido) installieren.
* Alternativ Über das Modul-Control folgende URL hinzufügen.
-`https://github.com/Wilkware/IPSymconAwido` oder `git://github.com/Wilkware/IPSymconAwido.git`
+`https://github.com/Wilkware/WasteManagement` oder `git://github.com/Wilkware/WasteManagement.git`
### 4. Einrichten der Instanzen in IP-Symcon
@@ -56,7 +59,7 @@ _Einstellungsbereich:_
Name | Beschreibung
----------------------- | ---------------------------------
-Zielkategorie | Kategorie unter welcher neue Instanzen erzeugt werden (keine Auswahl im Root)
+Zielkategorie | Kategorie unter welcher neue Instanzen erzeugt werden (keine Auswahl im Root). Nur bis Version 7!
_Aktionsbereich:_
@@ -78,6 +81,11 @@ Das Modul bietet keine direkten Funktionsaufrufe.
### 8. Versionshistorie
+v2.0.20231119
+
+* _NEU_: Onlinedienst MuellMax (muellmax.de) hinzugefügt
+* _NEU_: Unterstützung für neuen Konfigurator der Version 7
+
v1.3.20220309
* _NEU_: Konfigurationsformular angepasst
diff --git a/WasteManagementConfigurator/form.json b/WasteManagementConfigurator/form.json
index 9c6af74..de03fec 100644
--- a/WasteManagementConfigurator/form.json
+++ b/WasteManagementConfigurator/form.json
@@ -24,7 +24,8 @@
{
"type": "SelectCategory",
"name": "TargetCategory",
- "caption": "Target Category:"
+ "caption": "Target Category:",
+ "visible": false
}
],
"actions": [
diff --git a/WasteManagementConfigurator/module.php b/WasteManagementConfigurator/module.php
index f4d5e10..09c1aad 100644
--- a/WasteManagementConfigurator/module.php
+++ b/WasteManagementConfigurator/module.php
@@ -40,8 +40,14 @@ public function ApplyChanges()
public function GetConfigurationForm()
{
$form = json_decode(file_get_contents(__DIR__ . '/form.json'), true);
+ // Version check
+ $version = (float) IPS_GetKernelVersion();
// Save location
$location = $this->GetPathOfCategory($this->ReadPropertyInteger('TargetCategory'));
+ // Enable or disable "TargetCategory" for 6.x
+ if ($version < 7) {
+ $form['elements'][2]['visible'] = true;
+ }
// Build configuration list values
foreach (static::$PROVIDERS as $key => $value) {
$values[] = [
@@ -66,7 +72,7 @@ public function GetConfigurationForm()
[
'moduleID' => $value[1],
'configuration' => ['serviceProvider' => $key],
- 'location' => $location,
+ 'location' => ($version < 7) ? $location : [],
],
],
];
@@ -81,7 +87,7 @@ public function GetConfigurationForm()
[
'moduleID' => $value[1],
'configuration' => ['serviceProvider' => $key],
- 'location' => $location,
+ 'location' => ($version < 7) ? $location : [],
],
],
];
diff --git a/library.json b/library.json
index 3ecfaf1..880ad55 100644
--- a/library.json
+++ b/library.json
@@ -3,10 +3,10 @@
"author": "Wilkware (@Pitti)",
"url": "https://wilkware.de",
"compatibility": {
- "version": "6.0"
+ "version": "6.4"
},
"name": "Abfallwirtschaft",
- "version": "3.6",
- "build": 20230102,
- "date": 1672657200
+ "version": "4.0",
+ "build": 20231119,
+ "date": 1700391600
}
\ No newline at end of file
diff --git a/libs/ServiceHelper.php b/libs/ServiceHelper.php
index 65144a5..6b042a6 100644
--- a/libs/ServiceHelper.php
+++ b/libs/ServiceHelper.php
@@ -27,6 +27,7 @@ trait ServiceHelper
'abpio' => [2, '{53922265-6F58-E833-34A1-52D44D1C8D3F}', 'Abfall.IO', 'abfallplus.de', 'Abfall+ ist die Lösung für elektronische Bürgerdienste in der Abfallwirtschaft!'],
'mymde' => [3, '{BCB84068-9194-754C-436F-F10BDD8E51BE}', 'MyMüll', 'mymuell.de', 'Abfall und Wertstoffe sauber organisiert!'],
'regio' => [4, '{085BA8B2-118B-208D-3664-3C230C55952E}', 'AbfallNavi', 'regioit.de', 'Der digitale Abfallkalender der regio IT für die Abfallentsorgung.'],
+ 'maxde' => [5, '{2EC7DFA0-62D9-2E92-ADB1-6B8201D142FA}', 'MüllMax', 'muellmax.de', 'Abfallkalender – barrierefrei online und gedruckt!'],
];
/**
@@ -107,4 +108,42 @@ private function ExtractClients(string $url): array
// return the events
return $data['data']['clients'];
}
-}
+
+ /**
+ * Order assoziate array data
+ *
+ * @param array $arr
+ * @param string|null $key
+ * @param string $direction
+ */
+ private function OrderData(array $arr, string $key = null, string $direction = 'ASC')
+ {
+ // Check "order by key"
+ if (!is_string($key) && !is_array($key)) {
+ throw new InvalidArgumentException('Order() expects the first parameter to be a valid key or array');
+ }
+ // Build order-by clausel
+ $props = [];
+ if (is_string($key)) {
+ $props[$key] = strtolower($direction) == 'asc' ? 1 : -1;
+ } else {
+ $i = count($key);
+ foreach ($key as $k => $dir) {
+ $props[$k] = strtolower($dir) == 'asc' ? $i : -($i);
+ $i--;
+ }
+ }
+ // Sort by passed keys
+ usort($arr, function ($a, $b) use ($props) {
+ foreach ($props as $key => $val) {
+ if ($a[$key] == $b[$key]) {
+ continue;
+ }
+ return $a[$key] > $b[$key] ? $val : -($val);
+ }
+ return 0;
+ });
+ // Return sorted array
+ return $arr;
+ }
+}
\ No newline at end of file
diff --git a/libs/VisualisationHelper.php b/libs/VisualisationHelper.php
new file mode 100644
index 0000000..c6f21ed
--- /dev/null
+++ b/libs/VisualisationHelper.php
@@ -0,0 +1,205 @@
+
+ * @copyright 2021 Heiko Wilknitz
+ * @link https://wilkware.de
+ * @license https://creativecommons.org/licenses/by-nc-sa/4.0/ CC BY-NC-SA 4.0
+ */
+
+declare(strict_types=1);
+
+/**
+ * Helper class for support new tile visu.
+ */
+trait VisualisationHelper
+{
+ /**
+ * Build a html widget for waste dates.
+ *
+ * @param array $waste Array with waste names and the next pick-up date.
+ */
+ protected function BuildWidget(array $waste, string $skin)
+ {
+ $this->SendDebug(__FUNCTION__, $waste);
+ // (0) tabel with all infos
+ $table = [];
+ // (1) build new data array
+ foreach($waste as $key => $value) {
+ $id = @$this->GetIDForIdent($value['ident']);
+ if ($id !== false) {
+ $name = IPS_GetName($id);
+ $type = $this->RecognizeWaste($name);
+ $date = $value['date'];
+ $days = $this->CalcDaysToDate($date);
+ $table[] = ['name' => $name, 'type' => $type, 'date' => $date, 'days' => $days ];
+ }
+ }
+ // (2) sort waste by date
+ usort($table, function ($a, $b) {
+ return strtotime($a['date']) - strtotime($b['date']);
+ });
+ // (3) build html texts
+ $next = '';
+ // show today only if no date tommorow
+ if (strtotime($table[0]['date']) === strtotime('today')) {
+ $next = $this->Translate('Heute');
+ }
+ // tommorow overrule today
+ if (strtotime($table[0]['date']) === strtotime('tomorrow')) {
+ $next = $this->Translate('Morgen');
+ }
+ // generate widget for tile visu
+ if ($next == '') {
+ $next = date('d.m.', strtotime($table[0]['date']));
+ $next = $this->Translate(date('D', strtotime($table[0]['date']))) . '. ' . $next;
+ }
+ $textS = '';
+ $textM = '';
+ $textL = '';
+ // date infos
+ $days = $table[0]['days'];
+ $day = strtotime($table[0]['date']);
+ $wd = $this->Translate (date('l'));
+ $sd = date('d.m.', $day);
+ $wn = $table[0]['name'];
+ if($days > 1) {
+ $textS = "in $days " . $this->Translate('days');
+ $textM = "$wn
" . $this->Translate('Next pickup:') . "
in $days " . $this->Translate('days') . '
' . $this->Translate('on') . " $wd $sd";
+ } else {
+ $textS = $next;
+ $textM = "$wn
" . $this->Translate('Next pickup:') . "
$next
" . $this->Translate('on') . " $wd $sd";
+ }
+ // table rows
+ $textL = '';
+ foreach($table as $row) {
+ if ($row['days'] == 0) $text = $this->Translate('Today');
+ if ($row['days'] == 1) $text = $this->Translate('Tomorrow');
+ if ($row['days'] >= 2) $text = $row['days'] . ' ' . $this->Translate('days');
+ $textL .= '
' . $removal . ' | ' . $date . ' | ' . $pickup . ' |
---|