Download and parse untyped XML data
This commit is contained in:
1210
Cargo.lock
generated
Normal file
1210
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
5
Cargo.toml
Normal file
5
Cargo.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
[workspace]
|
||||
members = [
|
||||
"crates/runner",
|
||||
"crates/bidgely_adapter",
|
||||
]
|
||||
9
crates/bidgely_adapter/Cargo.toml
Normal file
9
crates/bidgely_adapter/Cargo.toml
Normal file
@@ -0,0 +1,9 @@
|
||||
[package]
|
||||
name = "bidgely_adapter"
|
||||
version = "0.1.0"
|
||||
authors = ["Steve Sampson <mail@stephensampson.dev>"]
|
||||
edition = "2018"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
114
crates/bidgely_adapter/src/lib.rs
Normal file
114
crates/bidgely_adapter/src/lib.rs
Normal file
@@ -0,0 +1,114 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct UserAuthResponse {
|
||||
pub request_id: String,
|
||||
pub payload: String,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct SessionResponse {
|
||||
pub request_id: String,
|
||||
pub payload: SessionPayload,
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct SessionPayload {
|
||||
pub pilot_id: u64,
|
||||
pub client_id: String,
|
||||
pub token_details: TokenDetails,
|
||||
pub user_profile_details: UserProfileDetails,
|
||||
pub user_type_details: UserTypeDetails,
|
||||
pub premises_details: PremisesDetails,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct TokenDetails {
|
||||
pub access_token: String,
|
||||
pub expiry_time_in_millis: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct UserProfileDetails {
|
||||
pub user_id: String,
|
||||
pub partner_user_id: String,
|
||||
pub meter_id: Option<String>,
|
||||
pub first_name: String,
|
||||
pub last_name: String,
|
||||
pub fuel_type: String, // todo: type this as enum FuelType
|
||||
pub email: String,
|
||||
pub utility_tags: UtilityTags,
|
||||
pub home_accounts: HomeAccounts,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "snake_case"))]
|
||||
pub struct UtilityTags {
|
||||
pub account_number: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct HomeAccounts {
|
||||
pub address: String,
|
||||
pub has_solar: bool,
|
||||
pub postal_code: String,
|
||||
pub rate: RatePlanInfo,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct RatePlanInfo {
|
||||
pub rate_plan_id: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct UserTypeDetails {
|
||||
pub user_segment: String, // todo: type this as enum UserSegment
|
||||
pub measurement_to_user_type_mappings: Vec<MeasurementToUserType>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct MeasurementToUserType {
|
||||
pub measurement_type: String,
|
||||
pub user_type: String,
|
||||
pub max_contract_end: u32,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct PremisesDetails {
|
||||
pub partner_user_id: String,
|
||||
pub premises: Vec<Premise>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct Premise {
|
||||
pub uuid: String,
|
||||
pub premise_id: Option<String>,
|
||||
pub address: PremiseAddress,
|
||||
pub supported_measurement_types: Vec<String>, // toto: type this as enum MeasurementType
|
||||
pub dashboard_last_visited: u32,
|
||||
pub status: String, // todo: type this as enum PremiseStatus
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
|
||||
#[serde(rename_all(deserialize = "camelCase"))]
|
||||
pub struct PremiseAddress {
|
||||
pub address_line_1: String,
|
||||
pub address_line_2: Option<String>,
|
||||
pub city: String,
|
||||
pub state: String,
|
||||
pub zipcode: String,
|
||||
pub context: Option<String>,
|
||||
}
|
||||
15
crates/runner/Cargo.toml
Normal file
15
crates/runner/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "nspdata"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
bidgely_adapter = { path = "../bidgely_adapter" }
|
||||
clap = { version = "4.0.17", features = ["derive"] }
|
||||
quick-xml = "0.25.0"
|
||||
reqwest = "0.11.12"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = { version = "1.0" }
|
||||
tokio = { version = "1.21.2", features = ["full"] }
|
||||
60
crates/runner/src/main.rs
Normal file
60
crates/runner/src/main.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
use bidgely_adapter::{SessionResponse, UserAuthResponse};
|
||||
use clap::Parser;
|
||||
|
||||
const BIDGELY_BASE_URL: &'static str = "https://caapi.bidgely.com/v2.0";
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
struct Args {
|
||||
#[arg(short, long)]
|
||||
uid: String,
|
||||
}
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
let args: Args = Args::parse();
|
||||
let user_id = args.uid.as_str();
|
||||
|
||||
let user_auth_response: UserAuthResponse = serde_json::from_str(
|
||||
&reqwest::get(format!(
|
||||
"{BIDGELY_BASE_URL}/user-auth/cipher?user-id={user_id}&pilot-id=40003"
|
||||
))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let session = user_auth_response.payload;
|
||||
|
||||
let session_response: SessionResponse = serde_json::from_str(
|
||||
&reqwest::get(format!(
|
||||
"{BIDGELY_BASE_URL}/web/web-session/{session}?pilotId=40003&clientId=nsp-dashboard"
|
||||
))
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let token = session_response.payload.token_details.access_token;
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
let xml_data = client.get(format!(
|
||||
"{BIDGELY_BASE_URL}/dashboard/users/{user_id}/gb-download?start=1660694400&end=1665964800&measurement-type=ELECTRIC"
|
||||
))
|
||||
.header(reqwest::header::CONTENT_TYPE, "application/json;charset=UTF-8")
|
||||
.header(reqwest::header::AUTHORIZATION, format!("Bearer {token}"))
|
||||
.send()
|
||||
.await
|
||||
.unwrap()
|
||||
.text()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
println!("{:?}", xml_data);
|
||||
}
|
||||
Reference in New Issue
Block a user