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


加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。