Skip to content

Instantly share code, notes, and snippets.

@emily-pesce
Last active January 24, 2021 12:39
Show Gist options
  • Save emily-pesce/69f8ada9494daee82d2d5fe3a92e32cc to your computer and use it in GitHub Desktop.
Save emily-pesce/69f8ada9494daee82d2d5fe3a92e32cc to your computer and use it in GitHub Desktop.
Google Sheet Data Logger for Teslas
function getData() {
var id = 'REPLACE_WITH_GOOGLE_SHEET_ID';
var sheet = SpreadsheetApp.openById(id);
var today = Utilities.formatDate(new Date(), 'America/New_York', "MM/dd/yy hh:mm:ss a");
var base_url = 'https://owner-api.teslamotors.com/api/1/vehicles/'
var auth_token = "Bearer REPLACE_WITH_AUTHORIZATION_STRING"
var response = UrlFetchApp.fetch(base_url, {
'headers':{
Authorization:auth_token
},
muteHttpExceptions:true
});
if (response.getResponseCode() == 401) {
MailApp.sendEmail('REPLACE_WITH_YOUR_EMAIL', 'tesla api auth failed', 'tesla api auth failed');
}
var data = JSON.parse(response.getContentText());
data.response.forEach(function( d ) {
var name = d.display_name
//***VEHICLE STATE***
var url = base_url + d.id_s + '/data_request/vehicle_state';
var vehicle_response = UrlFetchApp.fetch(url, {
'headers':{
Authorization:auth_token
},
muteHttpExceptions:true
});
var vehicle_data = JSON.parse(vehicle_response);
//var name = vehicle_data.response.display_name;
var version = vehicle_data.response.car_version;
var miles = vehicle_data.response.odometer;
var timestamp = new Date(parseInt(vehicle_data.response.timestamp));
//***DRIVE STATE***
var url = base_url + d.id_s + '/data_request/drive_state';
var drive_response = UrlFetchApp.fetch(url, {
'headers':{
Authorization:auth_token
},
muteHttpExceptions:true
});
var drive_data = JSON.parse(drive_response);
var drive_speed = drive_data.response.speed;
var drive_power = drive_data.response.power;
var drive_lat = drive_data.response.latitude;
var drive_lon = drive_data.response.longitude;
var drive_shift_state = drive_data.response.shift_state;
var drive_heading = drive_data.response.heading;
//***CLIMATE STATE***
var url = base_url + d.id_s + '/data_request/climate_state';
var climate_response = UrlFetchApp.fetch(url, {
'headers':{
Authorization:auth_token
},
muteHttpExceptions:true
});
var climate_data = JSON.parse(climate_response);
var climate_inside = climate_data.response.inside_temp;
var climate_outside = climate_data.response.outside_temp;
var climate_battery_heater = climate_data.response.battery_heater;
//*** START CHARGE STATE ***
var url = base_url + d.id_s + '/data_request/charge_state';
var charge_response = UrlFetchApp.fetch(url, {
'headers':{
Authorization:auth_token
},
muteHttpExceptions:true
});
var charge_data = JSON.parse(charge_response);
var charging_state = charge_data.response.charging_state;
var battery_level = charge_data.response.battery_level;
//var battery_current = ""; //charge_data.battery_current;
var charger_voltage = charge_data.response.charger_voltage;
var charger_actual_current = charge_data.response.charger_actual_current;
var charger_power = charge_data.response.charger_power;
var charge_energy_added = charge_data.response.charge_energy_added;
var charge_miles_added_rated = charge_data.response.charge_miles_added_rated;
var charge_miles_added_ideal = charge_data.response.charge_miles_added_ideal;
var rated_range = charge_data.response.battery_range
var est_range = charge_data.response.est_battery_range;
var ideal_range = charge_data.response.ideal_battery_range;
var implied_max_rated_range = rated_range / (battery_level / 100);
var implied_estimated_kwh_mi = ((battery_level / 100) * 72600) / est_range;
var max_range_cycles = charge_data.response.max_range_charge_counter;
var battery_heater_on = charge_data.response.battery_heater_on;
var trip_charging = charge_data.response.trip_charging;
var fast_charger = charge_data.response.fast_charger_present;
var usable_battery_level = charge_data.response.usable_battery_level;
var not_enough_power_to_heat = charge_data.response.not_enough_power_to_heat;
var time_to_full_charge = charge_data.response.time_to_full_charge;
var charge_limit_soc = charge_data.response.charge_limit_soc;
//*** END CHARGE STATE ***
//Create new sheet for new Car Name if it doesn't already exist
try {
sheet.setActiveSheet(sheet.getSheetByName(name));
} catch (e) {
sheet.insertSheet(name);
}
var data_sheet = sheet.getSheetByName(name);
data_sheet.appendRow([today,
timestamp,
name,
miles,
version,
rated_range,
est_range,
ideal_range,
charging_state,
battery_level,
//battery_current,
charger_voltage,
charger_actual_current,
charger_power,
charge_energy_added,
charge_miles_added_rated,
charge_miles_added_ideal,
battery_heater_on,
max_range_cycles,
charge_limit_soc,
trip_charging,
fast_charger,
usable_battery_level,
not_enough_power_to_heat,
time_to_full_charge,
implied_max_rated_range,
implied_estimated_kwh_mi,
drive_shift_state,
drive_speed,
drive_power,
drive_lat,
drive_lon,
drive_heading,
climate_inside,
climate_outside,
climate_battery_heater
]);
});
}
@Woekje
Copy link

Woekje commented Jan 20, 2021

I have the same problem, getting a 401 when getting the vehicle list. The token seems to be valid. I think the car doesn't need to be awake for the vehicle list, but in any case I made sure it was awake.
Any ideas?

Update, I added User-Agent and X-Tesla-User-Agent headers, and also used a different too4l to get a token, and now it works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment