feat: rename and add api calls (energy_sites)
- rename api/cli energy_sites to products (to match the api) - add energy_sites site_status - add energy_sites live_status - add energy_sites site_info
This commit is contained in:
parent
cc01e30c63
commit
a64a04e3d7
|
@ -1,5 +1,6 @@
|
||||||
use std::env;
|
use std::env;
|
||||||
use teslatte::auth::AccessToken;
|
use teslatte::auth::AccessToken;
|
||||||
|
use teslatte::products::Product;
|
||||||
use teslatte::Api;
|
use teslatte::Api;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -16,12 +17,46 @@ async fn main() {
|
||||||
};
|
};
|
||||||
|
|
||||||
let vehicles = api.vehicles().await.unwrap();
|
let vehicles = api.vehicles().await.unwrap();
|
||||||
dbg!(&vehicles);
|
dbg!(&*vehicles);
|
||||||
|
|
||||||
if !vehicles.is_empty() {
|
if !vehicles.is_empty() {
|
||||||
let vehicle_data = api.vehicle_data(&vehicles[0].id).await.unwrap();
|
let vehicle_data = api.vehicle_data(&vehicles[0].id).await.unwrap();
|
||||||
dbg!(vehicle_data);
|
dbg!(&*vehicle_data);
|
||||||
} else {
|
} else {
|
||||||
println!("No vehicles found!");
|
println!("No vehicles found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let products = api.products().await.unwrap();
|
||||||
|
dbg!(&*products);
|
||||||
|
|
||||||
|
if !products.is_empty() {
|
||||||
|
for product in &*products {
|
||||||
|
match product {
|
||||||
|
Product::Vehicle(v) => {
|
||||||
|
dbg!(v);
|
||||||
|
}
|
||||||
|
|
||||||
|
Product::Solar(e) => {
|
||||||
|
let site_info = api.energy_sites_site_info(&e.energy_site_id).await.unwrap();
|
||||||
|
dbg!(&*site_info);
|
||||||
|
|
||||||
|
let live_info = api
|
||||||
|
.energy_sites_live_status(&e.energy_site_id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
dbg!(&*live_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
Product::Powerwall(p) => {
|
||||||
|
let live_info = api
|
||||||
|
.energy_sites_live_status(&p.energy_site_id)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
dbg!(&*live_info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println!("No products found!");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
2
justfile
2
justfile
|
@ -9,7 +9,7 @@ no_token_test:
|
||||||
token_tests:
|
token_tests:
|
||||||
cargo run -- api vehicles
|
cargo run -- api vehicles
|
||||||
cargo run --no-default-features --features cli -- api vehicles
|
cargo run --no-default-features --features cli -- api vehicles
|
||||||
cargo run -- api energy-sites
|
cargo run -- api products
|
||||||
|
|
||||||
publish version:
|
publish version:
|
||||||
git diff-index --quiet HEAD
|
git diff-index --quiet HEAD
|
||||||
|
|
|
@ -1,105 +0,0 @@
|
||||||
use crate::energy::EnergySiteId;
|
|
||||||
use crate::Values;
|
|
||||||
use crate::{get_args, join_query_pairs, rfc3339, Api};
|
|
||||||
use chrono::{DateTime, FixedOffset};
|
|
||||||
use serde::Deserialize;
|
|
||||||
use strum::{Display, EnumString, IntoStaticStr};
|
|
||||||
|
|
||||||
#[rustfmt::skip]
|
|
||||||
impl Api {
|
|
||||||
get_args!(energy_sites_calendar_history, CalendarHistory, "/energy_sites/{}/calendar_history", CalendarHistoryValues);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Display, EnumString, IntoStaticStr)]
|
|
||||||
#[strum(serialize_all = "snake_case")]
|
|
||||||
pub enum HistoryKind {
|
|
||||||
Power,
|
|
||||||
Energy,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Display, EnumString, IntoStaticStr)]
|
|
||||||
#[strum(serialize_all = "snake_case")]
|
|
||||||
pub enum HistoryPeriod {
|
|
||||||
Day,
|
|
||||||
Month,
|
|
||||||
Year,
|
|
||||||
Lifetime,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct CalendarHistoryValues {
|
|
||||||
// Modify URL:
|
|
||||||
pub site_id: EnergySiteId,
|
|
||||||
|
|
||||||
// Query params:
|
|
||||||
pub period: HistoryPeriod,
|
|
||||||
pub kind: HistoryKind,
|
|
||||||
pub start_date: Option<DateTime<FixedOffset>>,
|
|
||||||
pub end_date: Option<DateTime<FixedOffset>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Values for CalendarHistoryValues {
|
|
||||||
fn format(&self, url: &str) -> String {
|
|
||||||
let url = url.replace("{}", &format!("{}", self.site_id.0));
|
|
||||||
let mut pairs: Vec<(&str, String)> = vec![
|
|
||||||
("period", self.period.to_string()),
|
|
||||||
("kind", self.kind.to_string()),
|
|
||||||
];
|
|
||||||
if let Some(start_date) = self.start_date {
|
|
||||||
let start_date = rfc3339(&start_date);
|
|
||||||
pairs.push(("start_date", start_date));
|
|
||||||
}
|
|
||||||
if let Some(end_date) = self.end_date {
|
|
||||||
let end_date = rfc3339(&end_date);
|
|
||||||
pairs.push(("end_date", end_date));
|
|
||||||
}
|
|
||||||
format!("{}?{}", url, join_query_pairs(&pairs))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct CalendarHistory {
|
|
||||||
pub serial_number: String,
|
|
||||||
/// Only appears in energy kind.
|
|
||||||
pub period: Option<String>,
|
|
||||||
pub installation_time_zone: String,
|
|
||||||
/// Optional because if there are no `Series` fields, this field is omitted.
|
|
||||||
pub time_series: Option<Vec<Series>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
#[serde(untagged)]
|
|
||||||
pub enum Series {
|
|
||||||
Power(PowerSeries),
|
|
||||||
Energy(EnergySeries),
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct PowerSeries {
|
|
||||||
pub timestamp: DateTime<FixedOffset>,
|
|
||||||
pub solar_power: f64,
|
|
||||||
pub battery_power: f64,
|
|
||||||
pub grid_power: f64,
|
|
||||||
pub grid_services_power: f64,
|
|
||||||
pub generator_power: f64,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct EnergySeries {
|
|
||||||
pub timestamp: DateTime<FixedOffset>,
|
|
||||||
pub solar_energy_exported: f64,
|
|
||||||
pub generator_energy_exported: f64,
|
|
||||||
pub grid_energy_imported: f64,
|
|
||||||
pub grid_services_energy_imported: f64,
|
|
||||||
pub grid_services_energy_exported: f64,
|
|
||||||
pub grid_energy_exported_from_solar: f64,
|
|
||||||
pub grid_energy_exported_from_generator: f64,
|
|
||||||
pub grid_energy_exported_from_battery: f64,
|
|
||||||
pub battery_energy_exported: f64,
|
|
||||||
pub battery_energy_imported_from_grid: f64,
|
|
||||||
pub battery_energy_imported_from_solar: f64,
|
|
||||||
pub battery_energy_imported_from_generator: f64,
|
|
||||||
pub consumer_energy_imported_from_grid: f64,
|
|
||||||
pub consumer_energy_imported_from_solar: f64,
|
|
||||||
pub consumer_energy_imported_from_battery: f64,
|
|
||||||
pub consumer_energy_imported_from_generator: f64,
|
|
||||||
}
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::calendar_history::{CalendarHistoryValues, HistoryKind, HistoryPeriod};
|
|
||||||
use crate::cli::print_json;
|
use crate::cli::print_json;
|
||||||
use crate::energy::EnergySiteId;
|
use crate::energy_sites::{CalendarHistoryValues, HistoryKind, HistoryPeriod};
|
||||||
|
use crate::products::EnergySiteId;
|
||||||
use crate::Api;
|
use crate::Api;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
use clap::{Args, Subcommand};
|
use clap::{Args, Subcommand};
|
||||||
|
@ -8,6 +8,9 @@ use miette::{IntoDiagnostic, WrapErr};
|
||||||
|
|
||||||
#[derive(Debug, Subcommand)]
|
#[derive(Debug, Subcommand)]
|
||||||
pub enum EnergySiteCommand {
|
pub enum EnergySiteCommand {
|
||||||
|
SiteStatus,
|
||||||
|
LiveStatus,
|
||||||
|
SiteInfo,
|
||||||
CalendarHistory(CalendarHistoryArgs),
|
CalendarHistory(CalendarHistoryArgs),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +25,15 @@ pub struct EnergySiteArgs {
|
||||||
impl EnergySiteArgs {
|
impl EnergySiteArgs {
|
||||||
pub async fn run(&self, api: &Api) -> miette::Result<()> {
|
pub async fn run(&self, api: &Api) -> miette::Result<()> {
|
||||||
match &self.command {
|
match &self.command {
|
||||||
|
EnergySiteCommand::SiteStatus => {
|
||||||
|
print_json(api.energy_sites_site_status(&self.id).await);
|
||||||
|
}
|
||||||
|
EnergySiteCommand::LiveStatus => {
|
||||||
|
print_json(api.energy_sites_live_status(&self.id).await);
|
||||||
|
}
|
||||||
|
EnergySiteCommand::SiteInfo => {
|
||||||
|
print_json(api.energy_sites_site_info(&self.id).await);
|
||||||
|
}
|
||||||
EnergySiteCommand::CalendarHistory(args) => {
|
EnergySiteCommand::CalendarHistory(args) => {
|
||||||
let start_date = args
|
let start_date = args
|
||||||
.start
|
.start
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::calendar_history::{HistoryKind, HistoryPeriod};
|
|
||||||
use crate::cli::print_json_data;
|
use crate::cli::print_json_data;
|
||||||
|
use crate::energy_sites::{HistoryKind, HistoryPeriod};
|
||||||
use crate::powerwall::{PowerwallEnergyHistoryValues, PowerwallId};
|
use crate::powerwall::{PowerwallEnergyHistoryValues, PowerwallId};
|
||||||
use crate::Api;
|
use crate::Api;
|
||||||
use clap::{Args, Subcommand};
|
use clap::{Args, Subcommand};
|
||||||
|
|
239
src/energy_sites.rs
Normal file
239
src/energy_sites.rs
Normal file
|
@ -0,0 +1,239 @@
|
||||||
|
use crate::products::EnergySiteId;
|
||||||
|
use crate::{get_arg, get_args, join_query_pairs, rfc3339, Api, Values};
|
||||||
|
use chrono::{DateTime, FixedOffset};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use strum::{Display, EnumString, IntoStaticStr};
|
||||||
|
|
||||||
|
#[rustfmt::skip]
|
||||||
|
impl Api {
|
||||||
|
get_arg!(energy_sites_site_status, SiteStatus, "/energy_sites/{}/site_status", EnergySiteId);
|
||||||
|
get_arg!(energy_sites_live_status, LiveStatus, "/energy_sites/{}/live_status", EnergySiteId);
|
||||||
|
get_arg!(energy_sites_site_info, SiteInfo, "/energy_sites/{}/site_info", EnergySiteId);
|
||||||
|
get_args!(energy_sites_calendar_history, CalendarHistory, "/energy_sites/{}/calendar_history", CalendarHistoryValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct SiteStatus {
|
||||||
|
pub backup_capable: bool,
|
||||||
|
pub battery_power: i64,
|
||||||
|
pub battery_type: String,
|
||||||
|
pub breaker_alert_enabled: bool,
|
||||||
|
pub energy_left: f64,
|
||||||
|
pub gateway_id: String,
|
||||||
|
pub percentage_charged: f64,
|
||||||
|
pub powerwall_onboarding_settings_set: bool,
|
||||||
|
pub powerwall_tesla_electric_interested_in: Option<()>, // TODO: Unknown type. Was null.
|
||||||
|
pub resource_type: String, // battery
|
||||||
|
pub site_name: String,
|
||||||
|
pub storm_mode_enabled: bool,
|
||||||
|
pub sync_grid_alert_enabled: bool,
|
||||||
|
pub total_pack_energy: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct LiveStatus {
|
||||||
|
pub backup_capable: bool,
|
||||||
|
pub battery_power: i64,
|
||||||
|
pub energy_left: f64,
|
||||||
|
pub generator_power: i64,
|
||||||
|
pub grid_power: i64,
|
||||||
|
pub grid_services_active: bool,
|
||||||
|
pub grid_services_power: i64,
|
||||||
|
pub grid_status: String,
|
||||||
|
pub island_status: String,
|
||||||
|
pub load_power: i64,
|
||||||
|
pub percentage_charged: f64,
|
||||||
|
pub solar_power: i64,
|
||||||
|
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.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct UserSettings {
|
||||||
|
pub breaker_alert_enabled: bool,
|
||||||
|
pub powerwall_onboarding_settings_set: bool,
|
||||||
|
pub powerwall_tesla_electric_interested_in: bool,
|
||||||
|
pub storm_mode_enabled: bool,
|
||||||
|
pub sync_grid_alert_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Schedule {
|
||||||
|
pub end_seconds: i64,
|
||||||
|
pub start_seconds: i64,
|
||||||
|
pub target: String,
|
||||||
|
pub week_days: Vec<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct TouSettings {
|
||||||
|
pub optimization_strategy: String,
|
||||||
|
pub schedule: Vec<Schedule>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Geolocation {
|
||||||
|
pub latitude: f64,
|
||||||
|
pub longitude: f64,
|
||||||
|
pub source: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Components {
|
||||||
|
pub backup: bool,
|
||||||
|
pub backup_time_remaining_enabled: bool,
|
||||||
|
pub battery: bool,
|
||||||
|
pub battery_solar_offset_view_enabled: bool,
|
||||||
|
pub battery_type: String,
|
||||||
|
pub car_charging_data_supported: bool,
|
||||||
|
pub configurable: bool,
|
||||||
|
pub edit_setting_energy_exports: bool,
|
||||||
|
pub edit_setting_grid_charging: bool,
|
||||||
|
pub edit_setting_permission_to_export: bool,
|
||||||
|
pub energy_service_self_scheduling_enabled: bool,
|
||||||
|
pub energy_value_header: String,
|
||||||
|
pub energy_value_subheader: String,
|
||||||
|
pub flex_energy_request_capable: bool,
|
||||||
|
pub gateway: String,
|
||||||
|
pub grid: bool,
|
||||||
|
pub grid_services_enabled: bool,
|
||||||
|
pub load_meter: bool,
|
||||||
|
pub off_grid_vehicle_charging_reserve_supported: bool,
|
||||||
|
pub set_islanding_mode_enabled: bool,
|
||||||
|
pub show_grid_import_battery_source_cards: bool,
|
||||||
|
pub solar: bool,
|
||||||
|
pub solar_type: String,
|
||||||
|
pub solar_value_enabled: bool,
|
||||||
|
pub storm_mode_capable: bool,
|
||||||
|
pub tou_capable: bool,
|
||||||
|
pub vehicle_charging_performance_view_enabled: bool,
|
||||||
|
pub vehicle_charging_solar_offset_view_enabled: bool,
|
||||||
|
pub wifi_commissioning_enabled: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Address {
|
||||||
|
pub address_line1: String,
|
||||||
|
pub city: String,
|
||||||
|
pub country: String,
|
||||||
|
pub state: String,
|
||||||
|
pub zip: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct SiteInfo {
|
||||||
|
pub address: Address,
|
||||||
|
pub backup_reserve_percent: i64,
|
||||||
|
pub battery_count: i64,
|
||||||
|
pub components: Components,
|
||||||
|
pub default_real_mode: String,
|
||||||
|
pub geolocation: Geolocation,
|
||||||
|
pub id: String,
|
||||||
|
pub installation_date: String,
|
||||||
|
pub installation_time_zone: String,
|
||||||
|
pub max_site_meter_power_ac: i64,
|
||||||
|
pub min_site_meter_power_ac: i64,
|
||||||
|
pub nameplate_energy: i64,
|
||||||
|
pub nameplate_power: i64,
|
||||||
|
pub site_name: String,
|
||||||
|
pub tou_settings: TouSettings,
|
||||||
|
pub user_settings: UserSettings,
|
||||||
|
pub version: String,
|
||||||
|
pub vpp_backup_reserve_percent: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Display, EnumString, IntoStaticStr)]
|
||||||
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
pub enum HistoryKind {
|
||||||
|
Power,
|
||||||
|
Energy,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Display, EnumString, IntoStaticStr)]
|
||||||
|
#[strum(serialize_all = "snake_case")]
|
||||||
|
pub enum HistoryPeriod {
|
||||||
|
Day,
|
||||||
|
Month,
|
||||||
|
Year,
|
||||||
|
Lifetime,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct CalendarHistoryValues {
|
||||||
|
// Modify URL:
|
||||||
|
pub site_id: EnergySiteId,
|
||||||
|
|
||||||
|
// Query params:
|
||||||
|
pub period: HistoryPeriod,
|
||||||
|
pub kind: HistoryKind,
|
||||||
|
pub start_date: Option<DateTime<FixedOffset>>,
|
||||||
|
pub end_date: Option<DateTime<FixedOffset>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Values for CalendarHistoryValues {
|
||||||
|
fn format(&self, url: &str) -> String {
|
||||||
|
let url = url.replace("{}", &format!("{}", self.site_id.0));
|
||||||
|
let mut pairs: Vec<(&str, String)> = vec![
|
||||||
|
("period", self.period.to_string()),
|
||||||
|
("kind", self.kind.to_string()),
|
||||||
|
];
|
||||||
|
if let Some(start_date) = self.start_date {
|
||||||
|
let start_date = rfc3339(&start_date);
|
||||||
|
pairs.push(("start_date", start_date));
|
||||||
|
}
|
||||||
|
if let Some(end_date) = self.end_date {
|
||||||
|
let end_date = rfc3339(&end_date);
|
||||||
|
pairs.push(("end_date", end_date));
|
||||||
|
}
|
||||||
|
format!("{}?{}", url, join_query_pairs(&pairs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct CalendarHistory {
|
||||||
|
pub serial_number: String,
|
||||||
|
/// Only appears in energy kind.
|
||||||
|
pub period: Option<String>,
|
||||||
|
pub installation_time_zone: String,
|
||||||
|
/// Optional because if there are no `Series` fields, this field is omitted.
|
||||||
|
pub time_series: Option<Vec<Series>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
#[serde(untagged)]
|
||||||
|
pub enum Series {
|
||||||
|
Power(PowerSeries),
|
||||||
|
Energy(EnergySeries),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct PowerSeries {
|
||||||
|
pub timestamp: DateTime<FixedOffset>,
|
||||||
|
pub solar_power: f64,
|
||||||
|
pub battery_power: f64,
|
||||||
|
pub grid_power: f64,
|
||||||
|
pub grid_services_power: f64,
|
||||||
|
pub generator_power: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct EnergySeries {
|
||||||
|
pub timestamp: DateTime<FixedOffset>,
|
||||||
|
pub solar_energy_exported: f64,
|
||||||
|
pub generator_energy_exported: f64,
|
||||||
|
pub grid_energy_imported: f64,
|
||||||
|
pub grid_services_energy_imported: f64,
|
||||||
|
pub grid_services_energy_exported: f64,
|
||||||
|
pub grid_energy_exported_from_solar: f64,
|
||||||
|
pub grid_energy_exported_from_generator: f64,
|
||||||
|
pub grid_energy_exported_from_battery: f64,
|
||||||
|
pub battery_energy_exported: f64,
|
||||||
|
pub battery_energy_imported_from_grid: f64,
|
||||||
|
pub battery_energy_imported_from_solar: f64,
|
||||||
|
pub battery_energy_imported_from_generator: f64,
|
||||||
|
pub consumer_energy_imported_from_grid: f64,
|
||||||
|
pub consumer_energy_imported_from_solar: f64,
|
||||||
|
pub consumer_energy_imported_from_battery: f64,
|
||||||
|
pub consumer_energy_imported_from_generator: f64,
|
||||||
|
}
|
|
@ -8,10 +8,10 @@ use std::fmt::{Debug, Display};
|
||||||
use tracing::debug;
|
use tracing::debug;
|
||||||
|
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod calendar_history;
|
pub mod energy_sites;
|
||||||
pub mod energy;
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod powerwall;
|
pub mod powerwall;
|
||||||
|
pub mod products;
|
||||||
pub mod vehicles;
|
pub mod vehicles;
|
||||||
|
|
||||||
#[cfg(feature = "cli")]
|
#[cfg(feature = "cli")]
|
||||||
|
|
|
@ -59,7 +59,7 @@ enum ApiCommand {
|
||||||
Vehicle(VehicleArgs),
|
Vehicle(VehicleArgs),
|
||||||
|
|
||||||
/// List of energy sites.
|
/// List of energy sites.
|
||||||
EnergySites,
|
Products,
|
||||||
|
|
||||||
/// Specific energy site.
|
/// Specific energy site.
|
||||||
EnergySite(EnergySiteArgs),
|
EnergySite(EnergySiteArgs),
|
||||||
|
@ -111,8 +111,8 @@ async fn main() -> miette::Result<()> {
|
||||||
ApiCommand::Vehicle(v) => {
|
ApiCommand::Vehicle(v) => {
|
||||||
v.run(&api).await?;
|
v.run(&api).await?;
|
||||||
}
|
}
|
||||||
ApiCommand::EnergySites => {
|
ApiCommand::Products => {
|
||||||
print_json(api.energy_sites().await);
|
print_json(api.products().await);
|
||||||
}
|
}
|
||||||
ApiCommand::EnergySite(e) => {
|
ApiCommand::EnergySite(e) => {
|
||||||
e.run(&api).await?;
|
e.run(&api).await?;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::calendar_history::{HistoryKind, HistoryPeriod};
|
use crate::energy_sites::{HistoryKind, HistoryPeriod};
|
||||||
use crate::energy::GatewayId;
|
use crate::products::GatewayId;
|
||||||
use crate::{get_arg, get_args, join_query_pairs, rfc3339, Api, Values};
|
use crate::{get_arg, get_args, join_query_pairs, rfc3339, Api, Values};
|
||||||
use chrono::{DateTime, FixedOffset};
|
use chrono::{DateTime, FixedOffset};
|
||||||
use derive_more::{Display, FromStr};
|
use derive_more::{Display, FromStr};
|
||||||
|
|
|
@ -2,15 +2,16 @@ use crate::error::TeslatteError;
|
||||||
use crate::powerwall::PowerwallId;
|
use crate::powerwall::PowerwallId;
|
||||||
use crate::vehicles::VehicleData;
|
use crate::vehicles::VehicleData;
|
||||||
use crate::{get, Api};
|
use crate::{get, Api};
|
||||||
|
use derive_more::Display;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
impl Api {
|
impl Api {
|
||||||
get!(energy_sites, Vec<EnergySite>, "/products");
|
get!(products, Vec<Product>, "/products");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize, Display)]
|
||||||
pub struct EnergySiteId(pub u64);
|
pub struct EnergySiteId(pub u64);
|
||||||
|
|
||||||
impl FromStr for EnergySiteId {
|
impl FromStr for EnergySiteId {
|
||||||
|
@ -28,7 +29,7 @@ pub struct GatewayId(String);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
#[serde(untagged)]
|
#[serde(untagged)]
|
||||||
pub enum EnergySite {
|
pub enum Product {
|
||||||
Vehicle(Box<VehicleData>),
|
Vehicle(Box<VehicleData>),
|
||||||
Solar(Box<SolarData>),
|
Solar(Box<SolarData>),
|
||||||
Powerwall(Box<PowerwallData>),
|
Powerwall(Box<PowerwallData>),
|
||||||
|
@ -83,7 +84,7 @@ pub struct Components {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::calendar_history::{CalendarHistoryValues, HistoryKind, HistoryPeriod};
|
use crate::energy_sites::{CalendarHistoryValues, HistoryKind, HistoryPeriod};
|
||||||
use crate::Values;
|
use crate::Values;
|
||||||
use chrono::DateTime;
|
use chrono::DateTime;
|
||||||
|
|
||||||
|
@ -117,7 +118,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
|
|
||||||
if let EnergySite::Powerwall(data) = serde_json::from_str(json).unwrap() {
|
if let Product::Powerwall(data) = serde_json::from_str(json).unwrap() {
|
||||||
assert_eq!(data.battery_type, "ac_powerwall");
|
assert_eq!(data.battery_type, "ac_powerwall");
|
||||||
assert!(data.backup_capable);
|
assert!(data.backup_capable);
|
||||||
assert_eq!(data.battery_power, -280);
|
assert_eq!(data.battery_power, -280);
|
||||||
|
@ -208,8 +209,8 @@ mod tests {
|
||||||
"command_signing": "allowed"
|
"command_signing": "allowed"
|
||||||
}
|
}
|
||||||
"#;
|
"#;
|
||||||
let energy_site: EnergySite = serde_json::from_str(json).unwrap();
|
let energy_site: Product = serde_json::from_str(json).unwrap();
|
||||||
if let EnergySite::Vehicle(v) = energy_site {
|
if let Product::Vehicle(v) = energy_site {
|
||||||
assert_eq!(v.id.0, 1111193485934);
|
assert_eq!(v.id.0, 1111193485934);
|
||||||
assert_eq!(v.user_id, 2222291283912);
|
assert_eq!(v.user_id, 2222291283912);
|
||||||
assert_eq!(v.vehicle_id.0, 333331238921);
|
assert_eq!(v.vehicle_id.0, 333331238921);
|
Loading…
Reference in a new issue