Ich habe für jeden meiner Räume ein dummy definiert, über den ich Durchschnittstemperatur, Raumklima usw. ermittle.
Als Attribute sind hier die Devices für Temperatur-/Feuchtigkeits-/ und Fenstersensoren, Heizkörperthermostate usw. angegeben - hier mal ein Define
define rooms1livingroom dummy
attr rooms1livingroom temperatureDevice1 MAX_0885cd
attr rooms1livingroom temperatureDevice2 MAX_18073f
attr rooms1livingroom temperatureDevice3 FGSD002_ID23
attr rooms1livingroom thermostatDevice MAX_18073f
attr rooms1livingroom windowDevice1 MAX_17fe6e
attr rooms1livingroom windowDevice2 MAX_18012b
In der 99_myUtils ermittle ich die benötigten Werte bei Temperaturänderung usw. und hinterlege entsprechende userReadings.
Möchte ich jetzt in einem Widget eines der dort angegebenen Devices verwenden, muss ich den Namen raussuchen und einsetzen.
<div data-type="include" data-url="controls/controlBattery.inc" data-parameter='{"batteryDevice":"MAX_0885cd"}'></div>
Einfacher wäre es den Raum rooms1livingroom und das hinterlegte Gerät z.B. temperatureDevice1 anzugeben (der Code unten funktioniert natürlich nicht, soll nur als Beispiel dienen).
<div data-type="include" data-url="controls/controlBattery.inc" data-parameter='{"batteryDevice":"<rooms1livingroom/temperatureDevice1>"}'></div>
Auf diese Weise könnte ich Geräte einfach im Dummy ändern oder hinzufügen ohne noch extra den HTML Code zu verändern (ich könnte z.B. nicht definierte automatisch per classchanger verstecken).
Jetzt die Frage: kann ich ein Attribut eines Devices überhaupt als data-device eines Widgets verwenden und wenn ja wie ? Eventuell als Funktion aus der 99_myUtils.pm ?
Erschwerend käme bei einem Funktionsaufruf hinzu, dass ich bereits einfache (') und doppelte (") Anführungszeichen für data-parameter= benötige. Wie würde ich hier einer Funktion eine Textkonstante mitgeben ?
hier noch die weiteren Includes ...
controlBattery.inc
<div class="control_line">
<div class="control_line_caption" data-type="include" data-url="labels/label.inc" data-parameter='{"dataDevice":"batteryDevice","dataGet":"deviceName","dataColor":"label_ok"}'></div>
<div class="control_line_trend" data-type="include" data-url="popups/popupBattery.inc" data-parameter='{"popupDevice":"batteryDevice"}'></div>
<div class="control_line_value" data-type="include" data-url="labels/labelBattery.inc" data-parameter='{"dataDevice":"batteryDevice","dataGet":"batteryPercent"}'></div>
</div>
label.inc
<div data-type="label"
data-device="dataDevice"
data-get="dataGet"
data-color="dataColor">
</div>
popupBattery.inc
<div id="popuppopupDevice"
class="interlock noshade"
data-type="popup"
data-width="95vw"
data-height="81vh"
data-left="5vw"
data-top="19vh"
data-draggable="false"
data-mode="fade">
<div data-type="include" data-url="symbols/symbolBattery.inc" data-parameter='{"dataDevice":"popupDevice","dataGet":"batteryPercent"}'></div>
<div class="dialog" onclick="$('#popuppopupDevice.dialog-close').trigger('click');">
<div data-type="chart"
data-device="popupDevice"
data-get="batteryPercent"
data-width="90vw"
data-height="76vh"
data-logdevice="logdb"
data-logfile="HISTORY"
data-columnspec='["popupDevice:batteryPercent"]'
data-style='["ftui l1fill"]'
data-ptype='["lines"]'
data-uaxis='["primary"]'
data-legend='["Ladezustand"]'
data-legendpos='["right","top"]'
data-showlegend="true"
data-yunit="%"
data-ytext="Ladezustand"
data-minvalue="0"
data-maxvalue="100"
data-yticks="auto"
data-nofulldays="true"
data-daysago_start="2M"
data-daysago_end="-1M"
data-cursorgroup="1"
data-scrollgroup="1"
data-xticks="auto">
</div>
</div>
</div>
symbolBattery.inc
<div data-type="symbol"
data-device="dataDevice"
data-get="dataGet"
data-states='["100.*|[8-9][0-9].*|[7][6-9].*","[7][0-5].*|[6][0-9].*|[5][1-9].*","50.*|[3-4][0-9].*|[2][6-9].*","[2][0-5].*|[1][1-9].*","10.*|[0][0-9].*|[0-9].*"]'
data-icons='["fa-battery-4 rotate-270","fa-battery-3 rotate-270","fa-battery-2 rotate-270","fa-battery-1 rotate-270 blink","fa-battery-0 rotate-270 blink"]'
data-colors='["battery_ok","battery_ok","battery_ok","battery_warn","battery_critical"]'>
</div>
labelBattery.inc
<div data-type="label"
data-device="dataDevice"
data-get="dataGet"
data-part="1"
data-unit=" %">
</div>
Die Klassen sind in einer separaten .css-Datei definiert...
define rooms1livingroom dummy
attr rooms1livingroom temperatureDevice1 MAX_0885cd
attr rooms1livingroom temperatureDevice2 MAX_18073f
attr rooms1livingroom temperatureDevice3 FGSD002_ID23
attr rooms1livingroom thermostatDevice MAX_18073f
attr rooms1livingroom windowDevice1 MAX_17fe6e
attr rooms1livingroom windowDevice2 MAX_18012b
(nur) Sowas kann es nicht geben. Poste mal bitte das Ergebnis von "list rooms1livingroom" im Kommandofeld von Fhem
Zitat von: amenomade am 05 November 2019, 19:22:25
define rooms1livingroom dummy
attr rooms1livingroom temperatureDevice1 MAX_0885cd
attr rooms1livingroom temperatureDevice2 MAX_18073f
attr rooms1livingroom temperatureDevice3 FGSD002_ID23
attr rooms1livingroom thermostatDevice MAX_18073f
attr rooms1livingroom windowDevice1 MAX_17fe6e
attr rooms1livingroom windowDevice2 MAX_18012b
(nur) Sowas kann es nicht geben. Poste mal bitte das Ergebnis von "list rooms1livingroom" im Kommandofeld von Fhem
Ich habe hier von define nur die Attribute gepostet, da es vorrangig darum ging. Hier aber gerne ein List meines Devices
Internals:
FUUID xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
NAME rooms1livingroom
NR 376
STATE Wohnzimmer
TYPE dummy
Helper:
DBLOG:
roomclimate:
logdb:
TIME 1573018336.61718
VALUE medium
roomdesiredTemperature:
logdb:
TIME 1573021916.44008
VALUE 21.0
roomtemperature1:
logdb:
TIME 1573023503.74073
VALUE 19.4
roomtemperature2:
logdb:
TIME 1573018272.31651
VALUE 18.3
roomtemperatureAvg:
logdb:
TIME 1573023503.78897
VALUE 19.1
roomthermostatMode:
logdb:
TIME 1573020592.13906
VALUE auto
roomthermostatPosition:
logdb:
TIME 1573022049.09975
VALUE 100
roomwindow1:
logdb:
TIME 1573020589.93032
VALUE wrc
roomwindow2:
logdb:
TIME 1573020589.95761
VALUE wlc
READINGS:
2019-10-17 13:19:24 roomName Wohnzimmer
2019-11-06 08:09:26 roomclimate medium
2019-11-06 08:09:28 roomdesiredTemperature 21.0
2019-10-30 10:28:31 roomhumidity --
2019-11-06 08:09:26 roomtemperature1 19.4
2019-11-06 06:34:32 roomtemperature2 18.3
2019-11-05 23:33:54 roomtemperature3 19.5
2019-11-06 08:09:26 roomtemperatureAvg 19.1
2019-10-30 10:28:30 roomtemperatureDevice1 Wandthermostat
2019-10-30 10:28:31 roomtemperatureDevice2 Heizkörperthermostat
2019-10-30 10:28:31 roomtemperatureDevice3 Rauchmelder
2019-11-06 08:09:26 roomtemperatureTrend1 -1
2019-11-06 06:34:32 roomtemperatureTrend2 -1
2019-11-05 23:33:54 roomtemperatureTrend3 0
2019-11-06 08:09:28 roomthermostatMode auto
2019-11-06 08:09:28 roomthermostatPosition 100
2019-11-06 08:09:34 roomwindow1 wrc
2019-11-06 08:09:34 roomwindow2 wlc
2019-10-30 10:28:31 roomwindowDevice1 Fenster links
2019-10-30 10:28:31 roomwindowDevice2 Fenster rechts
Attributes:
DbLogExclude .*
DbLogInclude roomclimate:86400,roomdesiredTemperature:3600,roomhumidity:3600,roomtemperature1:3600,roomtemperature2:3600,roomtemperature3:3600,roomtemperature4:3600,roomtemperatureAvg:3600,roomthermostatMode:3600,roomthermostatPosition:3600,roomwindow1:3600,roomwindow2:3600,roomwindow3:3600,roomwindow4:3600
group Raum
room Räume
stateFormat {ReadingsVal("$name","roomName","unbekannt");}
temperatureDevice1 MAX_0885cd
temperatureDevice2 MAX_18073f
temperatureDevice3 FGSD002_ID23
thermostatDevice MAX_18073f
windowDevice1 MAX_17fe6e
windowDevice2 MAX_18012b
Das Reading roomName wurde manuell per setreading gesetzt, die anderen room.* Readings werden automatisch bei Änderung durch eine Funktion in 99_myUtils.pm gesetzt
hier noch als Info die notifies und die Funktionen in 99_myUtils.pm
notify
define temperatureChange notify .*:temperature:.* {SetRoomTemperature("$NAME")}
setuuid temperatureChange xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
define humidityChange notify .*:humidity:.* {SetRoomHumidity("$NAME")}
setuuid humidityChange xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
define thermostatChange notify (.*:valveposition:.*|.*:mode:.*|.*:desiredTemperature:.*) {SetRoomThermostat("$NAME")}
setuuid thermostatChange xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
define windowChange notify Windows:windowsOpen:.* {SetRoomWindows()}
setuuid windowChange xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx
99_myUtils.pm
sub GetTemperatureTrend($$) {
my ($myRoom,$myValue) = @_;
my $myDesired = ReadingsNum($myRoom,"roomdesiredTemperature",20);
my $myMin = $myDesired;
my $myMax = maxNum(25,$myDesired);
if ($myValue < $myMin) {return(-1);} elsif
($myValue > $myMax) {return(1);} else {return(0);};
}
sub CheckTemperature($) {
my ($myRoom) = @_;
my $myValue = ReadingsNum($myRoom,"roomtemperatureAvg",20);
return(GetTemperatureTrend($myRoom,$myValue));
}
sub CheckHumidity($) {
my ($myRoom) = @_;
my $myValue = ReadingsNum($myRoom,"roomhumidity",40);
if ($myValue < 40) {return(-1);} elsif
($myValue > 60) {return(1);} else {return(0);};
}
sub SetClimate($$$$$$) {
my ($myDevice,$myRoom,$myReading,$myReadingNum,$myChanged,$myDefault) = @_;
if ($myDevice eq "") {return($myChanged)};
if (AttrVal($myRoom,$myReading."Device".$myReadingNum,"") ne $myDevice) {return($myChanged);}
my $myValue = ReadingsNum($myDevice,$myReading,$myDefault);
fhem("setreading ".$myRoom." room".$myReading.$myReadingNum." ".sprintf("%.1f",$myValue));
if ($myReading eq "temperature") {
fhem("setreading ".$myRoom." room".$myReading."Trend".$myReadingNum." ".GetTemperatureTrend($myRoom,$myValue));
} else {
fhem("setreading ".$myRoom." room".$myReading."Trend".$myReadingNum." ".CheckHumidity($myRoom));
}
return(1);
}
sub SetWindow($$$) {
my ($myDevice,$myRoom,$myReadingNum) = @_;
if ($myDevice eq "") {return()};
my $myValue = AttrVal($myDevice,"deviceType","wr").substr(Value($myDevice),0,1);
fhem("setreading ".$myRoom." roomwindow".$myReadingNum." ".$myValue);
}
sub SetThermostat($$) {
my ($myDevice,$myRoom) = @_;
if ($myDevice eq "") {return()};
if (AttrVal($myRoom,"thermostatDevice","") ne $myDevice) {return();}
fhem("setreading ".$myRoom." roomdesiredTemperature ".sprintf("%.1f",ReadingsVal($myDevice,"desiredTemperature",0)));
fhem("setreading ".$myRoom." roomthermostatMode ".ReadingsVal($myDevice,"mode",""));
fhem("setreading ".$myRoom." roomthermostatPosition ".ReadingsVal($myDevice,"valveposition",0));
}
sub GetTemperatureAvg($) {
my ($myRoom) = @_;
my $myTemperature = 0;
if (AttrVal($myRoom,"temperatureDevice1","") eq "") {return("--");}
$myTemperature+=ReadingsNum($myRoom,"roomtemperature1",0);
if (AttrVal($myRoom,"temperatureDevice2","") eq "") {return($myTemperature);}
$myTemperature+=ReadingsNum($myRoom,"roomtemperature2",0);
if (AttrVal($myRoom,"temperatureDevice3","") eq "") {return(sprintf("%.1f",($myTemperature/2)));}
$myTemperature+=ReadingsNum($myRoom,"roomtemperature3",0);
if (AttrVal($myRoom,"temperatureDevice4","") eq "") {return(sprintf("%.1f",($myTemperature/3)));}
$myTemperature+=ReadingsNum($myRoom,"roomtemperature4",0);
return(sprintf("%.1f",($myTemperature/4)));
}
sub SetRoomClimate($) {
my ($myRoom) = @_;
fhem("setreading ".$myRoom." roomtemperatureAvg ".GetTemperatureAvg($myRoom));
my $myTemperature = CheckTemperature($myRoom);
my $myHumidity = CheckHumidity($myRoom);
my $myClimateState = "good";
if (($myTemperature != 0) || ($myHumidity != 0)) {$myClimateState = "medium";}
if (($myTemperature != 0) && ($myHumidity != 0)) {$myClimateState = "bad";}
fhem("setreading ".$myRoom." roomclimate ".$myClimateState);
}
sub SetWindows($) {
my ($myRoom) = @_;
SetWindow(AttrVal($myRoom,"windowDevice1",""),$myRoom,"1");
SetWindow(AttrVal($myRoom,"windowDevice2",""),$myRoom,"2");
SetWindow(AttrVal($myRoom,"windowDevice3",""),$myRoom,"3");
SetWindow(AttrVal($myRoom,"windowDevice4",""),$myRoom,"4");
}
sub SetRoomTemperature($) {
my ($myDevice) = @_;
foreach my $myRoom (devspec2array("TYPE=dummy:FILTER=group=Raum")) {
my $myChanged = 0;
$myChanged = SetClimate($myDevice,$myRoom,"temperature","1",$myChanged,"--");
$myChanged = SetClimate($myDevice,$myRoom,"temperature","2",$myChanged,"");
$myChanged = SetClimate($myDevice,$myRoom,"temperature","3",$myChanged,"");
$myChanged = SetClimate($myDevice,$myRoom,"temperature","4",$myChanged,"");
if ($myChanged == 1) {SetRoomClimate($myRoom);};
}
}
sub SetRoomHumidity($) {
my ($myDevice) = @_;
foreach my $myRoom (devspec2array("TYPE=dummy:FILTER=group=Raum")) {
if (SetClimate($myDevice,$myRoom,"humidity","",0,"--") == 1) {SetRoomClimate($myRoom);};
}
}
sub SetRoomWindows() {
foreach my $myRoom (devspec2array("TYPE=dummy:FILTER=group=Raum")) {SetWindows($myRoom);}
}
sub SetRoomThermostat($) {
my ($myDevice) = @_;
foreach my $myRoom (devspec2array("TYPE=dummy:FILTER=group=Raum")) {SetThermostat($myDevice,$myRoom);}
}
sub InitDevice($$$$) {
my ($myRoom,$myReading,$myReadingNum,$myDefault) = @_;
if ($myDefault eq "") {
fhem("deletereading ".$myRoom." room".$myReading.$myReadingNum);
} else {
fhem("setreading ".$myRoom." room".$myReading.$myReadingNum." ".$myDefault);
}
fhem("deletereading ".$myRoom." ".$myReading."Trend".$myReadingNum);
fhem("deletereading ".$myRoom." ".$myReading."Device".$myReadingNum);
my $myDevice = AttrVal($myRoom,$myReading."Device".$myReadingNum,"");
if ($myDevice eq "") {return()};
if ($myReading eq "window") {
SetWindow($myDevice,$myRoom,$myReadingNum);
} else {
SetClimate($myDevice,$myRoom,$myReading,$myReadingNum,0,$myDefault);
}
fhem("setreading ".$myRoom." room".$myReading."Device".$myReadingNum." ".AttrVal($myDevice,"deviceName",""));
}
sub InitRooms() {
my $myDevice = "NoDevice";
my $myDeviceName = "";
my $myValue = "--";
foreach my $myRoom (devspec2array("TYPE=dummy:FILTER=group=Raum")) {
InitDevice($myRoom,"temperature","1","--");
InitDevice($myRoom,"temperature","2","");
InitDevice($myRoom,"temperature","3","");
InitDevice($myRoom,"temperature","4","");
InitDevice($myRoom,"humidity","","--");
InitDevice($myRoom,"window","1","n/a");
InitDevice($myRoom,"window","2","");
InitDevice($myRoom,"window","3","");
InitDevice($myRoom,"window","4","");
fhem("deletereading ".$myRoom." roomdesiredTemperature");
fhem("setreading ".$myRoom." roomthermostatMode n/a");
fhem("deletereading ".$myRoom." roomthermostatPosition");
SetThermostat(AttrVal($myRoom,"thermostatDevice",""),$myRoom);
fhem("deletereading ".$myRoom." roomclimate");
SetRoomClimate($myRoom);
}
my $myAttr = "";
foreach my $myDevice (devspec2array("deviceName=.*")) {
$myAttr = AttrVal($myDevice,"deviceName","");
if ($myAttr ne "") {fhem("setreading ".$myDevice." deviceName ".$myAttr);}
}
}
das geht mit Sicherheit kürzer und eleganter, aber es funktioniert so ...
InitRooms initialisiert alle Räume - ich könnte hier natürlich die Attribute in ein Reading schieben (genauso, wie ich es beim Namen auch mache), hilft mir aber auch nicht wirklich weiter ...
Das Attribut deviceType hab' ich bei den Fensterkontakten gesetzt, um das korrekte Symbol anzeigen zu können:
- dl,dr für Tür mit Griff links bzw. rechts
- wl,wr für Fenster mit Griff links bzw. rechts
- r für Dachfenster
Ergänzt wird das ganze durch "o" für open, "c" für closed oder "t" für tilted - je nach Zustand - und im Symbol ausgewertet:
<div class="autohide"
data-type="symbol"
data-device="dataDevice"
data-get="dataGet"
data-color="transparent"
data-states='["dlc","dlo","drc","dro","wlc","wlo","wlt","wrc","wro","wrt","rc","ro"]'
data-icons='["oa-fts_door","oa-fts_door_open","oa-fts_door flip-v","oa-fts_door_open flip-v","oa-fts_window_1w flip-v","oa-fts_window_1w_open flip-v","oa-fts_window_1w_tilt flip-v","oa-fts_window_1w","oa-fts_window_1w_open","oa-fts_window_1w_tilt","oa-fts_window_roof",
"oa-fts_window_roof_open_1"]'
data-colors='["symbol_ok","symbol_warn","symbol_ok","symbol_warn","symbol_ok","symbol_warn","symbol_warn","symbol_ok","symbol_warn","symbol_warn","symbol_ok","symbol_warn"]'
</div>
Ich verstehe nicht, wie Du diese Attribute gesetzt hast, ohne userAttr auch zu definieren. Bei mir kommt:rooms1livingroom: unknown attribute temperatureDevice1
da diese attribute keine standard Attribute eines dummy sind...
Aber gut...
Zu deine Frage: ich glaube nicht, dass sowas möglich ist: data-device muss ein Device sein, und aus TabletUI (Javascript) kannst Du keine Funktion aus myUtils (Perl) aufrufen. Wenn dann, musst Du eine Javascript Funktion schreiben.
Das mit Quotes wäre nicht das Problem. Das kann man auch in Javascript escapen
Zitat von: amenomade am 06 November 2019, 13:08:17
Ich verstehe nicht, wie Du diese Attribute gesetzt hast, ohne userAttr auch zu definieren. Bei mir kommt:rooms1livingroom: unknown attribute temperatureDevice1
da diese attribute keine standard Attribute eines dummy sind...
Aber gut...
Zu deine Frage: ich glaube nicht, dass sowas möglich ist: data-device muss ein Device sein, und aus TabletUI (Javascript) kannst Du keine Funktion aus myUtils (Perl) aufrufen. Wenn dann, musst Du eine Javascript Funktion schreiben.
Das mit Quotes wäre nicht das Problem. Das kann man auch in Javascript escapen
userAttr hab' ich beim global Device gesetzt ... sorry - hatte ich nicht auf dem Schirm
Die Frage wäre allerdings wo ich die Javascript Funktion einfüge ... im Prinzip müsste ja dann eine bestimmte Syntax für
jedes Widget ausgewertet werden um den Namen des Devices zu ermitteln. Ich fürchte dafür reichen meine JS Kenntnisse nicht aus ...
Zitat von: dt2510 am 06 November 2019, 13:42:07
userAttr hab' ich beim global Device gesetzt ... sorry - hatte ich nicht auf dem Schirm
Die Frage wäre allerdings wo ich die Javascript Funktion einfüge ... im Prinzip müsste ja dann eine bestimmte Syntax für jedes Widget ausgewertet werden um den Namen des Devices zu ermitteln. Ich fürchte dafür reichen meine JS Kenntnisse nicht aus ...
Ist auch ein bisschen zu viel für mich ;)
Man könnte wohl den Inhalt des Attributes über
http://server:port/fhem?cmd={AttrVal(%22device%22,%22attr%22,0)}&XHR=1
abfragen, allerdings müsste ich noch in Erfahrung bringen, ob ich den Rückgabewert irgendwie in meinen <div> Tag bekomme und ob der auch korrekt an das Widget übergeben wird.
Eine Lösung in Javascript gibt es wohl in fhemweb.js - allerdings müsste das dann wohl in fhem-tablet-ui.js eingebaut werden ... da will ich selbst nicht dran - wird auch bei Updates problematisch.
ich hab' gerade mal den Aufruf im Browser getestet (über VPN)
https://192.168.220.242:8085/fhem?cmd={AttrVal(%22rooms1livingroom%22,%22temperatureDevice3%22,0)}&XHR=1
ohne Erfolg
https://192.168.220.242:8084/fhem?cmd={AttrVal(%22rooms1livingroom%22,%22temperatureDevice3%22,0)}&XHR=1
im Lokalen Netz liefert das korrekte Ergebnis ...