Reading auftrennen und verarbeiten

Begonnen von jfi1310, 19 Juli 2019, 13:49:05

Vorheriges Thema - Nächstes Thema

Byte09

#15
nachtrag :

habe gerade mal im modul geschaut . das 'ursprungs'reading ( dessen timestamp du auch im userreading direkt nutzen kannst ) ist 'mower_nextStart' nicht 'mower_NextStart'.

Zitat von: 74_HusqvarnaAutomower.pmreadingsBulkUpdate($hash, "mower_nextStart", $nextStartTimestamp ); 

somit wird immer auf einen ersatzwert zurückgegriffen , da es das reading 'mower_NextStart' nicht gibt und schon geht es daneben !

gruss Byte09

jfi1310

Vorab erstmal: Vielen Dank für eure Hilfe bis hierher! Ich komme der Sache näher, aber konnte das Problem leider nicht lösen. Aber ich komme immer mehr dahinter und kann meine Schwierigkeiten benennen:

1. BetaUser hatte es schon angedeutet: Dass ich den Timestamp nutze ist nicht richtig, weil dieser nur angibt, wann die Startzeit das letzte Mal aktualisiert wurde. Daher muss ich also ReadingsVal benutzen.

2. Wenn ich ReadingsVal nutzen möchte, habe ich allerdings das Problem, dass die Zeitangabe nicht im richtigen Format vorliegt. Ich habe bspw.: "17:16". Ich bräuchte aber eine komplette Angabe mit Datum und Sekunden. Wie kann ich das Reading entsprechend ergänzen?

Beta-User

Na ja, entweder du nimmst diese Angaben aus localtime (wie in den Beispielen aus dem Wiki), oder du schaust einfach, dass die die beiden Angaben in eine Sekundenangabe umrechnest (split und HOURSECONDS etc.), davon die passende Anzahl von Sekunden abziehst und das ganze wieder passend formatierst; für ein at benötigst du z.B. keine Datumsangaben...

Zum "Rückwärtsformatieren" von Sekunden auf Stunden usw: Ggf. den Modulo-Befehl verwenden, habe grad leider nur einen etwas längeren, verschachtelten Code als Beispiel der Sekundenangaben dann ggf. sogar in Jahre umrechnet usw...:attr DEVICE userReadings formatedUptime:uptime.* {my $m = ReadingsVal($name,"uptime",0)/60;; return sprintf "0 000 00:%02d", $m if $m < 60;; my $h = $m / 60;; $m %= 60;; return sprintf "0 000 %02d:%02d", $h, $m if $h < 24;; my $d = $h / 24;; $h %= 24;; return sprintf "0 %03d %02d:%02d", $d, $h, $m if $d <365;; my $y = $d / 365;; $d %= 365;; return sprintf "%d %03d %02d:%02d", $y, $d, $h, $m}
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

Byte09

Zitat von: Beta-User am 22 Juli 2019, 17:34:59
Na ja, entweder du nimmst diese Angaben aus localtime (wie in den Beispielen aus dem Wiki), oder du schaust einfach, dass die die beiden Angaben in eine Sekundenangabe umrechnest (split und HOURSECONDS etc.), davon die passende Anzahl von Sekunden abziehst und das ganze wieder passend formatierst; für ein at benötigst du z.B. keine Datumsangaben...

Zum "Rückwärtsformatieren" von Sekunden auf Stunden usw: Ggf. den Modulo-Befehl verwenden, habe grad leider nur einen etwas längeren, verschachtelten Code als Beispiel der Sekundenangaben dann ggf. sogar in Jahre umrechnet usw...:attr DEVICE userReadings formatedUptime:uptime.* {my $m = ReadingsVal($name,"uptime",0)/60;; return sprintf "0 000 00:%02d", $m if $m < 60;; my $h = $m / 60;; $m %= 60;; return sprintf "0 000 %02d:%02d", $h, $m if $h < 24;; my $d = $h / 24;; $h %= 24;; return sprintf "0 %03d %02d:%02d", $d, $h, $m if $d <365;; my $y = $d / 365;; $d %= 365;; return sprintf "%d %03d %02d:%02d", $y, $d, $h, $m}


warum diesen aufwand ? da er ja eh nur die reine uhrzeit im reading hat, kann es sich ja immer nur um den aktuellen tag handeln. da wäre es mA einfacher , den timestamp zu splitten . datum davon genutzt und inhalt des "readings".":00"  angehangen , oder noch einfacher es mit den fheminternen variablen $year, $month und $day zusammenzubauen .


