Files
eink-push/README.md
YANG JIANKUAN 14359c8726 feat: 版式重构为三段 + 接入 Claude Usage(只读本地) + 定位江宁
将仪表盘从「四区(时钟/天气/今日实时/30天趋势)」重构为上中下三段:
- A 顶部:大时钟+日期 / 天气(定位改南京·江宁)
- B 中部主角 Claude Usage:5h/7d 用量进度条 + 大号百分比 + 时间维度对比 pace
  (pace=用量%−时间%,超前↑红/节余↓黑,参考 claude-statusline);用量≥阈值该条转红预警
- C 底部 橘喵今日实时:三列版式对齐主分支(名F12/值F24粗/环比同比偏移 +18/+34/+64/+82)
- 近30天趋势图隐藏(_trend_chart 及依赖保留、未调用,可挂回)

用量只读本地、不发网络请求:新增 usage_local.py 读取 claude-statusline 落盘的
/tmp/claude/statusline-usage-cache.json(utilization + resets_at)。utilization 可能滞后,
但 resets_at 为绝对时间,故 pace 每次按当前时间现算、始终准确;文件缺失回退 "--"。

其他:
- 天气定位 秦淮→江宁(config 默认 118.840,31.953)
- 进度条边框随条色(红条即红框);行内元素按墨迹竖直中心对齐(_mid)
- 新增 F13/F16 字号(非整数倍,fontmode=1 保持纯色)
- 全图仍严格三色(黑/白/红)、无灰阶不抖动;底部留 ~11px 下边距
- 同步更新 CLAUDE.md / README.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 18:55:46 +08:00

106 lines
6.4 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.

