v2/crates/homecore-automation/README.md
YAML-based automation engine for HOMECORE with trigger evaluation, conditions, and MiniJinja template support.
Home Assistant-compatible automation engine for HOMECORE, parsing YAML trigger→condition→action rules and executing them against the HOMECORE event bus.
homecore-automation provides the runtime for HOMECORE automations — YAML files that define "if X happens and Y is true, do Z". It includes:
EvaluateTrigger traitEvalContext for entity state injectionExecutionContextstates, state_attr, is_state, nowAutomations are stored in YAML files (e.g., automations.yaml) and loaded at startup. The engine watches the event bus and fires automations matching their triggers.
entity.light.kitchen changes to onat: "15:30:00" or minutes: 5 (cron-like)value_template: "{{ states('light.kitchen') == 'on' }}"service: light.turn_on for chaining automationscondition: state with entity_id + state matchingcondition: template with Jinja2 expressionscondition: numeric_state with above, below, betweencondition: and / condition: or for complex rulesaction: service with service: light.turn_on + dataaction: set_state to directly update entity state{{ now() }}, {{ states('sensor.temp') }}, {{ is_state('light.kitchen', 'on') }}| Capability | Type | Method | Notes |
|---|---|---|---|
| Parse YAML automation | Loader | serde_yaml::from_str::<Automation>(yaml_str) | Deserialize automation definition |
| Evaluate trigger | Trigger | Trigger::StateChanged {...}.evaluate(context) | Check if trigger condition met |
| Evaluate condition | Condition | Condition::State {...}.evaluate(context) | Check if condition passes |
| Execute action | Action | Action::Service {...}.execute(context) | Call service or set state |
| Render template | Template | TemplateEnvironment::render(expr, context) | Jinja2 with HA globals |
| Run automation | Engine | AutomationEngine::run_automation(automation, context) | Execute full trigger→condition→action pipeline |
| Subscribe to events | Engine | AutomationEngine::listen(homecore.event_bus()) | Drive automations on state changes |
| Aspect | Home Assistant | homecore-automation |
|---|---|---|
| Automation format | YAML in automations.yaml | Identical YAML format |
| Parser | Python YAML + voluptuous | serde_yaml + serde validation |
| Trigger types | state_changed, time, template, service, mqtt, ... | state_changed, time, template, service (core 4) |
| Condition types | state, numeric_state, template, and/or, ... | Identical (core types) |
| Action types | call_service, set_state, script, wait_template, ... | call_service, set_state (core 2) |
| Template engine | Python Jinja2 | MiniJinja (pure Rust, HA-compatible) |
| Globals | states, state_attr, is_state, now, ... | Identical set (MiniJinja filters) |
| Execution model | Python asyncio event loop | Tokio async tasks per automation |
| Automation modes | single (queue), parallel, restart | Identical behavior |
Run cargo bench -p homecore-automation for criterion benchmarks.
Define an automation in YAML:
alias: "Kitchen light on at sunset"
triggers:
- trigger: time
at: "17:30:00"
conditions:
- condition: state
entity_id: binary_sensor.is_dark
state: "on"
actions:
- action: service
service: light.turn_on
target:
entity_id: light.kitchen
data:
brightness: 200
mode: single
Load and run it (Rust):
use homecore_automation::{Automation, AutomationEngine};
use homecore::HomeCore;
#[tokio::main]
async fn main() {
let homecore = HomeCore::new();
let yaml = std::fs::read_to_string("automations.yaml").expect("read automation");
let automation: Automation = serde_yaml::from_str(&yaml).expect("parse automation");
let engine = AutomationEngine::new(homecore.clone());
engine.listen(homecore.event_bus()).await;
// Engine now drives automations on state changes
}
Programmatic creation:
use homecore_automation::{Automation, Trigger, Condition, Action, RunMode};
let automation = Automation {
id: "kitchen_light_sunset".to_string(),
alias: Some("Kitchen light on at sunset".to_string()),
triggers: vec![
Trigger::StateChanged {
entity_id: "binary_sensor.is_dark".to_string(),
to: Some("on".to_string()),
..Default::default()
},
],
conditions: vec![],
actions: vec![
Action::Service {
service: "light.turn_on".to_string(),
data: serde_json::json!({"entity_id": "light.kitchen", "brightness": 200}),
},
],
mode: RunMode::Single,
..Default::default()
};
println!("Automation: {}", automation.alias.unwrap_or_default());
homecore-automation (automation engine)
├─ homecore (state machine + event bus; automations subscribe to state changes)
├─ homecore-api (exposes automation metadata via REST, P2)
├─ homecore-assist (intents can trigger automations via service calls, P2)
├─ homecore-server (loads automations.yaml at startup)
└─ minijinja (template rendering)