FHEM Forum

FHEM => Anfängerfragen => Thema gestartet von: __benny__ am 07 November 2017, 21:41:04

Titel: Geräteliste in FHEM
Beitrag von: __benny__ am 07 November 2017, 21:41:04
Hallo,

ich habe folgendes anliegen:
Alle HM-CC-RT-DN (nur Kanal 4) auf "controlManu on" setzen um eine Wartung (Entlüften) der Heizungsanlage durchzuführen
Alle HM-CC-RT-DN (nur Kanal 4) auf "controlParty" setzen um "unverheizt" in den Urlaub zu fahren

Dazu müsste mir FHEM eine Liste der "bekannten" HM-CC-RT-DN ausgeben. Realisiert habe ich das nun wie folgt:

Eine Datei 99_ThermoMainentanceUtils.pm angelegt.
Darin habe ich eine globale Variable als Array definiert.

my @thermostates;

Mittels der nachfoglenden Funktion bekomme ich eine Liste aller Kanale aller "bekannten" HM-CC-RT-DN. Diese filtere ich nach Kanal 4.

sub ThermoGetAll() {

# clear current array of devices
@thermostates = ();

# get all HM-CC-RT-DN devices and channels
my @devices = devspec2array("model=HM-CC-RT-DN");

for my $device (@devices) {
# only channel 4 (Clima) is important
if ($device =~ m/_Clima$/) {
push(@thermostates, ThermoCreateRecord($device));
}
}
}

sub ThermoCreateRecord($) {

my ($device) = @_;

my $thermostate = {
device => $device,
temperature => "0.0",
mode => "auto"
}
}


Durch das "push" werden die "gesuchten" Kanäle als "record" in das Array abgelegt. Dadurch kann ich auch die Temperatur und den Betriebsmodus pro Gerät vor der Wartung speichern.

Starten tue ich dann die Wartung durch

sub ThermoMaintenanceOn() {

foreach my $record (@thermostates) {

# get current temperature setting of device
$record->{temperature} = fhem("get $record->{device} param desired-temp");

# get current mode of device
$record->{mode} = fhem("get $record->{device} param controlMode");

# open valve full
fhem("set $record->{device} controlManu on");

# update device immediate
fhem("set $record->{device} burstXmit");
}
}


Beenden kann ich die Wartung mittels

sub ThermoMaintenanceOff() {

foreach my $record (@thermostates) {

# restore mode of device
fhem("set $record->{device} controlMode $record->{mode}");

# restore temperature setting of device
fhem("set $record->{device} desired-temp $record->{temperature}");

# update device immediate
fhem("set $record->{device} burstXmit");
}
}


Für den Urlaub gibt es

sub ThermoVacation($$$$$) {

my ($temperature, $dateStart, $dateEnd, $timeStart, $timeEnd) = @_;

# map time to 00 or 30, others are not accepted by device
$timeStart =~ s/\:[0-2].$/:00/;
$timeStart =~ s/\:[3-5].$/:30/;
$timeEnd =~ s/\:[0-2].$/:00/;
$timeEnd =~ s/\:[3-5].$/:30/;

foreach my $record (@thermostates) {

# set "party/vacation" mode
fhem ("set $record->{device} controlParty $temperature $dateStart $timeStart $dateEnd $timeEnd");
}
}


Alles funktioniert wie es soll, nur werde ich das Gefühl nicht los, dass es etwas ähnliches eigentlich schon geben müsste oder?
Daher meine Frage: Gibt es in FHEM hierfür schon eine Funktionalität die ich "übersehen" habe?
-> Wenn ja bitte einen Schubs zur entsprechenden Doku.

Titel: Antw:Geräteliste in FHEM
Beitrag von: Hollo am 07 November 2017, 22:18:06
Naja, in der Regel hat man wahrscheinlich irgendein Schema für die Bezeichnung.

Damit lässt sich z.B. bei mir mit einem einzelnen
fhem ("set .*_Heizung_Clima controlManu on")
Dein Entlüften vorbereiten und sinngemäß auch wieder beenden.
Titel: Antw:Geräteliste in FHEM
Beitrag von: CoolTux am 07 November 2017, 22:39:48
Dein Clima Kanal kannst aber auch einfacher finden

:FILTER=chanNo=04
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 08 November 2017, 08:12:42
@Hollo:
naja das
..._Clima
ist ja vom System vorgegeben, damit könnte ich arbeiten. Mir ist nur nicht klar wie ich dein
fhem("set .*_Heizung_Clima controlManu on")
wieder rückgängig mache?
Ein einfaches
fhem("set .*_Heizung_Clima controlManu off")
langt da nicht. Ich muss mir ja irgendwie merken wie die Thermostate vorher eingestellt waren.

