<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Python on Bruce's 博客</title><link>https://www.huangqixuan.com/tags/python/</link><description>Recent content in Python on Bruce's 博客</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Tue, 08 Sep 2026 00:00:00 +0800</lastBuildDate><atom:link href="https://www.huangqixuan.com/tags/python/index.xml" rel="self" type="application/rss+xml"/><item><title>让 Codex 用灯光叫我回来：CodexLightHub 的 ROG 与 Yeelight 实机记录</title><link>https://www.huangqixuan.com/p/codexlighthub-windows-rgb/</link><pubDate>Tue, 08 Sep 2026 00:00:00 +0800</pubDate><guid>https://www.huangqixuan.com/p/codexlighthub-windows-rgb/</guid><description>&lt;img src="https://www.huangqixuan.com/site-images/codexlighthub/cover_hu_a0f28dc5a066aea9.webp" alt="Featured image of post 让 Codex 用灯光叫我回来：CodexLightHub 的 ROG 与 Yeelight 实机记录" /&gt;&lt;p&gt;Codex 在后台跑任务时，我不想一直盯着窗口。更需要提醒我的时刻，是它已经停下来，等我回答一个问题。既然桌上已经有 RGB 键盘和挂灯，能不能让这些灯直接表示任务状态？&lt;/p&gt;&#10;&lt;p&gt;这个想法来自 Codex Micro 的状态指示灯。它用颜色告诉我 Codex 正在工作、等待输入还是已经完成，我也想让整张桌面有同样直观的反馈。最后做出来的 CodexLightHub，是一个运行在 Windows 上的 Python 小程序。它接收 Codex 的生命周期事件，再把状态发给 ROG 笔记本灯光和 Yeelight 挂灯的后方氛围灯。&lt;/p&gt;&#10;&lt;p&gt;这篇记录整理到 &lt;code&gt;1.0.6&lt;/code&gt;。ASUS 和 Yeelight 两条链路已经接通，EZ80 仍停在只读探测阶段。本文中的灯光照片均来自实际运行效果，连接图只用于解释程序结构。&lt;/p&gt;&#10;&lt;h2 id="先确定灯光应该告诉我什么"&gt;&lt;a href="#%e5%85%88%e7%a1%ae%e5%ae%9a%e7%81%af%e5%85%89%e5%ba%94%e8%af%a5%e5%91%8a%e8%af%89%e6%88%91%e4%bb%80%e4%b9%88" class="header-anchor"&gt;&lt;/a&gt;先确定灯光应该告诉我什么&#10;&lt;/h2&gt;&lt;p&gt;最早的设想很直接：工作时蓝色，需要我时橙色，完成时绿色。真正用起来以后，才发现颜色背后的判断比变色本身更难。&lt;/p&gt;&#10;&lt;p&gt;例如，Codex 发起权限检查时，可能由自动审核处理，根本没有弹窗让我操作。如果每次都变橙色，我就会不断被叫回来，最后开始忽略它。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;1.0.6&lt;/code&gt; 把规则收紧到了下面这样：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;状态&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;当前行为&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;工作中&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;满亮蓝色；ROG 使用硬件呼吸形成动态起伏，Yeelight 保持静态蓝色&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;真实询问&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;&lt;code&gt;request_user_input&lt;/code&gt; 调用前变成满亮橙色，回答后恢复蓝色&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;自动审核或后台权限检查&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;保持蓝色，不触发橙色提醒&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;本轮完成&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;满亮绿色保持 180 秒，再恢复日常彩色灯效&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;收到中断事件&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;满亮红色短暂提示，默认保持 4 秒&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;空闲&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;ASUS 恢复 G-Helper 保存的灯效；Yeelight 按配置恢复彩虹&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;div class="article-photo-grid"&gt;&lt;figure&gt;&#10; &lt;img src="https://www.huangqixuan.com/img/codexlighthub/working-blue.webp" alt="蓝色：Codex 正在工作" loading="lazy" decoding="async"&gt;&#10; &lt;figcaption&gt;蓝色：Codex 正在工作&lt;/figcaption&gt;&#10; &lt;/figure&gt;&lt;figure&gt;&#10; &lt;img src="https://www.huangqixuan.com/img/codexlighthub/waiting-orange.webp" alt="橙色：等待我回答问题" loading="lazy" decoding="async"&gt;&#10; &lt;figcaption&gt;橙色：等待我回答问题&lt;/figcaption&gt;&#10; &lt;/figure&gt;&lt;figure&gt;&#10; &lt;img src="https://www.huangqixuan.com/img/codexlighthub/completed-green.webp" alt="绿色：这一轮已经完成" loading="lazy" decoding="async"&gt;&#10; &lt;figcaption&gt;绿色：这一轮已经完成&lt;/figcaption&gt;&#10; &lt;/figure&gt;&lt;figure&gt;&#10; &lt;img src="https://www.huangqixuan.com/img/codexlighthub/idle-rainbow.webp" alt="彩色：恢复平时的桌面灯效" loading="lazy" decoding="async"&gt;&#10; &lt;figcaption&gt;彩色：恢复平时的桌面灯效&lt;/figcaption&gt;&#10; &lt;/figure&gt;&lt;/div&gt;&#10;&#10;&lt;p&gt;这里的“完成”指当前一轮结束，不代表整个项目已经做完。红色也不能覆盖所有错误：当前安装器没有注册通用错误事件，Hub 只是保留了 &lt;code&gt;Interrupt&lt;/code&gt; 的处理入口。&lt;/p&gt;&#10;&lt;p&gt;还有一个限制要单独说清楚。项目默认启用了 &lt;code&gt;plan_stop_is_waiting&lt;/code&gt;，当收到带有 &lt;code&gt;permission_mode=plan&lt;/code&gt; 的 &lt;code&gt;Stop&lt;/code&gt; 时，会保守地显示等待状态。它是为部分计划确认界面补的启发式判断，不能证明屏幕上一定有弹窗。普通询问使用的是实际工具事件，这两条路径不能混为一谈。&lt;/p&gt;&#10;&lt;h2 id="一条很短的事件链"&gt;&lt;a href="#%e4%b8%80%e6%9d%a1%e5%be%88%e7%9f%ad%e7%9a%84%e4%ba%8b%e4%bb%b6%e9%93%be" class="header-anchor"&gt;&lt;/a&gt;一条很短的事件链&#10;&lt;/h2&gt;&lt;p&gt;程序分成三层：Hook 接事件，Hub 判断状态，Adapter 控灯。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="CodexLightHub 的事件、状态机和双设备输出示意" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.huangqixuan.com/site-images/codexlighthub/cover.svg"&gt;&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Codex lifecycle hooks&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;codex-light-hook.cmd → hook.py&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; │ UDP 127.0.0.1:17871&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ▼&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Hub：按会话保存状态、去重、决定当前灯色&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ├── ASUS HID → ROG 键盘与机身灯光&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; └── 本地 MIoT → Yeelight 后方氛围灯&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;hook.py&lt;/code&gt; 只挑出事件名、会话、轮次、工具名等少量字段，发送到本机回环地址后退出。提示词、工具参数、工具输出、回复正文和工作目录都不在转发白名单里。灯光程序也不输出允许或拒绝权限的决定。&lt;/p&gt;&#10;&lt;p&gt;硬件写入在 Hub 的工作线程里执行。挂灯连接慢了，或某个设备不可用，不应该让 Codex 的 Hook 一直等着。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Codex Desktop、ROG 键盘和 Yeelight 挂灯联动的桌面实拍" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1350" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.huangqixuan.com/site-images/codexlighthub/desktop-overview_hu_4bafa2bc26838238.webp" srcset="https://www.huangqixuan.com/site-images/codexlighthub/desktop-overview_hu_b720b52f4ea1c3c8.webp 800w, https://www.huangqixuan.com/site-images/codexlighthub/desktop-overview_hu_bc99cec487176054.webp 1600w, https://www.huangqixuan.com/site-images/codexlighthub/desktop-overview_hu_4bafa2bc26838238.webp 1800w" width="1800"&gt;&lt;/p&gt;&#10;&lt;p&gt;同一时间开多个任务时，Hub 按下面的顺序选择灯色：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;waiting &amp;gt; running &amp;gt; interrupted &amp;gt; completed &amp;gt; idle&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;因此，一个任务完成不会用绿色盖住另一个任务的橙色询问；只要还有任务在运行，整体也会优先显示蓝色。这意味着绿色的 3 分钟计时到了，不一定马上看到彩虹，还要看其他会话是否仍然活跃。&lt;/p&gt;&#10;&lt;h2 id="rog从没有设备的-rest-接口走到-asus-hid"&gt;&lt;a href="#rog%e4%bb%8e%e6%b2%a1%e6%9c%89%e8%ae%be%e5%a4%87%e7%9a%84-rest-%e6%8e%a5%e5%8f%a3%e8%b5%b0%e5%88%b0-asus-hid" class="header-anchor"&gt;&lt;/a&gt;ROG：从没有设备的 REST 接口，走到 ASUS HID&#10;&lt;/h2&gt;&lt;p&gt;这次使用的笔记本是 ROG Strix G16 G615LR，灯光由 G-Helper 0.279.0 管理。&lt;/p&gt;&#10;&lt;p&gt;最初的 Aura REST 探测没有枚举到设备，返回值是 &lt;code&gt;5&lt;/code&gt;。我们随后试过 Windows Dynamic Lighting，又遇到了 PyWinRT 枚举接口的参数问题。但确认平时由 G-Helper 控灯后，主线就转向了它使用的 ASUS HID 通道。&lt;/p&gt;&#10;&lt;p&gt;&lt;a class="link" href="https://github.com/seerge/g-helper" target="_blank" rel="noopener"&#10; &gt;G-Helper 的公开源码&lt;/a&gt;提供了实际设备控制实现。项目据此整理协议，再结合本机 G-Helper 日志确认目标设备，而不是只看到 ASUS 的厂商编号就发送数据。&lt;/p&gt;&#10;&lt;p&gt;本机核对到的参数是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;VID: 0B05&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;PID: 19B6&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Aura collection: col04&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Report length: 64 bytes&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;桥接层会同时检查 PID 白名单、配置中的允许列表、日志里的完整 HID 路径、报告长度和 Aura Probe 结果。检查不通过时，拒绝写入。&lt;/p&gt;&#10;&lt;p&gt;灯效写入沿用了三段报告的顺序：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5D-B3-00-{mode}-{R}-{G}-{B}-{speed}-...&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5D-B5-00-00-00&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;5D-B4&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;上面是协议结构说明，不是可以直接复制发送的完整数据包。它也不代表所有 ASUS 设备都适用。当前配置默认只允许这次验证过的 &lt;code&gt;19B6&lt;/code&gt;，换型号后应重新探测。&lt;/p&gt;&#10;&lt;p&gt;&lt;code&gt;GHelperAuraBridge.py&lt;/code&gt; 提供 &lt;code&gt;blue&lt;/code&gt;、&lt;code&gt;waiting&lt;/code&gt;、&lt;code&gt;complete&lt;/code&gt;、&lt;code&gt;error&lt;/code&gt; 和 &lt;code&gt;restore&lt;/code&gt; 命令。ASUS 的运行、等待和错误效果使用硬件呼吸模式，不需要 Python 持续计算每一帧亮度。四种任务状态都按 100% 亮度发送。&lt;/p&gt;&#10;&lt;p&gt;恢复灯效时，程序读取 G-Helper 保存的 &lt;code&gt;aura_mode&lt;/code&gt;、&lt;code&gt;aura_color&lt;/code&gt; 和 &lt;code&gt;aura_speed&lt;/code&gt;，再发送对应模式。它不会修改 G-Helper 的配置。这恢复的是保存的日常设置，并不是对接管前任意瞬时灯光状态的完整快照。&lt;/p&gt;&#10;&lt;h2 id="yeelight55443-不通仍然可以走本地-miot"&gt;&lt;a href="#yeelight55443-%e4%b8%8d%e9%80%9a%e4%bb%8d%e7%84%b6%e5%8f%af%e4%bb%a5%e8%b5%b0%e6%9c%ac%e5%9c%b0-miot" class="header-anchor"&gt;&lt;/a&gt;Yeelight：55443 不通，仍然可以走本地 MIoT&#10;&lt;/h2&gt;&lt;p&gt;挂灯是 Yeelight 显示器挂灯 2 Pro，设备型号为 &lt;code&gt;yeelink.light.lamp42&lt;/code&gt;。这里控制的是背后的氛围灯。&lt;/p&gt;&#10;&lt;p&gt;最容易绕进去的地方，是把“Yeelight 设备”与“开放传统 Yeelight LAN Control”画上等号。本机测试中，传统局域网控制端口 &lt;code&gt;55443&lt;/code&gt; 没有开放。这只能说明那条路径没有跑通，不能据此判定设备没有其他本地接口。&lt;/p&gt;&#10;&lt;p&gt;另一个障碍是登录。早期 &lt;code&gt;python-miio/micloud&lt;/code&gt; 的密码登录在这次环境中失败，后面改用了 &lt;a class="link" href="https://pypi.org/project/mihome-ctl/" target="_blank" rel="noopener"&#10; &gt;mihome-ctl&lt;/a&gt; 的米家扫码登录，取得设备的本地 IP 和 Token。这个工具用于完成设备信息获取；日常灯色切换由 CodexLightHub 的本地 MIoT 后端处理。&lt;/p&gt;&#10;&lt;p&gt;所以最终链路是：扫码取得凭据，然后通过本地 MIoT 控灯。它不需要每变一次颜色就重新扫码，也没有把米家账号密码写进 Hub。&lt;/p&gt;&#10;&lt;p&gt;在这盏灯上，氛围灯属性已经按下面的映射完成实机验证：&lt;/p&gt;&#10;&lt;table&gt;&#10;&#9;&lt;thead&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;属性&lt;/th&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;th&gt;SIID / PIID&lt;/th&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/thead&gt;&#10;&#9;&lt;tbody&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;开关&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3 / 1&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;亮度&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3 / 2&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;RGB 颜色&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3 / 3&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&#9;&#9;&lt;tr&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;模式&lt;/td&gt;&#10;&#9;&#9;&#9;&#9;&#9;&lt;td&gt;3 / 4&lt;/td&gt;&#10;&#9;&#9;&#9;&lt;/tr&gt;&#10;&#9;&lt;/tbody&gt;&#10;&lt;/table&gt;&#10;&lt;p&gt;颜色按 RGB 转成十进制值：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;正常变色时，后端依次写入静态模式、颜色、亮度和开关。恢复日常灯效时则把模式放到最后写，因为写颜色可能让设备回到静态模式。此次验证中，最后写入 &lt;code&gt;mode=1&lt;/code&gt; 可以恢复彩虹。&lt;/p&gt;&#10;&lt;p&gt;这里还有一个设备差异：ASUS 的蓝色运行和橙色等待灯效使用硬件呼吸，当前 Yeelight 后端则显示对应颜色的满亮静态灯效。两者表示同一个状态，动画并不完全一致。&lt;/p&gt;&#10;&lt;p&gt;&lt;img alt="Codex 完成后，Yeelight 挂灯显示绿色状态" class="gallery-image" data-flex-basis="320px" data-flex-grow="133" height="1350" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://www.huangqixuan.com/site-images/codexlighthub/yeelight-completed_hu_54f0cb2063c59573.webp" srcset="https://www.huangqixuan.com/site-images/codexlighthub/yeelight-completed_hu_d3664758feb739e.webp 800w, https://www.huangqixuan.com/site-images/codexlighthub/yeelight-completed_hu_5904de5a83dce505.webp 1600w, https://www.huangqixuan.com/site-images/codexlighthub/yeelight-completed_hu_54f0cb2063c59573.webp 1800w" width="1800"&gt;&lt;/p&gt;&#10;&lt;p&gt;Token 是设备控制密钥，只放在本地配置。文章没有附设备地址、Token、登录二维码或账号信息；如果分享工程，应使用 &lt;code&gt;config.example.json&lt;/code&gt;，不能打包自己的运行配置。&lt;/p&gt;&#10;&lt;h2 id="真正费时间的是状态细节"&gt;&lt;a href="#%e7%9c%9f%e6%ad%a3%e8%b4%b9%e6%97%b6%e9%97%b4%e7%9a%84%e6%98%af%e7%8a%b6%e6%80%81%e7%bb%86%e8%8a%82" class="header-anchor"&gt;&lt;/a&gt;真正费时间的是状态细节&#10;&lt;/h2&gt;&lt;h3 id="hook-显示完成不等于灯光脚本执行了"&gt;&lt;a href="#hook-%e6%98%be%e7%a4%ba%e5%ae%8c%e6%88%90%e4%b8%8d%e7%ad%89%e4%ba%8e%e7%81%af%e5%85%89%e8%84%9a%e6%9c%ac%e6%89%a7%e8%a1%8c%e4%ba%86" class="header-anchor"&gt;&lt;/a&gt;Hook 显示完成，不等于灯光脚本执行了&#10;&lt;/h3&gt;&lt;p&gt;Windows 包装命令曾是一个排查点。项目最后用 &lt;code&gt;.cmd&lt;/code&gt; 包装器承接 Python 调用，避免在 Hook 字符串里反复嵌套引号。&lt;/p&gt;&#10;&lt;p&gt;安装器会备份并合并已有的 &lt;code&gt;hooks.json&lt;/code&gt;，保留不属于本项目的处理器。最终版本还移除了本项目之前注册的 &lt;code&gt;PermissionRequest&lt;/code&gt; 处理器，让自动审核不再触发橙色。&lt;/p&gt;&#10;&lt;p&gt;这套安装方式是在本机路径和 Codex 版本下跑通的。包装命令依赖路径格式，迁移到包含空格的用户目录时仍应检查，不能把一次成功当成所有 Windows 环境的保证。&lt;/p&gt;&#10;&lt;h3 id="已完成和我已经看过不是一回事"&gt;&lt;a href="#%e5%b7%b2%e5%ae%8c%e6%88%90%e5%92%8c%e6%88%91%e5%b7%b2%e7%bb%8f%e7%9c%8b%e8%bf%87%e4%b8%8d%e6%98%af%e4%b8%80%e5%9b%9e%e4%ba%8b" class="header-anchor"&gt;&lt;/a&gt;“已完成”和“我已经看过”不是一回事&#10;&lt;/h3&gt;&lt;p&gt;开发中一度参考 Codex Micro 的“完成且未读”思路，让绿色一直保持到下一次交互。用了一下，我又把需求改成了“过几分钟切回彩色”。&lt;/p&gt;&#10;&lt;p&gt;最后的配置是：&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-json" data-lang="json"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;completed_hold_seconds&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;180&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;#34;sticky_completed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;新提示提交后立即回到蓝色，不必等计时结束。Hub 虽然保留了 &lt;code&gt;MarkRead&lt;/code&gt; 和 &lt;code&gt;Read&lt;/code&gt; 入口，但当前接入没有收到“用户已阅读回复”的事件，不能根据绿色是否消失判断我有没有看过结果。&lt;/p&gt;&#10;&lt;h3 id="橙色必须值得我回来"&gt;&lt;a href="#%e6%a9%99%e8%89%b2%e5%bf%85%e9%a1%bb%e5%80%bc%e5%be%97%e6%88%91%e5%9b%9e%e6%9d%a5" class="header-anchor"&gt;&lt;/a&gt;橙色必须值得我回来&#10;&lt;/h3&gt;&lt;p&gt;最后一次调整是把手工变橙色测试改成真正的询问弹窗测试。&lt;/p&gt;&#10;&lt;p&gt;先手工写入橙色，只能证明设备能接收颜色。真正调用 &lt;code&gt;request_user_input&lt;/code&gt;、出现问题、回答后恢复蓝色，才能检查从 Codex 到设备的整条链路。开发记录里最终确认了“弹窗且橙色”，随后完成 &lt;code&gt;1.0.6&lt;/code&gt;。&lt;/p&gt;&#10;&lt;p&gt;Hub 还处理了一个并行工具细节：已经在等我回答时，另一个工具先结束，不应把等待状态提前冲掉。只有匹配的询问结束，才应该回到运行状态。&lt;/p&gt;&#10;&lt;h2 id="目前完成到哪里"&gt;&lt;a href="#%e7%9b%ae%e5%89%8d%e5%ae%8c%e6%88%90%e5%88%b0%e5%93%aa%e9%87%8c" class="header-anchor"&gt;&lt;/a&gt;目前完成到哪里&#10;&lt;/h2&gt;&lt;p&gt;截至这次记录，已经完成 ASUS HID 写入、Yeelight 本地 MIoT 写入、双设备接入同一状态机、真实询问提醒，以及完成 3 分钟后的彩色恢复。最终开发记录报告 11 项自动测试通过，代码中的测试覆盖了状态变化、HID 构造与保护条件、MIoT 属性写入等部分。自动测试与实机变色是两类证据，不能互相替代。&lt;/p&gt;&#10;&lt;p&gt;EZ80 暂时只有只读 HID 探测器，没有写入灯光协议。当前项目也没有实现逐键显示多个任务、按某个键跳回会话，或者识别所有客户端弹窗。这些早期讨论过的想法，没有被写成已经完成的功能。&lt;/p&gt;&#10;&lt;p&gt;工程仍是围绕这台 G615LR 和这盏 lamp42 做的个人工具。设备断开、网络超时、G-Helper 与其他灯光控制器竞争，以及不同 Codex 版本的事件差异，都是后续使用时需要观察的地方。&lt;/p&gt;&#10;&lt;p&gt;对我来说，最有用的结果是：起伏的蓝色让我知道它还在工作，橙色提示有问题要回答，绿色短暂保留完成状态，然后桌面回到原来的彩色。这个小工具的价值，取决于这些提醒能不能对应真实情况。&lt;/p&gt;&#10;</description></item></channel></rss>