FHEM Forum

FHEM => Codeschnipsel => Thema gestartet von: Michael am 12 Juli 2015, 19:22:03

Titel: Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 12 Juli 2015, 19:22:03
Moin

Ich komm immer auf Ideen was das KS300 Modul angeht.
Aber so richtig Ahnung von Perl habe ich nicht.  :o

Ich brauche eure Hilfe.
Ich möchte gern die Sommertage eines Jahres ermitteln.

Was will ich : wenn die Temperatur über 25 °C steigt soll ein Reading (summer_days) einmalig am Tag
                     den Readingwert (summer_days) um 1 erhöhen.

Was habe ich : die KS300 im Garten und in Fhem eingebunden.
                        einbinden ins Modul mache ich über userReadings summer_days { sommertage("KS300") }.
                         in der myUtils habe ich folgenden Code, der nicht richtig ist.


use Date::Calc qw(:all);

sub sommertage($)
{
  my ($name)                              = @_;
  my $temp                                = ReadingsVal($name,"temperature",0);
  my ($year,$month,$day, $hour,$min,$sec) = Today_and_Now();
  my $hv                                  = 0;

  # Um 23:59:59 Uhr Hilfsvariable zurücksetzen
  if ($hour == 23 && $min == 59 && $sec == 59) {
     $hv = 0;
  }   

  if ($temp >= 25 && $hv == 0) {
    $hv = 1;
    return ReadingsVal($name,"summer_days",0) + 1;
  }
}


So, nun mein Problem mit der If Struktur.
Wie macht man dass das der Zähler nur einmal erhöht wird ?

PS. Code geändert. 13.07.15
                       
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Paul am 12 Juli 2015, 21:20:42
Ich kenne den KS300 nicht, deshalb die erste Frage speichert er die höchst und niedrigstemperaturen pro Tag? Wenn das der Fall ist würde ich um 23:59 Abfragen ob die Höchsttemperatur >= 25 ist und wenn ja Sommertag um 1 erhöhen.

Sollte das nicht der Fall sein, würde ich einen Dummy einrichten, der bei einer Temperatur >= 25 auf 1 gesetzt wird und diesen wie oben um 23:59 abfragen und wieder auf 0 setzen.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 13 Juli 2015, 17:44:05
Hallo Paul

Vielen Dank für deine Antwort.

Zitat... deshalb die erste Frage speichert er die höchst und niedrigstemperaturen pro Tag? ...
Ja, das macht das Statistik Modul.

ZitatWenn das der Fall ist würde ich um 23:59 Abfragen ob die Höchsttemperatur >= 25 ist und wenn ja Sommertag um 1 erhöhen.
Dann wäre die Summe aber immer um einen Tag versetzt, was nicht so toll wäre.

Wenn ich das mit userReadings mache würde eine Aktualisierung bei veränderter Temperatur durchgeführt.
Nun ist aber das Problem bei >= 25°C würde jedesmal dazugezählt.

Deshalb fehlt mir was in dem oben fehlerhaften Code.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 14 Juli 2015, 13:52:30
du musst vor dem incrementieren den timestamp vom sommertage-reading pruefen. wenn der heute schon erhoeht wurde, dann nicht noch mal.

gruss frank
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 15 Juli 2015, 07:12:16
Moin frank

Zitat
Autor: Michael
« am: 12 Juli 2015, 19:22:03 »
Aber so richtig Ahnung von Perl habe ich nicht.  :o
Auf meine kläglichen Versuche habe ich jetzt kein Zugriff.
Und das große gelächter will ich hier nicht auslösen. ::)

Kannst du mir etwas mehr Veraten?
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 15 Juli 2015, 13:15:42
ZitatUnd das große gelächter will ich hier nicht auslösen. ::)
die am lautesten lachen, haben vielleicht noch weniger wissen.  ;)

ZitatKannst du mir etwas mehr Veraten?
angenommen deine gepostete version stimmt noch. da versuchst du ja schon etwas ähnliches mit $hv. das problem ist halt nur jedesmal, wenn deine funktion aufgerufen wird, setzt du $hv=0. damit zerstörst du den sinn der variablen. speichere den wert in einem reading mit setreading immer wenn du den wert der variablen ändern würdest. und die initialisierung machst du dann mit ReadingsVal. damit überlebt deine hilfsvariable.

my $hv = ReadingsVal("KS300","meineHilfsVariable",0);
fhem("setreading KS300 meineHilfsVariable 0");


