Neues Modul: 57_GCALVIEW Google Kalender Viewer (+Abfall Kalender)

Begonnen von mumpitzstuff, 04 Oktober 2017, 00:02:11

Vorheriges Thema - Nächstes Thema

mumpitzstuff

Dieses Modul arbeitet Standalone, also baut nicht auf anderen Modulen auf. Alle Funktionen wurden absolut non blocking implementiert und sollten somit andere Module nicht behindern. Jedes angezeigte Event verfügt über einen anklickbaren Link, der direkt zum Eintrag im Google Kalender führt, so das man den Eintrag direkt editieren kann (funktioniert super in jedem Browser).

Es gibt innerhalb des Moduls 2 Ansichten, welche sich zum einen an 57_CALVIEW und zum anderen an 57_ABFALL anlehnen. Diese Ansicht lässt sich beliebig umschalten oder man erstellt mehrere Devices und konfiguriert die einzelnen Devices entsprechend. Bei mir kann dieses Modul die Module 57_CALENDAR, 57_CALVIEW und 57_ABFALL inzwischen komplett ersetzen.

Um das Modul nutzen zu können, muss gcalcli (open source) installiert sein!

Installation:

1.) Zuerst einmal muss man gcalcli installieren:
sudo apt-get install gcalcli
Eventuell müssen auch die folgenden Pakete installiert werden:
sudo apt-get install git python-pip python-gdata python-dateutil python-gflags python-vobject python-parsedatetime

2.) An dieser Stelle unbedingt prüfen, ob mindestens Version 3.4.0 installiert ist!
gcalcli --version
Wenn das nicht der Fall ist, können folgende Alternativen probiert werden:
pip install gcalcli --upgrade
oder
git clone https://github.com/insanum/gcalcli.git
cd gcalcli<br>
python setup.py install

oder
Hier kann man sich eine deb Datei für sein System runterladen: https://pkgs.org/download/gcalcli und installieren:
sudo dpkg -i <name of file>.deb
Wenn die Installation über pip fehl schlägt, dann muss man eventuell zuvor die über apt-get installierte Version entfernen:
sudo apt-get remove gcalcli

3.) Jetzt das folgende Kommando eingeben:
sudo -u fhem gcalcli --noauth_local_webserver list
Die angezeigte URL muss kopiert und mit einem Browser aufgerufen werden. Dort muss man die Verknüpfung mit dem Google Konto bestätigen und erhält dann ein OAuth Token angezeigt. Das kopiert man wieder und kopiert es in die Konsole des Users fhem und bestätigt die Eingabe. Nun kann gcalcli auf den Google Kalender zugreifen! Um das zu prüfen kann man folgendes eingeben und erhält dann eine Liste der verfügbaren Kalender angezeigt:
sudo -u fhem gcalcli list
Bitte an dieser Stelle prüfen, ob eine Datei namens .gcalcli_oauth im fhem Verzeichnis erstellt wurde (/opt/fhem). Wenn das nicht der Fall ist, sollte versucht werden Punkt 6. mit dieser zusätzlichen Option durchzuführen:
--configFolder /opt/fhem
Für neuere gcalcli Versionen muss --config-folder verwendet werden!

4.) In fhem sollte jetzt das folgende Kommando eine Liste deiner Google Kalender anzeigen:
{qx(gcalcli list);;}
oder
{qx(gcalcli list --configFolder /opt/fhem);;}
Für neuere gcalcli Versionen muss --config-folder verwendet werden!

5.) Jetzt kann das neue Modul 57_GCALVIEW installiert werden. Dazu folgende fhem Kommandos eingeben:
update add http://raw.githubusercontent.com/mumpitzstuff/fhem-GCALVIEW/master/controls_gcalview.txt
update all
shutdown restart

6.) Nun kann das Device in fhem angelegt werden:
define <name> GCALVIEW <timeout>
timeout ist hier ein Timeout in Sekunden für den Backgroundtask. Wenn dieses Timeout überschritten wird, dann wird der Task gekillt.

7.) Wenn es notwendig war die Option --configFolder bzw. --config-folder zu verwenden, dann muss unbedingt das Attribut configFolder im Device gesetzt werden!

Damit ist die Installation abgeschlossen!

