系列-脚本

自定义的显示器休眠模式

去年购买了新的 Mac mini 和 红米 G Pro 27U 显示器。

这款显示器还算不错,2000 元的价格在各方面都表现良好,对我来说有两个小不足:

  1. 唤醒有点慢,通过键盘唤醒约需 5 s
  2. 休眠以后无法使用“小爱同学”语音指令

研究了一下显示器的设置,没有保持待机不休眠的地方,只能自己动手了。

基本思路:这是一款 miniLED 显示器,在 Mac 系统开启 HDR 模式时,可以通过 Mac 系统调节显示器亮度(SDR 模式不可,只能通过显示器自身调整亮度)。miniLED 的分区控光特性决定了当亮度设置为 0 时,整块面板都不发光。
那么我需要做的就是在我不使用电脑时,把亮度设置为 0。如此的话显示器面板关闭(节能),但是系统还在运行,可以随时响应小爱同学指令。

前提条件

  1. miniLED 显示器,且已在 Mac OS - 设置 - 显示 - HDR 开启
  2. One Switch - Keep Awake
  3. Hammerspoon 软件

实现

1. 安装 Hammerspoon

  1. 官网下载安装 Hammerspoon
  2. 打开后,在菜单栏点 Hammerspoon → Open Config
  3. 会打开 ~/.hammerspoon/init.lua

也可以直接用 VS Code 等编辑器打开 ~/.hammerspoon/init.lua

2. 配置 init.lua

把下面的代码贴进 init.lua

init.lua
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
-- 屏保渐暗模式:进入屏保后 delayBeforeDim 分钟开始降亮度,dimDuration 降到 0
-- 退出屏保(比如按回车唤醒)后恢复原亮度

local brightness = require("hs.brightness")
local caffeinate = require("hs.caffeinate")
local timer = require("hs.timer")

-- 配置参数
local delayBeforeDim = 1 * 60 -- 进入屏保后等待 1 分钟再开始降亮度(秒)
local dimDuration = 5 -- 从当前亮度降到 0 的总时长(秒)
local steps = 2 -- 分多少步降完(越大越平滑)
local originalBrightness = nil
local dimTimer = nil
local delayTimer = nil

-- 停止所有计时器并恢复亮度
local function restoreBrightness()
if delayTimer then
delayTimer:stop()
delayTimer = nil
end
if dimTimer then
dimTimer:stop()
dimTimer = nil
end
if originalBrightness then
brightness.set(originalBrightness)
originalBrightness = nil
end
end

-- 开始渐暗
local function startDimming()
-- 如果已经在渐暗,就不重复
if dimTimer ~= nil then return end

originalBrightness = brightness.get()
if not originalBrightness or originalBrightness <= 0 then
return
end

local currentStep = 0
local stepInterval = dimDuration / steps
local stepDelta = originalBrightness / steps

dimTimer = timer.doEvery(stepInterval, function()
currentStep = currentStep + 1
local newValue = originalBrightness - stepDelta * currentStep
if newValue < 0 then newValue = 0 end
brightness.set(math.floor(newValue + 0.5))

if currentStep >= steps then
dimTimer:stop()
dimTimer = nil
end
end)
end

-- 进入屏保时:先等 delayBeforeDim 分钟,再开始渐暗
local function onScreensaverStart()
-- 防止重复
restoreBrightness()

delayTimer = timer.doAfter(delayBeforeDim, function()
startDimming()
end)
end

-- 退出屏保时:立刻恢复亮度
local function onScreensaverStop()
restoreBrightness()
end

local watcher = caffeinate.watcher.new(function(event)
if event == caffeinate.watcher.screensaverDidStart then
-- 进入屏保
onScreensaverStart()

elseif event == caffeinate.watcher.screensaverDidStop then
-- 退出屏保(一般是你按键/移动鼠标触发)
onScreensaverStop()

elseif event == caffeinate.watcher.screensDidLock then
-- 屏幕被锁定(手动锁屏或自动锁屏)
onScreensaverStart()

elseif event == caffeinate.watcher.screensDidUnlock then
-- 解锁成功(输入密码/Touch ID 后)
onScreensaverStop()

elseif event == caffeinate.watcher.systemDidWake then
-- 机器从睡眠中唤醒
restoreBrightness()

elseif event == caffeinate.watcher.screensDidWake then
-- 屏幕从睡眠中唤醒
restoreBrightness()
end
end)

watcher:start()

保存。

3. Reload Config

在菜单栏点 Hammerspoon → Reload Config。

设置完成,可以按 Control + Command + Q 进入锁屏测试效果。

结论

通过这个自定义脚本实现了我想要的显示器休眠模式。

不足:

  1. 在 Mac OS 登录界面无法监听事件进行恢复亮度,可以手动按键盘上的亮度控制按钮临时控制亮度
  2. 对比进入真休眠,会更耗电些(没有进行测试,大抵是不高的)

优点:

  1. 不用唤醒,也不用担心烧屏之类的问题
  2. 小爱同学随时待命(昨晚半夜喊小爱给我开空调)