dein zurücksetzen wird wahrscheinlich nicht funktionieren, denn dann müsste ja zufällig 23:59:59 sein, wenn du deine funktion aufrufst. dafür könntest du separat ein at definieren, das dir das reading zurücksetzt.

ausserdem würde ich das userreading nur triggern lassen wenn sich die temperatur (reading temperature?) ändert.
ZitatuserReadings summer_days:temperature { sommertage("KS300") }

gruss frank
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 16 Juli 2015, 17:24:02
Moin frank

Erstmal Danke für deine ausführliche Antwort.

Aber irgend was ist bei mir immer noch nicht Richtig.  :-[
Das ist jetzt der aktuelle Code.
sub sommertage($)
{
  my ($name)                              = @_;
  my $temp                                = ReadingsVal($name,"temperature",0);
  my $hv                                  = ReadingsVal($name,"x_sd",0);


  if ($temp >= 25 && $hv == 0) {
    fhem("setreading $name x_sd 1");
    return ReadingsVal($name,"summer_days",0) + 1;
    }
}

Das Hilfsreading wird so wie gewollt gesetzt.
Nur bei dem summer_days Reading passiert nichts
Sehe Anhang.

Zitatausserdem würde ich das userreading nur triggern lassen wenn sich die temperatur (reading temperature?) ändert.
Habe ich so Übernommen, man Lernt nie aus.
Das kannte ich so "summer_days:temperature" auch nicht.  :-[

Zitatdein zurücksetzen wird wahrscheinlich nicht funktionieren, denn ...
Auch das habe ich so übernommen.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 16 Juli 2015, 19:12:32
ZitatNur bei dem summer_days Reading passiert nichts

du hast kein return wert, wenn das if nicht wahr wird. in dem fall muss der gleiche wert zurückgegeben werden.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 17 Juli 2015, 17:43:33
Moin

Ich trau mich schon gar nicht mehr zu Fragen.  :-[

Aber was mache ich falsch, es will einfach nicht.

sub sommertage($)
{
  my ($name)                              = @_;
  my $temp                                = ReadingsVal($name,"temperature",0);
  my $hv                                  = ReadingsVal($name,"x_sd",0);



if($temp ge 25 && $hv eq 0)
{
  fhem("setreading $name x_sd 1");
  return ReadingsVal($name,"summer_days",0) + 1;
}
else
{
  return ReadingsVal($name,"summer_days",0);
}

}


Bitte
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 17 Juli 2015, 18:39:55
es gibt nun immer noch moeglichkeiten die funktion ohne return zu verlassen.  lass das if um das neue return weg.
ausserdem hast du wohl gerade eine klammer zu viel getippt.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: JoWiemann am 17 Juli 2015, 18:51:43
Hallo,

heißt das Device auch wirklich KS300? Wenn Du die Sub mit sommertage("KS300") aufrufst und das Device anders heißt bekommst Du auch kein Ergebnis.

Grüße Jörg
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 17 Juli 2015, 20:28:41
Moin

@frank
Noch habe ich nicht aufgegeben, es läuft aber auch noch nicht.
Versuche mich noch daran.

@Jörg
Zitatheißt das Device auch wirklich KS300? ...
Ja, das Device heißt so.

Ist schon lächerlich was ich Bewergstellige, bzw auch nicht.  :'(
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 17 Juli 2015, 21:13:36
Zitatif($temp ge 25 && $hv eq 0)
zahlenvergleiche besser mit "<,>,==".

zum testen empfiehlt es sich eine (mehrere) debugausgabe(n) einzubauen, die in fhem.log sichtbar werden.
Log(1,"----- mein debugger ----- $name $temp $hv");
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 18 Juli 2015, 15:41:54
Moin

So bin kurz vor der Aufgabe.  :'(

Habe jetzt z Zt diesen Code.

sub sommertage($)
{
  my ($name)                              = @_;
  my $out;
  my $temp                                = ReadingsVal($name,"temperature",0);
  my $sd                                  = ReadingsVal($name,"summer_days",0);
  my $hv                                  = ReadingsVal($name,"x_sd",0);


if($temp >= 25 && $hv == 1)
{
  $out = $sd + 1;
  #fhem("setreading $name x_sd 0");
}
elsif ($hv == 0)
{
  $out = $sd;
}

Log(1,"----- mein debugger ----- $name $temp $hv $sd");
return $out;   

}


So, nun habe ich heraus Gefunden, das wenn ich fhem("setreading $name x_sd 0"); aktiviere
wird die Hilfsvariable gesetzt, aber nicht das Reading summer_days aktualisiert wird.

Und natürlich wenn ich #fhem("setreading $name x_sd 0"); deaktiviere wird
das Reading summer_days mit jeder Device Aktualisierung erhöht.

In der Fhem.log (Log(1,"----- mein debugger ----- $name $temp $hv");) sind keine Einträge.

Und nun wie weiter?
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 18 Juli 2015, 18:08:00
ZitatIn der Fhem.log (Log(1,"----- mein debugger ----- $name $temp $hv");) sind keine Einträge.
das sollte dir zu denken geben.  ;)

kann eigentlich nur bedeuten, dass deine funktion nicht aufgerufen wird. userreading ok?

wenn du in die eingabezeile
{sommertage("KS300")}
eingibst, sollte in fhem.log die debuggingzeile erscheinen.

dann noch elsif in else ändern, sonst gibt es wieder fälle ohne return-wert. damit die logik stimmt im if auf $hv==0 prüfen. die logik für $hv hast du wohl geändert.

edit: ich habe die funktion jetzt bei mir mal eingebaut. da gibt es probleme mit dem setreading. es funktioniert nur, wenn das setzen des readings in ein anderes modul (oder dummy) gemacht wird. in deinem fall die hilfsvariable also nicht nach "KS300" speichern. die tücken mit setreading sind immer wieder beeindruckend.  ;)
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 19 Juli 2015, 10:29:46
Moin frank

Ich weiß auch nicht mehr was mit meinem System (zwischen den Ohren) los ist.  ;)

