前言#
在 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