@CoolTux:
Wo genau würde dieser Filter angewendet werden? Etwa so?
my @devices = devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=4");

Danke und Gruß
Titel: Antw:Geräteliste in FHEM
Beitrag von: CoolTux am 08 November 2017, 08:46:28
Zitat von: __benny__ am 08 November 2017, 08:12:42
@Hollo:
naja das
..._Clima
ist ja vom System vorgegeben, damit könnte ich arbeiten. Mir ist nur nicht klar wie ich dein
fhem("set .*_Heizung_Clima controlManu on")
wieder rückgängig mache?
Ein einfaches
fhem("set .*_Heizung_Clima controlManu off")
langt da nicht. Ich muss mir ja irgendwie merken wie die Thermostate vorher eingestellt waren.

@CoolTux:
Wo genau würde dieser Filter angewendet werden? Etwa so?
my @devices = devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=4");

Danke und Gruß

Bei mir geht das so

{ devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=04") }


Getestet direkt in der Eingabezeile von FHEMWEB
Titel: Antw:Geräteliste in FHEM
Beitrag von: Hollo am 08 November 2017, 09:18:34
Zitat von: __benny__ am 08 November 2017, 08:12:42
...Ich muss mir ja irgendwie merken wie die Thermostate vorher eingestellt waren.
Mehr oder weniger.   ;D
Wenn sie sonst auf "auto" stehen, setzt Du sie halt einfach wieder auf auto und die arbeiten direkt mit dem gültigen Wert der Temp-Liste.
Bei "manual" setzt Du sie einfach auf einen "passenden" Temperaturwert; Du wirst das Entlüften ja nicht mitten in der Nacht machen wollen.
fhem("set .*_Heizung_Clima controlManu 20.0")
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 08 November 2017, 19:30:05
@Hollo
eigentlich will ich nach dem Entlüften nicht nochmal 10 Heizkörper händisch anfassen, das widerspricht irgendwie dem Wort "Automatisierung"  ::)  ;D

@CoolTux
klappt leider nicht, das Ergebnis ist dann kein Array sondern eine Zahl?


Naja dann scheint es keinen "natürlichen" Weg zu geben - Danke an alle Antwortenden -> gelöst
Titel: Antw:Geräteliste in FHEM
Beitrag von: Hollo am 08 November 2017, 22:01:19
Zitat von: __benny__ am 08 November 2017, 19:30:05
@Hollo
eigentlich will ich nach dem Entlüften nicht nochmal 10 Heizkörper händisch anfassen, das widerspricht irgendwie dem Wort "Automatisierung"  ::)  ;D
Was
Was ist an 1 Befehl händisch und umständlich?  :o

Dein Weg ist doch okay, wenn er funktioniert.
Es gibt meist mehrere Varianten und selten die Ideallösung.

Titel: Antw:Geräteliste in FHEM
Beitrag von: CoolTux am 08 November 2017, 22:51:33
Zitat von: __benny__ am 08 November 2017, 19:30:05
@Hollo
eigentlich will ich nach dem Entlüften nicht nochmal 10 Heizkörper händisch anfassen, das widerspricht irgendwie dem Wort "Automatisierung"  ::)  ;D

@CoolTux
klappt leider nicht, das Ergebnis ist dann kein Array sondern eine Zahl?


Naja dann scheint es keinen "natürlichen" Weg zu geben - Danke an alle Antwortenden -> gelöst

Ja natürlich ist es eine Zahl. Weil die Liste in ein Array gelesen wird. Und das return Dir nur die Anzahl der Elemente zurück gibt. Du musst das ganze dann halt wie ein Perl Array behandeln.
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 09 November 2017, 07:08:34
@Hollo
Naja ich muss diesen zusätzlich in die Console eingeben, nachdem ich mir den Namen vom Device gesucht habe. Schließlich ist ja nicht klar, dass immer das gleiche Gerät gerade im Modus "Manu" ist. Mit der momentanen Lösung heißt es "Feuern-und-vergessen".

@CoolTux

Mit folgendem Code sehe ich die Log-Meldung

sub ThermoGetAll() {

# clear current array of devices
@thermostates = ();

# get all HM-CC-RT-DN devices and channels
my @devices = devspec2array("model=HM-CC-RT-DN");

for my $device (@devices) {

# only channel 4 (Clima) is important
if ($device =~ m/_Clima$/) {

{ Log 1, "ThermoGetAll: $device" };
push(@thermostates, ThermoCreateRecord($device));
}
}
}


damit leider nicht

sub ThermoGetAll() {

# clear current array of devices
@thermostates = ();

# get all HM-CC-RT-DN devices and channels
my @devices = devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=4");

for my $device (@devices) {

            { Log 1, "ThermoGetAll: $device" };
            push(@thermostates, ThermoCreateRecord($device));
}
}


