5 min read

Setting up TeslaLogger with a self-hosted Telemetry Server

Setting up TeslaLogger with a self-hosted Telemetry Server

This post expands in a bit more detail setting up TeslaLogger with a Local / self-hosted Tesla fleet telemetry server as outlined here:

TeslaLogger/TeslaLogger/LocalTelemetry.md at master · bassmaster187/TeslaLogger
TeslaLogger is a self hosted data logger for your Tesla Model S/3/X/Y. Actually it supports RaspberryPi 3B, 3B+, 4B, Docker and Synology NAS. - bassmaster187/TeslaLogger

If you don't need a writeup, here's the docker compose and configs for the stack:

services:
  fleet-telemetry:
    image: tesla/fleet-telemetry:latest
    command:
      - /fleet-telemetry
      - -config=/etc/fleet-telemetry/config.json
    ports:
      - 12345:12345
      - 5284:5284
    volumes:
      - ./config.json:/etc/fleet-telemetry/config.json:ro
      - ./certbot/conf/live/yourtelemetry.domainname.com/fullchain.pem:/certs/fullchain.pem:ro
      - ./certbot/conf/live/yourtelemetry.domainname.com/privkey.pem:/certs/privkey.pem:ro
  tesla_http_proxy:
    image: tesla/vehicle-command:latest
    ports:
      - 4443:4443
    environment:
      - TESLA_HTTP_PROXY_TLS_CERT=/config/tls-cert.pem
      - TESLA_HTTP_PROXY_TLS_KEY=/config/tls-key.pem
      - TESLA_HTTP_PROXY_HOST=0.0.0.0
      - TESLA_HTTP_PROXY_PORT=4443
      - TESLA_HTTP_PROXY_TIMEOUT=10s
      - TESLA_KEY_FILE=/config/fleet-key.pem
      - TESLA_VERBOSE=true
    volumes:
      - ./certbot/conf/live/yourtelemetry.domainname.com/fullchain.pem:/config/tls-cert.pem:ro
      - ./certbot/conf/live/yourtelemetry.domainname.com/privkey.pem:/config/tls-key.pem:ro
      - ./certs/private-key.pem:/config/fleet-key.pem:ro
  certbot:
    image: certbot/dns-cloudflare:latest
    volumes:
      - ./certbot/lib/:/var/lib/letsencrypt/:rw
      - ./certbot/conf/:/etc/letsencrypt/:rw
    command: certonly --non-interactive --agree-tos --dns-cloudflare
      --dns-cloudflare-credentials /etc/letsencrypt/cloudflare.ini -d
      yourtelemetry.domainname.com
  web:
    # This needs to be set up with SSL. Either configure it w/ the same LE certificate from above, or put this behind Cloudflare / reverse proxy that provisions automatically.
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html:ro
    ports:
     - "80:80"
    environment:
      - NGINX_HOST=yourtelemetry.domainname.com
      - NGINX_PORT=80
    restart: unless-stopped

fleet-telemetry/compose.yaml

{
    "host": "",
    "port": 12345,
    "log_level": "debug",
    "json_log_enable": true,
    "namespace": "TeslaLogger",
    "reliable_ack": true,
    "transmit_decoded_records": true,
    "logger": {
      "verbose": true
    },
    "zmq": {
        "addr": "tcp://*:5284",
        "verbose": true
    },
    "records": {
      "alerts": [
          "zmq"
      ],
      "errors": [
          "zmq"
      ],
      "V": [
          "zmq"
      ]
    },
    "tls": {
      "server_cert": "/certs/fullchain.pem",
      "server_key": "/certs/privkey.pem"
    }
}

fleet-telemetry/config.json

<?xml version="1.0" encoding="utf-8"?>
<configuration>
...
  <applicationSettings>
    <TeslaLogger.ApplicationSettings>
      ...
      <setting name="TelemetryServerURL" serializeAs="String">
        <value>tcp://192.168.xxx.xxx:5284</value>
      </setting>
      <setting name="UseTelemetryServer" serializeAs="String">
        <value>True</value>
      </setting>
      <setting name="TelemetryServerType" serializeAs="String">
        <value>ZMQ</value>
      </setting>
      <setting name="TeslaHttpProxyURL" serializeAs="String">
        <value>https://yourtelemetry.domainname.com:4443</value>
      </setting>
      <setting name="TelemetryClientID" serializeAs="String">
        <value>YOUR_TESLA_APPLICATION_CLIENT_ID</value>
      </setting>
    </TeslaLogger.ApplicationSettings>
  </applicationSettings>