Mit den Default Einstellungen sollten alle Termine der nächsten 5 Tage abgerufen werden. Das kann man entweder manuell auslösen oder man wartet das updateIntervall ab, das auf 1 Stunde voreingestellt ist.

Folgende Attribute gibt es aktuell:

updateIntervall: Intervall für das Abholen der Kalenderdaten in Sekunden (default: 3600s)

calendarFilter: Dieses Attribut wird erst verfügbar, wenn man das erste Mal seinen Google Calendar eingelesen hat. Mit diesem Attribut kann man bestimmte Kalender filtern. Wenn das Attribut nicht vorhanden ist oder kein Kalender ausgewählt ist, dann werden alle Kalender angezeigt. Ansonsten werden nur die ausgewählten Kalender angezeigt.

calendarDays: Gibt an von wievielen Tagen die Kalendereinträge angezeigt werden sollen. 30 würde z.B. bedeuten: von heute an 30 Tage in die Zukunft.

calendarIncludeStarted: Wenn das Attribut gesetzt ist, werden für die dort ausgewählten Kalender auch bereits gestartete Termine angezeigt. Wenn hier nichts gesetzt ist, dann werden gestartete Termine nicht angezeigt.

calendarType: Hier kann der Typ des Kalendars eingestellt werden. standard = 57_CALVIEW oder waste = 57_ABFALL

maxEntries: Hiermit kann die Anzahl der Einträge eingeschränkt werden. Die absolute Obergrenze sind jedoch 200 Einträge.

disable: Modul wird auf Eis gelegt und keine Updates werden mehr durchgeführt.

cache: Wenn das Attribut aktiviert ist, dann werden die Zugriffe nicht mehr durch einen Cache abgefedert.

filterSummary: Wenn dieses regex innerhalb des Summary matcht, dann wird das Event komplett ausgeblendet.

filterLocation: Wenn dieses regex innerhalb der Location matcht, dann wird das Event komplett ausgeblendet.

filterDescription: Wenn dieses regex innerhalb der Description matcht, dann wird das Event komplett ausgeblendet.

filterSource: Wenn dieses regex innerhalb von Source matcht, dann wird das Event komplett ausgeblendet.

filterAuthor: Wenn dieses regex innerhalb des Authors matcht, dann wird das Event komplett ausgeblendet.

filterOverall: Wenn dieses regex innerhalb des Summary, Location, Description, Source oder des Authors matcht, dann wird das Event komplett ausgeblendet.

alldayText: Gibt an, was bei einem Ganztagsevent ausgegeben werden soll (default: all-day).

weekdayText: Gibt an wie die Wochentage benannt werden sollen (default: Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday). Hier muss eine Komma separierte Liste von genau 7 Strings angegeben werden.

daysLeftLongText: Gibt an wie die lange Version der noch verbleibenden Tage benannt werden soll. Die Angabe muss eine Komma separierte Liste mit genau 3 Einträgen sein. Im letzten Eintrag sollte % verwendet werden, denn dieses Zeichen wird durch die Anzahl der verbleibenden Tage ersetzt (default: today,tomorrow,in % days).

readingPrefix: Dieses Attribut spielt nur beim Typ waste eine Rolle und gibt an, ob der Kalendername den einzelnen Readings vorangestellt werden soll oder nicht (default: nein).

sourceColor: Hiermit kann für die unterschiedlichen Kalenderquellen Farbwerte als String abgelegt werden. Es muss eine Komma separierte Liste im Stil von <source>:<color>,<source>:<color>,... angegeben werden.

wasteEventSeparator: Wenn der Typ waste eingestellt ist, dann hier hier das Trennzeichen angegeben werden, das verwendet werden soll, um Events die auf den selben Tag fallen, zusammen zu fassen (default: and).

showAge: Wenn das Attribut eingeschaltet ist, dann wird versucht, aus dem bei ageSource angegebenen Feld, eine vierstellige Zahl beginnend mit 19, 20 oder 21 zu extrahieren und das Alter z.B. einer Person zu berechnen (default: 0). Es wird ein separates Reading _age erzeugt.

ageSource: Gibt an, aus welchem Feld versucht wird, das Alter einer Person zu extrahieren (default: description). Es kann description, summary oder location ausgewählt werden.

configFolder: Hiermit kann man ein Verzeichnis für die Authentifizierungsdaten vorgeben, z.B. /opt/fhem.


