../
来传纸条吧 ========== 2022-08-30 之前有两个分别叫喵喵机和咕咕机的热敏打印机产品,里面最有趣的功能就是传纸条。可 是喵喵机的传纸条功能不知道为什么下线了,产品主打变成了学生错题打印机。不过这个 功能也不难实现,所以这里就用Telegram机器人和POS打印机自己做一个。## 申请Telegram机器人 首先打开BotFather,用/newbot命令申请创建机器人,如图:
输入完名字和ID之后会得到一个令牌(token),需要存下来。 ## 选购POS打印机 市面上的POS打印机以热敏打印机为主。但是热敏打印机有两个缺点: - 热敏纸上的涂层是一种低毒材料 - 热敏纸过几周之后就会褪色 但是好处是便宜:
此外还有针式的小票打印机,只需要普通纸带,也不会褪色,常用于发票打印。可价格却 也高出不少:
具体选哪种就见仁见智了。这些打印机都是通过USB口和计算机连接,在软件层面看都是一 样的。 ## 测试打印机 这里我选了在Linux操作系统下使用打印机。因为Linux比较适合嵌入式系统,可以用树莓 派这样的低功耗单板电脑。此外,Linux内核里面是自带USB打印机驱动的,比Windows还要 方便。用USB线把打印机连接到电脑上之后,用dmesg命令可以查看设备信息: $ sudo dmesg |grep -i printer [ 2.249791] usb 2-2.1: Product: USB PRINTER [ 2.249792] usb 2-2.1: Manufacturer: Printer [ 3.826349] usblp 2-2.1:1.0: usblp0: USB Bidirectional printer dev 4 \ if 0 alt 0 proto 2 vid 0x0483 pid 0x070B 如上述命令所示,新增了`usblp0`的打印机设备。此时`/dev/usb`目录下也会出现一个字 符设备: $ ls -l /dev/usb/ total 0 crw-rw---- 1 root root 180, 0 Aug 29 05:16 lp0 然后把这个设备的所有者改成成自己: sudo chown $USER:$USER /dev/usb/lp0 向这个字符设备中输入文本就可以开始打印了: echo "The quick brown fox jumps over the lazy dog." > /dev/usb/lp0 如果需要输入中文的话要留意,现在国内的热敏打印机大部分都是只支持GBK字符集的,需 要做编码转换: echo "我能吞下玻璃而不伤身体。" | iconv -i utf-8 -t gbk > /dev/usb/lp0 操作系统重启之后设备的所有者会恢复成root,需要修改udev配置: echo -e KERNEL=="lp0", \ SUBSYSTEM=="usbmisc", \ ACTION=="add", \ OWNER="$USER", \ GROUP="$USER" \ | sudo tee -a /etc/udev/rules.d/99-perm.rules ## 编写Telegram机器人 写Telegram机器人的话还是Python糊起来最容易! 首先下载Telegram机器人库: sudo pip3 install python-telegram-bot 本来讲道理应该用`virtualenv`之类的工具,不过我这里图省事直接全局安装了。 然后是代码: # 这里需要改成之前申请的令牌 TOKEN='xxxxxx' import logging from time import localtime, strftime from telegram import ForceReply, Update from telegram.ext import Updater, CommandHandler, MessageHandler, Filters logging.basicConfig( format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO ) def printer_output(content): # 需要以GBK编码打开设备文件 with open('/dev/usb/lp0', 'w', encoding='gbk') as fp: fp.write(content) def start(update, context): user = update.effective_user update.message.reply_text('来传纸条吧!') def print_msg(update, context): if update.message.text is None or update.effective_user is None: update.message.reply_text('错误: 不支持的消息类型') return user = update.effective_user name = user.first_name if user.last_name is not None: name = name + ' ' + user.last_name # 忽略名字里面的非GBK字符 # 或者可以遍历一下字符串,把非GBK字符变成口口口 name = name.encode("gbk", errors='ignore').decode("gbk") if user.username is not None: name = name + ' @' + user.username content = '-------------------------\n' content = content + 'from: ' + name + '\n' content = content + 'date: ' + strftime("%Y-%m-%d %H:%M:%S", localtime()) + '\n\n' content = content + update.message.text content = content + '\n-------------------------' content = content + '\n\n\n\n' try: printer_output(content) except Exception as e: update.message.reply_text('纸条传送失败: ' + str(e)) return update.message.reply_text('已送达') if __name__ == '__main__': updater = Updater(TOKEN) dispatcher = updater.dispatcher start_handler = CommandHandler('start', start) dispatcher.add_handler(start_handler) dispatcher.add_handler(MessageHandler(~Filters.command, print_msg)) updater.start_polling() updater.idle() 因为国内的网络问题,机器人没有办法直接连上Telegram的API服务器,所以这里要用代理, 最方便的是`proxychains-ng`: # RedHat系: $ sudo yum install proxychains-ng # Debian系 $ sudo apt-get install proxychains-ng 然后修改配置文件`/etc/proxychains.conf`,在ProxyList这一节加上你的代理地址和端 口,例如socks5一般是用localhost的1080端口: [ProxyList] # add proxy here ... # meanwile # defaults set to "tor" socks5 127.0.0.1 1080 最后运行机器人: proxychains -q python3 bot.py 顺利的话,一个可以传纸条的打印机应该就已经可以工作起来了。 ## 总结和进阶 到这里,这个传纸条的功能还很有限,只能打印GBK编码的字符文本,如果需要更复杂功能, 可以看一下python-escpos。市场上几乎所有的POS打印机都是用 ESCPOS协议和计算机交互 的。利用ESCPOS协议中的图片打印功能,可以打印条形码、二维码、图片,都是可以实现 的。 对于UTF-8编码的文本,如果包含韩文、emoji等不属于GBK字符集的字符,也可以用图片打 印的功能来间接实现:自己先在电脑上渲染成图片,然后再打印。 -------------------------------------------------------------------- Email: i (at) mistivia (dot) com