惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

腾讯CDC
GbyAI
GbyAI
C
CERT Recently Published Vulnerability Notes
S
Security @ Cisco Blogs
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Hacker News
The Hacker News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
P
Proofpoint News Feed
C
Cyber Attacks, Cyber Crime and Cyber Security
S
Securelist
Security Latest
Security Latest
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Simon Willison's Weblog
Simon Willison's Weblog
Latest news
Latest news
T
Tor Project blog
T
Threat Research - Cisco Blogs
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Spread Privacy
Spread Privacy
K
Kaspersky official blog
T
The Exploit Database - CXSecurity.com
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
V2EX - 技术
V2EX - 技术
L
Lohrmann on Cybersecurity
Google Online Security Blog
Google Online Security Blog
Cyberwarzone
Cyberwarzone
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog
C
Cybersecurity and Infrastructure Security Agency CISA
Attack and Defense Labs
Attack and Defense Labs
大猫的无限游戏
大猫的无限游戏
Schneier on Security
Schneier on Security
H
Heimdal Security Blog
O
OpenAI News
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
AI
AI
H
Hacker News: Front Page
博客园_首页
博客园 - 【当耐特】
L
LINUX DO - 最新话题
MyScale Blog
MyScale Blog
量子位
Vercel News
Vercel News
C
Cisco Blogs
L
LINUX DO - 热门话题
Y
Y Combinator Blog
T
Threatpost
爱范儿
爱范儿
P
Privacy & Cybersecurity Law Blog

少数派

