Freitag, 16. Februar 2018

Tasker und Tesla

Voraussetzungen

Um per Tasker auf die Tesla-API zuzugreifen benutze ich zusätzlich noch RESTask for Tasker (Beta) sowie AutoTools.

Da ich wenig Erfahrung mit dem XML-Export aus Tasker habe, hoffe ich, dass sich die folgenden Tasks importieren lassen. Falls nicht, dann lasst es mich bitte in den Kommentaren wissen.

Token

Als erstes muss man sich einen Token für den Zugriff holen. Dies geht mit dem folgenden Task:
<TaskerData sr="" dvi="1" tv="5.1m"> 
<Task sr="task473"> 
<cdate>1471281919651</cdate> 
<edate>1518800541033</edate> 
<id>473</id> 
<nme>Tesla Access-Token</nme> 
<pri>100</pri> 
<Action sr="act0" ve="7"> 
<code>1099157652</code> 
<Bundle sr="arg0"> 
<Vals sr="val"> 
<DeletePaths>&lt;null&gt;</DeletePaths> 
<DeletePaths-type>java.lang.String</DeletePaths-type> 
<DeleteValues>&lt;null&gt;</DeleteValues> 
<DeleteValues-type>java.lang.String</DeleteValues-type> 
<FilterField>&lt;null&gt;</FilterField> 
<FilterField-type>java.lang.String</FilterField-type> 
<FilterValye>&lt;null&gt;</FilterValye> 
<FilterValye-type>java.lang.String</FilterValye-type> 
<JsonAddToArrayKey>&lt;null&gt;</JsonAddToArrayKey> 
<JsonAddToArrayKey-type>java.lang.String</JsonAddToArrayKey-type> 
<JsonAddToArrayValues>&lt;null&gt;</JsonAddToArrayValues> 
<JsonAddToArrayValues-type>java.lang.String</JsonAddToArrayValues-type> 
<JsonArrayClear>false</JsonArrayClear> 
<JsonArrayClear-type>java.lang.Boolean</JsonArrayClear-type> 
<JsonArrayObjectKeys>&lt;null&gt;</JsonArrayObjectKeys> 
<JsonArrayObjectKeys-type>java.lang.String</JsonArrayObjectKeys-type> 
<JsonArrayObjectValues>&lt;null&gt;</JsonArrayObjectValues> 
<JsonArrayObjectValues-type>java.lang.String</JsonArrayObjectValues-type> 
<JsonArrayObjectValuesSeparator>|</JsonArrayObjectValuesSeparator> 
<JsonArrayObjectValuesSeparator-type>java.lang.String</JsonArrayObjectValuesSeparator-type> 
<JsonInput>&lt;null&gt;</JsonInput> 
<JsonInput-type>java.lang.String</JsonInput-type> 
<JsonKeys>grant_type,client_id,client_secret,email,password</JsonKeys> 
<JsonKeys-type>java.lang.String</JsonKeys-type> 
<JsonResultPretty>false</JsonResultPretty> 
<JsonResultPretty-type>java.lang.Boolean</JsonResultPretty-type> 
<JsonResultVariable>get_access_token</JsonResultVariable> 
<JsonResultVariable-type>java.lang.String</JsonResultVariable-type> 
<JsonValues>password,<client_id>,<client_secret>,<email@address.com>,<password></JsonValues> 
<JsonValues-type>java.lang.String</JsonValues-type> 
<MatchesCaseInsensitive>false</MatchesCaseInsensitive> 
<MatchesCaseInsensitive-type>java.lang.Boolean</MatchesCaseInsensitive-type> 
<MatchesCaseInsensitive_delete>false</MatchesCaseInsensitive_delete> 
<MatchesCaseInsensitive_delete-type>java.lang.Boolean</MatchesCaseInsensitive_delete-type> 
<MatchesContainsAll>false</MatchesContainsAll> 
<MatchesContainsAll-type>java.lang.Boolean</MatchesContainsAll-type> 
<MatchesContainsAll_delete>false</MatchesContainsAll_delete> 
<MatchesContainsAll_delete-type>java.lang.Boolean</MatchesContainsAll_delete-type> 
<MatchesExact>false</MatchesExact> 
<MatchesExact-type>java.lang.Boolean</MatchesExact-type> 
<MatchesExact_delete>false</MatchesExact_delete> 
<MatchesExact_delete-type>java.lang.Boolean</MatchesExact_delete-type> 
<MatchesRegex>false</MatchesRegex> 
<MatchesRegex-type>java.lang.Boolean</MatchesRegex-type> 
<MatchesRegex_delete>false</MatchesRegex_delete> 
<MatchesRegex_delete-type>java.lang.Boolean</MatchesRegex_delete-type> 
<Separator>,</Separator> 
<Separator-type>java.lang.String</Separator-type> 
<UpdatePaths>&lt;null&gt;</UpdatePaths> 
<UpdatePaths-type>java.lang.String</UpdatePaths-type> 
<UpdateValues>&lt;null&gt;</UpdateValues> 
<UpdateValues-type>java.lang.String</UpdateValues-type> 
<com.twofortyfouram.locale.intent.extra.BLURB>Separator: , 
Json Keys: grant_type,client_id,client_secret,email,password 
Json Values: password,<client_id>,<client_secret>,<email@address.com>,<password> 
Arrays Separator: |</com.twofortyfouram.locale.intent.extra.BLURB> 
<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type> 
<net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;%get_access_token 
Result Json 
Resulting Json that was written&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;%err
Error Code 
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;%errmsg
Error Message 
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;&lt;/StringArray&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES> 
<net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type> 
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>JsonKeys JsonValues JsonResultVariable Separator JsonArrayObjectValuesSeparator plugininstanceid plugintypeid </net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS> 
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type> 
<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled> 
<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type> 
<plugininstanceid>cf5b06e4-a532-488d-9cfd-edfe0a31bea4</plugininstanceid> 
<plugininstanceid-type>java.lang.String</plugininstanceid-type> 
<plugintypeid>com.joaomgcd.autotools.intent.IntentJsonWrite</plugintypeid> 
<plugintypeid-type>java.lang.String</plugintypeid-type> 
</Vals> 
</Bundle> 
<Str sr="arg1" ve="3">com.joaomgcd.autotools</Str> 
<Str sr="arg2" ve="3">com.joaomgcd.autotools.activity.ActivityConfigJsonWrite</Str> 
<Int sr="arg3" val="60"/> 
</Action> 
<Action sr="act1" ve="7"> 
<code>116</code> 
<Str sr="arg0" ve="3">https://owner-api.teslamotors.com</Str> 
<Str sr="arg1" ve="3">oauth/token</Str> 
<Str sr="arg2" ve="3">%get_access_token</Str> 
<Str sr="arg3" ve="3"/> 
<Str sr="arg4" ve="3"/> 
<Int sr="arg5" val="10"/> 
<Str sr="arg6" ve="3">application/json</Str> 
<Str sr="arg7" ve="3">Tasker/Tesla_access_token</Str> 
<Int sr="arg8" val="0"/> 
</Action> 
<Action sr="act10" ve="7"> 
<code>105</code> 
<Str sr="arg0" ve="3">%TESLA_ACCESS_TOKEN</Str> 
<Int sr="arg1" val="0"/> 
</Action> 
<Action sr="act11" ve="7"> 
<code>38</code> 
</Action> 
<Action sr="act2" ve="7"> 
<code>417</code> 
<Str sr="arg0" ve="3">Tasker/Tesla_access_token</Str> 
<Str sr="arg1" ve="3">%json_access_token</Str> 
</Action> 
<Action sr="act3" ve="7"> 
<code>1446874931</code> 
<Bundle sr="arg0"> 
<Vals sr="val"> 
<Average>&lt;null&gt;</Average> 
<Average-type>java.lang.String</Average-type> 
<Field>access_token, expires_in, created_at, refresh_token</Field> 
<Field-type>java.lang.String</Field-type> 
<FilterInvert>false</FilterInvert> 
<FilterInvert-type>java.lang.Boolean</FilterInvert-type> 
<GetParentValues>false</GetParentValues> 
<GetParentValues-type>java.lang.Boolean</GetParentValues-type> 
<InputFormat>&lt;null&gt;</InputFormat> 
<InputFormat-type>java.lang.String</InputFormat-type> 
<JoinOutputArray>&lt;null&gt;</JoinOutputArray> 
<JoinOutputArray-type>java.lang.String</JoinOutputArray-type> 
<Json>%json_access_token</Json> 
<Json-type>java.lang.String</Json-type> 
<JsonRootVariable>&lt;null&gt;</JsonRootVariable> 
<JsonRootVariable-type>java.lang.String</JsonRootVariable-type> 
<MatchField>&lt;null&gt;</MatchField> 
<MatchField-type>java.lang.String</MatchField-type> 
<MatchValue>&lt;null&gt;</MatchValue> 
<MatchValue-type>java.lang.String</MatchValue-type> 
<MatchesCaseInsensitive>false</MatchesCaseInsensitive> 
<MatchesCaseInsensitive-type>java.lang.Boolean</MatchesCaseInsensitive-type> 
<MatchesContainsAll>false</MatchesContainsAll> 
<MatchesContainsAll-type>java.lang.Boolean</MatchesContainsAll-type> 
<MatchesExact>false</MatchesExact> 
<MatchesExact-type>java.lang.Boolean</MatchesExact-type> 
<MatchesRegex>false</MatchesRegex> 
<MatchesRegex-type>java.lang.Boolean</MatchesRegex-type> 
<Max>&lt;null&gt;</Max> 
<Max-type>java.lang.String</Max-type> 
<MaxResults>&lt;null&gt;</MaxResults> 
<MaxResults-type>java.lang.String</MaxResults-type> 
<Min>&lt;null&gt;</Min> 
<Min-type>java.lang.String</Min-type> 
<Query>&lt;null&gt;</Query> 
<Query-type>java.lang.String</Query-type> 
<Separator>,</Separator> 
<Separator-type>java.lang.String</Separator-type> 
<SimpleMode>true</SimpleMode> 
<SimpleMode-type>java.lang.Boolean</SimpleMode-type> 
<SortArrayInvert>false</SortArrayInvert> 
<SortArrayInvert-type>java.lang.Boolean</SortArrayInvert-type> 
<SortArrayKey>&lt;null&gt;</SortArrayKey> 
<SortArrayKey-type>java.lang.String</SortArrayKey-type> 
<SortArrayObjectKey>&lt;null&gt;</SortArrayObjectKey> 
<SortArrayObjectKey-type>java.lang.String</SortArrayObjectKey-type> 
<Sum>&lt;null&gt;</Sum> 
<Sum-type>java.lang.String</Sum-type> 
<VariableName>&lt;null&gt;</VariableName> 
<VariableName-type>java.lang.String</VariableName-type> 
<com.twofortyfouram.locale.intent.extra.BLURB>Simple Mode: true 
Json: %json_access_token 
Fields: access_token, expires_in, created_at, refresh_token 
Separator: ,</com.twofortyfouram.locale.intent.extra.BLURB> 
<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type> 
<net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;%access_token 
Json Values 
Values of the fields you got from the json text&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;%created_at
Json Values 
Values of the fields you got from the json text&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;%expires_in
Json Values 
Values of the fields you got from the json text&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3&gt;%refresh_token
Json Values 
Values of the fields you got from the json text&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES3&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES4&gt;%err
Error Code 
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES4&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES5&gt;%errmsg
Error Message 
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES5&gt;&lt;/StringArray&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES> 
<net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type> 
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>Json Field Separator plugininstanceid plugintypeid </net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS> 
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type> 
<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled> 
<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type> 
<plugininstanceid>eb30d0c8-5739-44c3-aca5-ca33b2a8a4b2</plugininstanceid> 
<plugininstanceid-type>java.lang.String</plugininstanceid-type> 
<plugintypeid>com.joaomgcd.autotools.intent.IntentJson</plugintypeid> 
<plugintypeid-type>java.lang.String</plugintypeid-type> 
</Vals> 
</Bundle> 
<Str sr="arg1" ve="3">com.joaomgcd.autotools</Str> 
<Str sr="arg2" ve="3">com.joaomgcd.autotools.activity.ActivityConfigJson</Str> 
<Int sr="arg3" val="60"/> 
</Action> 
<Action sr="act4" ve="7"> 
<code>37</code> 
<ConditionList sr="if"> 
<Condition sr="c0" ve="3"> 
<lhs>%access_token</lhs> 
<op>1</op> 
<rhs>%TESLA_ACCESS_TOKEN</rhs> 
</Condition> 
</ConditionList> 
</Action> 
<Action sr="act5" ve="7"> 
<code>547</code> 
<Str sr="arg0" ve="3">%TESLA_ACCESS_TOKEN_VORHER</Str> 
<Str sr="arg1" ve="3">%TESLA_ACCESS_TOKEN</Str> 
<Int sr="arg2" val="0"/> 
<Int sr="arg3" val="0"/> 
<Int sr="arg4" val="0"/> 
</Action> 
<Action sr="act6" ve="7"> 
<code>547</code> 
<Str sr="arg0" ve="3">%TESLA_ACCESS_TOKEN_CREATED_AT</Str> 
<Str sr="arg1" ve="3">%created_at</Str> 
<Int sr="arg2" val="0"/> 
<Int sr="arg3" val="0"/> 
<Int sr="arg4" val="0"/> 
</Action> 
<Action sr="act7" ve="7"> 
<code>547</code> 
<Str sr="arg0" ve="3">%TESLA_ACCESS_TOKEN_EXPIRES_IN</Str> 
<Str sr="arg1" ve="3">%expires_in</Str> 
<Int sr="arg2" val="0"/> 
<Int sr="arg3" val="0"/> 
<Int sr="arg4" val="0"/> 
</Action> 
<Action sr="act8" ve="7"> 
<code>547</code> 
<Str sr="arg0" ve="3">%TESLA_ACCESS_TOKEN</Str> 
<Str sr="arg1" ve="3">%access_token</Str> 
<Int sr="arg2" val="0"/> 
<Int sr="arg3" val="0"/> 
<Int sr="arg4" val="0"/> 
</Action> 
<Action sr="act9" ve="7"> 
<code>547</code> 
<Str sr="arg0" ve="3">%TESLA_REFRESH_TOKEN</Str> 
<Str sr="arg1" ve="3">%refresh_token</Str> 
<Int sr="arg2" val="0"/> 
<Int sr="arg3" val="0"/> 
<Int sr="arg4" val="0"/> 
</Action> 
</Task> 
</TaskerData> 
Dabei sind die Teile <client_id>, <client_secret>, <email@address.com> und <password> zu ersetzen. Bitte umbedingt nur die ersetzen, die genau so in spitzen Klammern stehen. Die anderen Stellen nicht verändern! Die ersten beiden kann man mit einer Google-Suche nach den Begriffen finden, die letzten beiden sind eure individuellen Zugangsdaten, mit denen ihr bei auf der Tesla-Homepage einloggen könnt. Bitte beachtet, dass je nach Einstellungen in Tasker andere Apps auf diese Daten zugreifen können! Außerdem sollte das Verzeichnis Tasker auf eurem Handy im Hauptverzeichnis existieren. Ihr könnt aber natürlich auch ein anderes Verzeichnis und eine andere Datei nehmen, um den http-Zugriff zwischenzuspeichern.

Der Token (und ein paar weitere Daten) stehen anschließend für die weitere Verwendung in den Tasker-Variablen TESLA_... zur Verfügung. Außerdem enthält die Datei Tasker/Tesla_access_token noch diese Daten. Die Datei kann gelöscht werden.

Liste eurer Fahrzeuge

Anschließend könnt ihr euch eine Liste eurer Fahrzeuge holen. Ich lasse die Liste hier nur am Bildschirm anzeigen, da sie bei mir recht kurz ist und man diesen Schritt auch getrost überspringen kann, wenn man "nur" einen Tesla hat. 😉
<TaskerData sr="" dvi="1" tv="5.1m">
<Task sr="task872">
<cdate>1481824501685</cdate>
<edate>1518803855578</edate>
<id>872</id>
<nme>Tesla List of vehicles</nme>
<pri>100</pri>
<rty>1</rty>
<Action sr="act0" ve="7">
<code>554915598</code>
<se>false</se>
<Bundle sr="arg0">
<Vals sr="val">
<bundle_header>Authorization Bearer %TESLA_ACCESS_TOKEN</bundle_header>
<bundle_header-type>java.lang.String</bundle_header-type>
<bundle_param></bundle_param>
<bundle_param-type>java.lang.String</bundle_param-type>
<com.freehaha.restask.BASICAUTH></com.freehaha.restask.BASICAUTH>
<com.freehaha.restask.BASICAUTH-type>java.lang.String</com.freehaha.restask.BASICAUTH-type>
<com.freehaha.restask.BODY></com.freehaha.restask.BODY>
<com.freehaha.restask.BODY-type>java.lang.String</com.freehaha.restask.BODY-type>
<com.freehaha.restask.CERT></com.freehaha.restask.CERT>
<com.freehaha.restask.CERT-type>java.lang.String</com.freehaha.restask.CERT-type>
<com.freehaha.restask.CERTPATH>empty</com.freehaha.restask.CERTPATH>
<com.freehaha.restask.CERTPATH-type>java.lang.String</com.freehaha.restask.CERTPATH-type>
<com.freehaha.restask.CHUNKED>n</com.freehaha.restask.CHUNKED>
<com.freehaha.restask.CHUNKED-type>java.lang.String</com.freehaha.restask.CHUNKED-type>
<com.freehaha.restask.COOKIE>%rtck</com.freehaha.restask.COOKIE>
<com.freehaha.restask.COOKIE-type>java.lang.String</com.freehaha.restask.COOKIE-type>
<com.freehaha.restask.COOKIEJAR>restask</com.freehaha.restask.COOKIEJAR>
<com.freehaha.restask.COOKIEJAR-type>java.lang.String</com.freehaha.restask.COOKIEJAR-type>
<com.freehaha.restask.CUSTOMBODY>n</com.freehaha.restask.CUSTOMBODY>
<com.freehaha.restask.CUSTOMBODY-type>java.lang.String</com.freehaha.restask.CUSTOMBODY-type>
<com.freehaha.restask.CUSTOMECERT>n</com.freehaha.restask.CUSTOMECERT>
<com.freehaha.restask.CUSTOMECERT-type>java.lang.String</com.freehaha.restask.CUSTOMECERT-type>
<com.freehaha.restask.HEADER>%rthdr</com.freehaha.restask.HEADER>
<com.freehaha.restask.HEADER-type>java.lang.String</com.freehaha.restask.HEADER-type>
<com.freehaha.restask.HOST>https://owner-api.teslamotors.com/api/1/vehicles</com.freehaha.restask.HOST>
<com.freehaha.restask.HOST-type>java.lang.String</com.freehaha.restask.HOST-type>
<com.freehaha.restask.KEEP_COOKIE>n</com.freehaha.restask.KEEP_COOKIE>
<com.freehaha.restask.KEEP_COOKIE-type>java.lang.String</com.freehaha.restask.KEEP_COOKIE-type>
<com.freehaha.restask.OUTPUT_FILE>test.txt</com.freehaha.restask.OUTPUT_FILE>
<com.freehaha.restask.OUTPUT_FILE-type>java.lang.String</com.freehaha.restask.OUTPUT_FILE-type>
<com.freehaha.restask.REDIRECT>y</com.freehaha.restask.REDIRECT>
<com.freehaha.restask.REDIRECT-type>java.lang.String</com.freehaha.restask.REDIRECT-type>
<com.freehaha.restask.RESPONSE>%rtres</com.freehaha.restask.RESPONSE>
<com.freehaha.restask.RESPONSE-type>java.lang.String</com.freehaha.restask.RESPONSE-type>
<com.freehaha.restask.RETCODE>%rtcode</com.freehaha.restask.RETCODE>
<com.freehaha.restask.RETCODE-type>java.lang.String</com.freehaha.restask.RETCODE-type>
<com.freehaha.restask.SYNCCALL>y</com.freehaha.restask.SYNCCALL>
<com.freehaha.restask.SYNCCALL-type>java.lang.String</com.freehaha.restask.SYNCCALL-type>
<com.freehaha.restask.TIMEOUT>30</com.freehaha.restask.TIMEOUT>
<com.freehaha.restask.TIMEOUT-type>java.lang.String</com.freehaha.restask.TIMEOUT-type>
<com.freehaha.restask.TYPE>GET</com.freehaha.restask.TYPE>
<com.freehaha.restask.TYPE-type>java.lang.String</com.freehaha.restask.TYPE-type>
<com.twofortyfouram.locale.intent.extra.BLURB>REST call</com.twofortyfouram.locale.intent.extra.BLURB>
<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>com.freehaha.restask.TYPE com.freehaha.restask.HOST com.freehaha.restask.TIMEOUT com.freehaha.restask.BASICAUTH com.freehaha.restask.CUSTOMBODY com.freehaha.restask.BODY com.freehaha.restask.CUSTOMECERT com.freehaha.restask.CERTPATH com.freehaha.restask.SYNCCALL com.freehaha.restask.HEADER com.freehaha.restask.COOKIE com.freehaha.restask.COOKIEJAR com.freehaha.restask.KEEP_COOKIE com.freehaha.restask.REDIRECT com.freehaha.restask.CHUNKED com.freehaha.restask.OUTPUT_FILE bundle_param bundle_header</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>
<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
</Vals>
</Bundle>
<Str sr="arg1" ve="3">com.freehaha.restask</Str>
<Str sr="arg2" ve="3">com.freehaha.restask.EditActivity</Str>
<Int sr="arg3" val="30"/>
</Action>
<Action sr="act1" ve="7">
<code>548</code>
<Str sr="arg0" ve="3">%rtres

