Skill: flyfinec/camera-api (version 1.0.1)

--- name: camera-api description: 摄像头设备与云事件 API 技能。用于查询设备列表、根据设备名解析 device_id、查询设备最新封面图、查询设备在线状态、按天查询或汇总云事件、查询单个事件详情，以及在需要最新画面时向设备发送截图指令并轮询结果。当用户要求查看某个摄像头当前画面、最新封面、在线状态、今天/昨天/某天/最近几天发生了什么、某个事件详情，或只知道设备名称不知道 device_id 时使用。 metadata: {"openclaw":{"requires":{"env":["TIVS_API_KEY","TIVS_APP_ID"]},"primaryEnv":"TIVS_API_KEY"}} --- # Camera API 通过探鸽云端 API 完成设备解析、接口选路、云事件归纳和截图轮询，并将结果整理成面向用户的答案。优先返回设备状态、事件摘要和图片内容，不直接回传原始签名图片 URL 或未整理的接口响应。 ## 硬性约束 ### 认证与地址 - 所有请求都使用 `https://openapi-cn01.tange365.com/`。 - 所有请求都带上以下请求头： ```http Authorization: Bearer $TIVS_API_KEY X-Tg-App-Id: $TIVS_APP_ID Accept-Language: zh-CN X-Tg-Platform: pc Content-Type: application/json X-Tg-SDK-VERSION: 216 ``` - 只使用环境变量 `TIVS_API_KEY` 和 `TIVS_APP_ID`。不要在技能内容、代码或回复里硬编码任何凭据或用户私密信息。 - 默认按上面的 `X-Tg-Platform: pc` 发请求；如果当前运行环境已经通过 SDK 自动注入 `web`，沿用运行时默认值，不要同时发送两个不同的 `X-Tg-Platform`。 - 这些都是云端 API。通过局域网模式添加、直连的设备，不适用本技能里的云端查询接口。 - `https://openapi-cn01.tange365.com/` 只是 API 服务地址，不是创建 `AppID` 或 `api_key` 的入口页面。 ### 凭据缺失处理 - `AppID` / `api_key` 的获取页面可能因客户 APP 名称、APP 账号体系不同而不同，不要假设所有用户共用同一个入口页面。 - 只能按用户当前使用的 APP 名称来识别对应页面，不要尝试按品牌名推断，因为同一个 APP 里可能包含多个品牌。 - 已知映射： - `icam365` APP 账号：`https://skill.webcamapp.cc/icam365/api-key` - `wosee` APP 账号：`https://skill.webcamapp.cc/wosee/api-key` - 如果首次聊天里已经提到当前 APP 对应的获取页面，把这个页面记为固定上下文，后续缺少 `TIVS_API_KEY` 或 `TIVS_APP_ID` 时优先复用。 - 缺少凭据时，不要让用户直接把他人的密钥贴给你，也不要猜测或替换成 API Base URL、demo 地址、文档地址，更不要臆造一个 APP 页面 URL。 - 标准提示动作： 1. 明确指出缺少的是 `TIVS_API_KEY`、`TIVS_APP_ID`，还是两者都缺失。 2. 先确认用户当前使用的 APP 名称；如果上下文里已经明确，就不要重复追问。 3. 若 APP 命中已知映射，直接给出对应的 API Key 获取页面。 4. 若 APP 未命中已知映射，但首次聊天里给过该 APP 页面，就复用首次聊天里的页面。 5. 若 APP 未知或当前上下文里没有该 APP 页面，就明确让用户补充“当前使用的 APP 名称”或提供该 APP 的官方 API Key 获取页面。 6. 提醒用户在对应页面创建应用并获取 `AppID` 和 `api_key`，再配置到当前运行环境。 - 当用户只说“没有 API Key”但没说自己用的是哪个 APP 时，先追问 APP 名称，例如 `icam365`、`wosee`，再给页面。 ### 响应判断 - 将 `code = 0` 或 `code = 200` 视为成功。 - 失败时优先向用户解释失败原因或缺失条件，不要伪造结果。 - 对于没有完整字段文档支撑、或运行时字段结构不稳定的接口，只提取响应里实际存在的字段，不要臆造字段名。 - 云事件相关接口的常见字段并不完全一致，读取时优先兼容这些实际字段：`id`、`time`、`thumbnail`、`image`、`image_path`、`tag.tag`、`tag.name`、`tag.msg`、`can_play`、`summary`。 ### 图片与隐私 - 图片 URL 往往带签名参数，必须使用完整 URL 才能访问。 - 不要把原始签名图片 URL 直接发给用户。优先下载图片内容后再展示。 - 如果当前执行环境不能直接下载图片，就明确说明无法直接展示图片，不要把签名 URL 当作最终答案返回。 ### 参数处理 - 当用户只提供设备名称、备注名或模糊描述时，先调用设备列表接口定位 `device_id`。 - 只有明确支持多设备的接口才传入逗号分隔的 `device_id` 字符串；按天事件接口和事件详情接口按单设备、单事件处理。 - 用户说“今天”“昨天”“某天”时，先换算成明确日期，再调用按天事件接口。日期格式一律使用 `YYYY-MM-DD`。 - 用户未给日期，但问题是“发生了什么”“帮我总结事件”等日级查询时，默认按今天处理，并在回复里带上解析后的日期。 - 用户要求“最近几天”“一段时间内”的事件时，按天拆分成多次单日查询后再汇总，不要臆造不存在的范围 REST 接口。 - 用户要“实时画面”时，将其理解为“触发一次截图并等待设备上报结果”，不是实时视频流。 ### 路径与方法严格匹配 - 只能使用本技能已明确列出的 HTTP 方法和接口路径；不要根据命名习惯自行臆造相似路径。 - 截图工作流里，发送截图指令的唯一路径是 `POST /v2/msg/directive/device/{device_id}`；查询抓拍结果的唯一路径是 `GET /v2/cloud/screenshot/{device_id}`。 - `POST /v2/device/thumbnail` 只是查询封面图，不是抓拍结果接口；不要把它和 `GET /v2/cloud/screenshot/{device_id}` 混用。 - 明确禁止写成 `GET /v2/device/screenshot/{device_id}`、`POST /v2/device/screenshot/{device_id}`，或任何未在本文档出现的 screenshot 变体路径。 - 如果请求返回 `404`、`405` 或 `501`，先逐字检查方法和路径是否与本文档一致，再决定是否回退到备用接口；不要在错误路径上重复重试。 ## 任务路由 - 查询设备列表、根据名称找设备 ID：`POST /v2/device/list` - 查询设备最新封面图，不唤醒设备：`POST /v2/device/thumbnail` - 查询设备在线状态：`POST /v3/device/online` - 查询某个设备某一天的云事件：`GET /v2/cloud/events/{device_id}/{date}` - 分页查询某天云事件、按标签过滤、为截图轮询找新增事件：`POST /v2/cloud/event` - 查询单个云事件详情：`GET /v2/cloud/event/{event_id}` - 查询设备当前最新画面：先 `POST /v2/msg/directive/device/{device_id}` 发送截图指令，再优先 `GET /v2/cloud/screenshot/{device_id}` 或回退到当天云事件查询获取最新截图 ## 执行顺序 ### 1. 解析设备 当请求里没有可靠的 `device_id` 时： 1. 调用设备列表接口。 2. 优先按 `device_name` 精确匹配，再做保守的包含匹配。 3. 如果第一页不足以唯一定位，而响应里显示还有更多设备，继续翻页，直到唯一命中或穷尽列表。 4. 如果匹配到多个候选，先向用户澄清，不要随意选择。 5. 如果用户一次指定多个设备，为支持批量的接口整理成逗号分隔的 `device_id` 字符串；不支持批量的接口逐个调用。 ### 2. 选择接口 - 要“最新封面”“最近一张图”“不打扰设备看下最新画面”，优先用封面图接口。 - 要“当前是否在线”“能不能连上”“设备是否在休眠”，用在线状态接口。 - 要“今天发生了什么”“某天事件列表”“帮我总结当天事件”，用按天事件接口。 - 要“分页看事件”“只看某类 tag”“抓拍后找刚刚新增的事件”，用 `POST /v2/cloud/event`。 - 要“这个事件详情”“这个 event_id 是什么”，用事件详情接口。 - 要“现在拍一张”“看实时画面”“立即截图”，先发截图指令，再优先查 `GET /v2/cloud/screenshot/{device_id}`，必要时才回退到当天事件。 ### 3. 处理截图轮询 触发截图后按下面流程执行： 1. 记录发起截图时的当前时间，作为本次操作的时间基线。 2. 向 `/v2/msg/directive/device/{device_id}` 发送 `save_video` 指令。 3. 指令成功后必须先等待 3 秒，再查询抓拍结果；否则设备可能还没有完成上报。 4. 优先用 `GET /v2/cloud/screenshot/{device_id}` 获取最新抓拍结果；方法和路径都要逐字匹配，不要改写成 `/v2/device/screenshot/{device_id}` 或其他变体。 5. 只有当该接口返回的图片时间晚于时间基线，或能明确判断为本次新上报结果时，才把它当作本次截图结果。 6. 如果该接口只返回旧截图、没有可用时间字段、或无法确认新鲜度，则回退到 `POST /v2/cloud/event` 查询当天事件。 7. 在事件列表里优先选择时间晚于时间基线，且满足 `tag.tag == "screenshot"` 的最新事件；如果没有 `tag.tag`，再看 `tag.name` 或 `tag.msg` 是否表示截图。 8. 如果接口没有明确的截图标签，则选择时间晚于时间基线、且最可能由本次操作产生的新增事件。 9. 如果第一次还没有新截图，再等 2 秒重试，最多额外重试 2 次。 10. 超过重试次数仍没有结果时，明确告诉用户设备还没有上报新的截图结果。 不要无限轮询。 ## 输出规范 - 列设备时，优先给出 `device_name`、`device_id`、是否主人、绑定时间、联网方式等关键信息。 - 查封面图或截图结果时，优先直接展示图片内容；若无法展示，说明原因并保留事件摘要。 - 查在线状态时，先以顶层 `is_online` 作为设备整体是否在线的最终结论，再分别解释 `register_status.is_online`、`dormant_status.is_alive`、`rtc_status.is_online` 等子系统状态；子系统状态只能补充说明连接形态，不能单独推翻顶层在线结论。如果顶层 `is_online` 缺失，再明确说明整体结论未知，并列出已返回的各子系统状态。 - 查事件列表时，先自行按 `time` 倒序整理，再将 Unix 秒级时间戳转为可读时间，必要时结合 `tag`、`summary`、图片信息做简短总结。 - 查事件详情时，提取事件时间、类型、图片、摘要等关键信息。 - 对“今天”“昨天”等相对时间，向用户回复时优先带上解析后的明确日期，避免歧义。 - 用户要求总结某天事件时，基于该天全部事件做总结，不要只返回原始 JSON。 - 用户要求总结最近几天事件时，先按日期分组，再在每个日期内按设备归纳，最后给出跨天总结。 ## 接口说明 ### 查询设备列表 当需要列出设备或根据设备名解析 `device_id` 时，调用： ```http POST /v2/device/list ``` 请求体示例： ```json { "offset": 0, "limit": 10, "name": "我的门铃", "device_id": "" } ``` 请求参数说明： - `name`：按设备名称过滤，适合用户只提供设备名称、备注名或模糊名称时使用。 - `device_id`：按设备 ID 过滤，适合已经知道精确设备 ID 时使用。 - `offset` / `limit`：分页参数。 优先从响应中读取： - `device_id` - `device_name` - `is_owner` - `connect_way` - `extend.bind_time` - `total` - 当用户给的是设备名称时，可优先用 `name` 做初筛，再对返回项做精确匹配。 - 若 `total` 大于当前已取回的数量，而设备仍未唯一匹配，继续翻页。 ### 查询设备封面图 当用户想看设备最近一张画面，但不要求立刻唤醒设备时，调用： ```http POST /v2/device/thumbnail ``` 请求体示例： ```json { "device_id": "678A7QP6Q5WD" } ``` 说明： - 支持传单个或多个 `device_id`，多个设备用逗号分隔。 - 为稳妥起见，单次批量最多处理 10 个设备；超过 10 个时分批查询。 - 封面图来自设备最新上报事件截图，适合“快速看一眼”。 - 只从响应中提取实际存在的图片和设备标识字段。 ### 查询设备在线状态 当用户想知道设备是否在线、是否在工作、是否休眠、是否可用 RTC 连接时，调用： ```http POST /v3/device/online ``` 请求体示例： ```json { "device_id": "678A7QP6Q5WD" } ``` 说明： - 支持传单个或多个 `device_id`，多个设备用逗号分隔。 - 关注四类状态：整体在线、register 在线、休眠在线、RTC 在线。 - 返回结构是分层的：顶层 `is_online` 是设备整体在线状态的最终判断。用户问“设备在线吗”时，先回答这个结论。 - `register_status.is_online`、`dormant_status.is_alive`、`rtc_status.is_online` 分别表示长连接、休眠子系统、RTC 子系统的状态，用于解释整体状态来源和可用链路。 - 即使 `register_status.is_online` 为 `false`，只要顶层 `is_online` 为 `true`，仍应回答“设备整体在线”，再补充说明当前是哪个子系统在线、哪个子系统不在线。 - 只有当顶层 `is_online` 缺失时，才退化为分别报告各子系统状态，并明确说明“整体在线状态未知”。 - 如果接口返回更细字段，以实际字段为准进行解释；但不要让任何单个子系统状态覆盖顶层 `is_online` 的整体结论。 ### 查询某天云事件 当用户要查询今天或某一天的事件列表时，调用： ```http GET /v2/cloud/events/{device_id}/{date} ``` 路径参数： - `device_id`：单个设备 ID - `date`：`YYYY-MM-DD` 说明： - 事件通常包含时间、图片、标签，以及可能存在的 AI 总结摘要。 - 当用户要求“总结今天发生了什么”，先拉取该日事件，再基于 `tag` 和 `summary` 归纳。 - 如果用户要求汇总多个设备的同一天事件，对每个设备分别调用该接口，再合并结果。 - 如果用户要求最近几天的事件，对每一天分别调用该接口，再按日期汇总。 - 当天没有事件时，明确告诉用户“这一天没有查询到云事件”。 - 常见字段包括 `id`、`time`、`thumbnail`、`image`、`tag.tag`、`tag.name`、`tag.msg`、`can_play`。 ### 分页或按标签查询某天云事件 当你需要分页、按标签过滤事件，或为截图轮询查找新增事件时，调用： ```http POST /v2/cloud/event ``` 请求体示例： ```json { "device_id": "678A7QP6Q5WD", "tag": ["screenshot"], "date": "2026-03-21", "offset": 0, "limit": 10 } ``` 说明： - `tag` 可以留空数组，表示不过滤事件类型。 - 当需要更快定位截图结果时，优先把 `tag` 收窄到截图相关值。 - 该接口在现有 demo 中用于分页和标签过滤，比按天 GET 接口更适合轮询。 - 若非首页查询时 `offset > 0` 且返回空列表，视为没有更多数据。 - 成功响应中常见 `response.data.items` 数组，可继续读取 `time`、`thumbnail`、`image`、`tag`、`can_play` 等字段。 ### 查询事件详情 当用户提供 `event_id` 或要求查看某条事件详情时，调用： ```http GET /v2/cloud/event/{event_id} ``` 说明： - 提取事件时间、图片、标签、摘要等关键信息。 - 若接口返回 `detail.msg`、`detail.categoryName`、`containsVideo`、`storageId` 等详情字段，优先利用这些字段补充说明。 - 如果包含图片，遵守图片 URL 处理规则，不要直接回传签名 URL。 ### 查询最新抓拍结果 当截图指令已经发送，且当前环境提供专门的抓拍结果查询接口时，调用： ```http GET /v2/cloud/screenshot/{device_id} ``` 说明： - 这是截图工作流里的优先查询接口，现有 demo 已使用它读取抓拍结果。 - 这是查询抓拍结果时唯一允许直查的接口，方法固定为 `GET`，不要改写成 `/v2/device/screenshot/{device_id}` 或其他 `/v2/device/*` 路径。 - 常见结果结构为 `response.data.items`，图片字段常见为 `image_path`。 - 返回 `200` 不代表一定拿到了本次新截图；要优先结合 `time`、`created_at`、`create_time` 等时间字段，确认图片晚于截图指令的时间基线。 - 如果该接口只返回旧图片、没有时间字段，或无法确认是不是本次新结果，就按“没有返回可用图片”处理。 - 如果该接口返回 `404`、`405` 或 `501`，先检查自己是否把方法或路径写错了；确认无误后，再判断当前环境是否不支持该接口。 - 如果该接口不可用或没有返回可用图片，再回退到 `POST /v2/cloud/event`。 ### 发送截图指令 当用户明确要求“现在拍一张”“看当前画面”时，调用： ```http POST /v2/msg/directive/device/{device_id} ``` 请求体示例： ```json { "directive": "save_video", "reactive": false, "data": "" } ``` 说明： - 该接口只负责触发抓拍，不直接返回图片。 - 该接口按单个 `device_id` 调用；如果用户要多个设备的当前画面，逐个设备执行。 - 发送截图指令后必须先等待 3 秒，再去查询抓拍结果或当天事件；否则设备可能还没有完成上报。 - 如果用户没有特别要求，默认使用普通截图参数。 - 除非当前执行环境已经确认过高清截图参数的准确格式，否则不要自行扩展 `data` 字段结构。 ## 常见任务模板 ### 查看某个设备今天发生了什么 1. 如无 `device_id`，先查设备列表。 2. 将“今天”换算为明确日期。 3. 调用按天事件接口。 4. 提取关键事件并总结。 ### 查看多个设备某一天发生了什么 1. 将目标设备解析为多个 `device_id`。 2. 对每个设备分别调用按天事件接口。 3. 按设备汇总结果，再给出跨设备总结。 ### 查看某个设备最近几天发生了什么 1. 如无 `device_id`，先查设备列表。 2. 将时间范围拆成多个单日日期。 3. 对每一天分别调用按天事件接口。 4. 先按日期总结，再给出跨天结论。 ### 查看某个设备现在的画面 1. 如无 `device_id`，先查设备列表。 2. 发送截图指令。 3. 优先查 `GET /v2/cloud/screenshot/{device_id}`，失败再按轮询流程查当天事件。 4. 返回最新截图结果，不直接返回签名 URL。 ### 批量查看多个设备在线状态 1. 将多个 `device_id` 组装为逗号分隔字符串。 2. 调用在线状态接口。 3. 按设备逐个汇总状态，先给整体在线结论，再补充 register、休眠、RTC 等子系统状态。 ### 批量查看多个设备最新封面 1. 将多个 `device_id` 组装为逗号分隔字符串。 2. 调用封面图接口。 3. 按设备提取最新封面结果。 ## 失败场景处理 - 没有 `TIVS_API_KEY` 或 `TIVS_APP_ID`：明确提示缺少环境变量；先识别用户当前 APP 名称，再引导他去对应 APP 的 API Key 页面创建应用并获取 `AppID` 与 `api_key`。 - 设备属于局域网模式或直连设备：说明这些云端 API 不适用，不能用本技能直接查询。 - 设备名无法唯一匹配：先向用户确认设备。 - 查询某天事件为空：直接说明该天没有事件，不要当成系统错误。 - 截图指令成功但迟迟没有新事件：说明设备还未上报结果或当前不在线。 - 抓拍结果查询返回 `404`、`405` 或 `501`：先检查是否误写成 `/v2/device/screenshot/{device_id}`、是否把 `GET` 写成了其他方法；只有确认路径和方法都正确后，才判断接口本身不可用并回退到 `POST /v2/cloud/event`。 - 在线状态字段看起来互相矛盾：以顶层 `is_online` 作为整体结论，再说明各子系统状态可能处于切换瞬间；不要因为某一个子系统离线就误判整体离线。 - 接口返回未知字段结构：只总结已确认字段，不要杜撰字段含义。


Security scan verdicts — ClawScan: clean | static analysis: clean | VirusTotal: clean | SkillSpector: clean (LOW)