派早报:Google 发布 Fitbit Air 等 - 少数派 「新人报到」確認需求,再開始 - 少数派 从 SOLO 独立开发者社区,我看到了越来越多开发者开始做自己的产品 - 少数派 我怎么管理那些"不常做,但总会忘"的生活事项 - 少数派 人形机器人量产元年,数据才是具身智能的“生死线” - 少数派 BuhoLaunchpad 高度还原 Mac 启动台:开发历程与思考 - 少数派 五年陪伴依然不舍,DIY 换壳后让罗技 MX Master 3 继续服役 - 少数派 新玩意 240|少数派的编辑们最近买了啥? - 少数派 一日一技|为什么你应该关闭 iOS 的键盘声音 - 少数派 我做了个插件和 Skills,一键提取任何网站的设计规范 Design.md - 少数派 住在三四线城市的你,该开始录播客了 - 少数派 甘南秘境,大白高国 - 少数派 AI的审美:谁让把我变成川内倫子 - 少数派 返工怎能不烦恼,打工人片单总有一部是你的「嘴替」 - 少数派 为了让「上厕所」更健康,我做了一个小工具 - 少数派 AI + Skill,能够让生成的文章去除 AI 味吗? - 少数派 新玩意|韶音OpenDots ONE 耳夹式耳机 - 少数派 《美满》| 在每一个春天的晚上相爱(362) - 少数派 新玩意|优篮子 PS01 MagSnap 磁吸支架 - 少数派 自我整合手记 | 我开始早睡了:用稳定规则,为自由托底 - 少数派 用龙虾(OpenClaw)两个多月,我最深的12个体会 - 少数派 听歌时间到,12 张你可能错过的 2025 华语乐坛好专辑 - 少数派 承诺能追吗 - 少数派 macOS 26启动台没了? 我做了个不一样的App启动器 - Keboard - 少数派 《四海为家的人》| INTJ对话INTJ(361) - 少数派 你发过的那些黑历史,是时候一次清干净了 - 少数派 新玩意:安安静静玩,越玩越专注:计客密码机 - 少数派 iPad 用户首次体验 Android 平板:vivo Pad6 Pro - 少数派 数据逻辑强 - 少数派 极北行+ | 一路向北,探访日本至北之地 | 001 - 少数派 万字剖析:千问App深度体验报告(2026) - 少数派 在2026年,如何真正防止别人抄袭你的作品 - 少数派 怎么用 50 块搭个 AI 语音助手?我踩了 3 天坑 - 少数派 YeeroAI:让 AI 对话真正成为知识管理的一部分 - 少数派 爬泰山 - 少数派 「旅图显影」 App 更新:这次,我们补上了一点「手感」 - 少数派 假期出门太折磨?我的 23 条经验帮你规划惬意旅行 - 少数派 工作流会变吗 - 少数派 Claude Opus 4.6 怎么用最省钱?我测了 5 种方案 - 少数派 GPT Image 2 让图文并茂不再稀罕 - 少数派 用户侧出发——什么是AI,我要不要学习? - 少数派 找片、转存、整理、播放一条龙!让你的付费网盘值回票价 - 少数派 欢迎试用!日课一问2.0插件 - 少数派 自己做的MDeditor,原本想购买 Typora 试了两次支付不成功,干脆自己做一个 - 少数派 vibe coding了一个 3MB 的小工具,让 ~/Downloads 彻底告别混乱 - 少数派 因为受不了 Mac 的风扇策略,我做了一个风扇控制工具 - 少数派 别只怪模型 - 少数派 Warp 终端的 AI 功能怎么用?我测了一周的体验 - 少数派 AI 写代码老是出 bug?这 5 个配置我后悔没早知道 - 少数派 「新玩意」苹果出相机可能就这样:Sigma BF + 45mm F2.8 DG Contemporary - 少数派 一个面向2030年的AI操作系统是什么样子的:浅谈cola这款有灵魂的Agent - 少数派 别只看写代码 - 少数派 每天解决10个问题,还是一口气攻坚解决400个? - 少数派 AI 交易机器人怎么搭?我用 Claude 跑了一周实盘 - 少数派 Maptoposter Online:把你爱的城市画成艺术海报 - 少数派 Function Calling 怎么用?我测了 3 个模型发现差距真大 - 少数派 Legend Talk:我做了个 AI 圆桌,让 160 位思想家围着你的问题转 - 少数派 如何找到自己的蓝方?在小县城寻找压力测试 - 少数派 语音输入与软件接口|2026年聊AI时,我们都聊些什么(上) - 少数派 混动已经卖爆,纯电又来补刀——钛7闪充版简直“不讲武德” - 少数派 本月玩什么|朋友收藏、识质存在、沙罗周期 - 少数派 为什么要每天坚持输出? - 少数派 Claude API 挂了好几个小时,你的项目有备用方案吗? - 少数派 Function Calling 没你想的复杂——我用它做了个有点用的工具 - 少数派 登录系统立即播放视频或者图片音乐的软件 - 少数派 我为什么创建 FlipHTML5 下载工具 - 少数派 残局没电?多品牌外设电量统一管理软件EasyBluetooth已支持RTSS游戏内显示以及AIDA64 - 少数派 前往通义路的路 - 少数派 太好看了,媲美Sun的个人导航页,NAS部署星云门户 - 少数派 乌黑嘴唇“一键检测”上线了 - 少数派 派早报:Claude AI 接入多个创意软件生态、FILCO 生产方接手品牌等 - 少数派 【更新】BearCLI、Claude 连接器与 MCP 服务器 - 少数派 记了上千条流水,还是看不懂财务?我做了一个让 AI 读懂账本的工作台 - 少数派 MINI R56 升级原厂 Sport 模式 - 少数派 新玩意 | 一棵柠檬树(仿真版) - 少数派 Momenta的“物理AI”野望,需迈过“含摩量”这道关 - 少数派 网页直接投屏控制手机!NAS一键部署PandaScrcpy,流畅丝滑可远程。 - 少数派 众测|邀你一同探索随身 AI 硬件入口 YoooClaw C·ONE - 少数派 2050大会:分享时间是真诚 参会记 - 少数派 iPad 赋能电影创作:国内首部宣纸手绘长片《燃比娃》的幕后故事 - 少数派 AI的审美:我用 8 个大模型给 100 张旅行照片打分 - 少数派 普通人如何破圈?去参加一个本地协会 - 少数派 把极空间的图标全换了,主题DIY全攻略打造你的专属NAS桌面 - 少数派 电子便签墙,帮你实现便签自由 - 少数派 我如何用三个 CLI 工具取代文档创建需求 - 少数派 原来真的有人可以玩一辈子 - 少数派 社区速递 139 | 派友热议三月买了啥、复古单反尼康 Df 体验 - 少数派 06 作品的赏析与评价 - 少数派 TDS REVIEW|索尼 WF-1000XM6 降噪真无线耳机体验 - 少数派 35.98万起售的第二代腾势D9,我看重的不是堆料,而是不凑合 - 少数派 鼠须管 Squirrel 皮肤配置指北 - 少数派 从watch ultra2换到redmi watch6 - 少数派 派早报:阿里巴巴发布视频生成模型 HappyHorse 1.0 等 - 少数派 别迷信1M - 少数派 家人们天塌了!网盘“大封杀”,多个渠道多条路,NAS部署PanHub - 少数派 AI与人勾心斗角!NAS一键部署AI狼人杀,假日休闲必备。 - 少数派 电商必备!Comfyui工作流批量生图插件,一次生成12张!支持Nano banana pro模型 - 少数派 Comfyui工作流配置Gpt-image-2模型教程,0.03/张 - 少数派 OpenClaw第三方APi怎么配置?可使用Gpt-image-2模型 - 少数派 会员社区话题精选 Ep. 103 - 少数派
抓包解协议,代码造布局:电子墨水价签改造 NAS 监控屏小记 - 少数派
2023-03-26 · via 少数派

