v1.5.1
v1.5.1
针对 v1.5.0 多灯架构上线后用户反馈的两类问题做了集中修复:一是弹窗(Flyout)首次打开/刷新时的延迟和状态不一致,二是**电脑从休眠/显示器息屏恢复后状态一直"离线"**的致命 Bug。
整体效果:恢复后不手动操作任何按钮,10 秒内托盘图标和弹窗会自动回落到真实的亮度/色温/开关状态。
🐛 关键修复 · 休眠恢复永不离线
电源事件监听器从不关闭(#Critical)
v1.5.0 中 MonitorSleepListener 只有在至少勾选了一项「显示器息屏关灯 / 系统休眠关灯 / 唤醒开灯」时才会启动;如果用户三个复选框都没勾(最常见),系统唤醒广播 PBT_APMRESUMEAUTOMATIC 根本不会被接收 → 恢复后 UDP 会话已过期、缓存里全是超时的"离线"、只能手动点弹窗触发 refresh → 表现为一直显示离线。
v1.5.1 无论勾选与否,都始终启动并常驻监听窗口。各回调内部再根据复选框决定是否发"开关灯"指令,但 refresh() 一定会执行。
恢复后多轮补刀刷新(覆盖 WiFi/Docking 网卡延迟就绪)
系统唤醒那一刻:
- t + 0s:立即对所有设备发
refresh(),勾选了「唤醒开灯」的设备优先set_power(True) - t + 3s:第一轮补刀。WiFi 连接和扩展坞网卡平均需要 1~3 秒恢复 DHCP/链路,第一轮 refresh 通常全部超时"不可达"
- t + 8s:第二轮补刀。覆盖极慢的企业级 Wi-Fi / 需重新认证的热点 / USB 网卡
补刀轮只做 refresh() 不重发 power-on,避免中途用户手动关灯后被程序强制开回去。
显示器点亮 → 刷新全部设备(不再跳过未托管设备)
_on_monitor_wake 之前只对勾选了「显示器息屏关灯」的设备恢复供电;如果用户没勾这一项,长达几小时息屏后 UDP 会话已经失效,直到下次手动点弹窗之前,灯的滑杆一直显示陈旧的亮度/色温。
v1.5.1:显示器从 off → on 的一次广播会对所有设备并行 refresh。未托管的设备走 refresh,托管的设备按休眠前状态还原供电。
显示器息屏时也会完整记录每台设备的 pre-sleep 状态,不再只记录勾选了 sleep-shutdown 的设备。
✨ Flyout / 托盘图标体验大幅优化
打开弹窗秒显最后已知值
以前点击托盘图标后,弹窗会启动一个串行 _bg_refresh_all 线程逐个 refresh()。某台设备离线 → 2 秒 UDP 超时 → 下一台……整个弹窗卡死几秒。
现在打开弹窗:
- 先同步把缓存状态全部应用到 UI — 滑块位置、开关状态、文本立刻显示上次的值
- 再为每台设备单独起线程并行 refresh — 一台慢不阻塞其余
- 每台设备拿到真实状态后通过
root.after(0, …)回写
滑块初始值使用缓存不再硬编码
之前弹窗里的亮度滑块总是从 50 开始,色温从 4000 开始。打开后即使灯是 80% 亮度,滑块先跳到 50 再跳到 80,造成肉眼可见的抖动。
现在两个滑块都以 light.state.brightness / light.state.color_temp 为初始值并裁剪到合法范围内,打开即正确。后台 refresh 只会微调偏差,不会跳变。
离线时显示"最后已知状态 + (离线)"
之前设备不可达 → 状态标签直接显示「离线 — xxx error」或「离线」,用户不知道灯到底是开还是关,也没法判断是否需要重新点开关。
现在状态文案:
- 可达 →
已开灯/已关灯 - 离线 & 有错误信息 →
已开灯 (离线)/已关灯 (离线) - 离线但没加载过错误 → 仍显示
已开灯/已关灯(缓存值)
用户一眼看到"灯上次记录是开的,现在离线",决策清晰。
底部 ⏻ 按钮:从"只能全关"升级为"智能总开关"
- 任何一台灯为开 → 按钮高亮为亮色,点击全部关掉
- 所有灯为关 → 按钮为暗色,点击全部打开
- 不再跳过
reachable=False的设备 — 之前如果唤醒后还没刷新到设备 cached 为 unreachable,会被静默跳过导致"按了没反应" - 每次
apply_state后自动重算按钮颜色,与状态同步
托盘图标启动时不误导
启动瞬间图标默认设为"暗色(关)",等第一次状态回调后再翻转成真实的亮/暗。v1.5.0 启动后会先显示 2~3 秒"亮图标"然后闪一下变暗,给用户"灯被程序开了"的错觉。
✨ 设备名显示不再乱截断
阈值从 12 字符放宽到 34 字符,取消 Label(width=13) 固定列宽限制。
像 Mijia Computer Monitor Light Bar 2 这种 31 字符的官方英文名现在可以完整显示。超过 34 字符才会截断为 前 32 字符 + …。
✨ 启动即并行刷新全部设备
旧逻辑:启动后只对 "缺 model / device_id == 0" 的设备 refresh,其余设备的状态全是「默认离线」。即使灯一直开着,托盘图标也是暗的,直到用户手动点弹窗。
新逻辑:启动时为所有完整配置的设备并行起线程 refresh(开机自动开灯的设备在那条流程里已经 refresh 了,不重复做)。托盘图标在启动几秒后就能落到真实的"至少有一台开着 / 全部关着"聚合态。
🧹 其他
power-on-on-system-resume/power-off-on-monitor-sleep等复选框切换时_restart_power_listener与初始化保持一致(不再按旧的 need_listener 短路)- 日志:
Monitor wake event/System resume event/Resume refresh round: t+Xs都有 INFO/DEBUG 输出,便于用户排查"恢复后到底有没有刷新"
⚠️ 注意事项
- v1.5.1 的电源策略复选框仍是 v1.5.0 的语义 — 只决定"是否主动开关灯";刷新行为是常驻的、不需要配置
- 桌面小部件仍是单设备模式(配置列表第一台),多设备场景请仍使用托盘弹窗或快捷键
- 三轮补刀刷新期间会产生 ~3× 的 UDP 广播(
python-miiodiscovery),对家用路由无压力,但企业网络若有严格 ACL 请留意