HISTORY:
08.03.18

  • Attribut emptyReadingText hinzugefügt (damit kann man den Inhalt von leeren Readings festlegen)
  • Attribut invertFilter hinzugefügt (invertiert die Bedeutung der existierenden Filter). Hiermit kann man exakt die Einträge behalten, die dann dem Filtertext entsprechen!
  • Reading _daysnext hinzugefügt (nur waste Kalender)
  • Version erhöht von 1.0.2 nach 1.0.3
24.01.18

  • Attribut wasteEventSeparator fixed
18.01.18

  • Attribut calendarIncludeStarted hinzugefügt
  • Attribut includeStarted entfernt
  • Versionsinformationen hinzugefügt
14.12.17

  • Attribut ageSource hinzugefügt
  • bugfix falls description tabs enthalten sollte
09.12.17:

  • Attribut showAge hinzugefügt
04.12.17:

  • Attribut daysLeftLongText hinzugefügt
18.11.17:

  • Fehler bei der utf8 Behandlung behoben
11.11.17:

  • utf8 behandlung im Modul erweitert
  • bei einigen Attributen wurde die Einstellung 0 oder 1 erweitert, so das man hier umschalten kann, anstatt das Attribut zu löschen
  • probleme mit dem Attribut disable behoben
  • attribute configFolder added
  • readingsGroup template erweitert (Jahr vom Datum wird entfernt, Wochentag wird angezeigt, Farbdefinitionen des Kalenders werden verwendet)
06.11.17:

  • Attribut cache hinzugefügt
  • Logik von includeStarted invertiert
  • Probleme mit deutschen Umlauten behoben

TODO:

- Kalender Einträge erstellen und bearbeiten
- weitere Attribute unterstützen
- verschiedene Spielereien (für Voschläge wäre ich offen)

PS: Hier noch eine schöne readingsGroup die man verwenden könnte. Wenn man das entsprechende sourceColor Attribut im Kalender setzt, dann werden diese Farbwerte auch in der Readingsgroup angezeigt. Weiterhin sind die Einträge anklickbar und man wird direkt zum Eintrag im Google Kalender weiter geleitet z.B. um ihn zu editieren:


