feat: 新增 reTerminal E1002(800×480 六色 E Ink)目标设备支持

- 新增 renderer_e1002.py:E1002Renderer 继承 DashboardRenderer,以 k=2 整数倍缩放复用全部组件,重排为 800×480 四段版式(时钟/天气、Claude Usage、今日实时、六色测试色条)
- DashboardRenderer 改造为支持 k 缩放系数(字体按 k 倍创建,组件像素常量随 k 缩放),k=1 保持 400×300 原版不变
- main.py 新增 --target e1002 参数:渲染 800×480 六色图 + 固定尺寸 index.html 到 output/e1002/,供 SenseCraft HMI 的 HTML 控件云端周期性抓取(不推送)
- config.py 新增 E1002 画布尺寸与输出路径常量
- README.md / CLAUDE.md 补充新设备的架构说明与用法
This commit is contained in:
2026-09-10 10:49:26 +08:00
parent 097b9d1d64
commit eab90bf3b5
6 changed files with 214 additions and 27 deletions

View File

@@ -10,6 +10,8 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
> **分支 `feature/colorful`**:新设备在黑白外支持红色,本分支把渲染升级为黑/白/红三色。当前版式为**上中下三段**A 大时钟+日期 / 天气定位南京·江宁B **Claude Usage** 主角5h/7d 用量进度条 + 时间维度对比 pace用量吃紧转红预警C 橘喵今日实时三列。红作**语义强调**(用量预警、涨、定位、天气太阳/闪电),仍**无真灰阶、不抖动**全图只三种纯色。近30天趋势图当前**隐藏**`renderer._trend_chart` 及依赖保留、未调用,随时可挂回)。
> **分支 `feature/reterminal-e1002`**(基于 `feature/colorful`):新增第二个目标设备 **Seeed reTerminal E1002**7.3 寸 **800×480**E Ink **Spectra 6 原生六色**:黑/白/黄/红/绿/蓝)。该设备不接受局域网直推,而是由 **SenseCraft HMI** 云端的 **HTML 控件**按设备刷新间隔(最小 5 分钟)**每周期重新抓取**一个公网 HTTPS URL、无头浏览器截图后量化下发不支持 ETag/304内容不变也会整屏重绘全刷约 17 秒)。因此本分支产出的是**一张固定 800×480 的静态页 `output/e1002/index.html` + 同目录 `dashboard.png`**,需部署到公网 HTTPS局域网地址/明文 HTTP 云端抓不到)。渲染由 `renderer_e1002.py` 完成:继承 `DashboardRenderer` 的全部组件、以 **`k=2` 整数倍缩放**(字体 24/48/96px像素常量乘 k只重写 `render()` 版式;元素与三色版完全相同(时钟日期/天气、Claude Usage、橘喵今日实时黄/绿/蓝目前**仅用于底部六色测试色条**(真机校准平台量化用),语义配色仍只用黑/白/红。
## 命令
```bash
@@ -17,6 +19,7 @@ pip install -r requirements.txt # 仅 Pillow>=10.0urllib 用标准库
cp .env.example .env # 首次:复制模板并填入真实凭证 + 设备 host
python3 main.py # 取数据 → 渲染 → 推送(设备 host 取自 .env 的 EPD_HOST
python3 main.py --render-only # 只渲染到 output/dashboard.png不推送本地调试渲染时用这个
python3 main.py --target e1002 # reTerminal E1002渲染 800x480 六色图 + 固定尺寸 index.html 到 output/e1002/,不推送
sh run.sh # cron 包装脚本cd 项目目录 + vfox python 绝对路径 + 追加日志到 output/cron.log
@@ -48,6 +51,7 @@ EPD_HOST=epd400a44.local python3 main.py
- **`_trend_chart`当前隐藏**近30天三指标折线 `_styled_polyline()` solid/dashed/dotted 区分主指标(流水)红线各指标按自身极值独立归一化已保留但 `render()` 未调用想恢复即在 C 前挂回
- **天气图标全矢量手绘**无图片资源`_weather_category()` 把和风 icon 代码归并为 8 sunny/clear_night/cloudy/overcast/thunder/rain/snow/fog识别不了回退 cloudy再由 `_weather_icon()` `_sun`/`_cloud` 等基元按 1bit 描边画出改天气展示从这里动
- **`pusher.py`** 直连局域网墨水屏设备喵喵固件开源https://gitee.com/gxp666111/miaomiao`web/` 即设备自带管理页可浏览器打开 `http://<EPD_HOST>/` 调试同一套接口)。`push_image()` 先调 `GET /images` 拿画廊已存图片名单逐个 `POST /delete_image?name=`清空单张删除失败不阻塞后续 `POST /upload``Content-Type: image/png`body 为原始 PNG 字节 multipart触发设备转换+刷屏。**清空画廊是刻意设计**设备把每次 `/upload` 都追加存一份到画廊`GET /images` 可见不清理会越推越多且设备当前 `current_mode` slideshow 会轮播到旧图先清后传使画廊恒为 1 等价于始终静态展示最新一张。**清理非核心**拉取画廊列表本身失败也不阻塞后续 `/upload`跳过清理直接推)。`_request()` 对连接类异常`urllib.error.URLError` mDNS `.local` 域名解析瞬时失败内置重试`RETRY_TIMES=2`间隔 `RETRY_DELAY=2s`)——mDNS 基于组播 UDP偶发丢包很正常单次失败不该让整轮推送直接跳过历史上曾走 Zectrix 公网 API`POST /devices/{id}/display/image` + 设备 MAC + `ZECTRIX_API_KEY`现统一为局域网直连
- **`renderer_e1002.py`** reTerminal E1002 目标`E1002Renderer(DashboardRenderer)` `k=2` 复用全部组件`render()` 重排为 800×480 四段A 顶部 0112时钟 F48 + 同基线日期 F12右侧定位/温度 F24/天气·温区 F12 + 图标 s=2.0B 124258 Claude UsageC 272440 今日实时三列D 452480 六色测试色条 `_color_strip``SPECTRA6` 为六色调色板`write_page()` 写出固定 800×480 `index.html`零边距`image-rendering: pixelated`PNG 带时间戳参数防缓存)。**为何固定尺寸而非自适应**云端截图视口/DPR 不可控自适应会重排+抗锯齿产生中间色再被平台抖动固定页里的 1:1 PNG 每个像素本就是六色之一截图零损失——已用无头 Chrome `--window-size=800,480` 截图验证与 PNG 逐像素一致设备端 HTML 控件须铺满整个画布
- **`config.py`** 顶部 `_load_dotenv()` 先加载同目录 `.env`再定义 API设备画布尺寸字体路径推送参数凭证 fallback 为空串真实值来自 `.env`/环境变量
## 墨水屏渲染约束(改 renderer.py 必读)
@@ -56,6 +60,7 @@ EPD_HOST=epd400a44.local python3 main.py
- **红只作语义强调**方向)、警示闪电)、强调定位/主折线红占墨保持很小<10% 墨迹滥用会稀释注意力破坏层级整图**只允许三种纯色** `(0,0,0)/(255,255,255)/(255,0,0)`——渲染后可用 `img.getcolors()` 自查出现第四种色多为抗锯齿灰边即为 bug矢量图元(line/ellipse/polygon/arc)默认不抗锯齿故为纯色文字靠 `fontmode="1"` 保持纯色
- **`DashboardRenderer(k=…)` 缩放系数**所有组件`_label`/`_cmp_line`/`_usage_row`/`_pace`/`tri` 的像素常量与伪粗体偏移都乘 `k`字体按 `12*k/24*k/48*k` 创建`k=1` 400×300 原版改组件后务必用固定夹具比对 `k=1` 输出逐像素不变`k=2` 800×480字体属性名`F12/F24/F48`表达层级而非绝对像素写新版式时沿用原层级名不要再手动放大一档
- 字体固定用 **Fusion Pixel 12px 点阵字体**`fonts/`OFL 协议首选整数倍尺寸 **12/24/48**`F12/F24/F48`最锐利用量区为拿到合适的字号层级另用了 **F13/F16**1.08x/1.33x 非整数倍笔画略不均属有意取舍 `d.fontmode = "1"` 关抗锯齿仍保持纯色不糊跨字号竖直居中统一用 `_mid()` `getbbox` 墨迹中心对齐)。
- 加粗用伪粗体」:`_draw()` 1~bold px 水平偏移叠绘笔画点阵字体只有单一字重)。
- 推送时 `DITHER = False`硬阈值纯黑白图最锐利勿改成 `true`