fix: energy_left total_pack_energy` gone. Untagged handling
This commit is contained in:
parent
fcc9e63930
commit
1e6c1d5ff3
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file.
|
||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `energy_left` and `total_pack_energy` are gone from the API. (#22)
|
||||||
|
- Don't rely on serde untagged to determine the product type, as any missing
|
||||||
|
fields will give an unspecified error. Instead directly check known fields
|
||||||
|
that will probably not be removed. https://github.com/serde-rs/serde/pull/2376
|
||||||
|
|
||||||
## [0.1.13] - 2023-01-24
|
## [0.1.13] - 2023-01-24
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -37,17 +46,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- API changes for "api_version 67"
|
- API changes for "api_version 67"
|
||||||
|
|
||||||
- VehicleData new fields:
|
- VehicleData new fields:
|
||||||
|
|
||||||
- cached_data
|
- cached_data
|
||||||
- command_signing
|
- command_signing
|
||||||
- release_notes_supported
|
- release_notes_supported
|
||||||
|
|
||||||
- ClimateState new fields:
|
- ClimateState new fields:
|
||||||
|
|
||||||
- auto_steering_wheel_heat
|
- auto_steering_wheel_heat
|
||||||
- cop_activation_temperature,
|
- cop_activation_temperature,
|
||||||
- steering_wheel_heat_level
|
- steering_wheel_heat_level
|
||||||
|
|
||||||
- DriveState now Optional:
|
- DriveState now Optional:
|
||||||
|
|
||||||
- gps_as_of
|
- gps_as_of
|
||||||
- heading
|
- heading
|
||||||
- latitude
|
- latitude
|
||||||
|
@ -58,16 +71,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- native_type
|
- native_type
|
||||||
|
|
||||||
- DriveState new fields:
|
- DriveState new fields:
|
||||||
|
|
||||||
- active_route_traffic_minutes_delay
|
- active_route_traffic_minutes_delay
|
||||||
|
|
||||||
- GuiSettings new field:
|
- GuiSettings new field:
|
||||||
|
|
||||||
- gui_tirepressure_units
|
- gui_tirepressure_units
|
||||||
|
|
||||||
- VehicleConfig new fields:
|
- VehicleConfig new fields:
|
||||||
|
|
||||||
- cop_user_set_temp_supported
|
- cop_user_set_temp_supported
|
||||||
- webcam_selfie_supported
|
- webcam_selfie_supported
|
||||||
|
|
||||||
- VehicleState new fields:
|
- VehicleState new fields:
|
||||||
|
|
||||||
- media_info: MediaInfo
|
- media_info: MediaInfo
|
||||||
- tpms_hard_warning_fl
|
- tpms_hard_warning_fl
|
||||||
- tpms_hard_warning_fr
|
- tpms_hard_warning_fr
|
||||||
|
|
|
@ -18,7 +18,6 @@ pub struct SiteStatus {
|
||||||
pub battery_power: i64,
|
pub battery_power: i64,
|
||||||
pub battery_type: String,
|
pub battery_type: String,
|
||||||
pub breaker_alert_enabled: bool,
|
pub breaker_alert_enabled: bool,
|
||||||
pub energy_left: f64,
|
|
||||||
pub gateway_id: String,
|
pub gateway_id: String,
|
||||||
pub percentage_charged: f64,
|
pub percentage_charged: f64,
|
||||||
pub powerwall_onboarding_settings_set: bool,
|
pub powerwall_onboarding_settings_set: bool,
|
||||||
|
@ -29,14 +28,12 @@ pub struct SiteStatus {
|
||||||
pub site_name: String,
|
pub site_name: String,
|
||||||
pub storm_mode_enabled: bool,
|
pub storm_mode_enabled: bool,
|
||||||
pub sync_grid_alert_enabled: bool,
|
pub sync_grid_alert_enabled: bool,
|
||||||
pub total_pack_energy: i64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
#[derive(Debug, Clone, Deserialize, PartialEq)]
|
||||||
pub struct LiveStatus {
|
pub struct LiveStatus {
|
||||||
pub backup_capable: bool,
|
pub backup_capable: bool,
|
||||||
pub battery_power: i64,
|
pub battery_power: i64,
|
||||||
pub energy_left: f64,
|
|
||||||
pub generator_power: i64,
|
pub generator_power: i64,
|
||||||
pub grid_power: i64,
|
pub grid_power: i64,
|
||||||
pub grid_services_active: bool,
|
pub grid_services_active: bool,
|
||||||
|
|
|
@ -97,8 +97,6 @@ pub trait VehicleApi {
|
||||||
) -> Result<PostResponse, TeslatteError>;
|
) -> Result<PostResponse, TeslatteError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait EnergySitesApi {}
|
|
||||||
|
|
||||||
trait ApiValues {
|
trait ApiValues {
|
||||||
fn format(&self, url: &str) -> String;
|
fn format(&self, url: &str) -> String;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@ use crate::powerwall::PowerwallId;
|
||||||
use crate::vehicles::VehicleData;
|
use crate::vehicles::VehicleData;
|
||||||
use crate::{pub_get, OwnerApi};
|
use crate::{pub_get, OwnerApi};
|
||||||
use derive_more::Display;
|
use derive_more::Display;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
|
use serde_json::Value;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
|
@ -28,14 +29,44 @@ impl FromStr for EnergySiteId {
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct GatewayId(String);
|
pub struct GatewayId(String);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone)]
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum Product {
|
pub enum Product {
|
||||||
Vehicle(Box<VehicleData>),
|
Vehicle(Box<VehicleData>),
|
||||||
Solar(Box<SolarData>),
|
Solar(Box<SolarData>),
|
||||||
Powerwall(Box<PowerwallData>),
|
Powerwall(Box<PowerwallData>),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deserialize_product<'de, D>(deserializer: D) -> Result<Product, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
let v = Value::deserialize(deserializer)?;
|
||||||
|
|
||||||
|
if v.get("vehicle_id").is_some() {
|
||||||
|
let vehicle_data = VehicleData::deserialize(v).map_err(serde::de::Error::custom)?;
|
||||||
|
Ok(Product::Vehicle(Box::new(vehicle_data)))
|
||||||
|
} else if v.get("solar_type").is_some() {
|
||||||
|
let solar_data = SolarData::deserialize(v).map_err(serde::de::Error::custom)?;
|
||||||
|
Ok(Product::Solar(Box::new(solar_data)))
|
||||||
|
} else if v.get("battery_type").is_some() {
|
||||||
|
let powerwall_data = PowerwallData::deserialize(v).map_err(serde::de::Error::custom)?;
|
||||||
|
Ok(Product::Powerwall(Box::new(powerwall_data)))
|
||||||
|
} else {
|
||||||
|
Err(serde::de::Error::custom(
|
||||||
|
"No valid key found to determine the product type",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserialize<'de> for Product {
|
||||||
|
fn deserialize<D>(deserializer: D) -> Result<Product, D::Error>
|
||||||
|
where
|
||||||
|
D: Deserializer<'de>,
|
||||||
|
{
|
||||||
|
deserialize_product(deserializer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This is assumed from https://tesla-api.timdorr.com/api-basics/products
|
/// This is assumed from https://tesla-api.timdorr.com/api-basics/products
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
pub struct SolarData {
|
pub struct SolarData {
|
||||||
|
@ -61,8 +92,6 @@ pub struct PowerwallData {
|
||||||
pub id: PowerwallId,
|
pub id: PowerwallId,
|
||||||
pub gateway_id: GatewayId,
|
pub gateway_id: GatewayId,
|
||||||
pub asset_site_id: String,
|
pub asset_site_id: String,
|
||||||
pub energy_left: f64,
|
|
||||||
pub total_pack_energy: i64,
|
|
||||||
pub percentage_charged: f64,
|
pub percentage_charged: f64,
|
||||||
pub backup_capable: bool,
|
pub backup_capable: bool,
|
||||||
pub battery_power: i64,
|
pub battery_power: i64,
|
||||||
|
@ -239,4 +268,12 @@ mod tests {
|
||||||
OwnerApi::parse_json::<Vec<Product>>(&request_data, s.to_string(), PrintResponses::Pretty)
|
OwnerApi::parse_json::<Vec<Product>>(&request_data, s.to_string(), PrintResponses::Pretty)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn json_products_gak_2024_04_12() {
|
||||||
|
let s = include_str!("../testdata/products_gak_2024_04_12.json");
|
||||||
|
let request_data = RequestData::Get { url: "" };
|
||||||
|
OwnerApi::parse_json::<Vec<Product>>(&request_data, s.to_string(), PrintResponses::Pretty)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,9 +457,6 @@ pub struct GranularAccess {
|
||||||
pub hide_private: bool,
|
pub hide_private: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
|
||||||
pub struct Vehicles(Vec<Vehicle>);
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
pub struct Vehicle {
|
pub struct Vehicle {
|
||||||
pub id: VehicleId,
|
pub id: VehicleId,
|
||||||
|
|
70
testdata/products_gak_2024_04_12.json
vendored
Normal file
70
testdata/products_gak_2024_04_12.json
vendored
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
{
|
||||||
|
"count": 2,
|
||||||
|
"response": [
|
||||||
|
{
|
||||||
|
"access_type": "OWNER",
|
||||||
|
"api_version": 73,
|
||||||
|
"backseat_token": null,
|
||||||
|
"backseat_token_updated_at": null,
|
||||||
|
"ble_autopair_enrolled": false,
|
||||||
|
"cached_data": "",
|
||||||
|
"calendar_enabled": true,
|
||||||
|
"color": null,
|
||||||
|
"command_signing": "required",
|
||||||
|
"display_name": "Kool Beans",
|
||||||
|
"granular_access": {
|
||||||
|
"hide_private": false
|
||||||
|
},
|
||||||
|
"id": 123,
|
||||||
|
"id_s": "123",
|
||||||
|
"in_service": false,
|
||||||
|
"option_codes": null,
|
||||||
|
"release_notes_supported": true,
|
||||||
|
"state": "online",
|
||||||
|
"tokens": [],
|
||||||
|
"user_id": 123,
|
||||||
|
"vehicle_id": 123,
|
||||||
|
"vin": "LRW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"asset_site_id": "qwfp",
|
||||||
|
"backup_capable": true,
|
||||||
|
"battery_power": -1590,
|
||||||
|
"battery_type": "ac_powerwall",
|
||||||
|
"breaker_alert_enabled": true,
|
||||||
|
"components": {
|
||||||
|
"battery": true,
|
||||||
|
"battery_type": "ac_powerwall",
|
||||||
|
"grid": true,
|
||||||
|
"load_meter": true,
|
||||||
|
"market_type": "residential",
|
||||||
|
"solar": true,
|
||||||
|
"solar_type": "pv_panel",
|
||||||
|
"wall_connectors": [
|
||||||
|
{
|
||||||
|
"device_id": "qwfp",
|
||||||
|
"din": "qwfp",
|
||||||
|
"is_active": true,
|
||||||
|
"part_number": "1529455-02-D"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"energy_site_id": 1234,
|
||||||
|
"features": {
|
||||||
|
"rate_plan_manager_no_pricing_constraint": true
|
||||||
|
},
|
||||||
|
"gateway_id": "qwfp",
|
||||||
|
"go_off_grid_test_banner_enabled": null,
|
||||||
|
"id": "qwfp",
|
||||||
|
"percentage_charged": 48.872760297620715,
|
||||||
|
"powerwall_onboarding_settings_set": true,
|
||||||
|
"powerwall_tesla_electric_interested_in": null,
|
||||||
|
"resource_type": "battery",
|
||||||
|
"site_name": "",
|
||||||
|
"storm_mode_enabled": true,
|
||||||
|
"sync_grid_alert_enabled": true,
|
||||||
|
"vpp_tour_enabled": null,
|
||||||
|
"warp_site_number": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue