
1. 项目概述为什么需要一个E-ink Dashboard几年前我在家里书桌上摆满了各种电子设备一个显示日程的平板一个显示天气和新闻的智能音箱还有一个专门用来监控服务器状态的旧手机。它们都在发光、发热、发出通知让我感觉被信息包围却难以专注。直到我偶然把玩起一台闲置的旧Kindle看着那块在自然光下清晰、不闪烁、几乎不耗电的电子墨水屏一个想法冒了出来能不能用它来做一个纯粹的、安静的、只展示关键信息的“信息看板”这就是E-ink Dashboard项目的起点。简单来说E-ink Dashboard就是一个运行在电子墨水屏设备上的信息展示界面。它不像普通屏幕那样主动发光、刷新频繁而是像一张“数字纸张”只在内容需要更新时刷新一次其余时间完全断电也能保持显示。它的核心价值在于低干扰、低功耗和护眼。你不再需要一块刺眼的屏幕24小时亮着来告诉你天气或待办事项一块E-ink屏可以安静地待在角落像便利贴一样提供必要信息一周甚至一个月才充一次电。这个项目适合谁呢首先是极客和DIY爱好者喜欢把旧Kindle、文石、海信等E-ink设备“废物利用”赋予它们新生命。其次是追求效率和专注的数字工作者希望减少屏幕时间将日程、任务等关键信息从纷繁的电脑桌面或手机通知中剥离出来形成物理化的焦点。最后它也适合一些轻量级的物联网显示场景比如家庭环境监测温湿度、空气质量、简易的工控状态显示等这些场景对实时性要求不高但对功耗和常亮显示有要求。2. 核心设计思路与技术选型2.1 硬件选型你的“数字画布”从哪里来实现E-ink Dashboard的第一步是选择硬件。市面上主要有三类选择废旧电纸书阅读器如Kindle这是最经济、最普遍的选择。尤其是早期型号的Kindle如Kindle 3 4 5 Paperwhite 1/2它们价格低廉屏幕素质不错多为6英寸 800x600分辨率并且可以通过越狱Jailbreak安装自定义系统或直接运行一个轻量级的Linux环境。缺点是性能较弱系统封闭开发环境搭建有一定门槛。专用E-ink显示器/开发板例如 Waveshare微雪等厂商生产的各种尺寸2.9英寸、4.2英寸、7.5英寸等的E-ink屏幕模块通常通过SPI或e-Paper接口与树莓派Raspberry Pi、ESP32等微型控制器连接。这种方式最灵活你可以完全控制硬件和软件性能也足够但需要额外的控制器和一定的动手焊接/接线能力整体成本稍高。开放系统的电纸书/智能办公本如文石Boox、海信Hisense的某些型号它们本身运行Android系统可以直接安装APK。你可以直接开发一个Android App作为Dashboard。这种方式开发最便捷但设备本身价格昂贵用来做单纯的Dashboard有些“大材小用”。我的选择与理由对于大多数入门者和想快速看到成果的朋友我强烈推荐从越狱的旧Kindle开始。成本极低几十到一百元社区资源丰富有成熟的越狱工具和KUAL插件框架屏幕效果有保障。它能让你快速验证想法感受E-ink Dashboard的魅力。本篇文章的后续实操也将主要围绕这个场景展开。2.2 软件架构如何让信息“画”在屏幕上确定了硬件接下来要解决软件问题如何生成最终的显示图像并推送到屏幕核心思路是在设备上运行一个轻量级服务定期从网络API获取数据渲染成图片然后调用屏幕驱动进行局部或全局刷新。整个软件栈可以分解为以下几个层次显示驱动层这是最底层负责直接与E-ink屏幕的硬件控制器通信执行清屏、绘制位图、刷新等操作。对于越狱Kindle社区已经提供了成熟的驱动库如libinkview或通过fbink工具操作帧缓冲区。对于 Waveshare 屏幕厂商会提供针对树莓派或ESP32的C/Python库。渲染与布局层这一层决定Dashboard长什么样。由于E-ink刷新慢、不支持复杂动画界面设计必须极简以静态或缓慢更新的信息块为主。我们可以用HTML/CSS来定义布局和样式因为它非常直观且易于调整。然后需要一个“无头浏览器”或HTML渲染引擎将HTML/CSS“画”成一张位图图片。常用的工具有wkhtmltoimage一个命令行工具基于WebKit引擎可以将HTML网页转换为PNG或JPEG图片。它成熟稳定但对现代CSS支持一般。Headless Chrome/Chromium通过puppeteerNode.js或seleniumPython等库控制无头Chrome进行截图。这种方式对现代CSS和JavaScript支持最好功能强大但运行时内存占用相对较高。轻量级渲染库如Cairo图形库配合Pango文字排版直接通过代码绘图。这种方式最轻量、可控但开发复杂度高不适合快速迭代UI。数据获取与逻辑层这一层负责从各种数据源抓取信息。例如天气调用和风天气、OpenWeatherMap等API。日历与待办同步Google Calendar需OAuth、Todoist、或读取本地CalDAV服务器数据。新闻/RSS解析特定新闻网站的RSS源。系统状态监控本地树莓派的CPU温度、负载、硬盘空间等。自定义信息从自建服务器API获取数据。 通常使用Python、Node.js或Shell脚本来编写这些数据抓取和处理的逻辑因为它们有丰富的网络请求和JSON解析库。调度与集成层这是将以上所有部分粘合起来的“胶水”。我们需要一个定时任务调度器如Linux的cron定期例如每15分钟、每小时执行一个主控脚本。这个脚本的工作流是1) 运行数据获取脚本将结果填充到HTML模板的变量中2) 调用渲染引擎将最终的HTML生成为一张图片3) 调用显示驱动将这张图片推送到E-ink屏幕。为什么选择HTML无头浏览器方案因为它将UI设计HTML/CSS和业务逻辑数据获取解耦了。你可以像设计普通网页一样用Flexbox或Grid轻松拖拽出漂亮的布局而无需关心底层的像素计算。这对于快速原型和持续美化至关重要。3. 基于越狱Kindle的详细实现步骤下面我将以一台越狱的Kindle Paperwhite 2代号“PW2”为例手把手带你搭建一个显示天气、日历和名言警句的Dashboard。3.1 环境准备越狱与基础工具安装首先确保你的Kindle已经成功越狱。越狱方法因型号而异请搜索“Kindle [你的型号] Jailbreak”寻找最新教程。越狱后你需要安装两个核心组件KUALKindle Unified Application Launcher这是一个启动器允许你在Kindle上像运行App一样运行自定义脚本。从MobileRead论坛下载对应你系统版本的KUAL安装包.bin文件通过USB连接Kindle将文件拷贝到根目录然后在Kindle上点击“设置 - 更新您的Kindle”来安装。USBNetwork这个插件允许你通过USB网络连接或Wi-Fi SSH到你的Kindle这是后续文件传输和命令行操作的基础。同样从社区下载安装包进行安装。安装完成后通过USB连接Kindle和电脑启用USBNetwork功能通常在KUAL菜单中能找到然后你就可以使用SSH客户端如PuTTY或终端连接到你的Kindle了。默认IP地址通常是192.168.15.244用户名root密码默认为空。登录后首先更新软件包列表并安装一些必要工具# 进入Kindle的根文件系统 mntroot rw # 挂载根目录为可写 # 更新opkg包管理器源如果已配置 opkg update # 安装一些基础工具如wget, unzip, python如果系统自带版本过低可能需要额外安装 opkg install wget unzip3.2 核心组件部署渲染引擎与显示驱动Kindle的Linux环境比较精简我们选择wkhtmltoimage作为渲染引擎因为它有预编译的、兼容旧版glibc的静态二进制文件依赖少。下载并安装 wkhtmltoimage# 创建一个工作目录 mkdir -p /mnt/us/dashboard cd /mnt/us/dashboard # 从可靠的源下载静态编译版本需要根据你的Kindle CPU架构选择多数旧Kindle是armv7l wget https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/0.12.4/wkhtmltox-0.12.4_linux-generic-armv7l.tar.xz tar -xvf wkhtmltox-0.12.4_linux-generic-armv7l.tar.xz # 将可执行文件链接到系统路径 cp wkhtmltox/bin/wkhtmltoimage /usr/local/bin/ chmod x /usr/local/bin/wkhtmltoimage测试是否安装成功wkhtmltoimage --version。准备显示驱动工具fbinkfbink是Kindle社区大神NiLuJe开发的神器它能非常方便地操作Kindle的帧缓冲区framebuffer包括显示图片、文字、进行局部刷新等。从NiLuJe的发布页下载最新的fbink包通常是.tgz文件解压后将其中的可执行文件fbink放到/usr/local/bin/下。# 示例下载与安装版本号需替换为最新 wget https://www.mobileread.com/forums/attachment.php?attachmentidxxxxxxdyyyyyy -O fbink.tgz tar -xzvf fbink.tgz -C /usr/local/bin/ fbink/fbink chmod x /usr/local/bin/fbink3.3 数据获取与HTML模板设计我们在/mnt/us/dashboard目录下创建项目结构。创建数据获取脚本Python示例fetch_data.py#!/usr/bin/env python3 import requests import json from datetime import datetime import sys import os # 1. 获取天气数据以和风天气为例需要申请免费KEY WEATHER_API_KEY YOUR_HEFENG_KEY LOCATION 101010100 # 北京城市ID weather_url fhttps://devapi.qweather.com/v7/weather/now?location{LOCATION}key{WEATHER_API_KEY} try: resp requests.get(weather_url, timeout10) weather_data resp.json() temp weather_data[now][temp] # 温度 text weather_data[now][text] # 天气状况 humidity weather_data[now][humidity] # 湿度 except Exception as e: temp N/A text 获取失败 humidity N/A # 2. 生成一句名言这里简单从一个本地文件或固定列表读取也可调用API quotes [ Stay hungry, stay foolish. - Steve Jobs, The best time to plant a tree was 20 years ago. The second best time is now. - Chinese Proverb, Simple can be harder than complex. - Steve Jobs ] import random daily_quote random.choice(quotes) # 3. 获取今日日期 today datetime.now().strftime(%Y年%m月%d日 %A) # 4. 将数据写入一个JSON文件供HTML模板使用 data { temperature: temp, weatherText: text, humidity: humidity, quote: daily_quote, date: today } with open(/mnt/us/dashboard/data.json, w) as f: json.dump(data, f) print(Data fetched and saved.)记得给脚本执行权限chmod x fetch_data.py。你需要安装Python的requests库可以通过opkg install python3-pip然后pip3 install requests来安装或者在电脑上交叉编译后传上去。创建HTML模板template.html!DOCTYPE html html head meta charsetutf-8 style body { background-color: white; font-family: Helvetica Neue, Arial, sans-serif; margin: 0; padding: 20px; width: 800px; /* 匹配PW2屏幕宽度 */ height: 600px; /* 匹配PW2屏幕高度 */ display: flex; flex-direction: column; justify-content: space-between; } .header { text-align: center; border-bottom: 2px solid #333; padding-bottom: 10px; margin-bottom: 20px; } .date { font-size: 24px; font-weight: bold; color: #333; } .weather-section { display: flex; align-items: center; justify-content: space-around; background: #f5f5f5; border-radius: 10px; padding: 20px; margin: 20px 0; } .temp { font-size: 64px; font-weight: bold; color: #e74c3c; } .weather-info { font-size: 28px; color: #3498db; } .quote { font-size: 20px; font-style: italic; text-align: center; padding: 30px; border-top: 1px dashed #ccc; color: #555; line-height: 1.5; } .footer { text-align: center; font-size: 14px; color: #999; margin-top: 20px; } /style /head body div classheader div classdate iddate加载中.../div /div div classweather-section div classtemp idtemperature--°C/div div classweather-info div idweatherText.../div div湿度: span idhumidity--/span%/div /div /div div classquote idquote“正在获取今日格言...”/div div classfooter E-ink Dashboard | 最后更新: span idupdateTime/span /div script // 页面加载时从同目录下的data.json文件读取数据 fetch(file:///mnt/us/dashboard/data.json) .then(response response.json()) .then(data { document.getElementById(date).textContent data.date; document.getElementById(temperature).textContent data.temperature °C; document.getElementById(weatherText).textContent data.weatherText; document.getElementById(humidity).textContent data.humidity; document.getElementById(quote).textContent “ data.quote ”; const now new Date(); document.getElementById(updateTime).textContent now.toLocaleTimeString(zh-CN, {hour12: false}); }) .catch(error { console.error(Error loading data:, error); document.getElementById(date).textContent 数据加载失败; }); /script /body /html这个模板定义了简单的布局和样式并通过JavaScript读取本地data.json文件来填充数据。注意wkhtmltoimage支持执行页面中的JavaScript所以这种方式是可行的。3.4 整合与自动化主控脚本与定时任务创建一个主控脚本update_dashboard.sh它将串联所有步骤#!/bin/sh # 切换到工作目录 cd /mnt/us/dashboard # 1. 获取最新数据 python3 fetch_data.py # 2. 使用wkhtmltoimage将HTML渲染为PNG图片 # --width 和 --height 参数需匹配你的屏幕分辨率 # --disable-smart-width 选项有助于确保尺寸精确 wkhtmltoimage --width 800 --height 600 --disable-smart-width --quality 90 file:///mnt/us/dashboard/template.html /mnt/us/dashboard/output.png # 3. 使用fbink将图片显示到屏幕上 # -g 参数指定图片路径-h 参数居中显示 fbink -g file/mnt/us/dashboard/output.png,halignCENTER,valignCENTER # 可选添加一个日志记录 echo $(date): Dashboard updated. /mnt/us/dashboard/update.log给脚本执行权限chmod x update_dashboard.sh。现在你可以手动运行./update_dashboard.sh来测试整个流程。如果一切顺利你的Kindle屏幕应该会刷新并显示最新的Dashboard。最后设置定时任务让系统每30分钟自动更新一次。编辑Kindle的crontabcrontab -e在末尾添加一行*/30 * * * * /mnt/us/dashboard/update_dashboard.sh /mnt/us/dashboard/cron.log 21这样每30分钟系统就会自动抓取数据、生成图片并刷新屏幕。4. 进阶优化与问题排查4.1 性能与体验优化技巧减少刷新频率与局部刷新E-ink屏幕全刷时会有明显的闪烁黑屏-白屏-黑屏。为了更好的体验应尽量减少不必要的全局刷新。fbink支持局部刷新-P参数但需要精确计算区域。对于内容变化不大的部分如边框、标题可以尝试只刷新变化的数据区域。更简单的策略是根据数据变化程度决定刷新模式如果只是温度微调可以延迟更新或累积多次小变化后一次更新如果是日期变更跨天则执行一次全局刷新。图片预处理与抖动算法E-ink是黑白或灰阶显示。如果你渲染的图片包含彩色或复杂灰度直接显示效果可能很差对比度低、有毛刺。可以使用ImageMagick工具在服务器端或Kindle上对生成的PNG图片进行预处理如转换为纯黑白二值化、应用Floyd-Steinberg抖动算法来模拟灰度这样显示效果会更清晰。# 安装ImageMagick opkg install imagemagick # 将彩色PNG转换为1位深度的黑白BMP并应用抖动 convert output.png -colorspace Gray -ordered-dither o8x8,8,8,4 -depth 1 output_bw.bmp # 然后用fbink显示BMP文件fbink对BMP支持更好功耗极致优化在脚本执行间隙让Kindle进入深度睡眠。可以通过在cron任务中在脚本开始和结束时发送特定的命令给Kindle的电源管理具体命令因型号而异需要查询社区资料或者直接利用系统休眠机制。确保无线网络Wi-Fi只在数据抓取时开启完成后立即关闭。这可以显著延长充电间隔。UI设计原则高对比度使用纯黑#000000和纯白#FFFFFF避免使用浅灰色在E-ink上容易看不清。大字体考虑到观看距离和屏幕特性字体大小应比普通屏幕更大。避免复杂图形尽量减少细线和复杂图案它们可能在低分辨率下渲染不佳。预留边距屏幕边缘有时存在显示盲区内容不要紧贴边缘。4.2 常见问题与排查实录即使按照步骤操作你也可能会遇到一些问题。以下是我在多次搭建中踩过的坑和解决方案问题现象可能原因排查与解决思路运行wkhtmltoimage报错如Segmentation fault或找不到动态库1. 二进制文件与系统架构不匹配。2. 缺少依赖的动态链接库。1. 使用uname -m确认Kindle的CPU架构下载对应版本。2. 尝试下载静态编译的版本它不依赖系统库。如果已用静态版仍报错可能是内核版本太旧不兼容可尝试更老的版本如0.12.2.1。生成的图片是空白或布局错乱1. HTML/CSS中存在不兼容的属性。2.wkhtmltoimage的视口尺寸设置不对。3. JavaScript执行错误或网络请求被阻塞在本地文件file://协议下。1. 简化HTML/CSS避免使用Flexbox/Grid等高级布局先用绝对定位或简单浮动测试。2. 确保--width和--height参数与HTML中body的尺寸一致并加上--disable-smart-width。3. 检查浏览器控制台可在电脑上用浏览器打开HTML文件测试确保JS能正确加载本地JSON。尝试使用--disable-local-file-access以外的参数组合或改用Python直接将数据渲染到HTML字符串中避免JS。fbink显示图片失败提示FBInk: Failed to open fbdev1. 帧缓冲区设备权限问题。2. 当前不在图形界面framebuffer未激活。1. 确保以root用户运行。2. 确保Kindle处于“已解锁”状态即已退出屏保在主页或已启动KUAL。在屏保状态下framebuffer可能被锁定。可以尝试在脚本开头加一小段延迟sleep 5或发送一个模拟按键事件唤醒设备需额外工具。屏幕刷新后残留鬼影Ghosting严重E-ink屏幕特性长时间显示静态图像后切换新画面时旧图像的痕迹会残留。1. 定期如每24小时或每次重大内容更新时执行一次全刷清屏。fbink命令fbink -k可以强制全刷。2. 在你的主控脚本中每隔几次普通更新后插入一次fbink -k命令。3. 避免在短时间内频繁刷新给屏幕足够的恢复时间。Cron定时任务不执行1. Cron服务未运行。2. 脚本路径错误或没有执行权限。3. 环境变量问题cron的执行环境非常精简。1. 检查cron服务状态ps | grep cron。2. 在cron命令中使用绝对路径如/mnt/us/dashboard/update_dashboard.sh。3. 在脚本开头显式设置环境变量如#!/bin/sh下一行添加PATH/usr/local/bin:/usr/bin:/bin并确保wkhtmltoimage和fbink的路径在PATH中或使用绝对路径调用。天气API请求失败1. 网络未连接。2. API密钥无效或请求次数超限。3. Kindle的SSL证书过旧无法验证某些HTTPS站点。1. 在脚本中增加网络检查逻辑如ping -c 1 8.8.8.8。2. 检查API控制台确认密钥和调用量。3. 尝试使用curl的-k或--insecure参数绕过证书验证不推荐或更新Kindle的CA证书包操作复杂。更简单的方法是在本地局域网搭建一个简单的代理服务器如用树莓派运行一个Python HTTP服务让Kindle通过HTTP访问这个代理由代理去请求外部HTTPS API。4.3 扩展思路让Dashboard更强大基础功能实现后你可以根据兴趣无限扩展更多数据源日历集成使用Google Calendar API或读取本地ICS文件解析出今日/本周事件。任务列表集成Todoist、Microsoft To Do或滴答清单的API。新闻头条解析特定新闻网站的RSS feed。股票行情调用免费的财经API注意频率限制。智能家居状态显示Home Assistant或米家设备的状态。交互功能有限虽然E-ink不适合复杂交互但可以借助Kindle的物理按键或触摸屏实现简单操作。例如通过KUAL菜单创建多个Dashboard页面用按键切换或者利用触摸事件点击某个区域触发一次特定数据的强制刷新。多屏与轮播如果屏幕足够大可以设计多屏信息通过定时或按键进行轮播显示。移植物联网平台将整个逻辑移植到树莓派Zero W Waveshare E-ink屏的组合上。树莓派性能更强可以运行更复杂的渲染引擎如Headless Chrome连接更多传感器温湿度、空气质量打造一个功能更丰富的环境信息站。这个项目的乐趣在于它结合了硬件、软件和设计。从让一块旧屏幕重新焕发生机到精心编排每一个像素的显示整个过程充满了创造的满足感。它不再是一个被动的信息接收终端而是成了一个由你完全定义、安静陪伴的数字伙伴。