Part II
一台老 iPad 上的 Kiosk 系统设计
Kiosk 源于土耳其语,原意为路边无人看管的书报摊。现指一种独立结构,设计用于在客流量大的地方促进消费者交易或信息共享,可能无需直接人工交互,常引申为自助服务机或信息服务亭的概念。这里放在旁边的 iPad 就是典型 Kiosk 的应用设计。
为什么要用一台老 iPad 来做 Kiosk?
BK_STATION 的 Kiosk 最早来自一个很简单的问题:用户通过手机完成下单以后,走到打印区域时,现场几乎没有数字反馈。
2024 年 5 月开始,我在计划给打印店增加一个电子看板,这样用户真正与现场的打印店交互,而非在手机上下单后到现场盲等。
同期其他的打印店普遍使用便携屏 + HDMI 连接服务器来做 Kiosk 公告板,最基础的就是好看的壁纸 + Windows 原生的打印列表,有的会使用打印平台提供的广告屏能力。这样解决了最基本的问题,即用户下单后,一直到打印机吐完纸之前,都能清晰地看到自己的文件排到第几位了、什么时候才能打印、打印到第几页了。
但这样的一块屏幕至少需要几百元,需要长长的 HDMI 线连接到服务器,而且 Windows 原生的触屏体验也不够好。于是我将目光转向老 iPad。这台二手 iPad mini 3 只需要不到 150 元,自带电池、Wi-Fi、Retina 屏幕和触屏能力,很大程度上利用了老苹果设备的低残值和高性价比。我只需要实现局域网动态页面,然后将 iPad 连上 Wi-Fi 和电源即可。
我计划用引导式访问 + 固定布局 + Bark 通知 SDK + 浏览器来实现 Kiosk 功能。Kiosk 应用是服务器小主机上运行的 Python Flask 应用,通过 Win32 包实现读取打印列表和打印机状态。第一版的前端界面如图所示:
我觉得这样比单纯 Windows 后台打开一个打印列表窗口更像一个友好的用户界面。
右下角的置顶按钮可以在 20 秒倒计时圆环结束后自动返回最顶端(触摸操作会重置这个倒计时),同时页面的置顶目标有两个逻辑:
- 没有任务时,自动置顶到整个页面顶端。
- 有“当前活动任务”时,置顶位置改到“打印机状态”位置。
这样当有任务时,能确保页面始终能显示当前活动的列表。而无操作倒计时也是 Kiosk 类产品的基本特性之一。
此后,这个基于 iPad mini 的 Kiosk 在近两年的时间里一直不断进化,逐步实现了从打印量统计、文件类型统计识别到 Live2D 看板娘、随机播放的“一言”、互动交互界面、物品 AprilTag 视觉检测、打印-空气净化器联动、夜间自助打印、故障自助处理文档等一系列功能。
接下来我会详细讲解我如何在真实应用中迭代整个 Kiosk 设计的。
打印统计看板
我首先想到的是打印页数统计,对用户来说可能未必有用,但这是最能体现整个系统作为一个“活着的店铺”存在的面板:
界面会根据过去 12 小时的打印情况生成柱形图,并根据文件后缀名来分类。这样就能看到:“某天一个课程要开卷考,出现了大量的 PPT 订单”、“某天学校举行双选会,出现了大量单页的 PDF 简历”……图形会随着实际情况变化,Kiosk 看起来真正会和真实的运营情况联动。
文件识别直接通过正则过滤文件扩展名来实现。除了用于统计,还用于文件列表中的标签展示:
提交一份虚拟订单
假装你是打印店的顾客,提交一份文件。任务进入队列后,Kiosk 会显示使用哪台打印机、排到了哪里、还剩多少页。试试不同文件类型,观察普通文档、高质量文件和照片的展示差异。
- 当前排队
- 0 份
- 已打印
- — 页
“高质量打印”和其他特殊业务的展示
在购入新的打印机 GX 5580 后,由于有了第二个纸槽,可以装入两张不同类型的纸。我于是购入了几包 Double A 90 g 纸(相较于普通的 80 g 纸),肉眼可见地有更好的质感提升。配合驱动中设置的高质量打印参数,我开设了另一条“高质量打印”产品线;另外后部进纸器可以装入相纸,因此顺便加设一个 6 寸照片和证件照打印的选项。
视觉物品检测与归还提醒
接下来这个功能,多少有点小题大做的意思,但我自己觉得挺有意思。
我注意到打印区域的公共订书机、固体胶等,经常有人用完后不放回原位。于是就想到:能不能让系统自己知道,哪些工具还没被放回来?
我很想试试这个点子,于是用 3D 打印做了一个物品托盘:
每个物品上都贴有 AprilTag,且托盘本身也有 AprilTag。我通过磁吸固定在架子顶层的摄像头监控物品的情况。
程序会先根据左上和右下两个 Tag 框出感兴趣的区域,然后标记区域内的 Tag 号码来判断一个物品是否在指定区域内。由于打印区域有独立的 LED 照明,相机自动曝光的快门速度很高,识别情况良好。
物品检测以弹窗 Toast 的方式显示在 iPad Kiosk 的右上角,如图所示:
拿走,用完,再放回
点击托盘上的工具,模拟拿取或归还。真实系统通过摄像头识别 AprilTag 的 ID,并通过简单的状态机判断物体的消失与重现。
- 离开托盘
- 无
我无法统计物品放回率有多大程度上来自这个 Toast 弹窗,也有可能 3D 打印的物品托盘本身就让物品有了固定位置。但总之物品使用后的归位率确实比以前更高。
Kiosk 上的故障处理标识
我还想更加充分地利用这台 Kiosk。还记得之前的缺纸处理标牌吗?自从更换了两台打印机后,加纸变得比原先更复杂,且由于纸盒更大,打印机加纸的频率也变得更低,因此我一直没有再去做类似的标牌。有了 Kiosk 后,我们可以将不同打印机的不同错误自助处理教程直接显示在屏幕上,甚至可以根据打印机的错误情况,让 Kiosk 主动弹出加纸教程。我增设了一个“故障排除”入口,用户遇到常见问题,不必再等我回来处理,可以直接在 Kiosk 上查看教程:
后台检测到打印机缺纸时,会主动唤醒 Kiosk,然后显示处理窗口:
让故障变得可处理
模拟任意一台机器缺纸,观察状态提醒和对应的处理指引。受影响的任务暂停,另一台机器仍可工作;恢复供纸后,队列继续打印。把“出了问题”变成用户可以完成的下一步。
- 黑白一号
- 供纸正常
- 彩色二号
- 供纸正常
后台系统与空气净化的联动
购入激光打印机后我就一直担心空气质量问题。现代激光打印机存在的空间污染主要包括小于 100 nm 的超细颗粒和少量挥发性有机物,可能影响小于 5 m 内的室内区域。通风是最主要的解决手段。但当通风不足以依赖时,高换气量的空气净化器的效果有充分理论和实验依据,是性价比很高的措施:HEPA 滤网负责过滤小颗粒;活性炭夹层负责吸收有机挥发物。我在打印机上方放置了一台空气净化器,打印机排出的热气使得周围空气有上升趋势,因此理论上架子顶部的空气净化器是有效的。
有效建立在高换气量上。而高换气量往往意味着噪音。很难让空气净化器一直开着。理论上根据我的宿舍空间和使用的净化器 CADR,考虑射流短路等情况,保守只需要 40 min 即可完成一次能降低 90% 颗粒物的换气。
因此我计划将激光打印机的工作与净化器绑定。
很幸运,米家净化器有官方的 Home Assistant 支持,HA 又有很完善的 API 接口,我可以设计一个打印量-净化协同的策略:
- 只要有打印任务就启动 60% 风量过滤,直到持续 20 分钟没有打印任务。
- 如果过去一小时打印页数大于 110 页,启动 100% 风量的强力净化模式,直到过去一小时窗口的页数小于 80 页后,退回 20 分钟的 60% 风量过滤。
- 其他时间使用 30% 风量,夜间启用风量更小的睡眠模式。
让净化跟着负载走
调整过去一小时的打印页数,模拟待机、常规与强力净化。超过 110 页进入强力档,下降到 80 页以下才回到常规档,避免临界值附近频繁切换。没有打印负载时使用低风量待机。
- 当前负载
- 0 页
- 净化档位
- 待机 · 30%
三种简单的互动设计
接下来介绍一些无关痛痒的用户体验细节:
我希望在打印后,Kiosk 能主动与用户发起互动,分别解决等待过程无聊、用户反馈少、打印问题难以处理的问题。打印后的用户互动有三种形式,会在活动任务被清空后的十几秒后按照比例自动弹出:
在打印之后留一点反馈
触发点赞、满意度问卷或常见问题窗口。不同反馈用不同的操作粒度:点赞只需一次点击,评分表达整体感受,问题选项把反馈转化为具体的排查入口。样机中的反馈仅保存在本次体验中。
- 最近触发
- 尚未触发
我设计了三种互动类型:
- 点赞:单纯的休闲用户互动。可以连赞、有动效,且可以显示当天的总赞数。
- 评分问卷:一共有几种问题,随机选择后提问,用户可以从 0–5(非常不满意、不满意、一般、还行、满意、非常满意)中选择并进行评分。有助于改善服务质量。
- 常见问题弹窗:在用户最需要帮助的时候主动询问帮助。提供几种问题的快捷解决指南:缺纸、卡纸、质量不佳、排版错误、缺页和找不到。这些都是实际运营中高发的打印问题。
互动弹窗会停留一分钟以上的时间,足以覆盖用户等待和翻找的时间。
“一言”与待机提示文本
接下来是轮播文字。我希望 Kiosk 在用户等待过程中也能提供一些有意义的信息。参考游戏加载界面的轮播提示,我在 Kiosk 主页增加了一个一言/提示模块:
内容来自两种来源:
- 来自“一言”(一言开源社区)项目的结构化语句库。有上万条包括但不限于台词、歌词、诗句、网络梗、抖机灵等等内容。因为请求很频繁?(大约十几秒一次,全天候请求),我将整个一言句子库部署在了局域网内。
- 来自小黑店的提示。从几十句提示中轮流播放,包括打印店的使用技巧等。
两种来源按照 1:1 概率随机出现。
句子分行算法很值得聊。我通过多种标点特征和句子长度字数设置惩罚,程序预先计算多种可能的换行解,然后为每种页面宽度和每个句子提供一种合适的换行模式,使得句子尽可能以优雅易读的方式换行。(详见技术报告)
Live2D 看板娘
接下来是 Live2D 看板娘。“MO”是 @樱井檬公开的原创角色,我在此模型提供的能力上,通过 VTube Studio 调整人物参数、绘制带有店铺 Logo 的胸牌贴图,然后通过 oh-my-live2d 运行时在前端加载,实现动画效果。
MO 除了基本的呼吸、眨眼、摇曳动效以外,还提供简单的页面互动。当有 Toast 时,她会看向上方 Toast 的位置;当有弹窗时,会面向弹窗:
原本还想实现预设表情动画,但纯程序的实现略显僵硬,最后只保留了基本的朝向动作。
当页面滑动时,看板娘会隐藏,避免遮挡内容。此外,轮播文字区域也会避让看板娘。
让状态提示有一点温度
试试 MO 的进入、退出与视线变化。
- 模型状态
- 加载中
- 视线
- 正前方
非营业模式与 Kiosk 的联动
接下来聊一下非营业模式:自 2023 年以来,系统后台一直维持一个 23:50 打烊的设定。23:50 之后仍然能下单,但订单会堆积到第二天早 7:50 再打,以免夜间打印吵到睡觉。
但我们的就寝时间并没有那么固定,有时候即使到了 23:50,也未必有人睡觉,其实并不妨碍打印,但因为程序的规则固定 23:50,急需打印的用户只能找人工手动打印。
针对这个问题,我设计了非营业模式的界面,23:50 之后,Kiosk 会切换到这个模式:
打烊,但不用拒绝订单
切换到非营业模式,文件保留在队列中,默认等待次日营业。确实急需打印的人仍可在 Kiosk 内选择“立即打印”;结束非营业模式后,剩余任务恢复处理。
- 当前模式
- 营业中
- 队列任务
- 0 份
非营业模式仍然会暂停打印,但用户可以直接在 Kiosk 上解除暂停。因为如果用户真的到店了,“能否打印”这件事就应该交给现场人员判断,而不是墨守一个写死的规则。用户点击“立即打印”后,会发送请求给后台,解除对应任务默认的暂停状态。
总结
回头看,这套 Kiosk 并没有一个明确的“完成时刻”。最初它只是为了让用户知道自己的文件排到哪里了,后来才逐步接入打印机状态、故障处理、物品检测、空气净化、互动内容和夜间操作。很多功能甚至不是预先规划出来的,而是在真实使用过程中碰到一个问题,再补上一块。
这也让它最后变得不像一块单纯的电子看板。iPad 本身只是一个很便宜的显示终端,真正有价值的是后面那套把打印任务、设备状态、环境信息和用户操作整理到一起的系统。用户不需要知道 Win32 打印队列、AprilTag 或 Home Assistant 在后台怎么工作,只需要在合适的时候看到一条足够清楚的信息,然后知道接下来该做什么。
其中也有一些明显带着个人兴趣的功能,比如一言、Live2D 和点赞互动。它们并不是打印系统必须存在的部分,我也不会把这些东西解释成什么关键产品创新。但对一个长期摆在宿舍角落、每天都会被人看到和使用的界面来说,我还是希望它不只是一个冷冰冰的任务列表。它既承担功能,也多少保留一点这家小打印店自己的性格。
但 Kiosk 始终是一个辅助系统。整个项目中,非常遗憾的一点是打印的小程序和下单平台仍然是第三方的,这使得我很难推进一些真正自定义的用户功能。下一步,我的目标是做一个纯自然语言的打印小程序平台。这个小程序命名为 BK_Station。下一篇中,我将详细描述这个平台的完整产品设计。
