接入系统 Complication,补齐倒计时/自定义格式/28天累计/空气质量

字段 125 → 156 项。

Toybox.Complications(source/Comp.mc)
  这条路推翻了我之前几个「表盘做不到」的判断 —— 当时只查了 ActivityMonitor /
  UserProfile / Weather,漏了系统把这些作为 complication 发布出来:
    - 下一个日程(CIQ 确实没有日历 API,但有 CALENDAR_EVENTS complication)
    - 训练状态、完赛预测 ×4、配速预测 ×4、最近高尔夫得分
    - 本周跑步 / 骑行距离(按运动分类的,按天历史做不出来)
    - 第三方 App 1–5(CGM、补水、行情这类 App 发布的)
  需要 ComplicationSubscriber 权限。

其余补齐
  - 近 28 天累计:步数 / 卡路里 / 距离 / 楼层
  - 事件倒计时:设置里填 YYYY-MM-DD,显示还剩几天
  - 自定义时间格式、日期格式 1/2:单字母占位符(h/H/m/s/a/D/M/N/Y/y/w)
  - OWM 空气质量:AQI 等级 + 描述 + PM2.5 + PM10 + CO,走
    /data/2.5/air_pollution —— 那个接口在免费档就开放,不需要 One Call 订阅

运行时踩的坑
  - Complication.unit 不保证是 String(周跑步距离返回的就不是),直接调
    .length() 抛 Symbol Not Found。unit 和 shortLabel 都改成先 instanceof 判型。
  - 浮点 value 直接 toString 印成 "0.000000",统一格式化成一位小数。
  - 第三方 App 槽位每取一次就要走完整个迭代器,四个格子都选 App 时会走四遍。
    改成每帧只枚举一次,由 view 在绘制开始时调 Comp.beginFrame() 失效。

测试
  全字段验证的 harness 本身会触发看门狗(一次 onUpdate 里算 156 个字段),
  改成分批每帧 12 个。实际使用一帧只算 4 个,不受影响。
  156 项全部可渲染,零运行时错误;17 款设备全部编译通过。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-10 09:03:21 +08:00
parent 4d96ab0912
commit d9d45d983b
14 changed files with 651 additions and 19 deletions

View File

