[gelöst] Wie die Tage jetzt ohne Komma ?

Begonnen von TomLee, 24 August 2019, 15:31:52

Vorheriges Thema - Nächstes Thema

Otto123

Ich habe mir das alles nochmal in Ruhe angeschaut und dabei folgendes ermittelt/getestet:
Wesentlich finde ich die Aussage in der Doku:
ZitatEvents
Wenn der Kalendar neu geladen oder aktualisiert oder eine Alarm-, Start- oder Endzeit erreicht wurde, wird ein FHEM-Event erzeugt:
triggered
Man kann sich darauf verlassen, dass alle Readings des Kalenders in einem konsistenten und aktuellen Zustand befinden, wenn dieses Event empfangen wird.
Das Attribute update hatte ich falsch verstanden, es funktioniert wörtlich wie in der Doku, meint aber Änderungen im Kalender - der Kalender wird quasi nicht mehr eingelesen.
ZitatWird dieses Attribut auf none gesetzt ist, wird der Kalender überhaupt nicht aktualisiert.
Ein set ... update im eingestellten Intervall ist davon nicht betroffen. d.h. steht das Intervall auf 3600 wird weiterhin stündlich getriggert.
Da ich im Abfallkalender lediglich eine Darstellung haben will, werte ich keine Terminevents aus, sondern lese nur Termine aus. Ich will am nachmittag 15:00 Uhr und am Morgen 6:00 einen aktuellen Stand wegen "heute/morgen" haben, der Start des Intervalls ist ja zufällig. Kann man jetzt überlegen und einfach das Intervall auf 4 Stunden setzen, dann passt es immer. Oder man setzt einmal am Tag und synchronisiert mit einem "manuellem" set update (ein at jeden Tag 5:00 Uhr). Mit Abfrage damit es nicht doppelt passiert?
Für die Anzeige habe ich zwei userReadings gemacht:
attr TestKalender userReadings Tonne:triggered {fhem('get '.$name.' events format:custom="$S" limit:from=0,count=1',1)},\
nextWasteDays:triggered {my $day=(time_str2num(fhem('get '.$name.' events timeFormat:"%F" format:custom="$T1" limit:from=0,count=1',1)) - time_str2num(strftime '%F',localtime))/86400;;\
$day>1?$day:$day?"morgen":"heute"}
mit dieser Abfrage ist aus jetzt egal ob der Termin ein Tagestermin oder ein Stundentermin mitten am Tag ist. Es wird zuverlässig der Abstand in Kalendertagen ermittelt. 1 und 0 werden durch morgen und heute ersetzt.

Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

#106
ZitatIch habe mir das alles nochmal in Ruhe angeschaut

Ich noch nicht, ich beschäftige mich damit, Lust aber gleich wieder verloren, weil die Aussage
ZitatDoch es klappt, weiß der Teufel was schon wieder schiefging ich hatte extra FHEMWEB zweimal aktualisiert.
schon wieder Stuss war.
Zitat
Kann man jetzt überlegen und einfach das Intervall auf 4 Stunden setzen,
Ja, vermute das wäre dann die Lösung (bloß keine zusätzliche Definition  ;D)

ZitatIch will am nachmittag 15:00 Uhr und am Morgen 6:00 einen aktuellen Stand wegen "heute/morgen" haben
Wir verstehen uns schon  ;), muss mich aber erst wieder "packen", ich hab eh keine Ruhe bevor ichs nicht irgendwann begriffen habe, das "packen" bleibt aber gerade aus, auch wenn die Lösung wsl. schon präsentiert hast.


Otto123

#107
Zitat von: TomLee am 16 April 2021, 18:16:57
(bloß keine zusätzliche Definition  ;D)
Ich weiß nicht ob man das darf? :) noch ein userReadings ;)
sync:triggered {my $t='05:00:00';if (ReadingsVal($name,'nextUpdate','') !~ $t) {fhem("defmod a_$name at $t set $name update");'define'} else {'done'}}
Die Idee dahinter: Zu einem beliebigen Zeitpunkt wird der Kalender definiert und ein initiales update gemacht (neustart fhem) dadurch wird ein einmaliges at zum festgelegten Zeitpunkt ($t='05:00:00') definiert und dadurch ein update zu dieser Zeit ausgeführt. Ab da triggert der Kalender selbständig zu diesem Zeitpunkt einmal am Tag (86400).
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

Immer noch nicht wirklich mit beschäftigt  8), mir ist aber nebenbei aufgefallen dass das Array gar nicht nötig ist in den pc_...-Funktionen aus #91.

Was ich gerne dazu wüsste wie man den Vergleich eq undef richtig macht ?

Sowas klappt bspw. problemlos, hab ich geprüft:

