InfoFrame: Digitaler Bilderrahmen (Anzeige von Anrufen, E-Mails, Termine, Wetter...)

@jnappert
hier mein Auszug aus der config.ini
Code:
[CalendarPlugin]
client_id = "***apps.googleusercontent.com"
account_name = "***@developer.gserviceaccount.com"
project_name = "****"
key_file= "***"
calendar_ID_1 = "de.german#[email protected]"
calendar_ID_color_1 = "#ffff00"
number_of_days = 3

Dann gehört natürlich noch der Pfad zum GoogleApi mit in die Config.ini.

Hier noch mein funktionierendes CalenderPlugin,ich hoffe es hilft
PHP:
<?php
/***************************************************************************
 * InfoFrame (image generator for digital picture frames)
 * Copyright (C) 2009  Tobias Kolb
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/
 ***************************************************************************/

require_once 'Zend/Loader.php';

Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');


class CalendarPlugin implements IPlugin
{
    private $dbconn = NULL;
	private $config = NULL;
	
	public function __construct($dbconn, $config) {
		$this->dbconn = $dbconn;
		$this->config = $config;
	}
	
	
	 public function doUpdate()
    {
        require_once 'autoload.php';
        // get calendar entries
        session_start();
        $client_id = $this->config['client_id'];
        $service_account_name = $this->config['account_name'];
        
        try
        {
            $client = new Google_Client();
            $client->setApplicationName($this->config['project_name']);
            $cal = new Google_Service_Calendar($client);
        }
        catch (Exception $e)
        {
            die ('Folgender Fehler trat auf: ' . $e->getMessage());
        }
        
        if (isset($_SESSION['service_token']))
            $client->setAccessToken($_SESSION['service_token']);
        $key = file_get_contents($this->config['key_file']);
        $cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/calendar'), $key);

        $client->setAssertionCredentials($cred);
        if ($client->getAuth()->isAccessTokenExpired())
            $client->getAuth()->refreshTokenWithAssertion($cred);

        $_SESSION['service_token'] = $client->getAccessToken();
        
        //set startDate, endDate, eventParams
        $cal_date = new DateTime('NOW');
        $startDate = date_format($cal_date, DateTime::W3C);
        $cal_date = date_modify($cal_date, "+".$this->config['number_of_days']." day");
        $endDate = date_format($cal_date, DateTime::W3C);
        $eventParams = array('timeMin' => $startDate,
                             'timeMax' => $endDate,
                             'singleEvents' => 'true');

        //get Calendar Id´s    
        $calendarList = $cal->calendarList->listCalendarList();
        // delete all old calendar entries
        mysql_query("START TRANSACTION", $this->dbconn);
        $query = "Delete from if_calendar";
        mysql_query($query, $this->dbconn) or die('Error, delete query failed');
        
        // get all calendars
        foreach ($calendarList->getItems() as $calendar)
        {
            $calendarID = $calendar->getID();
            $color = $calendar->getBackgroundColor();
            $entries = $cal->events->listEvents($calendarID, $eventParams);        
            foreach ($entries->getItems() as $entry)
            {
                if (!empty($entry['modelData']['start']['dateTime']))
                {
                    $begin = strtotime($entry['modelData']['start']['dateTime']);
                    $end = strtotime($entry['modelData']['end']['dateTime']);
                }
                else
                {
                    $begin = strtotime($entry['modelData']['start']['date']);
                    $end = strtotime($entry['modelData']['end']['date']);
                }                  
                $title = $entry->getSummary();    
                $location = $entry->getLocation();
                $this->addCalendar($color, $begin, $end, $title, $location);
            }
        }
        
        // get all public calendars
        $calender_num = 0;
        while ($calendarID = $this->config['calendar_ID_' . ++$calender_num])
        {    
            $color = $this->config['calendar_ID_color_' . $calender_num];
            $entries = $cal->events->listEvents($calendarID, $eventParams);        
            foreach ($entries->getItems() as $entry)
            {
                if (!empty($entry['modelData']['start']['dateTime']))
                {
                    $begin = strtotime($entry['modelData']['start']['dateTime']);
                    $end = strtotime($entry['modelData']['end']['dateTime']);
                }
                else
                {
                    $begin = strtotime($entry['modelData']['start']['date']);
                    $end = strtotime($entry['modelData']['end']['date']);
                }                  
                $title = $entry->getSummary();    
                $location = $entry->getLocation();
                $this->addCalendar($color, $begin, $end, $title, $location);
            }
        }
        mysql_query("COMMIT", $this->dbconn);
    }  
	
	
	public function doOutput($image, $style, $updateData, &$yoffset) {
		if ($updateData)
			$this->doUpdate();

		$query = "SELECT * FROM `if_calendar` WHERE (`end` > NOW()) ORDER BY `begin` ASC";
		$result = mysql_query($query, $this->dbconn);
		if (mysql_num_rows($result) > 0) {

			// define styles
			$opt_header = array(
				'width' => imagesx($image)-290,
				'line_height' => 8,
				'align' => ALIGN_LEFT
			);
			
			$opt_day = array(
				'width' => imagesx($image)-290,
				'height' => 14,
				'line_height' => 14,
				'align' => ALIGN_LEFT
			);

			$opt_entry = array(
				'width' => imagesx($image)-290,
				'height' => 12,
				'line_height' => 12,
				'align' => ALIGN_LEFT,
				'word_wrap_hyphen' => '...',
				'aggressive_word_wrap' => true,
			);

			// print header
			imagettftextboxopt($image, 18, 0, 50, $yoffset, $style['textcolor'], $style['font'], "Nächste Termine", $opt_header);
			$icon = ImageCreateFromPNG ( 'resources/icons/clock.png' );
			ImageCopy($image, $icon, 20, $yoffset-12, 0, 0, imagesx($icon), imagesy($icon));
			ImageDestroy($icon);
			$yoffset += 10;
			
			// print calendar
			$counter = 0;
			$formatDate = "%d.%m.%Y";
			$formatTime = "%H:%M";
			$today = strftime( $formatDate );
			$tomorrow  = strftime( $formatDate, strtotime("+1 day", time() ) );
			$currently_displayed_day = 0;

			while ($row = mysql_fetch_assoc($result)) {
				$counter++;
				
				// if end of screen is reached and more than one items left -> cut off and show hint "x more appointments..."
				$rest = (mysql_num_rows($result) - $counter) + 1;
				if (($yoffset >= (imagesy($image) - 36)) && ($rest > 1)) {
					$text = "... $rest weitere Termine";
					imagettftextboxopt($image, 14, 0, 24, $yoffset, $style['textcolor'], $style['fontb'], $text, $opt_entry);
					$yoffset += 0;
					break;
				}
				
				// print day name
				$begin_date = strftime( $formatDate, strtotime($row['begin']));
				// if begin day is before today set begin to today
				if (strtotime($begin_date) < strtotime($today))
					$begin_date = $today;
				// now if begin is after $currently_displayed_day update $currently_displayed_day
				if (strtotime($begin_date) > $currently_displayed_day) {
					// update currently_displayed_day
					$currently_displayed_day = strtotime($begin_date);
					// print day name
					if( $begin_date == $today )
						$dayname = "Heute";
					else if( $begin_date == $tomorrow )
						$dayname = "Morgen";
					else
						//$dayname = strftime("%A, ".$formatDate, strtotime($begin_date));
                                                $dayname = datumDeutsch(strftime("%A, ".$formatDate, strtotime($begin_date)));

					imagettftextboxopt($image, 14, 0, 50, $yoffset +1, $style['textcolor'], $style['fontb'], $dayname, $opt_day);
					$yoffset += 22;
				}
				
				// build appointment time text
				$end_date = strftime( $formatDate, strtotime($row['end']));
				$begin_time = strftime( $formatTime, strtotime($row['begin']));
				$end_time = strftime( $formatTime, strtotime($row['end']));
				$text = $row['title'];
				if ($row['location'] != null)
					$text = $text . ", " . $row['location'];
				if (($begin_time == "00:00") && ($end_time == "00:00")) {
					// all day event (substract 1 second to get the real end date at 23:59) 
					$end_date = strftime( $formatDate, strtotime($row['end'])-1);
					// if all day event is longer than one day -> print end date
					if (strtotime($end_date) != $currently_displayed_day)
						$text = $text." (bis ".$end_date.")";
						
				} else {
					// normal event with start and end time
					$text = $text." (".$begin_time." - ";
					// if event ends not this day -> display end date additionally to time
					if (strtotime($end_date) != $currently_displayed_day)
						$text = $text.$end_date.", ";					
					$text = $text.$end_time.")";
				}
				
               // roundboxtrans_middel($image, $xleft, $xend, $yoffset+2, $yoffset_abstand, $yoffset_end, $inhalt_zeilen_hoehe);
               // roundboxtrans_bottom($image, $xleft, $xend, $yoffset, $yoffset_diff, $yoffset_abstand, $yoffset_end, $radius, $bottom_zeilen_hoehe);
               /*
             if ($letzter_eintrag == $currently_displayed_day) {
             	if (strlen($text) >= 15) $xoffset = 150;
               	$xoffset += 130;
               	$yoffset -= 25;
              }else{ 
              	$xoffset = 0;             
              	roundboxtrans_middel($image, $xleft, $xend, $yoffset, $yoffset_abstand+1, $yoffset_end, $inhalt_zeilen_hoehe+1);
            }
            */   
// ------------------------------------------- Müllabfuhr----------------------------------------                   
                 if (($row['color']) == "#d06b64") {
                	if (strpos($row['title'], 'Blaue') !== false)
                      $icon = ImageCreateFromPNG ( 'resources/icons/tonne_blau.png' );
                	if (strpos($row['title'], 'Biotonne') !== false)
                      $icon = ImageCreateFromPNG ( 'resources/icons/tonne_gruen.png' ); 
                	if (strpos($row['title'], 'Gelber Sack') !== false)
                      $icon = ImageCreateFromPNG ( 'resources/icons/gelber_sack.png' ); 
                	if (strpos($row['title'], 'Restabfall') !== false)
                      $icon = ImageCreateFromPNG ( 'resources/icons/tonne_schwarz.png' );                                               
                	ImageCopy($image, $icon, $xoffset+25, $yoffset-20, 0, 0, imagesx($icon), imagesy($icon));
                	ImageDestroy($icon);
                }  
// ------------------------------------------- Geburtstag ----------------------------------------     
				if (($row['color']) == "#d06b64") {  
					if (strpos($row['title'], 'Geburtstag') !== false)
						$icon = ImageCreateFromPNG ( 'resources/icons/birth.png' );
					ImageCopy($image, $icon, $xoffset+25, $yoffset-15, 0, 0, imagesx($icon), imagesy($icon));
					ImageDestroy($icon);
				}
// ------------------------------------------- Namenstag ----------------------------------------     
				if (($row['color']) == "#d06b64") {
					$icon = ImageCreateFromPNG ( 'resources/icons/name.png' );
					ImageCopy($image, $icon, $xoffset+27, $yoffset+1, 0, 0, imagesx($icon), imagesy($icon));
					ImageDestroy($icon);
				} else {
// ------------------------------------------- Standard - Button ----------------------------------------                
					// determine button color
					$colorArray = htmlColorToRgb($row['color']);
					$color = ImageColorAllocate ($image, $colorArray[0], $colorArray[1], $colorArray[2]);
					// print appointment text and button                             
					drawGlassButton($image, $color, $xoffset+32, $yoffset-6);
				}
                imagettftextboxopt($image, 12, 0, $xoffset+50, $yoffset-6, $style['textcolor'], $style['font'], $text, $opt_entry);
                $yoffset += 6; 
								$letzter_eintrag =  $currently_displayed_day;                        
          }
            $yoffset += 2;           
        }
       // roundboxtrans_bottom($image, $xleft, $xend, $yoffset, $yoffset_diff, $yoffset_abstand+16, $yoffset_end, $radius, $bottom_zeilen_hoehe);
        mysql_free_result($result);

    }

