Auf Euren Wunsch poste ich hier mal meine Gehversuche. Das ist bisher alles zusammengeschustert und nicht die feine Art zu coden. Hat noch einige Debugging Funktionen drin und man kann das (wenn dann die Zeit mal da ist) sicher viel schöner und kompakter lösen. Ich wollte primär mal sehen ob es geht und das tut es.
Wie gesagt, es sind lediglich Kopien der Leistungen von Menschen aus den anderen Foren mit kleinen Erweiterungen.
Das Grundkonzept erkläre ich nicht, auch das steht alles in den oben genannten Links.
Hiermit wird das Token angefordert:
<?
$username = "";
$password = "";
$auth_api = 'https://customer.bmwgroup.com/gcdm/oauth/authenticate';
// Init cURL
$ch = curl_init();
// Set cURL options
curl_setopt($ch, CURLOPT_URL, $auth_api);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_NOBODY, true);
curl_setopt($ch, CURLOPT_COOKIESESSION, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/x-www-form-urlencoded'));
//die Daten in der nächsten Zeile (unterbrochen mit ....) müssen gemäss den im Post genannten Links und Foren selbst herauslesen und vollständig eingetragen werden
curl_setopt($ch, CURLOPT_POSTFIELDS, 'username=' . urlencode( $username) . '&password=' . urlencode( $password) . '&client_id=dbf...dlIn0&locale=DE-de');
//curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false);
// Exec curl request
$response = curl_exec($ch);
$curl_error = curl_error($ch);
// Close connection
curl_close( $ch );
if(empty($response) || $response === false || !empty($curl_error))
{
$error_log = "Empty answer from Bearerinterface: ".$curl_error."
";
SetValue(34450 /*[BMW\Token fehlerfrei]*/, false);
return;
}
// Extract token
preg_match( '/access_token=([\w\d]+).*token_type=(\w+).*expires_in=(\d+)/', $response, $matches );
// Check token type
if ( empty( $matches[2] ) OR $matches[2] !== 'Bearer' )
{
$error_log = $error_log."No remote token received - username or password might be wrong: ".$response."
";
SetValue(34450 /*[BMW\Token fehlerfrei]*/, false);
return;
}
SetValue(34450 /*[BMW\Token fehlerfrei]*/, true);
SetValue(13653 /*[BMW\Token]*/, $matches[1]);
SetValue(11459 /*[BMW\Token Expiration]*/, time() + $matches[3]);
?>
Hier werden die verschiedenen Daten angefordert:
<?
// Hier muss die vollständige Fahrgestellnummer des Fahrzeugs eingetragen werden (nicht nur die letzten 7 Stellen)
$vehicle = "";
// Die Adresse ist für die Schweiz. Vermutlich .de anstatt .ch für Deutschland?
$api = 'https://www.bmw-connecteddrive.ch/api';
//Token neu anfordern, wenn nicht mehr gültig
if (time() > GetValue(11459 /*[BMW\Token Expiration]*/)) IPS_RunScriptWait(21000 /*[BMW\Token anfordern]*/);
$token = GetValue(13653 /*[BMW\Token]*/);
//Fahrzeugdaten anfordern
$resp_array_1a=null;
$resp_array_1b=null;
$resp_array_2=null;
$resp_array_3=null;
$resp_array_4=null;
$resp_array_5=null;
$resp_array_6=null;
// Init cURL
$ch_1 = curl_init();
$ch_2 = curl_init();
$ch_3 = curl_init();
$ch_4 = curl_init();
$ch_5 = curl_init();
$ch_6 = curl_init();
// Set cURL options
curl_setopt( $ch_1, CURLOPT_URL, $api . '/vehicle/dynamic/v1/' . $vehicle . '?offset=-60' );
curl_setopt( $ch_1, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token) );
curl_setopt( $ch_1, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_1, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_1, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch_2, CURLOPT_URL, $api . '/vehicle/navigation/v1/' . $vehicle );
curl_setopt( $ch_2, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token ) );
curl_setopt( $ch_2, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_2, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_2, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch_3, CURLOPT_URL, $api . '/vehicle/efficiency/v1/' . $vehicle );
curl_setopt( $ch_3, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token ) );
curl_setopt( $ch_3, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_3, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_3, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch_4, CURLOPT_URL, $api . '/vehicle/remoteservices/chargingprofile/v1/' . $vehicle );
curl_setopt( $ch_4, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token ) );
curl_setopt( $ch_4, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_4, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_4, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch_5, CURLOPT_URL, $api . '/me/service/mapupdate/download/v1/' . $vehicle );
curl_setopt( $ch_5, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token ) );
curl_setopt( $ch_5, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_5, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_5, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt( $ch_6, CURLOPT_URL, $api . '/vehicle/remoteservices/v1/' . $vehicle . '/history' );
curl_setopt( $ch_6, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token) );
curl_setopt( $ch_6, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch_6, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_6, CURLOPT_SSL_VERIFYPEER, false);
// Build the multi-curl handle
$mh = curl_multi_init();
curl_multi_add_handle( $mh, $ch_1 );
curl_multi_add_handle( $mh, $ch_2 );
curl_multi_add_handle( $mh, $ch_3 );
curl_multi_add_handle( $mh, $ch_4 );
curl_multi_add_handle( $mh, $ch_5 );
curl_multi_add_handle( $mh, $ch_6 );
// Execute all queries simultaneously
$running = null;
do
{
curl_multi_exec( $mh, $running );
}
while ( $running );
// Close the handles
curl_multi_remove_handle( $mh, $ch_1 );
curl_multi_remove_handle( $mh, $ch_2 );
curl_multi_remove_handle( $mh, $ch_3 );
curl_multi_remove_handle( $mh, $ch_4 );
curl_multi_remove_handle( $mh, $ch_5 );
curl_multi_remove_handle( $mh, $ch_6 );
curl_multi_close( $mh );
// evaluate response of navigation interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_1 = curl_multi_getcontent( $ch_1 );
if(empty($response_1))
{
$error_log = ('Empty answer from navigation interface: '.curl_error($ch_1));
}
else
{
// decode response 1a
$resp_array_1a=json_decode( $response_1, true )['attributesMap'];
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log_a = (' JSON1 - Maximale Stacktiefe überschritten'.">".$response_1."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log_a = (' JSON1 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_1."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log_a = (' JSON1 - Unerwartetes Steuerzeichen gefunden'.">".$response_1."<>".$ch_1."<");
break;
case JSON_ERROR_SYNTAX:
$error_log_a = (' JSON1 - Syntaxfehler, ungültiges JSON'.">".$response_1."<");
break;
case JSON_ERROR_UTF8:
$error_log_a = (' JSON1 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_1."<");
break;
default:
$error_log_a = (' JSON1 - Unbekannter Fehler'.">".$response_1."<");
break;
}
// decode response 1b
$resp_array_1b=json_decode( $response_1, true )['vehicleMessages']['cbsMessages'];
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log_b = (' JSON1 - Maximale Stacktiefe überschritten'.">".$response_1."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log_b = (' JSON1 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_1."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log_b = (' JSON1 - Unerwartetes Steuerzeichen gefunden'.">".$response_1."<>".$ch_1."<");
break;
case JSON_ERROR_SYNTAX:
$error_log_b = (' JSON1 - Syntaxfehler, ungültiges JSON'.">".$response_1."<");
break;
case JSON_ERROR_UTF8:
$error_log_b = (' JSON1 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_1."<");
break;
default:
$error_log_b = (' JSON1 - Unbekannter Fehler'.">".$response_1."<");
break;
}
}
// Fehler
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
if (!empty($error_log_a))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
if (!empty($error_log_b))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
print_r($resp_array_1a, true);
print_r($resp_array_1b, true);
// evaluate response of application interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_2 = curl_multi_getcontent( $ch_2 );
if(empty($response_2))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_2));
}
else
{
$resp_array_2=json_decode( $response_2, true);
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON2 - Maximale Stacktiefe überschritten'.">".$response_2."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON2 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_2."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON2 - Unerwartetes Steuerzeichen gefunden'.">".$response_2."<>".$ch_2."<");
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON2 - Syntaxfehler, ungültiges JSON'.">".$response_2."<");
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON2 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_2."<");
break;
default:
$error_log = (' JSON2 - Unbekannter Fehler'.">".$response_2."<");
break;
}
}
// Fehler
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
print_r($resp_array_2, true);
// evaluate response of efficiency interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_3 = curl_multi_getcontent( $ch_3 );
if(empty($response_3))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_3));
}
else
{
$resp_array_3=json_decode( $response_3, true);
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON2 - Maximale Stacktiefe überschritten'.">".$response_3."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON2 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_3."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON2 - Unerwartetes Steuerzeichen gefunden'.">".$response_3."<>".$ch_3."<");
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON2 - Syntaxfehler, ungültiges JSON'.">".$response_3."<");
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON2 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_3."<");
break;
default:
$error_log = (' JSON2 - Unbekannter Fehler'.">".$response_3."<");
break;
}
}
// Fehler
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
print_r($resp_array_3, true);
// evaluate response of charging interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_4 = curl_multi_getcontent( $ch_4 );
if(empty($response_4))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_4));
}
else
{
$resp_array_4=json_decode( $response_4, true);
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON2 - Maximale Stacktiefe überschritten'.">".$response_4."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON2 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_4."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON2 - Unerwartetes Steuerzeichen gefunden'.">".$response_4."<>".$ch_4."<");
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON2 - Syntaxfehler, ungültiges JSON'.">".$response_4."<");
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON2 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_4."<");
break;
default:
$error_log = (' JSON2 - Unbekannter Fehler'.">".$response_4."<");
break;
}
}
// Fehler loggen
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
$filename = "C:\Hausleitsystem\Logs\BMW-CD-Data_".date("Y", time()).".txt";
$file = fopen($filename, 'a');
$data = date("d.m.Y H:i:s - ", time())."Response 4: ";
$data = $data.$error_log."
";
$data = $data.$response_4."
";
$data = $data."----------------------------------------------------------------------"."
";
fwrite($file, utf8_decode($data));
fclose($file);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
print_r($resp_array_4, true);
// evaluate response of map interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_5 = curl_multi_getcontent( $ch_5 );
if(empty($response_5))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_5));
}
else
{
$resp_array_5=json_decode( $response_5, true);
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON2 - Maximale Stacktiefe überschritten'.">".$response_5."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON2 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_5."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON2 - Unerwartetes Steuerzeichen gefunden'.">".$response_5."<>".$ch_5."<");
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON2 - Syntaxfehler, ungültiges JSON'.">".$response_5."<");
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON2 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_5."<");
break;
default:
$error_log = (' JSON2 - Unbekannter Fehler'.">".$response_5."<");
break;
}
}
// Fehler loggen
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
print_r($resp_array_5, true);
// evaluate response of map interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
$response_6 = curl_multi_getcontent( $ch_6 );
if(empty($response_6))
{
//$error_log = (' Empty answer from application interface: '.curl_error($ch_6));
}
else
{
$resp_array_6=json_decode( $response_6, true);
$jsonerror=json_last_error();
switch($jsonerror)
{
case JSON_ERROR_NONE:
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON2 - Maximale Stacktiefe überschritten'.">".$response_6."<");
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON2 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_6."<");
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON2 - Unerwartetes Steuerzeichen gefunden'.">".$response_6."<>".$ch_6."<");
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON2 - Syntaxfehler, ungültiges JSON'.">".$response_6."<");
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON2 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_6."<");
break;
default:
$error_log = (' JSON2 - Unbekannter Fehler'.">".$response_6."<");
break;
}
}
// Fehler loggen
if (!empty($error_log))
{
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, false);
return;
}
// Keine Fehler
SetValue(20030 /*[BMW\Fahrzeugdaten fehlerfrei]*/, true);
SetValue(23655 /*[BMW\Fahrzeugdaten fehlerfrei\Zeitpunkt letzter fehlerfreier Empfang]*/, time());
print_r($resp_array_6, true);
// Daten auswerten
include '59002 /*[BMW\Fahrzeugdaten auswerten]*/.ips.php';
?>