ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

grocy 标签打印实战:基于 Webhook 的标签打印机集成方案

grocy 标签打印实战:基于 Webhook 的标签打印机集成方案 grocy 标签打印实战基于 Webhook 的标签打印机集成方案【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocyGrocy 是一款自托管的家庭库存与家务管理应用ERP beyond your fridge本文聚焦其标签打印Label printing功能Grocy 本身不直接驱动任何特定型号的标签打印机而是通过Webhook 机制把打印请求转发给一个你自建的打印服务。读完本文你将掌握如何在 config-dist.php 基础上启用该功能、理解服务端与浏览器端两种触发方式、读懂 Grocy 发出的完整请求格式并能够基于源码实现自己的标签打印接收端。为什么 Grocy 选择 Webhook 而不是直接驱动打印机标签打印机型号繁多、驱动协议各异作者无法为每一台设备编写适配代码更关键的是Grocy 常常被部署在云 VPS 上与家庭局域网的物理打印机之间根本没有直接网络连接。因此 Grocy 采用了一个轻量级的解耦方案见 docs/label-printing.md每当需要打印时Grocy 向一个配置好的 URL 发送 POST 请求由该 URL 背后的接收端负责真正排版与打印标签。这意味着打印逻辑完全外置Grocy 只负责“告诉”接收端要打印什么内容接收端可以是任何语言实现的服务只要能接收 HTTP POST标签打印机与 Grocy 主机是否同网、是否可达都不再是 Grocy 需要关心的问题。从仓库变更记录看该能力自 3.1.0 版本引入changelog/62_3.1.0_2021-07-16.md通过新增的FEATURE_FLAG_LABEL_PRINTER与LABEL_PRINTER*配置项启用。启用标签打印两处必要配置按照 docs/label-printing.md 的说明启用标签打印需要两步在config.php中把FEATURE_FLAG_LABEL_PRINTER设置为true提供一个负责实际打印的 Webhook 目标地址。相关默认值定义在 config-dist.php 与 config-dist.php配置项默认值作用FEATURE_FLAG_LABEL_PRINTERfalse总开关控制是否启用标签打印不启用则整个 UI 中不出现打印相关控件LABEL_PRINTER_WEBHOOKGrocy 需要打印标签时 POST 到的 URILABEL_PRINTER_RUN_SERVERtrueWebhook 在服务端调用GuzzleHttp还是浏览器端AJAX调用LABEL_PRINTER_PARAMS[font_family Source Sans Pro (Regular)]附加到每次请求的额外参数例如字体LABEL_PRINTER_HOOK_JSONtrue请求体使用 JSONtrue还是普通 POST 表单变量false在 config-dist.php 中FEATURE_FLAG_LABEL_PRINTER与库存、购物清单、菜谱等模块的 Feature Flag 并列默认关闭。一个最小的启用示例Setting(FEATURE_FLAG_LABEL_PRINTER, true); Setting(LABEL_PRINTER_WEBHOOK, http://127.0.0.1:3000/print);配置加载与覆盖机制Grocy 启动时按 app.php 的顺序加载配置先读取数据目录下的config.php再加载config-dist.php作为缺省值来源。每个配置项通过 helpers/extensions.php 中的Setting()函数注册为常量GROCY_*并且支持两级覆盖数据目录下settingoverrides/NAME.txt文件中的内容用于嵌入式模式同名环境变量GROCY_NAMEExternalSettingValue()会把字符串true/false解析为布尔值。所以生产环境也可以用环境变量GROCY_FEATURE_FLAG_LABEL_PRINTERtrue和GROCY_LABEL_PRINTER_WEBHOOK...覆盖而不必改动配置文件。此外 app.php 会通过ConfigurationValidator校验非法配置项写错的配置名会在启动时直接报错退出。Webhook 请求规范字段、格式与两种传输方式文档 docs/label-printing.md 给出了核心请求形态。当打印被触发时Grocy 会发出如下 POST 请求POST /your/printing/api/endpoint HTTP/1.1 productproductnamegrocycodegrocy:x:xxxdue_dateDD:%2021-06-09...各字段含义product产品名称即products.namegrocycode指向某个 Grocy 实体的编码形如grcy:p:13产品 13或grcy:p:13:60bf8b5244b04带库存条目 ID 的特定库存记录详见 docs/grocycode.mddue_date库存条目的最佳食用日期仅当开启保质期跟踪FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING时才会附带...其余字段例如details、stock_entry等结构化数据以及来自LABEL_PRINTER_PARAMS的额外参数默认带font_family。当LABEL_PRINTER_HOOK_JSON为true时请求体改为 JSON 编码字段含义保持不变。服务端模式推荐与浏览器端模式文档明确指出请求既可以由托管 Grocy 的机器通过 GuzzleHttp 服务端发出也可以由浏览器直接 AJAX 发出。两种模式的取舍服务端模式LABEL_PRINTER_RUN_SERVER true速度更快、稳定性更好适合 Grocy 主机能够访问打印服务或打印机的场景浏览器端模式LABEL_PRINTER_RUN_SERVER false当 Grocy 托管机器无法触达你的标签打印机但用户浏览器可以时例如打印机在用户本地局域网、Grocy 在云上必须使用此模式。注意文档中的提醒此时LABEL_PRINTER_PARAMS会被下发到所有客户端并随每个请求发送因此不要把敏感信息放进该配置。这一设计在后端 helpers/WebhookRunner.php 中有清晰的实现WebhookRunner基于 GuzzleHttpClient构建超时 2 秒run($url, $args, $json)根据$json参数选择json或form_params请求体请求失败会写入 stderr 日志runAll()则支持遍历多个 URL 逐一发送。服务端模式控制器中的打印调用链服务端模式下Grocy 的各个 API 控制器在构造好 webhook 数据后直接调用WebhookRunner。以库存产品标签为例controllers/Api/StockApiController.php 中的ProductPrintLabel通过StockService::GetInstance()-GetProductDetails($productId)取产品详情组装product产品名、grocycodeGrocycode::PRODUCT类型、details等字段并合并GROCY_LABEL_PRINTER_PARAMS若GROCY_LABEL_PRINTER_RUN_SERVER为真则(new WebhookRunner())-run(GROCY_LABEL_PRINTER_WEBHOOK, $webhookData, GROCY_LABEL_PRINTER_HOOK_JSON)无论如何都返回组装好的$webhookData供浏览器端模式使用。同样的模式出现在库存条目标签StockEntryPrintLabelcontrollers/Api/StockApiController.php会额外附加stock_entry与due_date、菜谱标签RecipePrintLabelcontrollers/Api/RecipesApiController.php字段为recipegrocycode、杂务标签ChorePrintLabelcontrollers/Api/ChoresApiController.php字段为chore以及电池标签BatteryPrintLabelcontrollers/Api/BatteriesApiController.php字段为battery中。这些接口统一暴露在 API 路由中routes.php、routes.php、routes.php、routes.phpGET /api/stock/products/{productId}/printlabel GET /api/stock/entry/{entryId}/printlabel GET /api/recipes/{recipeId}/printlabel GET /api/chores/{choreId}/printlabel GET /api/batteries/{batteryId}/printlabel即使LABEL_PRINTER_RUN_SERVER为false这些接口仍然返回完整的$webhookData供前端调用后自行发送——这是两种模式能够并存的关键设计。浏览器端模式前端如何接力发送当FEATURE_FLAG_LABEL_PRINTER开启且LABEL_PRINTER_RUN_SERVER为false时布局模板会把 Webhook 配置注入浏览器端的Grocy.Webhooks对象views/layout/default.blade.phpGrocy.Webhooks { labelprinter : { hook: {{ GROCY_LABEL_PRINTER_WEBHOOK }}, extra_data: {!! json_encode(GROCY_LABEL_PRINTER_PARAMS) !!}, json: {{ BoolToString(GROCY_LABEL_PRINTER_HOOK_JSON) }} } };前端统一通过 public/js/grocy.js 的Grocy.FrontendHelpers.RunWebhook(webhook, data, repetitions)发送先把extra_data合并进data再依据webhook.json决定使用$.ajaxJSON Content-Type还是$.post表单向webhook.hook发起 POST失败时只提示一次错误hasAlreadyFailed防重复弹窗。repetitions参数支持同一数据重复发送多次如每单位一张标签。仓库中大量视图脚本都通过这一入口触发打印例如购买入库后按用户选择打印标签public/viewjs/purchase.jsstock_label_type为 1 时打印单张标签为 2 时逐个库存条目打印库存条目编辑表单勾选“Reprint stock entry label”后重印public/viewjs/stockentryform.js产品表单中点击打印 grocycode 标签public/viewjs/productform.js库存总览、库存流水、电池总览、杂务总览、菜谱等页面的打印按钮stockoverview.js、stockjournal.js、batteriesoverview.js、choresoverview.js、recipes.js等。哪些场景会自动触发打印除手动点击打印按钮外Grocy 还在库存业务流中内建了自动打印逻辑全部集中在 services/StockService.php购买入库时AddProduct流程结束后若stock_label_type 1且服务端模式开启会立即发送单张标签services/StockService.php多单位/多条目场景则按“每单位一张”处理services/StockService.php保质期变化自动重印当产品勾选了“Auto reprint stock entry label”对应auto_reprint_stock_label字段见 views/productform.blade.php且“打开/解冻”等操作改变了库存条目的最佳食用日期时Grocy 会自动重新打印该条目标签services/StockService.php 与 services/StockService.php。购买表单中的标签选择控件定义在 views/purchase.blade.php三个选项为0 No label、1 Single label、2 Label per unit用户还可在库存设置中配置默认值product_presets_default_stock_label_type见 views/stocksettings.blade.php。另外库存条目编辑页views/stockentryform.blade.php提供“Reprint stock entry label”复选框用于对既有库存条目重新出签。参考实现与接收端设计建议原文档 docs/label-printing.md 记录了作者的验证环境Brother QL-600 标签打印机 Brother DK-2205 连续 62mm 标签纸Webhook 接收端基于brother_ql_web的一个分支实现作者 fork 并加入了对该请求格式的支持。这套组合验证了“Grocy 只发请求、接收端负责排版打印”的完整链路。对于自己实现接收端可以按以下要点设计暴露一个 HTTP POST 端点按LABEL_PRINTER_HOOK_JSON的设置解析 JSON 或表单数据读取product/chore/battery/recipe等实体名称字段作为标签主文本将grocycode字段编码为可扫描的条码DataMatrix 或 Code128见 docs/grocycode.md这样用户用 Grocy 的条码扫描/输入功能就能定位到对应实体或具体库存条目若收到due_date形如DD: 2021-06-09排版时把日期醒目标注在标签上尊重LABEL_PRINTER_PARAMS中的额外参数如默认的font_family作为排版选项做好失败处理Grocy 服务端模式仅把失败写入 stderrhelpers/WebhookRunner.php不会阻塞业务操作接收端应尽快返回并自行记录日志。与 Grocycode 的配合标签上打印的grocycode是连接“标签”与“库存数据”的桥梁格式定义在 docs/grocycode.md 与 helpers/Grocycode.php 中由魔数grcy、实体标识符p 产品、b 电池、c 杂务源码中还扩展了r 菜谱、对象 ID 以及可选附加数据如库存条目 ID用双冒号连接而成例如grcy:p:13:60bf8b5244b04。Grocy 默认用 DataMatrix 2D 码或 Code128 1D 码编码因为 DataMatrix 在相同信息量下占用空间更小、容错冗余更好且在非平整表面上更易被扫码枪读取。这也提示接收端实现尽量生成 DataMatrix 码扫码枪需开启正确的键盘模拟模式确保双冒号能够被正确录入。常见问题排查要点打印按钮不出现检查FEATURE_FLAG_LABEL_PRINTER是否已开启——它同时控制 UI 控件各 blade 视图与业务逻辑StockService的显隐服务端模式无请求确认LABEL_PRINTER_RUN_SERVER为true并核对LABEL_PRINTER_WEBHOOK可被 Grocy 主机访问注意WebhookRunner的 2 秒超时浏览器端模式无请求确认浏览器能访问LABEL_PRINTER_WEBHOOK例如打印服务在用户本地网络、Grocy 在云端的拓扑并检查浏览器开发者工具中Grocy.Webhooks.labelprinter是否已注入views/layout/default.blade.php字段缺失due_date只在开启FEATURE_FLAG_STOCK_BEST_BEFORE_DATE_TRACKING时附带接收端应对缺省字段做容错配置不生效优先检查config.php是否存在拼写错误ConfigurationValidator会拒绝未知配置名或是否被环境变量/settingoverrides覆盖helpers/extensions.php。通过以上配置与源码分析你现在可以在任何自建服务器、树莓派或云主机上搭建自己的标签打印接收端与 Grocy 的购买、库存、杂务、电池、菜谱模块无缝对接。【免费下载链接】grocyERP beyond your fridge - Grocy is a web-based self-hosted groceries household management solution for your home项目地址: https://gitcode.com/GitHub_Trending/gr/grocy创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表