====== Tado° ReST-API - Heizungssteuerung mit PHP ====== Die Firma tado GmbH produziert smarte Heizkörper-Thermostate, die sehr einfach gegen herkömmliche manuelle Thermostate ausgetauscht werden können. Neben den zahlreichen Features, welche die tado APP anbietet, besteht auch die Möglichkeit, die Thermostate über eine ReST-API anzusprechen. Mit der folgenden PHP-Klasse ist es möglich, die Thermostate per PHP auszulesen und zu steuern. Um die Klasse benutzen zu können sind hier noch Benutzername und Passwort zu ergänzen, wobei der Benutzername der E-Mail-Adresse, mit der Ihr Konto bei Tado angelegt wurde, entspricht. class Tado { const PRESENCE_HOME = 'HOME'; const PRESENCE_AWAY = 'AWAY'; private $token = ''; private $homeId = 0; private $zones = []; private $endpoint = ''; private $username = ''; private $password = ''; public function __construct() { $content = file_get_contents( 'https://my.tado.com/webapp/env.js' ); foreach( [ 'tgaRestApiV2Endpoint', 'apiEndpoint', 'clientId', 'clientSecret' ] as $var ) { preg_match( sprintf( "/%s: '(.*)'/", $var ), $content, $matches ); if( count( $matches ) === 2 ) { $parameter[] = $matches[1]; } } $this->endpoint = $parameter[0]; $this->setBearerToken( $parameter ); $this->setHomeId(); $this->setZones(); } private function setBearerToken( $parameter ) { $data['client_id'] = $parameter[2]; $data['client_secret'] = $parameter[3]; $data['grant_type'] = 'password'; $data['scope'] = 'home.user'; $data['username'] = $this->username; $data['password'] = $this->password; $result = $this->curl( $parameter[1] . '/token', 'POST', $data ); if( isset( $result->access_token ) ) { $this->token = $result->access_token; } } private function setHomeId() { $result = $this->curl( $this->endpoint . '/me', 'GET' ); $this->homeId = $result->homes[0]->id; } private function setZones() { $result = $this->curl( sprintf( $this->endpoint . '/homes/%s/zones', $this->homeId ), 'GET' ); $this->zones = $result; } /** * @param $name * @return integer|false */ private function getZoneId( $name ) { foreach( $this->zones as $zone ) { if( utf8_decode( $zone->name ) === $name ) { return $zone->id; } } return false; } public function getSetting( $zone = null ) { if( $zone === null ) { $path = sprintf( $this->endpoint . '/homes/%s/state', $this->homeId, $zone ); return $this->curl( $path, 'GET' ); } $path = sprintf( $this->endpoint . '/homes/%s/zones/%d/state', $this->homeId, $zone ); $result = $this->curl( $path, 'GET' ); unset( $result->setting->temperature->fahrenheit ); return $result->setting; } public function setPresence( $presence ) { $data = new stdClass(); $data->homePresence = $presence; $path = sprintf( $this->endpoint . '/homes/%s/presenceLock', $this->homeId ); $this->curl( $path, 'PUT', $data ); } /** * @param string $room * @param float $grad * @param integer $duration */ public function updateTemperature( string $room, float $grad, $duration = 0 ) { $zone = $this->getZoneId( $room ); if( $zone === false ) { return; } $setting = $this->getSetting( $zone ); $setting->type = 'HEATING'; $setting->temperature->celsius = $grad; $data = new stdClass(); $data->setting = $setting; $data->termination = new stdClass(); if( $duration === 0 ) { $data->termination->type = 'MANUAL'; } else { $data->termination->type = 'TIMER'; $data->termination->durationInSeconds = $duration; } $this->curl( sprintf( $this->endpoint . '/homes/%s/zones/%d/overlay', $this->homeId, $zone ), 'PUT', $data ); } /** * @param string $room */ public function removeManualControl( $room ) { $zone = $this->getZoneId( $room ); if( $zone === false ) { return; } $this->curl( sprintf( $this->endpoint . '/homes/%s/zones/%d/overlay', $this->homeId, $zone ), 'DELETE' ); } public function curl( $path, $method, $data = '' ) { $ch = curl_init( $path ); if( ! empty( $this->token ) ) { $header[] ='Authorization: Bearer ' . $this->token; if( $method === 'PUT' ) { $header[] ='Content-Type:application/json;charset=UTF-8'; } curl_setopt ($ch, CURLOPT_HTTPHEADER, $header ); } curl_setopt( $ch, CURLOPT_URL, $path ); curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true ); curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, $method ); if( ! empty( $data ) ) { if( $method === 'PUT' ) { curl_setopt( $ch, CURLOPT_POSTFIELDS, json_encode( $data ) ); } else { curl_setopt( $ch, CURLOPT_POSTFIELDS, http_build_query( $data ) ); } } $json = curl_exec( $ch ); curl_close( $ch ); return json_decode( $json ); } } ==== Beispiel 1: Temperatur im Büro dauerhaft auf 20 Grad stellen ==== $tado = new Tado; $tado->updateTemperature( 'Büro', 20 ); ==== Beispiel 2: Temperatur im Wohnzimmer für 90 Minuten auf 18 Grad stellen ==== Hinweis: Die Dauer wird in Sekunden übergeben (90 Minuten = 5400 Sekunden): $tado = new Tado; $tado->updateTemperature( 'Wohnzimmer', 18, 5400 ); ==== Beispiel 3: Manuelle Steuerung im Wohnzimmer entfernen (intelligenter Zeitplan wird wieder aktiviert) ==== $tado = new Tado; $tado->removeManualControl( 'Wohnzimmer' ); ==== Beispiel 4: Status "HOME" setzen ==== $tado = new Tado; $tado->setPresence( tado::PRESENCE_HOME ); ==== Beispiel 5: Status "AWAY" setzen ==== $tado = new Tado; $tado->setPresence( tado::PRESENCE_AWAY ); ==== Weiterführende Links ==== * [[http://blog.scphillips.com/posts/2017/01/the-tado-api-v2/|The Tado API v2]] * [[https://shkspr.mobi/blog/2019/02/tado-api-guide-updated-for-2019/|Tado API Guide von Terence Eden's Block]]