项目文件夹

文件
wehub-resource-sync 9740bc64c9
Bench Regression Guard / bench compile-verify (--no-run) (push) Failing after 0s
Continuous Deployment / Pre-deployment Checks (push) Has been skipped
Bench Regression Guard / bench fast-run (informational, non-gating) (push) Has been skipped
Firmware CI / Verify version.txt matches release tag (push) Has been skipped
Dashboard a11y + cross-browser / a11y (push) Failing after 0s
nvsim Dashboard → GitHub Pages / build-and-deploy (push) Failing after 2s
Firmware CI / Build firmware (esp32s3 / 4mb) (push) Failing after 15s
Firmware CI / Build firmware (esp32c6 / c6-4mb) (push) Failing after 15s
Firmware QEMU Tests (ADR-061) / Build Espressif QEMU (push) Failing after 1s
Firmware QEMU Tests (ADR-061) / Fuzz Testing (ADR-061 Layer 6) (push) Failing after 1s
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-max) (push) Has been skipped
Firmware CI / Build firmware (esp32s3 / 8mb) (push) Failing after 15s
Firmware QEMU Tests (ADR-061) / QEMU Test (boundary-min) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / QEMU Test (default) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier0) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / QEMU Test (edge-tier1) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / QEMU Test (full-adr060) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / QEMU Test (tdm-3node) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / Swarm Test (ADR-062) (push) Has been skipped
Firmware QEMU Tests (ADR-061) / NVS Matrix Generation (push) Failing after 1s
Fix-Marker Regression Guard / Verify fix markers (push) Failing after 1s
ADR-115 MQTT integration tests / mqtt-integration (push) Failing after 1s
npm packages / harness/ruview (node 20) (push) Failing after 1s
npm packages / tools/ruview-mcp (node 20) (push) Failing after 1s
npm packages / tools/ruview-cli (node 20) (push) Failing after 1s
npm packages / tools/ruview-cli (node 22) (push) Failing after 1s
npm packages / tools/ruview-mcp (node 22) (push) Failing after 1s
nvsim-server → ghcr.io / build-and-publish (push) Failing after 1s
ruview-swarm CI guard / tests (full+train) (push) Failing after 2s
ruview-swarm CI guard / tests (ruflo) (push) Failing after 1s
ruview-swarm CI guard / tests (train) (push) Failing after 2s
BFLD MQTT Integration / cargo test --features mqtt (live mosquitto) (push) Failing after 29s
ruview-swarm CI guard / tests (default) (push) Failing after 2s
Point Cloud Viewer → GitHub Pages / build-and-deploy (push) Failing after 8s
ruview-swarm CI guard / ITAR / publish guard (push) Failing after 0s
ruview-swarm CI guard / build train_marl bin (push) Failing after 2s
ruview-swarm CI guard / clippy (-D warnings, --no-deps) (push) Failing after 3s
Security Scanning / Dependency Vulnerability Scan (push) Failing after 0s
Security Scanning / Static Application Security Testing (push) Failing after 1s
Security Scanning / Infrastructure Security Scan (push) Failing after 1s
Security Scanning / Secret Scanning (push) Failing after 1s
npm packages / harness/ruview (node 22) (push) Failing after 17s
Security Scanning / License Compliance Scan (push) Failing after 1s
Security Scanning / Container Security Scan (push) Failing after 4s
Security Scanning / Security Policy Compliance (push) Failing after 0s
wifi-densepose sensing-server → Docker Hub + ghcr.io / build · push · smoke-test (push) Failing after 1s
three.js demos → GitHub Pages / build-and-deploy (push) Failing after 1s
Verify Pipeline Determinism / Verify Pipeline Determinism (3.11) (push) Failing after 1s
Continuous Deployment / Deploy to Production (push) Has been cancelled
Continuous Deployment / Rollback Deployment (push) Has been cancelled
Continuous Deployment / Post-deployment Monitoring (push) Has been cancelled
Continuous Deployment / Notify Deployment Status (push) Has been cancelled
Continuous Deployment / Deploy to Staging (push) Has been cancelled
Security Scanning / Security Report (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 11:59:54 +08:00
..

homecore-recorder

SQLite state-history recorder for HOMECORE with Home Assistant-compatible schema and optional ruvector semantic search (P2).

Crates.io License MSRV: 1.89+ Tests ADR-132

P1 release: SQLite database with Home Assistant-compatible schema for persistent state history. P2 (feature-gated): ruvector HNSW semantic index for natural-language queries ("show me all kitchen devices that were warm at 3 PM").

What this crate does

homecore-recorder persists HOMECORE state changes to SQLite and optionally indexes them for semantic search. It provides:

  • Listener pattern — subscribes to homecore event bus and captures all StateChanged events
  • SQLite schema — mirrors HA's recorder database schema (v48) for 1:1 compatibility
  • Dual-write architecture — writes state snapshots to states table and attributes to state_attributes table (same as HA)
  • Deduplication — avoids recording redundant state writes when state hasn't actually changed
  • SemanticIndex trait — abstraction for plugging in ruvector embeddings (P2)
  • NullSemanticIndex — no-op implementation used when ruvector feature is off

Data persists in .homecore/home.db (by default; configurable). Queries work via standard SQLx, so any tool that reads SQLite can access the history.

Features

  • Home Assistant schema compatibility — migrate from HA's recorder.db without schema changes
  • Event recording — all state changes captured with last_changed timestamp and old/new state
  • Attribute persistence — JSON attributes for entities stored in separate table (HA pattern)
  • Automatic deduplication — skip writes when state hasn't changed (detect via hash)
  • Recorder runs table — track purge cycles and migration events (HA recorder_runs equivalent)
  • Semantic search (P2, --features ruvector) — embed state attributes + query by meaning
  • HNSW index (P2) — k-NN search for "all warm rooms" via ruvector
  • No data export overhead — SQLite is queryable directly; no proprietary format

Capabilities

Capability Type Method Notes
Record state change Listener RecorderListener::on_state_changed(event) Fires on homecore event bus; writes to SQLite
Query state history SQL SELECT * FROM states WHERE entity_id = ? ORDER BY last_changed DESC Standard SQLite; can be queried from anywhere
Purge old states Maintenance Recorder::purge(older_than) Deletes states older than specified timestamp
Deduplicate write Dedup DedupEngine::should_record(old_state, new_state) Skip if state hash unchanged
Create semantic index Index SemanticIndex::index_state(entity_id, state) (P2, opt-in) Hash-based embeddings; real embeddings in P3
Search by meaning Search SemanticIndex::search(query, k) (P2, opt-in) "warm rooms" → k-NN search in ruvector HNSW

Comparison to Home Assistant

Aspect Home Assistant homecore-recorder
Database SQLite (Python sqlite3) SQLite (Rust sqlx)
Schema recorder/ (schema v48) Identical HA schema v48
State table states + state_attributes Same dual-table layout
Persistence location .homeassistant/home-assistant_v2.db .homecore/home.db
Deduplication Python stateful listener DedupEngine + hash comparison
Purge policy YAML auto_purge_* + retention Configurable via Recorder::purge()
Semantic search None (HA has YAML history stats only) ruvector HNSW k-NN (P2, opt-in)
Schema compatibility N/A Bidirectional; can read HA's home.db directly

Performance

  • State write latency — p50 < 2 ms (SQLite WAL append); p99 < 15 ms (disk fsync)
  • Query latency — < 1 ms for indexed entity_id lookups; < 50 ms for range scans (full table)
  • Semantic search (P2) — < 10 ms for k-NN on 1 million state records (ruvector HNSW)
  • Memory overhead — ~10 MB per million recorded states (SQLite index overhead)
  • Disk space — ~2-4 KB per state record (entity_id + attributes + timestamps)
  • No per-crate benchmarks yet — a follow-up issue tracks baseline measurements

Run cargo bench -p homecore-recorder --features ruvector for criterion benchmarks.

Usage

Recording state changes (P1):

use homecore_recorder::{Recorder, RecorderListener};
use homecore::HomeCore;

#[tokio::main]
async fn main() {
    let homecore = HomeCore::new();
    
    // Create the recorder (writes to .homecore/home.db)
    let recorder = Recorder::new(".homecore/home.db").await.expect("init recorder");

    // Create and spawn a listener
    let listener = RecorderListener::new(recorder.clone());
    let mut rx = homecore.event_bus().subscribe_system();
    
    tokio::spawn(async move {
        while let Ok(event) = rx.recv().await {
            if let Err(e) = listener.on_state_changed(&event).await {
                eprintln!("Recorder error: {}", e);
            }
        }
    });

    // State changes now persist to SQLite
}

Querying history directly (standard SQLite):

-- All light.kitchen state changes in the last hour
SELECT state, attributes, last_changed 
FROM states 
WHERE entity_id = 'light.kitchen' 
  AND last_changed > datetime('now', '-1 hour')
ORDER BY last_changed DESC;

-- Average brightness by hour
SELECT 
  strftime('%Y-%m-%d %H:00:00', last_changed) AS hour,
  JSON_EXTRACT(attributes, '$.brightness') AS brightness
FROM states 
WHERE entity_id = 'light.kitchen'
GROUP BY hour;

Semantic search (P2, with --features ruvector):

// (P2, not yet implemented)
// let index = SemanticIndex::new(recorder.clone()).await?;
// let results = index.search("find all warm rooms at 3pm", 5).await?;
// results.iter().for_each(|r| println!("{:?}", r));

Relation to other HOMECORE crates

homecore-recorder (state history + semantic search)
├─ homecore (state machine; listens to event bus)
├─ homecore-api (exposes recorder data via REST query endpoint, P3)
├─ homecore-automation (can trigger on historical state conditions, P3)
├─ homecore-server (starts the listener on init)
└─ ruvector-core (semantic index, P2, optional feature)

References