# @ajclarkson/homerun 中文文档

规范地址：https://npmcn.com/package/%40ajclarkson/homerun/

版本：0\.1\.0
npm 元数据更新时间：2026-11-08T12:53:24.692Z
中文译文更新时间：2026-11-08T12:59:58.603Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40ajclarkson/homerun
原文对照：https://npmcn.com/package/%40ajclarkson/homerun/?lang=original
项目主页：https://github.com/ajclarkson/homerun#readme
源码仓库：https://github.com/ajclarkson/homerun

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：191 kB，63 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：9 个
- 首次发布：2026-07-11T11:06:23.032Z
- 最新版本发布：2026-11-08T12:53:24.342Z
- 近 30 天下载量：2978（2026-10-05 至 2026-11-03，npm 官方下载统计）
- 已发布版本数：119（近 12 个月 119 个）

## 中文简介

家庭助理的脚本自动化框架

## 安装

```sh
npm install @ajclarkson/homerun
```

也可以使用：`pnpm add @ajclarkson/homerun`、`yarn add @ajclarkson/homerun`、`bun add @ajclarkson/homerun`

## README

# 全垒打

**TypeScript中的打字可测试的家庭助理自动化.**

> **状况:1.0前.** API可能会改变. 构建发布为 npm `@ajclarkson/homerun` (单位:千美元)`edge` 标签,每推一次 `main`和作为多克的形象, `ghcr.io/ajclarkson/homerun:edge`。 。 。 .

Homerun是一个以纯函数取代HA自动化和节点-RED流量的框架. 每个自动化都是上下文构建器和还原器——没有副作用,没有隐藏状态,没有YAML. 管线处理可观察性,错位隔离,动作执行.

* * *

## 问题

家庭助理自动化是YAML. 节点-RED流量为JSON blobs. 两者都难以测试,难以审查,也无法进行打字检查. 凌晨2点,一个糟糕的部署 静静地打破了你的灯.

Homerun带来了与应用代码相同的学科:纯函数,打入输入,以及以毫秒为单位运行的测试套件.

* * *

## 如何运作

每个自动化都遵循同样的管道:

```
Event → context() → reduce() → actions[]
```

**`context()`** 从 HA 状态缓存中读取并返回打入的快照——如果缺少所需的输入,则提前中止。 这是唯一触及外部国家的地方.

**`reduce()`** 是一个纯函数。 它收到上下文,并发回附有声明行动清单的决定。 没有Aync 没有副作用 没有HA的电话.

**输油管** 处理其他所有事项:关联ID、可观察事件、错误隔离和动作执行.

* * *

## 示例

```typescript
import { defineAutomation, abort, requireState, requireNumericState } from '@ajclarkson/homerun';

export default defineAutomation({
  id: 'kitchen:lighting',
  location: 'kitchen',
  subsystem: 'lighting',

  triggers: [
    { type: 'state_changed', entity: 'binary_sensor.kitchen_motion' },
    { type: 'on_start' },
  ],

  context(state) {
    if (requireState(state, 'input_boolean.kitchen_lights_enabled') !== 'on') {
      return abort('automation_disabled');
    }
    return {
      motion: requireState(state, 'binary_sensor.kitchen_motion') === 'on',
      lux: requireNumericState(state, 'sensor.kitchen_lux'),
      luxThreshold: requireNumericState(state, 'input_number.kitchen_lux_threshold'),
    };
  },

  reduce(ctx) {
    const shouldLight = ctx.motion && ctx.lux < ctx.luxThreshold;
    return {
      decision: shouldLight ? 'lights_on' : 'lights_off',
      actions: [
        {
          type: 'ha.call_service',
          domain: 'light',
          service: shouldLight ? 'turn_on' : 'turn_off',
          target: { entity_id: 'light.kitchen_ceiling' },
        },
      ],
    };
  },
});
```

`requireState` 财务报告和审定财务报表 `requireNumericState` 中止运行,如果一个实体不存在或非数字存在,则将丢失的实体记录下来,因此一个已死传感器永远不会沉默地变成一个错误的决定. 决定 `conditions` 默认到完整上下文,所以已发布的事件会解释自己.

