# Verwenden von Google Health

Die Google Health Data API wurde entwickelt um es Entwicklern zu erlauben die folgenden 2 Dinge zu tun:

- Das Google Gesundheitsprofil eines Benutzers lesen oder nach medizinischen Einträgen zu suchen die einem speziellen Kriterium entsprechen und dann die Ergebnisse zu verwenden um personalisierte Funktionalitäten basierend auf diesen Daten anzubieten.

- Neue Medizinische Daten zu einem Benutzerprofil hinzuzufügen indem CCR Daten eingefügt werden wenn eine Notiz an ein Benutzerprofil gesendet wird. Es ist zu beachten das die CCR Daten als XML Blob im <atom> Eintrag gespeichert werden. Die Bibliothek bietet keine direkten Zugriffsmethoden zu dem Objektmodell an aber es hat Helfer für das extrahieren von speziellen Feldern.

Es gibt drei Hauptfeeds, die alle eine Authentifikation benötigen. Anders als andere Google Data APIs hat jede der Google Health Feeds ein begrenztes Set von HTTP Anweisungen die auf Ihm ausgeführt werden können, abhängig von der Authentifizierungsmethode die man verwendet (ClientLogin oder AuthSub/OAuth). Für eine Liste von gestatteten Anweisungen siehe http://code.google.com/apis/health/reference.html#Authentication.

- Profil Feed verwende den Profilfeed um das Gesundheitsprofil eines Benutzers nach speziellen Informationen zu durchsuchen.

- Registrierungs Feed verwende den Registrierungsfeed um neue CCR Daten in ein Profil einzupflegen.

- Profil Listen Feed der Profil Listen Feed sollte verwendet werden um festzustellen mit welchem Gesundheitsprofil eines Benutzer interagiert werden soll. Dieser Feed ist nur vorhanden wenn man ClientLogin verwendet.

Siehe http://code.google.com/apis/health für weitere Informationen über die Google Health API.

## Zum Health Service verbinden

Die Google Health API basiert, wie alle Google Data APIs, auf dem Atom Publishing Protokoll (APP), einem XML basierenden Format für die Verwaltung von Web-basierenden Ressourcen. Verkehr zwischen einem Client und dem Google Health Servern findet über HTTP statt und erlaubt authentifizierte Verbindungen.

Bevor eine Transaktion stattfinden kann, muß eine Verbindung erstellt werden. Das Erstellen einer Verbindung zu den Health Servern beinhaltet zwei Schritte: Erstellung eines HTTP Clients und diesen Client an eine `Zend_Gdata_Health` Instanz binden.

### Authentifikation

Die Google Health API erlaubt den programmtechnischen Zugriff auf das Gesundheitsprofil eines Benutzer. Es gibt drei Authentifizierungsschemata die von Google Health unterstützt werden:

- ClientLogin bietet direkte Benutzername/Passwort Authentifikation zu den Health Servern. Da diese Methoden erwarten das Benutzer Ihr Passwort der Anwendung angeben müssen, wird dieses Authentifizierungsschema nur für installierte/Desktopanwendungen empfohlen.

- AuthSub erlaubt es einen Benutzer seine privaten Daten zu teilen. Das bietet das selbe Level der bequemlichkeit wir ClientLogin, aber ohne das Sicherheitsrisiko, was es zu einer idealen Wahl für Web-basierende Anwendungen macht. Für Google Health muß AuthSub in einem registrierten und sicheren Modus verwendet werden -- was bedeutet das alle Anfragen zur API digital signiert werden müssen.

- OAuth ist eine alternative zu AuthSub. Auch wenn dieses Authentifizierungschema nicht in diesem Dokument diskutiert wird, können weitere Informationen hier gefunden werden: Health Data API Developer's Guide.

Siehe Authentication Overview in the Google Data API documentation für weitere Informationen über jede Authentifizierungsmethode.

### Erstellen einer Health Service Instanz

Um mit Google Health zu interagieren, bietet die Client Bibliothek die Serviceklasse `Zend_Gdata_Health`. Diese Klasse bietet ein übliches Interface zu den Google Data und Atom Publishing Protokoll Modellen und hilft bei der Durchführung von Anfragen von und zur Health API.

Sobald man sich für ein Authentifizierungsschema entschieden hat, ist der nächste Schritt die Erstellung einer Instanz von `Zend_Gdata_Health`. Dieser Klasse sollte eine Instanz von `Zend_Gdata_HttpClient` übergeben werden. Diese bietet ein Interface für- AuthSub/OAuth und ClientLogin um einen speziell authentifizierten HTTP Client zu erstellen.

