ClawSkills logoClawSkills

Nest Devices

通过 Device Access API 控制 Nest 智能家居设备(恒温器、摄像头、门铃)。当被要求检查或调节家中温度、查看监控画面时使用...

介绍

# Nest Device Access

通过 Google 智能设备管理 API (Smart Device Management API) 控制 Nest 设备。

## 设置

### 1. Google Cloud 和设备访问

1. 在 [console.cloud.google.com](https://console.cloud.google.com) 创建一个 Google Cloud 项目 2. 支付 $5 费用并在 [console.nest.google.com/device-access](https://console.nest.google.com/device-access) 创建一个设备访问项目 3. 创建 OAuth 2.0 凭据(Web 应用程序类型) 4. 添加 `https://www.google.com` 作为授权的重定向 URI 5. 将您的 Nest 账户关联到设备访问项目

### 2. 获取刷新令牌

运行 OAuth 流程以获取刷新令牌:

```bash # 1. Open this URL in browser (replace CLIENT_ID and PROJECT_ID): https://nestservices.google.com/partnerconnections/PROJECT_ID/auth?redirect_uri=https://www.google.com&access_type=offline&prompt=consent&client_id=CLIENT_ID&response_type=code&scope=https://www.googleapis.com/auth/sdm.service

# 2. Authorize and copy the 'code' parameter from the redirect URL

# 3. Exchange code for tokens: curl -X POST https://oauth2.googleapis.com/token \ -d "client_id=CLIENT_ID" \ -d "client_secret=CLIENT_SECRET" \ -d "code=AUTH_CODE" \ -d "grant_type=authorization_code" \ -d "redirect_uri=https://www.google.com" ```

### 3. 存储凭据

存储在 1Password 或环境变量中:

**1Password**(推荐): 创建包含以下字段的项目:`project_id`, `client_id`, `client_secret`, `refresh_token`

**环境变量:** ```bash export NEST_PROJECT_ID="your-project-id" export NEST_CLIENT_ID="your-client-id" export NEST_CLIENT_SECRET="your-client-secret" export NEST_REFRESH_TOKEN="your-refresh-token" ```

## 使用方法

### 列出设备 ```bash python3 scripts/nest.py list ```

### 恒温器

```bash # Get status python3 scripts/nest.py get <device_id>

# Set temperature (Celsius) python3 scripts/nest.py set-temp <device_id> 21 --unit c --type heat

# Set temperature (Fahrenheit) python3 scripts/nest.py set-temp <device_id> 70 --unit f --type heat

# Change mode (HEAT, COOL, HEATCOOL, OFF) python3 scripts/nest.py set-mode <device_id> HEAT

# Eco mode python3 scripts/nest.py set-eco <device_id> MANUAL_ECO ```

### 摄像头

```bash # Generate live stream URL (RTSP, valid ~5 min) python3 scripts/nest.py stream <device_id> ```

## Python API

```python from nest import NestClient

client = NestClient()

# List devices devices = client.list_devices()

# Thermostat control client.set_heat_temperature(device_id, 21.0) # Celsius client.set_thermostat_mode(device_id, 'HEAT') client.set_eco_mode(device_id, 'MANUAL_ECO')

# Camera stream result = client.generate_stream(device_id) rtsp_url = result['results']['streamUrls']['rtspUrl'] ```

## 配置

脚本按以下顺序检查凭据:

1. **1Password**:设置 `NEST_OP_VAULT` 和 `NEST_OP_ITEM`(或使用默认值:保险库 "Alfred",项目 "Nest Device Access API") 2. **环境变量**:`NEST_PROJECT_ID`, `NEST_CLIENT_ID`, `NEST_CLIENT_SECRET`, `NEST_REFRESH_TOKEN`

## 温度参考

| 设置 | 摄氏度 | 华氏度 | |---------|---------|------------| | Eco (外出) | 15-17°C | 59-63°F | | 舒适 | 19-21°C | 66-70°F | | 温暖 | 22-23°C | 72-73°F | | 夜间 | 17-18°C | 63-65°F |

---

## 实时事件(门铃、移动等)

要在有人按门铃或检测到移动时即时收到警报,您需要设置 Google Cloud Pub/Sub 和 Webhook。

### 先决条件

- 已安装并完成身份验证的 Google Cloud CLI (`gcloud`) - 用于隧道的 Cloudflare 账户(免费层级即可) - 在配置中启用了 Clawdbot hooks

### 1. 启用 Clawdbot Hooks

添加到您的 `clawdbot.json`:

```json { "hooks": { "enabled": true, "token": "your-secret-token-here" } } ```

生成一个令牌:`openssl rand -hex 24`

### 2. 创建 Pub/Sub 主题

```bash gcloud config set project YOUR_GCP_PROJECT_ID

# Create topic gcloud pubsub topics create nest-events

# Grant SDM permission to publish (both the service account and publisher group) gcloud pubsub topics add-iam-policy-binding nest-events \ --member="serviceAccount:[email protected]" \ --role="roles/pubsub.publisher"

gcloud pubsub topics add-iam-policy-binding nest-events \ --member="group:[email protected]" \ --role="roles/pubsub.publisher" ```

### 3. 将主题关联到设备访问

前往 [console.nest.google.com/device-access](https://console.nest.google.com/device-access) → 您的项目 → 编辑 → 将 Pub/Sub 主题设置为:

``` projects/YOUR_GCP_PROJECT_ID/topics/nest-events ```

### 4. 设置 Cloudflare 隧道

```bash # Install cloudflared curl -L -o ~/.local/bin/cloudflared https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64 chmod +x ~/.local/bin/cloudflared

# Authenticate (opens browser) ~/.local/bin/cloudflared tunnel login

# Create named tunnel ~/.local/bin/cloudflared tunnel create nest-webhook

# Note the Tunnel ID (UUID) from output ```

创建 `~/.cloudflared/config.yml`:

```yaml tunnel: nest-webhook credentials-file: /home/YOUR_USER/.cloudflared/TUNNEL_ID.json

ingress: - hostname: nest.yourdomain.com service: http://localhost:8420 - service: http_status:404 ```

创建 DNS 路由:

```bash ~/.local/bin/cloudflared tunnel route dns nest-webhook nest.yourdomain.com ```

### 5. 创建 Systemd 服务

**Webhook 服务器** (`/etc/systemd/system/nest-webhook.service`):

```ini [Unit] Description=Nest Pub/Sub Webhook Server After=network.target

[Service] Type=simple User=YOUR_USER Environment=CLAWDBOT_GATEWAY_URL=http://localhost:18789 Environment=CLAWDBOT_HOOKS_TOKEN=your-hooks-token-here ExecStart=/usr/bin/python3 /path/to/skills/nest-devices/scripts/nest-webhook.py Restart=always RestartSec=5

[Install] WantedBy=multi-user.target ```

**Cloudflare 隧道** (`/etc/systemd/system/cloudflared-nest.service`):

```ini [Unit] Description=Cloudflare Tunnel for Nest Webhook After=network-online.target Wants=network-online.target

[Service] Type=simple User=YOUR_USER ExecStart=/home/YOUR_USER/.local/bin/cloudflared tunnel run nest-webhook Restart=always RestartSec=5

[Install] WantedBy=multi-user.target ```

启用并启动:

```bash sudo systemctl daemon-reload sudo systemctl enable --now nest-webhook cloudflared-nest ```

### 6. 创建 Pub/Sub 推送订阅

```bash gcloud pubsub subscriptions create nest-events-sub \ --topic=nest-events \ --push-endpoint="https://nest.yourdomain.com/nest/events" \ --ack-deadline=30 ```

### 7. 测试

```bash # Test webhook endpoint curl https://nest.yourdomain.com/health

# Simulate doorbell event curl -X POST http://localhost:8420/nest/events \ -H "Content-Type: application/json" \ -d '{"message":{"data":"eyJyZXNvdXJjZVVwZGF0ZSI6eyJuYW1lIjoiZW50ZXJwcmlzZXMvdGVzdC9kZXZpY2VzL0RPT1JCRUxMLTAxIiwiZXZlbnRzIjp7InNkbS5kZXZpY2VzLmV2ZW50cy5Eb29yYmVsbENoaW1lLkNoaW1lIjp7ImV2ZW50SWQiOiJ0ZXN0In19fX0="}}' ```

### 支持的事件

| 事件 | 行为 | |-------|-----------| | `DoorbellChime.Chime` | 🔔 **警报** — 发送照片到 Telegram | | `CameraPerson.Person` | 🚶 **警报** — 发送照片到 Telegram | | `CameraMotion.Motion` | 📹 仅记录(无警报) | | `CameraSound.Sound` | 🔊 仅记录(无警报) | | `CameraClipPreview.ClipPreview` | 🎬 仅记录(无警报) |

> **陈旧过滤器:** 超过 5 分钟的事件会被记录,但不会触发警报。这可以防止在 Pub/Sub 消息队列延迟投递时造成通知轰炸。

### 图像捕获

当门铃或人员事件触发警报时:

1. **主要方式:** SDM `GenerateImage` API — 快速,事件特定快照 2. **回退方式:** 通过 `ffmpeg` 捕获 RTSP 实时流帧(需要安装 `ffmpeg`)

### 环境变量

| 变量 | 是否必需 | 描述 | |----------|----------|-------------| | `CLAWDBOT_GATEWAY_URL` | 否 | 网关 URL(默认:`http://localhost:18789`) | | `CLAWDBOT_HOOKS_TOKEN` | 是 | 用于感知通知的网关 hooks 令牌 | | `OP_SVC_ACCT_TOKEN` | 是 | 用于 Nest API 凭据的 1Password 服务账户令牌 | | `TELEGRAM_BOT_TOKEN` | 是 | 用于发送警报的 Telegram 机器人令牌 | | `TELEGRAM_CHAT_ID` | 是 | 接收警报的 Telegram 聊天 ID | | `PORT` | 否 | Webhook 服务器端口(默认:`8420`) |

### 重要设置说明

- **验证设备访问控制台中的完整 Pub/Sub 主题路径**是否与您的 GCP 项目完全匹配:`projects/YOUR_GCP_PROJECT_ID/topics/nest-events` - **使用推送订阅,而非拉取订阅** — Webhook 期望通过 HTTP POST 接收数据 - **设置后进行端到端测试**:按一下门铃并确认收到照片。不要仅依赖模拟的 POST 请求。

---

## 限制

- 摄像头事件图像约在 5 分钟后过期(RTSP 回退方式将捕获当前帧) - 实时事件需要设置 Pub/Sub(见上文) - 快速隧道(不带 Cloudflare 账户)不保证在线时间 - 某些较旧的 Nest 设备可能不支持所有功能 - 移动和声音事件故意不设警报,以避免通知疲劳

更多产品