diff --git a/src/cli/vehicle.rs b/src/cli/vehicle.rs index f28c166..9c5a5ef 100644 --- a/src/cli/vehicle.rs +++ b/src/cli/vehicle.rs @@ -1,6 +1,6 @@ use crate::cli::print_json; use crate::vehicles::{ - SetChargeLimit, SetChargingAmps, SetScheduledCharging, SetScheduledDeparture, + SetChargeLimit, SetChargingAmps, SetScheduledCharging, SetScheduledDeparture, SetTemperatures, }; use crate::{Api, VehicleId}; use clap::{Args, Subcommand}; @@ -45,6 +45,24 @@ pub enum VehicleCommand { /// Flash the lights. FlashLights, + + /// Enable the HVAC + EnableHvac, + + /// Disable the HVAC + DisableHvac, + + /// Set the temperature for the HVAC + HvacTemperature(SetTemperatures), + + /// Door unlock + DoorUnlock, + + /// Door lock + DoorLock, + + /// For keyless driving + RemoteStartDrive, } #[derive(Debug, Args)] @@ -97,6 +115,24 @@ impl VehicleArgs { VehicleCommand::FlashLights => { print_json(api.flash_lights(&self.id).await); } + VehicleCommand::EnableHvac => { + print_json(api.auto_conditioning_start(&self.id).await); + } + VehicleCommand::DisableHvac => { + print_json(api.auto_conditioning_stop(&self.id).await); + } + VehicleCommand::HvacTemperature(temps) => { + print_json(api.set_temps(&self.id, &temps).await); + } + VehicleCommand::DoorUnlock => { + print_json(api.door_unlock(&self.id).await); + } + VehicleCommand::DoorLock => { + print_json(api.door_lock(&self.id).await); + } + VehicleCommand::RemoteStartDrive => { + print_json(api.remote_start_drive(&self.id).await); + } } Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index 67d4aef..5c67845 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -119,7 +119,7 @@ impl Api { let response_body = request_builder .header("Accept", "application/json") - .header("Authorization", format!("Bearer {}", self.access_token.0)) + .header("Authorization", format!("Bearer {}", self.access_token.0.trim())) .send() .await .map_err(|source| TeslatteError::FetchError { diff --git a/src/vehicles.rs b/src/vehicles.rs index 94fe4b3..7d5c0e1 100644 --- a/src/vehicles.rs +++ b/src/vehicles.rs @@ -9,6 +9,7 @@ use serde::{Deserialize, Serialize}; impl Api { get!(vehicles, Vec, "/vehicles"); get_arg!(vehicle_data, VehicleData, "/vehicles/{}/vehicle_data", VehicleId); + post_arg_empty!(wake_up, "/vehicles/{}/command/wake_up", VehicleId); // Alerts post_arg_empty!(honk_horn, "/vehicles/{}/command/honk_horn", VehicleId); @@ -25,6 +26,16 @@ impl Api { post_arg_empty!(charge_stop, "/vehicles/{}/command/charge_stop", VehicleId); post_arg!(set_scheduled_charging, SetScheduledCharging, "/vehicles/{}/command/set_scheduled_charging", VehicleId); post_arg!(set_scheduled_departure, SetScheduledDeparture, "/vehicles/{}/command/set_scheduled_departure", VehicleId); + + // HVAC + post_arg_empty!(auto_conditioning_start, "/vehicles/{}/command/auto_conditioning_start", VehicleId); + post_arg_empty!(auto_conditioning_stop, "/vehicles/{}/command/auto_conditioning_stop", VehicleId); + post_arg!(set_temps, SetTemperatures, "/vehicles/{}/command/set_temps", VehicleId); + + // Doors + post_arg_empty!(door_unlock, "/vehicles/{}/command/door_unlock", VehicleId); + post_arg_empty!(door_lock, "/vehicles/{}/command/door_lock", VehicleId); + post_arg_empty!(remote_start_drive, "/vehicles/{}/command/remote_start_drive", VehicleId); } #[derive(Debug, Clone, Deserialize)] @@ -134,7 +145,7 @@ pub struct ClimateState { pub driver_temp_setting: f64, pub fan_status: i64, pub hvac_auto_request: String, - pub inside_temp: f64, + pub inside_temp: Option, pub is_auto_conditioning_on: Option, pub is_climate_on: bool, pub is_front_defroster_on: bool, @@ -344,6 +355,13 @@ pub struct SetChargeLimit { pub percent: u8, } +#[derive(Debug, Serialize)] +#[cfg_attr(feature = "cli", derive(clap::Args))] +pub struct SetTemperatures { + pub driver_temp: f32, + pub passenger_temp: f32, +} + /// set_scheduled_charging #[derive(Debug, Serialize)] #[cfg_attr(feature = "cli", derive(clap::Args))] @@ -708,6 +726,26 @@ mod tests { Api::parse_json::(&request_data, s.to_string()).unwrap(); } + #[test] + fn json_vehicle_data_htlc_2023_10_18() { + let s = include_str!("../testdata/vehicle_data_HTLC_2023_10_18.json"); + + let request_data = RequestData::GET { + url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", + }; + Api::parse_json::(&request_data, s.to_string()).unwrap(); + } + + #[test] + fn json_vehicle_data_htlc_2023_10_19() { + let s = include_str!("../testdata/vehicle_data_HTLC_2023_10_19.json"); + + let request_data = RequestData::GET { + url: "https://owner-api.teslamotors.com/api/1/vehicles/1234567890/vehicle_data", + }; + Api::parse_json::(&request_data, s.to_string()).unwrap(); + } + #[test] fn json_vehicle_data_bitcoin_lightning_2023_10_09() { let s = include_str!("../testdata/vehicle_data_BitcoinLightning_2023_10_09.json"); diff --git a/testdata/vehicle_data_HTLC_2023_10_18.json b/testdata/vehicle_data_HTLC_2023_10_18.json new file mode 100644 index 0000000..b5bcb9f --- /dev/null +++ b/testdata/vehicle_data_HTLC_2023_10_18.json @@ -0,0 +1,239 @@ +{ + "response": { + "id": 1492931365719407, + "user_id": 219663, + "vehicle_id": 1328174702, + "vin": "5YJSA7H4XFF088491", + "color": null, + "access_type": "OWNER", + "granular_access": { + "hide_private": false + }, + "tokens": [ + "a9a19b8188059903", + "dccadbc9684ff90d" + ], + "state": "online", + "in_service": false, + "id_s": "1492931365719407", + "calendar_enabled": true, + "api_version": 36, + "backseat_token": null, + "backseat_token_updated_at": null, + "ble_autopair_enrolled": false, + "charge_state": { + "battery_heater_on": false, + "battery_level": 77, + "battery_range": 208.76, + "charge_amps": 16, + "charge_current_request": 16, + "charge_current_request_max": 16, + "charge_enable_request": false, + "charge_energy_added": 27.67, + "charge_limit_soc": 80, + "charge_limit_soc_max": 100, + "charge_limit_soc_min": 50, + "charge_limit_soc_std": 90, + "charge_miles_added_ideal": 86, + "charge_miles_added_rated": 107.5, + "charge_port_cold_weather_mode": null, + "charge_port_color": "", + "charge_port_door_open": null, + "charge_port_latch": "", + "charge_rate": 0, + "charge_to_max_range": false, + "charger_actual_current": null, + "charger_phases": null, + "charger_pilot_current": null, + "charger_power": null, + "charger_voltage": null, + "charging_state": "Stopped", + "conn_charge_cable": "", + "est_battery_range": 149.35, + "fast_charger_brand": "", + "fast_charger_present": null, + "fast_charger_type": "", + "ideal_battery_range": 167.01, + "managed_charging_active": false, + "managed_charging_start_time": null, + "managed_charging_user_canceled": false, + "max_range_charge_counter": 0, + "minutes_to_full_charge": 0, + "not_enough_power_to_heat": null, + "off_peak_charging_enabled": true, + "off_peak_charging_times": "all_week", + "off_peak_hours_end_time": 360, + "preconditioning_enabled": false, + "preconditioning_times": "all_week", + "scheduled_charging_mode": "DepartBy", + "scheduled_charging_pending": true, + "scheduled_charging_start_time": 1697685600, + "scheduled_charging_start_time_app": 0, + "scheduled_charging_start_time_minutes": 320, + "scheduled_departure_time": 1697691600, + "scheduled_departure_time_minutes": 420, + "supercharger_session_trip_planner": false, + "time_to_full_charge": 0, + "timestamp": 1697641367303, + "trip_charging": null, + "usable_battery_level": 76, + "user_charge_enable_request": null + }, + "climate_state": { + "allow_cabin_overheat_protection": false, + "battery_heater": false, + "battery_heater_no_power": null, + "cabin_overheat_protection": "On", + "climate_keeper_mode": "off", + "defrost_mode": 0, + "driver_temp_setting": 22, + "fan_status": 0, + "hvac_auto_request": "On", + "inside_temp": null, + "is_auto_conditioning_on": null, + "is_climate_on": false, + "is_front_defroster_on": false, + "is_preconditioning": false, + "is_rear_defroster_on": false, + "left_temp_direction": null, + "max_avail_temp": 28, + "min_avail_temp": 15, + "outside_temp": null, + "passenger_temp_setting": 23, + "remote_heater_control_enabled": false, + "right_temp_direction": null, + "seat_heater_left": 0, + "seat_heater_rear_center": 0, + "seat_heater_rear_left": 0, + "seat_heater_rear_right": 0, + "seat_heater_right": 0, + "side_mirror_heaters": false, + "steering_wheel_heater": false, + "supports_fan_only_cabin_overheat_protection": false, + "timestamp": 1697641367302, + "wiper_blade_heater": false + }, + "drive_state": { + "gps_as_of": 1697641366, + "heading": 107, + "latitude": 47.004166, + "longitude": 8.603513, + "native_latitude": 47.004166, + "native_location_supported": 1, + "native_longitude": 8.603513, + "native_type": "wgs", + "power": 0, + "shift_state": null, + "speed": null, + "timestamp": 1697641367303 + }, + "gui_settings": { + "gui_24_hour_time": true, + "gui_charge_rate_units": "km/hr", + "gui_distance_units": "km/hr", + "gui_range_display": "Ideal", + "gui_temperature_units": "C", + "show_range_units": true, + "timestamp": 1697641367303 + }, + "vehicle_config": { + "can_accept_navigation_requests": true, + "can_actuate_trunks": true, + "car_special_type": "base", + "car_type": "models", + "charge_port_type": "EU", + "dashcam_clip_save_supported": false, + "default_charge_to_max": false, + "driver_assist": "MonoCam", + "ece_restrictions": true, + "efficiency_package": "Default", + "eu_vehicle": true, + "exterior_color": "MetallicBlack", + "front_drive_unit": "NoneOrSmall", + "has_air_suspension": true, + "has_ludicrous_mode": false, + "has_seat_cooling": false, + "headlamp_type": "Hid", + "interior_trim_type": "AllBlack", + "motorized_charge_port": true, + "plg": true, + "pws": false, + "rear_drive_unit": "Large", + "rear_seat_heaters": 1, + "rear_seat_type": 0, + "rhd": false, + "roof_color": "None", + "seat_type": 1, + "spoiler_type": "Passive", + "sun_roof_installed": 1, + "third_row_seats": "None", + "timestamp": 1697641367314, + "trim_badging": "p85d", + "use_range_badging": false, + "utc_offset": 7200, + "wheel_type": "Charcoal21" + }, + "vehicle_state": { + "api_version": 36, + "autopark_state_v2": "standby", + "autopark_style": "dead_man", + "calendar_supported": true, + "car_version": "2022.8.10.16 7477b4ff8e78", + "center_display_state": 0, + "dashcam_clip_save_available": false, + "dashcam_state": "", + "df": 0, + "dr": 0, + "fd_window": 0, + "feature_bitmask": "5,0", + "fp_window": 0, + "ft": 0, + "homelink_device_count": 0, + "homelink_nearby": false, + "is_user_present": false, + "last_autopark_error": "no_error", + "locked": true, + "media_state": { + "remote_control_enabled": true + }, + "notifications_supported": true, + "odometer": 105505.507055, + "parsed_calendar_supported": true, + "pf": 0, + "pr": 0, + "rd_window": 0, + "remote_start": false, + "remote_start_enabled": false, + "remote_start_supported": true, + "rp_window": 0, + "rt": 0, + "santa_mode": 0, + "smart_summon_available": false, + "software_update": { + "download_perc": 0, + "expected_duration_sec": 2700, + "install_perc": 1, + "status": "", + "version": "EU-2023.20-14615" + }, + "speed_limit_mode": { + "active": false, + "current_limit_mph": 90, + "max_limit_mph": 90, + "min_limit_mph": 50, + "pin_code_set": false + }, + "summon_standby_mode_enabled": false, + "sun_roof_percent_open": 0, + "sun_roof_state": "closed", + "timestamp": 1697641367282, + "tpms_pressure_fl": null, + "tpms_pressure_fr": null, + "tpms_pressure_rl": null, + "tpms_pressure_rr": null, + "valet_mode": false, + "valet_pin_needed": true, + "vehicle_name": "HTLC" + } + } +} diff --git a/testdata/vehicle_data_HTLC_2023_10_19.json b/testdata/vehicle_data_HTLC_2023_10_19.json new file mode 100644 index 0000000..af1512e --- /dev/null +++ b/testdata/vehicle_data_HTLC_2023_10_19.json @@ -0,0 +1,237 @@ +{ + "response": { + "id": 1492931365719407, + "user_id": 219663, + "vehicle_id": 1328174702, + "vin": "5YJSA7H4XFF088491", + "color": null, + "access_type": "OWNER", + "granular_access": { + "hide_private": false + }, + "tokens": [ + "2a9e0a14dbfe959a", + "55b97eddefba9dff" + ], + "state": "online", + "in_service": false, + "id_s": "1492931365719407", + "calendar_enabled": true, + "api_version": 36, + "backseat_token": null, + "backseat_token_updated_at": null, + "ble_autopair_enrolled": false, + "charge_state": { + "battery_heater_on": false, + "battery_level": 70, + "battery_range": 190.64, + "charge_amps": 32, + "charge_current_request": 32, + "charge_current_request_max": 32, + "charge_enable_request": true, + "charge_energy_added": 6.57, + "charge_limit_soc": 80, + "charge_limit_soc_max": 100, + "charge_limit_soc_min": 50, + "charge_limit_soc_std": 90, + "charge_miles_added_ideal": 20.5, + "charge_miles_added_rated": 25.5, + "charge_port_cold_weather_mode": null, + "charge_port_color": "", + "charge_port_door_open": null, + "charge_port_latch": "", + "charge_rate": 0, + "charge_to_max_range": false, + "charger_actual_current": null, + "charger_phases": null, + "charger_pilot_current": null, + "charger_power": null, + "charger_voltage": null, + "charging_state": "Disconnected", + "conn_charge_cable": "", + "est_battery_range": 140.73, + "fast_charger_brand": "", + "fast_charger_present": null, + "fast_charger_type": "", + "ideal_battery_range": 152.51, + "managed_charging_active": false, + "managed_charging_start_time": null, + "managed_charging_user_canceled": false, + "max_range_charge_counter": 0, + "minutes_to_full_charge": 0, + "not_enough_power_to_heat": null, + "off_peak_charging_enabled": false, + "off_peak_charging_times": "all_week", + "off_peak_hours_end_time": 360, + "preconditioning_enabled": false, + "preconditioning_times": "all_week", + "scheduled_charging_mode": "Off", + "scheduled_charging_pending": false, + "scheduled_charging_start_time": null, + "scheduled_departure_time": 1697691600, + "scheduled_departure_time_minutes": 420, + "supercharger_session_trip_planner": false, + "time_to_full_charge": 0, + "timestamp": 1697695372486, + "trip_charging": null, + "usable_battery_level": 70, + "user_charge_enable_request": null + }, + "climate_state": { + "allow_cabin_overheat_protection": false, + "battery_heater": false, + "battery_heater_no_power": null, + "cabin_overheat_protection": "On", + "climate_keeper_mode": "off", + "defrost_mode": 0, + "driver_temp_setting": 22, + "fan_status": 0, + "hvac_auto_request": "On", + "inside_temp": null, + "is_auto_conditioning_on": null, + "is_climate_on": false, + "is_front_defroster_on": false, + "is_preconditioning": false, + "is_rear_defroster_on": false, + "left_temp_direction": null, + "max_avail_temp": 28, + "min_avail_temp": 15, + "outside_temp": null, + "passenger_temp_setting": 23, + "remote_heater_control_enabled": false, + "right_temp_direction": null, + "seat_heater_left": 0, + "seat_heater_rear_center": 0, + "seat_heater_rear_left": 0, + "seat_heater_rear_right": 0, + "seat_heater_right": 0, + "side_mirror_heaters": false, + "steering_wheel_heater": false, + "supports_fan_only_cabin_overheat_protection": false, + "timestamp": 1697695372486, + "wiper_blade_heater": false + }, + "drive_state": { + "gps_as_of": 1697695371, + "heading": 297, + "latitude": 47.164341, + "longitude": 8.515789, + "native_latitude": 47.164341, + "native_location_supported": 1, + "native_longitude": 8.515789, + "native_type": "wgs", + "power": 0, + "shift_state": null, + "speed": null, + "timestamp": 1697695372486 + }, + "gui_settings": { + "gui_24_hour_time": true, + "gui_charge_rate_units": "km/hr", + "gui_distance_units": "km/hr", + "gui_range_display": "Ideal", + "gui_temperature_units": "C", + "show_range_units": true, + "timestamp": 1697695372486 + }, + "vehicle_config": { + "can_accept_navigation_requests": true, + "can_actuate_trunks": true, + "car_special_type": "base", + "car_type": "models", + "charge_port_type": "EU", + "dashcam_clip_save_supported": false, + "default_charge_to_max": false, + "driver_assist": "MonoCam", + "ece_restrictions": true, + "efficiency_package": "Default", + "eu_vehicle": true, + "exterior_color": "MetallicBlack", + "front_drive_unit": "NoneOrSmall", + "has_air_suspension": true, + "has_ludicrous_mode": false, + "has_seat_cooling": false, + "headlamp_type": "Hid", + "interior_trim_type": "AllBlack", + "motorized_charge_port": true, + "plg": true, + "pws": false, + "rear_drive_unit": "Large", + "rear_seat_heaters": 1, + "rear_seat_type": 0, + "rhd": false, + "roof_color": "None", + "seat_type": 1, + "spoiler_type": "Passive", + "sun_roof_installed": 1, + "third_row_seats": "None", + "timestamp": 1697695372487, + "trim_badging": "p85d", + "use_range_badging": false, + "utc_offset": 7200, + "wheel_type": "Charcoal21" + }, + "vehicle_state": { + "api_version": 36, + "autopark_state_v2": "ready", + "autopark_style": "dead_man", + "calendar_supported": true, + "car_version": "2022.8.10.16 7477b4ff8e78", + "center_display_state": 0, + "dashcam_clip_save_available": false, + "dashcam_state": "", + "df": 0, + "dr": 0, + "fd_window": 0, + "feature_bitmask": "5,0", + "fp_window": 0, + "ft": 0, + "homelink_device_count": 0, + "homelink_nearby": false, + "is_user_present": false, + "last_autopark_error": "no_error", + "locked": true, + "media_state": { + "remote_control_enabled": true + }, + "notifications_supported": true, + "odometer": 105531.786131, + "parsed_calendar_supported": true, + "pf": 0, + "pr": 0, + "rd_window": 0, + "remote_start": false, + "remote_start_enabled": false, + "remote_start_supported": true, + "rp_window": 0, + "rt": 0, + "santa_mode": 0, + "smart_summon_available": false, + "software_update": { + "download_perc": 0, + "expected_duration_sec": 2700, + "install_perc": 1, + "status": "", + "version": "EU-2023.20-14615" + }, + "speed_limit_mode": { + "active": false, + "current_limit_mph": 90, + "max_limit_mph": 90, + "min_limit_mph": 50, + "pin_code_set": false + }, + "summon_standby_mode_enabled": false, + "sun_roof_percent_open": 0, + "sun_roof_state": "closed", + "timestamp": 1697695372486, + "tpms_pressure_fl": null, + "tpms_pressure_fr": null, + "tpms_pressure_rl": null, + "tpms_pressure_rr": null, + "valet_mode": false, + "valet_pin_needed": true, + "vehicle_name": "HTLC" + } + } +}