我为什么要买墨水屏产品

事情的起因是这样的,一年前,社交媒体上就已经有很多技术宅在自己玩一些微雪的墨水屏了,看着他们又是焊板子又是 PCB 的真的是馋死我了。

但苦于自己是软件出身,没有一点硬件的底子,我就在想,能不能买一个现成的,然后自己再慢慢地去分析原理呢?

于是我就持巨资买了两块超市用的价签,一块 65,带支架,有 App 控制,可以批量添加。

image-zglb-dppx.png
现在居然还涨价了……理财产品实锤

然后我拆了其中一块想试下能不能用我树莓派的视频输出去控制它。

然后……就悲剧了。

我发现这玩意儿的排线跟树莓派根本就不兼容……

image-eosd-rxjp-nuvf.png
被我拆掉的尸体,组装回去还能用,但我发现我没法用树莓派去接线驱动他

66 块钱就这么没了!

还有另一块作为我的备件一直躺在箱子里待了半年多。

废物再利用,另辟蹊径

直到今年年初,我 NAS 的硬盘被我用到了 80%,然后迅雷还在卯足了劲儿在往硬盘里塞东西,我每天不得不多次打开我的管理界面去检测 NAS 当前还有多少余量可以用。

然后我就想到了它,墨水屏,这东西显示的时候不耗电,只有刷新的时候才会用一点点电,简直就是为监控状态而生的屏幕啊。

所以我就又下定了决心去想驱动它的办法。

上次用硬件驱动的路子走不通了,学习成本过高。我开始另辟蹊径,往软件驱动上靠:我能不能去找到控制它刷新的协议呢?

答案是肯定的。

这类墨水屏走的都是低功耗蓝牙控制的路子,手机蓝牙发送数据都是可以通过 logcat 这个工具进行抓包,说干就干。

这是 logcat 抓取的所有的手机运行日志:

image-fzlx-bmwp.png

显然有很多是我们不需要的信息,这严重干扰了我的分析工作,那就加一个过滤条件,只接受蓝牙相关的信息。

还是看不出什么内容,只是很不相关的日志输出:

image-yijd-rcmn-nrqm.png

只能根据时间节点一点点翻 logcat 日志了,此时我发现一个值得关注的信息,在蓝牙发送的那段时间的日志中,有一个非常规律的,也很像有点儿内容的写(write)命令:

image-qedh-eiwd-pzkk.png
识别度 AAAA

于是我就把这个关键字作为单独的日志过滤条件重新进行了一次抓包,事情突然就明朗了,这就是蓝牙墨水屏的手机 App 控制协议,而且协议的内容也非常容易理解:

image-jlrd-hial-pnub.png

竖向看,注意到那个 01 02 03 04 05 06 了嘛?

为了信息发送的稳定性,开发者把这个屏幕的发送信息切成了一段一段的内容,分开发给蓝牙墨水屏屏幕。在发送结束后,再发送命令给墨水屏统一控制刷新一次,这样就完成了屏幕的刷新。

接下来我详细分析一下我对这段协议的理解。

报文分析,找到协议规律

可以参考上边的报文内容,并结合当前的分析内容看。

01-25 17:11:24.844 25455 25455 E write: total=1,13 01 b4 ff ... ff ff 4c

这是蓝牙发送协议的内容部分,报文的起始内容是 13 01 b4 ff ... ff ff 4c,其中:

  • 13:命令字,标识当前的内容是显示内容,对应到墨水屏的显示控制部分的地址
  • 01:报文顺序,通过上边截图(竖着看),也能看出,开发者是把屏幕的内容切割成一段一段分开发给屏幕的
  • b4:16 进制数字,代表 180,数一下 b4 后边的报文也就是 180 的长度(最后还有一个较短的尾巴,看下边说明)
  • 4c:校验位,防止当前这段报文在传输过程中有内容没收到或者传输错误,所以增加一个校验位,来保证当前报文是完整的
  • ff:这以下是报文内容,下边细说。

这种报文一共出现了 26 次,第二十七次有一点不同:

01-25 17:11:34.142 25455 25455 E write: total=1,13 1b 38 ff ... ff ff c8

可以看到,除了长度(38,即十进制 56)以外,报文的规则仍然符合我们上述的分析。