@@ -47,6 +47,10 @@ FIELDS = [
(850, "Seconds", "Seconds", "", "SEC", ""),
(869, "Seconds0", "Seconds (09)", "秒 (前导零)", "SEC", ""),
(873, "WeekCal", "Week Number", "周数", "WEEK", ""),
(861, "CustomTime", "Custom Time Format", "自定义时间格式", "TIME", "时间"),
(862, "DateFmt1", "Date Format 1", "日期格式 1", "DATE", "日期"),
(863, "DateFmt2", "Date Format 2", "日期格式 2", "DATE", "日期"),
(735, "Countdown", "Event Countdown", "事件倒计时", "DAYS", "倒计时"),
# ---- activity -------------------------------------------------------
(1, "Steps", "Steps", "步数", "STEP", "步数"),
@@ -73,6 +77,10 @@ FIELDS = [
(203, "FloorsWeek", "Floors (Week to Date)", "本周楼层", "WEEK", "周楼层"),
(204, "Floors7d", "Floors (Last 7 Days)", "近 7 天楼层", "7D", "7天"),
(200, "ActiveMin7d", "Active Minutes (7 Days)", "近 7 天活动分钟", "7D", "7天"),
(828, "Steps28d", "Steps (28 Days)", "近 28 天步数", "28D", "28天"),
(832, "Cal28d", "Calories (28 Days)", "近 28 天卡路里", "28D", "28天"),
(836, "Dist28d", "Distance (28 Days)", "近 28 天距离", "28D", "28天"),
(840, "Floors28d", "Floors (28 Days)", "近 28 天楼层", "28D", "28天"),
# ---- body -----------------------------------------------------------
(618, "HeartRate", "Heart Rate", "心率", "HR", "心率"),
@@ -137,6 +145,27 @@ FIELDS = [
(314, "Visibility", "Visibility", "能见度", "VIS", "能见度"),
(315, "DewPoint", "Dew Point", "露点", "DEW", "露点"),
# ---- 系统 Complication含第三方 App 发布的)------------------------
# 这些走 Toybox.Complications见 source/Comp.mc。
(612, "NextCal", "Next Calendar Event", "下一个日程", "CAL", "日程"),
(626, "TrainStatus", "Training Status", "训练状态", "TRN", "训练"),
(627, "Race5k", "Race Time (5k)", "5k 完赛预测", "5K", "5K"),
(628, "Race10k", "Race Time (10k)", "10k 完赛预测", "10K", "10K"),
(629, "RaceHalf", "Race Time (Half)", "半马完赛预测", "HM", "半马"),
(630, "RaceFull", "Race Time (Marathon)", "全马完赛预测", "FM", "全马"),
(631, "Pace5k", "Pace (5k)", "5k 配速预测", "5K", "5K配速"),
(632, "Pace10k", "Pace (10k)", "10k 配速预测", "10K", "10K配速"),
(633, "PaceHalf", "Pace (Half)", "半马配速预测", "HM", "半马配速"),
(634, "PaceFull", "Pace (Marathon)", "全马配速预测", "FM", "全马配速"),
(641, "GolfScore", "Last Golf Round Score", "最近高尔夫得分", "GOLF", "高尔夫"),
(619, "RunWeek", "Run Distance (Week)", "本周跑步距离", "RUN", "跑步"),
(620, "BikeWeek", "Bike Distance (Week)", "本周骑行距离", "BIKE", "骑行"),
(695, "App1", "App 1 (on watch)", "第三方 App 1", "APP1", "App1"),
(696, "App2", "App 2 (on watch)", "第三方 App 2", "APP2", "App2"),
(697, "App3", "App 3 (on watch)", "第三方 App 3", "APP3", "App3"),
(698, "App4", "App 4 (on watch)", "第三方 App 4", "APP4", "App4"),
(699, "App5", "App 5 (on watch)", "第三方 App 5", "APP5", "App5"),
# ---- OpenWeatherMap -------------------------------------------------
# Fetched by the background service; see source/Owm.mc.
(500, "OwmTemp", "OWM Temperature", "OWM 气温", "TEMP", "气温"),
@@ -162,6 +191,11 @@ FIELDS = [
(522, "OwmMinMaxTmrw", "OWM Min/Max Tomorrow", "OWM 明日高低温", "TMRW", "明日"),
(535, "OwmDayAfter", "OWM Temp Day After", "OWM 后日气温", "D+2", "后日"),
(523, "OwmMinMaxD2", "OWM Min/Max Day After", "OWM 后日高低温", "D+2", "后日"),
(538, "OwmAqi", "OWM Air Quality (AQI)", "OWM 空气质量", "AQI", "空气"),
(539, "OwmAqiText", "OWM AQI Description", "OWM 空气质量描述", "AQI", "空气"),
(540, "OwmPm25", "OWM PM2.5", "OWM PM2.5", "PM2.5", "PM2.5"),
(541, "OwmPm10", "OWM PM10", "OWM PM10", "PM10", "PM10"),
(542, "OwmCo", "OWM CO", "OWM 一氧化碳", "CO", "CO"),
(516, "OwmCity", "OWM City Name", "OWM 城市", "CITY", "城市"),
(517, "OwmUpdated", "OWM Update Time", "OWM 更新时间", "OWM", "更新"),
@@ -198,6 +232,22 @@ OTHER_SETTINGS = """
<settingConfig type="numeric" min="-720" max="840"/>
</setting>
<setting propertyKey="@Properties.CountdownDate" title="@Strings.SettingCountdownDate">
<settingConfig type="alphaNumeric" maxLength="10"/>
</setting>
<setting propertyKey="@Properties.TimeFmt" title="@Strings.SettingTimeFmt">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.DateFmt1" title="@Strings.SettingDateFmt1">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.DateFmt2" title="@Strings.SettingDateFmt2">
<settingConfig type="alphaNumeric" maxLength="16"/>
</setting>
<setting propertyKey="@Properties.OwmKey" title="@Strings.SettingOwmKey">
<settingConfig type="alphaNumeric" maxLength="40"/>
</setting>