Skip to main content

Quick Start Example

A minimal example to get started:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Create a new client
    let mut client = Growatt::new();

    // Login
    if client.login("your_username", "your_password").await? {
        println!("Login successful!");

        // Get plants
        let plants = client.get_plants().await?;
        println!("Plants: {:?}", plants);

        // When you're done
        client.logout().await?;
    }

    Ok(())
}

Environment Variables Configuration

Initialize the client using environment variables:
use growatt::Growatt;
use dotenv::dotenv;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Load from .env file and environment
    dotenv().ok();

    // Create client with env vars (GROWATT_USERNAME, GROWATT_PASSWORD, etc.)
    let mut client = Growatt::from_env();

    // Auto-login using credentials from environment
    if let (Some(username), Some(password)) = (
        std::env::var("GROWATT_USERNAME").ok(),
        std::env::var("GROWATT_PASSWORD").ok(),
    ) {
        client.login(&username, &password).await?;
        
        // Your code here
        let plants = client.get_plants().await?;
        println!("Found {} plants", plants.0.len());
        
        client.logout().await?;
    }

    Ok(())
}

.env File Format

GROWATT_USERNAME=your_username
GROWATT_PASSWORD=your_password
GROWATT_BASE_URL=https://server.growatt.com  # Optional
GROWATT_SESSION_DURATION=30  # Optional, in minutes

Complete Plant Information Example

From src/main.rs - iterate over all plants and retrieve detailed information:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize the Growatt client
    let mut client = Growatt::new();
    
    // Replace these with your actual credentials
    let username = "your_username";
    let password = "your_password";
    
    // Login to the Growatt API
    match client.login(username, password).await {
        Ok(true) => {
            println!("Login successful!");
            
            // Get the list of plants
            match client.get_plants().await {
                Ok(plants) => {
                    println!("Found {} plants:", plants.0.len());
                    
                    // Display information about each plant
                    for plant in plants.0 {
                        println!("Plant ID: {}", plant.plant_id);
                        println!("Plant Name: {}", plant.plant_name);
                        
                        if let Some(address) = plant.plant_address {
                            println!("Address: {}", address);
                        }
                        
                        if let Some(power) = plant.plant_watts {
                            println!("Power (W): {}", power);
                        }
                        
                        println!("-------------------");
                        
                        // Optional: Get more detailed data for each plant
                        match client.get_plant(&plant.plant_id).await {
                            Ok(plant_data) => {
                                println!("Additional plant data:");
                                if let Some(capacity) = plant_data.capacity {
                                    println!("Capacity: {}", capacity);
                                }
                                if let Some(today_energy) = plant_data.today_energy {
                                    println!("Today's Energy: {}", today_energy);
                                }
                                if let Some(total_energy) = plant_data.total_energy {
                                    println!("Total Energy: {}", total_energy);
                                }
                                println!("-------------------");
                            },
                            Err(e) => println!("Error getting detailed plant data: {}", e),
                        }
                    }
                },
                Err(e) => println!("Error getting plants: {}", e),
            }
            
            // Logout when done
            if let Err(e) = client.logout().await {
                println!("Error during logout: {}", e);
            } else {
                println!("Successfully logged out");
            }
        },
        Ok(false) => println!("Login failed! Check your credentials."),
        Err(e) => println!("Error during login: {}", e),
    }
    
    Ok(())
}

Custom Client Configuration

Examples of configuring the client with custom settings:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Use alternative API server
    let mut client = Growatt::new().with_alternate_url();
    
    client.login("username", "password").await?;
    let plants = client.get_plants().await?;
    client.logout().await?;
    
    Ok(());
}
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Set custom session duration (60 minutes)
    let mut client = Growatt::new().with_session_duration(60);
    
    client.login("username", "password").await?;
    // Session will remain valid for 60 minutes
    let plants = client.get_plants().await?;
    client.logout().await?;
    
    Ok(());
}

Energy Statistics Example

