banner
Vinking

Vinking

你写下的每一个BUG 都是人类反抗被人工智能统治的一颗子弹

將蘋果的健身記錄同步到博客展示

前言#

在 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 的快捷指令,設計思路如下:

思路

在將流程圖轉換為快捷指令的過程中有幾個需要注意的坑:

  1. 如果某類數據當天沒有記錄(如未鍛煉),快捷指令會返回空值而不是 0。需要提前設置一個初始值 0 以避免後續拼接描述文本出現問題。
  2. 如果想要數據與蘋果健康的健身記錄面板數據一致,需特別注意「站立 x 小時」(Stand Hours)的統計方式。它反映的是達標次數,而非實際站立時長。其計算邏輯為:每個小時內,只要累計站立時間達到或超過 1 分鐘,即算作 1 小時達標。例如,08:00 - 08:01 站立,09:30 - 09:31 站立,會被記錄為 2 小時達標。相比之下,快捷指令獲取的「站立分鐘數」(Stand Time)是每次站立的實際分鐘數。因此,若要統計「站立 x 小時」,需通過計數的方式統計每小時是否達標,而非直接累加站立分鐘數。使用指令表達如下:

統計達標次數

  1. 當接口成功設置狀態時,僅返回 204 狀態碼且不返回任何內容,加上快捷指令本身不支持直接對 HTTP 狀態碼進行詳細判斷,因此只能通過判斷返回文件的大小是否為 0 來確認設置是否成功。

由於快捷指令太長了,所以先把快捷指令放在前面:

快捷指令完整流程如下(超級長圖警告):

::: masonry
image
:::

此文由 Mix Space 同步更新至 xLog
原始鏈接為 https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status


載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。