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>
This commit is contained in:
2026-07-06 18:55:46 +08:00
parent 9b39eacecf
commit 14359c8726
6 changed files with 242 additions and 67 deletions

View File

@@ -1,30 +1,32 @@
# 墨水屏仪表盘推送eink-push
将橘喵今日经营、近30天趋势、日期与天气合成为一张 **400×300 三色(黑/白/红BWR**图片,
日期天气、Claude Code 用量、橘喵今日经营合成为一张 **400×300 三色(黑/白/红BWR**图片,
推送到 Zectrix 极趣云墨水屏设备。
纯 Python + Pillow + Fusion Pixel 点阵字体,**无浏览器依赖**,适合后台/定时运行。
> **`feature/colorful` 分支**:新设备支持红色。红作为**稀缺强调色**只点缀四处——定位图标、
> 天气的太阳/闪电、环比同比「涨」的三角与数值(红涨)、趋势图主指标(流水)折线——占墨极小,其余仍黑白。
> **`feature/colorful` 分支**:新设备支持红色,渲染升级为黑/白/红三色,版式为上中下三段
> (时钟天气 / Claude Usage / 今日实时)。红作**语义强调**——用量吃紧预警、涨、定位、天气太阳/闪电——
> 全图只三种纯色、无灰阶不抖动。近30天趋势图当前隐藏代码保留可挂回
## 效果
- 顶部:大号时钟 + 日期 天气(矢量手绘图标 + 温度 + 天气/温区)
- 中部:橘喵今日实时经营(单量 / 流水 / 毛利,含环比、同比涨跌)
- 底部:近30天三指标趋势折线图同一图表实线 / 虚线 / 点线区分X 轴仅月/日
- 顶部:大号时钟 + 日期 天气(矢量手绘图标 + 温度 + 天气/温区,定位南京·江宁
- 中部:**Claude Usage**——5h / 7d 用量进度条 + 大号百分比 + 时间维度对比 pace用量%−时间%,超前↑ / 节余↓);用量 ≥ 阈值时该条转红预警
- 底部:橘喵今日实时经营(单量 / 流水 / 毛利,含环比、同比涨跌,涨=红
## 目录结构
```
eink-push/
├── main.py # 入口:取数据 → 渲染 → 推送
├── config.py # 配置:API Key、设备、字体、尺寸、推送参数、缓存路径
├── data.py # 数据层:拉真实数据并映射,失败回退占位 "--"(不回退 mock天气/趋势缓存
├── jm_api.py # jm-devops 后端统计接口客户端(免登录 GET仅带 clientid 头
├── 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 # 推送层:设备列表 / 推送图片(标准库 urllib
├── pusher.py # 推送层:按 .env 设备 MAC 直接推送图片(标准库 urllib
├── run.sh # cron 包装脚本本机专用git 忽略)
├── fonts/ # Fusion Pixel 点阵字体OFL 协议)
├── output/ # 生成的图片与 cron.loggit 忽略)
@@ -41,7 +43,7 @@ pip install -r requirements.txt # 仅 Pillow>=10.0;网络请求用标准库
## 使用
```bash
python3 main.py # 渲染并推送(默认取设备列表第一个
python3 main.py # 渲染并推送(设备取 .env 的 ZECTRIX_DEVICE_ID
python3 main.py --render-only # 只渲染到 output/dashboard.png不推送本地调试渲染用
```
@@ -53,11 +55,13 @@ 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
@@ -68,13 +72,14 @@ QWEATHER_HOST=... QWEATHER_KEY=... WEATHER_LOCATION=经度,纬度 WEATHER_TTL
## 数据来源
- **橘喵今日经营 + 近30天趋势**:接入 jm-devops 后端统计接口(`jm_api.py`
免登录 GET仅带 `clientid` 头、无 token
- **橘喵今日经营**:接入 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`(控制台-设置查看)。
- `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**。
@@ -86,15 +91,16 @@ QWEATHER_HOST=... QWEATHER_KEY=... WEATHER_LOCATION=经度,纬度 WEATHER_TTL
- **天气缓存** `.weather_cache.json`TTL = `WEATHER_TTL`(默认 15 分钟),未过期不发请求。
- **趋势缓存** `.trend_cache.json`:按日期为 key当天命中即不再调 `recent-days`,每天只拉一次。
两者拉取失败均**沿用旧缓存**避免趋势/天气区整片 `"--"`,仍无缓存才回退占位。想强制重拉删掉对应缓存文件即可(均已 git 忽略)。
两者拉取失败均**沿用旧缓存**避免天气区整片 `"--"`,仍无缓存才回退占位。想强制重拉删掉对应缓存文件即可(均已 git 忽略)。
Claude 用量**不自建缓存**——直接读 statusline 落盘的本地文件,文件缺失/损坏即显示 `"--"`
## 设计说明
- 设备为**三色(黑/白/红)无真灰阶**,灰阶只能抖动成网点(难看),故底色只用黑白 + 红作稀缺强调,靠构图、字号、留白建立层级。
- **红只承载语义**(方向·警示·强调),占墨保持很小(实测红≈全图 0.6%、占墨迹 <10%整图仅三种纯色 `(0,0,0)/(255,255,255)/(255,0,0)`无灰不抖动
- 字体用 **Fusion Pixel 12px 点阵字体**整数倍尺寸(12/24/48)渲染关闭抗锯齿 像素锐利
重点数据用伪粗体」(偏移叠绘)加粗
- 字体用 **Fusion Pixel 12px 点阵字体**首选整数倍(12/24/48)最锐利用量区另用 13/16px(非整数倍笔画略不均)取字号层级关抗锯齿仍保持纯色不糊重点数据用伪粗体」(偏移叠绘)加粗
- **Claude Usage**每条单行 = 左标签(5h/7d) + 粗进度条 + 百分比 + pace(/下三角)用量 `USAGE_WARN`(默认 80) 时该条进度条与百分比转红预警行内所有元素按墨迹竖直中心对齐到同一中线
- 天气图标为**全矢量手绘**无图片资源按和风 icon 代码归并为 8 /晴夜/多云/////用基本图元描边画出太阳与闪电着红
- 趋势折线各指标按自身极值独立归一化故只表达**趋势形状**不可横向比绝对值主指标(流水)着红领读末点标红点
- 近30天趋势折线图当前**隐藏**`renderer._trend_chart` 及依赖保留未调用随时可挂回
- 推送用 `dither=false`硬阈值三色纯色图最锐利
```