Mal noch eine andere Frage zum Thema:
Wenn ich die Kanäle der Geräte einem speziellen "room" zuteile, dann müsste ich mir doch alle Geräte dieses Raums geben lassen können. Das müsst ich zwar konfigurieren, dafür könnte ich allerdings bestimmte Geräte von der Aktion ausschließen oder?


Titel: Antw:Geräteliste in FHEM
Beitrag von: CoolTux am 09 November 2017, 07:29:03
Benny! Konzentration und bisschen nachschauen bitte!

04
Man(n) beachte die 0 vor der vier

;D  ;D  ;D



Grüße
Leon
Titel: Antw:Geräteliste in FHEM
Beitrag von: DeeSPe am 09 November 2017, 09:46:15
Bissel viel Durcheinander! ;)
sub ThermoGetAll() {

# clear current array of devices
# @thermostates = ();
        # hier fehlte ein my
        my @thermostates;

# get all HM-CC-RT-DN devices and channels
my @devices = devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=04");

# for my $device (@devices) {
        # hier sollte foreach stehen
foreach my $device (@devices) {

            { Log 1, "ThermoGetAll: $device" };
            push(@thermostates, ThermoCreateRecord($device));
}
}


Gruß
Dan
Titel: Antw:Geräteliste in FHEM
Beitrag von: CoolTux am 09 November 2017, 09:59:30
Danke Dir Dan.
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 09 November 2017, 18:17:16
@Dan
nöp fehlte nicht, nur ist @thermostates außerhalb der "sub" global definiert, sonst wäre das ja weg am Ende der sub und wäre sinnfrei... -> siehe initialen Post

@CoolTux
verdammt, die "0" bringts :-) Danke
Titel: Antw:Geräteliste in FHEM
Beitrag von: DeeSPe am 09 November 2017, 18:59:08
Zitat von: __benny__ am 09 November 2017, 18:17:16
@Dan
nöp fehlte nicht, nur ist @thermostates außerhalb der "sub" global definiert, sonst wäre das ja weg am Ende der sub und wäre sinnfrei... -> siehe initialen Post

@CoolTux
verdammt, die "0" bringts :-) Danke

Global würde ich sowas aber lieber nicht definieren.
Was spricht dagegen die Variable an die jeweiligen Funktionen weiterzugeben?

Gruß
Dan
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 09 November 2017, 19:13:07
@Dan
naja irgendwo muss ich es vorhalten. In der Sprache "C" würde ich diese Variable in der main-Funktion definieren und genau wie du sagst an jede Funktion als Pointer übergeben. Wäre ein "dummy" in fhem.cfg dazu äquivalent?
Oder wäre die "globale" Definition schon ok nur die Übergabe an einzelne Funktionen fehlt noch? Wie macht man sowas korrekt in Perl?
Titel: Antw:Geräteliste in FHEM
Beitrag von: DeeSPe am 09 November 2017, 19:34:16
Wieso musst Du es denn "vorhalten"?

Mit:
my @devs = devspec2array("model=HM-CC-RT-DN:FILTER=chanNo=04");
hast Du sofort immer "lokal" ein Array mit den Namen aller Devices die zu der devspec gehören.

Gruß
Dan
Titel: Antw:Geräteliste in FHEM
Beitrag von: DeeSPe am 09 November 2017, 19:42:13
Ich bin kein "Perl-Profi".
Angewöhnt habe ich mir global nur Konstanten zu setzen.

z.B.:
my $thermostats = "model=HM-CC-RT-DN:FILTER=chanNo=04";

Und dann z.B.:
sub my_func {
  my @devs = devspec2array($thermostats);
}


Gruß
Dan
Titel: Antw:Geräteliste in FHEM
Beitrag von: Thorsten Pferdekaemper am 09 November 2017, 21:02:08
Hi,
soweit ich das verstehe, ist das "Problem" sich den alten Zustand zu merken und dann später wieder zurückzuholen. Ich würde da ganz "brutal" das ganze am Device selbst machen. Also in etwa so:

$main::defs{$device}{bennysOldDesiredTemp} = ReadingsVal($device, "desired-temp",22);

...und später

fhem("set ".$device." desired-temp ".$main::defs{$device}{bennysOldDesiredTemp});
delete $main::defs{$device}{bennysOldDesiredTemp};

Man sieht dann sogar in den Internals, was man getrieben hat.

Wenn das ganze einen FHEM-Neustart überleben soll, dann kann man das auch mit Readings machen:

readingsSingleUpdate($main::defs{$device}, "bennysOldDesiredTemp", ReadingsVal($device, "desired-temp",22), 1);

...und später

