云上驱动打印

Security

用于局域网打印机场景的客户端技能。打印 DOCX/EXCEL/PPT/PDF/图片等类型文件 到网络打印机(9100端口),支持发现、驱动搜索、云端上传、云端转打印数据并通过 9100 下发。Agent 自动化场景下一行命令搞定。

Install

openclaw skills install cloud-driver-print

cloud-driver-print


🔥 Agent 自动化打印 — 一步到位(先看这里)

最常见场景:用户说"打印这个文件到施乐/某打印机,打N份"。

Agent 在非交互环境下,必须带齐所有参数一步执行,脚本有 input() 的地方会 EOF 报错。

标准命令(直接复制改参数)

# === DOCX/PDF 统一入口:DOCX 自动走 _cvturl,超时自动降级 LibreOffice ===
CDF_PRINT_CONFIG_JSON='{"copies":2}' \
  python print_file_for_skill.py /path/to/file.docx \
    --ip 192.168.x.x \
    --driver "Xerox WorkCentre 7835" \
    --no-config-prompt \
    --json

print_file_for_skill.py 内置降级:_cvturl(60s 超时)→ 失败自动 LibreOffice 本地转 PDF 重新上传。

参数速查:

场景必带 flag
非交互环境--no-config-prompt --json
指定份数CDF_PRINT_CONFIG_JSON='{"copies":N}'
黑白/彩打CDF_PRINT_CONFIG_JSON='{"color":"MONOCHROME"}'
单双面CDF_PRINT_CONFIG_JSON='{"side":"DUPLEX"}'
A3/A4 纸张CDF_PRINT_CONFIG_JSON='{"paperConfig":{"name":"A4","width":210,"height":297}}'
驱动未保存search_driver.py "型号" --ip 192.168.x.x --pick 1 --json
IP 未登记discover.py --ip 192.168.x.x

⚡ 三步流程(决策树)

用户说"打印" 
  ├─ 打印机已知?─否→ discover.py --list 或 --ip 登记
  │     └─ 型号为 "-"?→ ipptool 探测型号(详见故障降级 §4)
  ├─ 驱动已保存?─否→ search_driver.py --pick 1 --json 自动选
  └─ print_file_for_skill.py 文件 --ip ... --driver ... --no-config-prompt --json

流程内置降级:_cvturl(60s 超时)→ 失败自动 LibreOffice 本地转换 + 重新上传。无需手动干预。

型号探测参考: references/printer-identification-ipptool.md — EPSON L6270 完整识别案例。


📋 常用命令

打印机管理

python discover.py --timeout 5          # 扫描局域网打印机
python discover.py --list               # 列出已保存打印机
python discover.py --ip 192.168.1.25    # 按 IP 登记单台
python connect_printer.py 192.168.1.25  # 测试 9100 连通性

驱动搜索(非交互用 --pick)

python search_driver.py "Xerox WorkCentre 7835"                      # 只搜索
python search_driver.py --ip 192.168.65.130 --pick 1 --json          # 自动选第一个并回写
python search_driver.py "HP M404" --ip 192.168.1.25 --pick 1 --json  # 指定查询词+自动选

打印

# DOCX/PDF 一把梭(内置转换降级)
python print_file_for_skill.py file.docx --ip 192.168.x.x --driver "..." --no-config-prompt --json

🌐 云端 API 规范

云端服务:https://any.webprinter.cn

函数路径HTTPContent-Type超时
uploadFileMCP/openapi/mcpClient/uploadFileMCPPOSTmultipart/form-data120s
convert_url_to_pdf/openapi/cdf/_cvturlPOSTapplication/json60s
print_for_skill/openapi/cdf/_pfsPOSTapplication/json300s

Headers(所有接口): Accept: application/json, tid: cdf_ai_terminal, ttp: AI

⚠️ 陷阱:form-encoded → 404

_cvturl_pfs 用 form-encoded(application/x-www-form-urlencoded)会返回 HTTP 404,但换 JSON body 后正常。这是路由不匹配,不是接口未部署。代码中这两个函数已使用 _post_json()

curl 调试

# _pfs(JSON body,含 fileName 原始文件名)
curl -s -X POST "https://any.webprinter.cn/openapi/cdf/_pfs" \
  -H "Content-Type: application/json" -H "tid:cdf_ai_terminal" -H "ttp:AI" \
  -d '{"printer":{"driver":"Xerox WorkCentre 7835","name":"Xerox WorkCentre 7835","portType":"NET","portAddr":"192.168.65.130"},"url":"...PDF_URL...","fileName":"新建 DOCX 文档.docx","config":{"copies":2}}'

# _cvturl(JSON body)
curl -s -X POST "https://any.webprinter.cn/openapi/cdf/_cvturl" \
  -H "Content-Type: application/json" -H "tid:cdf_ai_terminal" -H "ttp:AI" \
  -d '{"repoId":"ZIM_STORAGE","path":"EeW88JMOkyAA1Qv5/..."}'

🚫 硬性约束

禁止将原始文件(PDF/DOCX/图片等)直接通过 TCP 9100 或其他端口发送到打印机。

所有打印数据必须经过云端 _pfs 渲染管道生成,客户端只负责从 _pfs 返回的 fileUrl 下载二进制数据后发送到打印机 9100 端口。

❌ 禁止行为:

