Skip to content

Commit 10ea25c

Browse files
committed
fix(hammerspoon): 唤醒后恢复主动关闭的蓝牙
1 parent 208d20a commit 10ea25c

3 files changed

Lines changed: 105 additions & 9 deletions

File tree

‎macos/hammerspoon/plugins/power-lid-sleep/active_sleep.zsh‎

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,15 @@ set -u
1010
LOG_FILE="$HOME/.hammerspoon/logs/power-lid-sleep.log"
1111
MODE="sleep"
1212
RESULT_FILE="$HOME/.hammerspoon/logs/power-lid-sleep.result"
13+
RESTORE_MARKER_FILE="$HOME/.hammerspoon/logs/power-lid-sleep.restore-bluetooth"
1314
PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin"
1415

1516
if [ "${1:-}" = "--check-bluetooth-permission" ]; then
1617
MODE="check-bluetooth-permission"
1718
RESULT_FILE="${2:-$RESULT_FILE}"
19+
elif [ "${1:-}" = "--restore-bluetooth" ]; then
20+
MODE="restore-bluetooth"
21+
RESTORE_MARKER_FILE="${2:-$RESTORE_MARKER_FILE}"
1822
else
1923
RESULT_FILE="${1:-$RESULT_FILE}"
2024
fi
@@ -110,6 +114,73 @@ check_bluetooth_permission() {
110114
return "$rc"
111115
}
112116