fhem("set ".$device." desired-temp ".ReadingsVal($device, "bennysOldDesiredTemp",22));
fhem("deletereading ".$device." bennysOldDesiredTemp");

Das mit den Deletes ist natürlich optional.
Ich habe das nicht ausprobiert...
Gruß,
   Thorsten

Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 09 November 2017, 21:08:02
Vorhalten, weil ich mir ja die Zustände der Geräte merken will bevor ich temporär die Konfiguration überschreibe um diese dann nach der Wartung wieder so einzustellen wie diese vor der Wartung eingestellt waren.

mit

push(@thermostates, ThermoCreateRecord($device));


wird ja die

sub ThermoCreateRecord($) {

my ($device) = @_;

# { Log 1, "ThermoCreateRecord: \$device: $device" };

my $thermostate = {
device => $device,
temperature => "0.0",
mode => "auto"
}
}


In dieser Struktur ist dann Platz für die Elemente der Konfiguration die überschreiben werden - konrekt so:

sub ThermoMaintenanceOn() {

foreach my $record (@thermostates) {

# get current temperature setting of device
$record->{temperature} = fhem("get $record->{device} param desired-temp"); # <--- hier wird die aktuell eingestellte Temperatur ausgelesen

# get current mode of device
$record->{mode} = fhem("get $record->{device} param controlMode"); # <--- hier wird der aktuell eingestellte Bedienmodus ausgelesen

# { Log 1, "ThermoMaintenanceOn: \$device=$record->{device} : $record->{temperature} : $record->{mode}" };

# open valve full
fhem("set $record->{device} controlManu on"); # <--- hier wird die Einstellung überschrieben

# update device immediate
fhem("set $record->{device} burstXmit");
}
}


Jetzt kann ich die Wartung durchführen und wenn ich damit fertig bin, dann brauche ich nur noch den Button anklicken der

sub ThermoMaintenanceOff() {

foreach my $record (@thermostates) {

# { Log 1, "ThermoMaintenanceOff: \$device=$record->{device} : $record->{temperature} : $record->{mode}" };

# restore mode of device
fhem("set $record->{device} controlMode $record->{mode}"); # <--- hier wird der gemerkte Bedienmodus restauriert

# restore temperature setting of device
fhem("set $record->{device} desired-temp $record->{temperature}"); # <--- hier wird die gemerkte Temperatur restauriert

# update device immediate
fhem("set $record->{device} burstXmit");
}
}

aufruft und alles ist so, als hätte ich nie etwas geändert.
Titel: Antw:Geräteliste in FHEM
Beitrag von: Hollo am 09 November 2017, 21:19:40
Zitat von: __benny__ am 09 November 2017, 07:08:34
@Hollo
Naja ich muss diesen zusätzlich in die Console eingeben, nachdem ich mir den Namen vom Device gesucht habe. Schließlich ist ja nicht klar, dass immer das gleiche Gerät gerade im Modus "Manu" ist. Mit der momentanen Lösung heißt es "Feuern-und-vergessen".
Das kannst Du damit genauso.   :)
Titel: Antw:Geräteliste in FHEM
Beitrag von: __benny__ am 09 November 2017, 21:35:18
@Hollo
Ich kann deinen Ansatz nicht nachvollziehen. Wärst du so nett mal Schritt für Schritt darzulegen wie das gehen soll? Also was muss ich alles tun um ein beliebiges Gerät mit deiner Methode so einzustellen wie es vor der Wartung war.

@Thorsten:
Interessant, leider stecke ich noch nicht so tief in FHEM drin, um deine Ausführungen direkt verstehen zu können.

Das legt eine neue Variable (Reading) "bennysOldDesiredTemp" am Gerät an oder? (Wo steht denn das in der Referenz?)

$main::defs{$device}{bennysOldDesiredTemp}


Das müsste dann also so in die sub

sub ThermoMaintenanceOn($) {

    my ($device) = @_;

    $main::defs{$device}{bennysOldDesiredTemp} = ReadingsVal($device, "desired-temp",22); # <-- aktuelle Temperatur lesen, falls Fehlschlag dann "22°C" annehmen
    $main::defs{$device}{bennysOldcontrolMode} = ReadingsVal($device, "controlMode",auto); # <-- aktuellen Modus lesen, falls Fehlschlag dann "auto" annehmen

#   { Log 1, "ThermoMaintenanceOn: \$device=$record->{device} : $record->{temperature} : $record->{mode}" };

    # open valve full
    fhem("set $record->{device} controlManu on"); # <--- hier wird die Einstellung überschrieben

    # update device immediate
    fhem("set $record->{device} burstXmit");
}

Wie würde ich dass denn in fhem.cfg aufrufen um alle benötigten Geräte zu erwischen, also nur die _Clima?