gruss Byte09

jfi1310

#19
Zitat von: Byte09 am 22 Juli 2019, 18:13:35
warum diesen aufwand ? da er ja eh nur die reine uhrzeit im reading hat, kann es sich ja immer nur um den aktuellen tag handeln. da wäre es mA einfacher , den timestamp zu splitten . datum davon genutzt und inhalt des "readings".":00"  angehangen , oder noch einfacher es mit den fheminternen variablen $year, $month und $day zusammenzubauen .


gruss Byte09

Nein, es handelt sich nicht zwingend immer um den aktuellen Tag. Der Tag steht in dem Reading "mower_nextStart", das ich aufgetrennt habe. Den Tag schreibe ich dann in ein UserReading "next_start_day".

EDIT:

Ich bin jetzt schon deutlich weiter. Indem ich die Uhrzeit nochmal in Stunden und Minuten splitte, kann ich die Sekunden berechnen. Davon kann ich dann 300sec abziehen. Beim Umrechnen in Stunden und Minuten geht aber irgendwas schief. Die 35700 sec werden umgerechnet in 10:55 Uhr - eigentlich müsste es 09:55 Uhr sein. Kann da irgendwas mit der Zeitzone schieflaufen?

next_start_time_hours { (split ':',ReadingsVal("myMower","next_start_time",0))[0]},
next_start_time_min { (split ':',ReadingsVal("myMower","next_start_time",0))[1]},
next_start_time_abs {ReadingsVal("myMower","next_start_time_hours",0) * HOURSECONDS + ReadingsVal("myMower","next_start_time_min",0) * MINUTESECONDS},
next_open_time_abs {ReadingsVal("myMower","next_start_time_abs",0)-300},
next_open_time_HM {POSIX::strftime("%H:%M:%S",localtime(ReadingsVal("myMower","next_open_time_abs","0")))}


