Files
eink-push/CLAUDE.md
2026-06-29 09:43:20 +08:00

48 lines
4.2 KiB
Markdown
Raw 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.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## 项目定位
`eink-push` 是 JM monorepo 中一个**独立的 Python 工具**,与其余 Java/Vue 子项目技术栈无关,不受父级 CLAUDE.md 的 jm-cloud/uniapp/admin 开发约束。
作用把橘喵今日经营、近30天趋势、日期与天气合成为一张 **400×300 纯黑白1bit** PNG推送到 Zectrix 极趣云墨水屏设备(`zectrix-s3-epaper-4.2`)。纯 Python + Pillow**无浏览器依赖**,适合 cron 定时运行。
## 命令
```bash
pip install -r requirements.txt # 仅 Pillow>=10.0urllib 用标准库
python3 main.py # 取数据 → 渲染 → 推送(设备取列表第一个)
python3 main.py --render-only # 只渲染到 output/dashboard.png不推送本地调试渲染时用这个
# 环境变量覆盖配置(见 config.py
ZECTRIX_API_KEY=zt_xxx ZECTRIX_DEVICE_ID=AA:BB:CC:DD:EE:FF python3 main.py
```
无测试、无 lint。调试渲染效果就跑 `--render-only``output/dashboard.png`
## 架构(数据 → 渲染 → 推送 三层)
`main.py` 串联三层,各层职责单一、低耦合:
- **`data.py`** — 唯一数据入口 `get_dashboard_data()`,返回固定结构的 dict。日期/时间用真实系统时间;橘喵今日经营+趋势由 `_mao()``jm_api`、天气由 `_weather()``weather_api`(和风,定位南京·秦淮)拉真实数据,**任何接口异常都回退占位 `"--"`,不回退 mock**。改数据保持返回结构不变即可renderer 依赖其 key尤其 `mao.trend.series` 每条须带 `style`;环比/同比 `(direction, text)`direction 为 `None` 时不画涨跌三角)。
- **`jm_api.py`** — jm-devops 后端统计接口客户端,**免鉴权 GET**`/system/statistics/realtime``/recent-days?days=`)。注:早期曾实现登录+RSA/AES 加密+验证码 OCR后改为后端直接放开这两个接口故已全部删除——若后端再次收紧鉴权参考 jm-devops 的 `src/utils/{crypto,jsencrypt,request}.ts` 复刻。
- **`weather_api.py`** — 和风天气QWeather客户端。用**用户专属 API Host**`QWEATHER_HOST`+ `X-QW-Api-Key` 头鉴权;响应 **gzip 压缩**(按 magic number 手动解压)、返回 `code` 为**字符串**。`get_now()` 取实时(`now.text` 中文天气 / `now.temp``get_today()``/3d``daily[0]` 今日温区。`QWEATHER_HOST`/`QWEATHER_KEY` 未配置时直接抛错→天气区显示 `"--"`
- **`renderer.py`** — `DashboardRenderer.render(data)` 返回 PIL `'L'` 模式纯 0/255 图;`render_to_file()` 落盘。布局硬编码为三区:大时钟+日期 / 天气 / 橘喵三列 / 近30天趋势折线图。趋势线用 `_styled_polyline()` 按 solid/dashed/dotted 区分(设备无颜色),各指标按自身极值独立归一化(故只看趋势形状、不可横向比绝对值)。
- **`pusher.py`** — `push_image()` 走 Zectrix API`POST /devices/{id}/display/image`,手写 multipart`resolve_device_id()``config.DEVICE_ID` 为空时自动取设备列表第一个。
- **`config.py`** — API、设备、画布尺寸、字体路径、推送参数敏感项可被环境变量覆盖。
## 墨水屏渲染约束(改 renderer.py 必读)
设备是 **1bit、无真灰阶**——灰阶只能抖动成网点(难看),所以全程纯黑白,靠构图/字号/留白建立层级,**不要引入灰色填充或抖动**
- 字体固定用 **Fusion Pixel 12px 点阵字体**`fonts/`OFL 协议),只按整数倍尺寸 **12/24/48** 渲染(`F12/F24/F48`),并设 `d.fontmode = "1"` 关闭抗锯齿,否则像素会糊。
- 加粗用「伪粗体」:`_draw()` 按 1~bold px 水平偏移叠绘笔画(点阵字体只有单一字重)。
- 推送时 `DITHER = False`(硬阈值),纯黑白图最锐利,勿改成 `true`
- 坐标、字号均为像素网格上的硬编码常量;调布局时注意各区分隔线 `hdash` 的 y 值与下方组件位置联动。
## 注意
- `config.py` 内置了一个默认 `API_KEY`(硬编码 fallback。修改/分享代码时留意,优先用 `ZECTRIX_API_KEY` 环境变量。
- `output/``__pycache__/` 已在 `.gitignore` 中忽略。