通过浏览器控制bartender10.1打印程序,首先需要考虑浏览器怎么调用外部程序,外部程序怎么控制bartender进行打印?控制bartender打印,可以使用bartender 自动化(automation)版提供的SDK进行调用,使用bartender SDK编写脚本程序 从而控制bartender进行打印。浏览器通过自定义协议调用外部程序。
为了实现脚本程序和自定义协议不会根据产品种类增多而泛滥话,我们需要支持自定义协议支持参数传递,脚本程序可以接受自定义协议的参数从而实现根据不同产品打印不同标签的目的。
1.定义打印协议:
我定义的打印自定义协议为bartender://mes地址,mes账号,模板文件名,比如bartender://127.0.0.1,13800138000,jishen,注册脚本如下:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\bartender]
@="bartenderProtocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\bartender\DefaultIcon]
@="C:\\bartender\\print.exe,1"
[HKEY_CLASSES_ROOT\bartender\shell]
@=""
[HKEY_CLASSES_ROOT\bartender\shell\open]
@=""
[HKEY_CLASSES_ROOT\bartender\shell\open\command]
@="\"C:\\bartender\\print.exe\" \"%1\""
自定义协议只能传入一个参数,我们通过逗号分隔字符串的方式实现了同时传入MES地址,MES账号和模板文件名称三个参数。自定义协议指定的可执行文件存放于C:\bartender目录下,文件名需要重命名为print.exe。之所以放入C盘,是考虑到很多工位的电脑只有C盘,使用C盘可以保证所有工位都能使用。
2.实现MES获取打印信息和生成打印信息接口:
打印标签一般需要很多参数,由于我们使用逗号分隔参数,如果只通过自定义协议传参,不好控制数量和对应的字段。
于是我们只通过自定义协议传递MES地址,MES账户账号,模板文件名,通过调用MES接口获取其他打印信息。MES地址和MES帐号是获取打印参数使用的,模板文件名是后续选择打印模板使用的。代码实现中,我们根据MES帐号调用MES地址下的/read接口获取打印需要的信息,然后返回给打印脚本。获取打印信息的代码如下:
/**
* @apiNote 获取打印数据
* @param print
* @return
*/
@RequestMapping("/read")
public R read(PrintEntity print){
PrintEntity result = printService.getOne(Wrappers.<PrintEntity>lambdaQuery().eq(PrintEntity::getMobile, print.getMobile()),false);
if(result == null) {
result = print;
result.setSn("0000000000000000");
result.setNumber(0);
}
return R.ok().put("result", result);
}
打印信息是打印之前MES界面通过调用接口插入MES系统的,由于先调用插入接口成功后调用打印脚本,变相的实现了MES界面向打印脚本传递数据的作用。为了保证多工位同时打印信息不错乱,多工位插入数据时插入当前工位的账号信息,获取打印信息的接口也是通过这个账号去获取打印信息的。插入打印信息的代码如下:
/**
* @apiNote 打印信息同步到bartender配置的数据源
* @param print
* @return
*/
@RequestMapping("/print")
public R print(@RequestHeader(value="factory_code",required = true) String factoryCode,
@RequestHeader(value="role_code",required = true) String roleCode,
@RequestBody PrintEntity print){
printService.lambdaUpdate().eq(PrintEntity::getMobile, print.getMobile()).remove();
printService.save(print);
return R.ok("打印信息同步到bartender");
}
3.实现打印脚本:
A.脚本首先从URL的参数中读取MES地址,MES账号,模板文件名;
B.根据MES地址,MES账号调用MES接口获取打印数据信息;根据模板文件名获取模板文件;
C.将接口返回的数据赋值给模板嵌入的数据数据源,先是SN,然后从param1一直到paramN,N是接口中的number字段;
D.打印,完成后关闭模板,退出bartender。
模板文件名直接在参数模板文件名后加bartender模板的后缀.btw。 产品种类有可能很多,直接将模板文件放到C:\bartender会导致C:\bartender下文件很混乱,于是将模板放下放到C:\bartender下的文件夹model也就是C:\bartender\model下。
打印脚本代码如下:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Web.Script.Serialization;
namespace ConsoleApp1
{
class Program
{
private static void Main(string[] args)
{
//1.获取MES账户信息
String mobile = "13800138000";
String host = "127.0.0.1%3A8084";
String product = "jishen";
if (args.Length > 0)
{
string[] arg = { System.Text.RegularExpressions.Regex.Match(args[0], @"(?<=://).+?(?=:|/|\Z)").Value };
String urlArg = arg[0];
String[] urlArgs = urlArg.Split(',');
if (urlArgs.Length > 0) { host = urlArgs[0]; }
if (urlArgs.Length > 1) { mobile = urlArgs[1]; }
if (urlArgs.Length > 2) { product = urlArgs[2]; }
}
host = host.Replace("%3A", ":");
Console.WriteLine(mobile);
Console.WriteLine(host);
Console.WriteLine(product);
//1.打开bartender
BarTender.Application btapp = new BarTender.Application();
//2.选择模板
BarTender.Format btformat = btapp.Formats.Open(@"C:\bartender\model\"+ product +".btw", false, "");
HttpWebRequest request = WebRequest.Create("http://"+host+"/app/product/read?mobile=" + mobile) as HttpWebRequest;
// Get response
PrintEntity result;
using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
StreamReader reader = new StreamReader(response.GetResponseStream());
PrintMessage p = JsonJavaScriptSerializer.FromJSON<PrintMessage>(reader.ReadToEnd());
result = p.result;
}
//传递参数
if (result.number > 0) { btformat.SetNamedSubStringValue("sn", result.sn); }
if (result.number >= 1) { btformat.SetNamedSubStringValue("param1", result.param1); }
if (result.number >= 2) { btformat.SetNamedSubStringValue("param2", result.param2); }
if (result.number >= 3) { btformat.SetNamedSubStringValue("param3", result.param3); }
if (result.number >= 4) { btformat.SetNamedSubStringValue("param4", result.param4); }
if (result.number >= 5) { btformat.SetNamedSubStringValue("param5", result.param5); }
if (result.number >= 6) { btformat.SetNamedSubStringValue("param6", result.param6); }
if (result.number >= 7) { btformat.SetNamedSubStringValue("param7", result.param7); }
if (result.number >= 8) { btformat.SetNamedSubStringValue("param8", result.param8); }
if (result.number >= 9) { btformat.SetNamedSubStringValue("param9", result.param9); }
if (result.number >= 10) { btformat.SetNamedSubStringValue("param10", result.param10); }
if (result.number >= 11) { btformat.SetNamedSubStringValue("param11", result.param11); }
if (result.number >= 12) { btformat.SetNamedSubStringValue("param12", result.param12); }
if (result.number >= 13) { btformat.SetNamedSubStringValue("param13", result.param13); }
if (result.number >= 14) { btformat.SetNamedSubStringValue("param14", result.param14); }
if (result.number >= 15) { btformat.SetNamedSubStringValue("param15", result.param15); }
if (result.number >= 16) { btformat.SetNamedSubStringValue("param16", result.param16); }
if (result.number >= 17) { btformat.SetNamedSubStringValue("param17", result.param17); }
if (result.number >= 18) { btformat.SetNamedSubStringValue("param18", result.param18); }
if (result.number >= 19) { btformat.SetNamedSubStringValue("param19", result.param19); }
if (result.number >= 20) { btformat.SetNamedSubStringValue("param20", result.param20); }
if (result.number >= 21) { btformat.SetNamedSubStringValue("param21", result.param21); }
if (result.number >= 22) { btformat.SetNamedSubStringValue("param22", result.param22); }
if (result.number >= 23) { btformat.SetNamedSubStringValue("param23", result.param23); }
if (result.number >= 24) { btformat.SetNamedSubStringValue("param24", result.param24); }
if (result.number >= 25) { btformat.SetNamedSubStringValue("param25", result.param25); }
if (result.number >= 26) { btformat.SetNamedSubStringValue("param26", result.param26); }
if (result.number >= 27) { btformat.SetNamedSubStringValue("param27", result.param27); }
if (result.number >= 28) { btformat.SetNamedSubStringValue("param28", result.param28); }
if (result.number >= 29) { btformat.SetNamedSubStringValue("param29", result.param29); }
if (result.number >= 30) { btformat.SetNamedSubStringValue("param30", result.param30); }
if (result.number >= 31) { btformat.SetNamedSubStringValue("param31", result.param31); }
if (result.number >= 32) { btformat.SetNamedSubStringValue("param32", result.param32); }
if (result.number >= 33) { btformat.SetNamedSubStringValue("param33", result.param33); }
if (result.number >= 34) { btformat.SetNamedSubStringValue("param34", result.param34); }
if (result.number >= 35) { btformat.SetNamedSubStringValue("param35", result.param35); }
if (result.number >= 36) { btformat.SetNamedSubStringValue("param36", result.param36); }
if (result.number >= 37) { btformat.SetNamedSubStringValue("param37", result.param37); }
if (result.number >= 38) { btformat.SetNamedSubStringValue("param38", result.param38); }
if (result.number >= 39) { btformat.SetNamedSubStringValue("param39", result.param39); }
if (result.number >= 40) { btformat.SetNamedSubStringValue("param40", result.param40); }
if (result.number >= 41) { btformat.SetNamedSubStringValue("param41", result.param41); }
if (result.number >= 42) { btformat.SetNamedSubStringValue("param42", result.param42); }
if (result.number >= 43) { btformat.SetNamedSubStringValue("param43", result.param43); }
if (result.number >= 44) { btformat.SetNamedSubStringValue("param44", result.param44); }
if (result.number >= 45) { btformat.SetNamedSubStringValue("param45", result.param45); }
if (result.number >= 46) { btformat.SetNamedSubStringValue("param46", result.param46); }
if (result.number >= 47) { btformat.SetNamedSubStringValue("param47", result.param47); }
if (result.number >= 48) { btformat.SetNamedSubStringValue("param48", result.param48); }
if (result.number >= 49) { btformat.SetNamedSubStringValue("param49", result.param49); }
if (result.number >= 50) { btformat.SetNamedSubStringValue("param50", result.param50); }
//3.打印一份
btformat.PrintSetup.NumberSerializedLabels = 1;
//4.执行打印
btformat.PrintOut(true, false);
//5.关闭模板
btformat.Close();
//6.退出bartender
btapp.Quit();
}
}
public static class JsonJavaScriptSerializer
{
/// <summary>
/// 内存对象转换为json字符串
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToJSON(object obj)
{
StringBuilder sb = new StringBuilder();
JavaScriptSerializer json = new JavaScriptSerializer();
json.Serialize(obj, sb);
return sb.ToString();
}
/// <summary>
/// Json字符串转内存对象
/// </summary>
/// <param name="jsonString"></param>
/// <param name="obj"></param>
/// <returns></returns>
public static T FromJSON<T>(string jsonString)
{
JavaScriptSerializer json = new JavaScriptSerializer();
return json.Deserialize<T>(jsonString);
}
}
public class PrintMessage
{
public String code { set; get; }
public PrintEntity result { set; get; }
}
public class PrintEntity
{
public String sn { set; get; } //序列号
public int number { set; get; } //编码
//param1到param50
public String param1 { set; get; }
public String param2 { set; get; }
public String param3 { set; get; }
public String param4 { set; get; }
public String param5 { set; get; }
public String param6 { set; get; }
public String param7 { set; get; }
public String param8 { set; get; }
public String param9 { set; get; }
public String param10 { set; get; }
public String param11 { set; get; }
public String param12 { set; get; }
public String param13 { set; get; }
public String param14 { set; get; }
public String param15 { set; get; }
public String param16 { set; get; }
public String param17 { set; get; }
public String param18 { set; get; }
public String param19 { set; get; }
public String param20 { set; get; }
public String param21 { set; get; }
public String param22 { set; get; }
public String param23 { set; get; }
public String param24 { set; get; }
public String param25 { set; get; }
public String param26 { set; get; }
public String param27 { set; get; }
public String param28 { set; get; }
public String param29 { set; get; }
public String param30 { set; get; }
public String param31 { set; get; }
public String param32 { set; get; }
public String param33 { set; get; }
public String param34 { set; get; }
public String param35 { set; get; }
public String param36 { set; get; }
public String param37 { set; get; }
public String param38 { set; get; }
public String param39 { set; get; }
public String param40 { set; get; }
public String param41 { set; get; }
public String param42 { set; get; }
public String param43 { set; get; }
public String param44 { set; get; }
public String param45 { set; get; }
public String param46 { set; get; }
public String param47 { set; get; }
public String param48 { set; get; }
public String param49 { set; get; }
public String param50 { set; get; }
}
}
4.根据不同产品设计bartender模板文件:
设计好打印文件并试打成功之后给变化的组件加数据源,数据源类型为嵌入的数据,名称需要保持和脚本赋值的相同。为了打印程序通用,除了SN使用字段sn以外,其他的字段使用预留字段param1到param50,预留字段使用多少个由number字段控制,从1开始直到number结束。
5.MES系统前端开发:
产品管理页面通过SN搜索查询列表时,调用JavaScript的打印函数。
是否打印需要JavaScript通过调用MES的接口判断,如果SN不满足打印条件则补调用print协议即可。
如果满足,首先调用MES的插入打印信息接口,然后调用print协议。
由于MES设计的任何工站操作,操作成功后都是退出iframe后去查询当前SN,所以执行完任何工站都需要调用下打印函数。而打印需要当前SN在完成特定工站后才能打印,是否能够打印取决于打印函数内部的逻辑。从而实现当特定SN完成特定工站后可以自动打印的功能。
实际操作中,可能会因为打印机缺纸,模板文件误删等原因,即使调用了print协议也未必打印成功。这时候我们可以通过人为去搜索的方式,触发打印函数从而完成补打。这种设计可以兼容正常流程和异常流程,可以说是设计的非常巧妙。
前端传递的字段除了sn外,其余的以通用字段param1到param50控制,调用打印程序只需要传参SN,参数数组,模板文件名即可。MES账户通过浏览器的持久化存储器localStorage获取,number直接取参数数组长度,绝对保证不会出错。
代码如下:
/**
* @api 公共打印程序
* @param sn 标签
* @param params 参数集
* @param btwName 模板文件名
*/
function commonPrintBartender(sn,params,btwName) {
var map = {
mobile:localStorage.full_username,
sn:sn,
number:params.length
};
for(var i = 0;i < params.length;i++){
var index = i+1;
map["param"+index] = params[i];
}
ajax_api("POST","/app/product/print",map);
window.location.href = "bartender://"+encodeURIComponent(window.location.host)+","+localStorage.full_username+","+btwName;
}
6.投入生产:
A.生产电脑上安装bartender10.1 的自动化版本或者高级自动化版本;安装时需要勾选sdk的支持。
B.将bartender.rar直接解压到C盘跟目录下。
C.运行注册表.reg从而支持定义协议,如果杀毒软件拦截,点允许。
D.浏览器最好选择360浏览器,因为自定义协议调用外部exe文件时,360浏览器可以选择记住选择,后面调用会不再弹窗提示。
E.浏览器登录MES进行组装,产测或者称重等操作,完成操作后JavaScript会自动启用print协议调用脚本进行打印。
7.下载地址:
bartender 10.1下载地址:http://www.xue51.com/soft/1449.html
bartender 10.1 C#SDK下载地址:https://download.csdn.net/download/abcmaopao/13713268