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:
57
renderer.py
57
renderer.py
@@ -31,13 +31,17 @@ BLACK, WHITE, RED = (0, 0, 0), (255, 255, 255), (255, 0, 0)
|
||||
|
||||
|
||||
class DashboardRenderer:
|
||||
def __init__(self, font_path=config.FONT_PATH, size=(config.WIDTH, config.HEIGHT)):
|
||||
def __init__(self, font_path=config.FONT_PATH, size=(config.WIDTH, config.HEIGHT), k=1):
|
||||
"""k:整体缩放系数(整数)。k=1 为 400x300 原版;k=2 供 800x480 设备(reTerminal E1002)复用组件:
|
||||
字体按 k 倍创建(点阵字体整数倍最锐利),组件内的像素常量一律乘 k,故各组件在两种尺寸下形态一致。
|
||||
字体属性名仍按 k=1 的字号命名(F12/F24/…),表达「层级」而非绝对像素。"""
|
||||
self.W, self.H = size
|
||||
self.F12 = ImageFont.truetype(font_path, 12)
|
||||
self.F13 = ImageFont.truetype(font_path, 13) # 5h/7d 与 pace 用;接近原生 12px,畸变很小
|
||||
self.F16 = ImageFont.truetype(font_path, 16) # 非整数倍(1.33x):靠 fontmode='1' 保持纯色,笔画略不均可接受
|
||||
self.F24 = ImageFont.truetype(font_path, 24)
|
||||
self.F48 = ImageFont.truetype(font_path, 48)
|
||||
self.k = k
|
||||
self.F12 = ImageFont.truetype(font_path, 12 * k)
|
||||
self.F13 = ImageFont.truetype(font_path, 13 * k) # 5h/7d 与 pace 用;接近原生 12px,畸变很小
|
||||
self.F16 = ImageFont.truetype(font_path, 16 * k) # 非整数倍(1.33x):靠 fontmode='1' 保持纯色,笔画略不均可接受
|
||||
self.F24 = ImageFont.truetype(font_path, 24 * k)
|
||||
self.F48 = ImageFont.truetype(font_path, 48 * k)
|
||||
|
||||
# ---------- 基础绘制工具 ----------
|
||||
def _tw(self, s, ft, track=0):
|
||||
@@ -70,16 +74,16 @@ class DashboardRenderer:
|
||||
def ctext(self, cx, y, s, ft, fill=BLACK, bold=0):
|
||||
self._draw(cx - (self._tw(s, ft) + bold) / 2, y, s, ft, fill, bold)
|
||||
|
||||
def hdash(self, x0, x1, y, dash=4, gap=4, fill=BLACK):
|
||||
def hdash(self, x0, x1, y, dash=4, gap=4, fill=BLACK, width=1):
|
||||
x = x0
|
||||
while x < x1:
|
||||
self.d.line([x, y, min(x + dash, x1), y], fill=fill, width=1)
|
||||
self.d.line([x, y, min(x + dash, x1), y], fill=fill, width=width)
|
||||
x += dash + gap
|
||||
|
||||
def vdash(self, x, y0, y1, dash=4, gap=4, fill=BLACK):
|
||||
def vdash(self, x, y0, y1, dash=4, gap=4, fill=BLACK, width=1):
|
||||
y = y0
|
||||
while y < y1:
|
||||
self.d.line([x, y, x, min(y + dash, y1)], fill=fill, width=1)
|
||||
self.d.line([x, y, x, min(y + dash, y1)], fill=fill, width=width)
|
||||
y += dash + gap
|
||||
|
||||
def tri(self, cx, cy, sz, up=True, fill=BLACK):
|
||||
@@ -93,8 +97,9 @@ class DashboardRenderer:
|
||||
def _cmp_line(self, cx, y, label, pair, fg=BLACK):
|
||||
"""环比/同比一行:标签 + 涨跌三角 + 数值,整体居中。direction 为 None 时不画三角。"""
|
||||
direction, val = pair
|
||||
lw = self._tw(label, self.F12); gap = 5; nw = self._tw(val, self.F12)
|
||||
trw, tgap = (8, 4) if direction else (0, 0)
|
||||
k = self.k
|
||||
lw = self._tw(label, self.F12); gap = 5 * k; nw = self._tw(val, self.F12)
|
||||
trw, tgap = (8 * k, 4 * k) if direction else (0, 0)
|
||||
x = cx - (lw + gap + trw + tgap + nw) / 2
|
||||
self.text(x, y, label, self.F12, fill=fg); x += lw + gap
|
||||
# 方向语义配色(红涨):涨 → 箭头与百分比数值一起红;跌/无 → 黑(标签始终黑)
|
||||
@@ -102,17 +107,18 @@ class DashboardRenderer:
|
||||
val_color = RED if up else fg
|
||||
if direction:
|
||||
# 三角中心对齐 F12 数字墨迹竖直中心(y+8.5),否则箭头偏高
|
||||
self.tri(x + trw / 2, y + 8.5, 7, up=up, fill=val_color); x += trw + tgap
|
||||
self.tri(x + trw / 2, y + 8.5 * k, 7 * k, up=up, fill=val_color); x += trw + tgap
|
||||
self.text(x, y, val, self.F12, fill=val_color)
|
||||
|
||||
def _label(self, y, title, right=None):
|
||||
"""区块标题(两区块统一,对齐主分支 _title_bar 风格):
|
||||
■ 方块装饰(8px,与 F12 标题墨迹竖直居中) + 标题(F12,常规字重) + 可选右侧信息。"""
|
||||
SQ = 8
|
||||
self.d.rectangle([10, y + 4, 10 + SQ, y + 4 + SQ], fill=BLACK) # 中心≈y+8,对齐 F12 墨迹中心(≈y+8.5)
|
||||
self.text(10 + SQ + 6, y, title, self.F12)
|
||||
k = self.k
|
||||
SQ, M = 8 * k, 10 * k # 方块边长 / 左右页边距
|
||||
self.d.rectangle([M, y + 4 * k, M + SQ, y + 4 * k + SQ], fill=BLACK) # 中心≈y+8,对齐 F12 墨迹中心(≈y+8.5)
|
||||
self.text(M + SQ + 6 * k, y, title, self.F12)
|
||||
if right:
|
||||
self.rtext(self.W - 10, y, right, self.F12)
|
||||
self.rtext(self.W - M, y, right, self.F12)
|
||||
|
||||
def _mid(self, x, cy, s, ft, fill=BLACK, bold=0, align="l", track=0):
|
||||
"""按字符串「墨迹竖直中心」对齐到 cy 绘制——跨字号(F12/F24)也能真正居中,
|
||||
@@ -134,10 +140,10 @@ class DashboardRenderer:
|
||||
color = RED if up else BLACK
|
||||
txt = f"{abs(int(diff)):02d}"
|
||||
tw = self._tw(txt, self.F13)
|
||||
self._mid(xr, cy, txt, self.F13, fill=color, bold=1, align="r")
|
||||
self._mid(xr, cy, txt, self.F13, fill=color, bold=self.k, align="r")
|
||||
if diff == 0:
|
||||
return tw
|
||||
TRI_GAP, TRI = 4, 6
|
||||
TRI_GAP, TRI = 4 * self.k, 6 * self.k
|
||||
self.tri(xr - tw - TRI_GAP - TRI / 2, cy, TRI, up=up, fill=color)
|
||||
return tw + TRI_GAP + TRI
|
||||
|
||||
@@ -149,21 +155,22 @@ class DashboardRenderer:
|
||||
ok = isinstance(raw, (int, float)) # None/缺失 → 显示 "--"
|
||||
pct = max(0, min(100, int(raw))) if ok else 0
|
||||
color = RED if (ok and pct >= warn) else BLACK
|
||||
LABEL_W, G1, G2, H = 26, 13, 8, 15 # G1 进度条↔百分比、G2 百分比↔pace(视觉约 12/11)
|
||||
PCT_TRACK = 2 # F16(16/12x 非整数倍缩放)数字墨迹无侧边距、紧贴,手动加字符间距
|
||||
cy = y + 10 # 行竖直中心
|
||||
self._mid(x0, cy, bar["k"], self.F13, bold=1) # 左标签 F13
|
||||
k = self.k
|
||||
LABEL_W, G1, G2, H = 26 * k, 13 * k, 8 * k, 15 * k # G1 进度条↔百分比、G2 百分比↔pace(视觉约 12/11)
|
||||
PCT_TRACK = 2 * k # F16(16/12x 非整数倍缩放)数字墨迹无侧边距、紧贴,手动加字符间距
|
||||
cy = y + 10 * k # 行竖直中心
|
||||
self._mid(x0, cy, bar["k"], self.F13, bold=k) # 左标签 F13
|
||||
# 右侧从右往左:pace(最右) → 百分比 → 进度条
|
||||
pct_r = x1
|
||||
if ok and "time_pct" in bar:
|
||||
pace_w = self._pace(x1, cy, pct - int(bar["time_pct"]))
|
||||
pct_r = x1 - pace_w - G2
|
||||
pct_txt = f"{pct:02d}%" if ok else "--"
|
||||
self._mid(pct_r, cy, pct_txt, self.F16, fill=color, bold=1, align="r", track=PCT_TRACK) # 百分比 F16(主)
|
||||
self._mid(pct_r, cy, pct_txt, self.F16, fill=color, bold=k, align="r", track=PCT_TRACK) # 百分比 F16(主)
|
||||
bx0 = x0 + LABEL_W
|
||||
bx1 = pct_r - self._tw(pct_txt, self.F16, PCT_TRACK) - G1
|
||||
by = cy - H // 2
|
||||
self.d.rectangle([bx0, by, bx1, by + H], outline=color, width=1) # 轨道边框随条色
|
||||
self.d.rectangle([bx0, by, bx1, by + H], outline=color, width=k) # 轨道边框随条色
|
||||
fw = (bx1 - bx0) * pct / 100.0
|
||||
if fw >= 2:
|
||||
self.d.rectangle([bx0, by, bx0 + fw, by + H], fill=color)
|
||||
|
||||
Reference in New Issue
Block a user