|
|
||
|---|---|---|
| .. | ||
| src | ||
| Cargo.toml | ||
| README.md | ||
README.md
homecore-automation
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.
What this crate does
homecore-automation provides the runtime for HOMECORE automations — YAML files that define "if X happens and Y is true, do Z". It includes:
- Automation struct — YAML-deserializable automation definition with id, alias, triggers, conditions, actions, and run mode (single, parallel, restart)
- Trigger evaluation — state-changed, time-based, template, and service-call triggers; async
EvaluateTriggertrait - Condition evaluation — state conditions, template conditions, numeric comparisons, and logical operators (and/or);
EvalContextfor entity state injection - Action execution — call-service, set-state, and script actions via
ExecutionContext - MiniJinja templating — HA-compatible Jinja2 templates with globals like
states,state_attr,is_state,now - AutomationEngine — listens to homecore event bus, drives the trigger→condition→action pipeline asynchronously
Automations 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.
Features
- YAML automation syntax — familiar HA format: triggers, conditions, actions, mode
- State-changed triggers — fires when
entity.light.kitchenchanges toon - Time-based triggers —
at: "15:30:00"orminutes: 5(cron-like) - Template triggers —
value_template: "{{ states('light.kitchen') == 'on' }}" - Service-call triggers —
service: light.turn_onfor chaining automations - Condition evaluation —
condition: statewith entity_id + state matching - Template conditions —
condition: templatewith Jinja2 expressions - Numeric comparisons —
condition: numeric_statewithabove,below,between - Logical operators —
condition: and/condition: orfor complex rules - Service call actions —
action: servicewithservice: light.turn_on+ data - State setting actions —
action: set_stateto directly update entity state - MiniJinja templating —
{{ now() }},{{ states('sensor.temp') }},{{ is_state('light.kitchen', 'on') }} - Automation modes — single (queue), parallel (all fire), restart (drop old runs)
Capabilities
| 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 |
Comparison to Home Assistant
| 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 |
Performance
- Trigger evaluation — < 100 μs per trigger (state-changed lookups are lock-free)
- Condition evaluation — < 500 μs per condition (includes state machine reads)
- Template rendering — < 1 ms per expression (MiniJinja cached compilation)
- Action execution — < 10 ms per action (service call latency dominates; depends on handler)
- Automation engine throughput — 1,000+ automations per second (single event bus thread)
- Memory overhead per automation — ~1 KB (YAML struct + trigger enums)
- No per-crate benchmarks yet — a follow-up issue tracks baseline measurements
Run cargo bench -p homecore-automation for criterion benchmarks.
Usage
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());
Relation to other HOMECORE crates
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)