这样的文件会进入您的自动化目录; 见 [消费者设置](https://npmcn.com/package/%40ajclarkson/homerun/docs/consumers.md)。 。 。 .

* * *

## 测试

因为 `reduce()` 是纯函数,测试只是函数调用。 在没有家庭助理连接的情况下测试整个自动化,使用测试助手:

```typescript
import { describe, it, expect } from 'vitest';
import { testAutomation } from '@ajclarkson/homerun/testing';
import kitchenLights from './kitchen-lights';

describe('kitchen lighting', () => {
  it('turns lights on when motion is detected below the lux threshold', () => {
    const result = testAutomation(kitchenLights, {
      event: { type: 'state_changed', entity_id: 'binary_sensor.kitchen_motion', new_state: { state: 'on' } },
      state: {
        'input_boolean.kitchen_lights_enabled': { state: 'on' },
        'binary_sensor.kitchen_motion': { state: 'on' },
        'sensor.kitchen_lux': { state: '20' },
        'input_number.kitchen_lux_threshold': { state: '40' },
      },
    });
    expect(result.decision).toBe('lights_on');
    expect(result.actions[0]).toMatchObject({ service: 'turn_on' });
  });
});
```

没有嘲弄,没有HA连接,没有Aync. `testAbort` 财务报告和审定财务报表 `testUnavailable` 覆盖中止路径。 见 [自动化 API](https://npmcn.com/package/%40ajclarkson/homerun/docs/api.md)。 。 。 .

* * *

## 触发和行动

| 触发 | 当火 |
| --- | --- |
| `state_changed` | 实体的状态或属性变化. 过滤器为 `to`; 延迟使用 `duration`。 。 。 . |
| `schedule` | 疯狂的表达火. |
| `on_start` | 系统准备就绪,国家缓存人员已满员. |
| `timer_expired` | 前一个定时器 `timer.start` 动作已过期. |
| `button` | 按钮实体发出 a `single_press`, (中文(简体) ), `double_press`,或 `hold` 手势. |
| `mqtt_in` | 发送到 MQTT 主题的消息 . |

| 行动 | 效果 |
| --- | --- |
| `ha.call_service` | 家庭助理服务 |
| `mqtt.publish` | 发布到 MQTT 主题 |
| `timer.start` | 启动( 或重新启动) 一个命名的计时器 |
| `timer.cancel` | 取消命名的计时器 |

从 `reduce()` 作为平面数组;运行时间在决定事件发布后执行. 完整类型和语义 : [自动化 API](https://npmcn.com/package/%40ajclarkson/homerun/docs/api.md)。 。 。 .

* * *

## 观察性

每个管道运行都会向MQTT发布一个事件——无论是决定,中止,还是扔出——每个动作都会发布自己的起步和结果事件. A 类 `correlation_id` 在事件源头做薄荷 让你追踪到一个HA状态的变化 到服务电话 由此产生.

```json
{
  "schema": "home.events.v2",
  "correlation_id": "b3d2f1a0-...",
  "root_correlation_id": "b3d2f1a0-...",
  "automation_id": "kitchen:lighting",
  "location": "kitchen",
  "subsystem": "lighting",
  "event_type": "decision",
  "trigger": { "type": "state_changed", "entity_id": "binary_sensor.kitchen_motion", "to": "on" },
  "decision": "lights_on",
  "conditions": { "motion": true, "lux": 20, "luxThreshold": 40 },
  "actions": [{ "type": "ha.call_service", "domain": "light", "service": "turn_on" }],
  "hasAction": true,
  "timestamp": "2026-06-23T18:00:00.000Z"
}
```

Schema,主题,指令包跟踪和Prometheus 度量衡: [观察性](https://npmcn.com/package/%40ajclarkson/homerun/docs/observability.md)。 。 。 .

* * *

## 宣布的理由、目录和历史

默认的决定 `reason` 是一个自由字符串。 相反,自动化可以宣布它可能给出的原因,因此消费者(一个仪表板,一个通知器)可以在不解析字符串的情况下解释发生的事情. 这里的一切都是选入的:没有自动化的 `reasons` 行为和出版都和以前一样.

```typescript
export default defineAutomation({
  id: 'kitchen:lighting',
  location: 'kitchen',
  subsystem: 'lighting',
  triggers: [{ type: 'state_changed', entity: 'binary_sensor.kitchen_motion' }],
  reasons: {
    lights_on: { outcome: 'acted' },
    lux_high: { outcome: 'declined', facts: ['lux', 'threshold'] },
    startup: { outcome: 'ignored' },
  },
  context: (state) => ({ lux: requireNumericState(state, 'sensor.kitchen_lux') }),
  reduce: ({ lux }) =>
    lux > 40
      ? { decision: 'no_action', reason: 'lux_high', facts: { lux, threshold: 40 }, actions: [] }
      : { decision: 'turn_on', reason: 'lights_on', actions: [kitchenLightsOn] },
});
```

-   `outcome` 实值 `acted` (规则改变了什么), `declined` (它选择不采取行动,一个人会想知道原因)或 `ignored` (噪声:起步,已入正态). 它被宣布,从来没有从 `actions`。 。 。 .
-   `facts` 是输入的句子需要的值:每个理由最多8个按键,每个按字符串、有限数字、布尔或 `null`它们与 `conditions` 目的: `conditions` 是整个上下文的调试堆放 可能自由改变形状, `facts` 是消费者可以依赖的小型、 命名、 检查的套件.
-   宣布的理由执行三次。 编译时间 `reason` 已声明的密钥和 `facts` 必须准确携带该理由的密钥(额外密钥只在运行时被捕获,因为TypeScript不检查返回对象的多余属性)。 装入时间 `defineAutomation` 丢入不良结果、事实列表或理由名称(字母、数字和下划线:理由不包含自由文本)。 在运行时,一个未申报的理由,或一个未申报、失踪或非原始事实,从未停止行动:决定是在没有公布的情况下公布的 `outcome` 或者说 `facts` 和单独的形状 `declaration_error` 事件发布到 `homerun/events` 并登录,与 `problem` (单位:千美元)`undeclared_reason`, (中文(简体) ), `missing_fact`, (中文(简体) ), `undeclared_fact` 或者说 `invalid_fact_value`当标识形状时, `reason` 财务报告和审定财务报表 `fact`观察力绝不能阻止真正的行动。 宣布无一物不能返回的自动化 `facts` (一个编译错误). `defineAutomation` 和登记处(包括热重装)均拒绝错误声明,并拒绝保留地点 `dev`在装货.
-   决定事件获得可选 `outcome` 财务报告和审定财务报表 `facts`,只用于宣布自动化.

**目录.** 声明保留于 `homerun/catalog` (单位:千美元)`home.catalog.v1`) 启动时和重新装入后,每个条目的 `reasons` 添加到 `GET /automations`。只有宣布原因的自动化设备才会出现。 该目录在每次启动时都会被公布,如果无内容则会空出原因,所以保留的副本永远不会被搁置. 消费者可以对照其措辞表检查.

**历史.** 设定 `history` 在配置中(默认关闭)保留一个环缓冲器来显示值得询问的事件“这里发生了什么?”

```yaml
history:
  size: 20        # per location, 1 to 200
  houseSize: 30   # house-wide, 1 to 200
```

每个存储条目重新发布,最先更新,保留在 `homerun/{location}/history` 财务报告和审定财务报表 `homerun/history` (单位:千美元)`home.history.v1`) (中文(简体) ). 记得:已宣布 `acted` 财务报告和审定财务报表 `declined` (或,对于未宣布的自动化、有行动的决定),除 `disabled`,则失败动作(失败) `action_result` 或一个 `action_ack_timeout`) (中文(简体) ). 条目只结构化:理由键、事实、a `trigger` 概要和a `detail` 记录`abort_kind`编号 :`entity`,或 `failure`编号 :`action`编号 :`entity`。 留存的再版是和最新状态( 250ms) 相接的, 并被冲出关闭状态 。 启动时, 缓冲器会从保留的主题中重新播种, 因此历史可以幸存到重启中; 保存错误的信息会被记录下来, 而缓冲器开始为空 。 种子等待 `1s` 由经纪人发送保留的信息. `dev` 作为地点名称保留(登记时被拒)。 书目和历史都遵循 `events.enabled`: 当是时 `false`,既不是出版(也不是原始历史,也不是保存),与MQTT流的其他部分一样。 在干跑模式下,每个话题都移动到下面 `homerun/dev/`。 。 。 .

两种有效载荷的JSON Schemas装入 [`schemas/`](https://npmcn.com/package/%40ajclarkson/homerun/schemas) 并随包出版. 每一个有效载荷在公布之前都要对他们进行验证.

* * *

## 运行

```bash
npm install @ajclarkson/homerun
```

家常读作 `configuration.yaml` (路径从 `HOMERUN_CONFIG`)与您的家用助理 URL 和令牌, MQTT 经纪人和自动化目录. 秘密可以生活在一个 `secrets.yaml` 旁边,并被引用 `!secret`。 。 。 . [`configuration.yaml.example`](https://npmcn.com/package/%40ajclarkson/homerun/configuration.yaml.example) 显示每个选项.

设定 `options.dry_run: true` 在不采取任何行动的情况下运行整个管道——环境、减少、可观察性.

设置您的自动回放, 从您的家庭助理中生成实体类型, 运行运行时间包含在 [消费者设置](https://npmcn.com/package/%40ajclarkson/homerun/docs/consumers.md)。 。 。 .

要研究框架本身 复制并使用 `npm run dev` (从源头跑出,热量重载)和 `npm test`。 。 。 .

* * *

## HTTP API 密码

服务器在端口显示 HTTP API `7070` 默认(`server.port` 在配置中.

| 方法 | 路径 | 说明 |
| --- | --- | --- |
| `GET` | `/health/live` | 总是返回 `200 { status: "live" }` 用于活性探测器. |
| `GET` | `/health/ready` | 回返 `200` 当HA状态的缓存被装入,自动化设备被装入时, `503` 开始的时候。 反应包括 `entities`, (中文(简体) ), `automations` 计数,以及 `dry_run: true` 如果运行在干燥模式中. |
| `GET` | `/automations` | 列出所有注册自动化及其 `id`, (中文(简体) ), `location`, (中文(简体) ), `subsystem`类型,加 `reasons` 给那些宣布他们有罪的人. |
| `POST` | `/automations/:id/trigger` | 手动点火 `on_start` 用于给定自动化的事件. |
| `POST` | `/reload` | 重新扫描自动化目录并重载已更改的文件 . |
| `GET` | `/events` | 所有编审中的决定和行动活动的服务器发送事件流实时. |

* * *

## 建筑

```
HAClient ──────────────────────────────────────┐
  └─ state_changed (per entity, with corr. ID) │
                                               ▼
Scheduler (cron / on_start) ──────► TriggerEngine.dispatch()
TimerManager (setTimeout)  ──────►        │
                                          ▼
                                   matchAndFire()
                                          │
                              ┌───────────▼──────────┐
                              │    Pipeline Runner    │
                              │  context → reduce     │
                              │  → validate → fanout  │
                              └──────────┬────────────┘
                                         │
                          ┌──────────────┴──────────────┐
                          ▼                             ▼
                   Observability                  ActionRuntime
                 (MQTT events)           (HA calls / timers / MQTT)
```

* * *

## 许可证

麻省理工学院

## 常见问题

### @ajclarkson/homerun 是什么？

家庭助理的脚本自动化框架

### 如何安装 @ajclarkson/homerun？

在项目目录运行 npm install @ajclarkson/homerun，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 homerun、homerun-generate-ha-types、homerun-generate-ha-services，可以用 npx homerun 直接运行。

### @ajclarkson/homerun 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @ajclarkson/homerun 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @ajclarkson/homerun 可以商用吗？

@ajclarkson/homerun 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @ajclarkson/homerun 的下载量有多少？

根据 npm 官方下载统计，@ajclarkson/homerun 在 2026/10/05 – 2026/11/03 这 30 天内被下载 2,978 次，日均约 99 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @ajclarkson/homerun 还在维护吗？

最新版本 0\.1\.0 发布于 2026/11/08（今天）；至今共发布 119 个版本，其中过去 12 个月发布了 119 个；首次发布于 2026/07/11。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