Retrieve and display energy statistics:
use growatt::Growatt;
use chrono::Local;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    // Get plants and MIX devices
    let plants = client.get_plants().await?;
    let plant_id = &plants.0[0].plant_id;
    
    let mix_ids = client.get_mix_ids(plant_id).await?;
    // Extract MIX serial number from response
    let mix_sn = "your_mix_serial_number";
    
    // Current date components
    let now = Local::now();
    let today = now.format("%Y-%m-%d").to_string();
    let this_month = now.format("%Y-%m").to_string();
    let this_year = now.format("%Y").to_string();
    
    // Get daily energy statistics
    println!("Daily Statistics for {}:", today);
    let daily_stats = client.get_energy_stats_daily(&today, plant_id, mix_sn).await?;
    println!("{}", daily_stats);
    
    // Get monthly energy statistics
    println!("\nMonthly Statistics for {}:", this_month);
    let monthly_stats = client.get_energy_stats_monthly(&this_month, plant_id, mix_sn).await?;
    println!("{}", monthly_stats);
    
    // Get yearly energy statistics
    println!("\nYearly Statistics for {}:", this_year);
    let yearly_stats = client.get_energy_stats_yearly(&this_year, plant_id, mix_sn).await?;
    println!("{}", yearly_stats);
    
    // Get total energy statistics
    println!("\nTotal Energy Statistics:");
    let total_stats = client.get_energy_stats_total(&this_year, plant_id, mix_sn).await?;
    println!("{}", total_stats);
    
    client.logout().await?;
    Ok(())
}

Device Information Example

Retrieve device and MIX information:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    let plants = client.get_plants().await?;
    let plant_id = &plants.0[0].plant_id;
    
    // Get MIX device IDs
    println!("Fetching MIX devices...");
    let mix_ids = client.get_mix_ids(plant_id).await?;
    println!("MIX devices: {}", mix_ids);
    
    // Get device list
    println!("\nFetching device list...");
    let devices = client.get_device_list(plant_id).await?;
    println!("Devices: {}", devices);
    
    // Get devices with pagination
    println!("\nFetching devices (page 1)...");
    let devices_page = client.get_devices_by_plant_list(plant_id, Some(1)).await?;
    println!("Devices page: {}", devices_page);
    
    // Get MIX status (requires MIX serial number)
    let mix_sn = "your_mix_serial_number";
    println!("\nFetching MIX status...");
    let mix_status = client.get_mix_status(plant_id, mix_sn).await?;
    println!("MIX status: {}", mix_status);
    
    // Get MIX total data
    println!("\nFetching MIX total data...");
    let mix_total = client.get_mix_total(plant_id, mix_sn).await?;
    println!("MIX total: {}", mix_total);
    
    client.logout().await?;
    Ok(())
}

Fault Logs Example

Retrieve and parse fault logs:
use growatt::Growatt;
use chrono::Local;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    let plant_id = "your_plant_id";
    let device_sn = "your_device_serial_number";
    let today = Local::now().format("%Y-%m-%d").to_string();
    
    // Get fault logs
    // Parameters: plant_id, date (optional), device_sn, page_num, device_flag, fault_type
    let fault_logs = client.get_fault_logs(
        plant_id,
        Some(&today),  // Date (None for today)
        device_sn,
        1,             // Page number
        0,             // Device flag (0 = All)
        0              // Fault type (0 = All)
    ).await?;
    
    println!("Fault logs: {}", fault_logs);
    
    // Alternative method (same functionality)
    let fault_logs = client.get_plant_fault_logs(
        plant_id,
        Some(&today),
        device_sn,
        1,
        0,
        0
    ).await?;
    
    client.logout().await?;
    Ok(())
}

Battery Statistics Example

Retrieve battery charge/discharge statistics:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    let plant_id = "your_plant_id";
    let mix_sn = "your_mix_serial_number";
    
    // Get weekly battery statistics
    println!("Fetching battery statistics...");
    let battery_stats = client.get_weekly_battery_stats(plant_id, mix_sn).await?;
    println!("Battery statistics: {}", battery_stats);
    
    client.logout().await?;
    Ok(())
}