defmod rg_KALENDER readingsGroup <Datum>,<Tag>,<Zeit>,<Termin>,<Ort>\
KALENDER_VIEW:t_001_bdate,t_001_weekday,t_001_timeshort,t_001_summary,t_001_location\
KALENDER_VIEW:t_002_bdate,t_002_weekday,t_002_timeshort,t_002_summary,t_002_location\
KALENDER_VIEW:t_003_bdate,t_003_weekday,t_003_timeshort,t_003_summary,t_003_location\
KALENDER_VIEW:t_004_bdate,t_004_weekday,t_004_timeshort,t_004_summary,t_004_location\
KALENDER_VIEW:t_005_bdate,t_005_weekday,t_005_timeshort,t_005_summary,t_005_location\
KALENDER_VIEW:t_006_bdate,t_006_weekday,t_006_timeshort,t_006_summary,t_006_location\
KALENDER_VIEW:t_007_bdate,t_007_weekday,t_007_timeshort,t_007_summary,t_007_location\
KALENDER_VIEW:t_008_bdate,t_008_weekday,t_008_timeshort,t_008_summary,t_008_location\
KALENDER_VIEW:t_009_bdate,t_009_weekday,t_009_timeshort,t_009_summary,t_009_location\
KALENDER_VIEW:t_010_bdate,t_010_weekday,t_010_timeshort,t_010_summary,t_010_location\
KALENDER_VIEW:t_011_bdate,t_011_weekday,t_011_timeshort,t_011_summary,t_011_location\
KALENDER_VIEW:t_012_bdate,t_012_weekday,t_012_timeshort,t_012_summary,t_012_location\
KALENDER_VIEW:t_013_bdate,t_013_weekday,t_013_timeshort,t_013_summary,t_013_location\
KALENDER_VIEW:t_014_bdate,t_014_weekday,t_014_timeshort,t_014_summary,t_014_location\
KALENDER_VIEW:t_015_bdate,t_015_weekday,t_015_timeshort,t_015_summary,t_015_location\
KALENDER_VIEW:t_016_bdate,t_016_weekday,t_016_timeshort,t_016_summary,t_016_location\
KALENDER_VIEW:t_017_bdate,t_017_weekday,t_017_timeshort,t_017_summary,t_017_location\
KALENDER_VIEW:t_018_bdate,t_018_weekday,t_018_timeshort,t_018_summary,t_018_location\
KALENDER_VIEW:t_019_bdate,t_019_weekday,t_019_timeshort,t_019_summary,t_019_location\
KALENDER_VIEW:t_020_bdate,t_020_weekday,t_020_timeshort,t_020_summary,t_020_location
attr rg_KALENDER nameStyle style="font-weight:bold;;text-decoration:underline;;"
attr rg_KALENDER nonames 1
attr rg_KALENDER notime 1
attr rg_KALENDER room KALENDER
attr rg_KALENDER valueFormat {\
  if ($READING =~ /bdate$/)\
  {\
    my $readingStart = $READING;;\
    $readingStart =~ s/bdate$//;;\
    if (0 == ReadingsVal($DEVICE, $readingStart.'daysleft', -1))\
    {\
      "Heute";;\
    }\
    elsif (1 == ReadingsVal($DEVICE, $readingStart.'daysleft', -1))\
    {\
      "Morgen";;\
    }\
    else\
    {\
      # the follwoing line strips the year of the date (remove it if needed)\
      substr($VALUE, 0, 5);;\
    }\
  }\
  elsif ($READING =~ /weekday$/)\
  {\
    my $readingStart = $READING;;\
    $readingStart =~ s/weekday$//;;\
    \
     # the follwoing line strips the weekday down to 3 chars (remove it if needed)\
    substr($VALUE, 0, 3);;\
  }\
  elsif ($READING =~ /summary$/)\
  {\
    my $readingStart = $READING;;\
    $readingStart =~ s/summary$//;;\
    my $link = ReadingsVal($DEVICE, $readingStart.'url', '');;\
    my $age = ReadingsVal($DEVICE, $readingStart.'age', undef);;\
    my $style = 'style="color:'.ReadingsVal($DEVICE, $readingStart."sourcecolor", "white").'"';;\
    if (defined($age))\
    {\
      $link =~ s/\>link\</ $style\>$VALUE \($age\)\</;;\
    }\
    else\
    {\
      $link =~ s/\>link\</ $style\>$VALUE\</;;\
    }\
    $link;;\
  }\
}
attr rg_KALENDER valueStyle {\
  my $readingStart = $READING;;\
  $readingStart =~ s/(t_\d+_).+/$1/;;\
  'style="color:'.ReadingsVal($DEVICE, $readingStart."sourcecolor", "white").'"'\
}


Noch eine Readinsgroup für einen Abfallkalender:
defmod rg_Abfall readingsGroup ABFALL_LEERUNG:Restmuell_weekday,Restmuell_date,Restmuell_text,<%dustbin@red>,<{recyclebinCounter($DEVICE,'Restmuell_')}@state>\
ABFALL_LEERUNG:Rund_weekday,Rund_date,Rund_text,<%dustbin@green>,<{recyclebinCounter($DEVICE,'Rund_')}@state>\
ABFALL_LEERUNG:Flach_weekday,Flach_date,Flach_text,<%dustbin@limegreen>,<{recyclebinCounter($DEVICE,'Flach_')}@state>\
ABFALL_LEERUNG:Biogut_weekday,Biogut_date,Biogut_text,<%dustbin@yellow>,<{recyclebinCounter($DEVICE,'Biogut_')}@state>
attr rg_Abfall nonames 1
attr rg_Abfall room KALENDER
attr rg_Abfall valueFormat {\
  if ($READING =~ /bdate$/)\
  {\
    my $readingStart = $READING;;\
    my $daysLeft;;\
\
    $readingStart =~ s/bdate$//;;\
    $daysLeft = ReadingsVal($DEVICE, $readingStart.'daysleft', -1);;\
    \
    if (0 == $daysLeft)\
    {\
      'Heute';;\
    }\
    elsif (1 == $daysLeft)\
    {\
      'Morgen';;\
    }\
    elsif (2 == $daysLeft)\
    {\
      'Übermorgen';;\
    }\
    else\
    {\
      # the follwoing line strips the year of the date (remove it if needed)\
      substr($VALUE, 0, 5);;\
    }\
  }\
}
attr rg_Abfall valueStyle {\
  my $color;;   \
\
  if ($READING =~ /^(Restmuell_|Rund_|Flach_|Biogut_)/)\
  {\
    my $days = ReadingsVal($DEVICE, $1.'days', 0);;\
\
    $color = (1 == $days ? 'red' : 2 == $days ? 'darkorange' : 'white');;\
  }\
\
  return 'style="color:'.$color.'"';;\
}


