feat: support registered wall connectors

This commit is contained in:
gak 2023-11-06 11:57:10 +11:00
parent 36572f1ce2
commit eec64e3e7b
No known key found for this signature in database
5 changed files with 295 additions and 14 deletions

View file

@ -12,7 +12,7 @@ impl OwnerApi {
pub_get_args!(energy_sites_calendar_history, CalendarHistory, "/energy_sites/{}/calendar_history", CalendarHistoryValues);
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct SiteStatus {
pub backup_capable: bool,
pub battery_power: i64,
@ -32,7 +32,7 @@ pub struct SiteStatus {
pub total_pack_energy: i64,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct LiveStatus {
pub backup_capable: bool,
pub battery_power: i64,
@ -49,10 +49,31 @@ pub struct LiveStatus {
pub storm_mode_active: bool,
pub timestamp: String,
pub total_pack_energy: i64,
pub wall_connectors: Vec<()>, // TODO: gak: This is empty so I don't know what it looks like.
pub wall_connectors: Vec<LiveWallConnector>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct WallConnector {
pub device_id: String,
pub din: String,
pub is_active: bool,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct LiveWallConnector {
/// VIN of the car when connected to the wall connector.
pub vin: Option<String>,
pub din: String,
/// Observed:
/// 2: not plugged in
/// 4: plugged in (not charging)
pub wall_connector_state: i64,
pub wall_connector_power: i64,
pub wall_connector_fault_state: i64,
}
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct UserSettings {
pub breaker_alert_enabled: bool,
pub powerwall_onboarding_settings_set: bool,
@ -61,7 +82,7 @@ pub struct UserSettings {
pub sync_grid_alert_enabled: bool,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Schedule {
pub end_seconds: i64,
pub start_seconds: i64,
@ -69,20 +90,20 @@ pub struct Schedule {
pub week_days: Vec<i64>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct TouSettings {
pub optimization_strategy: String,
pub schedule: Vec<Schedule>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Geolocation {
pub latitude: f64,
pub longitude: f64,
pub source: String,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Components {
pub backup: bool,
pub backup_time_remaining_enabled: bool,
@ -115,7 +136,7 @@ pub struct Components {
pub wifi_commissioning_enabled: bool,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct Address {
pub address_line1: String,
pub city: String,
@ -124,7 +145,7 @@ pub struct Address {
pub zip: String,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct SiteInfo {
pub address: Address,
pub backup_reserve_percent: i64,
@ -192,7 +213,7 @@ impl Values for CalendarHistoryValues {
}
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct CalendarHistory {
pub serial_number: String,
/// Only appears in energy kind.
@ -202,14 +223,14 @@ pub struct CalendarHistory {
pub time_series: Option<Vec<Series>>,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum Series {
Power(PowerSeries),
Energy(EnergySeries),
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct PowerSeries {
pub timestamp: DateTime<FixedOffset>,
pub solar_power: f64,
@ -219,7 +240,7 @@ pub struct PowerSeries {
pub generator_power: f64,
}
#[derive(Debug, Clone, Deserialize)]
#[derive(Debug, Clone, Deserialize, PartialEq)]
pub struct EnergySeries {
pub timestamp: DateTime<FixedOffset>,
pub solar_energy_exported: f64,
@ -239,3 +260,85 @@ pub struct EnergySeries {
pub consumer_energy_imported_from_battery: f64,
pub consumer_energy_imported_from_generator: f64,
}
#[cfg(test)]
mod tests {
use crate::energy_sites::{LiveStatus, LiveWallConnector, WallConnector};
use crate::products::Product;
use crate::{OwnerApi, PrintResponses, RequestData};
#[test]
fn json_energy_sites_gak_2023_11_06() {
let s = include_str!("../testdata/energy_sites_gak_2023_11_06.json");
let request_data = RequestData::Get { url: "" };
let products = OwnerApi::parse_json::<Vec<Product>>(
&request_data,
s.to_string(),
PrintResponses::Pretty,
)
.unwrap();
let Product::Powerwall(powerwall) = &products[1] else {
panic!("Expected Powerwall product");
};
assert_eq!(
powerwall.components.wall_connectors[0],
WallConnector {
device_id: "uuid".to_string(),
din: "12345".to_string(),
is_active: true,
}
)
}
#[test]
fn json_energy_sites_live_power_gak_2023_11_06() {
let s = include_str!("../testdata/energy_sites_live_status_gak_plugged_in_2023_11_06.json");
let request_data = RequestData::Get { url: "" };
let live_status = OwnerApi::parse_json::<LiveStatus>(
&request_data,
s.to_string(),
PrintResponses::Pretty,
)
.unwrap();
let wall_connector = live_status.wall_connectors.first().unwrap();
assert_eq!(
wall_connector,
&LiveWallConnector {
vin: Some("1234".to_string()),
din: "5432".to_string(),
wall_connector_state: 4,
wall_connector_power: 0,
wall_connector_fault_state: 2,
}
);
}
#[test]
fn json_energy_sites_live_power_unplugged_charger_gak_2023_11_06() {
let s = include_str!("../testdata/energy_sites_live_status_gak_unplugged_2023_11_06.json");
let request_data = RequestData::Get { url: "" };
let live_status = OwnerApi::parse_json::<LiveStatus>(
&request_data,
s.to_string(),
PrintResponses::Pretty,
)
.unwrap();
let wall_connector = live_status.wall_connectors.first().unwrap();
assert_eq!(
wall_connector,
&LiveWallConnector {
vin: None,
din: "1234".to_string(),
wall_connector_state: 2,
wall_connector_power: 0,
wall_connector_fault_state: 2,
}
);
}
}

View file

@ -1,3 +1,4 @@
use crate::energy_sites::WallConnector;
use crate::error::TeslatteError;
use crate::powerwall::PowerwallId;
use crate::vehicles::VehicleData;
@ -79,6 +80,8 @@ pub struct Components {
pub grid: bool,
pub load_meter: bool,
pub market_type: String,
#[serde(default)]
pub wall_connectors: Vec<WallConnector>,
}
#[cfg(test)]

View file

@ -0,0 +1,120 @@
{
"count": 2,
"response": [
{
"access_type": "OWNER",
"api_version": 63,
"backseat_token": null,
"backseat_token_updated_at": null,
"ble_autopair_enrolled": false,
"cached_data": "",
"calendar_enabled": true,
"color": null,
"command_signing": "required",
"display_name": "Carname",
"granular_access": {
"hide_private": false
},
"id": 123456,
"id_s": "123546",
"in_service": false,
"option_codes": null,
"release_notes_supported": true,
"state": "online",
"tokens": [
"123",
"123"
],
"user_id": 1234,
"vehicle_config": {
"aux_park_lamps": "Eu",
"badge_version": 0,
"can_accept_navigation_requests": true,
"can_actuate_trunks": true,
"car_special_type": "base",
"car_type": "model3",
"charge_port_type": "CCS",
"cop_user_set_temp_supported": false,
"dashcam_clip_save_supported": true,
"default_charge_to_max": false,
"driver_assist": "TeslaAP3",
"ece_restrictions": false,
"efficiency_package": "M32021",
"eu_vehicle": true,
"exterior_color": "MidnightSilver",
"exterior_trim": "Black",
"exterior_trim_override": "",
"has_air_suspension": false,
"has_ludicrous_mode": false,
"has_seat_cooling": false,
"headlamp_type": "Global",
"interior_trim_type": "Black2",
"key_version": 2,
"motorized_charge_port": true,
"paint_color_override": "24,24,27,0.9,0.3",
"performance_package": "Base",
"plg": true,
"pws": false,
"rear_drive_unit": "PM216MOSFET",
"rear_seat_heaters": 1,
"rear_seat_type": 0,
"rhd": true,
"roof_color": "RoofColorGlass",
"seat_type": null,
"spoiler_type": "None",
"sun_roof_installed": null,
"supports_qr_pairing": false,
"third_row_seats": "None",
"timestamp": 1699226972553,
"trim_badging": "74d",
"use_range_badging": true,
"utc_offset": 36000,
"webcam_selfie_supported": true,
"webcam_supported": true,
"wheel_type": "StilettoRefresh19"
},
"vehicle_id": 123,
"vin": "1234"
},
{
"asset_site_id": "uuid",
"backup_capable": true,
"battery_power": -13520,
"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": "uuid",
"din": "12345",
"is_active": true
}
]
},
"energy_left": 36696.68421052631,
"energy_site_id": 12345,
"features": {
"rate_plan_manager_no_pricing_constraint": true
},
"gateway_id": "12345",
"go_off_grid_test_banner_enabled": null,
"id": "12345",
"percentage_charged": 87.61713394581648,
"powerwall_onboarding_settings_set": true,
"powerwall_tesla_electric_interested_in": null,
"resource_type": "battery",
"site_name": "address",
"storm_mode_enabled": true,
"sync_grid_alert_enabled": true,
"total_pack_energy": 41883,
"warp_site_number": "1234"
}
]
}

View file

@ -0,0 +1,28 @@
{
"response": {
"backup_capable": true,
"battery_power": -13950,
"energy_left": 37784.05263157895,
"generator_power": 0,
"grid_power": 0,
"grid_services_active": false,
"grid_services_power": 0,
"grid_status": "Active",
"island_status": "on_grid",
"load_power": 2226,
"percentage_charged": 90.21333866145918,
"solar_power": 16176,
"storm_mode_active": false,
"timestamp": "2023-11-06T10:30:11+11:00",
"total_pack_energy": 41883,
"wall_connectors": [
{
"din": "5432",
"vin": "1234",
"wall_connector_fault_state": 2,
"wall_connector_power": 0,
"wall_connector_state": 4
}
]
}
}

View file

@ -0,0 +1,27 @@
{
"response": {
"backup_capable": true,
"battery_power": 0,
"energy_left": 41880,
"generator_power": 0,
"grid_power": -12949,
"grid_services_active": false,
"grid_services_power": 0,
"grid_status": "Active",
"island_status": "on_grid",
"load_power": 3905,
"percentage_charged": 100,
"solar_power": 16854,
"storm_mode_active": false,
"timestamp": "2023-11-06T11:51:17+11:00",
"total_pack_energy": 41880,
"wall_connectors": [
{
"din": "1234",
"wall_connector_fault_state": 2,
"wall_connector_power": 0,
"wall_connector_state": 2
}
]
}
}