%rtcode</Str>
<Int sr="arg1" val="1"/>
</Action>
</Task>
</TaskerData>

ID eines eurer Fahrzeuge

Für die weiteren Befehle benötigt ihr die ID des Fahrzeugs, das angesprochen werden soll. Ihr könnt die ID wie folgt erhalten:
<TaskerData sr="" dvi="1" tv="5.1m">
<Task sr="task928">
<cdate>1490010484110</cdate>
<edate>1518803847913</edate>
<id>928</id>
<nme>Tesla Vehicle ID</nme>
<pri>100</pri>
<Action sr="act0" ve="7">
<code>554915598</code>
<se>false</se>
<Bundle sr="arg0">
<Vals sr="val">
<bundle_header>Authorization Bearer %TESLA_ACCESS_TOKEN</bundle_header>
<bundle_header-type>java.lang.String</bundle_header-type>
<bundle_param></bundle_param>
<bundle_param-type>java.lang.String</bundle_param-type>
<com.freehaha.restask.BASICAUTH></com.freehaha.restask.BASICAUTH>
<com.freehaha.restask.BASICAUTH-type>java.lang.String</com.freehaha.restask.BASICAUTH-type>
<com.freehaha.restask.BODY></com.freehaha.restask.BODY>
<com.freehaha.restask.BODY-type>java.lang.String</com.freehaha.restask.BODY-type>
<com.freehaha.restask.CERT></com.freehaha.restask.CERT>
<com.freehaha.restask.CERT-type>java.lang.String</com.freehaha.restask.CERT-type>
<com.freehaha.restask.CERTPATH>empty</com.freehaha.restask.CERTPATH>
<com.freehaha.restask.CERTPATH-type>java.lang.String</com.freehaha.restask.CERTPATH-type>
<com.freehaha.restask.CHUNKED>n</com.freehaha.restask.CHUNKED>
<com.freehaha.restask.CHUNKED-type>java.lang.String</com.freehaha.restask.CHUNKED-type>
<com.freehaha.restask.COOKIE>%rtck</com.freehaha.restask.COOKIE>
<com.freehaha.restask.COOKIE-type>java.lang.String</com.freehaha.restask.COOKIE-type>
<com.freehaha.restask.COOKIEJAR>restask</com.freehaha.restask.COOKIEJAR>
<com.freehaha.restask.COOKIEJAR-type>java.lang.String</com.freehaha.restask.COOKIEJAR-type>
<com.freehaha.restask.CUSTOMBODY>n</com.freehaha.restask.CUSTOMBODY>
<com.freehaha.restask.CUSTOMBODY-type>java.lang.String</com.freehaha.restask.CUSTOMBODY-type>
<com.freehaha.restask.CUSTOMECERT>n</com.freehaha.restask.CUSTOMECERT>
<com.freehaha.restask.CUSTOMECERT-type>java.lang.String</com.freehaha.restask.CUSTOMECERT-type>
<com.freehaha.restask.HEADER>%rthdr</com.freehaha.restask.HEADER>
<com.freehaha.restask.HEADER-type>java.lang.String</com.freehaha.restask.HEADER-type>
<com.freehaha.restask.HOST>https://owner-api.teslamotors.com/api/1/vehicles</com.freehaha.restask.HOST>
<com.freehaha.restask.HOST-type>java.lang.String</com.freehaha.restask.HOST-type>
<com.freehaha.restask.KEEP_COOKIE>n</com.freehaha.restask.KEEP_COOKIE>
<com.freehaha.restask.KEEP_COOKIE-type>java.lang.String</com.freehaha.restask.KEEP_COOKIE-type>
<com.freehaha.restask.OUTPUT_FILE></com.freehaha.restask.OUTPUT_FILE>
<com.freehaha.restask.OUTPUT_FILE-type>java.lang.String</com.freehaha.restask.OUTPUT_FILE-type>
<com.freehaha.restask.REDIRECT>y</com.freehaha.restask.REDIRECT>
<com.freehaha.restask.REDIRECT-type>java.lang.String</com.freehaha.restask.REDIRECT-type>
<com.freehaha.restask.RESPONSE>%rtres</com.freehaha.restask.RESPONSE>
<com.freehaha.restask.RESPONSE-type>java.lang.String</com.freehaha.restask.RESPONSE-type>
<com.freehaha.restask.RETCODE>%rtcode</com.freehaha.restask.RETCODE>
<com.freehaha.restask.RETCODE-type>java.lang.String</com.freehaha.restask.RETCODE-type>
<com.freehaha.restask.SYNCCALL>y</com.freehaha.restask.SYNCCALL>
<com.freehaha.restask.SYNCCALL-type>java.lang.String</com.freehaha.restask.SYNCCALL-type>
<com.freehaha.restask.TIMEOUT>30</com.freehaha.restask.TIMEOUT>
<com.freehaha.restask.TIMEOUT-type>java.lang.String</com.freehaha.restask.TIMEOUT-type>
<com.freehaha.restask.TYPE>GET</com.freehaha.restask.TYPE>
<com.freehaha.restask.TYPE-type>java.lang.String</com.freehaha.restask.TYPE-type>
<com.twofortyfouram.locale.intent.extra.BLURB>REST call</com.twofortyfouram.locale.intent.extra.BLURB>
<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>com.freehaha.restask.TYPE com.freehaha.restask.HOST com.freehaha.restask.TIMEOUT com.freehaha.restask.BASICAUTH com.freehaha.restask.CUSTOMBODY com.freehaha.restask.BODY com.freehaha.restask.CUSTOMECERT com.freehaha.restask.CERTPATH com.freehaha.restask.SYNCCALL com.freehaha.restask.HEADER com.freehaha.restask.COOKIE com.freehaha.restask.COOKIEJAR com.freehaha.restask.KEEP_COOKIE com.freehaha.restask.REDIRECT com.freehaha.restask.CHUNKED com.freehaha.restask.OUTPUT_FILE bundle_param bundle_header</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>
<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
</Vals>
</Bundle>
<Str sr="arg1" ve="3">com.freehaha.restask</Str>
<Str sr="arg2" ve="3">com.freehaha.restask.EditActivity</Str>
<Int sr="arg3" val="30"/>
</Action>
<Action sr="act1" ve="7">
<code>1446874931</code>
<Bundle sr="arg0">
<Vals sr="val">
<Average>&lt;null&gt;</Average>
<Average-type>java.lang.String</Average-type>
<Field>id_s</Field>
<Field-type>java.lang.String</Field-type>
<FilterInvert>false</FilterInvert>
<FilterInvert-type>java.lang.Boolean</FilterInvert-type>
<GetParentValues>false</GetParentValues>
<GetParentValues-type>java.lang.Boolean</GetParentValues-type>
<InputFormat>&lt;null&gt;</InputFormat>
<InputFormat-type>java.lang.String</InputFormat-type>
<JoinOutputArray>&lt;null&gt;</JoinOutputArray>
<JoinOutputArray-type>java.lang.String</JoinOutputArray-type>
<Json>%rtres</Json>
<Json-type>java.lang.String</Json-type>
<JsonRootVariable>&lt;null&gt;</JsonRootVariable>
<JsonRootVariable-type>java.lang.String</JsonRootVariable-type>
<MatchField>&lt;null&gt;</MatchField>
<MatchField-type>java.lang.String</MatchField-type>
<MatchValue>&lt;null&gt;</MatchValue>
<MatchValue-type>java.lang.String</MatchValue-type>
<MatchesCaseInsensitive>false</MatchesCaseInsensitive>
<MatchesCaseInsensitive-type>java.lang.Boolean</MatchesCaseInsensitive-type>
<MatchesContainsAll>false</MatchesContainsAll>
<MatchesContainsAll-type>java.lang.Boolean</MatchesContainsAll-type>
<MatchesExact>false</MatchesExact>
<MatchesExact-type>java.lang.Boolean</MatchesExact-type>
<MatchesRegex>false</MatchesRegex>
<MatchesRegex-type>java.lang.Boolean</MatchesRegex-type>
<Max>&lt;null&gt;</Max>
<Max-type>java.lang.String</Max-type>
<MaxResults>&lt;null&gt;</MaxResults>
<MaxResults-type>java.lang.String</MaxResults-type>
<Min>&lt;null&gt;</Min>
<Min-type>java.lang.String</Min-type>
<Query>&lt;null&gt;</Query>
<Query-type>java.lang.String</Query-type>
<Separator>,</Separator>
<Separator-type>java.lang.String</Separator-type>
<SimpleMode>true</SimpleMode>
<SimpleMode-type>java.lang.Boolean</SimpleMode-type>
<SortArrayInvert>false</SortArrayInvert>
<SortArrayInvert-type>java.lang.Boolean</SortArrayInvert-type>
<SortArrayKey>&lt;null&gt;</SortArrayKey>
<SortArrayKey-type>java.lang.String</SortArrayKey-type>
<SortArrayObjectKey>&lt;null&gt;</SortArrayObjectKey>
<SortArrayObjectKey-type>java.lang.String</SortArrayObjectKey-type>
<Sum>&lt;null&gt;</Sum>
<Sum-type>java.lang.String</Sum-type>
<VariableName>&lt;null&gt;</VariableName>
<VariableName-type>java.lang.String</VariableName-type>
<com.twofortyfouram.locale.intent.extra.BLURB>Simple Mode: true
Json: %rtres
Fields: id_s
Separator: ,</com.twofortyfouram.locale.intent.extra.BLURB>
<com.twofortyfouram.locale.intent.extra.BLURB-type>java.lang.String</com.twofortyfouram.locale.intent.extra.BLURB-type>
<net.dinglisch.android.tasker.RELEVANT_VARIABLES>&lt;StringArray sr=""&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;%id_s
Json Values
Values of the fields you got from the json text&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES0&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;%err
Error Code
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES1&gt;&lt;_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;%errmsg
Error Message
Only available if you select &amp;lt;b&amp;gt;Continue Task After Error&amp;lt;/b&amp;gt; and the action ends in error&lt;/_array_net.dinglisch.android.tasker.RELEVANT_VARIABLES2&gt;&lt;/StringArray&gt;</net.dinglisch.android.tasker.RELEVANT_VARIABLES>
<net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>[Ljava.lang.String;</net.dinglisch.android.tasker.RELEVANT_VARIABLES-type>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>Json Field Separator plugininstanceid plugintypeid </net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS>
<net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>java.lang.String</net.dinglisch.android.tasker.extras.VARIABLE_REPLACE_KEYS-type>
<net.dinglisch.android.tasker.subbundled>true</net.dinglisch.android.tasker.subbundled>
<net.dinglisch.android.tasker.subbundled-type>java.lang.Boolean</net.dinglisch.android.tasker.subbundled-type>
<plugininstanceid>ea561920-2772-45cc-a656-517da5ec285c</plugininstanceid>
<plugininstanceid-type>java.lang.String</plugininstanceid-type>
<plugintypeid>com.joaomgcd.autotools.intent.IntentJson</plugintypeid>
<plugintypeid-type>java.lang.String</plugintypeid-type>
</Vals>
</Bundle>
<Str sr="arg1" ve="3">com.joaomgcd.autotools</Str>
<Str sr="arg2" ve="3">com.joaomgcd.autotools.activity.ActivityConfigJson</Str>
<Int sr="arg3" val="60"/>
</Action>
<Action sr="act2" ve="7">
<code>547</code>
<Str sr="arg0" ve="3">%TESLA_VEHICLE_ID</Str>
<Str sr="arg1" ve="3">%id_s</Str>
<Int sr="arg2" val="0"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
</Action>
</Task>
</TaskerData>
Dies funktioniert so für ein Fahrzeug. Wer mehrere hat und Hilfe braucht...in meinem Tesla-Account ist noch Platz... 😂

Aufwecken

Die meisten Befehle kann man nur absetzen, wenn sich der Wagen nicht im Schlafmodus befindet. Mit dem folgenden Task kann man ihn falls nötig aufwecken:
<TaskerData sr="" dvi="1" tv="5.1m">
<Task sr="task39">
<cdate>1500629736233</cdate>
<edate>1518800648101</edate>
<id>39</id>
<nme>Tesla aufwecken</nme>
<pri>100</pri>
<rty>1</rty>
<Action sr="act0" ve="7">
<code>129</code>
<label>Aufwecken</label>
<Str sr="arg0" ve="3">var token = global('TESLA_ACCESS_TOKEN');
var id = global('TESLA_VEHICLE_ID');
var url = "https://owner-api.teslamotors.com/api/1/vehicles/" + id + "/wake_up"
var http = new XMLHttpRequest();
http.open("POST", url, false);
http.setRequestHeader("Authorization", "Bearer " + token);
http.send();
var http_status = http.status;
var http_response = http.responseText;</Str>
<Str sr="arg1" ve="3"/>
<Int sr="arg2" val="1"/>
<Int sr="arg3" val="45"/>
</Action>
<Action sr="act1" ve="7">
<code>523</code>
<Str sr="arg0" ve="3">Bitte Tesla-Token überprüfen!</Str>
<Str sr="arg1" ve="3"/>
<Img sr="arg2" ve="2">
<nme>mw_action_announcement</nme>
</Img>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
<Int sr="arg5" val="3"/>
<ConditionList sr="if">
<Condition sr="c0" ve="3">
<lhs>%http_status</lhs>
<op>2</op>
<rhs>401</rhs>
</Condition>
</ConditionList>
</Action>
<Action sr="act2" ve="7">
<code>37</code>
<ConditionList sr="if">
<Condition sr="c0" ve="3">
<lhs>%http_status</lhs>
<op>1</op>
<rhs>200</rhs>
</Condition>
</ConditionList>
</Action>
<Action sr="act3" ve="7">
<code>30</code>
<Int sr="arg0" val="0"/>
<Int sr="arg1" val="0"/>
<Int sr="arg2" val="1"/>
<Int sr="arg3" val="0"/>
<Int sr="arg4" val="0"/>
</Action>
<Action sr="act4" ve="7">
<code>135</code>
<Int sr="arg0" val="0"/>
<Int sr="arg1" val="1"/>
<Str sr="arg2" ve="3"/>
</Action>
<Action sr="act5" ve="7">
<code>38</code>
</Action>
</Task>
</TaskerData>
Hierfür wird das im ersten Schritt erzeugte Token benötigt.

Ladelimit

Anschließend kann man z.B. ein individuelles Ladelimit setzen, in diesem Fall 95%:
<TaskerData sr="" dvi="1" tv="5.1m"><Task sr="task312"><cdate>1491893622825</cdate><edate>1518800690210</edate><id>312</id><nme>Tesla Ladelimit 95</nme><pri>100</pri><rty>1</rty><Action sr="act0" ve="7"><code>130</code><Str sr="arg0" ve="3">Tesla aufwecken</Str><Int sr="arg1" val="50"/><Str sr="arg2" ve="3"/><Str sr="arg3" ve="3"/><Str sr="arg4" ve="3"/><Int sr="arg5" val="0"/></Action><Action sr="act1" ve="7"><code>129</code><Str sr="arg0" ve="3">var token = global('TESLA_ACCESS_TOKEN');var id = global('TESLA_VEHICLE_ID');var url = "https://owner-api.teslamotors.com/api/1/vehicles/" + id + "/command/set_charge_limit";var http = new XMLHttpRequest();http.open("POST", url, false);http.setRequestHeader("Content-Type", "application/json");http.setRequestHeader("Authorization", "Bearer " + token);var param = { "percent" : "95" };http.send(JSON.stringify(param));var http_status = http.status;</Str><Str sr="arg1" ve="3"/><Int sr="arg2" val="1"/><Int sr="arg3" val="45"/></Action><Action sr="act2" ve="7"><code>523</code><Str sr="arg0" ve="3">Bitte Tesla-Token überprüfen!</Str><Str sr="arg1" ve="3"/><Img sr="arg2" ve="2"><nme>mw_action_announcement</nme></Img><Int sr="arg3" val="0"/><Int sr="arg4" val="0"/><Int sr="arg5" val="3"/><ConditionList sr="if"><Condition sr="c0" ve="3"><lhs>%http_status</lhs><op>2</op><rhs>401</rhs></Condition></ConditionList></Action><Action sr="act3" ve="7"><code>37</code><ConditionList sr="if"><Condition sr="c0" ve="3"><lhs>%http_status</lhs><op>1</op><rhs>200</rhs></Condition></ConditionList></Action><Action sr="act4" ve="7"><code>30</code><Int sr="arg0" val="0"/><Int sr="arg1" val="0"/><Int sr="arg2" val="1"/><Int sr="arg3" val="0"/><Int sr="arg4" val="0"/></Action><Action sr="act5" ve="7"><code>135</code><Int sr="arg0" val="0"/><Int sr="arg1" val="1"/><Str sr="arg2" ve="3"/></Action><Action sr="act6" ve="7"><code>38</code></Action><Action sr="act7" ve="7"><code>30</code><Int sr="arg0" val="0"/><Int sr="arg1" val="0"/><Int sr="arg2" val="2"/><Int sr="arg3" val="0"/><Int sr="arg4" val="0"/></Action></Task></TaskerData>
Weitere API-Befehle findet man hier: Tesla Model S JSON API. Die meisten Befehle sind dabei wesentlich leichter umzusetzen als das mit dem individuellen Ladelimit.

Vortemperieren

Hier noch ein Beispiel für das Vortemperieren:
<TaskerData sr="" dvi="1" tv="5.1m">
<Task sr="task450">
<cdate>1518802836761</cdate>
<edate>1518802840428</edate>
<id>450</id>
<nme>Tesla vortemperieren starten</nme>
<Action sr="act0" ve="7">
<code>129</code>
<label>Starte Klimaanlage</label>
<Str sr="arg0" ve="3">var token = global('TESLA_ACCESS_TOKEN');
var id = global('TESLA_VEHICLE_ID');
var url = "https://owner-api.teslamotors.com/api/1/vehicles/" + id + "/command/auto_conditioning_start"
var http = new XMLHttpRequest();
http.open("POST", url, false);
http.setRequestHeader("Authorization", "Bearer " + token);
http.send();</Str>
<Str sr="arg1" ve="3"/>
<Int sr="arg2" val="1"/>
<Int sr="arg3" val="45"/>
</Action>
</Task>
</TaskerData>
Die anderen Befehle lassen sich durch recht einfaches Ersetzen der URL umsetzen. Im Zweifel aber bitte gerne bei mir melden, wenn es irgendwo hakt.

Keine Kommentare:

Kommentar veröffentlichen