Code für die 99_myUtils.pm:
sub recyclebinCounter($$)
{
  my ($device, $reading) = @_;
  my $days = ReadingsVal($device, $reading.'days', 'na');
  my $daysnext = ReadingsVal($device, $reading.'daysnext', 'na');
  my $color_days = ('1' eq $days ? 'red' : '2' eq $days ? 'darkorange' : 'green');
 
  return '<div style="width:16px;height:14px;border-radius:14px;color:white;background-color:'.
         $color_days.
         ';font-size:10px;font-weight:700;text-align:center;position:relative;padding-top:1%;'.
         'left:-29px;top:-4px;">'.$days.'</div>'.
         '<div style="width:16px;height:14px;border-radius:14px;color:white;'.
         'border:1px solid white;'.
         'font-size:10px;font-weight:700;text-align:center;position:relative;padding-top:1%;'.
         'left:-11px;top:-19px;">'.$daysnext.'</div>';
}


Zu guter Letzt noch ein Beispiel für einen Geburtstagskalender:
defmod rg_Geburtstage readingsGroup <Datum>,<Tag>,<verbl. Tage>,<Geburtstag>\
GEBURTSTAG_VIEW:t_001_bdate,t_001_weekday,t_001_daysleft,t_001_summary\
GEBURTSTAG_VIEW:t_002_bdate,t_002_weekday,t_002_daysleft,t_002_summary\
GEBURTSTAG_VIEW:t_003_bdate,t_003_weekday,t_003_daysleft,t_003_summary\
GEBURTSTAG_VIEW:t_004_bdate,t_004_weekday,t_004_daysleft,t_004_summary\
GEBURTSTAG_VIEW:t_005_bdate,t_005_weekday,t_005_daysleft,t_005_summary\
GEBURTSTAG_VIEW:t_006_bdate,t_006_weekday,t_006_daysleft,t_006_summary\
GEBURTSTAG_VIEW:t_007_bdate,t_007_weekday,t_007_daysleft,t_007_summary\
GEBURTSTAG_VIEW:t_008_bdate,t_008_weekday,t_008_daysleft,t_008_summary\
GEBURTSTAG_VIEW:t_009_bdate,t_009_weekday,t_009_daysleft,t_009_summary\
GEBURTSTAG_VIEW:t_010_bdate,t_010_weekday,t_010_daysleft,t_010_summary
attr rg_Geburtstage nameStyle style="font-weight:bold;;text-decoration:underline;;"
attr rg_Geburtstage nonames 1
attr rg_Geburtstage notime 1
attr rg_Geburtstage room KALENDER
attr rg_Geburtstage valueFormat {\
  if ($READING =~ /bdate$/)\
  {\
    my $readingStart = $READING;;\
    $readingStart =~ s/bdate$//;;\
    my $daysLeft = ReadingsVal($DEVICE, $readingStart.'daysleft', -1);;\
\
    if (0 == $daysLeft)\
    {\
      'Heute';;\
    }\
    elsif (1 == $daysLeft)\
    {\
      'Morgen';;\
    }\
  }\
  elsif ($READING =~ /summary$/)\
  {\
    my $readingStart = $READING;;\
    $readingStart =~ s/summary$//;;\
    my $age = ReadingsVal($DEVICE, $readingStart.'age', undef);;\
    if (defined($age))\
    {\
      $VALUE .= ' ('.$age.')';;\
    }\
    $VALUE;;\
  }\
}
attr rg_Geburtstage valueStyle {\
  my $readingStart = $READING;;\
  $readingStart =~ s/_[a-zA-Z]+$//;;\
  my $daysleft = ReadingsVal($DEVICE, $readingStart.'_daysleft', 0);;\
  my $color = ($daysleft <= 3 ? 'red' : $daysleft <= 7 ? 'orange' : $daysleft <= 14 ? 'yellow' : 'white');;\
\
  return 'style="color:'.$color.'"';;\
}


