接入系统 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:
46
README.md
46
README.md
@@ -34,6 +34,7 @@ fenix8v3-watchface/
|
|||||||
│ ├── Fields.mc # 125 项数据字段的取值与格式化
|
│ ├── Fields.mc # 125 项数据字段的取值与格式化
|
||||||
│ ├── Solar.mc # 日出/晨昏蒙影/黄金蓝调时刻的太阳高度角计算
|
│ ├── Solar.mc # 日出/晨昏蒙影/黄金蓝调时刻的太阳高度角计算
|
||||||
│ ├── Owm.mc # OpenWeatherMap 缓存读取
|
│ ├── Owm.mc # OpenWeatherMap 缓存读取
|
||||||
|
│ ├── Comp.mc # 系统 / 第三方 Complication 桥接
|
||||||
│ ├── Fenix8V3Background.mc # 后台服务:拉取 OWM
|
│ ├── Fenix8V3Background.mc # 后台服务:拉取 OWM
|
||||||
│ ├── Settings.mc # 所有设置项的读取与默认值
|
│ ├── Settings.mc # 所有设置项的读取与默认值
|
||||||
│ ├── FieldTable.mc # ⚠️ 自动生成:字段 id 表
|
│ ├── FieldTable.mc # ⚠️ 自动生成:字段 id 表
|
||||||
@@ -181,21 +182,48 @@ python3 tools/gen_themes.py && python3 tools/gen_preview_svg.py
|
|||||||
|
|
||||||
### 数据字段
|
### 数据字段
|
||||||
|
|
||||||
四个数据位共用一张 **125 项** 的字段表,编号沿用 [watchface.io/docs/datafields](https://watchface.io/docs/datafields),两边可以直接对照。底部两格的小标签跟随所选字段自动变化,不需要单独配置。
|
四个数据位共用一张 **156 项** 的字段表,编号沿用 [watchface.io/docs/datafields](https://watchface.io/docs/datafields),两边可以直接对照。底部两格的小标签跟随所选字段自动变化,不需要单独配置。
|
||||||
|
|
||||||
| 分类 | 字段 |
|
| 分类 | 字段 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| 日期时间 | 秒(前导零两种)、时间、UTC 时间、第二时区 1/2、星期月日、星期日、月日、日、星期(简写/全称)、月份(名称/数字)、上午下午、周数(ISO / 日历) |
|
| 日期时间 | 秒(前导零两种)、时间、UTC 时间、第二时区 1/2、星期月日、星期日、月日、日、星期(简写/全称)、月份(名称/数字)、上午下午、周数(ISO / 日历) |
|
||||||
| 活动 | 步数、步数取整、剩余步数、卡路里、活动卡路里、活动分钟(总/中强度/高强度/本周)、距离、上楼层数、下楼层数、爬升高度、推行距离、推行次数、**本周与近 7 天累计**(步数/卡路里/距离/楼层/活动分钟) |
|
| 活动 | 步数、步数取整、剩余步数、卡路里、活动卡路里、活动分钟(总/中强度/高强度/本周)、距离、上楼层数、下楼层数、爬升高度、推行距离、推行次数、**本周 / 近 7 天 / 近 28 天累计**(步数/卡路里/距离/楼层/活动分钟) |
|
||||||
| 身体 | 心率、静息心率、压力指数、血氧、呼吸频率、身体电量、活动条(正/反向)、体重、BMI、恢复时间、最大摄氧量(跑/骑) |
|
| 身体 | 心率、静息心率、压力指数、血氧、呼吸频率、身体电量、活动条(正/反向)、体重、BMI、恢复时间、最大摄氧量(跑/骑) |
|
||||||
| 系统 | 电量、剩余天数、电量+天数、闹钟、通知、勿扰、蓝牙、太阳能强度 |
|
| 系统 | 电量、剩余天数、电量+天数、闹钟、通知、勿扰、蓝牙、太阳能强度 |
|
||||||
| 环境 | 海拔、海平面气压、环境气压、日出、日落、下一太阳事件、距太阳事件、月龄、月球照明、民用/航海/天文晨昏蒙影(各 2 项)、黄金时刻(晨/昏)、蓝调时刻(晨/昏) |
|
| 环境 | 海拔、海平面气压、环境气压、日出、日落、下一太阳事件、距太阳事件、月龄、月球照明、民用/航海/天文晨昏蒙影(各 2 项)、黄金时刻(晨/昏)、蓝调时刻(晨/昏) |
|
||||||
| 天气 | 气温、最高/最低、体感、最高、最低、湿度、降水概率、风速、风向角、风向、更新时间、海平面气压、紫外线、能见度、露点 |
|
| 天气 | 气温、最高/最低、体感、最高、最低、湿度、降水概率、风速、风向角、风向、更新时间、海平面气压、紫外线、能见度、露点 |
|
||||||
| OpenWeatherMap | 气温、体感、最高/最低、天气描述(简/详)、湿度、气压、能见度、风速、风向角、风向、阵风、1h 降雨、1h 降雪、云量、降水概率、露点、明日与后日气温及高低温、城市名、更新时间(共 25 项) |
|
| OpenWeatherMap | 气温、体感、最高/最低、天气描述(简/详)、湿度、气压、能见度、风速、风向角、风向、阵风、1h 降雨、1h 降雪、云量、降水概率、露点、明日与后日气温及高低温、城市名、更新时间、**空气质量(AQI 等级 + 描述 + PM2.5 + PM10 + CO)**(共 30 项) |
|
||||||
| 自定义 | 自定义文字 1 / 2 / 3 |
|
| 系统 Complication | 下一个日程、训练状态、完赛预测(5k/10k/半马/全马)、配速预测(同上四项)、最近高尔夫得分、本周跑步距离、本周骑行距离、第三方 App 1–5 |
|
||||||
|
| 自定义 | 自定义文字 1 / 2 / 3、自定义时间格式、日期格式 1 / 2、事件倒计时 |
|
||||||
|
|
||||||
加字段:在 `tools/gen_fields.py` 的 `FIELDS` 表里加一行,跑一遍生成器,再到 `source/Fields.mc` 的 `value()` 里补一个分支。设置项、两种语言的文案、表盘标签会自动跟上。
|
加字段:在 `tools/gen_fields.py` 的 `FIELDS` 表里加一行,跑一遍生成器,再到 `source/Fields.mc` 的 `value()` 里补一个分支。设置项、两种语言的文案、表盘标签会自动跟上。
|
||||||
|
|
||||||
|
### 系统 Complication
|
||||||
|
|
||||||
|
`Toybox.Complications`(CIQ 4.2+,17 款设备全都有)让表盘可以订阅系统和**其它 App 发布**的复杂功能。这条路解锁了一批原本以为做不到的字段:
|
||||||
|
|
||||||
|
- **日历事件** —— CIQ 确实没有日历 API,但系统把「下一个日程」作为 complication 发布了出来
|
||||||
|
- **训练状态、完赛/配速预测、最近高尔夫得分** —— `ActivityMonitor.Info` 和 `UserProfile` 上都没有,这里有
|
||||||
|
- **本周跑步 / 骑行距离** —— 这是**按运动分类**的,`ActivityMonitor` 的按天历史做不出来
|
||||||
|
- **第三方 App 1–5** —— CGM、补水、行情这类 App 发布的复杂功能,按序号取
|
||||||
|
|
||||||
|
需要 `ComplicationSubscriber` 权限。第三方 App 那五个槽位按「有值且有短标签」过滤后按序号取,避免序号随手表上装了什么 App 而漂移。
|
||||||
|
|
||||||
|
### 自定义格式与倒计时
|
||||||
|
|
||||||
|
时间/日期格式串用单字母占位符(设置项能填的长度有限,这样中英文都好写):
|
||||||
|
|
||||||
|
| 占位符 | 含义 | 占位符 | 含义 |
|
||||||
|
|--------|------|--------|------|
|
||||||
|
| `h` / `H` | 小时(跟随 12/24 制)/ 补零 | `D` | 日 |
|
||||||
|
| `m` / `s` | 分钟 / 秒(补零) | `M` / `N` | 月(数字 / 名称) |
|
||||||
|
| `a` | 上午/下午(24 小时制下为空) | `Y` / `y` | 四位年 / 两位年 |
|
||||||
|
| | | `w` | 星期 |
|
||||||
|
|
||||||
|
其它字符原样输出,所以 `D/M` → `10/9`,`w N D` → `周四 9月 10`。
|
||||||
|
|
||||||
|
事件倒计时填 `YYYY-MM-DD`,显示还剩几天。
|
||||||
|
|
||||||
### 秒针与后台天气
|
### 秒针与后台天气
|
||||||
|
|
||||||
**秒**(850/869)通过 `onPartialUpdate` 每秒重绘:只有当某个数据位真的选了秒时才请求这个回调,并且只在该格的裁剪区内重绘,不动整个表盘。常亮的 AMOLED 机型不参与——那时数据位本来就不显示。
|
**秒**(850/869)通过 `onPartialUpdate` 每秒重绘:只有当某个数据位真的选了秒时才请求这个回调,并且只在该格的裁剪区内重绘,不动整个表盘。常亮的 AMOLED 机型不参与——那时数据位本来就不显示。
|
||||||
@@ -208,14 +236,14 @@ python3 tools/gen_themes.py && python3 tools/gen_preview_svg.py
|
|||||||
|
|
||||||
| 没做的 | 原因 |
|
| 没做的 | 原因 |
|
||||||
|--------|------|
|
|--------|------|
|
||||||
| 各运动项目的 WTD / 近 7 天 / 本月 / 近 28 天 汇总(约 80 项) | Connect IQ 只有 `ActivityMonitor.getHistory()` 的按天总计(步数/卡路里/距离/楼层/活动分钟),**没有**按运动分类的历史。所以通用的本周/近 7 天累计已经做了,按跑步/骑行/游泳分开的做不了——那些在 GreenBlack 那边是手机侧与 Garmin Connect 集成同步来的 |
|
| 按运动细分的多数汇总(游泳、自定义运动 1/2 的距离/时长/次数,约 60 项) | `ActivityMonitor.getHistory()` 只有按天总计,没有按运动分类的历史。**跑步和骑行的本周距离例外**——系统把这两项作为 complication 发布了,已经做了;游泳和自定义运动没有对应的 complication 类型 |
|
||||||
|
| 日历事件、计时器 | 日历已通过 Complication 做了。**计时器**仍然做不了:表盘拿不到触摸输入,没法启停 |
|
||||||
| StormGlass.io 潮汐(5 项) | 需要额外的付费 API key,且与本表盘的定位无关 |
|
| StormGlass.io 潮汐(5 项) | 需要额外的付费 API key,且与本表盘的定位无关 |
|
||||||
| 第三方 App 复杂功能(CGM、Hydration、QuoteGlance 等 12 项) | 需要用户装了对应的 App,并通过 Complications API 订阅 |
|
| 第三方 App 复杂功能(CGM、Hydration、QuoteGlance 等 12 项) | 需要用户装了对应的 App,并通过 Complications API 订阅 |
|
||||||
| 日历事件、计时器、倒计时 | 日历不对 CIQ 开放;表盘拿不到触摸输入,没法做启停 |
|
| 睡眠得分 | `ActivityMonitor.Info` 上没有,也没有对应的 complication 类型(SDK 9.1.0 实测)。训练状态与完赛/配速预测已改由 Complication 提供 |
|
||||||
| 睡眠得分、训练状态、完赛/配速预测 | `ActivityMonitor.Info` 与 `UserProfile` 上没有这些字段(SDK 9.1.0 实测) |
|
|
||||||
| 高尔夫成绩 | 无对应 API |
|
| 高尔夫成绩 | 无对应 API |
|
||||||
| 标记类字段(Marker,约 35 项) | 那是给刻度型表盘做环形标记用的,本表盘的进度环用的是自己的指标体系 |
|
| 标记类字段(Marker,约 35 项) | 那是给刻度型表盘做环形标记用的,本表盘的进度环用的是自己的指标体系 |
|
||||||
| OWM 的 AQI 与 UVI | 免费档的 `/data/2.5/weather` 不返回;要 One Call 3.0 订阅。露点已用 Magnus 公式从温湿度算出 |
|
| OWM 的 UVI | 要 One Call 3.0 订阅。**AQI 已经做了**——空气质量走 `/data/2.5/air_pollution`,那个接口在免费档就开放。露点用 Magnus 公式从温湿度算出 |
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -238,7 +266,7 @@ python3 tools/gen_themes.py && python3 tools/gen_preview_svg.py
|
|||||||
|
|
||||||
### 权限
|
### 权限
|
||||||
|
|
||||||
`manifest.xml` 声明四项:`UserProfile`(静息心率、体重、VO2max)、`SensorHistory`(血氧、身体电量)、`Communications` 与 `Background`(OpenWeatherMap)。用户安装时会看到授权提示。
|
`manifest.xml` 声明五项:`UserProfile`(静息心率、体重、VO2max)、`SensorHistory`(血氧、身体电量)、`Communications` 与 `Background`(OpenWeatherMap)、`ComplicationSubscriber`(日历、训练状态、第三方 App)。用户安装时会看到授权提示。
|
||||||
|
|
||||||
> `Sensor` 权限**不能**用于 `type="watchface"`(除非同时申请 `Background`),编译器会直接拒绝。所以海拔与气压走 `Activity.Info` 而不是 `Sensor.getInfo()`。
|
> `Sensor` 权限**不能**用于 `type="watchface"`(除非同时申请 `Background`),编译器会直接拒绝。所以海拔与气压走 `Activity.Info` 而不是 `Sensor.getInfo()`。
|
||||||
|
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
<iq:uses-permission id="UserProfile"/>
|
<iq:uses-permission id="UserProfile"/>
|
||||||
<iq:uses-permission id="Communications"/>
|
<iq:uses-permission id="Communications"/>
|
||||||
<iq:uses-permission id="Background"/>
|
<iq:uses-permission id="Background"/>
|
||||||
|
<iq:uses-permission id="ComplicationSubscriber"/>
|
||||||
<iq:uses-permission id="SensorHistory"/>
|
<iq:uses-permission id="SensorHistory"/>
|
||||||
</iq:permissions>
|
</iq:permissions>
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<string id="FldSeconds">秒</string>
|
<string id="FldSeconds">秒</string>
|
||||||
<string id="FldSeconds0">秒 (前导零)</string>
|
<string id="FldSeconds0">秒 (前导零)</string>
|
||||||
<string id="FldWeekCal">周数</string>
|
<string id="FldWeekCal">周数</string>
|
||||||
|
<string id="FldCustomTime">自定义时间格式</string>
|
||||||
|
<string id="FldDateFmt1">日期格式 1</string>
|
||||||
|
<string id="FldDateFmt2">日期格式 2</string>
|
||||||
|
<string id="FldCountdown">事件倒计时</string>
|
||||||
<string id="FldSteps">步数</string>
|
<string id="FldSteps">步数</string>
|
||||||
<string id="FldStepsRound">步数 (取整)</string>
|
<string id="FldStepsRound">步数 (取整)</string>
|
||||||
<string id="FldStepsToGo">剩余步数</string>
|
<string id="FldStepsToGo">剩余步数</string>
|
||||||
@@ -42,6 +46,10 @@
|
|||||||
<string id="FldFloorsWeek">本周楼层</string>
|
<string id="FldFloorsWeek">本周楼层</string>
|
||||||
<string id="FldFloors7d">近 7 天楼层</string>
|
<string id="FldFloors7d">近 7 天楼层</string>
|
||||||
<string id="FldActiveMin7d">近 7 天活动分钟</string>
|
<string id="FldActiveMin7d">近 7 天活动分钟</string>
|
||||||
|
<string id="FldSteps28d">近 28 天步数</string>
|
||||||
|
<string id="FldCal28d">近 28 天卡路里</string>
|
||||||
|
<string id="FldDist28d">近 28 天距离</string>
|
||||||
|
<string id="FldFloors28d">近 28 天楼层</string>
|
||||||
<string id="FldHeartRate">心率</string>
|
<string id="FldHeartRate">心率</string>
|
||||||
<string id="FldRestingHr">静息心率</string>
|
<string id="FldRestingHr">静息心率</string>
|
||||||
<string id="FldStress">压力指数</string>
|
<string id="FldStress">压力指数</string>
|
||||||
@@ -97,6 +105,24 @@
|
|||||||
<string id="FldUvi">紫外线指数</string>
|
<string id="FldUvi">紫外线指数</string>
|
||||||
<string id="FldVisibility">能见度</string>
|
<string id="FldVisibility">能见度</string>
|
||||||
<string id="FldDewPoint">露点</string>
|
<string id="FldDewPoint">露点</string>
|
||||||
|
<string id="FldNextCal">下一个日程</string>
|
||||||
|
<string id="FldTrainStatus">训练状态</string>
|
||||||
|
<string id="FldRace5k">5k 完赛预测</string>
|
||||||
|
<string id="FldRace10k">10k 完赛预测</string>
|
||||||
|
<string id="FldRaceHalf">半马完赛预测</string>
|
||||||
|
<string id="FldRaceFull">全马完赛预测</string>
|
||||||
|
<string id="FldPace5k">5k 配速预测</string>
|
||||||
|
<string id="FldPace10k">10k 配速预测</string>
|
||||||
|
<string id="FldPaceHalf">半马配速预测</string>
|
||||||
|
<string id="FldPaceFull">全马配速预测</string>
|
||||||
|
<string id="FldGolfScore">最近高尔夫得分</string>
|
||||||
|
<string id="FldRunWeek">本周跑步距离</string>
|
||||||
|
<string id="FldBikeWeek">本周骑行距离</string>
|
||||||
|
<string id="FldApp1">第三方 App 1</string>
|
||||||
|
<string id="FldApp2">第三方 App 2</string>
|
||||||
|
<string id="FldApp3">第三方 App 3</string>
|
||||||
|
<string id="FldApp4">第三方 App 4</string>
|
||||||
|
<string id="FldApp5">第三方 App 5</string>
|
||||||
<string id="FldOwmTemp">OWM 气温</string>
|
<string id="FldOwmTemp">OWM 气温</string>
|
||||||
<string id="FldOwmMinMax">OWM 最高/最低</string>
|
<string id="FldOwmMinMax">OWM 最高/最低</string>
|
||||||
<string id="FldOwmFeels">OWM 体感温度</string>
|
<string id="FldOwmFeels">OWM 体感温度</string>
|
||||||
@@ -120,6 +146,11 @@
|
|||||||
<string id="FldOwmMinMaxTmrw">OWM 明日高低温</string>
|
<string id="FldOwmMinMaxTmrw">OWM 明日高低温</string>
|
||||||
<string id="FldOwmDayAfter">OWM 后日气温</string>
|
<string id="FldOwmDayAfter">OWM 后日气温</string>
|
||||||
<string id="FldOwmMinMaxD2">OWM 后日高低温</string>
|
<string id="FldOwmMinMaxD2">OWM 后日高低温</string>
|
||||||
|
<string id="FldOwmAqi">OWM 空气质量</string>
|
||||||
|
<string id="FldOwmAqiText">OWM 空气质量描述</string>
|
||||||
|
<string id="FldOwmPm25">OWM PM2.5</string>
|
||||||
|
<string id="FldOwmPm10">OWM PM10</string>
|
||||||
|
<string id="FldOwmCo">OWM 一氧化碳</string>
|
||||||
<string id="FldOwmCity">OWM 城市</string>
|
<string id="FldOwmCity">OWM 城市</string>
|
||||||
<string id="FldOwmUpdated">OWM 更新时间</string>
|
<string id="FldOwmUpdated">OWM 更新时间</string>
|
||||||
<string id="FldCustom1">自定义文字 1</string>
|
<string id="FldCustom1">自定义文字 1</string>
|
||||||
@@ -127,7 +158,7 @@
|
|||||||
<string id="FldCustom3">自定义文字 3</string>
|
<string id="FldCustom3">自定义文字 3</string>
|
||||||
|
|
||||||
<!-- On-face captions, in FieldTable.IDS order. -->
|
<!-- On-face captions, in FieldTable.IDS order. -->
|
||||||
<string id="FieldLabels">,时间,UTC,时区1,时区2,日期,日期,日期,日,星期,星期,月,月,,周,秒,秒,周,步数,步数,还差,千卡,活动,分钟,中强度,高强度,周分钟,距离,楼层,下楼,爬升,推行,推行,周步数,7天,周千卡,7天,周距离,7天,周楼层,7天,7天,心率,静息,压力,血氧,呼吸,体能,活动,活动,体重,BMI,恢复,摄氧,摄氧,电量,天数,电量,闹钟,通知,勿扰,蓝牙,太阳能,海拔,气压,气压,日出,日落,太阳,太阳,月龄,月相,民用晨,航海晨,天文晨,蓝调晨,黄金晨,黄金昏,蓝调昏,民用昏,航海昏,天文昏,气温,高低温,体感,最高,最低,湿度,降水,风速,风向,风向,更新,气压,紫外线,能见度,露点,气温,高低温,体感,最高,最低,天气,天气,湿度,气压,能见度,风速,风向,风向,阵风,降雨,降雪,云量,降水,露点,明日,明日,后日,后日,城市,更新,,,</string>
|
<string id="FieldLabels">,时间,UTC,时区1,时区2,日期,日期,日期,日,星期,星期,月,月,,周,秒,秒,周,时间,日期,日期,倒计时,步数,步数,还差,千卡,活动,分钟,中强度,高强度,周分钟,距离,楼层,下楼,爬升,推行,推行,周步数,7天,周千卡,7天,周距离,7天,周楼层,7天,7天,28天,28天,28天,28天,心率,静息,压力,血氧,呼吸,体能,活动,活动,体重,BMI,恢复,摄氧,摄氧,电量,天数,电量,闹钟,通知,勿扰,蓝牙,太阳能,海拔,气压,气压,日出,日落,太阳,太阳,月龄,月相,民用晨,航海晨,天文晨,蓝调晨,黄金晨,黄金昏,蓝调昏,民用昏,航海昏,天文昏,气温,高低温,体感,最高,最低,湿度,降水,风速,风向,风向,更新,气压,紫外线,能见度,露点,日程,训练,5K,10K,半马,全马,5K配速,10K配速,半马配速,全马配速,高尔夫,跑步,骑行,App1,App2,App3,App4,App5,气温,高低温,体感,最高,最低,天气,天气,湿度,气压,能见度,风速,风向,风向,阵风,降雨,降雪,云量,降水,露点,明日,明日,后日,后日,空气,空气,PM2.5,PM10,CO,城市,更新,,,</string>
|
||||||
|
|
||||||
<string id="MetricSteps">步数</string>
|
<string id="MetricSteps">步数</string>
|
||||||
<string id="MetricCalories">卡路里</string>
|
<string id="MetricCalories">卡路里</string>
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
<string id="SettingTempUnit">温度单位</string>
|
<string id="SettingTempUnit">温度单位</string>
|
||||||
<string id="SettingAltOffset1">第二时区 1(相对本地分钟数)</string>
|
<string id="SettingAltOffset1">第二时区 1(相对本地分钟数)</string>
|
||||||
<string id="SettingAltOffset2">第二时区 2(相对本地分钟数)</string>
|
<string id="SettingAltOffset2">第二时区 2(相对本地分钟数)</string>
|
||||||
|
<string id="SettingCountdownDate">倒计时目标日期(YYYY-MM-DD)</string>
|
||||||
|
<string id="SettingTimeFmt">自定义时间格式(h m a)</string>
|
||||||
|
<string id="SettingDateFmt1">日期格式 1(D M Y w)</string>
|
||||||
|
<string id="SettingDateFmt2">日期格式 2(D M Y w)</string>
|
||||||
<string id="SettingOwmKey">OpenWeatherMap API 密钥</string>
|
<string id="SettingOwmKey">OpenWeatherMap API 密钥</string>
|
||||||
<string id="SettingCustom1">自定义文字 1</string>
|
<string id="SettingCustom1">自定义文字 1</string>
|
||||||
<string id="SettingCustom2">自定义文字 2</string>
|
<string id="SettingCustom2">自定义文字 2</string>
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
<property id="TempUnit" type="number">0</property>
|
<property id="TempUnit" type="number">0</property>
|
||||||
<property id="AltOffset1" type="number">0</property>
|
<property id="AltOffset1" type="number">0</property>
|
||||||
<property id="AltOffset2" type="number">0</property>
|
<property id="AltOffset2" type="number">0</property>
|
||||||
|
<property id="CountdownDate" type="string"></property>
|
||||||
|
<property id="TimeFmt" type="string">h:m a</property>
|
||||||
|
<property id="DateFmt1" type="string">D/M</property>
|
||||||
|
<property id="DateFmt2" type="string">w D M</property>
|
||||||
<property id="OwmKey" type="string"></property>
|
<property id="OwmKey" type="string"></property>
|
||||||
<property id="Custom1" type="string"></property>
|
<property id="Custom1" type="string"></property>
|
||||||
<property id="Custom2" type="string"></property>
|
<property id="Custom2" type="string"></property>
|
||||||
|
|||||||
@@ -32,6 +32,10 @@
|
|||||||
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
||||||
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
||||||
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
||||||
|
<listEntry value="861">@Strings.FldCustomTime</listEntry>
|
||||||
|
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
|
||||||
|
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
|
||||||
|
<listEntry value="735">@Strings.FldCountdown</listEntry>
|
||||||
<listEntry value="1">@Strings.FldSteps</listEntry>
|
<listEntry value="1">@Strings.FldSteps</listEntry>
|
||||||
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
||||||
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
||||||
@@ -56,6 +60,10 @@
|
|||||||
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
||||||
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
||||||
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
||||||
|
<listEntry value="828">@Strings.FldSteps28d</listEntry>
|
||||||
|
<listEntry value="832">@Strings.FldCal28d</listEntry>
|
||||||
|
<listEntry value="836">@Strings.FldDist28d</listEntry>
|
||||||
|
<listEntry value="840">@Strings.FldFloors28d</listEntry>
|
||||||
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
||||||
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
||||||
<listEntry value="12">@Strings.FldStress</listEntry>
|
<listEntry value="12">@Strings.FldStress</listEntry>
|
||||||
@@ -111,6 +119,24 @@
|
|||||||
<listEntry value="313">@Strings.FldUvi</listEntry>
|
<listEntry value="313">@Strings.FldUvi</listEntry>
|
||||||
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
||||||
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
||||||
|
<listEntry value="612">@Strings.FldNextCal</listEntry>
|
||||||
|
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
|
||||||
|
<listEntry value="627">@Strings.FldRace5k</listEntry>
|
||||||
|
<listEntry value="628">@Strings.FldRace10k</listEntry>
|
||||||
|
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
|
||||||
|
<listEntry value="630">@Strings.FldRaceFull</listEntry>
|
||||||
|
<listEntry value="631">@Strings.FldPace5k</listEntry>
|
||||||
|
<listEntry value="632">@Strings.FldPace10k</listEntry>
|
||||||
|
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
|
||||||
|
<listEntry value="634">@Strings.FldPaceFull</listEntry>
|
||||||
|
<listEntry value="641">@Strings.FldGolfScore</listEntry>
|
||||||
|
<listEntry value="619">@Strings.FldRunWeek</listEntry>
|
||||||
|
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
|
||||||
|
<listEntry value="695">@Strings.FldApp1</listEntry>
|
||||||
|
<listEntry value="696">@Strings.FldApp2</listEntry>
|
||||||
|
<listEntry value="697">@Strings.FldApp3</listEntry>
|
||||||
|
<listEntry value="698">@Strings.FldApp4</listEntry>
|
||||||
|
<listEntry value="699">@Strings.FldApp5</listEntry>
|
||||||
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
||||||
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
||||||
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
||||||
@@ -134,6 +160,11 @@
|
|||||||
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
||||||
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
||||||
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
||||||
|
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
|
||||||
|
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
|
||||||
|
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
|
||||||
|
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
|
||||||
|
<listEntry value="542">@Strings.FldOwmCo</listEntry>
|
||||||
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
||||||
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
||||||
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
||||||
@@ -162,6 +193,10 @@
|
|||||||
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
||||||
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
||||||
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
||||||
|
<listEntry value="861">@Strings.FldCustomTime</listEntry>
|
||||||
|
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
|
||||||
|
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
|
||||||
|
<listEntry value="735">@Strings.FldCountdown</listEntry>
|
||||||
<listEntry value="1">@Strings.FldSteps</listEntry>
|
<listEntry value="1">@Strings.FldSteps</listEntry>
|
||||||
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
||||||
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
||||||
@@ -186,6 +221,10 @@
|
|||||||
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
||||||
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
||||||
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
||||||
|
<listEntry value="828">@Strings.FldSteps28d</listEntry>
|
||||||
|
<listEntry value="832">@Strings.FldCal28d</listEntry>
|
||||||
|
<listEntry value="836">@Strings.FldDist28d</listEntry>
|
||||||
|
<listEntry value="840">@Strings.FldFloors28d</listEntry>
|
||||||
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
||||||
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
||||||
<listEntry value="12">@Strings.FldStress</listEntry>
|
<listEntry value="12">@Strings.FldStress</listEntry>
|
||||||
@@ -241,6 +280,24 @@
|
|||||||
<listEntry value="313">@Strings.FldUvi</listEntry>
|
<listEntry value="313">@Strings.FldUvi</listEntry>
|
||||||
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
||||||
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
||||||
|
<listEntry value="612">@Strings.FldNextCal</listEntry>
|
||||||
|
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
|
||||||
|
<listEntry value="627">@Strings.FldRace5k</listEntry>
|
||||||
|
<listEntry value="628">@Strings.FldRace10k</listEntry>
|
||||||
|
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
|
||||||
|
<listEntry value="630">@Strings.FldRaceFull</listEntry>
|
||||||
|
<listEntry value="631">@Strings.FldPace5k</listEntry>
|
||||||
|
<listEntry value="632">@Strings.FldPace10k</listEntry>
|
||||||
|
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
|
||||||
|
<listEntry value="634">@Strings.FldPaceFull</listEntry>
|
||||||
|
<listEntry value="641">@Strings.FldGolfScore</listEntry>
|
||||||
|
<listEntry value="619">@Strings.FldRunWeek</listEntry>
|
||||||
|
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
|
||||||
|
<listEntry value="695">@Strings.FldApp1</listEntry>
|
||||||
|
<listEntry value="696">@Strings.FldApp2</listEntry>
|
||||||
|
<listEntry value="697">@Strings.FldApp3</listEntry>
|
||||||
|
<listEntry value="698">@Strings.FldApp4</listEntry>
|
||||||
|
<listEntry value="699">@Strings.FldApp5</listEntry>
|
||||||
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
||||||
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
||||||
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
||||||
@@ -264,6 +321,11 @@
|
|||||||
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
||||||
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
||||||
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
||||||
|
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
|
||||||
|
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
|
||||||
|
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
|
||||||
|
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
|
||||||
|
<listEntry value="542">@Strings.FldOwmCo</listEntry>
|
||||||
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
||||||
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
||||||
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
||||||
@@ -292,6 +354,10 @@
|
|||||||
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
||||||
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
||||||
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
||||||
|
<listEntry value="861">@Strings.FldCustomTime</listEntry>
|
||||||
|
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
|
||||||
|
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
|
||||||
|
<listEntry value="735">@Strings.FldCountdown</listEntry>
|
||||||
<listEntry value="1">@Strings.FldSteps</listEntry>
|
<listEntry value="1">@Strings.FldSteps</listEntry>
|
||||||
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
||||||
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
||||||
@@ -316,6 +382,10 @@
|
|||||||
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
||||||
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
||||||
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
||||||
|
<listEntry value="828">@Strings.FldSteps28d</listEntry>
|
||||||
|
<listEntry value="832">@Strings.FldCal28d</listEntry>
|
||||||
|
<listEntry value="836">@Strings.FldDist28d</listEntry>
|
||||||
|
<listEntry value="840">@Strings.FldFloors28d</listEntry>
|
||||||
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
||||||
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
||||||
<listEntry value="12">@Strings.FldStress</listEntry>
|
<listEntry value="12">@Strings.FldStress</listEntry>
|
||||||
@@ -371,6 +441,24 @@
|
|||||||
<listEntry value="313">@Strings.FldUvi</listEntry>
|
<listEntry value="313">@Strings.FldUvi</listEntry>
|
||||||
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
||||||
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
||||||
|
<listEntry value="612">@Strings.FldNextCal</listEntry>
|
||||||
|
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
|
||||||
|
<listEntry value="627">@Strings.FldRace5k</listEntry>
|
||||||
|
<listEntry value="628">@Strings.FldRace10k</listEntry>
|
||||||
|
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
|
||||||
|
<listEntry value="630">@Strings.FldRaceFull</listEntry>
|
||||||
|
<listEntry value="631">@Strings.FldPace5k</listEntry>
|
||||||
|
<listEntry value="632">@Strings.FldPace10k</listEntry>
|
||||||
|
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
|
||||||
|
<listEntry value="634">@Strings.FldPaceFull</listEntry>
|
||||||
|
<listEntry value="641">@Strings.FldGolfScore</listEntry>
|
||||||
|
<listEntry value="619">@Strings.FldRunWeek</listEntry>
|
||||||
|
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
|
||||||
|
<listEntry value="695">@Strings.FldApp1</listEntry>
|
||||||
|
<listEntry value="696">@Strings.FldApp2</listEntry>
|
||||||
|
<listEntry value="697">@Strings.FldApp3</listEntry>
|
||||||
|
<listEntry value="698">@Strings.FldApp4</listEntry>
|
||||||
|
<listEntry value="699">@Strings.FldApp5</listEntry>
|
||||||
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
||||||
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
||||||
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
||||||
@@ -394,6 +482,11 @@
|
|||||||
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
||||||
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
||||||
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
||||||
|
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
|
||||||
|
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
|
||||||
|
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
|
||||||
|
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
|
||||||
|
<listEntry value="542">@Strings.FldOwmCo</listEntry>
|
||||||
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
||||||
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
||||||
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
||||||
@@ -422,6 +515,10 @@
|
|||||||
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
<listEntry value="850">@Strings.FldSeconds</listEntry>
|
||||||
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
<listEntry value="869">@Strings.FldSeconds0</listEntry>
|
||||||
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
<listEntry value="873">@Strings.FldWeekCal</listEntry>
|
||||||
|
<listEntry value="861">@Strings.FldCustomTime</listEntry>
|
||||||
|
<listEntry value="862">@Strings.FldDateFmt1</listEntry>
|
||||||
|
<listEntry value="863">@Strings.FldDateFmt2</listEntry>
|
||||||
|
<listEntry value="735">@Strings.FldCountdown</listEntry>
|
||||||
<listEntry value="1">@Strings.FldSteps</listEntry>
|
<listEntry value="1">@Strings.FldSteps</listEntry>
|
||||||
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
<listEntry value="14">@Strings.FldStepsRound</listEntry>
|
||||||
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
<listEntry value="707">@Strings.FldStepsToGo</listEntry>
|
||||||
@@ -446,6 +543,10 @@
|
|||||||
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
<listEntry value="203">@Strings.FldFloorsWeek</listEntry>
|
||||||
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
<listEntry value="204">@Strings.FldFloors7d</listEntry>
|
||||||
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
<listEntry value="200">@Strings.FldActiveMin7d</listEntry>
|
||||||
|
<listEntry value="828">@Strings.FldSteps28d</listEntry>
|
||||||
|
<listEntry value="832">@Strings.FldCal28d</listEntry>
|
||||||
|
<listEntry value="836">@Strings.FldDist28d</listEntry>
|
||||||
|
<listEntry value="840">@Strings.FldFloors28d</listEntry>
|
||||||
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
<listEntry value="618">@Strings.FldHeartRate</listEntry>
|
||||||
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
<listEntry value="276">@Strings.FldRestingHr</listEntry>
|
||||||
<listEntry value="12">@Strings.FldStress</listEntry>
|
<listEntry value="12">@Strings.FldStress</listEntry>
|
||||||
@@ -501,6 +602,24 @@
|
|||||||
<listEntry value="313">@Strings.FldUvi</listEntry>
|
<listEntry value="313">@Strings.FldUvi</listEntry>
|
||||||
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
<listEntry value="314">@Strings.FldVisibility</listEntry>
|
||||||
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
<listEntry value="315">@Strings.FldDewPoint</listEntry>
|
||||||
|
<listEntry value="612">@Strings.FldNextCal</listEntry>
|
||||||
|
<listEntry value="626">@Strings.FldTrainStatus</listEntry>
|
||||||
|
<listEntry value="627">@Strings.FldRace5k</listEntry>
|
||||||
|
<listEntry value="628">@Strings.FldRace10k</listEntry>
|
||||||
|
<listEntry value="629">@Strings.FldRaceHalf</listEntry>
|
||||||
|
<listEntry value="630">@Strings.FldRaceFull</listEntry>
|
||||||
|
<listEntry value="631">@Strings.FldPace5k</listEntry>
|
||||||
|
<listEntry value="632">@Strings.FldPace10k</listEntry>
|
||||||
|
<listEntry value="633">@Strings.FldPaceHalf</listEntry>
|
||||||
|
<listEntry value="634">@Strings.FldPaceFull</listEntry>
|
||||||
|
<listEntry value="641">@Strings.FldGolfScore</listEntry>
|
||||||
|
<listEntry value="619">@Strings.FldRunWeek</listEntry>
|
||||||
|
<listEntry value="620">@Strings.FldBikeWeek</listEntry>
|
||||||
|
<listEntry value="695">@Strings.FldApp1</listEntry>
|
||||||
|
<listEntry value="696">@Strings.FldApp2</listEntry>
|
||||||
|
<listEntry value="697">@Strings.FldApp3</listEntry>
|
||||||
|
<listEntry value="698">@Strings.FldApp4</listEntry>
|
||||||
|
<listEntry value="699">@Strings.FldApp5</listEntry>
|
||||||
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
<listEntry value="500">@Strings.FldOwmTemp</listEntry>
|
||||||
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
<listEntry value="515">@Strings.FldOwmMinMax</listEntry>
|
||||||
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
<listEntry value="503">@Strings.FldOwmFeels</listEntry>
|
||||||
@@ -524,6 +643,11 @@
|
|||||||
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
<listEntry value="522">@Strings.FldOwmMinMaxTmrw</listEntry>
|
||||||
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
<listEntry value="535">@Strings.FldOwmDayAfter</listEntry>
|
||||||
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
<listEntry value="523">@Strings.FldOwmMinMaxD2</listEntry>
|
||||||
|
<listEntry value="538">@Strings.FldOwmAqi</listEntry>
|
||||||
|
<listEntry value="539">@Strings.FldOwmAqiText</listEntry>
|
||||||
|
<listEntry value="540">@Strings.FldOwmPm25</listEntry>
|
||||||
|
<listEntry value="541">@Strings.FldOwmPm10</listEntry>
|
||||||
|
<listEntry value="542">@Strings.FldOwmCo</listEntry>
|
||||||
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
<listEntry value="516">@Strings.FldOwmCity</listEntry>
|
||||||
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
<listEntry value="517">@Strings.FldOwmUpdated</listEntry>
|
||||||
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
<listEntry value="703">@Strings.FldCustom1</listEntry>
|
||||||
@@ -597,6 +721,22 @@
|
|||||||
<settingConfig type="numeric" min="-720" max="840"/>
|
<settingConfig type="numeric" min="-720" max="840"/>
|
||||||
</setting>
|
</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">
|
<setting propertyKey="@Properties.OwmKey" title="@Strings.SettingOwmKey">
|
||||||
<settingConfig type="alphaNumeric" maxLength="40"/>
|
<settingConfig type="alphaNumeric" maxLength="40"/>
|
||||||
</setting>
|
</setting>
|
||||||
|
|||||||
@@ -18,6 +18,10 @@
|
|||||||
<string id="FldSeconds">Seconds</string>
|
<string id="FldSeconds">Seconds</string>
|
||||||
<string id="FldSeconds0">Seconds (09)</string>
|
<string id="FldSeconds0">Seconds (09)</string>
|
||||||
<string id="FldWeekCal">Week Number</string>
|
<string id="FldWeekCal">Week Number</string>
|
||||||
|
<string id="FldCustomTime">Custom Time Format</string>
|
||||||
|
<string id="FldDateFmt1">Date Format 1</string>
|
||||||
|
<string id="FldDateFmt2">Date Format 2</string>
|
||||||
|
<string id="FldCountdown">Event Countdown</string>
|
||||||
<string id="FldSteps">Steps</string>
|
<string id="FldSteps">Steps</string>
|
||||||
<string id="FldStepsRound">Steps Rounded</string>
|
<string id="FldStepsRound">Steps Rounded</string>
|
||||||
<string id="FldStepsToGo">Steps to Go</string>
|
<string id="FldStepsToGo">Steps to Go</string>
|
||||||
@@ -42,6 +46,10 @@
|
|||||||
<string id="FldFloorsWeek">Floors (Week to Date)</string>
|
<string id="FldFloorsWeek">Floors (Week to Date)</string>
|
||||||
<string id="FldFloors7d">Floors (Last 7 Days)</string>
|
<string id="FldFloors7d">Floors (Last 7 Days)</string>
|
||||||
<string id="FldActiveMin7d">Active Minutes (7 Days)</string>
|
<string id="FldActiveMin7d">Active Minutes (7 Days)</string>
|
||||||
|
<string id="FldSteps28d">Steps (28 Days)</string>
|
||||||
|
<string id="FldCal28d">Calories (28 Days)</string>
|
||||||
|
<string id="FldDist28d">Distance (28 Days)</string>
|
||||||
|
<string id="FldFloors28d">Floors (28 Days)</string>
|
||||||
<string id="FldHeartRate">Heart Rate</string>
|
<string id="FldHeartRate">Heart Rate</string>
|
||||||
<string id="FldRestingHr">Resting Heart Rate</string>
|
<string id="FldRestingHr">Resting Heart Rate</string>
|
||||||
<string id="FldStress">Stress Score</string>
|
<string id="FldStress">Stress Score</string>
|
||||||
@@ -97,6 +105,24 @@
|
|||||||
<string id="FldUvi">UV Index</string>
|
<string id="FldUvi">UV Index</string>
|
||||||
<string id="FldVisibility">Visibility</string>
|
<string id="FldVisibility">Visibility</string>
|
||||||
<string id="FldDewPoint">Dew Point</string>
|
<string id="FldDewPoint">Dew Point</string>
|
||||||
|
<string id="FldNextCal">Next Calendar Event</string>
|
||||||
|
<string id="FldTrainStatus">Training Status</string>
|
||||||
|
<string id="FldRace5k">Race Time (5k)</string>
|
||||||
|
<string id="FldRace10k">Race Time (10k)</string>
|
||||||
|
<string id="FldRaceHalf">Race Time (Half)</string>
|
||||||
|
<string id="FldRaceFull">Race Time (Marathon)</string>
|
||||||
|
<string id="FldPace5k">Pace (5k)</string>
|
||||||
|
<string id="FldPace10k">Pace (10k)</string>
|
||||||
|
<string id="FldPaceHalf">Pace (Half)</string>
|
||||||
|
<string id="FldPaceFull">Pace (Marathon)</string>
|
||||||
|
<string id="FldGolfScore">Last Golf Round Score</string>
|
||||||
|
<string id="FldRunWeek">Run Distance (Week)</string>
|
||||||
|
<string id="FldBikeWeek">Bike Distance (Week)</string>
|
||||||
|
<string id="FldApp1">App 1 (on watch)</string>
|
||||||
|
<string id="FldApp2">App 2 (on watch)</string>
|
||||||
|
<string id="FldApp3">App 3 (on watch)</string>
|
||||||
|
<string id="FldApp4">App 4 (on watch)</string>
|
||||||
|
<string id="FldApp5">App 5 (on watch)</string>
|
||||||
<string id="FldOwmTemp">OWM Temperature</string>
|
<string id="FldOwmTemp">OWM Temperature</string>
|
||||||
<string id="FldOwmMinMax">OWM Max/Min Temp</string>
|
<string id="FldOwmMinMax">OWM Max/Min Temp</string>
|
||||||
<string id="FldOwmFeels">OWM Feels Like</string>
|
<string id="FldOwmFeels">OWM Feels Like</string>
|
||||||
@@ -120,6 +146,11 @@
|
|||||||
<string id="FldOwmMinMaxTmrw">OWM Min/Max Tomorrow</string>
|
<string id="FldOwmMinMaxTmrw">OWM Min/Max Tomorrow</string>
|
||||||
<string id="FldOwmDayAfter">OWM Temp Day After</string>
|
<string id="FldOwmDayAfter">OWM Temp Day After</string>
|
||||||
<string id="FldOwmMinMaxD2">OWM Min/Max Day After</string>
|
<string id="FldOwmMinMaxD2">OWM Min/Max Day After</string>
|
||||||
|
<string id="FldOwmAqi">OWM Air Quality (AQI)</string>
|
||||||
|
<string id="FldOwmAqiText">OWM AQI Description</string>
|
||||||
|
<string id="FldOwmPm25">OWM PM2.5</string>
|
||||||
|
<string id="FldOwmPm10">OWM PM10</string>
|
||||||
|
<string id="FldOwmCo">OWM CO</string>
|
||||||
<string id="FldOwmCity">OWM City Name</string>
|
<string id="FldOwmCity">OWM City Name</string>
|
||||||
<string id="FldOwmUpdated">OWM Update Time</string>
|
<string id="FldOwmUpdated">OWM Update Time</string>
|
||||||
<string id="FldCustom1">Custom Text 1</string>
|
<string id="FldCustom1">Custom Text 1</string>
|
||||||
@@ -127,7 +158,7 @@
|
|||||||
<string id="FldCustom3">Custom Text 3</string>
|
<string id="FldCustom3">Custom Text 3</string>
|
||||||
|
|
||||||
<!-- On-face captions, in FieldTable.IDS order. -->
|
<!-- On-face captions, in FieldTable.IDS order. -->
|
||||||
<string id="FieldLabels">,TIME,UTC,TZ1,TZ2,DATE,DATE,DATE,DAY,DAY,DAY,MON,MON,,WEEK,SEC,SEC,WEEK,STEP,STEP,TO GO,KCAL,ACAL,MIN,MOD,VIG,WEEK,DST,FLR,DESC,ASC,PUSH,PUSH,WEEK,7D,WEEK,7D,WEEK,7D,WEEK,7D,7D,HR,RHR,STRS,SPO2,RESP,BODY,MOVE,MOVE,WT,BMI,RCVR,VO2,VO2,BATT,DAYS,BATT,ALRM,MSG,DND,BT,SOLR,ALT,hPa,hPa,RISE,SET,SUN,SUN,MOON,MOON,CIVIL,NAUT,ASTR,BLUE,GOLD,GOLD,BLUE,CIVIL,NAUT,ASTR,TEMP,HI/LO,FEEL,HIGH,LOW,HUM,RAIN,WIND,WIND,WIND,WX,hPa,UVI,VIS,DEW,TEMP,HI/LO,FEEL,HIGH,LOW,WX,WX,HUM,hPa,VIS,WIND,WIND,WIND,GUST,RAIN,SNOW,CLD,RAIN,DEW,TMRW,TMRW,D+2,D+2,CITY,OWM,,,</string>
|
<string id="FieldLabels">,TIME,UTC,TZ1,TZ2,DATE,DATE,DATE,DAY,DAY,DAY,MON,MON,,WEEK,SEC,SEC,WEEK,TIME,DATE,DATE,DAYS,STEP,STEP,TO GO,KCAL,ACAL,MIN,MOD,VIG,WEEK,DST,FLR,DESC,ASC,PUSH,PUSH,WEEK,7D,WEEK,7D,WEEK,7D,WEEK,7D,7D,28D,28D,28D,28D,HR,RHR,STRS,SPO2,RESP,BODY,MOVE,MOVE,WT,BMI,RCVR,VO2,VO2,BATT,DAYS,BATT,ALRM,MSG,DND,BT,SOLR,ALT,hPa,hPa,RISE,SET,SUN,SUN,MOON,MOON,CIVIL,NAUT,ASTR,BLUE,GOLD,GOLD,BLUE,CIVIL,NAUT,ASTR,TEMP,HI/LO,FEEL,HIGH,LOW,HUM,RAIN,WIND,WIND,WIND,WX,hPa,UVI,VIS,DEW,CAL,TRN,5K,10K,HM,FM,5K,10K,HM,FM,GOLF,RUN,BIKE,APP1,APP2,APP3,APP4,APP5,TEMP,HI/LO,FEEL,HIGH,LOW,WX,WX,HUM,hPa,VIS,WIND,WIND,WIND,GUST,RAIN,SNOW,CLD,RAIN,DEW,TMRW,TMRW,D+2,D+2,AQI,AQI,PM2.5,PM10,CO,CITY,OWM,,,</string>
|
||||||
|
|
||||||
<string id="MetricSteps">Steps</string>
|
<string id="MetricSteps">Steps</string>
|
||||||
<string id="MetricCalories">Calories</string>
|
<string id="MetricCalories">Calories</string>
|
||||||
|
|||||||
@@ -13,6 +13,10 @@
|
|||||||
<string id="SettingTempUnit">Temperature Unit</string>
|
<string id="SettingTempUnit">Temperature Unit</string>
|
||||||
<string id="SettingAltOffset1">Alternate Time 1 (minutes from local)</string>
|
<string id="SettingAltOffset1">Alternate Time 1 (minutes from local)</string>
|
||||||
<string id="SettingAltOffset2">Alternate Time 2 (minutes from local)</string>
|
<string id="SettingAltOffset2">Alternate Time 2 (minutes from local)</string>
|
||||||
|
<string id="SettingCountdownDate">Countdown Target (YYYY-MM-DD)</string>
|
||||||
|
<string id="SettingTimeFmt">Custom Time Format (h m a)</string>
|
||||||
|
<string id="SettingDateFmt1">Date Format 1 (D M Y w)</string>
|
||||||
|
<string id="SettingDateFmt2">Date Format 2 (D M Y w)</string>
|
||||||
<string id="SettingOwmKey">OpenWeatherMap API Key</string>
|
<string id="SettingOwmKey">OpenWeatherMap API Key</string>
|
||||||
<string id="SettingCustom1">Custom Text 1</string>
|
<string id="SettingCustom1">Custom Text 1</string>
|
||||||
<string id="SettingCustom2">Custom Text 2</string>
|
<string id="SettingCustom2">Custom Text 2</string>
|
||||||
|
|||||||
184
source/Comp.mc
Normal file
184
source/Comp.mc
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
import Toybox.Lang;
|
||||||
|
import Toybox.Complications;
|
||||||
|
import Toybox.System;
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// 系统 Complication 桥接
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Toybox.Complications(CIQ 4.2+,本项目支持的 17 款设备全都有)让表盘可以订阅
|
||||||
|
// 系统和**其它 App 发布**的复杂功能数据。
|
||||||
|
//
|
||||||
|
// 这个模块解锁了一批我原本判断「表盘做不到」的字段 —— 当时只查了
|
||||||
|
// ActivityMonitor / UserProfile / Weather,漏掉了这条路:
|
||||||
|
//
|
||||||
|
// 日历事件 CIQ 确实没有日历 API,但系统把「下一个日程」作为
|
||||||
|
// complication 发布出来了
|
||||||
|
// 训练状态 ActivityMonitor.Info 上没有,这里有
|
||||||
|
// 完赛/配速预测 同上,5k/10k/半马/全马各两套
|
||||||
|
// 本周跑步/骑行距离 这是**按运动分类**的,ActivityMonitor 的按天历史做不出来
|
||||||
|
// 高尔夫成绩 无其它来源
|
||||||
|
// 第三方 App CGM、补水、行情这类 App 发布的复杂功能,
|
||||||
|
// 通过迭代器按序号取(对应目录里的 App 1..App 5)
|
||||||
|
//
|
||||||
|
// 取值策略:每次绘制现查(getComplication 很轻量),不做订阅回调 ——
|
||||||
|
// 表盘每分钟才重绘一次,订阅的实时性没有意义,反而要维护状态。
|
||||||
|
// ============================================================================
|
||||||
|
module Comp {
|
||||||
|
|
||||||
|
// 字段编号 → complication 类型。
|
||||||
|
// 返回 null 表示这个编号不归本模块管。
|
||||||
|
function typeFor(id as Number) {
|
||||||
|
if (id == 612) { return Complications.COMPLICATION_TYPE_CALENDAR_EVENTS; }
|
||||||
|
if (id == 626) { return Complications.COMPLICATION_TYPE_TRAINING_STATUS; }
|
||||||
|
if (id == 627) { return Complications.COMPLICATION_TYPE_RACE_PREDICTOR_5K; }
|
||||||
|
if (id == 628) { return Complications.COMPLICATION_TYPE_RACE_PREDICTOR_10K; }
|
||||||
|
if (id == 629) {
|
||||||
|
return Complications.COMPLICATION_TYPE_RACE_PREDICTOR_HALF_MARATHON;
|
||||||
|
}
|
||||||
|
if (id == 630) {
|
||||||
|
return Complications.COMPLICATION_TYPE_RACE_PREDICTOR_MARATHON;
|
||||||
|
}
|
||||||
|
if (id == 631) { return Complications.COMPLICATION_TYPE_RACE_PACE_PREDICTOR_5K; }
|
||||||
|
if (id == 632) { return Complications.COMPLICATION_TYPE_RACE_PACE_PREDICTOR_10K; }
|
||||||
|
if (id == 633) {
|
||||||
|
return Complications.COMPLICATION_TYPE_RACE_PACE_PREDICTOR_HALF_MARATHON;
|
||||||
|
}
|
||||||
|
if (id == 634) {
|
||||||
|
return Complications.COMPLICATION_TYPE_RACE_PACE_PREDICTOR_MARATHON;
|
||||||
|
}
|
||||||
|
if (id == 641) {
|
||||||
|
return Complications.COMPLICATION_TYPE_LAST_GOLF_ROUND_SCORE;
|
||||||
|
}
|
||||||
|
if (id == 619) {
|
||||||
|
return Complications.COMPLICATION_TYPE_WEEKLY_RUN_DISTANCE;
|
||||||
|
}
|
||||||
|
if (id == 620) {
|
||||||
|
return Complications.COMPLICATION_TYPE_WEEKLY_BIKE_DISTANCE;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 第三方 App 列表的每帧缓存。
|
||||||
|
//
|
||||||
|
// 枚举一次要走完整个迭代器,四个数据位如果都选了 App 槽就会走四遍。
|
||||||
|
// 表盘每分钟才画一次,本来不算大开销,但 onUpdate 有看门狗时限,
|
||||||
|
// 能省则省 —— 所以每帧只枚举一次,由 view 在绘制开始时调 beginFrame() 失效。
|
||||||
|
var mApps as Array<Complications.Complication>?;
|
||||||
|
|
||||||
|
function beginFrame() as Void {
|
||||||
|
mApps = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 695..699 是「第三方 App 1..5」,不对应固定类型,靠迭代器按序号取。
|
||||||
|
function isAppSlot(id as Number) as Boolean {
|
||||||
|
return id >= 695 && id <= 699;
|
||||||
|
}
|
||||||
|
|
||||||
|
function owns(id as Number) as Boolean {
|
||||||
|
return isAppSlot(id) || typeFor(id) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 按类型取一个 complication 对象;取不到返回 null。
|
||||||
|
// 用 try 包住是因为设备不支持某个类型时 getComplication 会抛,而不是返回
|
||||||
|
// null —— 和本项目里其它 CIQ API 的老毛病一样。
|
||||||
|
function byType(type) as Complications.Complication? {
|
||||||
|
try {
|
||||||
|
return Complications.getComplication(new Complications.Id(type));
|
||||||
|
} catch (e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 取第 n 个**第三方发布**的 complication(n 从 0 起)。
|
||||||
|
//
|
||||||
|
// 迭代器里既有系统自带的,也有别的 App 发布的。这里只保留「有短标签且有值」
|
||||||
|
// 的项 —— 没装对应 App 时那些是空壳,全留着的话序号会随手表上装了什么 App
|
||||||
|
// 而漂移,用户设好的第 3 个明天可能就变成别的东西了。
|
||||||
|
//
|
||||||
|
// Complication 的成员是 complicationId / value / unit / shortLabel /
|
||||||
|
// longLabel / ranges(没有 label,别写错)。
|
||||||
|
function nthApp(n as Number) as Complications.Complication? {
|
||||||
|
if (mApps == null) {
|
||||||
|
var list = [] as Array<Complications.Complication>;
|
||||||
|
try {
|
||||||
|
var it = Complications.getComplications();
|
||||||
|
if (it != null) {
|
||||||
|
var c = it.next();
|
||||||
|
while (c != null) {
|
||||||
|
if (c.value != null && c.shortLabel != null
|
||||||
|
&& c.shortLabel instanceof Lang.String) {
|
||||||
|
list.add(c);
|
||||||
|
}
|
||||||
|
c = it.next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// 设备不支持枚举时就当作一个都没有。
|
||||||
|
}
|
||||||
|
mApps = list;
|
||||||
|
}
|
||||||
|
return (n >= 0 && n < mApps.size()) ? mApps[n] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 把 complication 的值转成可显示的字符串。
|
||||||
|
//
|
||||||
|
// value 的类型随 complication 而变(数字、字符串都有),unit 有时带单位词。
|
||||||
|
// 完赛/配速预测的 value 是**秒数**,直接印出来是一串没意义的数字,
|
||||||
|
// 所以单独格式化成 h:mm:ss / mm:ss。
|
||||||
|
function render(c as Complications.Complication?, id as Number) as String? {
|
||||||
|
if (c == null || c.value == null) { return null; }
|
||||||
|
var v = c.value;
|
||||||
|
if (isTimeSeconds(id) && !(v instanceof Lang.String)) {
|
||||||
|
return hms(v.toNumber());
|
||||||
|
}
|
||||||
|
// 浮点直接 toString 会印成 "0.000000",统一保留一位小数。
|
||||||
|
if (v instanceof Lang.Float || v instanceof Lang.Double) {
|
||||||
|
return trimUnit(v.toFloat().format("%.1f"), c);
|
||||||
|
}
|
||||||
|
var s = v.toString();
|
||||||
|
// 单位词能明显帮上忙时才拼(比如距离的 km),纯数字类就不拼了。
|
||||||
|
//
|
||||||
|
// ⚠️ unit 的类型不保证是 String —— 周跑步距离那种返回的不是字符串,
|
||||||
|
// 直接调 .length() 会抛 "Could not find symbol 'length'"。
|
||||||
|
// 所以先用 instanceof 判一次再说。
|
||||||
|
if (c.unit != null && c.unit instanceof Lang.String) {
|
||||||
|
var u = c.unit as String;
|
||||||
|
if (u.length() > 0 && u.length() <= 3) { s = s + u; }
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 把单位词拼到已格式化好的数值后面(如果 unit 确实是个短字符串)。
|
||||||
|
function trimUnit(s as String, c as Complications.Complication) as String {
|
||||||
|
if (c.unit != null && c.unit instanceof Lang.String) {
|
||||||
|
var u = c.unit as String;
|
||||||
|
if (u.length() > 0 && u.length() <= 3) { return s + u; }
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 完赛预测(627–630)与配速预测(631–634)都是秒。
|
||||||
|
function isTimeSeconds(id as Number) as Boolean {
|
||||||
|
return id >= 627 && id <= 634;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 秒 → h:mm:ss,不足一小时则 m:ss。配速通常是后者。
|
||||||
|
function hms(total as Number) as String {
|
||||||
|
if (total <= 0) { return "--"; }
|
||||||
|
var h = total / 3600;
|
||||||
|
var m = (total % 3600) / 60;
|
||||||
|
var s = total % 60;
|
||||||
|
if (h > 0) {
|
||||||
|
return h.format("%d") + ":" + m.format("%02d") + ":" + s.format("%02d");
|
||||||
|
}
|
||||||
|
return m.format("%d") + ":" + s.format("%02d");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字段取值总入口。不属于本模块的编号返回 null。
|
||||||
|
function value(id as Number) as String? {
|
||||||
|
if (!owns(id)) { return null; }
|
||||||
|
var c = isAppSlot(id) ? nthApp(id - 695) : byType(typeFor(id));
|
||||||
|
var out = render(c, id);
|
||||||
|
return out == null ? "--" : out;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,9 +13,10 @@ import Toybox.Position;
|
|||||||
// HTTP 请求。Connect IQ 的方案是**后台服务**:系统按定时器唤醒一个独立进程,
|
// HTTP 请求。Connect IQ 的方案是**后台服务**:系统按定时器唤醒一个独立进程,
|
||||||
// 在里面发请求,把结果通过 Background.exit() 交回前台,前台再写进 Storage。
|
// 在里面发请求,把结果通过 Background.exit() 交回前台,前台再写进 Storage。
|
||||||
//
|
//
|
||||||
// 每次唤醒发两个请求:
|
// 每次唤醒发三个请求:
|
||||||
// 1. 当前天气 /data/2.5/weather
|
// 1. 当前天气 /data/2.5/weather
|
||||||
// 2. 短期预报 /data/2.5/forecast?cnt=16(约 48 小时,够算明日/后日高低温)
|
// 2. 短期预报 /data/2.5/forecast?cnt=16(约 48 小时,够算明日/后日高低温)
|
||||||
|
// 3. 空气质量 /data/2.5/air_pollution(AQI / PM2.5 / PM10 / CO)
|
||||||
//
|
//
|
||||||
// ⚠️ 预报接口必须带 cnt 限制条数。后台进程的内存预算非常小(约 32KB),
|
// ⚠️ 预报接口必须带 cnt 限制条数。后台进程的内存预算非常小(约 32KB),
|
||||||
// 完整的 5 天 / 3 小时预报解析出来能有几十 KB,会直接爆掉。
|
// 完整的 5 天 / 3 小时预报解析出来能有几十 KB,会直接爆掉。
|
||||||
@@ -49,7 +50,7 @@ class Fenix8V3Background extends System.ServiceDelegate {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mResult = {};
|
mResult = {};
|
||||||
mPending = 2;
|
mPending = 3; // 当前天气 + 短预报 + 空气质量
|
||||||
// 一律用 units=metric 请求,单位换算统一放到 Fields 里按用户设置做,
|
// 一律用 units=metric 请求,单位换算统一放到 Fields 里按用户设置做,
|
||||||
// 这样切换单位不用重新联网。
|
// 这样切换单位不用重新联网。
|
||||||
var common = {"lat" => lat, "lon" => lon,
|
var common = {"lat" => lat, "lon" => lon,
|
||||||
@@ -66,6 +67,12 @@ class Fenix8V3Background extends System.ServiceDelegate {
|
|||||||
Communications.makeWebRequest(
|
Communications.makeWebRequest(
|
||||||
"https://api.openweathermap.org/data/2.5/forecast",
|
"https://api.openweathermap.org/data/2.5/forecast",
|
||||||
fc, opts, method(:onForecast));
|
fc, opts, method(:onForecast));
|
||||||
|
// 空气质量走独立接口。它在免费档里是开放的(One Call 才要订阅),
|
||||||
|
// 所以 AQI / PM2.5 / PM10 / CO 这几项不用付费也能有。
|
||||||
|
Communications.makeWebRequest(
|
||||||
|
"https://api.openweathermap.org/data/2.5/air_pollution",
|
||||||
|
{"lat" => lat, "lon" => lon, "appid" => Owm.key()},
|
||||||
|
opts, method(:onAir));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 当前天气的回调。OWM 的 JSON 是嵌套的,逐层取值时每层都要判空 ——
|
// 当前天气的回调。OWM 的 JSON 是嵌套的,逐层取值时每层都要判空 ——
|
||||||
@@ -143,6 +150,25 @@ class Fenix8V3Background extends System.ServiceDelegate {
|
|||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 空气质量的回调。响应形如 { list: [ { main: {aqi}, components: {...} } ] }。
|
||||||
|
function onAir(code as Number, body as Dictionary?) as Void {
|
||||||
|
if (code == 200 && body != null) {
|
||||||
|
var list = body.get("list") as Array?;
|
||||||
|
if (list != null && list.size() > 0) {
|
||||||
|
var e = list[0] as Dictionary;
|
||||||
|
var main = e.get("main") as Dictionary?;
|
||||||
|
if (main != null) { put("aqi", main.get("aqi")); }
|
||||||
|
var comp = e.get("components") as Dictionary?;
|
||||||
|
if (comp != null) {
|
||||||
|
put("pm2_5", comp.get("pm2_5"));
|
||||||
|
put("pm10", comp.get("pm10"));
|
||||||
|
put("co", comp.get("co"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done();
|
||||||
|
}
|
||||||
|
|
||||||
// 距 Unix 纪元的整天数,用来给预报条目分桶。
|
// 距 Unix 纪元的整天数,用来给预报条目分桶。
|
||||||
function dayNumber(unix as Number) as Number {
|
function dayNumber(unix as Number) as Number {
|
||||||
return unix / 86400;
|
return unix / 86400;
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import Fields;
|
|||||||
import Layout;
|
import Layout;
|
||||||
import Icons;
|
import Icons;
|
||||||
import Settings;
|
import Settings;
|
||||||
|
import Comp;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 表盘主体
|
// 表盘主体
|
||||||
@@ -429,6 +430,7 @@ class Fenix8V3View extends WatchUi.WatchFace {
|
|||||||
var ti = Settings.themeIndex(Themes.NAMES.size());
|
var ti = Settings.themeIndex(Themes.NAMES.size());
|
||||||
var ds = System.getDeviceSettings();
|
var ds = System.getDeviceSettings();
|
||||||
var ctx = new Fields.Ctx(ds, Settings.tempUnit());
|
var ctx = new Fields.Ctx(ds, Settings.tempUnit());
|
||||||
|
Comp.beginFrame(); // 让第三方 App 列表这一帧只枚举一次
|
||||||
var info = ctx.info();
|
var info = ctx.info();
|
||||||
var stats = ctx.stats();
|
var stats = ctx.stats();
|
||||||
var level = 0.0f;
|
var level = 0.0f;
|
||||||
|
|||||||
@@ -11,12 +11,14 @@ module FieldTable {
|
|||||||
// 全部字段 id,顺序与 FieldLabels 资源串(逗号分隔的标签表)严格一致 ——
|
// 全部字段 id,顺序与 FieldLabels 资源串(逗号分隔的标签表)严格一致 ——
|
||||||
// Fields.label() 就是靠这个下标去取对应标签的。
|
// Fields.label() 就是靠这个下标去取对应标签的。
|
||||||
const IDS = [
|
const IDS = [
|
||||||
0,860,880,864,865,851,872,852,855,870,856,853,868,858,859,850,869,873,1,14,707,2,
|
0,860,880,864,865,851,872,852,855,870,856,853,868,858,859,850,869,873,861,862,863,
|
||||||
603,150,152,154,151,3,4,5,6,9,10,219,220,211,212,213,214,203,204,200,618,276,12,635,
|
735,1,14,707,2,603,150,152,154,151,3,4,5,6,9,10,219,220,211,212,213,214,203,204,200,
|
||||||
11,623,8,15,281,742,13,278,277,250,251,257,253,255,254,256,252,615,616,733,712,717,
|
828,832,836,840,618,276,12,635,11,623,8,15,281,742,13,278,277,250,251,257,253,255,
|
||||||
700,731,706,732,710,709,708,711,714,715,718,719,720,721,306,639,300,301,302,305,304,
|
254,256,252,615,616,733,712,717,700,731,706,732,710,709,708,711,714,715,718,719,720,
|
||||||
308,307,310,309,312,313,314,315,500,515,503,504,505,507,502,501,506,509,510,511,518,
|
721,306,639,300,301,302,305,304,308,307,310,309,312,313,314,315,612,626,627,628,629,
|
||||||
512,513,532,536,537,530,534,522,535,523,516,517,703,704,705
|
630,631,632,633,634,641,619,620,695,696,697,698,699,500,515,503,504,505,507,502,501,
|
||||||
|
506,509,510,511,518,512,513,532,536,537,530,534,522,535,523,538,539,540,541,542,516,
|
||||||
|
517,703,704,705
|
||||||
];
|
];
|
||||||
|
|
||||||
// 由字段 id 反查它在 IDS 里的下标;找不到返回 0(对应「关闭」)。
|
// 由字段 id 反查它在 IDS 里的下标;找不到返回 0(对应「关闭」)。
|
||||||
|
|||||||
125
source/Fields.mc
125
source/Fields.mc
@@ -15,6 +15,7 @@ import FieldTable;
|
|||||||
import Settings;
|
import Settings;
|
||||||
import Solar;
|
import Solar;
|
||||||
import Owm;
|
import Owm;
|
||||||
|
import Comp;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// 数据字段
|
// 数据字段
|
||||||
@@ -80,6 +81,89 @@ module Fields {
|
|||||||
return Lang.format(mDateFmt, [month(g), g.day.format("%d")]);
|
return Lang.format(mDateFmt, [month(g), g.day.format("%d")]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 按用户填的格式串拼时间/日期。
|
||||||
|
//
|
||||||
|
// 用单字母占位符,因为设置项里能填的长度有限,而且这样中英文都好写:
|
||||||
|
// h 小时(12/24 跟随手表) H 小时补零
|
||||||
|
// m 分钟补零 s 秒补零
|
||||||
|
// a 上午/下午(24 小时制下为空)
|
||||||
|
// D 日 M 月(数字) N 月(名称)
|
||||||
|
// Y 四位年 y 两位年 w 星期
|
||||||
|
// 其它字符原样输出,所以 "D/M" → "10/9","w N D" → "周四 9月 10"。
|
||||||
|
function applyFormat(fmt as String, g as Gregorian.Info, c as Ctx) as String {
|
||||||
|
var out = "";
|
||||||
|
var chars = fmt.toCharArray();
|
||||||
|
for (var i = 0; i < chars.size(); i++) {
|
||||||
|
var ch = chars[i];
|
||||||
|
if (ch == 'h') {
|
||||||
|
var hh = g.hour;
|
||||||
|
if (!c.is24) {
|
||||||
|
if (hh == 0) { hh = 12; } else if (hh > 12) { hh = hh - 12; }
|
||||||
|
}
|
||||||
|
out += hh.format("%d");
|
||||||
|
} else if (ch == 'H') {
|
||||||
|
out += g.hour.format("%02d");
|
||||||
|
} else if (ch == 'm') {
|
||||||
|
out += g.min.format("%02d");
|
||||||
|
} else if (ch == 's') {
|
||||||
|
out += g.sec.format("%02d");
|
||||||
|
} else if (ch == 'a') {
|
||||||
|
out += c.is24 ? "" : meridiem(g);
|
||||||
|
} else if (ch == 'D') {
|
||||||
|
out += g.day.format("%d");
|
||||||
|
} else if (ch == 'M') {
|
||||||
|
out += g.month.format("%d");
|
||||||
|
} else if (ch == 'N') {
|
||||||
|
out += month(g);
|
||||||
|
} else if (ch == 'Y') {
|
||||||
|
out += g.year.format("%d");
|
||||||
|
} else if (ch == 'y') {
|
||||||
|
out += (g.year % 100).format("%02d");
|
||||||
|
} else if (ch == 'w') {
|
||||||
|
out += dow(g);
|
||||||
|
} else {
|
||||||
|
out += ch.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 距目标日期还有几天。目标日期是设置里填的 YYYY-MM-DD 字符串。
|
||||||
|
// 解析失败(没填/格式不对)返回 null,字段显示 "--"。
|
||||||
|
function daysUntil(target as String, g as Gregorian.Info) as Number? {
|
||||||
|
if (target.length() < 8) { return null; }
|
||||||
|
var parts = splitOn(target, '-');
|
||||||
|
if (parts.size() < 3) { return null; }
|
||||||
|
var y = parts[0].toNumber();
|
||||||
|
var mo = parts[1].toNumber();
|
||||||
|
var d = parts[2].toNumber();
|
||||||
|
if (y == null || mo == null || d == null) { return null; }
|
||||||
|
// 都换算成「儒略日式」的绝对天数再相减,省得处理跨月跨年。
|
||||||
|
return absDay(y, mo, d) - absDay(g.year, g.month, g.day);
|
||||||
|
}
|
||||||
|
|
||||||
|
function absDay(y as Number, m as Number, d as Number) as Number {
|
||||||
|
var yy = y;
|
||||||
|
var mm = m;
|
||||||
|
if (mm <= 2) { yy = yy - 1; mm = mm + 12; }
|
||||||
|
var a = yy / 100;
|
||||||
|
var b = 2 - a + a / 4;
|
||||||
|
return (365.25 * (yy + 4716)).toNumber() + (30.6001 * (mm + 1)).toNumber()
|
||||||
|
+ d + b - 1524;
|
||||||
|
}
|
||||||
|
|
||||||
|
function splitOn(str as String, sep as Char) as Array<String> {
|
||||||
|
var out = [] as Array<String>;
|
||||||
|
var cur = "";
|
||||||
|
var chars = str.toCharArray();
|
||||||
|
for (var i = 0; i < chars.size(); i++) {
|
||||||
|
if (chars[i] == sep) { out.add(cur); cur = ""; }
|
||||||
|
else { cur += chars[i].toString(); }
|
||||||
|
}
|
||||||
|
out.add(cur);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
// 英文出 "10",中文出 "10日"。
|
// 英文出 "10",中文出 "10日"。
|
||||||
// 后缀带在本地化的日期格式串里,所以这里把月份传空串即可。
|
// 后缀带在本地化的日期格式串里,所以这里把月份传空串即可。
|
||||||
function dayOnly(g as Gregorian.Info) as String {
|
function dayOnly(g as Gregorian.Info) as String {
|
||||||
@@ -375,6 +459,15 @@ module Fields {
|
|||||||
// view 只在有格子选了秒时才去请求那个回调。
|
// view 只在有格子选了秒时才去请求那个回调。
|
||||||
if (id == 850) { return c.greg.sec.format("%d"); } // 秒
|
if (id == 850) { return c.greg.sec.format("%d"); } // 秒
|
||||||
if (id == 869) { return c.greg.sec.format("%02d"); } // 秒 (前导零)
|
if (id == 869) { return c.greg.sec.format("%02d"); } // 秒 (前导零)
|
||||||
|
// 自定义格式:格式串来自设置,占位符说明见 applyFormat
|
||||||
|
if (id == 861) { return applyFormat(Settings.text("TimeFmt"), c.greg, c); }
|
||||||
|
if (id == 862) { return applyFormat(Settings.text("DateFmt1"), c.greg, c); }
|
||||||
|
if (id == 863) { return applyFormat(Settings.text("DateFmt2"), c.greg, c); }
|
||||||
|
if (id == 735) { // 事件倒计时
|
||||||
|
var left = daysUntil(Settings.text("CountdownDate"), c.greg);
|
||||||
|
if (left == null) { return DASH; }
|
||||||
|
return left.format("%d");
|
||||||
|
} // 秒 (前导零)
|
||||||
if (id == 870) { return dow(c.greg); } // 星期简写
|
if (id == 870) { return dow(c.greg); } // 星期简写
|
||||||
if (id == 856) { return dow(c.greg); } // 星期全称
|
if (id == 856) { return dow(c.greg); } // 星期全称
|
||||||
if (id == 853) { return month(c.greg); } // 月份
|
if (id == 853) { return month(c.greg); } // 月份
|
||||||
@@ -450,6 +543,14 @@ module Fields {
|
|||||||
return (id == 213) ? dist(v, c) : rounded(v);
|
return (id == 213) ? dist(v, c) : rounded(v);
|
||||||
}
|
}
|
||||||
// 近 7 天步数 / 近 7 天卡路里 / 近 7 天距离 / 近 7 天楼层 / 近 7 天活动分钟
|
// 近 7 天步数 / 近 7 天卡路里 / 近 7 天距离 / 近 7 天楼层 / 近 7 天活动分钟
|
||||||
|
if (id == 828 || id == 832 || id == 836 || id == 840) {
|
||||||
|
// 近 28 天。getHistory 能返回多少天由固件决定,sumHistory 内部会按
|
||||||
|
// 实际条数截断,所以拿不到 28 天时是「有多少算多少」而不是报错。
|
||||||
|
var w28 = (id == 828) ? 0 : ((id == 832) ? 1 : ((id == 836) ? 2 : 3));
|
||||||
|
var v28 = sumHistory(c, w28, 27);
|
||||||
|
if (v28 == null) { return DASH; }
|
||||||
|
return (id == 836) ? dist(v28, c) : rounded(v28);
|
||||||
|
}
|
||||||
if (id == 220 || id == 212 || id == 214 || id == 204 || id == 200) {
|
if (id == 220 || id == 212 || id == 214 || id == 204 || id == 200) {
|
||||||
var which = (id == 220) ? 0 : ((id == 212) ? 1
|
var which = (id == 220) ? 0 : ((id == 212) ? 1
|
||||||
: ((id == 214) ? 2 : ((id == 204) ? 3 : 4)));
|
: ((id == 214) ? 2 : ((id == 204) ? 3 : 4)));
|
||||||
@@ -760,6 +861,18 @@ module Fields {
|
|||||||
if (id == 523) { // OWM 后日高低温
|
if (id == 523) { // OWM 后日高低温
|
||||||
return temp(Owm.get("hi2"), c) + "/" + temp(Owm.get("lo2"), c);
|
return temp(Owm.get("hi2"), c) + "/" + temp(Owm.get("lo2"), c);
|
||||||
}
|
}
|
||||||
|
if (id == 538 || id == 539) { // 空气质量指数 / 描述
|
||||||
|
var aqi = Owm.get("aqi");
|
||||||
|
if (aqi == null) { return DASH; }
|
||||||
|
if (id == 538) { return num(aqi); }
|
||||||
|
// OWM 的 AQI 是 1..5 的等级,不是欧美常见的 0..500 数值。
|
||||||
|
var names = ["", "优", "良", "中", "差", "很差"];
|
||||||
|
var k = aqi.toNumber();
|
||||||
|
return (k >= 1 && k <= 5) ? names[k] : DASH;
|
||||||
|
}
|
||||||
|
if (id == 540) { return oneDp(Owm.get("pm2_5")); } // PM2.5
|
||||||
|
if (id == 541) { return oneDp(Owm.get("pm10")); } // PM10
|
||||||
|
if (id == 542) { return oneDp(Owm.get("co")); } // 一氧化碳
|
||||||
if (id == 516) { return str(Owm.get("city")); } // OWM 城市
|
if (id == 516) { return str(Owm.get("city")); } // OWM 城市
|
||||||
if (id == 517) { // OWM 更新时间
|
if (id == 517) { // OWM 更新时间
|
||||||
var dt = Owm.get("dt");
|
var dt = Owm.get("dt");
|
||||||
@@ -768,10 +881,21 @@ module Fields {
|
|||||||
return DASH;
|
return DASH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function oneDp(v) as String {
|
||||||
|
return v == null ? DASH : v.toFloat().format("%.1f");
|
||||||
|
}
|
||||||
|
|
||||||
function str(v) as String {
|
function str(v) as String {
|
||||||
return v == null ? DASH : v.toString();
|
return v == null ? DASH : v.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---- 系统 Complication ----
|
||||||
|
// 日历、训练状态、完赛/配速预测、按运动的周距离、以及第三方 App 发布的
|
||||||
|
// 复杂功能。全部由 Comp.mc 经 Toybox.Complications 取得。
|
||||||
|
function complication(id as Number, c as Ctx) as String? {
|
||||||
|
return Comp.value(id);
|
||||||
|
}
|
||||||
|
|
||||||
// ---- 自定义文字 ----
|
// ---- 自定义文字 ----
|
||||||
// 用户在设置里自己填的三段文字。
|
// 用户在设置里自己填的三段文字。
|
||||||
function custom(id as Number, c as Ctx) as String? {
|
function custom(id as Number, c as Ctx) as String? {
|
||||||
@@ -791,6 +915,7 @@ module Fields {
|
|||||||
if (v == null) { v = system(id, c); }
|
if (v == null) { v = system(id, c); }
|
||||||
if (v == null) { v = environment(id, c); }
|
if (v == null) { v = environment(id, c); }
|
||||||
if (v == null) { v = weather(id, c); }
|
if (v == null) { v = weather(id, c); }
|
||||||
|
if (v == null) { v = complication(id, c); }
|
||||||
if (v == null) { v = owm(id, c); }
|
if (v == null) { v = owm(id, c); }
|
||||||
if (v == null) { v = custom(id, c); }
|
if (v == null) { v = custom(id, c); }
|
||||||
return v == null ? "" : v;
|
return v == null ? "" : v;
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ FIELDS = [
|
|||||||
(850, "Seconds", "Seconds", "秒", "SEC", "秒"),
|
(850, "Seconds", "Seconds", "秒", "SEC", "秒"),
|
||||||
(869, "Seconds0", "Seconds (09)", "秒 (前导零)", "SEC", "秒"),
|
(869, "Seconds0", "Seconds (09)", "秒 (前导零)", "SEC", "秒"),
|
||||||
(873, "WeekCal", "Week Number", "周数", "WEEK", "周"),
|
(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 -------------------------------------------------------
|
# ---- activity -------------------------------------------------------
|
||||||
(1, "Steps", "Steps", "步数", "STEP", "步数"),
|
(1, "Steps", "Steps", "步数", "STEP", "步数"),
|
||||||
@@ -73,6 +77,10 @@ FIELDS = [
|
|||||||
(203, "FloorsWeek", "Floors (Week to Date)", "本周楼层", "WEEK", "周楼层"),
|
(203, "FloorsWeek", "Floors (Week to Date)", "本周楼层", "WEEK", "周楼层"),
|
||||||
(204, "Floors7d", "Floors (Last 7 Days)", "近 7 天楼层", "7D", "7天"),
|
(204, "Floors7d", "Floors (Last 7 Days)", "近 7 天楼层", "7D", "7天"),
|
||||||
(200, "ActiveMin7d", "Active Minutes (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 -----------------------------------------------------------
|
# ---- body -----------------------------------------------------------
|
||||||
(618, "HeartRate", "Heart Rate", "心率", "HR", "心率"),
|
(618, "HeartRate", "Heart Rate", "心率", "HR", "心率"),
|
||||||
@@ -137,6 +145,27 @@ FIELDS = [
|
|||||||
(314, "Visibility", "Visibility", "能见度", "VIS", "能见度"),
|
(314, "Visibility", "Visibility", "能见度", "VIS", "能见度"),
|
||||||
(315, "DewPoint", "Dew Point", "露点", "DEW", "露点"),
|
(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 -------------------------------------------------
|
# ---- OpenWeatherMap -------------------------------------------------
|
||||||
# Fetched by the background service; see source/Owm.mc.
|
# Fetched by the background service; see source/Owm.mc.
|
||||||
(500, "OwmTemp", "OWM Temperature", "OWM 气温", "TEMP", "气温"),
|
(500, "OwmTemp", "OWM Temperature", "OWM 气温", "TEMP", "气温"),
|
||||||
@@ -162,6 +191,11 @@ FIELDS = [
|
|||||||
(522, "OwmMinMaxTmrw", "OWM Min/Max Tomorrow", "OWM 明日高低温", "TMRW", "明日"),
|
(522, "OwmMinMaxTmrw", "OWM Min/Max Tomorrow", "OWM 明日高低温", "TMRW", "明日"),
|
||||||
(535, "OwmDayAfter", "OWM Temp Day After", "OWM 后日气温", "D+2", "后日"),
|
(535, "OwmDayAfter", "OWM Temp Day After", "OWM 后日气温", "D+2", "后日"),
|
||||||
(523, "OwmMinMaxD2", "OWM Min/Max 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", "城市"),
|
(516, "OwmCity", "OWM City Name", "OWM 城市", "CITY", "城市"),
|
||||||
(517, "OwmUpdated", "OWM Update Time", "OWM 更新时间", "OWM", "更新"),
|
(517, "OwmUpdated", "OWM Update Time", "OWM 更新时间", "OWM", "更新"),
|
||||||
|
|
||||||
@@ -198,6 +232,22 @@ OTHER_SETTINGS = """
|
|||||||
<settingConfig type="numeric" min="-720" max="840"/>
|
<settingConfig type="numeric" min="-720" max="840"/>
|
||||||
</setting>
|
</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">
|
<setting propertyKey="@Properties.OwmKey" title="@Strings.SettingOwmKey">
|
||||||
<settingConfig type="alphaNumeric" maxLength="40"/>
|
<settingConfig type="alphaNumeric" maxLength="40"/>
|
||||||
</setting>
|
</setting>
|
||||||
|
|||||||
Reference in New Issue
Block a user