Files
kindle-calendar/dash/docs/kindle-city-location-plan.zh.md
2026-03-18 13:35:19 +08:00

221 lines
6.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Kindle 市级位置方案
## 背景
当前仓库里的天气位置来源仍在 `calendar/` 前端:
- [calendar/src/lib/weather.ts](/Users/gavin/kindle-dash/calendar/src/lib/weather.ts) 会优先尝试 `navigator.geolocation`
- 失败时回退到固定默认值 `杭州`
这条路径不适合当前 Kindle 运行架构,原因有两个:
1. Kindle 实机显示的不是一个在设备上实时运行的天气网页,而是先在别处渲染,再同步为背景图。
2. 如果由 Web 服务器代查 IP 位置,拿到的是服务器公网 IP对应的是服务器所在城市不是 Kindle 所在城市。
本方案的目标是:
- 位置精度只要求到“市”颗粒度
- 位置来源应尽量接近 Kindle 当前网络出口
- 在 SSH 暂时不可用的情况下,先把方案文档明确下来,后续恢复 SSH 后再实现
## 结论
浏览器网页定位不应继续作为主路径。
推荐改成:
1. Kindle 侧自己请求 GeoIP 接口,获取当前公网 IP 对应的城市、经纬度和时区
2. 把结果缓存到本地
3. 天气与相关展示统一读取这份缓存
4. 当 GeoIP 不可用或结果异常时,回退到 Kindle 侧固定配置的 `city/lat/lon/timezone`
这是一个“市级近似定位”方案,不是 GPS 精确定位方案。
## 为什么 Kindle 侧 GeoIP 可行
GeoIP 的前提是“由目标设备自己发请求”。
对当前项目,正确的请求路径应该是:
```text
Kindle -> GeoIP 服务 -> 返回 city / lat / lon / timezone
```
而不是:
```text
Kindle -> 你的 Web 服务 -> Web 服务代查 GeoIP
```
后一种方式只会得到 Web 服务所在机房或服务器出口的位置。
如果 Kindle 走家庭 Wi-Fi且只要求“市级”颗粒度GeoIP 通常够用。
如果 Kindle 走手机热点、VPN、代理、企业网络或运营商 NAT结果可能偏到邻近城市必须接受这种误差。
## 目标能力
实现后需要具备以下能力:
1. Kindle 联网后,能够自己获取当前网络出口对应的城市信息
2. 获取结果会写入本地缓存
3. 断网时仍可继续使用上次缓存
4. GeoIP 失败时可回退到固定配置
5. 只需要市级位置,不追求街道级精度
## 推荐数据模型
建议在 Kindle 侧维护一份位置缓存文件。
路径建议:
```text
/mnt/us/dashboard/local/state/location.env
```
字段建议:
```text
LOCATION_SOURCE=geoip
LOCATION_CITY=杭州
LOCATION_LAT=30.274084
LOCATION_LON=120.155070
LOCATION_TIMEZONE=Asia/Shanghai
LOCATION_UPDATED_AT=2026-03-17T10:00:00+08:00
```
同时保留一份固定兜底配置,例如:
```text
LOCATION_FALLBACK_CITY=杭州
LOCATION_FALLBACK_LAT=30.274084
LOCATION_FALLBACK_LON=120.155070
LOCATION_FALLBACK_TIMEZONE=Asia/Shanghai
```
## 运行时脚本设计
建议新增 Kindle 侧脚本:
```text
dash/src/local/location-sync.sh
```
职责:
1. 检查网络是否可用
2. 由 Kindle 自己请求 GeoIP 接口
3. 解析响应中的城市、经纬度、时区
4. 校验字段是否完整
5. 写入本地缓存
6. 失败时保留旧缓存,不要清空已有结果
建议同时新增一个只负责读取并导出环境变量的脚本,例如:
```text
dash/src/local/location-env.sh
```
职责:
1. 优先读取新鲜的 GeoIP 缓存
2. 没有新鲜缓存时读取旧缓存
3. 缓存不存在或无效时回退到固定配置
4. 对外输出统一的 `LOCATION_CITY/LAT/LON/TIMEZONE`
## 刷新策略
位置不需要高频刷新。
建议策略:
1. 启动 dashboard 且确认联网后,首次同步一次位置
2. 每 12 小时或 24 小时刷新一次
3. 手动切换主题时不强制刷新位置
4. 天气刷新与位置刷新解耦
5. 位置同步失败时继续使用现有缓存
## 与现有架构的衔接方式
当前项目是“背景图 + Kindle 本地时钟覆盖”的架构不是“Kindle 上实时跑完整天气网页”的架构。
因此接入位置数据时,有两条可选路径。
### 路径 A最小改动路径
保留当前背景图生成方式,但让背景图生成时显式读取 Kindle 侧缓存导出的城市与经纬度。
优点:
- 改动面相对小
- 仍可复用现有天气卡片布局与导出流程
缺点:
- 需要重新梳理“背景图生成端”如何拿到 Kindle 缓存
- 如果背景仍在 Mac 侧导出,就必须把 Kindle 缓存同步回 Mac 或转成请求参数
### 路径 B更符合现状的运行时路径
把“城市文本、天气数据”也逐步下沉到 Kindle 运行时,和本地时钟一样由设备端控制。
优点:
- 位置与天气都由 Kindle 自己决定
- 不会再混入 Mac 浏览器位置或服务器 IP 位置
缺点:
- 改动更大
- 需要重新设计天气卡的本地渲染方式
## 当前推荐
短期推荐先做:
1. Kindle 侧 GeoIP 获取
2. 本地缓存
3. 固定配置兜底
等 SSH 恢复后,再决定位置数据如何喂给天气展示层。
也就是说,先把“位置来源”稳定下来,再改“展示方式”。
## 实施顺序
建议按下面顺序落地:
1. 新增 `location-sync.sh`
2. 新增 `location-env.sh`
3. 在 Kindle 运行时目录中引入固定兜底配置
4. 在主循环启动阶段接入位置缓存刷新
5. 让天气读取逻辑改为优先使用 Kindle 侧位置缓存
6. 最后补文档和手动刷新命令
## 验收标准
实现完成后,至少应满足以下验收条件:
1. Kindle 联网后可生成位置缓存文件
2. 缓存中至少包含 `city/lat/lon/timezone`
3. 断网后仍能继续使用旧缓存
4. GeoIP 失败时会稳定回退到固定城市
5. 显示出的城市与 Kindle 当前所在城市大体一致
## 注意事项
1. GeoIP 只能提供近似位置,不要当作精确定位
2. 手机热点、VPN、代理、企业网络都会降低城市准确率
3. 城市级结果可以用于天气展示,但不适合做严格地理判断
4. 任何实现都必须保证“失败不影响 dashboard 主循环”
## 现阶段状态
当前仅完成方案设计,尚未开始代码实现。
直接原因是:
- 目前 SSH 还未恢复
- 设备侧脚本还不能方便地下发、调试和验证
后续等 SSH 恢复后,再按本方案分步实施。