alle künftigen Kalendereinträge des aktuellen Tages auslesen

O

obelix76

Ambitioniertes Mitglied
9
ich bin im Moment mit meinen (bescheidenen) Versuchen bei Tasker an einem Punkt angekommen, wo ich um Hilfe fragen muß...

ich habe zwar gesehen, daß man ein (das aktuelle?) Kalenderereignis auslesen kann irgendwie, aber das ist nicht das was ich möchte... ;) Mir schwebt eher vor, daß morgens, wenn das Handy aus der Ladeschale gezogen wird, mir alle Termine des Tages vorgelesen werden. Am besten sortiert nach Ganztagesterminen und uhrzeitbasierten Terminen. Dazu muß ich aber irgendwie an die gesammelten Kalendereinträge des Tages rankommen... Hat jemand schon mal etwas ähnliches gemacht und kann mir einen Tip geben? Oder ist das nicht möglich, was ich da vor habe?

Danke schon mal vorab! :)
 
Mit sortierter Anzeige wird das wohl nicht so einfach gehen, aber in diesem Post erfährst du zumindest wie man Einträge ausliest. Falls weitere Fragen diesbezüglich aufkommen, bitte im verlinkten Thread weiter machen.


Gruß

Chillmann
 
Ich hab mal irgendwo einen toten Thread gefunden wo der Kalender per API abgefragt wurde. Dann kann man das XMP zerlegen.
 
*gnampf*
ja, an das einfachste denkt man immer zuletzt... ;)
Danke für den Hinweis, mal nach einer google Kalender-API zu schauen.
 
So. ich hatte am Wochenende etwas Zeit... ;)

Entstanden ist ein PHP-Script (analog dem Wettervorleser von hier: https://www.android-hilfe.de/forum/...wetterservern.297343-page-3.html#post-4614794 ), womit mir eine (konfigurierbare) Liste aller im Google Kalender gespeicherten Termine für den gesamten Tag ab der aktuellen Uhrzeit ausgegeben werden kann.

hier erstmal das PHP-Script, danach folgen noch ein paar Erläuterungen von mir:

PHP:
<?php

/*************************************************************************************************
 * Einfaches Script zum Abrufen von in Google Calendar gespeicherten Terminen des Tages          *
 * Syntax: scriptname.php?location&descr&noumlaut&debug&calpath=URL_zum_Kalender                 *
 *                                                                                               *
 *         Erklärung der Parameter:                                                              *
 *           debug    ... Ausgabe der Rohdaten zu Debugzwecken (optional)                        *
 *           location ... wenn Termine eine Angabe zum Ort enthalten, diesen mit ausgeben        *
 *           descr    ... wenn Termine eine Beschreibung enthalten, diese mit ausgeben           *
 *           calpath  ... URL zum Google-Kalender, Format siehe weiterer Beschreibungstext unten *
 *           noumlaut ... für TTS-Stimmen, die Probleme mit Umlauten und Sonderzeichen haben,    *
 *                        ä,ö,ü,ß,Ä,Ö,Ü durch Lautumschreibung ersetzen                          *
 *                                                                                               *
 * Datum: 03.12.2012                                                                             *
 * Version: 1.0 vom 03.12.2012                                                                   *
 *                                                                                               *
 * Anmerkung und Hinweise zu calpath:                                                            *
 * calpath findet man im Webfrontend des Google Calendar, "Meine Kalender" - Einstellungen -     *
 * Klick auf den Namen des Kalenders - Privatadresse - XML                                       *
 * Beachten: im Link von Google das "basic" am Ende durch "full" ersetzen. Die Projection        *
 * "basic" liefert nicht alle Daten, auf die das Script zugreifen möchte!                        *
 * (durch Verwenden der Privatadresse spar ich in dem Script die Autorisiererei bei google ;))   *
 *                                                                                               *
 * eine calpath-URL sieht etwa so aus:                                                           *
 * https://www.google.com/calendar/feeds/ACCOUNT@googlemail.com/private-WIRREZEICHEN/full        *
 *                                                                                               *
 * Google Calendar reference: https://developers.google.com/google-apps/calendar/v2/reference    *
 *                                                                                               *
 *************************************************************************************************/

unset($errors); //Fehlercounter zurücksetzen
 
function debugprint($variable){
    if (isset($_GET['debug'])){
        echo "<pre>";
        print_r($variable);
        echo "</pre><br>";
    }
}

function umlaut_convert($text){
    if (isset($_GET['noumlaut'])){
        $search   = array( 'ä', 'ö', 'ü', 'ß', 'Ä', 'Ö', 'Ü' );
        $replace  = array( 'ae', 'oe', 'ue', 'ss', 'Ae', 'Oe', 'Ue' );
        $text     = str_replace( $search, $replace, $text );
    }
    return $text;
}

if (!(isset($_GET['calpath']))){
    $errors[] = "Keine Kalender-URL übergeben, Keine Datenauswertung möglich!";
}
else{
    $calpath = $_GET['calpath'];
}

if (empty($errors)){
    //ACHTUNG: Sonderzeichen im Datum URL-encodieren, sonst geht der calendar_query schief!
    $calstart = date("Y-m-d\TH\%3\Ai\%3\As", time());
    $calend   = date("Y-m-d\T23\%3\A59\%3\A59", time());

    $calendar_query = $calpath."?orderby=starttime&sortorder=a&start-min=$calstart&start-max=$calend";
    debugprint($calendar_query);
    $calendar_data = file_get_contents($calendar_query);
    //simplexml und Namespaces hab ich nicht wirklich sauber hinbekommen... :)
    //wenn mir jemand zeigen kann, wie es geht, kann ichs auch ändern. *g* bis 
    //dahin der "workaround" mit dem Ersetzen.
    $calendar_data = str_replace("<gd:", "<gd_", $calendar_data);
    $calendar_data = str_replace("</gd:", "</gd_", $calendar_data);
    $calendar_xml = simplexml_load_string($calendar_data);

    $dayevent = 0; //Zählvariable für Ganztagesereignisse auf Null setzen
    $appntmnt = 0; //Zählvariable für Termine auf Null setzen

    foreach ($calendar_xml->entry as $entry){
        //Kalenderereignisse ablaufen und relevante Daten in je ein Array für
        //Ganztagesereignisse und Termine speichern, Unterscheidung anhand der
        //Länge der Startzeit (bei Ganztags ist nur das Datum enthalten)
        if (trim(strlen((string)$entry->gd_when["startTime"]))== 10){
            //wir haben ein Ganztagesevent
            $dayevent_data[$dayevent]["type"]    ="dayevent"; //eigentlich überflüssig, da getrennte Arrays für beide Kalenderereignisse
            $dayevent_data[$dayevent]["title"]   =utf8_decode((string)$entry->title);
            $dayevent_data[$dayevent]["content"] =utf8_decode((string)$entry->content);
            $dayevent_data[$dayevent]["location"]=utf8_decode((string)$entry->gd_where["valueString"]);
            $dayevent_data[$dayevent]["start"]   =strtotime((string)$entry->gd_when["startTime"]);
            $dayevent_data[$dayevent]["end"]     =strtotime((string)$entry->gd_when["endTime"]);
            $dayevent++;
        }
        else{
            //wir haben einen normalen Termin
            $appntmnt_data[$appntmnt]["type"]     ="appointment";
            $appntmnt_data[$appntmnt]["title"]   =utf8_decode((string)$entry->title);
            $appntmnt_data[$appntmnt]["content"] =utf8_decode((string)$entry->content);
            $appntmnt_data[$appntmnt]["location"]=utf8_decode((string)$entry->gd_where["valueString"]);
            $appntmnt_data[$appntmnt]["start"]   =strtotime((string)$entry->gd_when["startTime"]);
            $appntmnt_data[$appntmnt]["end"]     =strtotime((string)$entry->gd_when["endTime"]);    
            $appntmnt++;
        }
    }

    //$dayevent zum Sortieren aufbereiten und nach Startzeit sortieren, da manchmal die Sortierung 
    //von Google trotz gesetztem Parameter im query nicht korrekt zurückgeliefert wurde
    $original_data_array = $appntmnt_data;
    $new_data_array = array();
    foreach ($original_data_array as $key => $entry_array)
    {
        $new_key = $entry_array['start'].".".base_convert((md5($entry_array['title']) + md5($entry_array['content']) + md5($entry_array['location'])), 16, 10);
        //da wir das Array umtransformieren würden bei gleichen Timestamps einträge verloren gehen
        //daher errechne ich aus den MD5-hashes von title, content und location einen (hoffentlich :)) 
        //eindeutigen Zusatz zum neuen Arraykey, konvertiere ihn von Hex nach Dec und hänge ihn an 
        //start als "Nachkommastelle" an... 
        $new_data_array[ $new_key ] = $entry_array;
    }
    ksort($new_data_array); //Array nach key (unsere Terimnstartzeit + "Zusatz") sortieren
    $appntmnt_data = $new_data_array; //und alles wieder in unser Original-Array zurückschreiben
    debugprint($dayevent_data);
    debugprint($appntmnt_data);

    //String zum Ansagen der Termine zusammenstellen
    //zuerst prüfen, ob heute überhaupt Termine anstehen
    if (($dayevent==0) AND ($appntmnt==0)){
        //keine Termine
        $return = "DESCRIPTION: Für heute sind keine Termine vorhanden.";
    }
    else{
        //Termine
        $return = "DESCRIPTION: Einträge für heute: ";
        if ($dayevent>0){
            $return .= "$dayevent Ganztagstermin";
            if ($dayevent>1){
                $return .= "e";
            }
            $return .= ": ";
            $count = 1;
            foreach ($dayevent_data as $line){
                $return .= "Termin $count: ".$line['title']." ";
                if (!(empty($line['location'])) and (isset($_GET['location']))) {
                    $return .= "in ".$line['location'];
                }
                if (!(empty($line['content'])) and (isset($_GET['descr']))) {
                    $return .= ", ".$line['content'];
                }
                $count++;
                $return .= ". ";
            }
        }
        if ($appntmnt>0){
            $return .= "$appntmnt Ereignis";
            if ($appntmnt>1){
                $return .= "se";
            }
            $return .= ": ";
            $count = 1;
            foreach ($appntmnt_data as $line){
                $return .= date("G \U\h\\r i", $line[start])." ".$line['title']." ";
                if (!(empty($line['location'])) and (isset($_GET['location']))) {
                    $return .= "in ".$line['location'];
                }
                if (!(empty($line['content'])) and (isset($_GET['descr']))) {
                    $return .= ", ".$line['content'];
                }
                $count++;
                $return .= ". ";
            }
        }
    }
    echo umlaut_convert($return);
}

if (isset($errors)){
    //Fehler im Scriptablauf? Dann Fehlermeldungen ausgeben. 
    foreach($errors as $f) { 
        echo $f."<br>";
    }
}
?>
jetzt die Erklärungen dazu...

Das Script erwartet ein paar Parameter beim Aufruf:

  • "debug" macht das Script etwas "gesprächiger" und wirft noch ein paar Rohdaten mit aus
  • "location" gibt, wenn Termineinträge vorhanden sind und bei denen das "Ort"-Feld belegt wurde, den Ort mit in die Ausgabe
  • "descr" gibt, wenn Termineinträge vorhanden sind und bei denen das "Beschreibung"-Feld belegt wurde, die Beschreibung mit in die Ausgabe
  • "noumlaut" konvertiert alle deutschen Umlaute und das "ß" in Lautumschreibungen für TTS-Stimmen, die nicht mit Umlauten klar kommen (z.B. die Samsung-Stimme auf meinem Galaxy S2). Wird der Parameter weggelassen, erscheinen Umlaute (die wiederum auf der Defaultstimme meines Pearl-Noname Tablets wieder besser klingen als die Lautumschreibungen...)
  • "calpath=PFAD_ZUM_KALENDER" gibt die Privatadresse des abzurufenden Kalenders an. Die Beschreibung, wie man an die Privatadresse herankommt, ist im Scriptkommentar enthalten. Wichtig ist noch, die Adresse wie im Kommentar beschrieben zu ändern und aus der Projection "basic" die Projection "full" zu machen.
Dieser Adressaufruf ist auch der Grund, warum ich dieses Script nicht öffentlich hoste. Mit der Privatadresse ist auch ohne weiteres authorize ein Lesender Zugriff auf den Kalender möglich! Das heißt, jeder, der die Adresse hat, kann den Kalender lesen! Da bei einem Aufruf aber genau jene Adresse als Parameter mitkommt, würde also euer Kalender-lesezugriff in meinen Webserver-Logfiles landen. Das ...möchte ich nicht. ;) Wer das Terminscript nutzen möchte, muß es also auf einem eigenen Server hosten (und da natürlich auch wieder bedenken, wer ggfs. sonst so Zugriff auf die Logfiles hat).


Das Script kann natürlich nur Termine aufbereiten, die im Google Kalender hinterlegt sind. Wird der Androide "offline" und nur lokal ohne die Google Kalenderfunktion verwendet, wird das Script nix finden. ;)

Zudem ist mir im Tasker noch was aufgefallen. Ich frage die im PHP die Parameter (mit Ausnahme von calpath) nur auf "ist gesetzt" ab. Wenn man in der Tasker-Option des HTTP-Get allerdings nur den Parameter (ohne Wert) bei Attribute hinterlegt, werden sie nicht an den Server geschickt.
Wenn man bei Attribute allerdings Parameter in der Form
"location=ja"
"noumlaut=ja"
"descr=ja"
(ohne die einschließenden Anführungszeichen) hinterlegt, funktioniert es. :)


Viel Spaß mit dem Script und dem Voice-Terminassistenten :)
 
Zuletzt bearbeitet:
  • Danke
Reaktionen: Cupra

Ähnliche Themen

X
Antworten
4
Aufrufe
758
xyzUpdate
X
D
  • Dreamweaver
Antworten
5
Aufrufe
521
bbfh
bbfh
marspoki
Antworten
2
Aufrufe
461
Cecoupeter
Cecoupeter
Zurück
Oben Unten