Menu
HomeDriversSkillsSolutionsUpdatesGitHub

PhanthyMotus

← Skill Marketplace

天翼远程物品守护

Utilityv1.0.0by hasip· 9/14/2026

当用户说"帮我看/守护某物品"时,用视觉检测持续巡查该物品,发现被拿走时本地语音播报、挥手报警,并通过 channel_reply 向消息平台发送远程报警。

Description

当用户说"帮我看/守护某物品"时,用视觉检测持续巡查该物品,发现被拿走时本地语音播报、挥手报警,并通过 channel_reply 向消息平台发送远程报警。

Instruction Content

# 物品守护 — 稳定执行脚本

严格按此逻辑运行,不得额外发挥。

## 一、触发门禁

```text
IF 用户消息包含 ("不用看了" OR "停止守护" OR "结束守护"):
    执行 STOP_FLOW

ELIF 用户消息包含 ("帮我看" OR "看着" OR "守护" OR "盯着")
     AND 包含具体物品名:
    执行 GUARD_FLOW

ELIF 用户消息包含 ("帮我看" OR "看着" OR "守护" OR "盯着")
     BUT 不包含具体物品名:
    TEXT_REPLY "请告诉我要守护什么物品,比如说帮我看手机"

ELSE:
    按正常对话处理
    # 不启动、停止或修改守护任务
    # 不因为普通对话调用 channel_reply
```

普通对话不能中断正在运行的守护任务。

## 二、允许使用的工具

本脚本只允许使用以下工具或动作:

```text
vop
tts.speak
speaker.play
channel_reply
camera_rgb
TEXT_REPLY
SLEEP
```

`camera_rgb` 仅作为 `vop` 的输入源。

禁止调用 `arm_gesture` 或任何手部动作工具。

## 三、channel_reply 核心规则

`channel_reply` 是一次性事件通知工具,不是循环播报工具。

只允许在以下四种状态事件首次发生时调用:

```text
guard_started
item_missing
guard_completed
guard_stopped
```

每个事件在一次守护任务中最多通知一次。

禁止在以下情况下调用 `channel_reply`:

```text
每次巡查
每次调用 vop.read
物品仍然存在
首次暂时未检测到物品
等待下一次确认
普通对话
重复进入同一状态
守护任务已经结束
没有状态变化
```

所有 `channel_reply` 必须通过下面的统一通知逻辑执行,不得直接在其他位置调用:

```text
FUNCTION SEND_EVENT_ONCE(EVENT_NAME, CONTENT):
    IF EVENT_NAME NOT IN notified_events:
        notified_events.ADD(EVENT_NAME)
        channel_reply(content=CONTENT)
    ELSE:
        RETURN
```

`TEXT_REPLY`、`tts.speak` 和 `channel_reply` 都只能在对应事件真正发生时执行一次,不得因为循环仍在运行而重复执行。

## 四、物品名称转换

从用户消息中提取物品名,按以下翻译表转换为 `vop` 英文类名:

```text
手机→cell phone
包/背包→backpack
杯子→cup
电脑/笔记本→laptop
书→book
遥控器→remote
伞→umbrella
瓶子→bottle
行李箱→suitcase
剪刀→scissors
钟→clock
花瓶→vase
毛绒熊→teddy bear
香蕉→banana
苹果→apple
披萨→pizza
蛋糕→cake
碗→bowl
刀→knife
叉子→fork
勺子→spoon
鼠标→mouse
键盘→keyboard
电视→tv
椅子→chair
沙发→couch
相机→camera
```

```text
IF 物品在翻译表中:
    TARGET = 翻译后的英文类名
ELSE:
    TARGET = 用户说的物品名称
    # 使用 vop 开放词汇检测

ITEM_CN = 用户说的原始物品名
```

## 五、GUARD_FLOW

### STEP 1:检查现有任务

```text
IF 已经存在 guard_status == "running" 的守护任务:
    TEXT_REPLY "当前正在守护" + ITEM_CN + ",请先结束当前守护"
    RETURN
```

禁止同时创建多个守护循环。

### STEP 2:解析守护时间

```text
IF 用户明确指定守护时长:
    DURATION_SECONDS = 将用户指定的时长转换为秒
    DURATION_TEXT = 用户指定的原始时长
ELSE:
    DURATION_SECONDS = 120
    DURATION_TEXT = "2分钟"
```

### STEP 3:初始化任务状态

每次启动新任务时必须重新初始化:

```text
guard_status = "starting"
miss_count = 0
notified_events = EMPTY_SET
start_time = 当前时间
end_time = start_time + DURATION_SECONDS
```

旧任务留下的 `miss_count`、`notified_events`、`end_time` 或状态不得复用。