# 墨水屏仪表盘推送eink-push
将日期天气、Claude Code 用量、橘喵今日经营合成为一张 **400×300 三色(黑/白/红BWR**图片,
推送到 Zectrix 极趣云墨水屏设备。
纯 Python + Pillow + Fusion Pixel 点阵字体,**无浏览器依赖**,适合后台/定时运行。
> **`feature/colorful` 分支**:新设备支持红色,渲染升级为黑/白/红三色,版式为上中下三段
> (时钟天气 / Claude Usage / 今日实时)。红作**语义强调**——用量吃紧预警、涨、定位、天气太阳/闪电——
> 全图只三种纯色、无灰阶不抖动。近30天趋势图当前隐藏代码保留可挂回
## 效果
- 顶部:大号时钟 + 日期 天气(矢量手绘图标 + 温度 + 天气/温区,定位南京·江宁)
- 中部:**Claude Usage**——5h / 7d 用量进度条 + 大号百分比 + 时间维度对比 pace用量%−时间%,超前↑ / 节余↓);用量 ≥ 阈值时该条转红预警
- 底部:橘喵今日实时经营(单量 / 流水 / 毛利,含环比、同比涨跌,涨=红)
## 目录结构
```
eink-push/
├── main.py # 入口:取数据 → 渲染 → 推送
├── config.py # 配置:设备、天气、用量、字体、尺寸、推送参数、缓存路径
├── data.py # 数据层:拉真实数据并映射,失败回退占位 "--"(不回退 mock天气/趋势缓存
├── jm_api.py # jm-devops 后端统计接口客户端(设备密钥 client_secret 授权 + token 缓存)
├── weather_api.py # 和风天气QWeather客户端实时天气 + 今日温区)
├── usage_local.py # Claude Code 用量:只读本地 statusline 缓存文件(不发网络请求)
├── renderer.py # 渲染层DashboardRenderer 生成 400×300 三色(黑/白/红)图片
├── pusher.py # 推送层:按 .env 设备 MAC 直接推送图片(标准库 urllib
├── run.sh # cron 包装脚本本机专用git 忽略)
├── fonts/ # Fusion Pixel 点阵字体OFL 协议)
├── output/ # 生成的图片与 cron.loggit 忽略)
├── requirements.txt
└── README.md
```
## 安装
```bash
pip install -r requirements.txt # 仅 Pillow>=10.0;网络请求用标准库 urllib
```
## 使用
```bash
python3 main.py # 渲染并推送(设备取 .env 的 ZECTRIX_DEVICE_ID
python3 main.py --render-only # 只渲染到 output/dashboard.png不推送本地调试渲染用
```
环境变量可覆盖配置(详见 `config.py`
```bash
# Zectrix 设备
ZECTRIX_API_KEY=zt_xxx ZECTRIX_DEVICE_ID=AA:BB:CC:DD:EE:FF python3 main.py
# jm-devops 后端 / 和风天气
JM_BASE_API=... JM_CLIENT_ID=...
QWEATHER_HOST=... QWEATHER_KEY=... WEATHER_LOCATION=经度,纬度 WEATHER_TTL=900
# Claude Code 用量(只读本地 statusline 缓存,不发请求)
USAGE_LOCAL_PATH=/tmp/claude/statusline-usage-cache.json USAGE_WARN=80
```
## 定时刷新cron
设计为**每分钟**触发:业务数据每次都刷新,天气靠缓存、用量读本地文件,避免高频打接口(见下「设计说明」)。
`run.sh` 是 cron 入口——cron 不继承登录环境,故脚本内 python 写死绝对路径、`cd` 到项目目录后追加日志到 `output/cron.log`
```cron
* * * * * /path/to/eink-push/run.sh
```
手动测试:`sh run.sh`
## 数据来源
- **橘喵今日经营**:接入 jm-devops 后端统计接口(`jm_api.py`,设备密钥 client_secret 授权):
- `GET /system/statistics/realtime` —— 今日单量/流水/毛利 + 环比/同比
- `GET /system/statistics/recent-days?days=30` —— 近30天每日数据趋势图当前隐藏仍会拉取并缓存
- **天气**接入真实和风天气QWeather`weather_api.py`),定位固定南京·江宁。
实时天气取 `now.text`/`now.temp`/`now.icon`,今日温区取 `/3d``daily[0]`。需配置 `QWEATHER_HOST` + `QWEATHER_KEY`
- **Claude Code 用量****只读本地**`usage_local.py`,不发请求)——读 claude-statusline 落盘的
`/tmp/claude/statusline-usage-cache.json`,取 5h/7d 的 `utilization``resets_at`
注:新版 Claude Code 经 stdin 喂 statusline该缓存 `utilization` 可能滞后;`resets_at` 为绝对时间,故 pace 时间对比始终准确。
- **日期 / 时间 / 上次更新**:真实系统时间。
> `data.py` 负责把响应映射成渲染结构;**任何接口失败都回退占位 `"--"`,不回退 mock**。
## 缓存机制
为「每分钟触发、但天气/趋势无需高频刷新」而设的两套**文件缓存**cron 每次独立进程,必须落盘):
- **天气缓存** `.weather_cache.json`TTL = `WEATHER_TTL`(默认 15 分钟),未过期不发请求。
- **趋势缓存** `.trend_cache.json`:按日期为 key当天命中即不再调 `recent-days`,每天只拉一次。
两者拉取失败均**沿用旧缓存**避免天气区整片 `"--"`,仍无缓存才回退占位。想强制重拉删掉对应缓存文件即可(均已 git 忽略)。
Claude 用量**不自建缓存**——直接读 statusline 落盘的本地文件,文件缺失/损坏即显示 `"--"`
## 设计说明
- 设备为**三色(黑/白/红)无真灰阶**,灰阶只能抖动成网点(难看),故底色只用黑白 + 红作稀缺强调,靠构图、字号、留白建立层级。
- **红只承载语义**(方向·警示·强调),占墨保持很小(实测红≈全图 0.6%、占墨迹 <10%整图仅三种纯色 `(0,0,0)/(255,255,255)/(255,0,0)`无灰不抖动
- 字体用 **Fusion Pixel 12px 点阵字体**首选整数倍(12/24/48)最锐利用量区另用 13/16px(非整数倍笔画略不均)取字号层级关抗锯齿仍保持纯色不糊重点数据用伪粗体」(偏移叠绘)加粗
- **Claude Usage**每条单行 = 左标签(5h/7d) + 粗进度条 + 百分比 + pace(/下三角)用量 `USAGE_WARN`(默认 80) 时该条进度条与百分比转红预警行内所有元素按墨迹竖直中心对齐到同一中线
- 天气图标为**全矢量手绘**无图片资源按和风 icon 代码归并为 8 /晴夜/多云/////用基本图元描边画出太阳与闪电着红
- 近30天趋势折线图当前**隐藏**`renderer._trend_chart` 及依赖保留未调用随时可挂回)。
- 推送用 `dither=false`硬阈值三色纯色图最锐利
```