Hierfür benötigt man ein spezielles Kalenderdevice, in dem man entweder nach einem speziellen Kalender filtert oder nach einem Schlüsselwort wie z.B. Geburtstag. Bei mir hat das Kalenderdevice z.B. folgende Attribute:
attr GEBURTSTAG_VIEW alldayText ganztägig
attr GEBURTSTAG_VIEW calendarDays 365
attr GEBURTSTAG_VIEW filterOverall [Gg]eburtstag
attr GEBURTSTAG_VIEW invertFilter 1
attr GEBURTSTAG_VIEW room KALENDER
attr GEBURTSTAG_VIEW showAge 1
attr GEBURTSTAG_VIEW updateInterval 3600
attr GEBURTSTAG_VIEW weekdayText Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag,Sonntag


Ein Abfallkalender als DOIF:

defmod doif_Abfall DOIF ##
attr doif_Abfall room KALENDER
attr doif_Abfall uiTable {\
  package ui_Table;;\
\
  $SHOWNOSTATE=1;;\
\
  sub ic\
  {\
    my ($icon, $days, $days2) = @_;;\
    \
    icon_label2($icon, $days, $days2, 'white', (1 == $days ? 'red' : 2 == $days ? 'darkorange' : 'green'));;\
  }\
  \
  sub icon_label2\
  {\
    my ($icon, $text, $text2, $color, $color_bg, $pos_left, $pos_top) = @_;;\
    my $pad = ((length($text) > 1) ? 2 : 5);;\
    my $pad2 = ((length($text2) > 1) ? 2 : 5);;\
    \
    $color = "" if (!defined ($color));;\
    $color_bg = "" if (!defined ($color_bg));;\
    $pos_left = -5 if (!defined ($pos_left));;\
    $pos_top = -10 if (!defined ($pos_top));;\
   \
    return '<div style="display:inline-table;;">'.::FW_makeImage($icon).\
           '<div style="display:inline;;width:16px;;height:14px;;border-radius:14px;;color:'.$color.';;background-color:'.$color_bg.\
           ';;font-size:10px;;font-weight:700;;text-align:center;;position:relative;;padding-top:1px;;padding-left:'.$pad.'px;;padding-right:'.$pad.'px;;padding-bottom:1px;;'.\
           'left:'.$pos_left.'px;;top:'.$pos_top.'px;;">'.$text.'</div>'.\
           '<div style="display:inline;;width:16px;;height:14px;;border-radius:14px;;color:'.$color.';;border:1px solid white;;'.\
           'font-size:10px;;font-weight:700;;text-align:center;;position:relative;;padding-top:1px;;padding-left:'.$pad2.'px;;padding-right:'.$pad2.'px;;padding-bottom:1px;;'.\
           'left:'.$pos_left.'px;;top:'.$pos_top.'px;;">'.$text2.'</div></div>';;\
  }\
\
  sub convDate\
  {\
    my ($date, $days) = @_;;\
\
    return 'Heute' if (0 == $days);;\
    return 'Morgen' if (1 == $days);;\
    return 'Übermorgen' if (2 == $days);;\
    \
    # the following line strips the year of the date (remove it if needed)\
    #return substr($date, 0, 5);;\
    return $date;;\
  }\
\
  sub textColor\
  {\
    my $days = shift;;\
    \
    return (1 == $days ? 'red' : 2 == $days ? 'darkorange' : 'white');;\
  }\
}\
\
DEF TPL_Abfall (style([ABFALL_LEERUNG:$1_weekday], textColor([ABFALL_LEERUNG:$1_days]))|\
style(convDate([ABFALL_LEERUNG:$1_date], [ABFALL_LEERUNG:$1_days]), textColor([ABFALL_LEERUNG:$1_days]))|\
style([ABFALL_LEERUNG:$1_text], textColor([ABFALL_LEERUNG:$1_days]))|\
ic("dustbin\@$2", [ABFALL_LEERUNG:$1_days], [ABFALL_LEERUNG:$1_daysnext]))\
\
TPL_Abfall (Restmuell,red)\
TPL_Abfall (Rund,green)\
TPL_Abfall (Flach,limegreen)\
TPL_Abfall (Biogut,yellow)\

Mave

Moin mumpitzstuff,