Um mit dem H9 des Entwicklers (/h9) statt Google Health (/health) nimmt der Konstruktor von `Zend_Gdata_Health` ein optionales drittes Argument mit dem man den H9 Service Name 'weaver' spezifizieren kann.

Das folgende Beispiel zeigt wie eine Health Service Klasse bei Verwendung der ClientLogin Authentifizierung erstellt wird:

    // Parameter für die ClientLogin Authentifikation
    $healthServiceName = Zend_Gdata_Health::HEALTH_SERVICE_NAME;
    //$h9ServiceName = Zend_Gdata_Health::H9_SANDBOX_SERVICE_NAME;
    $user = "user@gmail.com";
    $pass = "pa$$w0rd";

    // Erstellt einen authentifizierten HTTP Client
    $client = Zend_Gdata_ClientLogin::getHttpClient($user,
                                                    $pass,
                                                    $healthServiceName);

    // Erstellt eine Instanz des Health Services
    $service = new Zend_Gdata_Health($client);

Ein Health Service der AuthSub verwendet kann ähnlich erstellt werden, im einem etwas längeren Aussehen. AuthSub ist das empfohlene Interface um mit Google Health zu kommunizieren weil jeder Token direkt zu einem speziellen Profil im Account des Benutzers verlinkt wird. Anders als andere Google Data APIs, ist es notwendig das alle Anfragen von der eigenen Anwendung digital signiert werden.

    /*
     * Empfängt die aktuelle URL damit der AuthSub Server weiß wohin er den
     * Benutzer routen soll nachdem die Authentifizierung komplett ist.
     */
    function getCurrentUrl() {
        $phpRequestUri = htmlentities(substr($_SERVER['REQUEST_URI'],
                                             0,
                                             strcspn($_SERVER['REQUEST_URI'],
                                                     "\n\r")),
                                      ENT_QUOTES);

        if (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on') {
            $protocol = 'https://';
        } else {
            $protocol = 'http://';
        }
        $host = $_SERVER['HTTP_HOST'];
        if ($_SERVER['SERVER_PORT'] != '' &&
           (($protocol == 'http://' && $_SERVER['SERVER_PORT'] != '80') ||
           ($protocol == 'https://' && $_SERVER['SERVER_PORT'] != '443'))) {
            $port = ':' . $_SERVER['SERVER_PORT'];
        } else {
            $port = '';
        }
        return $protocol . $host . $port . $phpRequestUri;
    }

    /*
     * Leitet einen Benutzer zu AuthSub um wenn er keinen gültigen Session Token
     * hat. Wenn er von AuthSub mit einem einmal-zu-verwendenden Token zurückkommt,
     * wird ein neuer HTTP Client initialisiert und der Token mit eine langlebigen
     * Sessiontoken getauscht.
     */
    function setupClient($singleUseToken = null) {
        $client = null;

        // Einen neuen AuthSub Token holen?
        if (!$singleUseToken) {
            $next = getCurrentUrl();
            $scope = 'https://www.google.com/health/feeds';
            $authSubHandler = 'https://www.google.com/health/authsub';
            $secure = 1;
            $session = 1;
            $authSubURL =  Zend_Gdata_AuthSub::getAuthSubTokenUri($next,
                                                                  $scope,
                                                                  $secure,
                                                                  $session,
                                                                  $authSubHandler);

             // 1 - Erlaubt es Notizen zu schicken und das Lesen von Profildaten
            $permission = 1;
            $authSubURL .= '&permission=' . $permission;

            echo '<a href="' . $authSubURL . '">Dein Google Health Account</a>';
        } else {
            $client = new Zend_Gdata_HttpClient();

            // Setzen des privaten Schlüssels mit dem nachfolgende Anfragen
            // signiert werden
            $client->setAuthSubPrivateKeyFile('/path/to/your/rsa_private_key.pem',
                                              null,
                                              true);

            $sessionToken =
                Zend_Gdata_AuthSub::getAuthSubSessionToken(trim($singleUseToken),
                                                           $client);

            // Setzt den langlebigen Sessiontoken für nachfolgende Anfragen
            $client->setAuthSubToken($sessionToken);
        }
        return $client;
    }

    // -> Skriptausführung beginnt hier <-

    session_start();

    $client = setupClient(@$_GET['token']);

    // Erstellt eine Instanz des Health Services
    $userH9Sandbox = false;
    $healthService = new Zend_Gdata_Health($client,
                                           'googleInc-MyTestAppName-v1.0',
                                           $userH9Sandbox);

