Back to Ruview

homecore-automation

v2/crates/homecore-automation/README.md

20967.9 KB
Original Source

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 EvaluateTrigger trait
  • Condition evaluation — state conditions, template conditions, numeric comparisons, and logical operators (and/or); EvalContext for 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.kitchen changes to on
  • Time-based triggersat: "15:30:00" or minutes: 5 (cron-like)
  • Template triggersvalue_template: "{{ states('light.kitchen') == 'on' }}"
  • Service-call triggersservice: light.turn_on for chaining automations
  • Condition evaluationcondition: state with entity_id + state matching
  • Template conditionscondition: template with Jinja2 expressions
  • Numeric comparisonscondition: numeric_state with above, below, between
  • Logical operatorscondition: and / condition: or for complex rules
  • Service call actionsaction: service with service: light.turn_on + data
  • State setting actionsaction: set_state to 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

CapabilityTypeMethodNotes
Parse YAML automationLoaderserde_yaml::from_str::<Automation>(yaml_str)Deserialize automation definition
Evaluate triggerTriggerTrigger::StateChanged {...}.evaluate(context)Check if trigger condition met
Evaluate conditionConditionCondition::State {...}.evaluate(context)Check if condition passes
Execute actionActionAction::Service {...}.execute(context)Call service or set state
Render templateTemplateTemplateEnvironment::render(expr, context)Jinja2 with HA globals
Run automationEngineAutomationEngine::run_automation(automation, context)Execute full trigger→condition→action pipeline
Subscribe to eventsEngineAutomationEngine::listen(homecore.event_bus())Drive automations on state changes

Comparison to Home Assistant

AspectHome Assistanthomecore-automation
Automation formatYAML in automations.yamlIdentical YAML format
ParserPython YAML + voluptuousserde_yaml + serde validation
Trigger typesstate_changed, time, template, service, mqtt, ...state_changed, time, template, service (core 4)
Condition typesstate, numeric_state, template, and/or, ...Identical (core types)
Action typescall_service, set_state, script, wait_template, ...call_service, set_state (core 2)
Template enginePython Jinja2MiniJinja (pure Rust, HA-compatible)
Globalsstates, state_attr, is_state, now, ...Identical set (MiniJinja filters)
Execution modelPython asyncio event loopTokio async tasks per automation
Automation modessingle (queue), parallel, restartIdentical 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:

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):

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:

rust
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)

References