Ich hatte mir schon lange mal vorgenommen, einen kleinen Datenlogger für mein Model S zu entwickeln, der einfach periodisch alle Daten abfragt und diejenigen, die sich seit der letzten Abfrage verändert haben, ausgibt.
Der Riesenvorteil gegenüber kommerziellen Lösungen ist, dass ich niemandem meine „my Tesla“ credentials geben muss und dass ich alle Parameter selbst festlegen kann.
Erstaunlicherweise geht das mit dem teslajson Python Modul sehr leicht und ich konnte eine erste voll funktionsfähige Version mit wenigen Zeilen Python code entwickeln.
Hat jemand von Euch Interesse an so einem Datenlogger, mag ihn mal ausprobieren und mir Rückmeldungen geben, was man verbessern sollte?
Voraussetzung: Du musst wissen, wie man auf einem Computer Deiner Wahl zwei Umgebungsvariablen setzt und ein Python Programm ausführt. Auf dem Computer muss natürlich Python mit teslajson Modul installiert sein.
Ein raspberry pi eignet sich zum Beispiel hervorragend.
Edit: Da jetzt doch danach gefragt wurde, habe ich es eben auf einem raspberry kurz ausprobiert.
Die folgenden Schritte habe ich ausgeführt:
-
eine root shell in /tmp gestartet:
cd /tmp
sudo sh -
die Python setuptools mit apt-get installiert:
apt-get install python-setuptools -
das teslajson Paket heruntergeladen, ausgepackt und installiert:
wget github.com/gglockner/teslajson/ … master.zip
unzip master.zip
cd teslajson-master
python setup.py install -
die root shell beendet:
exit -
Den Quelltext meines loggers auf „log_all_data.py“ abgelegt.
-
Die beiden Umgebunsvariablen gesetzt und den logger probeweise gestartet:
export TESLA_EMAIL=cko@my_provider.de
export TESLA_PASSWORD=my_secret_password
python log_all_data.py
Wenn das problemlos funktioniert (sieh man daran, dass jetzt alle bekannten
states angezeigt werden), kann man es mit ^C wieder abbrechen
und den log dauerhaft in eine Datei umlenken, zum Beispiel mit
python log_all_data.py >> tesla.log
Den log kann man in einer anderen shell auf dem raspi verfolgen mit
tail -f tesla.log
Hier der Quelltext der aktuellen Version:
""" log_all_data.py - log all Tesla data available via the JSON REST API.
This tool requests all known state data for the first vehicle
that is found for the myTesla credentials configured via
the environment variables TESLA_EMAIL and TESLA_PASSWORD
in dynamic intervals.
While the drive state changes it is polled in a tight loop.
The poll interval increases when nothing has changed
and decreases otherwise.
All changed data are shown in plain text on stdout.
Please note that the use of the Tesla REST API in general
and the use of this software in particular is not endorsed by Tesla.
You use this software at your own risk.
The author does not take responsibility for anything related
to the use of this software.
See http://tff-forum.de/viewtopic.php?f=58&t=17286 for more info.
"""
import os
import sys
import time
import urllib2
import teslajson
class StateMonitor(object):
""" Monitor all Tesla states."""
def __init__(self, tesla_email, tesla_password):
self.requests = ("charge_state", "climate_state", "drive_state",
"gui_settings", "vehicle_state")
self.priority_requests = {1: ("drive_state", ),
2: ("drive_state", ),
4: ("charge_state", "drive_state", )}
self.old_values = dict([(r, {}) for r in self.requests])
connection = teslajson.Connection(tesla_email, tesla_password)
self.vehicle = connection.vehicles[0]
def wake_up(self):
""" Request wake up of car. """
delay = 1
while True:
try:
result = self.vehicle.wake_up()["response"]
print "\nwake_up %s:" % time.ctime()
for element in sorted(result):
print " %s=%s" % (element, result[element])
return
except (KeyError, urllib2.HTTPError, urllib2.URLError) as details:
delay *= 2
print "\nError:", time.ctime(), details
print "Waiting %d seconds before retrying." % delay
time.sleep(delay)
def request_state_group(self, request):
""" Request and process one group of Tesla states. """
header_printed = False
any_change = False
result = self.vehicle.data_request(request)
for element in sorted(result):
if element not in ("timestamp", "gps_as_of"):
old_value = self.old_values[request].get(element, '')
new_value = result[element]
if ((old_value == '') or
((new_value is not None) and (new_value != old_value))):
if not header_printed:
timestamp = None
if "timestamp" in result:
timestamp = result["timestamp"] / 1000
print "\n%s %s:" % (request, time.ctime(timestamp))
header_printed = True
any_change = True
print " %s=%s" % (element, new_value)
self.old_values[request][element] = new_value
return any_change
def check_states(self, interval):
""" Check all Tesla states. """
any_change = False
for request in self.priority_requests.get(interval, self.requests):
try:
if self.request_state_group(request):
any_change = True
if request == "drive_state":
interval = 1
except (urllib2.HTTPError, urllib2.URLError) as details:
print "\nError:", time.ctime(), details
return -1 # re-initialize.
if any_change:
if interval > 1:
interval /= 2
else:
if interval < 8192:
interval *= 2
return interval
if __name__ == "__main__":
state_monitor = StateMonitor(os.environ["TESLA_EMAIL"],
os.environ["TESLA_PASSWORD"])
poll_interval = -1
while True:
if poll_interval > 1:
time.sleep(poll_interval - time.time() % poll_interval)
elif poll_interval < 0:
state_monitor.wake_up()
poll_interval = 1
poll_interval = state_monitor.check_states(poll_interval)
sys.stdout.flush()
Edit: neue Version fängt „HTTP Error 500: Internal Server Error“ ab.
Edit: Neue Version mit dynamischen poll Intervallen.
Edit: Neue Version mit kontinuierlichem monitoring des drive_state beim Fahren.
Edit: Anleitung für raspberry.
Edit: Neue Version, die „None“ Werte unterdrückt und Netzwerkfehler besser behandelt.