### STEP 4:启动检测

必须先配置并启动检测,再宣布守护已经开始:

```text
vop.stop()
vop.set_classes([TARGET])
vop.start()

guard_status = "running"
```

如果用户未指定守护时长:

```text
TEXT_REPLY "好的,我帮你守护" + ITEM_CN + ",默认守护2分钟,拿走的话我会报警"

SEND_EVENT_ONCE(
    "guard_started",
    "物品守护已开始:" + ITEM_CN + ",默认守护2分钟。"
)
```

如果用户指定了守护时长:

```text
TEXT_REPLY "好的,我帮你守护" + ITEM_CN + ",持续" + DURATION_TEXT + ",拿走的话我会报警"

SEND_EVENT_ONCE(
    "guard_started",
    "物品守护已开始:" + ITEM_CN + ",守护时长为" + DURATION_TEXT + "。"
)
```

开始通知只发送一次。

### STEP 5:循环巡查

```text
WHILE guard_status == "running":

    IF 当前时间 >= end_time:
        guard_status = "completed"
        BREAK

    SLEEP(不超过5秒)

    # 睡眠后重新检查状态,避免停止后继续检测
    IF guard_status != "running":
        BREAK

    IF 当前时间 >= end_time:
        guard_status = "completed"
        BREAK

    result = vop.read()
    found = TARGET IN result.objects

    IF found:
        miss_count = 0

    ELSE:
        miss_count += 1

        IF miss_count == 1:
            TEXT_REPLY "暂时没看到" + ITEM_CN + ",再确认一次"
            # 此处禁止调用 channel_reply
            # 此处禁止报警

        ELIF miss_count >= 2:
            guard_status = "alarm"
            BREAK
```

循环内禁止调用 `channel_reply`。

普通对话不会修改 `guard_status`、`miss_count` 或 `end_time`。

## 六、ALARM

仅当状态首次从 `running` 变为 `alarm` 时执行:

```text
IF guard_status == "alarm":

    vop.stop()

    tts.speak("警报!" + ITEM_CN + "不见了!")
    speaker.play()
    TEXT_REPLY ITEM_CN + "被拿走了!"

    SEND_EVENT_ONCE(
        "item_missing",
        "警报!" + ITEM_CN + "不见了,疑似被拿走,请立即查看。"
    )

    guard_status = "finished"
    RETURN
```

报警通知只能发送一次。

进入 `finished` 后不得重新报警,不得继续巡查,不得发送完成通知。

## 七、GUARD_COMPLETE

仅当状态首次从 `running` 变为 `completed` 时执行:

```text
IF guard_status == "completed":

    vop.stop()

    tts.speak("已完成" + ITEM_CN + "的守护")
    speaker.play()
    TEXT_REPLY "已完成" + ITEM_CN + "的守护"

    SEND_EVENT_ONCE(
        "guard_completed",
        "物品守护结束:" + ITEM_CN + "已完成指定时长的守护。"
    )

    guard_status = "finished"
    RETURN
```

完成通知只能发送一次。

进入 `finished` 后不得继续巡查,也不得再次发送完成通知。

## 八、STOP_FLOW

停止请求的优先级高于启动请求。

```text
IF guard_status == "running" OR guard_status == "starting":

    # 先改变状态,确保巡查循环立即失效
    guard_status = "stopping"

    vop.stop()

    tts.speak("已结束守护")
    speaker.play()
    TEXT_REPLY "已停止守护"

    SEND_EVENT_ONCE(
        "guard_stopped",
        "物品守护已提前结束:" + ITEM_CN + "。"
    )

    guard_status = "finished"
    RETURN

ELSE:
    TEXT_REPLY "当前没有正在进行的物品守护"
    RETURN
```

没有运行中的守护任务时,禁止调用 `channel_reply`。

提前停止通知只能发送一次。

## 九、终态互斥规则

一次守护任务只能以以下一种方式结束:

```text
item_missing
guard_completed
guard_stopped
```

三个结束事件互斥。

如果已经发生其中一个结束事件:

```text
不得执行另外两个结束流程
不得再次调用 channel_reply
不得继续调用 vop.read
必须保持 guard_status == "finished"
```

## 十、允许的 channel_reply 调用位置汇总

整个脚本只能出现以下四种远程消息:

```text
开始:
"物品守护已开始:{物品名},守护时长为{时长}。"

物品消失:
"警报!{物品名}不见了,疑似被拿走,请立即查看。"

正常结束:
"物品守护结束:{物品名}已完成指定时长的守护。"

提前结束:
"物品守护已提前结束:{物品名}。"
```

除此之外,任何分支、循环、普通对话或重复状态都禁止调用 `channel_reply`。

# ── 结束。无其他步骤。──