    private function addCalendar($color, $begin, $end, $title, $location) {
        $query = "INSERT INTO `if_calendar` (`id`, `color`, `begin`, `end`, `title`, `location`) 
                  VALUES (NULL,
                  '".mysql_real_escape_string($color)."', FROM_UNIXTIME($begin), FROM_UNIXTIME($end),
                  '".mysql_real_escape_string($title)."',
                  '".mysql_real_escape_string($location)."'
                  )";
        mysql_query($query, $this->dbconn) or die('CalendarPlugin: '.mysql_error());
    }
    
}

Also bei mir funktioniert es prima,allerdings lokal auf einen Wind7 Rechner unter Xampp.
Schau mal Deine php Version nach ,bei einer veralteteten Version geht es auch nicht.Ich musste mir auch Xampp neu installieren mit einer neueren php Version,dann lief es.(Jetzt php Version 5.6.3)

Viel Erfolg

Volker
 
Hi Spoon3er,

das Hermes-Tracking funktioniert bei mir auch nicht.
Sie scheitert beim Versuch mit Curl die SessionID zu holen, nach
PHP:
$result = curl_exec($ch);
ist $result = 0
Entsprechend kommt dann mit dem Rest nur noch murks und fliegt dann beim
PHP:
$table = $xpath->query('//*[@class="content_table table_shipmentDetails"]')->item(0)->childNodes->item(1)->firstChild;
endgültig raus.

Haben wir irgendeine Curl Option nicht installiert?

Gruß, Michael...
 
Zuletzt bearbeitet:
@Volker: Vielen Dank - wird heute abend sofort getestet. Stimmt, ich hätte vielleicht schreiben sollen, das ich das ganze Projekt auf einem Rapsberry PI laufen habe. Die php Version dürfte aber recht aktuell sein.
 
Hi zusammen
Ich habe gerade Spoo3ners Hermes Teil bei mir eingefügt aber es kommt nur Sendung nicht gefunden.Datenbankeinträge: Paketnummer steht drin, Datum " NULL" ,Status "NULL" ,Position "0"
Mein Hermes Teil sieht jetzt so aus
PHP:
 	private function hermesTracking($trackingnumber, $id) {
        $i=0; $inhalt=$bild=$posi=$shedule='';
        $trans = array('an die Hermes Logistik Gruppe' => '', 'Hermes' => '','Die' => '', 'Sendung wurde' =>'Sendung ', 'ist' => '', 'für den weiteren Transport' => '');
        $patterns = array('übermittelt', 'verlassen', 'übernommen', 'sortiert', 'eingetroffen', 'Zustellung', 'zugestellt'); 
                                
 // aktuelle session id holen
          $url = 'https://www.myhermes.de/wps/portal/paket/Home/privatkunden/sendungsverfolgung';
        $ch = curl_init();
        $options = array(CURLOPT_HEADER => FALSE, CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE);
            curl_setopt_array($ch, $options);    
        $result = curl_exec($ch);  
        curl_close($ch);  
           preg_match('#<form name="mhStatusForm" id="mhStatusForm" action="(.*?)" onsubmit=.*?>#i', $result, $matches);
 
 // mit aktueller session id  die trackingnummer abfragen        
       $url = 'https://www.myhermes.de'.preg_replace('#<!.*>$#', '', $matches[1]).'?action=trace&shipmentID='.$trackingnumber.'&receiptID=';
       $i=0;
          $xml = new DOMDocument();
          $xml->loadHTMLFile($url, LIBXML_NOBLANKS);
          $xpath = new DOMXPath($xml);

          $table = $xpath->query('//*[@class="content_table table_shipmentDetails"]')->item(0)->childNodes->item(1)->firstChild;    
        //  var_dump($table);      
          if($table->hasChildNodes()){
              $datum = trim(preg_replace('#\s+#', ' ', $table->childNodes->item(0)->nodeValue.' '.$table->childNodes->item(2)->nodeValue));
              $stat_txt = trim(preg_replace('#\s+#', ' ', utf8_decode($table->childNodes->item(4)->nodeValue)));         
                $stat_txt = strtr($stat_txt, $trans);
    
              if ($stat_txt == ' Sendung  auf Tour gegangen') $stat_txt = 'Sendung in Zustellung';
                foreach ($patterns as $pattern) {    
                     if(strpos($stat_txt, $pattern) !== FALSE){
                         $posi = array_search($pattern, $patterns);
                         for ($k=0; $k<=$posi; $k++)
                            $bild[$k] = 'resources/icons/hermes_'.$patterns[$k].'.png'; 
                        }
                    }
                        if ( ($posi >= 2) AND ($posi <= 3) )
                                        unset($bild[1]);
                        if ($posi >= 4)
                                        unset($bild[1], $bild[3]);
                    $bild = array_values($bild);
            }    else    {
                    $stat_txt = 'Sendung nicht gefunden';
                    $datum = date('d.m.Y H:m:s', time());
            }
            return array($stat_txt, $datum, $bild, $id, $posi); 
 }

@marvin,da bin ich ja froh das es nicht nur bei mir nicht funktioniert.Langsam fange ich ja schon an zu zweifeln.:confused:;)

Volker
 