# NEVER do this — 直接发送原始文件
s = socket.create_connection(('192.168.x.x', 9100))
s.sendall(open('/tmp/file.pdf', 'rb').read())

✅ 正确流程:上传 → _cvturl 转换 → _pfs 渲染 → 下载 fileUrl 二进制 → 发送到打印机


🧯 故障降级

诊断参考文件:

  • references/pfs-empty-fileurl-debug.md_pfs fileUrl 返回 0 字节的完整复现与诊断(含间歇性规律和 fileUrl //0 格式线索)
  • references/epson-l6270-experience.md — EPSON L6270 Series 完整接入参考(发现、IPP识别、驱动、已知问题)
  • references/printer-identification-ipptool.md — IPP 探测打印机型号完整案例
  • references/session-20260515-pfs-cvturl.md — _cvturl 超时处理和接口规范

1. _cvturl 超时 → 内置自动降级

print_file_for_skill.py 已内置:_cvturl 失败后自动调用 LibreOffice 本地转 PDF 并重新上传,无需手动干预。

_pfs 成功后会返回 fileUrl。该 URL 指向二进制打印数据;_pfs 本身不实际触发打印,客户端需要下载该二进制内容并发送到目标打印机的 9100(或记录中的原始 TCP 端口)。

2. _pfs 返回 success 但 fileUrl 下载 0 字节 — 已确认真实故障

现象: _pfs 返回 "success": true + 有效 fileUrl,但从 fileUrl 下载得到 200 OK + 0 bytesprint_file_for_skill.py 报错:发送打印数据失败:下载到的打印数据为空。

根因: 云端驱动渲染管道对特定 PDF 格式/打印机型号未能输出有效二进制数据。_pfs 本身调用成功(业务层面无错误),但渲染产物为空。此 Bug 已在 EPSON L6270 Series + fpdf2 生成的 PDF 上复现。

诊断步骤:

# 1. 直接调 _pfs 获取原始响应
curl -s -X POST "https://any.webprinter.cn/openapi/cdf/_pfs" \
  -H "Content-Type: application/json" -H "tid:cdf_ai_terminal" -H "ttp:AI" \
  -d '{"printer":{"driver":"EPSON L6270 Series","name":"EPSON L6270 Series","portType":"NET","portAddr":"192.168.66.139"},"url":"...PDF_URL...","config":{},"fileName":"test.pdf"}' \
  | python3 -m json.tool

# 2. 下载 fileUrl 验证大小
curl -s -o /tmp/pfs_dl.bin -w "HTTP %{http_code}, size: %{size_download}\n" \
  -H "tid:cdf_ai_terminal" -H "ttp:AI" "<_pfs返回的fileUrl>"

处理方案: print_file_for_skill.py 报错退出,需反馈给用户排查云端渲染管道(联系后端确认驱动/PDF兼容性)。禁止绕过 _pfs 直接发送原始文件。

3. search_driver.py EOF → 加 --pick

无 stdin 时交互式 input() 报 EOF,用 --pick 1 --json 自动选第一个候选。

4. 打印机型号无法识别 → ipptool 兜底

discover.py --ip 返回型号为 -(无法自动识别)时,按以下顺序探测:

优先级方式命令示例成功率
IPP(最可靠)ipptool -tv http://<IP>:631/ipp/print get-printer-attributes.test极高
HTTP 首页curl -s --max-time 5 http://<IP>/中等
SNMPsnmpget -v2c -c public <IP> 1.3.6.1.2.1.25.3.2.1.3.1

IPP 返回的关键字段:

  • printer-make-and-model → 精确型号(如 EPSON L6270 Series
  • printer-device-id → 含 MFG/MDL/CMD 等完整标识
  • printer-info → 打印机友好名称
  • marker-levels → 墨量/碳粉余量(单位 %)
  • pages-per-minute / pages-per-minute-color → 打印速度

典型用法:

# 一步获取型号 + 墨量
ipptool -tv http://192.168.x.x:631/ipp/print get-printer-attributes.test 2>/dev/null \
  | grep -E 'printer-make-and-model|printer-info|marker-levels|marker-names|pages-per-minute'

⚠️ 有些打印机 IPP 监听在 80 端口而非 631,可尝试 http://<IP>/ipp/print


🏗️ 架构

print_file_for_skill.py      ← 入口(上传+转换+下载打印数据+9100发送)
  ├── cdf/ai/skillPrint.py   ← REST 适配层 (uploadFileMCP / _cvturl / _pfs + fileUrl下载/9100发送)
  ├── cdf/ai/config.py       ← 服务地址 + headers 构建
  ├── cdf/ai/searchDriver.py ← 驱动搜索
  ├── printer_store.py       ← 本地 Markdown 打印机记录 (printers/*.md)
  └── driver_workflow.py     ← 驱动搜索→选择→回写 工作流

discover.py                  ← 网络发现 / IP登记 / 列表
connect_printer.py           ← TCP 9100 连通性检查
search_driver.py             ← 驱动搜索 CLI 入口

适配要求

  1. cdf/ai/ 下维护云端服务地址和 headers。
  2. 所有打印请求带 tid: cdf_ai_terminal + ttp: AI
  3. 鉴权通过环境变量 CDF_PRINT_API_KEY 注入 Bearer Token(可选)。

依赖

  • Python 3.10+
  • zeroconf(mDNS 打印机发现,可选)
  • LibreOffice(DOCX→PDF 本地转换降级,必需)