...
</configuration>

teslalogger/TeslaLogger/bin/TeslaLogger.exe.config

^ If this file doesn't exist, copy teslalogger/TeslaLogger/App.config as teslalogger/TeslaLogger/bin/TeslaLogger.exe.config and make the changes above.

Tesla Setup

Pre-requisites
  • You need to have an FQDN and DNS record that points to the IP you're hosting this on. You also need to port forward ports: 12345,4443.
Notes
  • When creating a developer application, set the origin URL as the same domain you used in the docker compose. (eg: yourtelemetry.domainname.com)
  • For redirect URL, you can set it to whatever you want. It really doesn't matter as long as you keep it consistent (eg: localhost)

Make a note of your: client_id, redirect_uri, VIN

Steps
CODE=NA_xxx
CLIENT_ID=YOUR_APP_CLIENT_ID
CLIENT_SECRET=YOUR_APP_CLIENT_SECRET
AUDIENCE=https://fleet-api.prd.na.vn.cloud.tesla.com
CALLBACK=YOUR_REDIRECT_URI
curl --request POST \
  --header 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode 'grant_type=authorization_code' \
  --data-urlencode "client_id=$CLIENT_ID" \
  --data-urlencode "client_secret=$CLIENT_SECRET" \
  --data-urlencode "code=$CODE" \
  --data-urlencode "audience=$AUDIENCE" \
  --data-urlencode "redirect_uri=$CALLBACK" \
  'https://fleet-auth.prd.vn.cloud.tesla.com/oauth2/v3/token'
    • This will return something like: {"access_token":"eyJhbGciOiJSUxxx","refresh_token":"NA_xxx","id_token":"eyJhbGciOxxx","expires_in":28800,"state":"$STATE","token_type":"Bearer"}%
    • Keep track of the access_token and your refresh_token.
  • Pair the Virtual key:
    • On your phone with the Tesla app installed, go to this URL (replace placeholder with your FQDN): https://tesla.com/_ak/yourtelemetry.domainname.com
  • Configure fleet telemetry (this is what instructs Tesla's API to stream data to your telemetry-server. Note the curl URL is to your command_proxy):
    • export TESLA_AUTH_TOKEN=your_access_token
    • For the "ca" field, you can get the certificate authority certificate by running
openssl s_client -showcerts -connect yourtelemetry.domainname.com:12345
    • The string you're looking for is just under 1 s:C=US, O=Let's Encrypt, CN=E5...--—BEGIN CERTIFICATE--—. REMOVE all line breaks and insert it to the code snippet below at CERTIFICATE_DATA_HERE.
curl -H "Authorization: Bearer $TESLA_AUTH_TOKEN" \
     -H 'Content-Type: application/json' \
     --data '{
  "vins": ["YOUR_CAR_VIN"],
  "config": {
    "hostname": "yourtelemetry.domainname.com",
    "port": 12345,
    "ca": "-----BEGIN CERTIFICATE-----\nCERTIFICATE_DATA_HERE\n-----END CERTIFICATE-----\n",
    "fields": {
      "PackVoltage": { "interval_seconds": 10 },
      "PackCurrent": { "interval_seconds": 10 },
      "ACChargingPower": { "interval_seconds": 10 },
      "ACChargingEnergyIn" : { "interval_seconds": 60 },
      "DCChargingPower": { "interval_seconds": 1 },
      "DCChargingEnergyIn" : { "interval_seconds": 30 },
      "ChargeLimitSoc": { "interval_seconds": 30 },
      "FastChargerPresent": { "interval_seconds": 5 },
      "Location": { "interval_seconds": 1 },
      "VehicleSpeed": { "interval_seconds": 1 },
      "Gear": { "interval_seconds": 5 },
      "EstBatteryRange": { "interval_seconds": 30 },
      "RatedRange": { "interval_seconds": 30 },
      "IdealBatteryRange": { "interval_seconds": 30 },
      "Soc": { "interval_seconds": 15 },
      "ModuleTempMax": { "interval_seconds": 60 },
      "NumModuleTempMax": { "interval_seconds": 60 },
      "ModuleTempMin": { "interval_seconds": 60 },
      "NumModuleTempMin": { "interval_seconds": 60 },
      "NumBrickVoltageMax": { "interval_seconds": 60 },
      "BrickVoltageMax": { "interval_seconds": 60 },
      "NumBrickVoltageMin": { "interval_seconds": 60 },
      "BrickVoltageMin": { "interval_seconds": 60 },
      "Odometer": { "interval_seconds": 30 },
      "EnergyRemaining": { "interval_seconds": 60 },
      "TimeToFullCharge": { "interval_seconds": 60 },
      "EstBatteryRange": { "interval_seconds": 60 },
      "SentryMode": { "interval_seconds": 10 },
      "ChargeState": { "interval_seconds": 10 },
      "DetailedChargeState": { "interval_seconds": 10 },
      "BatteryHeaterOn": { "interval_seconds": 10 },
      "DoorState": { "interval_seconds": 10 },
      "FdWindow": { "interval_seconds": 10 },
      "FpWindow": { "interval_seconds": 10 },
      "RdWindow": { "interval_seconds": 10 },
      "RpWindow": { "interval_seconds": 10 },
      "TpmsPressureFl": { "interval_seconds": 10 },
      "TpmsPressureFr": { "interval_seconds": 10 },
      "TpmsPressureRl": { "interval_seconds": 10 },
      "TpmsPressureRr": { "interval_seconds": 10 },
      "VehicleName": { "interval_seconds": 600 },
      "CarType": { "interval_seconds": 600 },
      "Trim": { "interval_seconds": 600 },
      "Version": { "interval_seconds": 600 },
      "InsideTemp": { "interval_seconds": 60 },
      "OutsideTemp": { "interval_seconds": 60 },
      "Locked": { "interval_seconds": 5 },
      "ChargePortDoorOpen": { "interval_seconds": 10 },
      "PreconditioningEnabled": { "interval_seconds": 30 },
      "DefrostForPreconditioning": { "interval_seconds": 30 },
      "DefrostMode": { "interval_seconds": 60 },
      "FastChargerType": { "interval_seconds": 10 },
      "HvacACEnabled": { "interval_seconds": 60 },
      "HvacAutoMode": { "interval_seconds": 60 },
      "HvacLeftTemperatureRequest": { "interval_seconds": 60 },
      "HvacSteeringWheelHeatAuto": { "interval_seconds": 60 },
      "HvacSteeringWheelHeatLevel": { "interval_seconds": 60 },
      "SoftwareUpdateVersion": { "interval_seconds": 600 },
      "SoftwareUpdateDownloadPercentComplete": { "interval_seconds": 600 },
      "SoftwareUpdateExpectedDurationMinutes": { "interval_seconds": 600 },
      "SoftwareUpdateInstallationPercentComplete": { "interval_seconds": 600 },
      "SoftwareUpdateScheduledStartTime": { "interval_seconds": 600 },
      "WiperHeatEnabled": { "interval_seconds": 60 }
    }
  }
}' \
      -X POST \
      -i https://yourtelemetry.domainname.com:4443/api/1/vehicles/fleet_telemetry_config
    • You can verify this propagated by running: curl -H "Authorization: Bearer $TESLA_AUTH_TOKEN" -i "https://yourtelemetry.domainname.com:4443/api/1/vehicles/$VIN/fleet_telemetry_config"
  • You're ready to add your keys to TeslaLogger!
    • id is the car ID that corresponds to the car you want to add in TeslaLogger (Eg: Car 1 => id=1).
    • your_teslalogger.com:8888/admin/password_fleet.php?id=1&vin=YOUR_CAR_VIN&AT=eyJhbGcxxxxxxxxx&RT=NA_xxxxxxx
  • Check the log to make sure there are no errors.

Congratulations, you did it!