banner
Vinking

Vinking

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

Sync Apple fitness records to blog display

Preface#

In the Shiro theme, there is a “Personal Status Display” feature that can showcase some custom statuses.

To make full use of this feature, I wanted to synchronize the fitness ring data from my phone to display in my personal status, resulting in the following effect:

Effect Image

Initially, I planned to implement this idea by writing a JavaScript script and using the Scriptable app. However, after trying, I found that Scriptable does not support HealthKit, making it impossible to access health data. On Apple devices, applications need to access health data through the HealthKit API, and Scriptable attempted to integrate HealthKit but was rejected by the Apple Store. Therefore, I had to settle for using Apple's built-in Shortcuts to achieve this functionality.

Status Display Settings#

By manually setting the personal status display, I could see that the page sent a request to https://{backend server}/api/v2/serverless/shiro/status via POST in the console:

Personal Status Display Request

The request body contains a JSON formatted like this:

{
	"emoji": "😴", // Emoji at the bottom right of the avatar
	"desc": "Consumed 0 kcal energy Exercised 0 minutes Stood 0 hours", // Expanded description
	"ttl": 60 // Duration of the status, in seconds
}

To complete the operation of updating the personal status, it is necessary to first obtain an access token and construct the request header Authorization: bearer {token} for user permission verification.

There are two ways to obtain the access token. The first is to initiate a login request before setting the status each time, and the access token in the format of xxxxx.xxxxxxxx can be obtained from the JSON returned by the login request.

The second way is to create a new access token in the format of xxxxxxxxxxxxxx in the backend Settings -> Security -> API Token; this method is recommended.

After obtaining the access token, verify it in the console:

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: "Test",
    ttl: 60,
  }),
})
  .then((response) => {
    if (response.ok) {
      return response.text().then(() => {
        console.log(`User status set successfully, status code: ${response.status}`);
      });
    }
  })
  .catch((error) => console.error("Error setting user status:", error));

Status set successfully.

Set Successfully

Designing Shortcuts#

To automatically synchronize health data to the personal status display, it is necessary to design a shortcut that can retrieve health data, construct requests, and call the API. The design idea is as follows:

Design Idea

There are a few pitfalls to note when converting the flowchart into a shortcut:

  1. If a certain type of data has no records for the day (e.g., no exercise), the shortcut will return a null value instead of 0. It is necessary to set an initial value of 0 in advance to avoid problems with subsequent concatenation of description text.
  2. If you want the data to be consistent with the fitness record panel data in Apple Health, special attention should be paid to the statistics for "Stand Hours." It reflects the number of times the goal was met, not the actual standing duration. The calculation logic is: within each hour, as long as the cumulative standing time reaches or exceeds 1 minute, it counts as 1 hour met. For example, standing from 08:00 to 08:01 and from 09:30 to 09:31 will be recorded as 2 hours met. In contrast, the "Stand Time" obtained from the shortcut is the actual minutes of standing each time. Therefore, to count "Stand x Hours," it is necessary to count whether the hour was met rather than directly summing the standing minutes. The instruction expression is as follows:

Count Met Instances

  1. When the interface successfully sets the status, it only returns a 204 status code and does not return any content. Additionally, since the shortcut itself does not support directly judging HTTP status codes in detail, it can only confirm whether the setting was successful by checking if the returned file size is 0.

Since the shortcut is too long, I will place the shortcut at the front:

The complete process of the shortcut is as follows (super long image warning):

::: masonry
image
:::

This article is synchronized and updated to xLog by Mix Space. The original link is https://www.vinking.top/posts/codes/sync-fitness-records-to-blog-status

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.