Also irgendetwas hat da hermes gedreht... Rufe ich die funktion das erstamal auf funktioniert sie hier und ich bekomme ein gefülltes array raus. Rufe ich die funktion sofort nochmal auf bekomme ich kein response mehr von hermes. Ich nehme an, daß die session-id jetzt eine bestimmte zeit (5mins?) gültig ist und man mit einer neuen session id keinen response bekommt. Bissi schwierig zu testen :(

Hier meine alte Version ohne DOM, nur preg_match. diese funktioniert bei mir alle paar minuten...
PHP:
$trackingnumber_hermes = 'paketnummereintragen';
	function hermesTracking($trackingnumber, $id) {
		$i=0; $inhalt=$bild=$posi=$shedule='';
		$trans = array('an die Hermes Logistik Gruppe' => '', 'Hermes' => '','Die' => '', 'Sendung wurde' =>'Sendung ', 'ist' => '', 'für den weiteren Transport' => '');
		$patterns = array('übermittelt', 'verlassen', 'übernommen', 'sortiert', 'eingetroffen', 'Zustellung', 'zugestellt'); 
								
 // aktuelle session id holen
 	 	$url = 'https://www.myhermes.de/wps/portal/paket/Home/privatkunden/sendungsverfolgung';
    	$ch = curl_init();
    	$options = array(CURLOPT_HEADER => FALSE, CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE);
			curl_setopt_array($ch, $options);    
    	$result = curl_exec($ch);  
    	curl_close($ch);  
   		preg_match('#<form name="mhStatusForm" id="mhStatusForm" action="(.*?)" onsubmit=.*?>#i', $result, $matches);
   		echo preg_replace('#<!.*>$#', '', $matches[1]).PHP_EOL;
 
 // mit aktueller session id  die trackingnummer abfragen
   	 
   	$url = 'https://www.myhermes.de'.preg_replace('#<!.*>$#', '', $matches[1]).'?action=trace&shipmentID='.$trackingnumber.'&receiptID=';
   	
   		$file = 'hermes.txt';
			$handle = fopen($file, 'w+');
    	$ch = curl_init();
    	$options = array(CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => TRUE, CURLOPT_FILE => $handle);
			curl_setopt_array($ch, $options);   
    	curl_exec($ch);   
			curl_close($ch); 
			rewind($handle);
			while(!feof($handle)) {
				$zeile[$i++] = trim(fgets($handle));
			}	
			fclose($handle);
			
			for ($j=0; $j<$i; $j++)  {
		      $inhalt .= strip_tags($zeile[$j], '<tbody>');
		    }
		    echo $inhalt;
		  $inhalt = str_replace($trackingnumber, ' ', $inhalt);	
		  preg_match_all('#<tbody>(\d{2}\.\d{2}\.\d{4})(\d{2}:\d{2}:\d{2})(.+)</tbody>#', $inhalt, $matches);
		  $datum = $matches[1][0].'  '.$matches[2][0];
		  $stat_txt = strtr(substr($matches[3][0], 0 , strpos($matches[3][0], '.')), $trans);
		  if ($stat_txt == ' Sendung  auf Tour gegangen') $stat_txt = 'Sendung in Zustellung';
			foreach ($patterns as $pattern) {	
			 	if(strpos($stat_txt, $pattern) !== FALSE){
			 		$posi = array_search($pattern, $patterns);
			 		for ($k=0; $k<=$posi; $k++)
						$bild[$k] = 'resources/icons/hermes_'.$patterns[$k].'.png'; 
					}
				}
					if ( ($posi >= 2) AND ($posi <= 3) )
									unset($bild[1]);
					if ($posi >= 4)
									unset($bild[1], $bild[3]);
				$bild = array_values($bild);
				return array($stat_txt, $datum, $bild, $id, $posi, $shedule);
 }
print_r(hermesTracking($trackingnumber_hermes, 0));

wohlgemerkt das hier ist zum testen gedacht!!! nicht zum einbauen in das plugin.
 
Hi Volker,

diese Zeile kannste ruhig löschen. Zend wird nicht mehr benötigt und ist nur noch Ballast.
PHP:
require_once 'Zend/Loader.php';
Zend_Loader::loadClass('Zend_Gdata');
Zend_Loader::loadClass('Zend_Gdata_AuthSub');
Zend_Loader::loadClass('Zend_Gdata_ClientLogin');
Zend_Loader::loadClass('Zend_Gdata_Calendar');


@jnappert,
hier der Code, den ich zur Zeit verwende, wobei ich aber nicht verstehe, warum meiner funktioniert und Spoon3ers nicht. Meiner ist eigentlich zu 99% bei Spoon3er abgekupfert und lediglich auf meine Belange angepasst.
Irgendwie liefert mir die neue API die Farben nicht korrekt, daher die neuen Optionen calendar_* und color_*

Code:
client_id = "XXX.apps.googleusercontent.com"
account_name = "[email protected]"
project_name = "InfoFrame"
key_file= "cache/InfoFrame.p12"

calendar_1 = "Kalender1"
color_1 = "#22b14c"
calendar_2 = "[email protected]"
color_2 = "#0000a0"
calendar_3 = "Geburtstage"
color_3 = "#ff0000"

;abonierte Kalender
calendar_ID_1 = "de.german#[email protected]"
calendar_ID_color_1 = "#ffff80"

number_of_days = 7
;number_of_lines = 7

PHP:
<?php
/***************************************************************************
 * InfoFrame (image generator for digital picture frames)
 * Copyright (C) 2009  Tobias Kolb
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/
 ***************************************************************************/

class CalendarPlugin implements IPlugin
{
	private $dbconn = NULL;
	private $config = NULL;
	
	public function __construct($dbconn, $config)
	{
		$this->dbconn = $dbconn;
		$this->config = $config;
	}
	
	public function doUpdate()
	{
		require_once '/usr/share/google-api-php-client-master/autoload.php';
		session_start();
		$client_id = $this->config['client_id'];
		$service_account_name = $this->config['account_name'];
		
		try
		{
			$client = new Google_Client();
			$client->setApplicationName($this->config['project_name']);
			$service = new Google_Service_Calendar($client);
		}
		catch (Exception $e)
		{
			die ('Folgender Fehler trat auf: ' . $e->getMessage());
		}
		
		if (isset($_SESSION['service_token']))
			$client->setAccessToken($_SESSION['service_token']);
		$key = file_get_contents($this->config['key_file']);
		$cred = new Google_Auth_AssertionCredentials($service_account_name, array('https://www.googleapis.com/auth/calendar'), $key);

		$client->setAssertionCredentials($cred);
		if ($client->getAuth()->isAccessTokenExpired())
			$client->getAuth()->refreshTokenWithAssertion($cred);

		$_SESSION['service_token'] = $client->getAccessToken();
		
		// get colors
		// $color = $calendar->getBackgroundColor();
		// solagne nicht die korrekten Farben geholt werden, aus der ini
		$calender_num = 0;
		while ($calendar_name = $this->config['calendar_' . ++$calender_num])
			$color_array[$calendar_name] = $this->config['color_' . $calender_num];
		
		// set startDate, endDate, eventParams
		$cal_date = new DateTime('NOW');
		$startDate = date_format($cal_date, DateTime::W3C);
		$cal_date = date_modify($cal_date, "+".$this->config['number_of_days']." day");
		$endDate = date_format($cal_date, DateTime::W3C);
		
		$eventParams = array('timeMin' => $startDate,
							 'timeMax' => $endDate,
							 'singleEvents' => 'true');

		// get Calendar Id´s	
		$listParams = array ('minAccessRole' => 'reader');
		$calendarList = $service->calendarList->listCalendarList($listParams);
		
		// delete all old calendar entries
		mysql_query("START TRANSACTION", $this->dbconn);
		$query = "Delete from if_calendar where `color`<>'#000000'";
		mysql_query($query, $this->dbconn) or die('Error, delete query failed');
		
		// get all calendars
		while(true)
		{
			foreach ($calendarList->getItems() as $calendarListEntry)
			{
				$calendarID = $calendarListEntry->getID();
				if (($color = $color_array[$calendarListEntry->getsummary()]) == null)
					$color = '#80ffff';
				$events = $service->events->listEvents($calendarID, $eventParams);	    
				while(true)
				{
					foreach ($events->getItems() as $event)
					{
						if (!empty($event['modelData']['start']['dateTime']))
						{
							$begin = strtotime($event['modelData']['start']['dateTime']);
							$end = strtotime($event['modelData']['end']['dateTime']);
						}
						else
						{
							$begin = strtotime($event['modelData']['start']['date']);
							$end = strtotime($event['modelData']['end']['date']);
						}			  	
						$title = $event->getSummary();	
						$location = $event->getLocation();
						$this->addCalendar($color, $begin, $end, $title, $location);
					}
					// next event page if there is one
					$pageToken = $events->getNextPageToken();
					if ($pageToken)
					{
						$optParams = array('pageToken' => $pageToken);
						$events = $service->events->listEvents($calendarID, $optParams);
					}
					else
					{
						break;
					}
				}
			}
			// next calendar page if there is one
			$pageToken = $calendarList->getNextPageToken();
			if ($pageToken)
			{
				$optParams = array('pageToken' => $pageToken);
				$calendarList = $service->calendarList->listCalendarList($optParams);
			}
			else
			{
				break;
			}
		}
		
		// get all public calendars
		$calender_num = 0;
		while ($calendarID = $this->config['calendar_ID_' . ++$calender_num])
		{	
			$color = $this->config['calendar_ID_color_' . $calender_num];
			$events = $service->events->listEvents($calendarID, $eventParams);	    
			while (true)
			{
				foreach ($events->getItems() as $event)
				{
					if (!empty($event['modelData']['start']['dateTime']))
					{
						$begin = strtotime($event['modelData']['start']['dateTime']);
						$end = strtotime($event['modelData']['end']['dateTime']);
					}
					else
					{
						$begin = strtotime($event['modelData']['start']['date']);
						$end = strtotime($event['modelData']['end']['date']);
					}			  	
					$title = $event->getSummary();	
					$location = $event->getLocation();
					$this->addCalendar($color, $begin, $end, $title, $location);
				}
				// next event page if there is one
				$pageToken = $events->getNextPageToken();
				if ($pageToken)
				{
					$optParams = array('pageToken' => $pageToken);
					$events = $service->events->listEvents($calendarID, $optParams);
				}
				else
				{
					break;
				}
			}
		}
		mysql_query("COMMIT", $this->dbconn);
	}
	
	
	public function doOutput($image, $style, $updateData, &$yoffset)
	{
		if ($updateData)
			$this->doUpdate();
		
		$max_lines=$this->config['number_of_lines'];
		if (($max_lines == null) || ($max_lines == ""))
			$max_lines = 15;

		$query = "SELECT * FROM `if_calendar` WHERE (`end` > NOW()) ORDER BY `begin` ASC";
		$result = mysql_query($query, $this->dbconn);
		if (mysql_num_rows($result) > 0)
		{
			// define styles
			$opt_header = array(
				'width' => imagesx($image)-290,
				'line_height' => 18,
				'align' => ALIGN_LEFT
			);
			
			$opt_day = array(
				'width' => imagesx($image)-290,
				'height' => 14,
				'line_height' => 14,
				'align' => ALIGN_LEFT
			);

			$opt_entry = array(
				'width' => imagesx($image)-290,
				'height' => 12,
				'line_height' => 12,
				'align' => ALIGN_LEFT,
				'word_wrap_hyphen' => '...',
				'aggressive_word_wrap' => true,
			);

			// print header
			imagettftextboxopt($image, 22, 0, 50, $yoffset, $style['textcolor'], $style['font'], "Nächste Termine", $opt_header);
			$icon = ImageCreateFromPNG ( 'resources/icons/clock.png' );
			ImageCopy($image, $icon, 20, $yoffset-3, 0, 0, imagesx($icon), imagesy($icon));
			ImageDestroy($icon);
			$yoffset += 26;
			
			// print calendar
			$counter = 0;
			$line = 0;
			$formatDate = "%d.%m.%Y";
			$formatTime = "%H:%M";
			$today = strftime( $formatDate );
			$tomorrow  = strftime( $formatDate, strtotime("+1 day", time() ) );
			$currently_displayed_day = 0;

			while ($row = mysql_fetch_assoc($result)) {
				$counter++;
				$line++;
				
				// if end of screen is reached and more than one items left -> cut off and show hint "x more appointments..."
				$rest = (mysql_num_rows($result) - $counter) + 1;
				if (($yoffset >= (imagesy($image) - 36)) && ($rest > 1) || ($line > $max_lines)) {
					$text = "... $rest weitere Termine";
					imagettftextboxopt($image, 14, 0, 24, $yoffset, $style['textcolor'], $style['fontb'], $text, $opt_entry);
					$yoffset += 20;
					break;
				}
				
				// print day name
				$begin_date = strftime( $formatDate, strtotime($row['begin']));
				// if begin day is before today set begin to today
				if (strtotime($begin_date) < strtotime($today))
					$begin_date = $today;
				// now if begin is after $currently_displayed_day update $currently_displayed_day
				if (strtotime($begin_date) > $currently_displayed_day) {
					// update currently_displayed_day
					$currently_displayed_day = strtotime($begin_date);
					// print day name
					if( $begin_date == $today )
						$dayname = "Heute";
					else if( $begin_date == $tomorrow )
						$dayname = "Morgen";
					else
						$dayname = strftime("%A, ".$formatDate, strtotime($begin_date));

					imagettftextboxopt($image, 14, 0, 50, $yoffset+4, $style['textcolor'], $style['fontb'], $dayname, $opt_day);
					$yoffset += 22;
					$line++;
				}
				
				// build appointment time text
				$end_date = strftime( $formatDate, strtotime($row['end']));
				$begin_time = strftime( $formatTime, strtotime($row['begin']));
				$end_time = strftime( $formatTime, strtotime($row['end']));
				$text = $row['title'];
				if ($row['location'] != null)
					$text = $text . ", " . $row['location'];
				if (($begin_time == "00:00") && ($end_time == "00:00")) {
					// all day event (substract 1 second to get the real end date at 23:59) 
					$end_date = strftime( $formatDate, strtotime($row['end'])-1);
					// if all day event is longer than one day -> print end date
					if (strtotime($end_date) != $currently_displayed_day)
						$text = $text." (bis ".$end_date.")";
						
				} else {
					// normal event with start and end time
					$text = $text." (".$begin_time." - ";
					// if event ends not this day -> display end date additionally to time
					if (strtotime($end_date) != $currently_displayed_day)
						$text = $text.$end_date.", ";					
					$text = $text.$end_time.")";
				}
				
				// print appointment text and button
				
				if (strpos($row['title'], 'Geburtstag') !== false)
				{
                                        $icon = ImageCreateFromPNG ( 'resources/icons/birth.png' );
                                        ImageCopy($image, $icon, $xoffset+20, $yoffset-5, 0, 0, imagesx($icon), imagesy($icon));
                                        ImageDestroy($icon);
                                }
                                else
                                {
                                        // determine button color
        				$colorArray = htmlColorToRgb($row['color']);
	        			$color = ImageColorAllocate ($image, $colorArray[0], $colorArray[1], $colorArray[2]);
		                        drawGlassButton($image, $color, 32, $yoffset+8);
                                }
				imagettftextboxopt($image, 12, 0, 50, $yoffset, $style['textcolor'], $style['font'], $text, $opt_entry);
				
				$yoffset += 18;
			}
			$yoffset += 26;
		}
		mysql_free_result($result);
	}

	private function addCalendar($color, $begin, $end, $title, $location) {
		$query = "INSERT INTO `if_calendar` (`id`, `color`, `begin`, `end`, `title`, `location`) 
				  VALUES (NULL,
				  '".mysql_real_escape_string($color)."', FROM_UNIXTIME($begin), FROM_UNIXTIME($end),
				  '".mysql_real_escape_string($title)."',
				  '".mysql_real_escape_string($location)."'
				  )";
		mysql_query($query, $this->dbconn) or die('Error, insert query failed: '.mysql_error());
	}
	
}

?>
 
Hi jnappert,

läuft bei mir auch auf dem Raspi, kein Problem.

Gruß, Michael...
 
Hi jnappert,

läuft bei mir auch auf dem Raspi, kein Problem.

Gruß, Michael...

Na, da habe ich doch schon mal einen Fortschritt. Ich habe Deine .ini verwendet und auch Deinen Code (und natürlich die Werte in der config.ini überschrieben). Zumindest habe ich jetzt mal eine Fehlermeldung: "Die Grafik "//192.168.2.33/infoframe" kann nich angezeigt werden, weil sie Fehler enthält ;-) Gehört jetzt eigentlich hinter den Api-Pfad ein "/" oder nicht? Im Moment habe ich das so: google_api_path = "../google-api-php-client"

Und der Projektname ist bei Google per Standard "Mein Projekt" oder sollte man dort die Projekt ID oder gar die Projektnummer eintragen?
 
Zumindest habe ich jetzt mal eine Fehlermeldung: "Die Grafik "//192.168.2.33/infoframe" kann nich angezeigt werden, weil sie Fehler enthält ;-)
Gut, der Code läuft schon mal durch.

Gehört jetzt eigentlich hinter den Api-Pfad ein "/" oder nicht? Im Moment habe ich das so: google_api_path = "../google-api-php-client"
den Eintrag kannst Du ganz aus der ini entfernen, in meinem Code ist der Pfad zur google-api hart codiert require_once '/usr/share/google-api-php-client-master/autoload.php';

Im allgemeinen, wenn Du Dir nicht sicher bist, mach immer ein "/" dran. Die meisten Betriebssysteme können mit sowas "/level1//level2/" umgehen.

Und der Projektname ist bei Google per Standard "Mein Projekt" oder sollte man dort die Projekt ID oder gar die Projektnummer eintragen?
Korrekt, der Projektname! nicht die ID und auch nicht die Nummer.

Gruß, Michael...
 
Also laut Google-Statistik kommen da jetzt auch Anfragen durch - und werden scheinbar auch in die DB eingetragen. Sobald ich das alte calendar.plugin drüberkopiere erscheinen die Termine auch.
 
Die Anfragen kommen durch, die Termine werden in die Datenbank geschrieben, was willst Du mehr? Ich weiß im Moment nicht, wie ich Dir helfen soll, bzw. wo der Fehler liegen soll. Kannst Du etwas näher definieren, wo der InfoFrame aussteigt? Was sagt der /var/log/apache2/error.log?

Nachtrag:
was heißt denn "scheinbar"? Sind nun Termine in die Datenbank geschrieben oder nicht? Das sollte sich doch feststellen lassen.
 
Zuletzt bearbeitet:
Paketplugin Hermes

Rufe ich die funktion das erstamal auf funktioniert sie hier und ich bekomme ein gefülltes array raus

Hallo Spoon3er,
curl_error ($ch) sagt er hätte ein "SSL certificate problem: unable to get local issuer certificate".
Das kann man mit der Option
PHP:
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
unterbinden.

Gruß, Michael...
 
Top Michael!!!

Damit funktioniert auch die DOM-abfrage wieder.
Komischerweise gibt es ab und an aussetzer bei mir. Mal läuft es das erstemal durch oder erst beim zweiten mal...
Bei dir auch so?
 
Nein, bei mir lief es gar nicht. Ich musste auch curl_setop_array gegen einzelne curl_setopt tauschen. curl_setop_array macht bei mir Probleme.
 
strange:
curl_setopt_array (PHP 5 >= 5.1.3)
curl_setopt (PHP 4 >= 4.0.2, PHP 5)

Deine php-version sollte aber locker > 5.3 sein.... i don´t get it :confused:

hmm evtl php5-curl updaten?
Code:
root@SERVER:~# apt-cache policy  php5-curl
php5-curl:
  Installiert:           5.6.2+dfsg-1
  Installationskandidat: 5.6.2+dfsg-1
  Versionstabelle:
     5.6.3+dfsg-1 0
        750 http://ftp.de.debian.org/debian/ unstable/main amd64 Packages
 *** 5.6.2+dfsg-1 0
        800 http://ftp.de.debian.org/debian/ testing/main amd64 Packages
        100 /var/lib/dpkg/status
     5.4.4-14+deb7u14 0
        300 http://ftp2.de.debian.org/debian/ stable/main amd64 Packages
 
Zuletzt bearbeitet:
Die Anfragen kommen durch, die Termine werden in die Datenbank geschrieben, was willst Du mehr? Ich weiß im Moment nicht, wie ich Dir helfen soll, bzw. wo der Fehler liegen soll. Kannst Du etwas näher definieren, wo der InfoFrame aussteigt? Was sagt der /var/log/apache2/error.log?Nachtrag: was heißt denn "scheinbar"? Sind nun Termine in die Datenbank geschrieben oder nicht? Das sollte sich doch feststellen lassen.

Ist es. Ich habe das alles noch einmal in Ruhe durchgesehen und angepasst. Am Ende waren es zwei Kleinigkeiten - ein falscher Pfad und mein Denkfehler. Vielen Dank - es funzt ;-) Schöne Weihnachtstage:p
 