Sowohl FHEM ({localtime()} als auch der Raspberry (date) geben aber die richtige Uhrzeit an. Woran kann es also liegen?

Byte09

#20

ich hab total den faden verloren , diese ganze rechnerei ist mit sicherheit nicht wirklich nötig.

gib uns doch bitte mal ein list vom ursprungsdevice ... myMower ... denke ich . dann sieht man, was du wirklich hast und den kürzesten weg zum ziel.

gruss Byte09

jfi1310

#21
Internals:
   FUUID      #####
   NAME       myMower
   NOTIFYDEV  global,myMower
   NR         16
   NTFY_ORDER 50-myMower
   STATE      connected
   TYPE       HusqvarnaAutomower
   HusqvarnaAutomower:
     CONNECTED  connected
     batteryPercent 0
     expires    1564668969
     interval   60
     language   EN
     mower      0
     mower_activity PARKED_IN_CS
     mower_battery 94
     mower_commandStatus OK
     mower_cuttingMode MAIN_AREA
     mower_id   164303498-163200209
     mower_lastLatitude #####
     mower_lastLongitude #####
     mower_mode AUTO
     mower_model E
     mower_name Rudi
     mower_nextStart 1563868800
     mower_nextStartSource WEEK_TIMER
     mower_restrictedReason WEEK_SCHEDULE
     mower_state RESTRICTED
     password   #####
     provider   husqvarna
     token      #####
     updateStartTime 1563814594
     user_id    694fda86-8f3e-4fca-84d1-949668079a92
     username   #####
     version    0.5.1
   OLDREADINGS:
   READINGS:
     2019-07-22 18:56:34   batteryPercent  94
     2019-07-22 16:16:10   expires         2019-08-01 16:16:09
     2019-07-22 18:56:34   mower_activity  PARKED_IN_CS
     2019-07-22 18:56:34   mower_battery   94%
     2019-07-22 18:40:34   mower_commandStatus OK
     2019-07-22 18:56:34   mower_cuttingMode MAIN_AREA
     2019-07-22 16:16:10   mower_id        #####
     2019-07-22 18:56:34   mower_lastLatitude #####
     2019-07-22 18:56:34   mower_lastLongitude #####
     2019-07-22 18:56:34   mower_mode      AUTO
     2019-07-22 16:16:10   mower_name      Rudi
     2019-07-22 18:56:34   mower_nextStart Tomorrow at 10:00
     2019-07-22 18:56:34   mower_nextStartSource WEEK_TIMER
     2019-07-22 18:56:34   mower_restrictedReason WEEK_SCHEDULE
     2019-07-22 18:56:34   mower_state     RESTRICTED
     2019-07-22 18:56:34   next_open_time_HM 10:55:00
     2019-07-22 18:56:34   next_open_time_abs 35700
     2019-07-22 18:56:34   next_opening    18:56
     2019-07-22 18:56:34   next_start_day  Tomorrow
     2019-07-22 18:56:34   next_start_time 10:00
     2019-07-22 18:56:34   next_start_time_abs 36000
     2019-07-22 18:56:34   next_start_time_hours 10
     2019-07-22 18:56:34   next_start_time_min 00
     2019-07-22 16:16:10   provider        husqvarna
     2019-07-22 16:16:10   state           connected
     2019-07-22 16:16:10   token           #####
     2019-07-22 16:16:10   user_id         #####
   updateDispatch:
Attributes:
   group      Husqvarna
   icon       scene_robo_lawnmower
   interval   60
   language   EN
   password   #####
   room       Garten
   userReadings next_start_time { (split ' ',ReadingsVal("myMower","mower_nextStart",0))[2]},
next_start_day { (split ' ',ReadingsVal("myMower","mower_nextStart",0))[0]},
next_opening {POSIX::strftime("%H:%M",localtime(time_str2num(ReadingsTimestamp("myMower","next_start_time",0))))},
next_start_time_hours { (split ':',ReadingsVal("myMower","next_start_time",0))[0]},
next_start_time_min { (split ':',ReadingsVal("myMower","next_start_time",0))[1]},
next_start_time_abs {ReadingsVal("myMower","next_start_time_hours",0) * HOURSECONDS + ReadingsVal("myMower","next_start_time_min",0) * MINUTESECONDS},
next_open_time_abs {ReadingsVal("myMower","next_start_time_abs",0)-300},
next_open_time_HM {POSIX::strftime("%H:%M:%S",localtime(ReadingsVal("myMower","next_open_time_abs","0")))}
   username   #####


Ein paar Daten habe ich rausgenommen (#####).

Anscheinend wird das Reading "mower_nextStart" ja von einer Sekundenangabe in "Tomorrow at 10:00" umgerechnet. Wie komme ich an die ursprüngliche Sekundenangabe?

Byte09

#22
das ist doch schonmal ein guter anfang. auf 'mower_nextStart 1563868800' kannst du zuzgreifen und diese daten direkt nehmen

my $daten = $hash->{mower_nextStart}


dann sparst du dir die ganze rechnerei

gruss Byte09

edit: als userreading
nextstart {my $test=$hash->{mower_nextStart}; return $test}

Byte09

#23
mid den folgenden userreadings solltest du alle daten bekommen , die du brauchst.

das letzte ist wohl das wirklich benötigte ( startzeit -5 min ) . dieses kann ja ggf. noch wie benötigt formatiert werden.

nextstart {my $test=$hash->{mower_nextStart}; return $test},
nextstart1 {localtime($hash->{mower_nextStart})},
nextstart2 {POSIX::strftime("%H:%M:%S",localtime($hash->{mower_nextStart}-300))}


gruss Byte09

Beta-User

...noch ein paar Anmerkungen:
- Das mit den userreadings ohne engeren Trigger bleibt suboptimal (es wird ständig/mehrfach unnötigerweise gerechnet);
- Auf Internals sollte man (mind. als User) nicht über den $hash zugreifen, sondern stattdessen die "offizielle" Funktion (InternalVal()) nutzen.
- im Prinzip brauchst du keine Readings, sondern einen passenden Timer nebst "Sesam-öffne-dich"-Anweisung.

Warum gehst du nicht so vor: ein notify auf irgendein Reading, das "sowieso" exisitiert und regelmäßig aktualisiert wird. In dem notify-code schaust du dann, ob die nächsten 24h noch ein Start ansteht, wenn ja, generierst du ein at (via defmod), das eben ausreichend vorher die Klappe öffnet. Done...
Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

jfi1310

#25
So langsam verzweifle ich... und ihr wahrscheinlich auch  :o

Den Code von Byte09 habe ich ausprobiert (in die UserReadings kopiert). Allerdings wird mir das Reading nextstart nicht angezeigt. nextstart1 und nextstart2 zeigen somit falsche Werte an (nextstart1 "Thu Jan 1 01:00:00 1970"; nextstart2 "00:55:00").
Wenn ich den reinen Perl-Code von nextstart in die Befehlszeile kopiere, bekomme ich die folgende Fehlermeldung:
Global symbol "$hash" requires explicit package name (did you forget to declare "my $hash"?) at (eval 340) line 1.
Missing right curly or square bracket at (eval 340) line 1, at end of line
syntax error at (eval 340) line 1, at EOF

Unknown command return, try help.


Außerdem habe ich versucht, mit InternalVal an den Wert zu kommen, aber auch das funktioniert nicht. Diesen Code habe ich probiert:
{InternalVal("myMower","mower_nextStart","0")}
Der Befehl gibt mir aber immer nur den Default-Wert zurück...

Woran könnte das liegen?

EDIT: Könnte es sein, dass es (bei InternalVal) damit zusammenhängt, dass "mower_nextStart" in der Untergruppe "HusqvarnaAutomower" gelistet ist? Wenn ich nämlich beispielsweise auf "NAME" oder "TYPE" zugreifen will, klappt es.

Byte09

Ich glaube das internal liegt eine Ebene tiefer.


versuch mal testweise

 
nextstart2 {POSIX::strftime("%H:%M:%S",localtime($hash->{HusqvarnaAutomower} {mower_nextStart}-300))}



gruss Byte09


Gesendet von meinem ELE-L29 mit Tapatalk


jfi1310

Zitat von: Byte09 am 23 Juli 2019, 09:57:03
Ich glaube das internal liegt eine Ebene tiefer.


versuch mal testweise

 
nextstart2 {POSIX::strftime("%H:%M:%S",localtime($hash->{HusqvarnaAutomower} {mower_nextStart}-300))}



gruss Byte09


Gesendet von meinem ELE-L29 mit Tapatalk



Das klappt!! Vielen Dank für die Hilfe!

Beta-User

Argh, das steht in einer Unterstruktur "HusqvarnaAutomower", wie Byte09 schon angemerkt hat.
Da kannst du zwar mit der von Byte09 vorgeschlagenene Methode drauf zugreifen (indem du den "Zwischenschritt" auch noch einfügst), aber sauber ist das nicht (es kann zu verwaisten Einträgen führen, wenn die Oberstruktur vorher nicht existent war...).

M.E. dann lieber ein notify auf mower_nextStart hören lassen, das nur anspringt, wenn da "Today" steht (oder was auch immer "heute" signalisiert). Dann den Startzeitpunkt greifen (müßte $EVTPART2 sein), umrechnen in Sekunden, "Vorwarnzeit" abziehen, at defmodden, done.

Server: HP-elitedesk@Debian 12, aktuelles FHEM@ConfigDB | CUL_HM (VCCU) | MQTT2: MiLight@ESP-GW, BT@OpenMQTTGw | MySensors: seriell, v.a. 2.3.1@RS485 | ZWave | ZigBee@deCONZ | SIGNALduino | MapleCUN | RHASSPY
svn: u.a MySensors, Weekday-&RandomTimer, Twilight,  div. attrTemplate-files

DeeSPe

#29
Habe mich mal ran gesetzt und ein notify für Dich geschrieben und dokumentiert.
Damit sollte es klappen:
defmod n_myMower notify myMower:mower_nextStart:.* {\
  if ($EVTPART1 eq "Today")\
  {\
    # Zeit aus Reading holen\
    my $time = $EVTPART3;;\
    # Zeit in Stunden und Minuten aufteilen\
    my ($h,$m) = split ":",$time;;\
    # Gesamt-Sekunden aus Stunden und Minuten berechnen\
    my $s = $h*3600 + $m*60;;\
    # Vorlaufzeit abziehen (hier 2,5 min.)\
    $s = $s-150;;\
    # Stunden neu berechnen\
    $h = int($s / 3600);;\
    # Minuten neu berechnen\
    $m = int(($s-$h*3600)/60);;\
    # Sekunden neu berechnen\
    $s = ($s % 60);;\
    # formatieren der Uhrzeit\
    my $open = sprintf ("%02d:%02d:%02d",$h,$m,$s);;\
    # at definieren zum Öffnen der Garage\
    fhem "defmod at_myMower_open_garage at $open set myGarage open";;\
  }\
}


Du musst eigentlich nur noch den "Öffnen-Befehl" in der letzten Zeile für Deine Garage anpassen.

Gruß
Dan

EDIT: Habe noch die Behandlung von negativen Minuten (Tageswechsel) hinzugefügt. Das war Quatsch! Da auf "Today" geprüft wird, kann ein Tageswechsel nicht vorkommen.
MAINTAINER: 22_HOMEMODE, 98_Hyperion, 98_FileLogConvert, 98_serviced

Als kleine Unterstützung für meine Programmierungen könnt ihr mir gerne einen Kaffee spendieren: https://buymeacoff.ee/DeeSPe