enphase_local/lib.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
// Copyright 2024 the octopower authors.
// This project is dual-licensed under Apache 2.0 and MIT terms.
// See LICENSE-APACHE and LICENSE-MIT for details.
//! A client library for the Enphase Envoy local API.
//!
//! # Example
//!
//! ```
//! use enphase_local::Envoy;
//! use reqwest::Url;
//!
//! const AUTH_TOKEN: &str = "...";
//!
//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
//! let envoy = Envoy::new(Url::parse("https://envoy.local/")?, AUTH_TOKEN);
//! let production = envoy.production().await?;
//! println!("Production: {:?}", production);
//! # Ok(()) }
//! ```
pub mod home;
pub mod inventory;
pub mod meters;
pub mod production;
mod timestamp_string;
use home::Home;
use inventory::Inventory;
use meters::{Reading, Report};
use production::Production;
use reqwest::{Client, Error, Url};
/// Client for the Enphase Envoy local API.
#[derive(Clone, Debug)]
pub struct Envoy {
base_url: Url,
auth_token: String,
client: Client,
}
impl Envoy {
/// Constructs a new Enphase Envoy local API client with the given base URL and auth token.
pub fn new(base_url: Url, auth_token: &str) -> Self {
Self {
base_url,
auth_token: auth_token.to_owned(),
client: Client::builder()
.danger_accept_invalid_certs(true)
.build()
.unwrap(),
}
}
/// Returns a summary of the gateway status.
pub async fn home(&self) -> Result<Home, Error> {
self.client
.get(self.base_url.join("home.json").unwrap())
.send()
.await?
.error_for_status()?
.json()
.await
}
/// Returns an inventory of devices in the system.
pub async fn inventory(&self, include_deleted: bool) -> Result<Inventory, Error> {
let mut url = self.base_url.join("inventory.json").unwrap();
url.set_query(Some(&format!(
"deleted={}",
if include_deleted { 1 } else { 0 }
)));
self.client
.get(url)
.bearer_auth(&self.auth_token)
.send()
.await?
.error_for_status()?
.json()
.await
}
/// Returns statistics about current and past production and consumption.
pub async fn production(&self) -> Result<Production, Error> {
self.client
.get(self.base_url.join("production.json?details=1").unwrap())
.bearer_auth(&self.auth_token)
.send()
.await?
.error_for_status()?
.json()
.await
}
/// Gets readings from all meters.
pub async fn meter_readings(&self) -> Result<Vec<Reading>, Error> {
self.client
.get(self.base_url.join("ivp/meters/readings").unwrap())
.bearer_auth(&self.auth_token)
.send()
.await?
.error_for_status()?
.json()
.await
}
/// Gets reports from all meters.
pub async fn meter_reports(&self) -> Result<Vec<Report>, Error> {
self.client
.get(self.base_url.join("ivp/meters/reports").unwrap())
.bearer_auth(&self.auth_token)
.send()
.await?
.error_for_status()?
.json()
.await
}
}