用 iPhone 或 Apple Watch 的藍牙訊號,離開自動鎖定 Mac、回來自動解鎖。
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗帶著手機離開座位,Mac 自動鎖定;走回來,自動解鎖。
Presence 是 macOS 選單列工具,用藍牙偵測你的 iPhone、Apple Watch 或其他 BLE 裝置在不在附近。想法來自 BLEUnlock,針對新版 macOS 重新設計與實作,並修正了原版幾個安全問題。
手機和手錶不用裝任何 App:Presence 讀的是它們本來就會發出的藍牙訊號。配套的 Presence Remote 是選用的,裝了可以從手機和手錶遠端鎖定、暫停、收通知,並在解鎖前加密確認;升級 Presence Pro 還能當簡報筆翻頁。
https://github.com/user-attachments/assets/ed99e2bb-de2b-4e57-80bd-02ce0df88796
| 總覽:誰在附近、最近 3 分鐘的訊號和最近的事件 | 裝置:同時監控 iPhone 和 Apple Watch,各自的門檻 |
| 鎖定與解鎖:鎖定方式、自動解鎖與 iPhone 加密確認 | 情境:在家、接著電源或時段外不自動鎖定 |
| 在座時間:今天坐了多久、最近 7 天、久坐提醒 | 紀錄:每次鎖定、解鎖的時間和原因 |
到 Releases 下載 Presence-版本.zip,解壓縮後把 Presence 拖進「應用程式」資料夾再打開。App 已經過 Apple 公證,之後的新版會透過 Sparkle 自動更新。
一定要放在「應用程式」資料夾:從「下載」或外接硬碟執行,系統可能在睡眠時把它結束,登入時也開不起來。放錯地方時,Presence 會提醒你並可以一鍵移過去。
iPhone 與 Apple Watch 的 Presence Remote 在 App Store 免費下載,也可以從原始碼建置(見「開發」)。
也可以從原始碼建置 Mac 版:
brew install xcodegen
xcodegen generate
xcodebuild -project Presence.xcodeproj -scheme Presence -configuration Release build
打開 Presence 後,主視窗會列出還沒完成的步驟:
如果你在用 BLEUnlock,請先在它的選單關掉「登入時啟動」並結束它,兩個同時執行會互相干擾。
Presence Remote 是 Presence 的配套 App,透過藍牙直接連到你的 Mac,不需要帳號或網路。不裝也能使用 Presence 的自動鎖定與解鎖;裝了多了下面這些功能。
簡報遙控(Presence Pro):把 iPhone 和 Apple Watch 變成簡報筆。點一下或滑一下翻頁,也能跳頁、黑畫面、開始與結束播放;手機鎖著時在鎖定畫面與動態島翻頁;手錶點按、轉錶冠或兩指互點;演講倒數,剩 5 分鐘與時間到時震動提醒;簡報中 Mac 暫停自動鎖定。要先在 Mac 的「手機與手錶」打開「允許簡報遙控」。運作方式與給其他 App 的配合指引見 docs/presenter-remote.md。
Presence Pro 是 App 內購買:月訂閱、年訂閱(都可以免費試用 7 天)或一次買斷,三種都可以家人共享。鎖定、暫停、通知、小工具與 Mac 版都免費。
配對:在 Mac 的 Presence 打開「手機與手錶」,按「配對新的 iPhone…」,再用 Presence Remote 掃描畫面上的 QR code。Apple Watch 會透過這支 iPhone 取得配對,不用另外設定。
需要 iOS 26、watchOS 26 以上。只在藍牙範圍內(大約同一個房間)有效。
配對後如果把 App 刪掉,請在 Mac 的「手機與手錶」取消配對,或在「鎖定與解鎖」關掉「需要 iPhone 加密確認」。否則 Mac 會一直等不到 iPhone 的確認,就不會自動輸入密碼,只能用 Apple Watch、Touch ID 或密碼解鎖。
判斷在不在附近:取最近 4 秒訊號的中位數,至少要有 3 筆樣本。鎖定門檻要低於解鎖門檻(遲滯),避免在邊界反覆鎖定、解鎖。
狀態未知時一律不解鎖:剛啟動、系統睡眠醒來、藍牙關閉或換了裝置時,會清掉舊的訊號,重新收到足夠的新訊號後才會解鎖。原版 BLEUnlock 會沿用睡眠前的狀態。
收不到訊號就鎖定:藍牙關閉或裝置訊號消失超過逾時時間,會照常鎖定,不會因此停止保護。暫停或情境結束時如果你不在,也會立刻補鎖。
不提供 URL scheme:任何網頁都能觸發 URL scheme,等於讓網頁可以暫停你的自動鎖定。自動化請用「捷徑」動作。
解鎖流程:喚醒螢幕 → 先等幾秒,讓 macOS 內建的「用 Apple Watch 解鎖」有機會先解開 → 還鎖著才輸入密碼。手錶解鎖比較安全,也不會跟 Presence 打字互搶。預設等 5 秒;如果連續幾次都沒有手錶先解開,就縮短成 1.5 秒。每送出一段字元前、按 Enter 前,都會確認「仍在鎖定」而且「前景是登入畫面」。如果你在這期間用 Touch ID 或 Apple Watch 先解鎖了,Presence 會立刻停止輸入,密碼不會被打進其他 App(原版的 #182)。解鎖後一分鐘內不讓螢幕因為閒置而變暗,避免剛解開又被系統鎖回去。
解鎖時機:只在訊號剛從不夠近變成夠近(你走回來了),或螢幕被喚醒(你碰了鍵盤滑鼠)時嘗試。連續失敗兩次就停止自動解鎖,直到你手動解鎖一次,避免密碼錯誤累積。
手動鎖定:用 Presence 的「立即鎖定」鎖定後,要離開超過 30 秒再回來才會自動解鎖,訊號短暫變弱不算(原版的 #137)。
密碼:存在鑰匙圈,只在解鎖那一刻讀出,不會寫進任何紀錄。
加密確認:只看訊號強弱的話,偽造你手機的藍牙廣播就能讓 Mac 解鎖。配對了 iPhone 時,Presence 在輸入密碼前會送出一個隨機的 128 位元挑戰,只有用配對金鑰加密、在時限內原樣送回的回應才算數;挑戰每次不同、只收一次。iPhone 沒有連上或沒有回應時就不自動解鎖,改由你用 Apple Watch、Touch ID 或密碼解鎖。這擋不了把你手機訊號轉送到遠處的中繼攻擊(見 docs/companion-app.md)。
各項系統行為在 macOS 26.7 的實測結果見 docs/macos26-findings.md。
Presence 與 Presence Remote 不收集任何資料:沒有帳號、伺服器或分析工具,裝置之間只用藍牙直接溝通。Mac 版只會向 GitHub 讀取更新清單。詳見隱私權政策。
在 ~/Library/Application Scripts/com.chung.presence/event 放一個可執行檔,鎖定或解鎖時會帶參數執行:
| 參數 | 時機 |
|---|---|
away | 訊號變弱而鎖定 |
lost | 收不到訊號而鎖定 |
unlocked | Presence 自動解鎖 |
intruded | 裝置不在附近時,有人手動解鎖 |
第二個參數是當時的訊號強度(dBm)。
# 判斷邏輯的單元測試
cd Packages/PresenceCore && swift test
# 重新產生 App 圖示(iPhone、手錶分別加 ios、watchos)
swift scripts/make-icon.swift Presence/Assets.xcassets/AppIcon.appiconset
# iPhone 與手錶 App(含小工具),用 Xcode 自動簽章
xcodebuild -project Presence.xcodeproj -scheme PresenceRemote -destination 'generic/platform=iOS' \
-derivedDataPath build.noindex/ios -allowProvisioningUpdates build
# 發佈 Mac 新版:先改 project.yml 的 MARKETING_VERSION 與 CURRENT_PROJECT_VERSION,commit 並 push 後執行
scripts/release.sh
# README 的截圖與宣傳影片:用開發版的示範模式(假裝置、模擬訊號),期間不要碰滑鼠鍵盤
scripts/promo/screenshots.sh
scripts/promo/video.sh
scripts/release.sh 會用 Developer ID 簽章、送 Apple 公證、產生用 EdDSA 簽章的 Sparkle 更新清單,並在 GitHub 建立 Release 草稿。簽更新用的私鑰在發佈者的鑰匙圈(Sparkle 的 generate_keys),弄丟的話已安裝的人就收不到更新,請另外備份(generate_keys -x 檔名)。
Packages/PresenceCore 是不碰系統 API 的純邏輯(何時算在附近、何時鎖定、何時嘗試解鎖),App 只負責把藍牙、螢幕狀態和使用者操作接上去。
感謝 Takeshi Sone 的 BLEUnlock(MIT 授權)。Presence 沿用了它的做法與事件腳本格式,程式碼為重新撰寫。
MIT,見 LICENSE。