Hauptmenü

Perl switch statement

Begonnen von dantist, 22 Juli 2015, 19:48:08

Vorheriges Thema - Nächstes Thema

dantist

Hallo zusammen,

ich finde kaum Informationen zu FHEM in Verbindung mit dem Perl switch-Statement. Scheinbar wird es nicht unterstützt, ich bekomme jedenfalls trotz korrekter Syntax (analog zu http://perldoc.perl.org/5.8.8/Switch.html) Fehler im Log angezeigt. libswitch-perl ist installiert.

Hat das schon einmal jemand zum Laufen bekommen und könnte ein Code-Beispiel beisteuern?

Mehrere if-Befehle funktionieren zwar, finde ich aber unübersichtlich.

Gruß
Dan

maxritti

Magst du die Fehler aus dem Log und ggf auch deinen Code eventuell auch Posten?
Hilft eventuell bei der Lösungsfindung.  ;)

dantist

Klar, gerne:


SchalterSchlafzimmer {
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  switch ($statusLichtSchlafzimmer) {
    case 0 { fhem("set Pushbullet message aus"); }
    else { fhem("set Pushbullet message an"); }
  }
}


2015.07.22 21:07:30.313 1: PERL WARNING: Number found where operator expected at (eval 7908) line 4, near "case 0"
2015.07.22 21:07:30.326 1: PERL WARNING: Number found where operator expected at (eval 7909) line 4, near "case 0"
2015.07.22 21:07:30.338 1: PERL WARNING: Number found where operator expected at (eval 7910) line 4, near "case 0"


Ich bin nicht sicher, ob der switch-Parameter in Anführungszeichen gehört switch("$statusLichtSchlafzimmer")

Es klappt aber weder mit noch ohne.

maxritti

Fehler sind es ja erst mal nicht. Denn da steht ja recht deutlich WARNING  :)

Dann würde ich mir mal den Wert von der Variablen ausgeben lassen.
Und dann mal ins Log schauen.

SchalterSchlafzimmer {
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  Log (3, "statusLichtSchlafzimmer: $statusLichtSchlafzimmer");
  switch ($statusLichtSchlafzimmer) {
    case 0 { Log(3, "set Pushbullet message aus"); }
    else { Log(3, "set Pushbullet message an"); }
  }
}

dantist

Zitat von: maxritti am 22 Juli 2015, 21:37:21
Fehler sind es ja erst mal nicht. Denn da steht ja recht deutlich WARNING  :)

Dann würde ich mir mal den Wert von der Variablen ausgeben lassen.
Und dann mal ins Log schauen.

SchalterSchlafzimmer {
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  Log (3, "statusLichtSchlafzimmer: $statusLichtSchlafzimmer");
  switch ($statusLichtSchlafzimmer) {
    case 0 { Log(3, "set Pushbullet message aus"); }
    else { Log(3, "set Pushbullet message an"); }
  }
}


Das ist das Ergebnis:

2015.07.22 21:58:28.411 1: PERL WARNING: Number found where operator expected at (eval 9736) line 6, near "case 0"
2015.07.22 21:58:28.413 3: eval: {
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  Log (3, "statusLichtSchlafzimmer: $statusLichtSchlafzimmer");
  switch ($statusLichtSchlafzimmer) {
    case 0 { Log (3, "aus"); }
    else { Log (3, "an"); }
  }
}
2015.07.22 21:58:28.415 3: AktionenSchalterSchlafzimmerTest return value: syntax error at (eval 9736) line 5, near ") {"
syntax error at (eval 9736) line 7, near "}
    else"


Nur wenn ich den Switch-Befehl komplett rausnehme, läuft es. Dann loggt er auch brav
2015.07.22 21:55:49.575 3: statusLichtSchlafzimmer: 75

justme1968

welche perl version hast du denn? es hat schon eine grund das es bei perldoc nur für version 5.8.8 beschrieben ist und nicht mehr bei aktuellen versionen.

gruß
  andre
hue, tradfri, alexa-fhem, homebridge-fhem, LightScene, readingsGroup, ...

https://github.com/sponsors/justme-1968

dantist

Die Version ist v5.14.2. Aber auch wenn es in der Doku nicht mehr aufgeführt wird, sollte es doch laufen, wenn libswitch-perl installiert ist?

maxritti

Also ich habe nun mal in meiner 99_mUtils.pm folgendes eingetragen:

use Switch;
sub SchalterSchlafzimmer {
  my $statusLichtSchlafzimmer = ReadingsVal("test","state","");
  Log (3, "state: $statusLichtSchlafzimmer");
  switch ($statusLichtSchlafzimmer) {
    case 0 { Log(3, "set Pushbullet message aus"); }
    else { Log(3, "set Pushbullet message an"); }
  }
}


test ist ein Dummy, der den Wert a hat.
Nach Aufruf der Funktion sehe ich im Log dies:

