From a1c0f23e6e9aa1040818998b670fdb1fd09e69b2 Mon Sep 17 00:00:00 2001 From: jemu75 Date: Sun, 21 Mar 2021 21:09:15 +0100 Subject: [PATCH] V3.0.0 --- README.md | 22 +-- public/cfg/config.json | 10 +- src/App.vue | 9 ++ src/assets/templates.json | 28 ++-- src/components/TemplDefault.vue | 132 ++++++++++++++---- src/components/TemplScenes.vue | 2 +- src/components/TemplSonos.vue | 51 ++++--- src/plugins/fhem.js | 10 +- www/fhemapp/cfg/config.json | 10 +- ...1711b5.css => chunk-5b592ef2.611711b5.css} | 0 www/fhemapp/css/chunk-788ccab5.611711b5.css | 1 + www/fhemapp/css/chunk-a9a9ce50.55c011d2.css | 1 - www/fhemapp/index.html | 2 +- www/fhemapp/js/app.33b11d80.js | 1 - www/fhemapp/js/app.d2009b57.js | 1 + www/fhemapp/js/chunk-098d33d4.6eeee095.js | 1 - www/fhemapp/js/chunk-098d33d4.92ca4235.js | 1 + www/fhemapp/js/chunk-130a45b2.d90c60f4.js | 1 - www/fhemapp/js/chunk-2d212bf1.59146528.js | 1 + www/fhemapp/js/chunk-2d212bf1.9028291f.js | 1 - www/fhemapp/js/chunk-5b592ef2.ded7dec1.js | 1 + ...7a32d934.js => chunk-72c6e8d8.c00175b8.js} | 2 +- www/fhemapp/js/chunk-788ccab5.d389c4fa.js | 1 + www/fhemapp/js/chunk-a9a9ce50.721bad2f.js | 1 - ....010d3aee.js => chunk-vendors.41085411.js} | 2 +- 25 files changed, 198 insertions(+), 94 deletions(-) rename www/fhemapp/css/{chunk-130a45b2.611711b5.css => chunk-5b592ef2.611711b5.css} (100%) create mode 100644 www/fhemapp/css/chunk-788ccab5.611711b5.css delete mode 100644 www/fhemapp/css/chunk-a9a9ce50.55c011d2.css delete mode 100644 www/fhemapp/js/app.33b11d80.js create mode 100644 www/fhemapp/js/app.d2009b57.js delete mode 100644 www/fhemapp/js/chunk-098d33d4.6eeee095.js create mode 100644 www/fhemapp/js/chunk-098d33d4.92ca4235.js delete mode 100644 www/fhemapp/js/chunk-130a45b2.d90c60f4.js create mode 100644 www/fhemapp/js/chunk-2d212bf1.59146528.js delete mode 100644 www/fhemapp/js/chunk-2d212bf1.9028291f.js create mode 100644 www/fhemapp/js/chunk-5b592ef2.ded7dec1.js rename www/fhemapp/js/{chunk-72c6e8d8.7a32d934.js => chunk-72c6e8d8.c00175b8.js} (99%) create mode 100644 www/fhemapp/js/chunk-788ccab5.d389c4fa.js delete mode 100644 www/fhemapp/js/chunk-a9a9ce50.721bad2f.js rename www/fhemapp/js/{chunk-vendors.010d3aee.js => chunk-vendors.41085411.js} (96%) diff --git a/README.md b/README.md index b68b71c6..5d9c0494 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,11 @@ Kopiert einfach alle Dateien und Unterverzeichnisse aus dem Ordner [www/fhemapp] └── js ``` -# Grundkonfiguration der FHEMApp -Die Grundkonfiguration von **FHEMApp** erfolgt über die Datei `config.json` welche sich im Verzeichnis `../fhemapp/cfg/` auf eurem Webserver befindet. Die Konfigurationsdatei könnt ihr über einen normalen Texteditor bearbeiten, um die folgenden Einstellungen vorzunehmen. +# Grundkonfiguration der FHEMApp verändern +Die Grundkonfiguration von **FHEMApp** könnt ihr über die Datei `config.json` welche sich im Verzeichnis `../fhemapp/cfg/` auf eurem Webserver befindet, anpassen. Die Konfigurationsdatei könnt ihr über einen normalen Texteditor bearbeiten, um die folgenden Einstellungen zu verändern. -### Verbindungseinstellung für FHEM -Hier wird festgelegt, wo sich die FHEM Installation befindet. Der Parameter `location` gibt die IP-Adresse bzw. URL von FHEM an. Die Parameter `port` und `path` entsprechen dem Standard eurer FHEM Installation und können bei Bedarf angepasst werden. +### Verbindungseinstellung für FHEM (optional) +Wenn ihr **FHEMApp** unter *opt/fhem/www/fhemapp* abgelegt habt, müssen keine Verbindungseinstellungen in der `config.json` hinterlegt werden. Solltet ihr **FHEMApp** auf einem separaten Webserver (z.B. apache) betreiben, dann sind diese Angaben notwendig. Das folgende Beispiel zeigt die Verbindungseinstellungen für eine Standard FHEM-Installation. ``` "connection": { "location": "http://fhem", @@ -97,7 +97,7 @@ Das Attribut `appOptions` kann mit unterschiedlichen Parametern befüllt werden, ``` { "template": "string", - steuert über welches Template das Device dargestellt wird - "name":" "string", - kann alternativ zum FHEM-Attribut 'alias' verwendet werden + "name": "string", - kann alternativ zum FHEM-Attribut 'alias' verwendet werden "room": "string", - kann alternativ zum FHEM-Attribut 'room' verwendet werden "group": "string", - kann alternativ zum FHEM-Attribut 'group' verwendet werden "home": "true", - zeigt ein Device auf der Startseite an @@ -160,12 +160,14 @@ Alternativ können eigene Templates in der Datei `config.json` als Vorlage abgel }, "main": [ { - "leftIcon": ["reading:value:icon:disabled"], + "leftBtn": ["reading:value:icon:disabled"], "leftClick": ["reading:value:set_param"], "leftLong": ["reading:value:set_param"], "leftLongRelease": ["reading:value:set_param"], "text": ["reading:value:text"], - "rightIcon": ["reading:value:icon:disabled"], + "text2": ["reading:value:text"], + "slider": ["reading:value:set_param:current:min:max"], + "rightBtn": ["reading:value:icon:disabled"], "rightClick": ["reading:value:set_param"], "rightLong": ["reading:value:set_param"], "rightLongRelease": ["reading:value:set_param"] @@ -199,19 +201,21 @@ Beispiele: - **%n.2** - liefert das *Reading* als Zahlenwert mit der gewünschten Anzahl an Nachkommastellen. Sollte das Reading aus Text und Zahlen bestehen, so wird der erste Zahlenwert zurückgegeben - **%i1** - erhöht (%i1.5) bzw. verringert (%i-1.5) das *Reading* um den Wert. Hierfür muss das *Reading* Zahlenwerte enthalten. - **%t** - liefert das *Reading* als Zeitstempel im Format TT.MM.JJJJ hh:mm:ss zurück +- **%v** - ausschließlich in Verbindung mit dem Element *slider* notwendig. ## verfügbare Elemente |Bereich|Element|Zuweisung|Beschreibung| |-------|-------|-----|-------------| |status|bar|reading:wert:level:color:invert|definiert mit welcher **Farbe** und mit welchem **Level** der Status angezeigt wird. Bei Angabe von invert wird *level* invertiert| |status|error|reading:wert:level:color:text|definiert mit welcher **Farbe** und mit welchem **Level** Fehler angezeigt werden. Weiterhin wird die **Fehlermeldung** definiert.| -|main|leftIcon|reading:wert:icon:disabled (alternativ: icon)|definiert welches *Icon* auf der linken Taste angezeigt wird. Optional kann das Flag *disabled* gesetzt werden. Icon Bibliothek [siehe](https://materialdesignicons.com/)| +|main|leftBtn|reading:wert:icon:disabled (alternativ: icon)|definiert welches *Icon* auf der linken Taste angezeigt wird. Optional kann das Flag *disabled* gesetzt werden. Icon Bibliothek [siehe](https://materialdesignicons.com/)| |main|leftClick|reading:wert:cmd|defniert welches FHEM-Kommando bei Klick auf die linke Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| |main|leftLong|reading:wert:cmd|defniert welches FHEM-Kommando bei langem Halten der linken Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| |main|leftLongRelease|reading:wert:cmd|defniert welches FHEM-Kommando beim loslassen nach langem Halten der linken Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| |main|text|reading:wert:text|definiert den **ersten Text** der in der Mitte angezeigt wird| |main|text2|reading:wert:text|definiert den **zweiten Text** der in der Mitte angezeigt wird *Hinweis:* bei Verwendung von Tasten sollte auf die Anzeige eines zweiten Wertes verzichtet werden, da die Breite des Templates im Normalfall nicht ausreicht| -|main|rightIcon|reading:wert:icon:disabled (alternativ: icon)|definiert welches *Icon* auf der rechten Taste angezeigt wird. Optional kann das Flag *disabled* gesetzt werden. Icon Bibliothek [siehe](https://materialdesignicons.com/)| +|main|slider|reading:wert:cmd:current:min:max|stellt einen **Slider** in der Mitte dar. In diesem Fall werden die Elemente `text` und `text2` nicht angezeigt und evtl. definierte Tasten reagieren nur auf `leftClick` bzw. `rightClick`. *Wichtig:* `cmd` muss die Ersetzung *%v* (den aktuellen Wert des Sliders) enthalten. `current` sollte nur die Ersetzung *%n* enthalten, damit der Slider den aktuellen Wert des Readings anzeigt. `min` und `max` begrenzen die Sliderwerte. *Beispiel:* `["pct::pct %v:%n:0:100"]` verbindet das Reading `pct` mit einem Slider und begrenzt die Wert auf 0-100| +|main|rightBtn|reading:wert:icon:disabled (alternativ: icon)|definiert welches *Icon* auf der rechten Taste angezeigt wird. Optional kann das Flag *disabled* gesetzt werden. Icon Bibliothek [siehe](https://materialdesignicons.com/)| |main|leftClick|reading:wert:cmd|defniert welches FHEM-Kommando bei Klick auf die rechte Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| |main|rightLong|reading:wert:cmd|defniert welches FHEM-Kommando bei langem Halten der rechten Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| |main|rightLongRelease|reading:wert:cmd|defniert welches FHEM-Kommando beim loslassen nach langem Halten der rechten Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden| diff --git a/public/cfg/config.json b/public/cfg/config.json index d33fccbf..adf7c8b6 100644 --- a/public/cfg/config.json +++ b/public/cfg/config.json @@ -33,12 +33,14 @@ }, "main": [ { - "leftIcon": "string", + "leftBtn": ["reading:value:icon:disabled"], "leftClick": ["reading:value:set_param"], "leftLong": ["reading:value:set_param"], "leftLongRelease": ["reading:value:set_param"], "text": ["reading:value:text"], - "rightIcon": "string", + "text2": ["reading:value:text"], + "slider": ["reading:value:set_param:current:min:max"], + "rightBtn": ["reading:value:icon:disabled"], "rightClick": ["reading:value:set_param"], "rightLong": ["reading:value:set_param"], "rightLongRelease": ["reading:value:set_param"] @@ -61,12 +63,12 @@ }, "main": [ { - "leftIcon": "mdi-power-off", + "leftBtn": "mdi-power-off", "leftClick": ["state::off"], "leftLong": [], "leftLongRelease": [], "text": ["state:on:an","state:off:aus"], - "rightIcon": "mdi-power-on", + "rightBtn": "mdi-power-on", "rightClick": ["state::on"], "rightLong": [], "rightLongRelease": [] diff --git a/src/App.vue b/src/App.vue index 7c100120..787b042d 100644 --- a/src/App.vue +++ b/src/App.vue @@ -74,6 +74,14 @@ System + + + + + {{ version }} + + + @@ -106,6 +114,7 @@ groupList: [] } }, + version: 'v3.0.0', status: { color: 'secondary', icon: 'mdi-circle', diff --git a/src/assets/templates.json b/src/assets/templates.json index d6a190ac..3f0cddf0 100644 --- a/src/assets/templates.json +++ b/src/assets/templates.json @@ -28,10 +28,10 @@ }, "main": [ { - "leftIcon": "mdi-power-off", + "leftBtn": "mdi-power-off", "leftClick": ["state::off"], "text": ["state:on:an","state:off:aus","state::%s"], - "rightIcon": "mdi-power-on", + "rightBtn": "mdi-power-on", "rightClick": ["state::on"] } ], @@ -49,10 +49,10 @@ }, "main": [ { - "leftIcon": "mdi-power-off", + "leftBtn": "mdi-power-off", "leftClick": ["state::off"], "text": ["state:on:an","state:off:aus","state::%s"], - "rightIcon": "mdi-power-on", + "rightBtn": "mdi-power-on", "rightClick": ["state::on"] } ], @@ -68,12 +68,12 @@ }, "main": [ { - "leftIcon": "mdi-minus", - "leftClick": ["pct:100:pct 75","pct:75:pct 50","pct:50:pct 25","pct:25:off"], + "leftBtn": "mdi-minus", + "leftClick": ["pct:10:pct %i-10","pct::off"], "leftLong": ["state::off"], "text": ["pct:1:an:","pct::aus"], - "rightIcon": "mdi-plus", - "rightClick": ["pct:75:on","pct:50:pct 75","pct:25:pct 50","pct:0:pct 25"], + "rightBtn": "mdi-plus", + "rightClick": ["pct:90:on","pct::pct %i10"], "rightLong": ["state::on"] } ], @@ -90,12 +90,12 @@ }, "main": [ { - "leftIcon": "mdi-chevron-down", + "leftBtn": "mdi-chevron-down", "leftClick": ["motor:stop:off","motor::stop"], "leftLong": ["motor::off"], "leftLongRelease": ["motor::stop"], "text": ["motor:up:öffnet...","motor:down:schließt...","pct:1:offen","pct::geschlossen"], - "rightIcon": "mdi-chevron-up", + "rightBtn": "mdi-chevron-up", "rightClick": ["motor:stop:on","motor::stop"], "rightLong": ["motor::on"], "rightLongRelease": ["motor::stop"] @@ -151,7 +151,7 @@ "main": [ { "text": ["level:2:Alarm","level::bereit"], - "rightIcon": "mdi-bell-off-outline", + "rightBtn": "mdi-bell-off-outline", "rightClick": ["peerList:self01:alarmOff","peerList::set %s alarmOff"] } ], @@ -170,11 +170,11 @@ }, "main": [ { - "leftIcon": "mdi-minus", + "leftBtn": "mdi-minus", "leftClick": ["desired-temp:17.5:desired-temp %i-0.5","desired-temp::"], "leftLong": ["R-nightTemp::desired-temp %n.1"], "text": ["desired-temp::%n.1°C"], - "rightIcon": "mdi-plus", + "rightBtn": "mdi-plus", "rightClick": ["desired-temp:25:","desired-temp::desired-temp %i0.5"], "rightLong": ["R-dayTemp::desired-temp %n.1"] } @@ -235,7 +235,7 @@ "main": [ { "text": ["state:closed:geschlossen","state:open:offen","state::%s"], - "rightIcon": "mdi-unfold-more-horizontal", + "rightBtn": "mdi-unfold-more-horizontal", "rightClick": ["Connected.button.Internals.NAME::set %s on-for-timer 0.4"] } ], diff --git a/src/components/TemplDefault.vue b/src/components/TemplDefault.vue index 1987b9d0..804671a2 100644 --- a/src/components/TemplDefault.vue +++ b/src/components/TemplDefault.vue @@ -12,28 +12,40 @@ - + - - - {{ vals.main.leftIcon }} + + + {{ vals.main.leftBtn }} - +
{{ vals.main.text }}
- +
{{ vals.main.text2 }}
- - - - {{ vals.main.rightIcon }} + + + + {{ vals.main.rightBtn }}
+ + + + + + + + {{ vals.info.left1Icon }}{{ vals.info.left1Text }} @@ -76,12 +88,16 @@ invert: false, }, main: { - leftIcon: '', - leftIconDisabled: false, + leftBtn: '', + leftBtnDisabled: false, text: '', text2: '', - rightIcon: '', - rightIconDisabled: false + slider: false, + sliderCurrent: 0, + sliderMin: 0, + sliderMax: 100, + rightBtn: '', + rightBtnDisabled: false }, info: { left1Icon: '', @@ -103,7 +119,8 @@ mainLevel: 0, isActive: true, timer: false, - long: false + long: false, + pendingClick: 0 }), watch: { @@ -133,6 +150,31 @@ }, methods: { + sendCmd(cmd, delay) { + if(!delay) { + this.$fhem.request(cmd); + } else { + if (this.pendingClick) { + clearTimeout(this.pendingClick); + this.pendingClick = 0; + } + + this.pendingClick = setTimeout(() => { + this.$fhem.request(cmd); + }, 1000); + } + }, + + updateReading(cmd) { + let cmdParts = cmd.split(' '); + + if(cmdParts.length === 4) { + if(this.$fhem.getEl(this.item, 'Readings', cmdParts[2], 'Value')) { + this.item.Readings[cmdParts[2]].Value = cmdParts[3]; + } + } + }, + clickStart(val) { this.long = false; @@ -145,7 +187,7 @@ let param = this.$fhem.handleVals(this.item, action); if(param[0]) { let cmd = param[0].match('set') ? param[0] : 'set ' + this.item.Name + ' ' + param[0]; - this.$fhem.request(cmd); + this.sendCmd(cmd); this.timer = clearInterval(this.timer); } } @@ -161,7 +203,22 @@ let param = this.$fhem.handleVals(this.item, action); if(param[0]) { let cmd = param[0].match('set') ? param[0] : 'set ' + this.item.Name + ' ' + param[0]; - this.$fhem.request(cmd); + let isIncrement = action.findIndex((e) => e.match('%i')) != -1 ? true : false; + if(!this.long && isIncrement) this.updateReading(cmd); + this.sendCmd(cmd, isIncrement); + } + } + }, + + setSlider(val) { + let action = this.setup.main[this.mainLevel].slider; + + if(action) { + let param = this.$fhem.handleVals(this.item, action); + if(param[0]) { + let cmd = param[0].match('set') ? param[0] : 'set ' + this.item.Name + ' ' + param[0]; + cmd = cmd.replace('%v', val); + this.sendCmd(cmd); } } }, @@ -175,22 +232,29 @@ if(this.mainLevel > this.setup.main.length - 1) this.mainLevel = 0; } - this.vals.main.leftIcon = this.setup.main[this.mainLevel].leftIcon; - this.vals.main.rightIcon = this.setup.main[this.mainLevel].rightIcon; + this.vals.main.leftBtn = this.setup.main[this.mainLevel].leftBtn; + this.vals.main.rightBtn = this.setup.main[this.mainLevel].rightBtn; let mainText = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].text); let mainText2 = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].text2); - let mainLeftIcon = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].leftIcon) - let mainRightIcon = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].rightIcon) + let mainLeftBtn = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].leftBtn) + let mainRightBtn = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].rightBtn) + + let mainSlider = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].slider); this.vals.main.text = mainText[0] || ''; this.vals.main.text2 = mainText2[0] || ''; - this.vals.main.leftIcon = mainLeftIcon[0] || ''; - this.vals.main.rightIcon = mainRightIcon[0] || ''; - this.vals.main.leftIconDisabled = mainLeftIcon[1] ? true : false; - this.vals.main.rightIconDisabled = mainRightIcon[1] ? true : false; + this.vals.main.leftBtn = mainLeftBtn[0] || ''; + this.vals.main.rightBtn = mainRightBtn[0] || ''; + this.vals.main.leftBtnDisabled = mainLeftBtn[1] ? true : false; + this.vals.main.rightBtnDisabled = mainRightBtn[1] ? true : false; + + this.vals.main.slider = mainSlider[0] ? true : false; + this.vals.main.sliderCurrent = mainSlider[1] || 0; + this.vals.main.sliderMin = mainSlider[2] || 0; + this.vals.main.sliderMax = mainSlider[3] || 100; }, setValues() { @@ -199,8 +263,9 @@ let errorVals = this.$fhem.handleVals(this.item, this.setup.status.error); let mainText = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].text); let mainText2 = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].text2); - let mainLeftIcon = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].leftIcon) - let mainRightIcon = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].rightIcon) + let mainSlider = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].slider); + let mainLeftBtn = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].leftBtn); + let mainRightBtn = this.$fhem.handleVals(this.item, this.setup.main[this.mainLevel].rightBtn); let infoLeft1Vals = this.$fhem.handleVals(this.item, this.setup.info.left1); let infoLeft2Vals = this.$fhem.handleVals(this.item, this.setup.info.left2); let infoMid1Vals = this.$fhem.handleVals(this.item, this.setup.info.mid1); @@ -233,10 +298,15 @@ this.vals.main.text = mainText[0] || ''; this.vals.main.text2 = mainText2[0] || ''; - this.vals.main.leftIcon = mainLeftIcon[0] || ''; - this.vals.main.rightIcon = mainRightIcon[0] || ''; - this.vals.main.leftIconDisabled = mainLeftIcon[1] ? true : false; - this.vals.main.rightIconDisabled = mainRightIcon[1] ? true : false; + this.vals.main.slider = mainSlider[0] ? true : false; + this.vals.main.sliderCurrent = mainSlider[1] || 0; + this.vals.main.sliderMin = mainSlider[2] || 0; + this.vals.main.sliderMax = mainSlider[3] || 100; + + this.vals.main.leftBtn = mainLeftBtn[0] || ''; + this.vals.main.rightBtn = mainRightBtn[0] || ''; + this.vals.main.leftBtnDisabled = mainLeftBtn[1] ? true : false; + this.vals.main.rightBtnDisabled = mainRightBtn[1] ? true : false; if(errorVals.length > 0) { this.vals.status.level = errorVals[0] || '100'; diff --git a/src/components/TemplScenes.vue b/src/components/TemplScenes.vue index ab26d8f9..43cfee56 100644 --- a/src/components/TemplScenes.vue +++ b/src/components/TemplScenes.vue @@ -17,7 +17,7 @@ diff --git a/src/components/TemplSonos.vue b/src/components/TemplSonos.vue index 1dd14ea1..b87579f1 100644 --- a/src/components/TemplSonos.vue +++ b/src/components/TemplSonos.vue @@ -15,7 +15,7 @@ - + {{ leftIcon }} @@ -30,7 +30,7 @@ - + {{ rightIcon }} @@ -45,7 +45,7 @@ - +