Zitat
Zitat
In der Fhem.log (Log(1,"----- mein debugger ----- $name $temp $hv");) sind keine Einträge.
das sollte dir zu denken geben.  ;)

kann eigentlich nur bedeuten, dass deine funktion nicht aufgerufen wird. userreading ok?
Sie wird sicher Aufgerufen, denn wenn ich die Variablen hinterm return schreibe bekomme
ich auch den Inhalt ins Device eingetragen.

Zitat
wenn du in die eingabezeile
Code: [Auswählen]
{sommertage("KS300")}
eingibst, sollte in fhem.log die debuggingzeile erscheinen.
Mache ich das bekomme ich den Wert um eins höher wie im Device angezeigt aber in der Fhem.log
erscheint immer noch nichts.

Zitat
dann noch elsif in else ändern, ...
Dann bekomme ich : ERROR
syntax error at /opt/fhem//FHEM/99_myUtils.pm line 239, near "else (" Global symbol "$name" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 244. Global symbol "$out" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 244. Global symbol "$temp" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 244. Global symbol "$sd" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 244. Global symbol "$hv" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 244. Global symbol "$out" requires explicit package name at /opt/fhem//FHEM/99_myUtils.pm line 245. syntax error at /opt/fhem//FHEM/99_myUtils.pm line 247, near "}"

Zitat
... die logik für $hv hast du wohl geändert.
Nur zum testen, denn wenn ich über die Kommandozeile den Wert von $hv mit setreading ändern möchte (zurück setzen) nimmt
das System es manchmal nicht an.

Zitatedit: ich habe die funktion jetzt bei mir mal eingebaut. da gibt es probleme mit dem setreading. es funktioniert nur, wenn das setzen des readings in ein anderes modul (oder dummy) gemacht wird. in deinem fall die hilfsvariable also nicht nach "KS300" speichern. die tücken mit setreading sind immer wieder beeindruckend.  ;)
OK, werden mal ein Hilfs Dummy einsetzen.

Werde mich wieder melden, ob so oder so.  ;)
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: frank am 19 Juli 2015, 10:51:46
bei else darf natuerlich keine bedingung existieren.
verbose von global und ks300 muessen mindestens auf 1 stehen, oder beim log befehl die 1 zu 0 aendern.
Titel: Antw:Perl Hilfe nötig (Sommertage ermitteln)
Beitrag von: Michael am 19 Juli 2015, 11:04:21
Zitatbei else darf natuerlich keine bedingung existieren.
Bin ich do.. .  :'(

Zitatverbose von global und ks300 muessen mindestens auf 1 stehen, oder beim log befehl die 1 zu 0 aendern.
Ja klar!

Melde mich die Tage, denn heute hat's bis jetzt 22 l Regen gemacht.
Aber es sah schon, mit anderer Temperatur (10°C  :o) ganz gut aus.

Dank dir erstmal, schönen Sonntag noch.