2015.07.23 17:03:35.271 3: state: a
2015.07.23 17:03:35.271 3: set Pushbullet message an


Wenn ich den Dummy mit einem set test 0 auf 0 setze und die Funktion aufrufe, kommt das im Log:

2015.07.23 17:06:03.126 3: state: 0
2015.07.23 17:06:03.126 3: set Pushbullet message aus


Also eigentlich alles wie erwartet. Ohne jedes WARNING und ohne Fehler.

So recht weiss ich jetzt nicht, was ich Dir noch sagen soll.  ;)

dantist

#8
Trotzdem Danke fürs Nachschauen. Dann ist wohl mit meiner Installation etwas im Argen, obwohl alle Module aktuell und unverändert sind.

Ist das "use Switch" eigentlich nötig? Ich habe es mal in die 99_Utils eingetragen und FHEM neu gestartet, bekomme aber weiterhin die gleichen Fehler.

Und wird evtl. ein Modul Switch.pm benötigt? Ich habe davon in einem anderen Thread gelesen, finde aber sonst keine Infos hierzu.

maxritti

Zitat von: dantist am 23 Juli 2015, 18:57:24
Ist das "use Switch" eigentlich nötig? Ich habe es mal in die 99_Utils eingetragen und FHEM neu gestartet, bekomme aber weiterhin die gleichen Fehler.
Nun ja, wenn Du Deinem Link aus dem ersten Post folgst und bei perldoc schaust, ist in der ersten Zeile des dort gezeigten Codes genau das "use Switch".

Macht wohl Sinn, das mit einzubauen.

dantist

Zitat von: maxritti am 23 Juli 2015, 17:07:32
Also ich habe nun mal in meiner 99_mUtils.pm folgendes eingetragen:

Funktioniert es bei dir auch, wenn du es in der fhem.cfg anlegst?

An der 99_mUtils.pm habe ich mich gestern auch zum ersten Mal versucht, da bekomme ich aber momentan überhaupt keine Ausgabe hin, mit oder ohne Switch. Daher die Frage, ob ein Switch in der normalen Config grundsätzlich möglich ist oder ausgelagert werden muss?

maxritti

a) Habe ich keine fhem.cfg, da ich mit configDB arbeite.
b) Macht es Sinn, solche Funktionen auszulagern, wenn diese länger als 2-3 Zeilen sind. Und das scheint bei Dir ja der Fall zu sein.
c) Testweise habe ich das mal auch nicht in ein notify o.ä. implementiert bekommen.

Aber wie sieht Dein Versuch mit der 99_myUtils.pm (da habe ich wohl ein y vergessen im Dateinamen) aus?

