Skip to content

Commit

Permalink
V3.1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
jemu75 committed Mar 22, 2021
1 parent 3b3ada9 commit 82d30a6
Show file tree
Hide file tree
Showing 24 changed files with 206 additions and 1,236 deletions.
47 changes: 46 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ Beispiele:
| [watersensor](#template-watersensor) | Zisternensensor | ![](./docs/media/template_watersensor_example.png) |
| sonos | Sonosplayer | ![](./docs/media/template_sonos_example.png) |
| scenes | LightScenes | ![](./docs/media/template_scenes_example.png) |
| panel | Panel zur Gruppierung mehrerer Devices | ![](./docs/media/template_panel_example.png) |
| [panel](#template-panel) | Panel zur Gruppierung mehrerer Devices | ![](./docs/media/template_panel_example.png) |
| chart | Diagramm zur Visualisierung von Log-Daten | ![](./docs/media/template_chart_example.png) |
| weather | Wettervorhersage (darksky-API) | ![](./docs/media/template_weather_example.png) |
| sysmon | Systemmonitor | ![](./docs/media/template_sysmon_example.png) |
Expand Down Expand Up @@ -590,3 +590,48 @@ Im FHEM-Device muss im Attribut `appOptions` folgendes eingetragen werden.
}
}
```
# Template Panel
Über dieses Template können mehrere FHEM-Devices angezeigt werden. Dabei dient das Template `panel` nur als *Rahmen*. Die Liste der FHEM-Devices die innerhalb des Panels angezeigt werden, definiert ihr über den Parameter `connected` in `appOptions`. Die einzelnen *PanelItems* müssen in den jeweiligen FHEM-Devices über den Parameter `panel` in `appOptions` konfiguriert werden.

Sinnvoll ist der Einsatz von Panels z.B. für den *Homescreen* in **FHEMApp** da Panels einen guten Gesamtüberblick über deine Hausautomation liefern. So ist die Verwendung von FHEM *structure* Komponenten z.B. gut geeignet um, in einem Panel den Zustand aller Heizungen, Fenster, Rauchmelder usw. im Haus zu bekommen.

Zusätzlich können in jedem PanelItem entweder ein *Link* oder eine *Taste* aktiviert werden. Über *Link* könnt ihr innerhalb der **FHEMApp** auf einen anderen Screen navigieren. Über die *Taste* könnt ihr wiederum Kommandos an FHEM absenden.

Da *Panel* kein Standard-Template ist, könnt ihr nur ausgewählte Eigenschaften über den Parameter `setup` in `appOptions` anpassen. Folgende Eigenschaften könnt ihr individuell anpassen:
```
"setup": {
"info": {
"left1": ["reading:value:text:icon"],
"left2": ["reading:value:text:icon"],
"mid1": ["reading:value:text:icon"],
"mid2": ["reading:value:text:icon"],
"right1": ["reading:value:text:icon"],
"right2": ["reading:value:text:icon"]
}
}
```

#### Definition von Panel
Um das Panel selbst anzulegen ordnet ihr einem FHEM-Device (sinnvoller Weise einem *dummy*) in `appOptions` das Template *panel* zu. Weiterhin legt ihr fest, welche FHEM-Devices innerhalb des Panels angezeigt werden sollen. Dazu nutzt ihr in `appOptions` den Parameter `connected`.
```
{ "template": "panel", "connected": { "1": "<devicename1>", "2": "<devicename2>", ... } }
```

#### Definition der einzelnen PanelItems
Nachdem ihr das Panel selbst angelegt habt, müsst ihr jetzt in jedem unter `connected` definierten FHEM-Devices festlegen, wie sich dieses *PanelItem* verhalten soll. Dazu nutzt ihr in `appOptions` den Parameter `panel` (für PanelItems eignen sich insbesondere FHEM *structure* Devices. Grundsätzlich könnt ihr aber auch jedes andere FHEM-Device als PanelItem definieren.)
```
{
"panel": {
"status": ["reading:wert:text:level:color"],
"btn": ["reading:wert:icon"],
"click": ["reading:wert:cmd"],
"link": "string",
}
}
```
|Element|Zuweisung|Beschreibung|
|-------|---------|------------|
|status|reading:wert:text:level:color|definiert welcher **Statustext** im PanelItem angezeigt wird. Weiterhin mit welcher **Farbe** und mit welchem **Level** der Status in dem *Kreis* angezeigt wird.|
|btn|reading:wert:icon (alternativ: icon)|definiert welches *Icon* auf der Taste im PanelItem angezeigt wird. Icon Bibliothek [siehe](https://materialdesignicons.com/)|
|click|reading:wert:cmd|defniert welches FHEM-Kommando bei Klick auf die Taste abgesendet wird. *Hinweis:* `set devicename` kann weggelassen werden|
|link|<route>|link kann alternativ zu click verwendet werden. In diesem Fall wird kein FHEM-Kommando gesendet sondern man kann auf einen anderen Screen in **FHEMApp** wechseln. Die *route* muss mit **/devices/** beginnen. Am besten schaut ihr euch dazu vorher die URL in **FHEMApp** auf den gewünschten Screen an.|
32 changes: 0 additions & 32 deletions public/cfg/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,38 +25,6 @@
}
},
"custom": [
{
"name": "example",
"author": "name",
"date": "YYYY-MM-DD",
"status": {
"bar": ["reading:value:level:color:invert"],
"error": ["reading:value:level:color:text"]
},
"main": [
{
"leftBtn": ["reading:value:icon:disabled"],
"leftClick": ["reading:value:set_param"],
"leftLong": ["reading:value:set_param"],
"leftLongRelease": ["reading:value:set_param"],
"text": ["reading:value:text"],
"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"]
}
],
"info": {
"left1": ["reading:value:text:icon"],
"left2": ["reading:value:text:icon"],
"mid1": ["reading:value:text:icon"],
"mid2": ["reading:value:text:icon"],
"right1": ["reading:value:text:icon"],
"right2": ["reading:value:text:icon"]
}
},
{
"name": "shellySwitch",
"author": "jemu75",
Expand Down
2 changes: 1 addition & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@
groupList: []
}
},
version: 'v3.0.0',
version: 'v3.1.0',
status: {
color: 'secondary',
icon: 'mdi-circle',
Expand Down
2 changes: 1 addition & 1 deletion src/components/TemplDefault.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<v-progress-linear height="7" :value="getLevel" :color="vals.status.color" background-color="secondary darken-1"></v-progress-linear>

<v-card-title class="text-truncate">
{{ vals.title }}{{ vals.order }}
{{ vals.title }}
<v-spacer></v-spacer>
<v-btn v-if="multiLevel && isActive" small icon @click="setLevel()">
<v-icon small>{{ multiLevelIcon }}</v-icon>
Expand Down
210 changes: 151 additions & 59 deletions src/components/TemplPanel.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<v-col class="col-12 col-sm-6 col-md-6 col-lg-6">
<v-card :dark="this.$vuetify.theme.dark" color="secondary">
<v-progress-linear height="7" :value="vals.mainLevel" :color="vals.mainColor" background-color="secondary darken-1"></v-progress-linear>
<v-progress-linear height="7" :value="getLevel" :color="vals.status.color" background-color="secondary darken-1"></v-progress-linear>

<v-card-title class="text-truncate">{{ vals.title }}</v-card-title>
<v-divider></v-divider>
Expand All @@ -10,33 +10,37 @@
<div v-for="el in list" :key="el.Name" align="center">
<v-row dense class="ma-1" align="center">
<v-col class="col-2">
<v-progress-circular :value="el.mainLevel" :color="el.mainColor">
<v-progress-circular :value="el.level" :color="el.color">
</v-progress-circular>
</v-col>
<v-col class="text-truncate" align="left">
<div class="text-truncate headline">{{ el.title }}</div>
<div class="text-truncate">{{ el.mainState }}</div>
<div class="text-truncate">{{ el.text }}</div>
</v-col>
<v-divider v-if="el.toggleCmd" vertical></v-divider>
<v-col class="col-2" align="center">
<v-btn v-if="el.route" icon link :to="el.route">
<v-icon large>{{ rightIcon }}</v-icon>
<v-btn v-if="el.route && !el.click && el.icon" icon link :to="el.route">
<v-icon large>{{ el.icon }}</v-icon>
</v-btn>
<div v-if="el.toggleCmd">
<v-btn icon @click="set(el.toggleCmd)">
<v-icon large>{{ el.toggleIcon }}</v-icon>
<div v-if="el.click && !el.route && el.icon">
<v-btn icon @click="set(el.device, el.click)">
<v-icon large>{{ el.icon }}</v-icon>
</v-btn>
</div>
</v-col>
</v-row>
<v-divider></v-divider>
</div>
</v-card-text>

<v-system-bar color="secondary darken-1">
<v-icon>{{ vals.systemIcon }}</v-icon>{{ vals.systemIconValue }}
<v-icon class="ml-0">{{ vals.info.left1Icon }}</v-icon>{{ vals.info.left1Text }}
<v-icon>{{ vals.info.left2Icon }}</v-icon>{{ vals.info.left2Text }}
<v-spacer></v-spacer>
{{ vals.systemLastEvent }}
<v-icon>{{ vals.info.mid1Icon }}</v-icon>{{ vals.info.mid1Text }}
<v-icon class="ml-2">{{ vals.info.mid2Icon }}</v-icon>{{ vals.info.mid2Text }}
<v-spacer></v-spacer>
<v-icon>{{ vals.info.right1Icon }}</v-icon>{{ vals.info.right1Text }}
<v-icon class="mr-0">{{ vals.info.right2Icon }}</v-icon>{{ vals.info.right2Text }}
</v-system-bar>
</v-card>
</v-col>
Expand All @@ -45,17 +49,43 @@
<script>
export default {
data: () => ({
name: 'linkPanel',
defaultSet: [],
name: 'panel',
setup: {
status: {
bar: [],
error: []
},
info: {
left1: [],
left2: [],
mid1: [],
mid2: [],
right1: [],
right2: []
}
},
vals: {
title: '',
mainLevel: 100,
mainColor: 'success',
systemIcon: '',
systemIconValue: '',
systemLastEvent: ''
status: {
level: 0,
color: '',
invert: false,
},
info: {
left1Icon: '',
left1Text: '',
left2Icon: '',
left2Text: '',
mid1Icon: '',
mid1Text: '',
mid2Icon: '',
mid2Text: '',
right1Icon: '',
right1Text: '',
right2Icon: '',
right2Text: ''
}
},
rightIcon: 'mdi-chevron-right',
list: []
}),
Expand All @@ -67,73 +97,135 @@
let alias = this.$fhem.getEl(val, 'Attributes', 'alias') || val.Name;
this.vals.title = this.$fhem.getEl(val, 'Options', 'name') || alias;
this.vals = this.$fhem.handleStates(val, this.vals);
this.doList(val);
this.setValues();
this.doList();
}
},
setup: {
deep: true,
handler() {
this.setValues();
}
}
},
computed: {
getLevel() {
return this.vals.status.invert ? 100 - this.vals.status.level : this.vals.status.level;
}
},
methods: {
checkToggle(item) {
let toggleDefs = this.$fhem.getEl(item, 'Options', 'toggle');
let result = null;
if(toggleDefs && toggleDefs.length > 0) {
for(var def of toggleDefs) {
let vals = def.split(':');
let value = this.$fhem.getEl(item, 'Readings', vals[0] || 'state', 'Value')
if(!result || value === vals[1]) {
result = {
cmd: vals[2] ? ('set ' + item.Name + ' ' + vals[2]) : null,
icon: vals[3] || ''
}
}
}
setValues() {
let statusVals = this.$fhem.handleVals(this.item, this.setup.status.bar);
let errorVals = this.$fhem.handleVals(this.item, this.setup.status.error);
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);
let infoMid2Vals = this.$fhem.handleVals(this.item, this.setup.info.mid2);
let infoRight1Vals = this.$fhem.handleVals(this.item, this.setup.info.right1);
let infoRight2Vals = this.$fhem.handleVals(this.item, this.setup.info.right2);
this.vals.status.level = statusVals[0] || '100';
this.vals.status.color = statusVals[1] || 'success';
this.vals.status.invert = statusVals[2] ? true : false;
this.vals.info.left1Icon = infoLeft1Vals[1] || '';
this.vals.info.left1Text = infoLeft1Vals[0] || '';
this.vals.info.left2Icon = infoLeft2Vals[1] || '';
this.vals.info.left2Text = infoLeft2Vals[0] || '';
this.vals.info.mid1Icon = infoMid1Vals[1] || '';
this.vals.info.mid1Text = infoMid1Vals[0] || '';
this.vals.info.mid2Icon = infoMid2Vals[1] || '';
this.vals.info.mid2Text = infoMid2Vals[0] || '';
this.vals.info.right1Icon = infoRight1Vals[1] || '';
this.vals.info.right1Text = infoRight1Vals[0] || '';
this.vals.info.right2Icon = infoRight2Vals[1] || '';
this.vals.info.right2Text = infoRight2Vals[0] || '';
if(errorVals.length > 0) {
this.vals.status.level = errorVals[0] || '100';
this.vals.status.color = errorVals[1] || 'error';
this.vals.main.text = errorVals[2] || 'Fehler';
this.isActive = false;
} else {
result = { cmd: null, icon: '' }
this.isActive = true;
}
return result;
},
set(cmd) {
this.$fhem.request(cmd)
set(device, param) {
let cmd = param.match('set') ? param : 'set ' + device + ' ' + param;
this.$fhem.request(cmd);
},
doList(val) {
if(val.Connected) {
for(var item in val.Options.connected) {
loadItem(obj) {
let device = this.$fhem.getEl(obj, 'Name') || '';
let alias = this.$fhem.getEl(obj, 'Attributes', 'alias') || obj.Name;
let title = this.$fhem.getEl(obj, 'Options', 'name') || alias;
let route = this.$fhem.getEl(obj, 'Options', 'panel', 'link') || '';
let state = this.$fhem.handleVals(obj, this.$fhem.getEl(obj, 'Options', 'panel', 'status')) || [];
let btn = this.$fhem.handleVals(obj, this.$fhem.getEl(obj, 'Options', 'panel', 'btn')) || [];
let cmd = this.$fhem.handleVals(obj, this.$fhem.getEl(obj, 'Options', 'panel', 'click')) || [];
let result = {
device: device,
title: title,
text: state[0] || '',
level: state[1] || 0,
color: state[2] || 'success',
icon: btn[0] || '',
route: route,
click: cmd[0] || ''
}
return result;
},
doList() {
if(this.item.Connected) {
for(var item in this.item.Options.connected) {
let idx = this.list.map((e) => e.name).indexOf(item);
let states = this.$fhem.handleStates(val.Connected[item], {});
let toggle = this.checkToggle(val.Connected[item]);
let data = this.loadItem(this.item.Connected[item]);
let listItem = {
name: item,
title: this.$fhem.getEl(val.Connected[item], 'Attributes', 'alias') || val.Connected[item].Name,
mainState: states.mainState,
mainColor: states.mainColor,
mainLevel: states.mainLevel,
route: this.$fhem.getEl(val.Connected[item], 'Options', 'link'),
toggleIcon: toggle.icon,
toggleCmd: toggle.cmd
}
device: data.device,
level: data.level,
color: data.color,
title: data.title,
text: data.text,
icon: data.icon,
route: data.route,
click: data.click
};
if(listItem.mainColor != 'success') {
this.vals.mainColor = listItem.mainColor;
this.vals.mainLevel = 100;
}
if(data.color != 'success') this.vals.status.color = data.color;
if(idx != -1) {
this.list.splice(idx, 1, listItem);
} else {
this.list.push(listItem);
}
}
}
}
},
created() {
let status = this.$fhem.getEl(this.item, 'Options', 'setup', 'status');
let info = this.$fhem.getEl(this.item, 'Options', 'setup', 'info');
if(status) Object.assign(this.setup.status, status);
if(info) Object.assign(this.setup.info, info);
},
props: {
item: {}, // jsonObject from FHEM Device
}
Expand Down
Loading

0 comments on commit 82d30a6

Please sign in to comment.