bcms 0.1.12

Bluetooth Client Manager Service for IoT device management
Documentation
use bcms::rpc::client::RpcClient;
use std::net::SocketAddr;
use std::env;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Initialize tracing
    tracing_subscriber::fmt()
        .with_env_filter("debug")
        .init();

    // Get server address from args or use default
    let server_address = env::args()
        .nth(1)
        .unwrap_or_else(|| "127.0.0.1:4567".to_string());
    
    let socket_addr: SocketAddr = server_address.parse()?;
    let client = RpcClient::new(socket_addr);

    println!("📊 BCMS Stats Example");
    println!("🔗 RPC Server: {}", server_address);
    println!();

    match client.get_stats().await {
        Ok((device_stats, total_data_points, errors)) => {
            if !errors.is_empty() {
                println!("⚠️  Errors:");
                for error in &errors {
                    println!("   - {}", error);
                }
                println!();
            }

            println!("📈 System Statistics:");
            println!("   📊 Total Data Points: {}", total_data_points);
            println!("   🔧 Total Devices: {}", device_stats.len());
            println!();

            if device_stats.is_empty() {
                println!("📭 No devices found");
            } else {
                println!("🔍 Device Details:");
                for (i, device) in device_stats.iter().enumerate() {
                    println!("  {}. 📱 {} ({})", i + 1, device.name, device.address);
                    println!("     • Type: {}", device.connection_type);
                    println!("     • Approved: {}", if device.approved { "✅" } else { "❌" });
                    println!("     • Paired: {}", if device.paired { "✅" } else { "❌" });
                    println!("     • Backend Registered: {}", if device.backend_registered { "✅" } else { "❌" });
                    
                    if device.last_seen > 0 {
                        println!("     • Last Seen: {}", format_timestamp(device.last_seen));
                    } else {
                        println!("     • Last Seen: Never");
                    }

                    if device.data_types.is_empty() {
                        println!("     • Data: No data recorded");
                    } else {
                        println!("     • Data Types:");
                        for data_type in &device.data_types {
                            println!("       - {}: {} samples (latest: {})", 
                                data_type.data_type, 
                                data_type.count,
                                format_timestamp(data_type.last_timestamp)
                            );
                        }
                    }
                    println!();
                }
            }

            println!("✅ Stats retrieved successfully!");
        }
        Err(e) => {
            eprintln!("❌ Failed to get stats: {}", e);
            std::process::exit(1);
        }
    }

    Ok(())
}

fn format_timestamp(timestamp: i64) -> String {
    use chrono::{DateTime, Utc};
    
    if timestamp == 0 {
        return "Never".to_string();
    }
    
    match DateTime::from_timestamp(timestamp, 0) {
        Some(dt) => {
            let utc_dt: DateTime<Utc> = dt.into();
            utc_dt.format("%Y-%m-%d %H:%M:%S UTC").to_string()
        }
        None => format!("Invalid timestamp: {}", timestamp)
    }
}