use clap::{Parser, Subcommand};
use homeassistant_cli::output::{OutputConfig, OutputFormat, exit_codes};
use homeassistant_cli::{api, commands};
#[derive(Parser)]
#[command(
name = "ha",
version,
about = "CLI for Home Assistant",
arg_required_else_help = true
)]
struct Cli {
#[arg(long, env = "HA_PROFILE", global = true)]
profile: Option<String>,
#[arg(long, value_enum, env = "HA_OUTPUT", global = true)]
output: Option<OutputFormat>,
#[arg(long, global = true)]
quiet: bool,
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
#[command(subcommand, arg_required_else_help = true)]
Entity(EntityCommand),
#[command(subcommand, arg_required_else_help = true)]
Service(ServiceCommand),
#[command(subcommand, arg_required_else_help = true)]
Event(EventCommand),
Init {
#[arg(long)]
profile: Option<String>,
},
#[command(subcommand, arg_required_else_help = true)]
Config(ConfigCommand),
Schema,
}
#[derive(Subcommand)]
enum EntityCommand {
Get { entity_id: String },
List {
#[arg(long)]
domain: Option<String>,
},
Watch { entity_id: String },
}
#[derive(Subcommand)]
enum ServiceCommand {
Call {
service: String,
#[arg(long)]
entity: Option<String>,
#[arg(long)]
data: Option<String>,
},
List {
#[arg(long)]
domain: Option<String>,
},
}
#[derive(Subcommand)]
enum EventCommand {
Fire {
event_type: String,
#[arg(long)]
data: Option<String>,
},
Watch {
event_type: Option<String>,
},
}
#[derive(Subcommand)]
enum ConfigCommand {
Show,
Set { key: String, value: String },
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
let out = OutputConfig::new(cli.output, cli.quiet);
match cli.command {
Command::Init { profile } => {
commands::init::init(profile).await;
}
Command::Schema => {
commands::schema::print_schema();
}
Command::Config(cmd) => match cmd {
ConfigCommand::Show => {
commands::config::show(&out, cli.profile.as_deref());
}
ConfigCommand::Set { key, value } => {
commands::config::set(&out, cli.profile.as_deref(), &key, &value);
}
},
command => {
let cfg = match homeassistant_cli::config::Config::load(cli.profile.clone()) {
Ok(c) => c,
Err(e) => {
eprintln!("{e}");
std::process::exit(exit_codes::CONFIG_ERROR);
}
};
let client = api::HaClient::new(&cfg.url, &cfg.token);
let result = match command {
Command::Entity(cmd) => match cmd {
EntityCommand::Get { entity_id } => {
commands::entity::get(&out, &client, &entity_id).await
}
EntityCommand::List { domain } => {
commands::entity::list(&out, &client, domain.as_deref()).await
}
EntityCommand::Watch { entity_id } => {
commands::entity::watch(&out, &client, &entity_id).await
}
},
Command::Service(cmd) => match cmd {
ServiceCommand::Call {
service,
entity,
data,
} => {
commands::service::call(
&out,
&client,
&service,
entity.as_deref(),
data.as_deref(),
)
.await
}
ServiceCommand::List { domain } => {
commands::service::list(&out, &client, domain.as_deref()).await
}
},
Command::Event(cmd) => match cmd {
EventCommand::Fire { event_type, data } => {
commands::event::fire(&out, &client, &event_type, data.as_deref()).await
}
EventCommand::Watch { event_type } => {
commands::event::watch(&out, &client, event_type.as_deref()).await
}
},
Command::Init { .. } | Command::Schema | Command::Config(_) => unreachable!(),
};
if let Err(e) = result {
let code = exit_codes::for_error(&e);
out.print_error(&e);
std::process::exit(code);
}
}
}
}