117+
# 读取蓝牙电源状态。
118+
# 入参:$1 blueutil 可执行文件路径。
119+
# 返回值:成功时输出 0 或 1,并返回 0;失败返回非 0。
120+
read_bluetooth_power() {
121+
local blueutil_path="$1"
122+
local power
123+
power="$("$blueutil_path" --power 2>/tmp/power-lid-sleep-blueutil.err)"
124+
local rc=$?
125+
if [ "$rc" -ne 0 ]; then
126+
local stderr
127+
stderr="$(tr '\n' ' ' </tmp/power-lid-sleep-blueutil.err 2>/dev/null || true)"
128+
rm -f /tmp/power-lid-sleep-blueutil.err
129+
log_info "蓝牙状态读取失败: rc=$rc stderr=$stderr"
130+
return "$rc"
131+
fi
132+
133+
rm -f /tmp/power-lid-sleep-blueutil.err
134+
power="${power//[[:space:]]/}"
135+
if [ "$power" = "0" ] || [ "$power" = "1" ]; then
136+
echo "$power"
137+
return 0
138+
fi
139+
140+
log_info "蓝牙状态读取结果无法解析: power=$power"
141+
return 1
142+
}
143+
144+
# 标记唤醒后需要恢复蓝牙。
145+
# 入参:$1 关闭前蓝牙状态。
146+
# 返回值:无。
147+
mark_bluetooth_restore() {
148+
local original_power="$1"
149+
mkdir -p "$(dirname "$RESTORE_MARKER_FILE")"
150+
{
151+
printf 'original_power=%s\n' "$original_power"
152+
printf 'created_at=%s\n' "$(date '+%Y-%m-%d %H:%M:%S')"
153+
} > "$RESTORE_MARKER_FILE"
154+
}
155+
156+
# 恢复蓝牙并清理恢复标记。
157+
# 入参:无。
158+
# 返回值:0 表示已恢复,非 0 表示失败。
159+
restore_bluetooth() {
160+
local blueutil_path
161+
blueutil_path="$(command -v blueutil 2>/dev/null || true)"
162+
if [ -z "$blueutil_path" ]; then
163+
log_info "蓝牙恢复失败: 未检测到 blueutil"
164+
return 1
165+
fi
166+
167+
"$blueutil_path" --power on >/tmp/power-lid-sleep-blueutil.out 2>/tmp/power-lid-sleep-blueutil.err
168+
local rc=$?
169+
local stdout stderr
170+
stdout="$(tr '\n' ' ' </tmp/power-lid-sleep-blueutil.out 2>/dev/null || true)"
171+
stderr="$(tr '\n' ' ' </tmp/power-lid-sleep-blueutil.err 2>/dev/null || true)"
172+
rm -f /tmp/power-lid-sleep-blueutil.out /tmp/power-lid-sleep-blueutil.err
173+
174+
if [ "$rc" -eq 0 ]; then
175+
rm -f "$RESTORE_MARKER_FILE"
176+
log_info "蓝牙恢复完成: stdout=$stdout stderr=$stderr"
177+
return 0
178+
fi
179+
180+
log_info "蓝牙恢复失败: rc=$rc stdout=$stdout stderr=$stderr"
181+
return "$rc"
182+
}
183+
113184
# 关闭蓝牙。
114185
# 入参:无。
115186
# 返回值:0 表示成功或跳过,非 0 表示失败;蓝牙失败会阻止主动睡眠。
@@ -122,6 +193,9 @@ disable_bluetooth() {
122193
return 0
123194
fi
124195

196+
local original_power
197+
original_power="$(read_bluetooth_power "$blueutil_path" || true)"
198+
125199
"$blueutil_path" --power 0 >/tmp/power-lid-sleep-blueutil.out 2>/tmp/power-lid-sleep-blueutil.err
126200
local rc=$?
127201
local stdout stderr
@@ -131,6 +205,10 @@ disable_bluetooth() {
131205

132206
if [ "$rc" -eq 0 ]; then
133207
log_info "蓝牙关闭完成: stdout=$stdout stderr=$stderr"
208+
if [ "$original_power" = "1" ]; then
209+
mark_bluetooth_restore "$original_power"
210+
log_info "已标记唤醒后恢复蓝牙"
211+
fi
134212
echo "蓝牙:已关闭"
135213
return 0
136214
fi
@@ -158,6 +236,12 @@ if [ "$MODE" = "check-bluetooth-permission" ]; then
158236
exit 0
159237
fi
160238

239+
if [ "$MODE" = "restore-bluetooth" ]; then
240+
log_info "蓝牙恢复执行器启动"
241+
restore_bluetooth
242+
exit $?
243+
fi
244+
161245
log_info "主动睡眠执行器启动"
162246

163247
results=()

‎macos/hammerspoon/plugins/power-lid-sleep/bluetooth_guard.lua‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ local shellPath = [[PATH="/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sb
99
local logger = nil
1010
local diagnosticLogPath = nil
1111
local activeTasks = {}
12+
local blueutilPath
1213

1314
-- 追加蓝牙守卫诊断日志到文件。
1415
-- 入参:level 日志级别;message 日志内容。
@@ -155,7 +156,7 @@ end
155156
-- 查找 blueutil 可执行文件。
156157
-- 入参:无。
157158
-- 返回值:成功时返回可执行文件路径;失败时返回 nil。
158-
local function blueutilPath()
159+
blueutilPath = function()
159160
if cachedBlueutilPath ~= nil then
160161
return cachedBlueutilPath
161162
end

‎macos/hammerspoon/plugins/power-lid-sleep/plugin.lua‎

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ function plugin.start(context)
141141
hs.fs.mkdir(logDir)
142142
end
143143
local diagnosticLogPath = logDir .. "/power-lid-sleep.log"
144+
local bluetoothRestoreMarkerPath = logDir .. "/power-lid-sleep.restore-bluetooth"
144145
if type(bluetoothGuard.setLogger) == "function" then
145146
bluetoothGuard.setLogger(log, diagnosticLogPath)
146147
end
@@ -202,14 +203,24 @@ function plugin.start(context)
202203
return
203204
end
204205

205-
if state.bluetoothWasChanged and state.bluetoothOriginalPower ~= 0 then
206-
if type(bluetoothGuard.powerOnAsync) == "function" and bluetoothGuard.powerOnAsync() then
207-
log.i("已安排后台恢复蓝牙电源")
208-
elseif bluetoothGuard.powerOn() then
209-
log.i("已恢复蓝牙电源")
210-
else
211-
log.w("蓝牙恢复失败,请确认 blueutil 可用")
212-
end
206+
local restoreMarked = hs.fs.pathToAbsolute(bluetoothRestoreMarkerPath) ~= nil
207+
if restoreMarked then
208+
appendDiagnosticLog(diagnosticLogPath, "检测到主动睡眠蓝牙恢复标记")
209+
end
210+
211+
if restoreMarked or (state.bluetoothWasChanged and state.bluetoothOriginalPower ~= 0) then
212+
local helperPath = context.pluginsDir .. "/" .. plugin.id .. "/active_sleep.zsh"
213+
local command = string.format(
214+
"/bin/zsh %s --restore-bluetooth %s >/dev/null 2>&1 &",
215+
shellQuote(helperPath),
216+
shellQuote(bluetoothRestoreMarkerPath)
217+
)
218+
hs.execute(command, false)
219+
log.i("已安排独立执行器恢复蓝牙电源")
220+
appendDiagnosticLog(diagnosticLogPath, "已安排独立执行器恢复蓝牙电源")
221+
state.bluetoothWasChanged = false
222+
state.bluetoothOriginalPower = nil
223+
return
213224
end
214225

215226
state.bluetoothWasChanged = false

0 commit comments

Comments
 (0)