====== 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]]