前言#
在 Shiro 主題中有一個 「個人狀態展示」 功能,可以展示一些自定義的狀態。
為了充分利用這個功能,想將手機的健身圓環的數據同步展示在個人狀態裡,效果如下:
最初計劃通過編寫 JavaScript 腳本並借助 Scriptable 應用來實現這個想法。然而經過嘗試後發現,Scriptable 並不支持 HealthKit,從而無法獲取到健康數據。在蘋果設備上,應用需要通過 HealthKit 的 API 才能訪問健康數據,而 Scriptable 曾嘗試集成 HealthKit 但是被蘋果商店拒絕。所以只能退而求其次,使用蘋果自帶的快捷指令來實現這一功能。
狀態展示的設置#
通過手動設置個人狀態展示,可以在控制台中看到頁面通過 POST
的方式向 https://{後端伺服器}/api/v2/serverless/shiro/status
發送了一個請求:
請求的請求體包含下面這樣格式的 JSON:
{
"emoji": "😴", // 頭像右下角的 Emoji
"desc": "消耗0千卡能量 鍛煉0分鐘 站立0小時", // 展開後的描述
"ttl": 60 // 狀態的持續時間,單位為秒
}
為了完成更新個人狀態的操作,需要先獲取訪問令牌並且構建請求頭 Authorization: bearer {token}
用於驗證用戶權限。
訪問令牌有兩種獲得方法,第一種是每次設置狀態前先發起一次登錄請求,在登錄請求返回的 JSON 裡就能獲得一個 xxxxx.xxxxxxxx
格式的訪問令牌。
另一種是通過在後台 設定 -> 安全 -> API Token 裡新建一個 xxxxxxxxxxxxxx
格式的訪問令牌,這裡推薦這種方式。
拿到訪問令牌後,控制台裡驗證一下:
const token = "xxxxxxxxx";
fetch("https://server.vinking.top/api/v2/serverless/shiro/status", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: token,
},
body: JSON.stringify({
emoji: "✌️",
desc: "測試",
ttl: 60,
}),
})
.then((response) => {
if (response.ok) {
return response.text().then(() => {
console.log(`用戶狀態設置成功,狀態碼: ${response.status}`);
});
}
})
.catch((error) => console.error("用戶狀態設置錯誤:", error));
成功設置狀態。
設計快捷指令#
要實現自動同步健康數據到個人狀態展示,需要設計一個能獲取健康數據、構建請求並調用 API 的快捷指令,設計思路如下:
在將流程圖轉換為快捷指令的過程中有幾個需要注意的坑:
- 如果某類數據當天沒有記錄(如未鍛煉),快捷指令會返回空值而不是 0。需要提前設置一個初始值 0 以避免後續拼接描述文本出現問題。
- 如果想要數據與蘋果健康的健身記錄面板數據一致,需特別注意「站立 x 小時」(Stand Hours)的統計方式。它反映的是達標次數,而非實際站立時長。其計算邏輯為:每個小時內,只要累計站立時間達到或超過 1 分鐘,即算作 1 小時達標。例如,08:00 - 08:01 站立,09:30 - 09:31 站立,會被記錄為 2 小時達標。相比之下,快捷指令獲取的「站立分鐘數」(Stand Time)是每次站立的實際分鐘數。因此,若要統計「站立 x 小時」,需通過計數的方式統計每小時是否達標,而非直接累加站立分鐘數。使用指令表達如下:
- 當接口成功設置狀態時,僅返回
204
狀態碼且不返回任何內容,加上快捷指令本身不支持直接對 HTTP 狀態碼進行詳細判斷,因此只能通過判斷返回文件的大小是否為 0 來確認設置是否成功。
由於快捷指令太長了,所以先把快捷指令放在前面:
快捷指令完整流程如下(超級長圖警告):
::: masonry
:::
此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status