Abend,
da ich kein Plan habe, wie Module zu erstellen sind. Hier mal etwas „Oldschool“ als Script die Abfrage der Daten.
Ist habe das meiste nur, aus den Schnipseln hier, zusammenkopiert und etwas in Form gebracht.
Ich nutze nur den Bereich ‚/vehicle/dynamic/v1/‘ . Deswegen ist da auch nur da eine Auswertung und Speicherung der Variablen.
Einfach Script ausführen und fertig.
Variablen werden über IDENT gesetzt, können also umbenannt werden müssen aber im Ordner bleiben.
Attain
<?
// THX to kjb70 , pitti , Fonzo
$debug = false;
//KONFIG
$user = "E_Mail Adresse Login BMW Connected";
$password = "Passwort";
$vehicle = "WBA11111111111111"; // Hier muss die vollständige Fahrgestellnummer des Fahrzeugs eingetragen werden (nicht nur die letzten 7 Stellen)
$ID_data_folder = IPS_GetParent($_IPS['SELF']); // wo sollen die variablen hin?
//select the needed request
$option1 = true;
$option2 = false;
$option3 = false;
$option4 = false;
$option5 = false;
$option6 = false;
//KONFIG ENDE
//SERVER
$auth_api = 'https://customer.bmwgroup.com/gcdm/oauth/authenticate';
$app_id = 'dbf0a542-ebd1-4ff0-a9a7-55172fbfce35';
$api = 'https://www.bmw-connecteddrive.de/api'; // Vermutlich .de für Deutschland und .ch für Schweiz?
$no_error = true;
//Token ermitteln
$token = ATN_GetToken();
//Fahrzeugdaten anfordern
if ($option1) $resp_array_1a=null;
if ($option1) $resp_array_1b=null;
if ($option2) $resp_array_2=null;
if ($option3) $resp_array_3=null;
if ($option4) $resp_array_4=null;
if ($option5) $resp_array_5=null;
if ($option6) $resp_array_6=null;
// Init cURL
if ($option1) $ch_1 = curl_init();
if ($option2) $ch_2 = curl_init();
if ($option3) $ch_3 = curl_init();
if ($option4) $ch_4 = curl_init();
if ($option5) $ch_5 = curl_init();
if ($option6) $ch_6 = curl_init();
// Set cURL options
if ($option1) ATN_SetCURLOptions($ch_1,$api . '/vehicle/dynamic/v1/' . $vehicle . '?offset=-60');
if ($option2) ATN_SetCURLOptions($ch_2,$api . '/vehicle/navigation/v1/' . $vehicle );
if ($option3) ATN_SetCURLOptions($ch_3,$api . '/vehicle/efficiency/v1/' . $vehicle );
if ($option4) ATN_SetCURLOptions($ch_4,$api . '/vehicle/remoteservices/chargingprofile/v1/' . $vehicle );
if ($option5) ATN_SetCURLOptions($ch_5,$api . '/me/service/mapupdate/download/v1/' . $vehicle );
if ($option6) ATN_SetCURLOptions($ch_6,$api . '/vehicle/remoteservices/v1/' . $vehicle . '/history' );
// Build the multi-curl handle
$mh = curl_multi_init();
if ($option1) curl_multi_add_handle( $mh, $ch_1 );
if ($option2) curl_multi_add_handle( $mh, $ch_2 );
if ($option3) curl_multi_add_handle( $mh, $ch_3 );
if ($option4) curl_multi_add_handle( $mh, $ch_4 );
if ($option5) curl_multi_add_handle( $mh, $ch_5 );
if ($option6) curl_multi_add_handle( $mh, $ch_6 );
// Execute all queries simultaneously
$running = null;
do
{
curl_multi_exec( $mh, $running );
}
while ( $running );
// Close the handles
if ($option1) curl_multi_remove_handle( $mh, $ch_1 );
if ($option2) curl_multi_remove_handle( $mh, $ch_2 );
if ($option3) curl_multi_remove_handle( $mh, $ch_3 );
if ($option4) curl_multi_remove_handle( $mh, $ch_4 );
if ($option5) curl_multi_remove_handle( $mh, $ch_5 );
if ($option6) curl_multi_remove_handle( $mh, $ch_6 );
curl_multi_close( $mh );
// evaluate response of navigation interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option1){
$response_1 = curl_multi_getcontent( $ch_1 );
if(empty($response_1))
{
$error_log = ('Empty answer from navigation interface: '.curl_error($ch_1));
$no_error = false;
}
else
{
// decode response 1a
print_r($response_1,!$debug);
$resp_array_1a=json_decode( $response_1, true )['attributesMap'];
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
// decode response 1b
$resp_array_1b=json_decode( $response_1, true )['vehicleMessages']['cbsMessages'];
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_1a, !$debug);
print_r($resp_array_1b, !$debug);
} //endif option 1
// evaluate response of application interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option2) {
$response_2 = curl_multi_getcontent( $ch_2 );
if(empty($response_2))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_2));
$no_error = false;
}
else
{
$resp_array_2=json_decode( $response_2, true);
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_2, !$debug);
} //endif option 2
// evaluate response of efficiency interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option3){
$response_3 = curl_multi_getcontent( $ch_3 );
if(empty($response_3))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_3));
$no_error = false;
}
else
{
$resp_array_3=json_decode( $response_3, true);
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_3, true);
} //endif option 3
// evaluate response of charging interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option4){
$response_4 = curl_multi_getcontent( $ch_4 );
if(empty($response_4))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_4));
$no_error = false;
}
else
{
$resp_array_4=json_decode( $response_4, true);
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_4, true);
} //endif option 4
// evaluate response of map interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option5){
$response_5 = curl_multi_getcontent( $ch_5 );
if(empty($response_5))
{
$error_log = (' Empty answer from application interface: '.curl_error($ch_5));
$no_error = false;
}
else
{
$resp_array_5=json_decode( $response_5, true);
$jsonerror=json_last_error();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_5, !$debug);
} //endif option 5
// evaluate response of map interface
// -----------------------------------------------------------------------------------------------------------------------------------------------------------
if ($option6){
$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();
$no_error = ATN_CheckJSON();
}
print_r($resp_array_6, !$debug);
} //endif option 6
ATN_SetValueByParentID('Letzter Datenabfrage von Server','lastdatarequest', time(), $ID_data_folder, 'Letzer Datenempfang', '~UnixTimestamp');
ATN_SetValueByParentID('JSON Fehlerfrei Decodiert', 'JSONError', $no_error, $ID_data_folder, 'JSON konnte gelesen werden?','~Alert.Reversed');
/* #################################
Daten auswerten
###################################
*/
if ($option1){
foreach ($resp_array_1a as $key => $value)
{
$profile = "";
$ident = str_replace( "_", "", $key );
$ident = str_replace( " ", "", $ident);
IF ($value === NULL) $value = false;
IF ($value == "CLOSED")
{
$value = false;
$profile = "~Window";
}
ELSEIF ($value == "OPEN")
{
$value = true;
$profile = "~Window";
}
Switch ($key)
{
Case "updateTime_converted" : //MEZ
$value = strtotime($value);
$profile = "~UnixTimestamp";
break;
Case "updateTime_converted_timestamp" : //UTC??
$value = $value/1000;
$value = (int) $value;
$profile = "~UnixTimestamp";
break;
Case "door_lock_state" :
$profile = "~Lock";
If ($value == "LOCKED") $value = true;
ELSEIF ($value == "SECURED") $value = true;
ELSEIf ($value == "UNLOCKED") $value = false;
break;
Case "mileage" :
Case "beRemainingRangeFuelKm" :
Case "beRemainingRangeFuel" :
Case "beRemainingRangeFuelMile" :
Case "remaining_fuel" :
$value = (int) $value;
break;
Case "gps_lng" :
Case "gps_lat" :
$value = (float) $value;
break;
}
if ($debug) echo "Varname = ". $key . " Value = " . $value . " IDENT = " . $ident . "
";
ATN_SetValueByParentID($key,$ident,$value,$ID_data_folder,"Variable = " . $key . " Ident = ". $ident,$profile );
}
foreach ($resp_array_1b as $value)
{
if ($debug) print_r ($value);
$status = false;
if($value['status'] == "OK") $status = true;
ATN_SetValueByParentID($value['text'] , $value['id'], $status, $ID_data_folder,"Variable = " . $value['text'] . " Ident = ". $value['id'], "~Alert.Reversed");
ATN_SetValueByParentID($value['text'] . " Datum", $value['id']."date",strtotime($value['date']), $ID_data_folder,"Variable = " . $value['text'] . " Ident = ". $value['id'] . "date", "~UnixTimestamp" );
if (isset($value['unitOfLengthRemaining']))
ATN_SetValueByParentID($value['text'] . " in Kilometer",$value['id']."km", $value['unitOfLengthRemaining'],$ID_data_folder,"Variable = " . $value['text'] . " Ident = ". $value['id'] . "km");
}
}
if ($option2){
//do this or that
}
// and so on
function ATN_SetValueByParentID($Variablename,$Ident,$Wert,$ParentID,$Info = 'Diese Variable wurde Automatisch erstellt', $VARprofile = ''){
$id = @IPS_GetObjectIDByIdent($Ident,$ParentID);
if($id == 0) { // wenn Variable fehlt: anlegen
if (is_bool($Wert)) $typ = 0;
elseif (is_int($Wert)) $typ = 1;
elseif (is_float($Wert)) $typ = 2;
elseif (is_string($Wert)) $typ = 3;
$id = IPS_CreateVariable($typ);
IPS_SetParent($id,$ParentID);
IPS_SetName($id,$Variablename);
IPS_SetInfo($id, $Info);
IPS_SetIdent($id, $Ident);
IPS_SetVariableCustomProfile($id,$VARprofile);
}
if (GetValue($id) != $Wert) SetValue($id,$Wert); // Ausgabe der Werte
}
function ATN_GetToken()
{
global $user,$password,$app_id,$auth_api,$ID_data_folder;
$id = @IPS_GetObjectIDByIdent('TokenExpire',IPS_GetParent($_IPS['SELF']));
$token_expire = @GetValue($id);
$token_error = true;
if ($id == 0 || $token_expire < time())
{
$postfields = http_build_query(array(
'username' => $user,
'password' => $password,
'client_id' => $app_id,
'redirect_uri' => 'https://www.bmw-connecteddrive.com/app/default/static/external-dispatch.html',
'response_type' => 'token',
'locale' => 'DE-de'
));
// 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'));
curl_setopt($ch, CURLOPT_POSTFIELDS, $postfields);
//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."
";
$token_error = false;
$token = false;
}
// 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 = "No remote token received - username or password might be wrong: ".$response."
";
$token_error = false;
$token = false;
}
else // no token error
{
$token = $matches[1];
ATN_SetValueByParentID('TokenError', 'TokenError', $token_error, $ID_data_folder, 'Token wurde empfangen?','~Alert.Reversed');
ATN_SetValueByParentID('Token', 'Token', $token, $ID_data_folder, 'Empfangener Token');
ATN_SetValueByParentID('TokenExpire', 'TokenExpire', time() + $matches[3], $ID_data_folder, 'Token gültig bis', '~UnixTimestamp');
}
}
else // token still valid
{
$id = @IPS_GetObjectIDByIdent('Token',$ID_data_folder);
$token = @GetValue($id);
}
if (!$token_error) IPS_LogMessage($error_log);
return $token;
}
function ATN_CheckJSON()
{
global $jsonerror;
switch($jsonerror)
{
case JSON_ERROR_NONE:
$no_error = true;
break;
case JSON_ERROR_DEPTH:
$error_log = (' JSON1 - Maximale Stacktiefe überschritten'.">".$response_1."<");
$no_error = false;
break;
case JSON_ERROR_STATE_MISMATCH:
$error_log = (' JSON1 - Unterlauf oder Nichtübereinstimmung der Modi'.">".$response_1."<");
$no_error = false;
break;
case JSON_ERROR_CTRL_CHAR:
$error_log = (' JSON1 - Unerwartetes Steuerzeichen gefunden'.">".$response_1."<>".$ch_1."<");
$no_error = false;
break;
case JSON_ERROR_SYNTAX:
$error_log = (' JSON1 - Syntaxfehler, ungültiges JSON'.">".$response_1."<");
$no_error = false;
break;
case JSON_ERROR_UTF8:
$error_log = (' JSON1 - Missgestaltete UTF-8 Zeichen, möglicherweise fehlerhaft kodiert'.">".$response_1."<");
$no_error = false;
break;
default:
$error_log = (' JSON1 - Unbekannter Fehler'.">".$response_1."<");
$no_error = false;
break;
}
if (!$no_error) IPS_LogMessage($error_log);
return($no_error);
}
function ATN_SetCURLOptions($ch,$option)
{
global $token;
curl_setopt( $ch, CURLOPT_URL, $option );
curl_setopt( $ch, CURLOPT_HTTPHEADER, array( 'Content-Type: application/json' , 'Authorization: Bearer ' . $token ) );
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
//curl_setopt( $ch_2, CURLOPT_SSL_VERIFYPEER, false);
}
?>