Hi Spoon3er,
sehr strange. Es ist nicht so, dass PHP den Befehl nicht kennt, es wird alles brav ausgeführt, funktioniert aber nicht.
 
HermesTracking

Hallo Spoon3er, Volker,

die Probleme, die Volker mit dem HermesTracking hatte, waren ähnlich wie bei der DHL Geschichte darin begründet, dass er sein Paket selbst abgeholt hat.
Mit Deiner Erlaubnis die DOM Version Deines Hermestrackings, inklusive Selbstabholung. Es sind nur zwei Zeilen hinzugekommen (//neu) und eine geändert, weil ich Probleme mit den Umlauten hatte (//geändert).

PHP:
    private function hermesTracking($trackingnumber, $id) {
		$i = 0;
		$inhalt = '';
		$bild = '';
		$posi = '';
		$shedule = '';
		$trans = array(
			'an die Hermes Logistik Gruppe' => '',
			'Hermes' => '',
			'Die' => '',
			'Sendung wurde' =>'Sendung ',
			'ist' => '',
			'für den weiteren Transport' => '');
		$patterns = array(
			'übermittelt',
			'verlassen',
			'übernommen',
			'sortiert',
			'eingetroffen',
			'Zustellung',
			'zugestellt',
			// neu
			'abgeholt'); 
		// aktuelle session id holen
		$url = 'https://www.myhermes.de/wps/portal/paket/Home/privatkunden/sendungsverfolgung';
		$ch = curl_init();
		curl_setopt ($ch, CURLOPT_HEADER, 0);
		curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
		curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
		curl_setopt ($ch, CURLOPT_URL, $url);
		$result = curl_exec($ch);
		curl_close($ch);
		preg_match('#<form name="mhStatusForm" id="mhStatusForm" action="(.*?)" onsubmit=.*?>#i', $result, $matches);
		
		// mit aktueller session id  die trackingnummer abfragen
		$url = 'https://www.myhermes.de'.preg_replace('#<!.*>$#', '', $matches[1]).'?action=trace&shipmentID='.$trackingnumber.'&receiptID=';
		$i = 0;
		$xml = new DOMDocument();
		$xml->loadHTMLFile($url, LIBXML_NOBLANKS);
		$xpath = new DOMXPath($xml);
		$table = $xpath->query('//*[@class="content_table table_shipmentDetails"]')->item(0)->childNodes->item(1)->firstChild;
		
		//  var_dump($table);
		if($table->hasChildNodes()) {
			$stat_txt = trim(preg_replace('#\s+#', ' ', utf8_decode($table->childNodes->item(4)->nodeValue)));
			$stat_txt = strtr($stat_txt, $trans);
			if ($stat_txt == ' Sendung  auf Tour gegangen') {
				$stat_txt = 'Sendung in Zustellung';
			}
			foreach ($patterns as $pattern) {
				if(strpos($stat_txt, $pattern) !== FALSE) {
					$posi = array_search($pattern, $patterns);
					for ($k=0; $k<=$posi; $k++) {
                                                // geändert utf8_encode hinzugefügt
						$bild[$k] = 'resources/icons/tracking/hermes_'.utf8_encode($patterns[$k]).'.png';
					}
				}
			}
            if (($posi >= 2) AND ($posi <= 3)) unset($bild[1]);
			if ($posi >= 4) unset($bild[1], $bild[3]);
			// neu
			if ($posi == 7) unset ($bild[7]);
			$bild = array_values ($bild);
		}
		else {
			$stat_txt = 'Sendung nicht gefunden';
			$datum = date('d.m.Y H:m:s', time());
		}
		return array($stat_txt, $datum, $bild, $id, $posi);
	}

@Volker,
bitte so gegen Deine alte funktion im PaketPlugin austauschen.

Gruß, Michael...
 
Zuletzt bearbeitet:
Hallo zusammen
So es funktioniert endlich ,vielen vielen Dank an marvin424 für seine Hilfe und natürlich auch an Spoo3ner ,der uns auch tatkräftig unterstützt hat.
Hier jetzt das funktionierende PaketPlugin
PHP:
<?php
/***************************************************************************
 * InfoFrame (image generator for digital picture frames)
 * Copyright (C) 2009  Tobias Kolb
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see http://www.gnu.org/licenses/
 ***************************************************************************/

class PaketPlugin implements IPlugin
{
  private $dbconn = NULL;
	private $config = NULL;
	
	public function __construct($dbconn, $config) {
		$this->dbconn = $dbconn;
		$this->config = $config;		
	}
		
	
public function doUpdate() {
	// hole Dienstleister aus der Datenbank
	$query = "SELECT * FROM if_paket";
	$result = mysql_query($query, $this->dbconn)or die(mysql_error());
if (mysql_num_rows($result) == 0) return;
	 	while ($row = mysql_fetch_assoc($result)) {
	 		$id = $row['ID'];
	 		$trackingnumber = $row['paketnummer'];
	 		if ($row['dienst'] == 'DHL') {
	 			list($stat_txt, $datum, $bild, $id, $posi, $shedule) = $this->dhlTracking($trackingnumber, $id);
						
      } elseif($row['dienst'] == 'GLS') {
     		list($stat_txt, $datum, $bild, $id, $posi, $shedule) = $this->glsTracking($trackingnumber, $id);
    	
      } elseif($row['dienst'] == 'hermes') {
     		list($stat_txt, $datum, $bild, $id, $posi, $shedule) = $this->hermesTracking($trackingnumber, $id);
    	
      } elseif($row['dienst'] == 'UPS') {
     		list($stat_txt, $datum, $bild, $id, $posi, $shedule) = $this->upsTracking($trackingnumber, $id);
     	
      } elseif($row['dienst'] == 'DPD') {
     	  list($stat_txt, $datum, $bild, $id, $posi, $shedule) = $this->dpdTracking($trackingnumber, $id);
     
      } elseif($row['dienst'] == 'TNT') {
     	    return;
     
     }    
       $this->addPaket($stat_txt, $datum, $bild, $id, $posi, $shedule);    	
    }
    mysql_free_result($result);
  }	


public function doOutput($image, $style, $updateData, &$yoffset) {	
	 
    if ($updateData)
           	$this->doUpdate();

		$query = "SELECT * FROM `if_paket`";
		$result = mysql_query($query, $this->dbconn);
		if (mysql_num_rows($result) == 0) return;
		
		// define styles
		$opt_header = array(
			'width' => imagesx($image)-290,
			'line_height' => 18,
			'align' => ALIGN_LEFT
		);
		
		$opt_entry = array(
			'width' => imagesx($image)-290,
			'height' => 12,
			'line_height' => 12,
			'align' => ALIGN_LEFT,
			'word_wrap_hyphen' => '...',
			'aggressive_word_wrap' => TRUE,
		);
		
/********************************************* Roundboxtrans funktioniert, fuer upload daektiviert************************		
		$entrylimit = $this->config['max_displayed_trackings'];
    $db_zeilenc = mysql_num_rows($result);
  	$db_zeilen = $db_zeilenc;
  	if ($entrylimit < $db_zeilenc) $db_zeilen = $entrylimit+1;
 // 	if ($row['liefertermin']) $db_zeilen = $db_zeilen+1;
  	$ba = 8;
   	$ue_hoehe = 18;
   	$inhalt_hoehe = 18;
   if ( (mysql_num_rows($result) <= 2) && ($yoffset <= (imagesy($image)-60)) ) $inhalt_hoehe = 60;  
	  roundbox_trans($image, 0, 0, 0, 0, 0, 0, $ba, $db_zeilen, $ue_hoehe, $inhalt_hoehe, $yoffset);
******************************************************************************************************************************/
											
		// print header
		$text = 'Paketverfolgung';
		imagettftextboxopt($image, 18, 0, 40, $yoffset, $style['textcolor'], $style['font'], $text, $opt_header);
	  $icon = ImageCreateFromPNG ( 'resources/icons/tracking.png' );
		ImageCopy($image, $icon, 8, $yoffset-3, 0, 0, imagesx($icon), imagesy($icon));
		ImageDestroy($icon);
		$yoffset += 25;
								
	 // print entries
		$counter = 0;
    while ($row = mysql_fetch_assoc($result)) {
         $counter++;
         $rest = (mysql_num_rows($result) - $counter) + 1;
							if ( (($entrylimit) && ($counter > $entrylimit)) || (($yoffset >= (imagesy($image) - 25)) && ($rest > 1)) ) {
								  if ($rest > 1)
                    $text = "... $rest weitere Pakete";
                else
                    $text = "... $rest weiteres Paket";
                
								imagettftextboxopt($image, 12, 0, 30, $yoffset, $style['textcolor'], $style['fontb'], $text, $opt_entry);
								$yoffset += 15;
								break;
							}	
				if ($row['datum'] and $row['status'])	{	
					// print entry text
					$text = $row['datum'].'Uhr:  '.$row['status'];
					// dirty trick for replacing inch-symbol \xE2\x80\xB3 by nomal " (because not supported by imagettftext)
					$text = str_replace("\xE2\x80\xB3", "\"", $text);
				} else {
					$text = 'Sendung  "'.$row['paketnummer'].'"  nicht gefunden!';
				}	
	//*********************************gro�e Symbole wenn weniger als 2 Trackings gleichzeitig und mehr als 60px Platz	*************	
				if ( ((mysql_num_rows($result) <= 2) && ($yoffset <= (imagesy($image)-60))) ) {
					$xoffset = 0;
					$bilder = explode('|', $row['bild']);	
					if ( ($row['dienst'] == "UPS") || ($row['dienst'] == "DPD") ){ 
									$bild = $bilder[$row['position']];
									$icon = ImageCreateFromPng($bild);
									ImageCopy($image, $icon, 45+$xoffset, $yoffset+5, 0, 0, imagesx($icon), imagesy($icon));
    							ImageDestroy($icon);						
						}else{					
							if (($row['dienst']) == "GLS") { 
          				$xoffset += 75; 				
							} elseif ( ($row['dienst'] == "DHL") || ($row['dienst'] == "hermes") ){ 
									$xoffset += 45;								
									for ($i=0; $i<=$row['position']; $i++) {										
										$bild = $bilder[$i];
										$icon = ImageCreateFromPng($bild);
										ImageCopy($image, $icon, 45+($xoffset*$i), $yoffset+5, 0, 0, imagesx($icon), imagesy($icon));
    								ImageDestroy($icon);
    							}
    						}
    					}							
					imagettftextboxopt($image, 11, 0, 43, $yoffset+45, $style['textcolor'], $style['fontb'], $text, $opt_entry);
					if ($row['liefertermin']) {
								$yoffset += 13;
								imagettftextboxopt($image, 11, 0, 43, $yoffset+45, $style['textcolor'], $style['fontb'], $row['liefertermin'], $opt_entry);
				 }
					$yoffset += 60;
  //*********************************************************************************************************************************************					
        } else {	
				$xoffset = 0;	
  // ***********************************icons nach dienstleister, wenn mehr als 3 pakete oder weniger als 60px platz ****************************
				if (($row['dienst']) == "DHL") {
             $icon = ImageCreateFromPNG('resources/icons/dhl_logo.png');
             $xoffset = 6;
           } elseif (($row['dienst']) == "GLS") {
             $icon = ImageCreateFromPNG('resources/icons/gls_logo.png');
           } elseif (($row['dienst']) == "UPS") {          	 
             $icon = ImageCreateFromPNG('resources/icons/ups_logo.png');
             $xoffset = -2;
           } elseif (($row['dienst']) == "DPD") {
             $icon = ImageCreateFromPNG('resources/icons/dpd_logo.png');
             $xoffset = 3;  
           } elseif (($row['dienst']) == "TNT") {
             $icon = ImageCreateFromPNG('resources/icons/tnt_logo.png');
             $xoffset = 12; 
           } elseif (($row['dienst']) == "hermes") {
             $icon = ImageCreateFromPNG('resources/icons/hermes_logo.png');
             $xoffset = 4;  
           } else {
           	 $icon = ImageCreateFromPNG('resources/icons/lieferung.png');
           } 
  //********************************************************************************************************************************************                                    
				ImageCopy($image, $icon, 23-$xoffset, $yoffset+0, 0, 0, imagesx($icon), imagesy($icon));
        ImageDestroy($icon);
				imagettftextboxopt($image, 11, 0, 55, $yoffset, $style['textcolor'], $style['font'], $text, $opt_entry);
				$yoffset += 18;
				}
	}
		$yoffset += 10;	
		
}

// eigentliche Tracking funtionen
	private function glsTracking($trackingnumber, $id) {
		$datum=$stat_txt=$bild=$posi=$shedule='';
		$bild_name = array('erfasst', 'Transport', 'Zustellung', 'zugestellt');
		$bild_nr = array('0', '1', '2', '3');
		$stat_bild = array(
									'erfasst' => array('Paket erfasst', 'Paket eingeliefert'),
 									'Transport' => array('Transport', 'Paket am Umschlagplatz', 'Paket im Zielland', 'Paket hat Deutschland verlassen', 'Paket in der Verzollung', 'Paket im Zieldepot'),
 									'Zustellung' => 'Paket in Zustellung', 
 									'zugestellt' => array("Paket zugestellt", 'Im PaketShop zugestellt', 'Zwischenlagerung im GLS-Depot', 'Zustellung nicht m�glich')
 								  );
 		$url ='http://www.gls-germany.com/de/online/paketstatus_xml.php3?datatype=paketnr&filter=all&paketliste[0]='.$trackingnumber;
		$glsxml = file_get_contents($url);
		$glsxml = simplexml_load_string($glsxml);
		if(!empty($glsxml)) {
			$path = '/paketstatus/paketdaten';
				if (!$glsxml = $glsxml->xpath($path)) {
					return;
				} else {
						$stat_txt = $glsxml[0]->stat_txt;
						$stat_txt = $this->glsStatusReplace($stat_txt);
        		$datum = $glsxml[0]->ps_dat.' '.$glsxml[0]->ps_zeit;
						$posi = str_replace($bild_name, $bild_nr, recursive_array_search($stat_txt, $stat_bild));
 						for ($i=0; $i<=$posi; $i++) {
	 						$bild[$i] = 'resources/icons/gls_'.$bild_name[$i].'.png';
 							if ($i == '3') {
 									if ($stat_txt == 'Paket zugestellt') $bild[$i] = 'resources/icons/gls_zugestellt.png';								 
 									if (strpos($stat_txt, 'PaketShop') !== FALSE) $bild[$i] = 'resources/icons/gls_paketshop.png';
 									if (strpos($stat_txt, 'Zwischenlagerung') !== FALSE) $bild[$i] = 'resources/icons/gls_zwischenlagerung.png';
 									if (strpos($stat_txt, 'nicht') !== FALSE) $bild[$i] = 'resources/icons/gls_nicht.png'; 									 
 							}
     		   	}     		   					
 	 	 		}        		        		
    }
    return array($stat_txt, $datum, $bild, $id, $posi, $shedule);
 }	
 
	
        private function dhlTracking($trackingnumber, $id) {
           $i=0; $datum=$stat_txt=$inhalt=$posi=$bild=$shedule='';
           $i=0; $datum=$stat_txt=$inhalt=$posi=$bild=$shedule='';
           $trans = array('Die ' => '', 'wurde ' => '', 'zu dieser Sendung wurden vom Absender ' => '', 'an DHL ' => '', 'im Zustell-Depot ' => '');
            $stat_bild = array('eingeliefert' => array('Auftragsdaten elektronisch �bermittelt', 'Paket eingeliefert', 'Sendung vom Absender in der Filiale eingeliefert'),
                                                  'transport' => array('Sendung wird zum Paketzentrum transportiert', 'Sendung wird zum Ziel-Paketzentrum transportiert', 'Sendung im Start-Paketzentrum bearbeitet', 'Auslands-Sendung im Start-Paketzentrum bearbeitet', 'Auslands-Sendung wird zum Export-Paketzentrum transportiert',
                                                                                              'Auslandssendung im Export-Paketzentrum bearbeitet'),
                                                  'Paketzentrum' => array('Sendung im Ziel-Paketzentrum bearbeitet', 'Sendung im Paketzentrum bearbeitet', 'Sendung wird zur Zustellbasis transportiert', 'Auslands-Sendung wird f�r den Transport ins Zielland vorbereitet',
                                                                                                   'Sendung ist im Zielland eingetroffen', 'Sendung hat das Import-Paketzentrum im Zielland verlassen'),
                                                  'Zustellung' => array('Zustellung', 'Sendung in das Zustellfahrzeug geladen', 'Sendung wird f�r die Zustellung vorbereitet', 'Sendung konnte nicht zugestellt werden, da der Empf�nger nicht angetroffen wurde, und wird gelagert. Der Empf�nger benachrichtigt'),
                                                  'zugestellt' => array('Sendung erfolgreich zugestellt', 'Der Empf�nger hat die Sendung in der Filiale abgeholt')
                                                 );
           $bild_name = array(0 => 'eingeliefert', 1 => 'transport', 2 => 'Paketzentrum', 3 => 'Zustellung', 4 => 'zugestellt');    
            $url = 'http://nolp.dhl.de/nextt-online-public/set_identcodes.do?lang=de&idc='.$trackingnumber;
          $xml = new DOMDocument();
          $xml->loadHTMLFile($url);
          $xpath = new DOMXPath($xml);              
          foreach($xpath->query('//*[@class="mm_bold text-right"]') as $div) {
              $datum = $this->after(', ', $div->nodeValue);
              if ($datum) {
                //$stat_txt = trim(str_replace('.','',($xpath->query('//*[@class="mm_delivered"]')->item(0)->nodeValue)));
                  $stat_txt = trim(str_replace('.','',(utf8_decode($xpath->query('//*[@class="mm_delivered"]')->item(0)->nodeValue))));  
                //echo "Text: ".$datum. " - ".$stat_txt.PHP_EOL;

                if ( ($stat_txt) AND (strpos($stat_txt, 'Paketzentrum transportiert') !== FALSE) AND (strpos($stat_txt, 'Start-Paketzentrum bearbeitet') !== FALSE) ) {
                              $stat_txt = strtr($stat_txt, $trans);
                      } else {    
                            $stat_txt = strtr($stat_txt, $trans);
                    }                                
                    $posi = array_search(recursive_array_search($stat_txt, $stat_bild), $bild_name);
                        for ($i=0; $i<=$posi; $i++) {
                                    if ( ($i==0) AND (strpos($stat_txt, '�bermittelt') !== FALSE) ) {
                                        $bild[$i] = 'resources/icons/dhl_�bermittelt.png';
                                    }elseif ( ($i>=1) AND ((strpos($stat_txt, 'Auslandssendung') !== FALSE) OR (strpos($stat_txt, 'Zielland') !== FALSE)) ) {
                                        $bild[$i] = 'resources/icons/dhl_ausland_'.$bild_name[$i].'.png';
                                    }else {
                                        $bild[$i] = 'resources/icons/dhl_'.$bild_name[$i].'.png';
                                    }
                                }
                    return array($stat_txt, $datum, $bild, $id, $posi);                                                                                                                                      
                 }    else    {
                        $stat_txt = 'Sendung nicht gefunden';
                        $datum = date('d.m.Y H:m:s', time());
                }
            }                 
            return array($stat_txt, $datum, $bild, $id, $posi);
    }  

	
	private function upsTracking($trackingnumber, $id) {
			$i=0; $datum=$stat_txt=$posi=$bild=$content=$shedule='';
			$search = array('&nbsp;', 'On:', 'To:', 'at ', '. ', ' P�nktlich', ',');
			$replace = array('', '|', '|', '', '', '', ' ');
	 		$url = 'http://wwwapps.ups.com/ietracking/tracking.cgi?tracknum='.$trackingnumber.'&IATA=de&Lang=ger';
	 		$bild_name = array(0 => 'erfasst', 1 => 'Transport', 2 => 'Zustellung', 3 => 'zugestellt', 4 =>'fehler');
			$stat_bild = array(
									'erfasst' => array('Auftrag bearbeitet: F�r UPS bereit', 'Scan in der Abholniederlassung'),
 									'Transport' => array('Paket wird transportiert', 'Zollabfertigung abgeschlossen', 'Zollabfertigung l�uft', 'Umschlagplatz ausgang', 'Bestimmungsort-Scan'),
 									'Zustellung' => 'Paket in der Zustellung', 
 									'zugestellt' => array('Paket zugestellt', 'Im �rtlichen Postamt', 'Abgabe in einem UPS Store', 'F�r die Zustellung an das �rtliche Postamt �bergeben'),
 									'fehler' => array('Ausnahme: Aktion erforderlich', 'Ausnahme', 'Zustellung nicht m�glich',  'Zur�ckgesendet an Absender', 'Zur�ck an den Absender', 'Sendungsinformationen storniert')
 								  );	 		
			$file = fopen ($url,"r");
			if (!$file) {
				return;// 
			} else {
				while (!feof($file)) {
					$zeile[$i++] = fgets($file);
				}
				fclose($file);
			}
			for ($j=0; $j<$i; $j++) {
		  $content .= trim($zeile[$j]);
		 }
			if ($content) {
				
				preg_match('#<td class="nowrap">(.*?)</td><td class="nowrap">(\d{2}/\d{2}/\d{4})</td><td class="nowrap">(\d{1,2}:\d{2}\s[A|P]\.M\.)</td><td>(.*?)</td>#', $content, $matches);
				preg_match('#Scheduled Delivery:</label></dt><dd>(.*?),(.*?)(\d{2}/\d{2}/\d{4}),(.*?)</dd>#', $content, $match);
				if ($match) {
						 $shedule_date = datumDeutsch($match[1]).'  '.strftime('%d.%m.%Y', strtotime($match[3]));						
					   $shedule = 'Voraussichtliche Lieferung:  '.$shedule_date;
					}				
					$ups_stat_txt = str_replace($search, $replace, $this->upsStatusReplace($matches[4]));					
					$datum = strftime('%d.%m.%Y - %H:%m', strtotime($matches[2].$matches[3]));
					$posi = array_search(recursive_array_search($ups_stat_txt, $stat_bild), $bild_name);
					$stat_txt = $matches[1].': '.$ups_stat_txt;
					for ($i=0; $i<=$posi; $i++)
	 									$bild[$i] = 'resources/icons/ups_'.$bild_name[$i].'.png';						
			}	else	{
					$stat_txt = 'Sendung nicht gefunden';
					$datum = date('d.m.Y H:m:s', time());			
			}				
				return array($stat_txt, $datum, $bild, $id, $posi, $shedule);	
		}
	
	private function dpdTracking($trackingnumber, $id) {
   		$i=0; $zeit=$status=$shedule=$posi=$bild=$inhalt='';
   		$trans = array('&nbsp;' => '', '&bull;' => '');
   		$bild_name = array(0 => 'Eingang', 1 => 'Transport', 2 => 'Auslieferung', 3 => 'zugestellt', 4 =>'fehler');
   		$stat_bild = array(
   								 'Eingang' => array('Einrollung', 'Erfasst'),
   								 'Transport' => array('Eingang', 'HUB-Durchlauf', 'In Verzollung', 'Konsolidierung'),
   								 'Auslieferung' => array('Lager', 'Ausrollung'),
   								 'zugestellt' => array('Zustellung', 'zugestellt'),
   								 'fehler' => array('Zustellversuch nicht erfolgreich', 'System-Retoure', 'Ausrollretoure')
   								 );
			$uri  = '/cgi-bin/delistrack?typ=1&lang=de&pknr='.$trackingnumber;
			$sock = fsockopen("extranet.dpd.de", 80, $errno, $errstr, 5); // 80 = Port, 5 = Timeout
			if (!$sock) {
				return;
			} else {
				fputs($sock, "GET ".$uri." HTTP/1.1\r\n");
				fputs($sock, "User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.2.1) Gecko/20021204\r\n");
				fputs($sock, "Host: www.extranet.dpd.de\r\n");
				fputs($sock, "Connection: close\r\n\r\n");
				while(!feof($sock)) {					
					$zeile[$i++] = trim(fgets($sock));
				}
				fclose($sock);
			}
		for ($j=5; $j<$i; $j++) {
		$inhalt .= strip_tags(trim($zeile[$j]), '<td><b>'); 
	 }
	 if ($inhalt) {
			$inhalt = strtr($inhalt, $trans);
			preg_match_all('#(\d{2}\.\d{2}\.\d{4}\s\d{1,2}:\d{2})(.*?)</b>(.*?)</td><td style="padding-left: 10px;">(.*?)</td>#is', $inhalt, $matches);
			$last_matches = array_reverse_recursive($matches); 
			$dpd_stat_txt = $last_matches[0][0];
			if (strpos($last_matches[0][0], 'Zustellung') !== FALSE ){ 
					$last_matches[0][0] = str_replace('Zustellung', 'zugestellt',(substr($last_matches[0][0], 12)));
					$dpd_stat_txt = 'zugestellt';
			}
			$stat_txt = $last_matches[0][0].'  '.$last_matches[1][0];
			$datum = $last_matches[3][0];
			$posi = array_search(recursive_array_search($dpd_stat_txt, $stat_bild), $bild_name);
			for ($i=0; $i<=$posi; $i++)
	 		 					$bild[$i] = 'resources/icons/ups_'.$bild_name[$i].'.png';
	 		}	else {
					$stat_txt = 'Sendung nicht gefunden';
					$datum = date('d.m.Y H:m:s', time());			
			}			 			
		 				 
		 return array($stat_txt, $datum, $bild, $id, $posi, $shedule);
 }
 
    private function hermesTracking($trackingnumber, $id) {
        $i = 0;
        $inhalt = '';
        $bild = '';
        $posi = '';
        $shedule = '';
        $trans = array(
            'an die Hermes Logistik Gruppe' => '',
            'Hermes' => '',
            'Die' => '',
            'Sendung wurde' =>'Sendung ',
            'ist' => '',
            'für den weiteren Transport' => '');
        $patterns = array(
            'übermittelt',
            'verlassen',
            'übernommen',
            'sortiert',
            'eingetroffen',
            'Zustellung',
            'zugestellt',
            // neu
            'abgeholt'); 
        // aktuelle session id holen
        $url = 'https://www.myhermes.de/wps/portal/paket/Home/privatkunden/sendungsverfolgung';
        $ch = curl_init();
        curl_setopt ($ch, CURLOPT_HEADER, 0);
        curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
        curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
        curl_setopt ($ch, CURLOPT_URL, $url);
        $result = curl_exec($ch);
        curl_close($ch);
        preg_match('#<form name="mhStatusForm" id="mhStatusForm" action="(.*?)" onsubmit=.*?>#i', $result, $matches);
        
        // mit aktueller session id  die trackingnummer abfragen
        $url = 'https://www.myhermes.de'.preg_replace('#<!.*>$#', '', $matches[1]).'?action=trace&shipmentID='.$trackingnumber.'&receiptID=';
        $i = 0;
        $xml = new DOMDocument();
        $xml->loadHTMLFile($url, LIBXML_NOBLANKS);
        $xpath = new DOMXPath($xml);
        $table = $xpath->query('//*[@class="content_table table_shipmentDetails"]')->item(0)->childNodes->item(1)->firstChild;
        
        //  var_dump($table);
        if($table->hasChildNodes()) {
		    $datum = trim(preg_replace('#\s+#', ' ', $table->childNodes->item(0)->nodeValue.' '.$table->childNodes->item(2)->nodeValue)); 
            $stat_txt = trim(preg_replace('#\s+#', ' ', utf8_decode($table->childNodes->item(4)->nodeValue)));
            $stat_txt = strtr($stat_txt, $trans);
            if ($stat_txt == ' Sendung  auf Tour gegangen') {
                $stat_txt = 'Sendung in Zustellung';
            }
            foreach ($patterns as $pattern) {
                if(strpos($stat_txt, $pattern) !== FALSE) {
                    $posi = array_search($pattern, $patterns);
                    for ($k=0; $k<=$posi; $k++) {
                                                // geändert utf8_encode hinzugefügt
                        $bild[$k] = 'resources/icons/hermes_'.utf8_decode($patterns[$k]).'.png';
                    }
                }
            }
            if (($posi >= 2) AND ($posi <= 3)) unset($bild[1]);
            if ($posi >= 4) unset($bild[1], $bild[3]);
            // neu
            if ($posi == 7) unset ($bild[7]);
            $bild = array_values ($bild);
        }
        else {
            $stat_txt = 'Sendung nicht gefunden';
            $datum = date('d.m.Y H:m:s', time());
        }
        return array($stat_txt, $datum, $bild, $id, $posi);
    }  

// Ausgabe Bereinigung, falls zu un�bersichtlich in der Trackingfunktion selber	
  private function glsStatusReplace($stat_txt) {
  $glsStatus = array('HSC: Abgabe Empfaenger', 'HSC: Rollkartenscannung', 'Eingang I-Punkt EPL', 'ZUP-Durchlauf NORMAL', 'Eingang APL I-Punkt', 'NIF-Eingang', 'NIF-Ausgang', 'Kunde nicht angetroffen',
  									 'PK im Verzollungsprozess', 'Paket im Lager', 'STAT_DEFAULT', 'Fix-Termin', 'Adresse falsch', 'RUP-Durchlauf'
  									 );
  $normalisiert = array('Paket zugestellt', 'Paket in Zustellung', 'Paket im Zieldepot', 'Paket am Umschlagplatz', 'Paket eingeliefert', 'Paket im Zielland', 'Paket hat Deutschland verlassen', 'Kunde nicht angetroffen',
  											'Paket in der Verzollung', 'Zwischenlagerung im GLS-Depot', 'Paket erfasst', 'Termin mit Kunden', 'Adresse falsch', 'Paket am Umschlagplatz'
  											);
	return str_replace($glsStatus, $normalisiert, $stat_txt);
 }
 
  private function upsStatusReplace($stat_txt){
	$englisch = array('Delivered', 'In Transit', 'Out For Delivery', 'Arrival Scan', 'At Local Post Office', 'Clearance Completed', 'Clearance in Progress', 'Departure Scan', 
										'Destination Scan', 'Dropped off at a UPS Retail Location', 'Exception: Action Required', 'Exception', 'Order Processed: Ready for UPS', 'Origin Scan',
										'Returned to Sender', 'Returning to Sender', 'Shipment Information Voided', 'Transferred to Local Post Office for Delivery', 'On Time'
										);
	$deutsch = array('Paket zugestellt', 'Paket wird transportiert', 'Paket in der Zustellung', 'Umschlagplatz eingang', 'Im �rtlichen Postamt', 'Zollabfertigung abgeschlossen', 'Zollabfertigung l�uft', 'Umschlagplatz ausgang', 
									 'Bestimmungsort-Scan', 'Abgabe in einem UPS Store', 'Ausnahme: Aktion erforderlich', 'Ausnahme', 'Auftrag bearbeitet: F�r UPS bereit', 'Scan in der Abholniederlassung',
									 'Zur�ckgesendet an Absender', 'Zur�ck an den Absender', 'Sendungsinformationen storniert', 'F�r die Zustellung an das �rtliche Postamt �bergeben', 'P�nktlich'
									 );
   	return str_replace($englisch, $deutsch, $stat_txt);
 }
 
    private function recursive_array_search($needle, $haystack) {
    foreach($haystack as $key => $value) {
        $current_key = $key;
        if($needle === $value OR (is_array($value) && recursive_array_search($needle, $value) !== FALSE)) {
            return $current_key;
        }
    }
    return false;
    }

    private function array_reverse_recursive($arr) {
    foreach ($arr as $key => $val) {
        if (is_array($val))
            $arr[$key] = array_reverse_recursive($val);
    }
    return array_reverse($arr);
}

    private function after ($needle, $inthat){
        if (!is_bool(strpos($inthat, $needle)))
        return substr($inthat, strpos($inthat,$needle)+strlen($needle));
 } 

 
// In die Datenbank schreiben
	private function addPaket($stat_txt, $datum, $bild, $id, $posi, $shedule) {	 				
 		$bild = implode('|',$bild);
		if ( (strpos($stat_txt, 'zugestellt') !== FALSE) and (time() - strtotime($datum) >= 36000) ) {
					$query = "DELETE FROM `if_paket` WHERE id='$id'";
			}else{ 		
 				$query = "UPDATE `if_paket` SET datum='".mysql_real_escape_string($datum)."', status='".mysql_real_escape_string($stat_txt)."', bild='".mysql_real_escape_string($bild)."', position='$posi', liefertermin='".mysql_real_escape_string($shedule)."' WHERE id='$id'";
			}
	   	mysql_query($query, $this->dbconn) or die ('PaketPlugin'.mysql_error());
 }

}



?>

Also ich freu mich ,das jetzt DHL und Hermes bei mir wieder funktionieren!!!:D:D:D:D:D

Eine Kleinigkeit habe ich allerdings noch.Beim Testen ist mir aufgefallen, das beim Benzinplugin als Änderungsdatum immer der 30.11.steht.Die Aktuallisierung der Preise stimmt aber, nur das Datum nicht.
In der Datenbank steht als Datum der 30.11.1999.
Gibt es dafür auch noch ne Lösung??

Volker
 
wer von euch verwendet ein Tablet als Anzeige! Ich z.B. verwende eines..habe das aber glaube ich etwas umständlich gelöst....habe firefox drauf. Damit rufe ich die Seite 192.168.178.1:5050 auf. Die index.php habe ich so eingestellt, dass sich die Seite alle zwei Sekunden refreshed.

Jetzt habe ich hier im Thread irgendwo gelesen, dass es mit einem App "Digitaler Fotorahmen" auch funktionieren soll?!

Kann hier jemand ein Statement abgeben - Oder Vorschläge wie sich das eleganter lösen lässt, wie meine Vorgehensweise?

Danke
 
Holen Sie sich 3CX - völlig kostenlos!
Verbinden Sie Ihr Team und Ihre Kunden Telefonie Livechat Videokonferenzen

Gehostet oder selbst-verwaltet. Für bis zu 10 Nutzer dauerhaft kostenlos. Keine Kreditkartendetails erforderlich. Ohne Risiko testen.

3CX
Für diese E-Mail-Adresse besteht bereits ein 3CX-Konto. Sie werden zum Kundenportal weitergeleitet, wo Sie sich anmelden oder Ihr Passwort zurücksetzen können, falls Sie dieses vergessen haben.