first commit
This commit is contained in:
449
dash/docs/layered-clock-plan.zh.md
Normal file
449
dash/docs/layered-clock-plan.zh.md
Normal file
@@ -0,0 +1,449 @@
|
||||
# Kindle Dashboard 分层时钟方案
|
||||
|
||||
## 1. 背景
|
||||
|
||||
当前仓库里有两部分:
|
||||
|
||||
- `calendar/`:负责渲染仪表盘网页与导出背景素材
|
||||
- `dash/`:运行在 Kindle 上,负责拉图、刷屏、休眠与唤醒
|
||||
|
||||
最新设计稿来自 Figma:
|
||||
|
||||
- 文件:`calendar`
|
||||
- 节点:`6:2`
|
||||
- 链接:`https://www.figma.com/design/3bXFNM5nM6mCq0TpL3nPYK/calendar?node-id=6-2&m=dev`
|
||||
|
||||
该节点 annotation 已明确:
|
||||
|
||||
- `阳历当天`
|
||||
- `星期`
|
||||
- `农历日`
|
||||
- `时钟区域`
|
||||
- `日历`
|
||||
- `天气预报卡片`
|
||||
- `书摘卡片`
|
||||
|
||||
本方案基于这些约束,采用“低频背景 + 本地时钟”的拆分方式:
|
||||
|
||||
- `calendar/` 每 `2 小时` 生成一次背景图
|
||||
- 背景图直接写到:
|
||||
- `/Users/gavin/kindle-dash/calendar/dist/kindlebg.png`
|
||||
- Kindle 通过固定 HTTPS 地址拉取背景图:
|
||||
- `https://shell.biboer.cn:20001/kindlebg.png`
|
||||
- Kindle 端每分钟`不联网`
|
||||
- Kindle 端只在本地重画时钟区域
|
||||
|
||||
## 2. 目标
|
||||
|
||||
这次改造不是单纯调样式,而是把页面拆成两类刷新节奏完全不同的素材:
|
||||
|
||||
1. 低频背景层
|
||||
2. 高频时钟层
|
||||
|
||||
目标收益:
|
||||
|
||||
- 背景内容不再分钟级刷新
|
||||
- 分钟级变化只限制在时钟区域
|
||||
- 降低 Wi-Fi 唤醒次数
|
||||
- 降低全屏刷新频率
|
||||
- 减少墨水屏闪烁与残影
|
||||
|
||||
## 3. 分层边界
|
||||
|
||||
### 3.1 全屏背景层
|
||||
|
||||
背景层文件名固定为:
|
||||
|
||||
- `kindlebg.png`
|
||||
|
||||
背景层包含:
|
||||
|
||||
- 整体外层容器、圆角、阴影、背景渐变
|
||||
- 日历卡片中的:
|
||||
- 阳历当天数字
|
||||
- 星期
|
||||
- 农历日
|
||||
- 下方月历区域
|
||||
- 天气卡片全部内容
|
||||
- 书摘卡片全部内容
|
||||
|
||||
背景层**不包含**:
|
||||
|
||||
- 时钟表盘主体
|
||||
- 时钟刻度
|
||||
- 时针
|
||||
- 分针
|
||||
- 中心圆点
|
||||
|
||||
也就是说,背景图在时钟区域只保留布局占位,不直接承载任何分钟级内容。
|
||||
|
||||
### 3.2 静态表盘 patch
|
||||
|
||||
静态表盘 patch 为一个独立本地素材:
|
||||
|
||||
- `clock-face.png`
|
||||
|
||||
该素材包含:
|
||||
|
||||
- 圆形表盘主体
|
||||
- 刻度
|
||||
- 中心底座或中心圆盘
|
||||
|
||||
建议尺寸直接对齐 Figma 时钟区域:
|
||||
|
||||
- 节点:`24:74`
|
||||
- 设计尺寸:`220 x 220`
|
||||
|
||||
这张图应当保存在 Kindle 本地,例如:
|
||||
|
||||
- `/mnt/us/dashboard/assets/clock-face.png`
|
||||
|
||||
它不需要分钟级联网拉取,只需要在部署时同步到设备,或者在更换设计稿时重新同步。
|
||||
|
||||
### 3.3 指针层
|
||||
|
||||
高频变化层只包含:
|
||||
|
||||
- 时针
|
||||
- 分针
|
||||
|
||||
这里不建议包含秒针:
|
||||
|
||||
- 墨水屏收益低
|
||||
- 刷新频率会显著上升
|
||||
- 更容易产生残影
|
||||
|
||||
由于当前 `dash/` 链路本质是 `eips` 刷图,不是 SVG/Canvas 实时渲染,所以推荐使用`分层素材方案`:
|
||||
|
||||
- `minute-hand/00.png` 到 `minute-hand/59.png`
|
||||
- `hour-hand/000.png` 到 `hour-hand/719.png`
|
||||
|
||||
说明:
|
||||
|
||||
- 分针每分钟一个角度,共 `60` 张
|
||||
- 时针如果要做到真正随分钟连续移动,需要 `12 * 60 = 720` 张
|
||||
- 这些都是小尺寸 patch,不是整屏图,体积可控
|
||||
|
||||
如果后续确认 Kindle 端存在稳定的本地绘线工具,再考虑把指针改成算法绘制;当前版本不依赖这个前提。
|
||||
|
||||
## 4. 为什么不能只把表盘放进整页背景
|
||||
|
||||
这个问题必须单独说明。
|
||||
|
||||
如果:
|
||||
|
||||
- 表盘主体和刻度只存在于 `kindlebg.png`
|
||||
- Kindle 每分钟只覆盖新的时针/分针
|
||||
|
||||
那么上一分钟留下的旧指针就无法被干净擦除。
|
||||
|
||||
因此 Kindle 端每分钟的正确流程应该是:
|
||||
|
||||
1. 先重画一张本地 `clock-face.png`
|
||||
2. 再叠加新的时针素材
|
||||
3. 再叠加新的分针素材
|
||||
|
||||
这等价于“先擦除,再重画”,并且整个流程不依赖网络。
|
||||
|
||||
所以本方案不是“背景图 + 两根指针”两层,而是:
|
||||
|
||||
1. `kindlebg.png`:全屏低频背景
|
||||
2. `clock-face.png`:本地静态表盘 patch
|
||||
3. `hour-hand/*.png + minute-hand/*.png`:本地高频指针素材
|
||||
|
||||
## 5. 数据刷新策略
|
||||
|
||||
### 5.1 背景层刷新
|
||||
|
||||
背景层刷新触发条件:
|
||||
|
||||
- 每 `2 小时` 一次
|
||||
- 跨天时立即刷新一次
|
||||
- 天气接口异常恢复后可补刷一次
|
||||
|
||||
推荐调度:
|
||||
|
||||
- `00:00 / 02:00 / 04:00 / ... / 22:00`
|
||||
|
||||
背景层刷新输出:
|
||||
|
||||
- `/Users/gavin/kindle-dash/calendar/dist/kindlebg.png`
|
||||
|
||||
背景层对 Kindle 的访问地址固定为:
|
||||
|
||||
- `https://shell.biboer.cn:20001/kindlebg.png`
|
||||
|
||||
### 5.2 静态表盘 patch 刷新
|
||||
|
||||
静态表盘 patch 不参加分钟级调度。
|
||||
|
||||
建议刷新方式:
|
||||
|
||||
- 随部署同步一次
|
||||
- Figma 设计或尺寸变化时重新导出并同步
|
||||
|
||||
### 5.3 指针层刷新
|
||||
|
||||
指针层刷新触发条件:
|
||||
|
||||
- 每分钟一次
|
||||
|
||||
指针层数据只依赖 Kindle 本地时间:
|
||||
|
||||
- 小时
|
||||
- 分钟
|
||||
|
||||
分钟刷新不需要联网。
|
||||
|
||||
## 6. 网页渲染模式设计
|
||||
|
||||
为了让 `calendar/` 稳定产出背景与表盘素材,建议支持下面 3 种模式。
|
||||
|
||||
### 6.1 `full`
|
||||
|
||||
用途:
|
||||
|
||||
- 本地开发预览
|
||||
- 对照 Figma 联调
|
||||
|
||||
输出内容:
|
||||
|
||||
- 背景层
|
||||
- 表盘
|
||||
- 指针预览
|
||||
|
||||
### 6.2 `background`
|
||||
|
||||
用途:
|
||||
|
||||
- 生成 `kindlebg.png`
|
||||
|
||||
输出内容:
|
||||
|
||||
- 只渲染背景层
|
||||
- 时钟区域保留占位,但不绘制表盘与指针
|
||||
|
||||
### 6.3 `clock-face`
|
||||
|
||||
用途:
|
||||
|
||||
- 生成静态表盘 patch
|
||||
|
||||
输出内容:
|
||||
|
||||
- 只渲染表盘主体、刻度和中心底座
|
||||
- 不绘制时针、分针
|
||||
|
||||
### 6.4 URL 约定
|
||||
|
||||
建议页面支持如下参数:
|
||||
|
||||
```text
|
||||
/?mode=full
|
||||
/?mode=background
|
||||
/?mode=clock-face
|
||||
```
|
||||
|
||||
## 7. 产物约定
|
||||
|
||||
推荐最终产出这几类文件:
|
||||
|
||||
```text
|
||||
calendar/dist/kindlebg.png
|
||||
calendar/dist/dashboard-manifest.json
|
||||
|
||||
kindle local:
|
||||
/mnt/us/dashboard/assets/clock-face.png
|
||||
/mnt/us/dashboard/assets/hour-hand/000.png ... 719.png
|
||||
/mnt/us/dashboard/assets/minute-hand/00.png ... 59.png
|
||||
```
|
||||
|
||||
`manifest` 建议至少包含这些字段:
|
||||
|
||||
```json
|
||||
{
|
||||
"background": {
|
||||
"path": "kindlebg.png",
|
||||
"url": "https://shell.biboer.cn:20001/kindlebg.png",
|
||||
"updatedAt": "2026-03-15T10:00:00+08:00",
|
||||
"refreshIntervalMinutes": 120
|
||||
},
|
||||
"clockRegion": {
|
||||
"x": 313,
|
||||
"y": 0,
|
||||
"width": 220,
|
||||
"height": 220
|
||||
},
|
||||
"clockFace": {
|
||||
"path": "clock-face.png",
|
||||
"managedOnKindle": true
|
||||
},
|
||||
"clockHands": {
|
||||
"hourPattern": "assets/hour-hand/%03d.png",
|
||||
"minutePattern": "assets/minute-hand/%02d.png",
|
||||
"refreshIntervalMinutes": 1,
|
||||
"networkRequired": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- `x/y/width/height` 先按设计稿记录
|
||||
- 真正接入 Kindle 时,要换算成最终截图分辨率下的实际像素值
|
||||
|
||||
## 8. Kindle 侧刷新策略
|
||||
|
||||
### 8.1 已确认的前提
|
||||
|
||||
`eips` 支持把 PNG/JPG 绘制到指定坐标,参数包含:
|
||||
|
||||
- `-g`
|
||||
- `-x`
|
||||
- `-y`
|
||||
- `-f`
|
||||
|
||||
MobileRead Wiki 明确写了:
|
||||
|
||||
- `eips -g|-b image_path [-w waveform -f -x xpos -y ypos -v]`
|
||||
- `-x` 与 `-y` 以像素为单位
|
||||
来源:<https://wiki.mobileread.com/wiki/Eips>
|
||||
|
||||
因此,对 Kindle Voyage 而言,“在固定时钟区域重画小图”这个前提是成立的。
|
||||
|
||||
### 8.2 推荐流程
|
||||
|
||||
#### 启动或背景刷新时
|
||||
|
||||
1. 通过 HTTPS 拉取:
|
||||
- `https://shell.biboer.cn:20001/kindlebg.png`
|
||||
2. 保存为本地背景缓存
|
||||
3. 使用全屏刷新显示背景图
|
||||
4. 在时钟区域重画一次:
|
||||
- `clock-face.png`
|
||||
- 当前时针
|
||||
- 当前分针
|
||||
|
||||
#### 每分钟刷新时
|
||||
|
||||
1. 读取 Kindle 本机时间
|
||||
2. 计算:
|
||||
- `minute_index = 00..59`
|
||||
- `hour_index = ((hour % 12) * 60 + minute) = 000..719`
|
||||
3. 在固定坐标先画:
|
||||
- `clock-face.png`
|
||||
4. 再画:
|
||||
- `hour-hand/<hour_index>.png`
|
||||
5. 再画:
|
||||
- `minute-hand/<minute_index>.png`
|
||||
6. 默认做局部/普通刷新
|
||||
7. 每 `10` 到 `15` 分钟对时钟区域补一次全刷,清理残影
|
||||
|
||||
### 8.3 功耗模型
|
||||
|
||||
这套方式的功耗来源拆成两类:
|
||||
|
||||
- 背景刷新:
|
||||
- 每 2 小时联网一次
|
||||
- 全屏刷新一次
|
||||
- 时钟刷新:
|
||||
- 每分钟本地刷一次小区域
|
||||
- 不联网
|
||||
|
||||
相比“每分钟拉一张整屏背景图”,这会明显省电。
|
||||
|
||||
## 9. 代码改造建议
|
||||
|
||||
### 9.1 `calendar/`
|
||||
|
||||
建议改造点:
|
||||
|
||||
- 新增 `mode=background`
|
||||
- 新增 `mode=clock-face`
|
||||
- 时钟区域从日历/天气/书摘中完全拆开
|
||||
- 增加一个定时生成任务,每 2 小时把背景图写到:
|
||||
- `/Users/gavin/kindle-dash/calendar/dist/kindlebg.png`
|
||||
- 生成 `dashboard-manifest.json`
|
||||
|
||||
### 9.2 `dash/`
|
||||
|
||||
建议改造点:
|
||||
|
||||
- `dash/src/local/fetch-dashboard.sh`
|
||||
- 改成只拉取 `kindlebg.png`
|
||||
- `dash/src/dash.sh`
|
||||
- 从“单一刷新循环”改为“背景刷新 + 本地时钟刷新”双节奏
|
||||
- 新增例如:
|
||||
- `dash/src/local/render-clock.sh`
|
||||
- `dash/src/local/render-clock-face.sh`
|
||||
- `dash/src/local/clock-index.sh`
|
||||
|
||||
推荐新增配置项:
|
||||
|
||||
```sh
|
||||
export BACKGROUND_URL="https://shell.biboer.cn:20001/kindlebg.png"
|
||||
export BACKGROUND_REFRESH_SCHEDULE="0 */2 * * *"
|
||||
export CLOCK_REGION_X=313
|
||||
export CLOCK_REGION_Y=0
|
||||
export CLOCK_REGION_WIDTH=220
|
||||
export CLOCK_REGION_HEIGHT=220
|
||||
export CLOCK_FULL_REFRESH_INTERVAL_MINUTES=15
|
||||
```
|
||||
|
||||
## 10. 实施顺序
|
||||
|
||||
建议按下面顺序落地,避免一次改太多导致链路难排查。
|
||||
|
||||
### 阶段 1:`calendar/` 分层输出
|
||||
|
||||
目标:
|
||||
|
||||
- `full/background/clock-face` 三种模式跑通
|
||||
- 每 2 小时把背景图写到 `calendar/dist/kindlebg.png`
|
||||
|
||||
输出:
|
||||
|
||||
- 浏览器可预览
|
||||
- `kindlebg.png` 可被 nginx 直接访问
|
||||
|
||||
### 阶段 2:时钟静态素材准备
|
||||
|
||||
目标:
|
||||
|
||||
- 产出 `clock-face.png`
|
||||
- 产出 `hour-hand` 与 `minute-hand` 素材库
|
||||
|
||||
输出:
|
||||
|
||||
- Kindle 本地时钟素材目录结构确定
|
||||
|
||||
### 阶段 3:Kindle 本地分钟时钟
|
||||
|
||||
目标:
|
||||
|
||||
- Kindle 每分钟本地重画时钟
|
||||
- 不联网
|
||||
|
||||
输出:
|
||||
|
||||
- 背景低频更新 + 时钟本地高频更新的完整链路
|
||||
|
||||
## 11. 推荐结论
|
||||
|
||||
当前最稳妥的推进顺序是:
|
||||
|
||||
1. 先让 `calendar/` 每 2 小时稳定生成:
|
||||
- `/Users/gavin/kindle-dash/calendar/dist/kindlebg.png`
|
||||
2. 再让 Kindle 只从:
|
||||
- `https://shell.biboer.cn:20001/kindlebg.png`
|
||||
拉背景图
|
||||
3. 时钟区域完全本地化:
|
||||
- 本地 `clock-face.png`
|
||||
- 本地 `hour-hand/*.png`
|
||||
- 本地 `minute-hand/*.png`
|
||||
4. 分钟刷新时:
|
||||
- 先重画表盘
|
||||
- 再重画时针
|
||||
- 再重画分针
|
||||
|
||||
也就是说,**背景是远端低频资源,时钟是本地高频资源,二者不要混在同一个刷新链路里**。
|
||||
Reference in New Issue
Block a user