{return fhem(q(get cal_example events format:custom="$S" limit:from=1,count=1)) eq undef ? 'ja' : 'nein'}

Bin mir aber wie gesagt unsicher ob der Vergleich mit dem Operator eq korrekt umgesetzt wäre ?

Otto123

Naja was auch cool ist, dafür den // Operator zu verwenden:
{my $zeit=ReadingsVal('global','willi',undef) // 0}

{fhem(q(get cal_example events format:custom="$S" limit:from=1,count=1)) // 'ja' }
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

#110
Klappt aber nicht (Kommandozeile);
{my $NAME = 'cal_example';;
my $index = '1';;
my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from='.$index.',count='.$index,1);;
my $ii = sprintf("t_%03.0f", $index);;
if ($t // undef) {fhem("deletereading $NAME ".$ii."_summary");;
return;;}
return $t;;}


Meine Variante mit eq schon:

{my $NAME = 'cal_example';;
my $index = '1';;
my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from='.$index.',count='.$index,1);;
my $ii = sprintf("t_%03.0f", $index);;
if ($t eq undef) {fhem("deletereading $NAME ".$ii."_summary");;
return;;}
return $t;;}


edit: Ok, da war ich zu schnell und habs nicht richtig nachvollzogen das natürkich Quatsch $t // undef und du hast mich nicht verstanden

Otto123

#111
Mir war nicht klar ob Dir ja oder nein wichtig war  ;D ;D ;D
Für ja ist meine Lösung gut, für nein nicht ;)
Aber ich denke sowas geht ?
{my $NAME = 'cal_example';;
my $index = '1';;
my $ii = sprintf("t_%03.0f", $index);;
my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from='.$index.',count='.$index,1) // fhem("deletereading $NAME ".$ii."_summary");;
return $t}

Zumindest funktioniert das:
{my $zeit=ReadingsVal('global','willi',0) // fhem("list global state")}
{my $zeit=ReadingsVal('global','willi',undef) // fhem("list global state")}


Logical Defined-Or hier suchen https://perldoc.perl.org/perlop
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

Mein Gedanke war ich kann mir in diesem Code (der macht was er soll) das Array sparen:

t_001_summary:triggered {pc_ce2r($NAME,'0')},
t_002_summary:triggered {pc_ce2r($NAME,'1')},
t_003_summary:triggered {pc_ce2r($NAME,'2')},
t_004_summary:triggered {pc_ce2r($NAME,'3')},
t_005_summary:triggered {pc_ce2r($NAME,'4')}


sub pc_ce2r {
    my $NAME = shift;
    my $index = shift;
    my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=5',1);
    my @a= split("\n",$t);
    my $ii = sprintf("t_%03.0f", $index + 1);
    if (!defined $a[$index]) {
       fhem("deletereading $NAME ".$ii."_summary");
       return;
    }
   return $a[$index];
}


Ergebnis ist bei einem vorhandenen Termin ein Reading:
setstate cal_example 2021-04-18 11:55:24 t_001_summary Jalousie


Dein Beispiel mit // mal aussen vor, warum werden mit

t_001_summary:triggered {pc_ce2r($NAME,'1')},
t_002_summary:triggered {pc_ce2r($NAME,'2')},
t_003_summary:triggered {pc_ce2r($NAME,'3')},
t_004_summary:triggered {pc_ce2r($NAME,'4')},
t_005_summary:triggered {pc_ce2r($NAME,'5')}


sub pc_ce2r {
my $NAME = shift;
my $index = shift;
my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from='.$index.',count='.$index,1);
my $ii = sprintf("t_%03.0f", $index);
if ($t eq undef) {fhem("deletereading $NAME ".$ii."_summary");
return;}
return $t;}


5 Readings mit dem einen Termin erstellt ?

setstate cal_example 2021-04-18 11:58:43 t_001_summary Jalousie
setstate cal_example 2021-04-18 11:58:43 t_002_summary Jalousie
setstate cal_example 2021-04-18 11:58:43 t_003_summary Jalousie
setstate cal_example 2021-04-18 11:58:43 t_004_summary Jalousie
setstate cal_example 2021-04-18 11:58:43 t_005_summary Jalousie


Das return; in dem if Zweig
if ($t eq undef) {fhem("deletereading $NAME ".$ii."_summary");
return;}

sollte doch ? verhindern das nichts gemacht wird wenn nicht vorhanden und return $t; nicht mehr ausgeführt wird !?

Es kann nicht daran liegen das $index nicht korrekt übergeben wird, hier mein ich:
my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from='.$index.',count='.$index,1);
weil wenn ich den Termin lösche (kein Termin mehr vorhanden) dann werden die fünf Readings wie gewollt gelöscht.


TomLee

Denkfehler, war der Meinung mit

format:custom="$S" limit:from=1,count=1
format:custom="$S" limit:from=2,count=2
format:custom="$S" limit:from=3,count=3
format:custom="$S" limit:from=4,count=4
...


bekomme ich den 1. den 2. den 3. usw. Termin zurück, da hab ich mich nicht richtig mit beschäftigt.

Und zu dem Vergleich ($var eq undef) wie man den richtig macht mein ich jetzt festgestellt zu haben das man das genauso macht wie in der Funktion mit dem Array nämlich !defined ($t).

Otto123

#114
limit:from ist Zeit!
from=[+|-]<timespec> zeigt nur Termine die nach einer Zeitspanne <timespec> ab jetzt enden; Minuszeichen für Termine in der Vergangenheit benutzen; <timespec> wird weiter unten im Attribut-Abschnitt beschrieben.
Aber mit format:custom="$S" limit:from=0,count=5 bekommst Du doch ein Array?
Hast Du doch auch so?
    my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=5',1);
    my @a= split("\n",$t);


Und leere Termine kommen doch dabei nicht zurück? Aber ich verstehe dein gesamt Konstrukt nicht. Ich denke in meinem Kalender genau bis zur nächsten Tonne  ;D
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

#115
ZitatAber ich verstehe dein gesamt Konstrukt nicht. Ich denke in meinem Kalender genau bis zur nächsten Tonne

bei den pc_...-Funktionen (#91) gehts auch nicht um die Tonne sondern um die nächsten fünf Termine eines anderen Kalender.

Otto123

Ok die nächsten 5 sind aber immer 5 es sei den es gibt nur noch weniger.
Das Array hat also 5 Elemente, da kommt ja ein undef gar nicht vor?
Diese Funktion pc_ce2r  - die löscht sich quasi selbst - also das reading welches ermittelt wird?
Warum wird der index Handgesetzt - ein Array kennt doch sein Grenzen.

Steht schon irgendwo was Du erreichen wolltest?
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

#117
ZitatWarum wird der index Handgesetzt - ein Array kennt doch sein Grenzen.

Weil ich dann für fünf Readings keine fünf Funktionen brauche sondern nur eine, es sollen auch nicht irgendwann mal mehr werden sondern immer nur die nächsten fünf.

Probiers halt aus, was ich mir in #91 ausgedacht habe:

defmod cal_example Calendar ical file ./beispiel.ics 86400
attr cal_example defaultFormat "$T1 $S"
attr cal_example hideOlderThan 0
attr cal_example room Kalender
attr cal_example userReadings t_001_summary:lastUpdate:.* {pc_ce2r($NAME,'0')},\
t_002_summary:lastUpdate:.* {pc_ce2r($NAME,'1')},\
t_003_summary:lastUpdate:.* {pc_ce2r($NAME,'2')},\
t_004_summary:lastUpdate:.* {pc_ce2r($NAME,'3')},\
t_005_summary:lastUpdate:.* {pc_ce2r($NAME,'4')},\
t_001_btime:lastUpdate:.* {pc_cb2r($NAME,'1','1')},\
t_002_btime:lastUpdate:.* {pc_cb2r($NAME,'2','3')},\
t_003_btime:lastUpdate:.* {pc_cb2r($NAME,'3','5')},\
t_004_btime:lastUpdate:.* {pc_cb2r($NAME,'4','7')},\
t_005_btime:lastUpdate:.* {pc_cb2r($NAME,'5','9')},\
t_001_bdate:lastUpdate:.* {pc_cd2r($NAME,'1','0')},\
t_002_bdate:lastUpdate:.* {pc_cd2r($NAME,'2','2')},\
t_003_bdate:lastUpdate:.* {pc_cd2r($NAME,'3','4')},\
t_004_bdate:lastUpdate:.* {pc_cd2r($NAME,'4','6')},\
t_005_bdate:lastUpdate:.* {pc_cd2r($NAME,'5','8')},\
t_001_daysleft:lastUpdate:.* {pc_cnd2r($NAME,'0')},\
t_002_daysleft:lastUpdate:.* {pc_cnd2r($NAME,'1')},\
t_003_daysleft:lastUpdate:.* {pc_cnd2r($NAME,'2')},\
t_004_daysleft:lastUpdate:.* {pc_cnd2r($NAME,'3')},\
t_005_daysleft:lastUpdate:.* {pc_cnd2r($NAME,'4')}


package main;

use strict;
use warnings;

sub Calendar_Utils_Initialize {
  my $hash = shift//return;
  return;
}


# Enter you functions below _this_ line.

sub pc_ce2r {
    my $NAME = shift;
    my $index = shift;
    my $t = fhem('get '.$NAME.' events format:custom="$S" limit:from=0,count=5',1);
    my @a= split("\n",$t);
    my $ii = sprintf("t_%03.0f", $index + 1);
    if (!defined $a[$index]) {
       fhem("deletereading $NAME ".$ii."_summary");
       return;
    }
    return $a[$index];
}

sub pc_cb2r {
    my $NAME = shift;
    my $ii = shift;
my $aindex = shift;
$ii = sprintf("t_%03.0f", $ii);
    my $t = fhem('get '.$NAME.' events format:custom="$T1" limit:from=0,count=5',1);
$t =~ s/\n/ /g;
    my @a = split (/ /,$t);
    if (!defined $a[$aindex]) {
       fhem("deletereading $NAME ".$ii."_btime");
       return;
    }
    return $a[$aindex];
}

sub pc_cd2r {
    my $NAME = shift;
    my $ii = shift;
my $aindex = shift;
$ii = sprintf("t_%03.0f", $ii);
    my $t = fhem('get '.$NAME.' events format:custom="$T1" limit:from=0,count=5',1);
$t =~ s/\n/ /g;
    my @a = split (/ /,$t);
    if (!defined $a[$aindex]) {
       fhem("deletereading $NAME ".$ii."_bdate");
       return;
    }
    return $a[$aindex];
}

sub pc_cnd2r {
    my $NAME = shift;
my $index = shift;
my $t = fhem('get '.$NAME.' events timeFormat:"%F 00:00:00" format:custom="$T1" limit:from=0,count=5',1);
    my @a = split (/\n/,$t);
    my $ii = sprintf("t_%03.0f", $index + 1);
    if (!defined $a[$index]) {
       fhem("deletereading $NAME ".$ii."_daysleft");
       return;
    }
return (time_str2num($a[$index]) - time_str2num(strftime('%F 00:00:00',localtime(time))))/86400;
}
1;


ZitatSteht schon irgendwo was Du erreichen wolltest?

Na in #91 und nicht "erreichen wollte" sondern das klappt so wie vorgesehen schon länger.

Ich dachte halt nur zum Zeitpunkt #108 man könnte sich das ersetzen und splitten des beim Array sparen, aber falsch gelegen.

Otto123

#118
Hallo Thomas,

ich weiß Du willst keine extra DEF - aber ist das wirklich entscheidend?
Ich habe mal, das was Dein wildes Konstrukt aus userReadings und Sub macht, als Kommando zusammen gefasst. Erstmal einfach steif dreimal untereinander, damit man die Beziehung noch sieht - da wäre also jede Menge Optimierung möglich. ;)
Macht das, das wo Deine Routine macht?
Ich habe nämlich nicht verstanden, warum Du umständlich löschst, man kann doch einfach überschreiben?
Edit: my raus für Warnung weg und Readings vorher löschen.
{
fhem("deletereading TestKalender t00.*");;
my $t = fhem('get TestKalender events format:custom="$S" limit:from=0,count=5',1);;
my @a= split("\n",$t);;
my $i=0;;
for (@a) {fhem("setreading TestKalender t00".$i."_summary $_");;
          $i++;;}

$t = fhem('get TestKalender events format:custom="$T1" limit:from=0,count=5',1);;
@a= split("\n",$t);;
$i=0;;
for (@a) {fhem("setreading TestKalender t00".$i."_btime ".(split ' ' ,$_)[1]);;
          fhem("setreading TestKalender t00".$i."_bdate ".(split ' ' ,$_)[0]);;
          $i++;;}

$t = fhem('get TestKalender events timeFormat:"%F" format:custom="$T1" limit:from=0,count=5',1);;
@a= split("\n",$t);;
$i=0;;
for (@a) {fhem("setreading TestKalender t00".$i."_daysleft ".(time_str2num($_) - time_str2num(strftime('%F',localtime(time))))/86400);;
          $i++;;}
}


Gruß Otto
Viele Grüße aus Leipzig  ⇉  nächster Stammtisch an der Lindennaundorfer Mühle
RaspberryPi B B+ B2 B3 B3+ ZeroW,HMLAN,HMUART,Homematic,Fritz!Box 7590,WRT3200ACS-OpenWrt,Sonos,VU+,Arduino nano,ESP8266,MQTT,Zigbee,deconz

TomLee

ZitatIch habe nämlich nicht verstanden, warum Du umständlich löschst, man kann doch einfach überschreiben?

Und wenns keinen keinen ersten, zweiten dritten Termin usw.  gibt ? was dann ? dann sollen die Readings erhalten bleiben ? dann gibts ja auch nix zu überschreiben, deswegen löschh ich sie wieder wenn nicht vorhanden.

Hast den Code mal ausprobiert ?

Da wird bisher nichts gelöscht, aber darum gehts mir ja auch gerade, kein Termin -> kein Reading