In #2 habe ich ja schon mal nach Code gefragt, der bei Dir nicht funktioniert.
Wenn man den nicht gezeigt bekommt, ist das alles hier nur Kaffeesatzleserei.  >:(

dantist

Ich habe eine Weile rumprobiert und es nun doch noch in der 99_myUtils.pm zum Laufen bekommen. Scheint so, als würde der Switch-Befehl tatsächlich nur dort funktionieren und nicht in der fhem.cfg. So sieht es jetzt aus:

Notify in fhem.cfg
SchalterSchlafzimmer:SchalterSchlafzimmer_Button.* { AktionenSchalterSchlafzimmer_("$EVENT") }

Code in 99_myUtils.pm
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.

package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.

sub AktionenSchalterSchlafzimmer_($) {
  use Switch;
  my ($event) = @_;
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  my $currentTime = sprintf("%02d:%02d", $hour, $min);
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  my $farbtonNormal = ReadingsVal("FarbtonNormal","state","");
  switch($event) {
    case "SchalterSchlafzimmer_Button1 Short" {
      if($currentTime lt "07:00" && $statusLichtSchlafzimmer < 10) { fhem("set HUEDevice8 dim10%"); }
      if($currentTime ge "07:00" && $statusLichtSchlafzimmer < 75) { fhem("set HUEDevice8 dim75%"); }
      if($statusLichtSchlafzimmer == 0) {
        fhem("set HUEDevice8 hue $farbtonNormal : sat 192");
      }
    }
    case "SchalterSchlafzimmer_Button2 Short" {
      fhem("set HUEDevice8 off");
    }
    case "SchalterSchlafzimmer_Button1 Long" {
      if($statusLichtSchlafzimmer <= 90) {
        my $brightnessHigher = $statusLichtSchlafzimmer+10;
        fhem("set HUEDevice8 dim$brightnessHigher%");
      }
    }
    case "SchalterSchlafzimmer_Button2 Long" {
      if($statusLichtSchlafzimmer >= 20) {
        my $brightnessLower = $statusLichtSchlafzimmer-10;
        fhem("set HUEDevice8 dim$brightnessLower%");
      }
    }
  }
}

1;


Ist das von der Denkweise her richtig?

Mir ist aufgefallen, dass mit Auslagerung der Funktion in 99_myUtils.pm die Performance stark einbricht. Wenn man den Taster gedrückt hält, werden in kurzen Abständen Events gefeuert, "SchalterSchlafzimmer_Button1 Short" bzw. "SchalterSchlafzimmer_Button2 Short". Damit hatte ich einen schönen Dimmer-Effekt realisiert. Seit der Auslagerung reagiert es jedoch stark verzögert, d.h. das Dimmen dauert länger, die gefeuerten Events werden noch abgearbeitet, wenn man den Taster bereits wieder losgelassen hat.

Falls das zu OT ist, mache ich einen neuen Thread dazu auf.

Und sorry wegen der fehlenden Codebeispiele. Hatte von der Arbeit aus geschrieben und keinen Zugriff auf den Heimserver.

maxritti

Zitat von: dantist am 28 Juli 2015, 19:42:00
Ich habe eine Weile rumprobiert und es nun doch noch in der 99_myUtils.pm zum Laufen bekommen. Scheint so, als würde der Switch-Befehl tatsächlich nur dort funktionieren und nicht in der fhem.cfg. So sieht es jetzt aus:

Notify in fhem.cfg
SchalterSchlafzimmer:SchalterSchlafzimmer_Button.* { AktionenSchalterSchlafzimmer_("$EVENT") }

Code in 99_myUtils.pm
##############################################
# $Id: myUtilsTemplate.pm 7570 2015-01-14 18:31:44Z rudolfkoenig $
#
# Save this file as 99_myUtils.pm, and create your own functions in the new
# file. They are then available in every Perl expression.

package main;

use strict;
use warnings;
use POSIX;

sub
myUtils_Initialize($$)
{
  my ($hash) = @_;
}

# Enter you functions below _this_ line.

sub AktionenSchalterSchlafzimmer_($) {
  use Switch;
  my ($event) = @_;
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
  my $currentTime = sprintf("%02d:%02d", $hour, $min);
  my $statusLichtSchlafzimmer = ReadingsVal("HUEDevice8","pct","");
  my $farbtonNormal = ReadingsVal("FarbtonNormal","state","");
  switch($event) {
    case "SchalterSchlafzimmer_Button1 Short" {
      if($currentTime lt "07:00" && $statusLichtSchlafzimmer < 10) { fhem("set HUEDevice8 dim10%"); }
      if($currentTime ge "07:00" && $statusLichtSchlafzimmer < 75) { fhem("set HUEDevice8 dim75%"); }
      if($statusLichtSchlafzimmer == 0) {
        fhem("set HUEDevice8 hue $farbtonNormal : sat 192");
      }
    }
    case "SchalterSchlafzimmer_Button2 Short" {
      fhem("set HUEDevice8 off");
    }
    case "SchalterSchlafzimmer_Button1 Long" {
      if($statusLichtSchlafzimmer <= 90) {
        my $brightnessHigher = $statusLichtSchlafzimmer+10;
        fhem("set HUEDevice8 dim$brightnessHigher%");
      }
    }
    case "SchalterSchlafzimmer_Button2 Long" {
      if($statusLichtSchlafzimmer >= 20) {
        my $brightnessLower = $statusLichtSchlafzimmer-10;
        fhem("set HUEDevice8 dim$brightnessLower%");
      }
    }
  }
}

1;


Ist das von der Denkweise her richtig?

Mir ist aufgefallen, dass mit Auslagerung der Funktion in 99_myUtils.pm die Performance stark einbricht. Wenn man den Taster gedrückt hält, werden in kurzen Abständen Events gefeuert, "SchalterSchlafzimmer_Button1 Short" bzw. "SchalterSchlafzimmer_Button2 Short". Damit hatte ich einen schönen Dimmer-Effekt realisiert. Seit der Auslagerung reagiert es jedoch stark verzögert, d.h. das Dimmen dauert länger, die gefeuerten Events werden noch abgearbeitet, wenn man den Taster bereits wieder losgelassen hat.

Falls das zu OT ist, mache ich einen neuen Thread dazu auf.

Und sorry wegen der fehlenden Codebeispiele. Hatte von der Arbeit aus geschrieben und keinen Zugriff auf den Heimserver.

Sieht für mich  mal korrekt aus. Wobei der Funktionsname mit einem _ am Ende erst mal komisch aussieht. Dürfte aber an der Funktion nichts ändern. Scheint ja nun auch zu funktionieren.

Das es merkbar langsamer ist, kann ich mir nicht wirklich vorstellen. Wüsste aber auch nicht, wie man die Sache angehen würde. Außer ein paar Logeinträge zu generieren und damit die Stelle suchen wo es klemmt.

Vielleicht liest noch jemand mit, der eine andere Idee hat.