Deine Idee hört sich erstmal nicht schlecht an. Vielen Dank für Dein Engagement.

Für mich als Tablet UI User ist natürlich interessant, ob es auch ein Widget für Tablet UI geben wird, damit die Termine schön angezeigt werden können.

Grüße Mave

Mave

Hast Du das Modul jetzt in den letzten 3 Tagen auf die Beine gestellt?

Du hast am 30.09. erstmals von gcalcli berichtet und heute präsentierst Du ein fertiges Modul?  :o

Respekt.

mumpitzstuff

Ich verwende leider keine alternative Oberfläche, deshalb kann ich dazu wenig beitragen. Ich kann allerdings dabei unterstützen.
Wenn es aber bereits etwas für das originale CALVIEW gibt, dann sollte man die eigentlich auch fast übernehmen können. Alle Readings sind eigentlich gleich benannt in meinem Modul. Im Idealfall kann man mit diesem Modul einfach das alte CALVIEW Device ersetzen und darauf aufbauende Schichten wie. z.B. eine GUI sollten davon gar nichts mitbekommen.

Das Modul zu erstellen war erschreckend einfach, denn der gesamte Unterbau wird von gcalcli übernommen. Ich musste an der Stelle nur noch die Daten in die Readings überführen, was sich auf nur wenige Zeilen Code beschränkt hat. Ich war selbst etwas verblüfft darüber, wie schnell etwas funktionsfähiges entstanden ist.

Ich hätte gern noch 1-2 Screenshots erstellt, damit sich jeder vor der Installation ein Bild davon machen kann, aber das ist bei privaten Kalendern immer so eine Sache...

mumpitzstuff

Auch wenns nur für mich ist, hatte ich einfach Lust das Modul weitestgehend fertig zu stellen... Das Update ist jetzt verfügbar.

Jamo

Hallo Mumpitzstuff,
funktioniert prima. Erste Sahne. Auch mit dem anklickbaren link ist super Praktisch.
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

mumpitzstuff

Das freut mich. Wenn du noch etwas vermisst oder was nicht funktioniert, dann einfach melden.

Jamo

Das attr 'includeStarted' funktioniert nicht wie erwartet.
Ich habe das attr nicht gesetzt, also sollten angefangene Termine nicht mehr angezeigt werden.
Habe gerade einen Eintrag 'Test' für 21:20 gemacht, der wird aber weiterhin um 21:26 nach dem Kalender update angezeigt.
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

mumpitzstuff

#8
Okay schau ich mir an.

Oder Moment. Das ist mir auch schon mal aufgefallen. Das liegt am Cache. Gcalcli legt sich einen Cache an und bedient sich für kurze Zeit daraus, bevor es wieder den Server abfragt. Deshalb hat man dann teilweise kurze Zeit solche Inkonsistenzen. Man kann den Cache aber löschen lassen. Dafür werde ich mal ein set Kommando einfügen. Oder ich frage generell ohne Cache ab, das könnte ich auch machen.
Kannst du mal versuchen einen längeren Termin anzulegen und nach 1h noch mal zu gucken? Ich hab leider keine Ahnung wie lange gcalcli den Cache beibehält.

Jamo

Ich habe es jetzt 2 mal probiert, gestern Abend mit einem 1-stündigem Termin der um 21:20 anfing, und heute einem 8 stündigem Termin ab 10:00.
Beidesmal ist der Termin nach über 2 Stunden immer noch sichtbar, auch wenn ich zwischendurch 'update' ausführe (um damit den stündlichen refresh öfter auszuführenn), das wäre mir eindeutig zu lange, weil im ersten Fall der Termin sogar schon zuende ist.
Vielleicht besser ohne Cache?
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

mumpitzstuff

Ich baue mal ein Attribut ein Cache ein/aus. Mal sehen ob das hilft. Ansonsten funktioniert die Filterung durch gcalcli nicht und ich muss das dann selbst "nachfiltern".

Jamo

Der 8 stündige Termin von heute morgen ab 10:00 ist immer noch im Kalender. Attribut Cache ein/aus hört sich gut an. Danke!
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

Jamo

Übrigens, der 8 stündige Termin von heute morgen mit start 10:00 / ende 18:00 ist immer noch im Kalender :-)
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack

rabehd

Was mache ich falsch?