Achtung: der Rest dieses Dokument wird annehmen das man AuthSub für die Authentifikation verwendet.

## Profil Feed

Um den Profil Feed des Benutzers abzufragen, muß man sicherstellen das der initiale AuthSub Token mit gesetztem `permission=1` Parameter angefragt wurde. Der Prozess des extrahierens von Daten aus dem Profil benötigt zwei Schritte. Das Senden einer Anfrage und dem durchlaufen des resultierenden Feeds.

### Eine strukturierte Anfrage senden

Man kann strukturierte Anfragen senden um spezielle Einträge von einem Benutzerprofil zu erhalten.

Wenn man die Health API verwendet um ein Profil zu empfangen, werden speziell konstruierte Anfrage URLs verwendet um zu beschreiben welche (CCR) Daten zurückgegeben werden sollen. Die Klasse `Zend_Gdata_Health_Query` hilft dabei diese Aufgabe zu vereinfachen indem automatisch eine Abfrage URL erstellt wird basierend auf den Parametern die man gesetzt hat.

#### Den Feed abfragen

Um eine Abfrage eines Profil Feeds durchzuführen, muß eine neue Instanz von `Zend_Gdata_Health_Query` erzeugt und die `getHealthProfileFeed()` Methode des Services aufgerufen werden:

    $healthService = new Zend_Gdata_Health($client);

    // Beispielabfrage für die besten 10 Medikationen mit jeweils 2 Elementen
    $query = new Zend_Gdata_Health_Query();
    $query->setDigest("true");
    $query->setGrouped("true");
    $query->setMaxResultsGroup(10);
    $query->setMaxResultsInGroup(2);
    $query->setCategory("medication");

    $profileFeed = $healthService->getHealthProfileFeed($query);

Wenn man `setDigest("true")` verwendet werden alle CCR Daten des Benutzers in einem einzelnen Atom `<entry>` zurückgegeben.

Dem `setCategory()` Helfer kann ein zusätzlicher Parameter übergeben werden um spezifischere CCR Informationen zurückzuerhalten. Um zum Beispiel nur die Medikation Lipitor zurückzugeben verwendet man `setCategory("medication", "Lipitor")`. Die selbe Methode kann bei anderen Kategorien wie Konditionen, Allergien, Labor Ergebnisse, usw. angewendet werden.

Eine komplette Liste der unterstützten Abfrageparameter ist im Kapitel der Abfrageparameter des Health API Referenz Guides vorhanden.

### Durch die Profil Einträge iterieren

Jeder Google Health Eintrag enthält CCR Daten, trotzem führt die Verwendung des Abfrageparameters `digest=true` dazu das alle CCR Elemente (die dieser Abfrage entsprechen) in einen einzelnen Atom `<entry>` zusammengefügt werden.

Um die kompletten CCR Informationen von einem Eintrag zu erhalten, muß ein Aufruf zur `getCcr()` Methode der `Zend_Gdata_Health_ProfileEntry` Klasse durchgeführt werden. Das gibt ein `Zend_Gdata_Health_Extension_CCR` zurück:

    $entries = $profileFeed->getEntries();
    foreach ($entries as $entry) {
        $medications = $entry->getCcr()->getMedications();
        //$conditions = $entry->getCcr()->getConditions();
        //$immunizations = $entry->getCcr()->getImmunizations();

        // Das CCR XML ausgeben (das werden nur die Medikationen des Eintrags sein)
        foreach ($medications as $med) {
            $xmlStr = $med->ownerDocument->saveXML($med);
            echo "<pre>" . $xmlStr . "</pre>";
        }
    }

Hier wird die `getCcr()` Methode in Verbindung mit einem magischen Helfer verwendet um nur die Medikationsdaten aufzureißen und aus den CCR des Eintrags zu extrahieren. Der hierbei erwähnte magische Helfer nimmt das Formular `getCATEGORYNAME()`, wobei `CATEGORYNAME` eine unterstützte Kategorie von Google Health ist. Für mögliche Kategorien kann in den Google Health Referenz Guide gesehen werden.

