公司现阶段使用的各个系统中有很多都是使用RF扫码枪进行业务操作,因此学会利用现有系统框架开发能在RF扫码枪上使用的业务功能非常有必要。
使用Win+R
快捷键打开命令窗口,输入以下内容(这里以jac_parts_wms系统中的RF为例,不同的系统输入的网址和端口号是不一样的)。
其中,telnet是协议名 “192.168.10.92”是IP地址,6666是服务端口(配置端口的文件是standardListener.properties)。点击“确定”按钮,进入到telnet登录界面:
输入用户名和密码,按键盘上的“↑”键或者“↓”键切换仓库,
就进入到了模拟RF扫码枪操作的主界面。
主界面上的各种功能就是我们要开发的功能。接着我们来讲解公司现有系统的RF功能的开发步骤:
首先要在kangarooMenu.xml中的Menu
标签中配置在telnet主界面上显示的功能菜单。
举例说明:
上述配置了一个器具签收的功能菜单,配置好之后,就会在telnet主界面上显示如下内容:
我们编写的每一个shell文件都是java文件,由于使用了Spring框架对所有的java对象进行管理,因此要配置bean。公司现有系统都是在shellContext.xml中对RF操作的java类进行配置。
这里还是以器具签收为例:
上述代码中还使用构造函数的方式进行了bean的依赖注入操作,这里不再详述,需要依赖注入可以按上述代码的注入方式进行注入即可。
要在对应的项目文件夹下编写一个名为XXXShell类的java文件。按照继承的父类的不同,目前遇到的shell文件有这么三种:
shell父类 | 作用 |
---|---|
YzBaseShell | 一般用于用户输入的code或者ID等 |
JacPageableBaseShell | 用于批量展示业务数据,可以选择某条数据 |
Thorn4BaseShell | 展示每一条业务数据,并可以输入数量等字段 |
这里以jac_parts_wms系统中RF操作的器具签收功能为例:
签收界面:
代码如下:
package com.vtradex.wms.server.telnet.shell.view;
import java.io.IOException;
import java.util.Map;
import net.wimpi.telnetd.net.Connection;
import org.apache.commons.lang.StringUtils;
import com.vtradex.kangaroo.shell.BreakException;
import com.vtradex.kangaroo.shell.ContinueException;
import com.vtradex.kangaroo.shell.ShellFactory;
import com.vtradex.wms.server.model.base.BaseStatus;
import com.vtradex.wms.server.telnet.pick.WmsPickRFManager;
import com.vtradex.wms.server.telnet.shell.ShellExceptions;
import com.vtradex.wms.server.telnet.shell.YzBaseShell;
import com.yc.utils.common.MyUtils;
/**器具签收*/
public class SignScanPickContainerShell extends YzBaseShell{
public static final String PAGE_ID = "signScanPickContainerShell";
public static final String BOX_TAG = "BOX_TAG";
public static final String ERROR = "";
private final WmsPickRFManager pickRFManager;
public SignScanPickContainerShell(WmsPickRFManager pickRFManager) {
this.pickRFManager = pickRFManager;
}
@Override
protected void mainProcess(Connection connection) throws BreakException,
ContinueException, IOException, Exception {
String messge = "成功";
String boxTag = (String) this.getParentValue(BOX_TAG);
if(boxTag==null){
boxTag = this.getTextField("scan.boxTag");
if (StringUtils.isEmpty (boxTag) || BaseStatus.NULLVALUE.equals(boxTag)) {
this.setStatusMessage(ShellExceptions.ERROR_OVER);
}
boxTag = boxTag.trim();
if(MyUtils.OVER.equals(boxTag)){
forward(ShellFactory.getMainShell());
}
Map<String,String> result = pickRFManager.checkBoxTag(boxTag);
if(!result.get(ERROR).isEmpty()){
messge = result.get(ERROR);
this.forward(SignScanPickContainerShell.PAGE_ID, messge);
}else{
messge = "选择序号";
this.put(BOX_TAG, boxTag);
this.forward(ViewScanPickContainerDetailShell.PAGE_ID, messge);
}
}
}
}
代码讲解如下图:
对上图补充一点:boxTag = this.getTextField("scan.boxTag");
代码中那个的scan.boxTag
是自定义的,并且要对其国际化。国际化如下:
新建一个和XXXShell_zh.properties
的文件,在该文件中编写需要国际化的字段。
该界面主要用于展示,有点类似于表格的概念。话不多说,直接上图:
代码如下:
package com.vtradex.wms.server.telnet.shell.view;
import java.util.HashMap;
import java.util.Map;
import com.vtradex.wms.server.telnet.shell.JacPageableBaseShell;
public class ViewScanPickContainerDetailShell extends JacPageableBaseShell{
public static final String PAGE_ID = "viewScanPickContainerDetailShell";
public static final String TASK_ID = "TASK_ID";
public static final String ITEM_CODE = "ITEM_CODE";
public static final String ITEM_NAME = "ITEM_NAME";
public static final String MOVED_QUANTITY = "MOVED_QUANTITY";
public static final String PRODUCT_LINE = "PRODUCT_LINE";
@Override
public String[] getTableHeader() {
return new String[]{"序号","物料编码","物料名称","数量","产线"};
}
@Override
public String getHql() {
String hql = " SELECT task.id" +
",task.moveDocDetail.item.code" +
",task.moveDocDetail.item.name" +
",task.movedQuantityBU" +
",task.moveDocDetail.productionLine" +
" FROM WmsTask task" +
" WHERE task.signTime is null" +
" /~BOXTAG: AND task.boxTag = {BOXTAG}~/";
return hql;
}
@Override
public String getNextShell() {
Object[] rowData = (Object[])get(ROW_DATA_KEY);
String boxTag = (String) this.getParentValue(SignScanPickContainerShell.BOX_TAG);
this.put(TASK_ID, rowData[0]);
this.put(ITEM_CODE, rowData[1]);
this.put(ITEM_NAME, rowData[2]);
this.put(MOVED_QUANTITY, rowData[3]);
this.put(PRODUCT_LINE, rowData[4]);
this.put(SignScanPickContainerShell.BOX_TAG, boxTag);
return SignScanPickContainerDetailShell.PAGE_ID;
}
@Override
public String getUpShell() {
return SignScanPickContainerShell.PAGE_ID;
}
@Override
public Map<String, Object> getParams() {
Map<String, Object> params = new HashMap<String, Object>();
String boxTag = (String) this.getParentValue(SignScanPickContainerShell.BOX_TAG);
params.put("BOXTAG", boxTag);
return params;
}
}
package com.vtradex.wms.server.telnet.shell.view;
import java.io.IOException;
import java.util.Map;
import org.apache.commons.lang.StringUtils;
import net.wimpi.telnetd.net.Connection;
import com.vtradex.kangaroo.shell.BreakException;
import com.vtradex.kangaroo.shell.ContinueException;
import com.vtradex.kangaroo.shell.Thorn4BaseShell;
import com.vtradex.wms.server.telnet.pick.WmsPickRFManager;
import com.vtradex.wms.server.telnet.shell.ShellExceptions;
import com.yc.utils.common.JavaTools;
import com.yc.utils.common.MyUtils;
public class SignScanPickContainerDetailShell extends Thorn4BaseShell{
public static final String PAGE_ID = "signScanPickContainerDetailShell";
private final WmsPickRFManager pickRFManager;
public static final String ERROR = "ERROR";
public SignScanPickContainerDetailShell(WmsPickRFManager pickRFManager) {
this.pickRFManager = pickRFManager;
}
@Override
protected void mainProcess(Connection connection) throws BreakException,
ContinueException, IOException, Exception {
String messge = "";
Long taskId = (Long)this.getParentValue(ViewScanPickContainerDetailShell.TASK_ID);
String boxTag = (String) this.getParentValue(SignScanPickContainerShell.BOX_TAG);
String itemCode = (String) this.getParentValue(ViewScanPickContainerDetailShell.ITEM_CODE);
String itemName = (String) this.getParentValue(ViewScanPickContainerDetailShell.ITEM_NAME);
String productLine = (String) this.getParentValue(ViewScanPickContainerDetailShell.PRODUCT_LINE);
double quantity = (Double) this.getParentValue(ViewScanPickContainerDetailShell.MOVED_QUANTITY);
output("物料编码",itemCode);
output("物料名称",itemName);
output("产线",productLine);
output("数量",String.valueOf(quantity));
String value = this.getTextField("task.signQty");
Double signQuantityBU = 0D;
if(StringUtils.isEmpty(value)){
signQuantityBU = quantity;
}else{
if(MyUtils.OVER.equals(value)){
messge = "选择序号";
this.put(SignScanPickContainerShell.BOX_TAG, messge);
this.forward(ViewScanPickContainerDetailShell.PAGE_ID,messge);
}
if(!JavaTools.isNumber(value)){
messge = "失败!签收数量不合法!00返回上一级";
this.setStatusMessage(messge);
}
signQuantityBU = JavaTools.stringToDouble(value);
if(signQuantityBU<0 || signQuantityBU>quantity){
messge = "失败!签收数量不合法!00返回上一级";
this.setStatusMessage(messge);
}
}
try {
Map<String,String> results = pickRFManager.signScanPickContainerDetail(taskId,signQuantityBU);
if(!StringUtils.isEmpty(results.get(ERROR))){
messge = results.get(ERROR);
this.put(SignScanPickContainerShell.BOX_TAG, messge);
this.forward(ViewScanPickContainerDetailShell.PAGE_ID,messge);
}
} catch (Exception e) {
e.printStackTrace();
this.reset(e.getMessage());
}
//验证器具单明细是否全部签收
Map<String,String> results = pickRFManager.checkBoxTag(boxTag);
if(!StringUtils.isEmpty(results.get(ERROR))){
messge = "签收完成,继续扫码";
this.forward(SignScanPickContainerShell.PAGE_ID,messge);
}
messge = "选择序号";
this.put(SignScanPickContainerShell.BOX_TAG, boxTag);
this.forward(ViewScanPickContainerDetailShell.PAGE_ID,messge);
}
}
代码讲解如下:
RF功能开发的大致流程就是以上这些,关于RF开发的内容还有很多没有讲到,可自行查看源码分析学习。如有不正确的地方,请各位批评指正,不胜感激!!!