Zitat2017.11.06 20:55:34 3: GCALVIEW defined with timeout 30
2017.11.06 20:56:29 3: Kalendertest blocking call already running
2017.11.06 20:56:30 3: Kalendertest: something went wrong (invalid gcalcli output) - 2017-11-06, 16:00, 2017-11-06, 16:30, https://www.google.com/calendar/event?eid=dmN

Im Log stehen einmalig die Einträge, aber keine readings.
Auch funktionierende Lösungen kann man hinterfragen.

Jamo

Hallo rabehd, ehrlich gesagt keine Ahnung, ich habe alles nach Anleitung von mumpitzstuff gemacht, und das hat auf Anhieb funktioniert.

Hier mal eine sub, mit der kann man aus dem Kalender-Readings von 'today_00[1-9]_[be]time' sich ein 'at' event generieren. Falls das reading 'today_00[1-9]_summary' mit dem Trigger übereinstimmt, wird das 'at' zum start oder end Zeitpunkt generiert. Über den 2-ten parameter "Start oder Ende" kann man definieren ob das at event am Anfang oder am Ende vom Kalendereintrag generiert werden soll. Das ist case insensitiv wil ich das über lc() konvertiert habe.
Der Trigger muss mit dem Kalendereintrag matchen
Die Action kann dann eine beliebige fhem Aktion sein, hier wird der Schalter_Heizung eingeschaltet.

Ich bin kein Perl experte, geht bestimmt schöner, aber funktioniert bei mir.


##########################################################
# define GoogleCalendar_n notify GoogleCalendar:to.*_00[1-9]_[be]time:.* {Kalenderstart("$EVENT","Trigger","Action")}
# define GoogleCalendar_n notify GoogleCalendar:to.*_00[1-9]_[be]time:.* {Kalenderstart("$EVENT","BEGIN","Besuch kommt","set Schalter1 on;;set Schalter2 off")}
# define GoogleCalendar_n notify GoogleCalendar:to.*_00[1-9]_[be]time:.* {Kalenderstart("$EVENT","Start","Besuch kommt","set Schalter1 on;;set Schalter2 off")}
# define GoogleCalendar_n notify GoogleCalendar:to.*_00[1-9]_[be]time:.* {Kalenderstart("$EVENT","Anfang","Besuch kommt","set HMIP_PSM1 on")}
# define GoogleCalendar_n notify GoogleCalendar:to.*_00[1-9]_[be]time:.* {Kalenderstart("$EVENT","End","Besuch kommt","set HMIP_PSM1 off")}
##########################################################
sub Kalenderstart ($$$$) {
  my ($Event,$StartOrEnd,$Trigger,$Action) = @_;
  my $hm         = strftime("%H:%M", localtime(time()));
  my $startlcend = lc($StartOrEnd);
  my @EVENTarray = split(": ", $Event);
  if (($hm lt $EVENTarray[1] && $EVENTarray[0] =~ 'today_.*') || ($hm gt $EVENTarray[1] && $EVENTarray[0] =~ 'tomorrow_.*')) {
    my @EVENTsplit = ($startlcend eq "begin" || $startlcend eq "start" || $startlcend eq "anfang")?split("btime", $EVENTarray[0]):split("etime", $EVENTarray[0]);
    my $summary    = $EVENTsplit[0]."summary";
    #Log 3, "Event: $Event; StartOrEnd: $StartOrEnd; Trigger: $Trigger; Action: $Action; EVENTarray[0]: $EVENTarray[0]; EVENTarray[1]: $EVENTarray[1]; summary: $summary; $Action";
    my $Kalendertext = ReadingsVal("GoogleCalendar","$summary","nA");
    my @Triggerarray = (split(" ", $Trigger),"_","_");
    my $devSpec      = $Triggerarray[0]."_".$Triggerarray[1]."_".$Triggerarray[2]."_".$startlcend;
    if ($Kalendertext =~ /$Trigger/) {fhem("defmod $devSpec at $EVENTarray[1]:00 $Action;attr $devSpec room Calendar ")}
}}
Bullseye auf iNUC, Homematic + HMIP(UART/HMUSB), Debmatic, HUEBridge, Zigbee/ConbeeII, FB, Alexa (fhem-lazy), Livetracking, LaCrosse JeeLink, LoRaWan / TTN / Chirpstack