Um effizienter zu sein, können auch Kategorie Abfragen verwendet werden um nur die notwendigen CCRs von den Google Health Servern zu erhalten. Dann muß durch diese Ergebnisse iteriert werden:

    $query = new Zend_Gdata_Health_Query();
    $query->setDigest("true");
    $query->setCategory("condition");
    $profileFeed = $healthService->getHealthProfileFeed($query);

    // Da die Abfrage digest=true enthält, wird nur der Atom Eintrag zurückgegeben
    $entry = $profileFeed->entry[0];
    $conditions = $entry->getCcr()->getConditions();

    // Die CCR Daten ausgeben (das sind nur die Konditionen des Profils)
    foreach ($conditions as $cond) {
        $xmlStr = $cond->ownerDocument->saveXML($cond);
        echo "<pre>" . $xmlStr . "</pre>";
    }

## Profil Listen Feed

Beachte: Dieser Feed ist nur vorhanden wenn man ClientLogin verwendet

Da ClientLogin bei jedem seiner Feeds eine Profil ID benötigt, sollten Anwendungen diesen Feed als erstes abfragen um die richtigen Profile auszuwählen. Der Profil Listen Feed gibt Atom Einträge zurück die jedem Profil im Benutzeraccount von Google Health entsprechen. Die ProfilID wird im Atom `<content>` und der Name im `<title>` Element zurückgegeben.

### Den Feed abfragen

Um eine Abfrage gegen den Profil Listen Feed durchzuführen muß die `getHealthProfileListFeed()` Methode des Services aufgerufen werden:

    $client = Zend_Gdata_ClientLogin::getHttpClient('user@gmail.com',
                                                    'pa$$word',
                                                    'health');
    $healthService = new Zend_Gdata_Health($client);
    $feed = $healthService->getHealthProfileListFeed();

    // Jeden Namen und jede ID des Profils ausgeben
    $entries = $feed->getEntries();
    foreach ($entries as $entry) {
        echo '<p>Profil Name: ' . $entry->getProfileName() . '<br>';
        echo 'Profil ID: ' . $entry->getProfileID() . '</p>';
    }

Sobald man sich entschieden hat welches Profil verwendet werden soll, wird `setProfileID()` mit der Profil ID als Argument aufgerufen. Das begrenzt die weiteren API Abfragen auf genau das betreffende Profil:

    // Verwende das erste Profil
    $profileID = $feed->entry[0]->getProfileID();
    $healthService->setProfileID($profileID);

    $profileFeed = $healthService->getHealthProfileFeed();

    $profileID = $healthService->getProfileID();
    echo '<p><b>Abgefragte Profil ID</b>: ' . $profileID . '</p>';

## Notizen an des Register Feed versenden

Individuelle Antworten zum registrierten Feed sind als Notizen bekannt. Notizen werden von Dritt-Anwendungen gesendet um den Benutzer über ein neues Event zu informieren. Mit AuthSub/OAuth, sind Notizen einfach etwas womit die eigene Anwendung neue CCR Informationen zu einem Benutzerprofil hinzufügen kann. Notizen können reinen Text enthalten (inklusive einiger XHTML Elemente), ein CCR Dokument oder beides. Als Beispiel können Notizen gesendet werden um Benutzer daran zu erinnern das Sie spezielle Rezepte nehmen sollen, oder sie können Laborergebnisse im CCR Format enthalten.

### Senden einer Notiz

Notizen können durch das Verwenden der `sendHealthNotice()` Methode des Health Services gesendet werden:

    $healthService = new Zend_Gdata_Health($client);

    $subject = "Der Titel der Notiz ist hier";
    $body = "Der Notizinhalt kann einige <b>html</b> Elemente enthalten";
    $ccr = '<ContinuityOfCareRecord xmlns="urn:astm-org:CCR">
      <Body>
       <Problems>
        <Problem>
          <DateTime>
            <Type><Text>Start Datum</Text></Type>
            <ExactDateTime>2007-04-04T07:00:00Z</ExactDateTime>
          </DateTime>
          <Description>
            <Text>Medikament gegen Aorta Verengung</Text>
            <Code>
              <Value>410.10</Value>
              <CodingSystem>ICD9</CodingSystem>
              <Version>2004</Version>
            </Code>
          </Description>
          <Status><Text>Aktiv</Text></Status>
        </Problem>
      </Problems>
      </Body>
    </ContinuityOfCareRecord>';

    $responseEntry = $healthService->sendHealthNotice($subject,
                                                      $body,
                                                      "html",
                                                      $ccr);