And again

This commit is contained in:
Moritz Ruth 2023-02-21 18:29:17 +01:00
parent 603b51dfc1
commit b87c19df84
Signed by: moritzruth
GPG key ID: C9BBAB79405EE56D
4 changed files with 77 additions and 30 deletions

View file

@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run" type="CargoCommandRunConfiguration" factoryName="Cargo Command" nameIsGenerated="true"> <configuration default="false" name="Run (dry)" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="run -F dry_run" /> <option name="command" value="run -F dry_run" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" /> <option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="false" /> <option name="emulateTerminal" value="false" />

View file

@ -0,0 +1,19 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Run (not dry)" type="CargoCommandRunConfiguration" factoryName="Cargo Command">
<option name="command" value="run" />
<option name="workingDirectory" value="file://$PROJECT_DIR$" />
<option name="emulateTerminal" value="false" />
<option name="channel" value="DEFAULT" />
<option name="requiredFeatures" value="false" />
<option name="allFeatures" value="false" />
<option name="withSudo" value="false" />
<option name="buildTarget" value="REMOTE" />
<option name="backtrace" value="SHORT" />
<envs>
<env name="RUST_LOG" value="hassliebe" />
</envs>
<option name="isRedirectInput" value="false" />
<option name="redirectInputPath" value="" />
<method v="2" />
</configuration>
</component>

View file

@ -3,7 +3,7 @@
## Features ## Features
- [ ] Triggers - [ ] Triggers
- [ ] shutdown, hibernate, suspend, reboot - [ ] shutdown, reboot
- [ ] Custom commands - [ ] Custom commands
- [ ] Notifications - [ ] Notifications
- [ ] Actions - [ ] Actions

View file

@ -1,57 +1,54 @@
use crate::modules::ModuleContext;
use anyhow::Result; use anyhow::Result;
use rumqttc::QoS; use rumqttc::QoS;
use tokio::process::Command; use tokio::process::Command;
use super::ModuleContext;
const MODULE_ID: &str = "power";
const BUTTON_TRIGGER_TEXT: &str = "press";
pub(crate) async fn init(context: &mut ModuleContext<'_>) -> Result<()> { pub(crate) async fn init(context: &mut ModuleContext<'_>) -> Result<()> {
log::info!("Initializing…"); log::info!("Initializing…");
let module_id = "power"; init_command_button(context, "shutdown", "Shutdown", "shutdown -h now").await?;
let sub_id = "shutdown"; init_command_button(context, "reboot", "Reboot", "shutdown -r now").await?;
let trigger_text = "press"; Ok(())
}
let entity_id = context.get_entity_id(module_id, sub_id); async fn init_command_button(
let entity_id = entity_id.as_str(); context: &mut ModuleContext<'_>,
sub_id: &str,
name: &str,
command: impl Into<String>,
) -> Result<()> {
let command = command.into();
let command_topic = context.get_mqtt_topic("button", entity_id, "trigger"); let entity_id = context.get_entity_id(MODULE_ID, sub_id);
let command_topic = context.get_mqtt_topic("button", &entity_id, "trigger");
context context
.mqtt_client .mqtt_client
.publish( .publish(
context.get_mqtt_topic("button", entity_id, "config"), context.get_mqtt_topic("button", &entity_id, "config"),
QoS::AtLeastOnce, QoS::AtLeastOnce,
true, true,
json::stringify(json::object! { json::stringify(json::object! {
"availability_topic": context.mqtt_availability_topic, "availability_topic": context.mqtt_availability_topic,
"command_topic": command_topic.as_str(), "command_topic": command_topic.as_str(),
"device": context.mqtt_discovery_device_object.clone(), "device": context.mqtt_discovery_device_object.clone(),
// "device_class": "restart",
"icon": "mdi:power", "icon": "mdi:power",
"name": "Shutdown", "name": name,
"payload_press": trigger_text, "payload_press": BUTTON_TRIGGER_TEXT,
"object_id": entity_id, "object_id": entity_id.as_str(),
"unique_id": entity_id "unique_id": entity_id.as_str()
}), }),
) )
.await?; .await?;
context.subscribe_mqtt_topic(command_topic, move |text| { context.subscribe_mqtt_topic(command_topic, move |text| {
if text == trigger_text { if text == BUTTON_TRIGGER_TEXT {
if cfg!(feature = "dry_run") { run_command(command.clone());
log::info!("Received shutdown command (dry run)");
} else {
log::info!("Shutting down…");
tokio::spawn(async {
Command::new("shutdown")
.args(["-h", "now"])
.status()
.await?;
anyhow::Ok(())
});
}
} }
Ok(()) Ok(())
@ -59,3 +56,34 @@ pub(crate) async fn init(context: &mut ModuleContext<'_>) -> Result<()> {
Ok(()) Ok(())
} }
fn run_command(command: String) {
tokio::spawn(async move {
let is_dry_run = cfg!(feature = "dry_run");
let status = {
log::info!(
"Executing command{}: {}",
if is_dry_run { "(dry run)" } else { "" },
command
);
let mut command_parts = command.split(' ').collect::<Vec<_>>();
let mut actual_command = Command::new(command_parts[0]);
command_parts.remove(0);
actual_command.args(command_parts);
if is_dry_run {
None
} else {
Some(actual_command.status())
}
};
if let Some(f) = status {
f.await?;
}
anyhow::Ok(())
});
}