那么我们现在就可以来总结一下这个命令字 0x13 的所有内容了:

  • 总长度为 180×26+56 = 4736(180 内容长度的报文重复了 26 次,又加上了一个 56 内容长度的尾巴)
  • 已知的情况是:我们的墨水屏屏幕分辨率为 296×128,是 4736 的 8 倍。那缺失的这个系数 8 哪去了呢?

我们知道,ff 是 16 进制数,换算为 10 进制是 255,换算为 2 进制是 11111111

11111111,这不正好是 8 个长度位吗?

事情开始明了了,每个 16 进制数含有 8 个二进制数,其值 10 分别对应墨水屏的黑色和白色状态。这样,每个 16 进制数就可以控制八个墨水屏像素。

那我们的等式就成立了:报文含有 4736 个 16 进制数,正好可以控制 8 倍于它的像素总数 296×128。

因为我买的是三色显示,所以除了显示黑白,这个屏幕还可以显示红色。红色报文的控制跟上述类似,只是命令字不同(从 0x13 变成了 0x12),就不再赘述。

新的问题,蓝牙连接

搞定了这块屏幕的控制协议,接下来就是怎么把协议发过去了。到了这一阶段就彻底没有可能通过报文分析,只能盲猜了。

我查了一些低功耗蓝牙的连接资料,同时一步一步地写代码来测试,最终还是摸索到了连接蓝牙并发送的方法了

const onCharacteristicFound = (_error, services, _characteristics) => {
      const characteristic = services[0].characteristics[0]
      characteristic.once('notify', (state) => { log('notify: ' + state) });
      characteristic.once('write', () => { }, (res) => {
                             log('write get response: ' + res)
      })
      setTimeout(() => {
            sendData(characteristic)
      }, 250)
}

const onDescover = (peripheral) => {
      log('searning...')
      if (peripheral.connectable === true && peripheral.state === 'disconnected') {
            if (peripheral.advertisement.localName === '你的蓝牙设备识别码') {
                  stopScanning()
                  currentDevice = peripheral
                  peripheral.once('connect', () => {
                        log('Connected !!! ')
                        peripheral.discoverSomeServicesAndCharacteristics(
                                    ['服务特征码1'], 
                                    ['服务特征码2'],
                                    onCharacteristicFound);
                  });
                  peripheral.once('disconnect', () => {
                        log('disconnected !!! ')
                  });
                  peripheral.connect()
            }
      }
}

以上代码就是搜索蓝牙、连接蓝牙、连接服务、发送数据的全部代码了,当然,完整的项目代码晚点我也会上传 GitHub,欢迎大家多多 Star,多多提意见。

最终效果

image-igpa-anwy-jvhg.png

屏幕其实挺小的,2.9 寸

在这块小屏幕上,分别展示了

  1. 我的 NAS 的两块存储池的使用情况
  2. NAS 的 CPU、内存占用情况
  3. 树莓派的内存状态
  4. 树莓派的 CPU 状态
  5. 当前信息的刷新时间

不多,但是也够用了。

其实在代码上我还有一些内容忘记聊了,关于显示内容的控制。

上边的信息看起来挺简单的,但把它换算成一个一个像素点其实还是蛮复杂的,需要分析字库字形、图形缩放等等,时间成本过高。

我突然想到了 Canvas。Canvas 就是一个可以定制显示画布像素的完美工具,而且在上边可以做几乎任何事情。说干就干,我把需要显示的内容通过 Canvas 绘制出来,然后再转换成一个一个的像素信息,然后再通过黑白红颜色的 RGB 值来决定最终发送的报文信息,搞定!

我把这个程序跑在我的树莓派上,然后 NAS(见我之前写过的文章)上设置了一个定时任务,每隔一段时间就推送信息到树莓派上,然后树莓派再通过蓝牙把信息发送给墨水屏。

image-jgup-bsod-tlyy.png

如果你也有兴趣使用,可以找一个树莓派这样的低功耗设备,克隆我的 GitHub 项目,然后运行:

yarn
node app.js

更多说明请参考项目的 Readme。

这感觉,才叫自动化啊 😄 😄 😄

总结

整个项目如果从买设备开始算跨度倒还挺大的,不过此次 Hack 的时间倒不长,前前后后也就一两周时间,而且都是晚上下班或者用周末时间来做的。

当然啦,如果是熟悉这个领域的大佬来搞,可能所用的时间更短,毕竟我还是一个小前端。哈哈哈。

希望我可以保持这种 Hack 精神,因为这真的是太有意思了。

希望大家也可以分享更多类似的经历,毕竟我知道自己在这个折腾的过程中很开心,相信大家知道了之后也会替我开心(并不),尤其是那些想动手还没动手的人,说不定已经跃跃欲试了。

Fun to life, fun to coding~