Weather Information Example

Retrieve weather data for a plant:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    let plants = client.get_plants().await?;
    
    for plant in plants.0 {
        println!("Weather for plant: {}", plant.plant_name);
        
        match client.get_weather(&plant.plant_id).await {
            Ok(weather) => println!("Weather data: {}", weather),
            Err(e) => eprintln!("Error getting weather: {}", e),
        }
        
        println!("-------------------");
    }
    
    client.logout().await?;
    Ok(())
}

Comprehensive Error Handling Example

Robust error handling for production use:
use growatt::{Growatt, GrowattError};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    let username = "your_username";
    let password = "your_password";
    
    // Handle login errors
    match client.login(username, password).await {
        Ok(true) => println!("Login successful!"),
        Ok(false) => {
            eprintln!("Login failed! Check your credentials.");
            return Ok(());
        },
        Err(err) => match err {
            GrowattError::AuthError(msg) => {
                eprintln!("Authentication error: {}", msg);
                return Ok(());
            },
            GrowattError::RequestError(err) => {
                eprintln!("Network error: {}", err);
                return Ok(());
            },
            GrowattError::JsonError(err) => {
                eprintln!("JSON parsing error: {}", err);
                return Ok(());
            },
            GrowattError::InvalidResponse(msg) => {
                eprintln!("Invalid API response: {}", msg);
                return Ok(());
            },
            GrowattError::NotLoggedIn => {
                eprintln!("Not logged in");
                return Ok(());
            }
        }
    }
    
    // Handle API call errors
    match client.get_plants().await {
        Ok(plants) => {
            println!("Found {} plants:", plants.0.len());
            for plant in plants.0 {
                println!("- {}: {}", plant.plant_id, plant.plant_name);
            }
        },
        Err(e) => eprintln!("Error getting plants: {}", e),
    }
    
    // Logout gracefully
    if let Err(e) = client.logout().await {
        eprintln!("Error during logout: {}", e);
    } else {
        println!("Successfully logged out");
    }
    
    Ok(())
}

MIX Device Control Example

Update MIX device settings:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    client.login("username", "password").await?;
    
    let plant_id = "your_plant_id";
    let mix_sn = "your_mix_serial_number";
    
    // Update MIX AC discharge time period to current time
    println!("Updating MIX discharge time period...");
    let result = client.post_mix_ac_discharge_time_period_now(plant_id, mix_sn).await?;
    println!("Update result: {}", result);
    
    client.logout().await?;
    Ok(())
}

Session Management Example

Demonstrate automatic session renewal:
use growatt::Growatt;
use tokio::time::{sleep, Duration};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new()
        .with_session_duration(1); // 1 minute session for testing
    
    client.login("username", "password").await?;
    println!("Initial login successful");
    
    // First API call - should work with active session
    let plants = client.get_plants().await?;
    println!("First call: Found {} plants", plants.0.len());
    
    // Wait for session to expire
    println!("Waiting for session to expire...");
    sleep(Duration::from_secs(70)).await;
    
    // Second API call - should automatically re-authenticate
    let plants = client.get_plants().await?;
    println!("Second call (after session expiry): Found {} plants", plants.0.len());
    println!("SDK automatically re-authenticated!");
    
    client.logout().await?;
    Ok(())
}

Token Access Example

Access the authentication token:
use growatt::Growatt;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut client = Growatt::new();
    
    // Before login, token is None
    assert!(client.get_token().is_none());
    
    // Login
    client.login("username", "password").await?;
    
    // After login, token may be available (if API provides it)
    if let Some(token) = client.get_token() {
        println!("Authentication token: {}", token);
        // Use token for external purposes if needed
    } else {
        println!("No token provided by API");
    }
    
    // Check login status
    println!("Is logged in: {}", client.is_logged_in());
    
    client.logout().await?;
    
    // After logout, status changes
    println!("Is logged in: {}", client.is_logged_in());
    
    Ok(())
}

Build docs developers (and LLMs) love