package com.zy.core.thread.impl;
|
|
import com.alibaba.fastjson.JSON;
|
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.serializer.SerializerFeature;
|
import com.baomidou.mybatisplus.mapper.EntityWrapper;
|
import com.core.common.DateUtils;
|
import com.core.common.SpringUtils;
|
import com.zy.asrs.entity.*;
|
import com.zy.asrs.service.BasDualCrnpOptService;
|
import com.zy.asrs.service.BasDualCrnpService;
|
import com.zy.asrs.utils.Utils;
|
import com.zy.common.utils.RedisUtil;
|
import com.zy.core.News;
|
import com.zy.core.cache.MessageQueue;
|
import com.zy.core.cache.OutputQueue;
|
import com.zy.core.cache.SlaveConnection;
|
import com.zy.core.enums.*;
|
import com.zy.core.model.CommandResponse;
|
import com.zy.core.model.StationObjModel;
|
import com.zy.core.model.Task;
|
import com.zy.core.model.command.DualCrnCommand;
|
import com.zy.core.model.param.SendDualCrnCommandParam;
|
import com.zy.core.model.protocol.DualCrnProtocol;
|
import com.zy.core.model.protocol.StationProtocol;
|
import com.zy.core.network.DeviceConnectPool;
|
import com.zy.core.network.ZyDualCrnConnectDriver;
|
import com.zy.core.network.entity.ZyDualCrnStatusEntity;
|
import com.zy.core.thread.DualCrnThread;
|
import com.zy.core.thread.StationThread;
|
import lombok.Data;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.text.MessageFormat;
|
import java.util.*;
|
|
import com.zy.asrs.entity.BasDualCrnpErrLog;
|
import com.zy.asrs.service.BasDualCrnpErrLogService;
|
|
/**
|
* 双工位堆垛机线程
|
*/
|
@Data
|
@Slf4j
|
public class ZySiemensDualCrnThread implements Runnable, DualCrnThread {
|
|
private DeviceConfig deviceConfig;
|
private RedisUtil redisUtil;
|
private ZyDualCrnConnectDriver zyDualCrnConnectDriver;
|
private DualCrnProtocol crnProtocol;
|
private int deviceLogCollectTime = 200;
|
|
public ZySiemensDualCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
|
this.deviceConfig = deviceConfig;
|
this.redisUtil = redisUtil;
|
}
|
|
@Override
|
@SuppressWarnings("InfiniteLoopStatement")
|
public void run() {
|
this.connect();
|
this.initCrn();
|
|
Thread readThread = new Thread(() -> {
|
while (true) {
|
try {
|
deviceLogCollectTime = Utils.getDeviceLogCollectTime();
|
readStatus();
|
Thread.sleep(50);
|
} catch (Exception e) {
|
log.error("DualCrnThread Fail", e);
|
}
|
}
|
});
|
readThread.start();
|
|
Thread processThread = new Thread(() -> {
|
while (true) {
|
try {
|
int step = 1;
|
Task task = MessageQueue.poll(SlaveType.DualCrn, deviceConfig.getDeviceNo());
|
if (task != null) {
|
step = task.getStep();
|
}
|
|
if (step == 2) {
|
List<SendDualCrnCommandParam> commandList = (List<SendDualCrnCommandParam>) task.getData();
|
for (SendDualCrnCommandParam sendDualCrnCommandParam : commandList) {
|
DualCrnCommand dualCrnCommand = sendDualCrnCommandParam.getCommands().get(0);
|
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + dualCrnCommand.getTaskNo(), sendDualCrnCommandParam.getCommandIdx(), 60 * 60 * 24);
|
}
|
|
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getCrnNo(), JSON.toJSONString(commandList, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24);
|
} else if (step == 3) {
|
sendCommand((DualCrnCommand) task.getData());
|
}
|
|
Thread.sleep(100);
|
} catch (Exception e) {
|
log.error("DualCrnProcess Fail", e);
|
}
|
}
|
});
|
processThread.start();
|
|
Thread commandThread = new Thread(() -> {
|
while (true) {
|
try {
|
if(crnProtocol.getMode() != DualCrnModeType.AUTO.id) {
|
continue;
|
}
|
|
if(crnProtocol.getAlarm() != 0) {
|
continue;
|
}
|
|
if (!((crnProtocol.getStatusType().equals(DualCrnStatusType.IDLE) || crnProtocol.getStatusType().equals(DualCrnStatusType.FETCH_COMPLETE))
|
&& (crnProtocol.getStatusTypeTwo().equals(DualCrnStatusType.IDLE) || crnProtocol.getStatusTypeTwo().equals(DualCrnStatusType.FETCH_COMPLETE)))
|
) {
|
continue;
|
}
|
|
Object commandListObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getCrnNo());
|
if (commandListObj == null) {
|
continue;
|
}
|
List<SendDualCrnCommandParam> commandList = JSON.parseArray(commandListObj.toString(), SendDualCrnCommandParam.class);
|
for (SendDualCrnCommandParam commandParam : commandList) {
|
processStation(commandParam);
|
}
|
|
Thread.sleep(100);
|
} catch (Exception e) {
|
log.error("DualCrnCommand Fail", e);
|
}
|
}
|
});
|
commandThread.start();
|
}
|
|
private void processStation(SendDualCrnCommandParam commandParam) {
|
Integer station = commandParam.getStation();
|
List<DualCrnCommand> commandList = commandParam.getCommands();
|
DualCrnCommand firstCommand = commandList.get(0);
|
Object idxObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo());
|
if(idxObj == null) {
|
return;
|
}
|
Integer idx = (Integer) idxObj;
|
if (idx >= commandList.size()) {
|
return;
|
}
|
DualCrnCommand dualCommand = commandList.get(idx);
|
|
boolean send = false;
|
if (station == 1) {
|
if (crnProtocol.getStatus().equals(DualCrnStatusType.FETCH_COMPLETE.id)
|
|| crnProtocol.getStatus().equals(DualCrnStatusType.IDLE.id)
|
) {
|
send = true;
|
}
|
}else {
|
if (crnProtocol.getStatusTwo().equals(DualCrnStatusType.FETCH_COMPLETE.id)
|
|| crnProtocol.getStatusTwo().equals(DualCrnStatusType.IDLE.id)
|
) {
|
send = true;
|
}
|
}
|
|
if (idx == 0) {
|
if(send) {
|
idx++;
|
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo(), idx, 60 * 60 * 24);
|
sendCommand(dualCommand);
|
redisUtil.set(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo(), "lock", 5);
|
}
|
return;
|
}else {
|
if (dualCommand.getTaskMode() == DualCrnTaskModeType.PUT.id.shortValue()) {
|
//等待下一个任务
|
Object wait = redisUtil.get(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo());
|
if (wait != null) {
|
return;
|
}
|
|
Integer taskNo = dualCommand.getTaskNo();
|
Object outTaskStationInfoObj = redisUtil.get(RedisKeyType.DUAL_CRN_OUT_TASK_STATION_INFO.key + taskNo);
|
if (outTaskStationInfoObj != null) {
|
//检测出口站是否可执行放货动作
|
StationObjModel stationObjModel = JSON.parseObject(outTaskStationInfoObj.toString(), StationObjModel.class);
|
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, stationObjModel.getDeviceNo());
|
if (stationThread == null) {
|
return;
|
}
|
|
Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
|
StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId());
|
if (stationProtocol == null) {
|
return;
|
}
|
|
if (!stationProtocol.isAutoing()) {
|
return;
|
}
|
|
if (stationProtocol.isLoading()) {
|
return;
|
}
|
|
if (stationProtocol.getTaskNo() > 0) {
|
return;
|
}
|
}
|
}
|
|
if(send) {
|
idx++;
|
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo(), idx, 60 * 60 * 24);
|
sendCommand(dualCommand);
|
}
|
return;
|
}
|
}
|
|
/**
|
* 初始化堆垛机状态
|
*/
|
private void initCrn() {
|
if (null == crnProtocol) {
|
crnProtocol = new DualCrnProtocol();
|
crnProtocol.setCrnNo(deviceConfig.getDeviceNo());
|
}
|
crnProtocol.setMode(-1);
|
|
//工位1
|
crnProtocol.setTaskNo(0);
|
crnProtocol.setStatus(-1);
|
crnProtocol.setBay(0);
|
crnProtocol.setLevel(0);
|
crnProtocol.setForkPos(-1);
|
crnProtocol.setLoaded(0);
|
crnProtocol.setWalkPos(0);
|
crnProtocol.setLiftPos(0);
|
|
//工位2
|
crnProtocol.setTaskNoTwo(0);
|
crnProtocol.setStatusTwo(-1);
|
crnProtocol.setBayTwo(0);
|
crnProtocol.setLevelTwo(0);
|
crnProtocol.setForkPosTwo(-1);
|
crnProtocol.setLoadedTwo(0);
|
crnProtocol.setWalkPosTwo(0);
|
crnProtocol.setLiftPosTwo(0);
|
|
crnProtocol.setAlarm(0);
|
crnProtocol.setXSpeed(0D);
|
crnProtocol.setYSpeed(0D);
|
crnProtocol.setZSpeed(0D);
|
crnProtocol.setXDistance(0D);
|
crnProtocol.setYDistance(0D);
|
crnProtocol.setXDuration(0D);
|
crnProtocol.setYDuration(0D);
|
|
BasDualCrnpService basDualCrnpService = null;
|
try {
|
basDualCrnpService = SpringUtils.getBean(BasDualCrnpService.class);
|
}catch (Exception e){
|
|
}
|
if (basDualCrnpService != null) {
|
BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", deviceConfig.getDeviceNo()));
|
if(basDualCrnp == null) {
|
basDualCrnp = new BasDualCrnp();
|
basDualCrnp.setCrnNo(deviceConfig.getDeviceNo());
|
basDualCrnp.setStatus(1);
|
basDualCrnp.setInEnable("N");
|
basDualCrnp.setOutEnable("N");
|
basDualCrnp.setMaxInTask(5);
|
basDualCrnp.setMaxOutTask(5);
|
basDualCrnp.setCreateTime(new Date());
|
basDualCrnpService.insert(basDualCrnp);
|
}
|
}
|
}
|
|
@Override
|
public boolean connect() {
|
zyDualCrnConnectDriver = new ZyDualCrnConnectDriver(deviceConfig);
|
zyDualCrnConnectDriver.start();
|
DeviceConnectPool.put(SlaveType.Crn, deviceConfig.getDeviceNo(), zyDualCrnConnectDriver);
|
return true;
|
}
|
|
/**
|
* 读取状态
|
*/
|
private void readStatus(){
|
ZyDualCrnStatusEntity crnStatus = zyDualCrnConnectDriver.getStatus();
|
if (crnStatus == null) {
|
OutputQueue.DUAL_CRN.offer(MessageFormat.format("【{0}】读取双工位堆垛机plc状态信息失败 ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
|
return;
|
}
|
crnProtocol.setMode(crnStatus.getMode());
|
|
//工位1
|
crnProtocol.setTaskNo(crnStatus.getTaskNo());
|
crnProtocol.setStatus(crnStatus.getStatus());
|
crnProtocol.setForkPos(crnStatus.getForkPos());
|
crnProtocol.setLoaded(crnStatus.getLoaded());
|
crnProtocol.setTaskReceive(crnStatus.getTaskReceive());
|
|
//工位2
|
crnProtocol.setTaskNoTwo(crnStatus.getTaskNoTwo());
|
crnProtocol.setStatusTwo(crnStatus.getStatusTwo());
|
crnProtocol.setForkPosTwo(crnStatus.getForkPosTwo());
|
crnProtocol.setLoadedTwo(crnStatus.getLoadedTwo());
|
crnProtocol.setTaskReceiveTwo(crnStatus.getTaskReceiveTwo());
|
|
crnProtocol.setBay(crnStatus.getBay());
|
crnProtocol.setLevel(crnStatus.getLevel());
|
crnProtocol.setWalkPos(crnStatus.getWalkPos());
|
crnProtocol.setLiftPos(crnStatus.getLiftPos());
|
crnProtocol.setAlarm(crnStatus.getAlarm());
|
crnProtocol.setTemp1(crnStatus.getTemp1());
|
crnProtocol.setTemp2(crnStatus.getTemp2());
|
crnProtocol.setTemp3(crnStatus.getTemp3());
|
crnProtocol.setTemp4(crnStatus.getTemp4());
|
crnProtocol.setXSpeed(crnStatus.getXSpeed());
|
crnProtocol.setYSpeed(crnStatus.getYSpeed());
|
crnProtocol.setZSpeed(crnStatus.getZSpeed());
|
crnProtocol.setXDistance(crnStatus.getXDistance());
|
crnProtocol.setYDistance(crnStatus.getYDistance());
|
crnProtocol.setXDuration(crnStatus.getXDuration());
|
crnProtocol.setYDuration(crnStatus.getYDuration());
|
crnProtocol.setGoodsType(crnStatus.getGoodsType());
|
crnProtocol.setBarcode(crnStatus.getBarcode());
|
|
OutputQueue.DUAL_CRN.offer(MessageFormat.format("【{0}】[id:{1}] <<<<< 实时数据更新成功",DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
|
|
if (crnProtocol.getAlarm() > 0) {
|
crnProtocol.setLastCommandTime(-1L);
|
}
|
|
if (crnProtocol.getAlarm() == 0 && crnProtocol.getLastCommandTime() == -1) {
|
crnProtocol.setLastCommandTime(System.currentTimeMillis());
|
}
|
|
if (System.currentTimeMillis() - crnProtocol.getDeviceDataLog() > deviceLogCollectTime) {
|
//保存数据记录
|
DeviceDataLog deviceDataLog = new DeviceDataLog();
|
deviceDataLog.setOriginData(JSON.toJSONString(crnStatus));
|
deviceDataLog.setWcsData(JSON.toJSONString(crnProtocol));
|
deviceDataLog.setType(String.valueOf(SlaveType.DualCrn));
|
deviceDataLog.setDeviceNo(crnProtocol.getCrnNo());
|
deviceDataLog.setCreateTime(new Date());
|
|
redisUtil.set(RedisKeyType.DEVICE_LOG_KEY.key + System.currentTimeMillis(), deviceDataLog, 60 * 60 * 24);
|
//更新采集时间
|
crnProtocol.setDeviceDataLog(System.currentTimeMillis());
|
}
|
|
try {
|
BasDualCrnpErrLogService errLogService = SpringUtils.getBean(BasDualCrnpErrLogService.class);
|
if (errLogService != null) {
|
String errFlagKey = RedisKeyType.DEVICE_ERR_ACTIVE_DUAL_CRN.key + crnProtocol.getCrnNo();
|
Object active = redisUtil.get(errFlagKey);
|
if (crnProtocol.getAlarm() != null && crnProtocol.getAlarm() > 0) {
|
if (active == null) {
|
BasDualCrnpErrLog log = new BasDualCrnpErrLog();
|
Integer wrkNo = (crnProtocol.getTaskNo() != null && crnProtocol.getTaskNo() > 0) ? crnProtocol.getTaskNo() : crnProtocol.getTaskNoTwo();
|
log.setWrkNo(wrkNo);
|
log.setStartTime(new Date());
|
log.setCrnNo(crnProtocol.getCrnNo());
|
log.setBarcode(crnProtocol.getBarcode());
|
log.setErrCode(crnProtocol.getAlarm());
|
log.setStatus(1);
|
log.setCreateTime(new Date());
|
log.setSystemStatus(JSON.toJSONString(crnProtocol));
|
errLogService.insert(log);
|
if (log.getId() != null) {
|
redisUtil.set(errFlagKey, log.getId(), 60 * 60 * 24);
|
}
|
}
|
} else {
|
if (active != null) {
|
Long id = Long.valueOf(String.valueOf(active));
|
BasDualCrnpErrLog update = new BasDualCrnpErrLog();
|
update.setId(id);
|
update.setEndTime(new Date());
|
update.setStatus(2);
|
update.setUpdateTime(new Date());
|
errLogService.updateById(update);
|
redisUtil.del(errFlagKey);
|
}
|
}
|
}
|
} catch (Exception ignore) {}
|
}
|
|
@Override
|
public void close() {
|
if (zyDualCrnConnectDriver != null) {
|
zyDualCrnConnectDriver.close();
|
}
|
}
|
|
@Override
|
public DualCrnProtocol getStatus() {
|
return this.crnProtocol;
|
}
|
|
@Override
|
public DualCrnCommand getPickAndPutCommand(String sourceLocNo, String targetLocNo, Integer taskNo, Integer crnNo, Integer station) {
|
DualCrnCommand crnCommand = new DualCrnCommand();
|
crnCommand.setCrnNo(crnNo); // 堆垛机编号
|
crnCommand.setTaskNo(taskNo); // 工作号
|
crnCommand.setTaskMode(DualCrnTaskModeType.TRANSFER.id); // 任务模式: 取放货
|
crnCommand.setSourcePosX(Utils.getRow(sourceLocNo)); // 源库位排
|
crnCommand.setSourcePosY(Utils.getBay(sourceLocNo)); // 源库位列
|
crnCommand.setSourcePosZ(Utils.getLev(sourceLocNo)); // 源库位层
|
crnCommand.setDestinationPosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setDestinationPosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setDestinationPosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setStation(station);//工位
|
crnCommand.setCommand(1); // 任务确认
|
return crnCommand;
|
}
|
|
@Override
|
public DualCrnCommand getPickCommand(String targetLocNo, Integer taskNo, Integer crnNo, Integer station) {
|
DualCrnCommand crnCommand = new DualCrnCommand();
|
crnCommand.setCrnNo(crnNo); // 堆垛机编号
|
crnCommand.setTaskNo(taskNo); // 工作号
|
crnCommand.setTaskMode(DualCrnTaskModeType.PICK.id); // 任务模式: 取货
|
crnCommand.setSourcePosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setSourcePosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setSourcePosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setDestinationPosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setDestinationPosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setDestinationPosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setStation(station);//工位
|
crnCommand.setCommand(1); // 任务确认
|
return crnCommand;
|
}
|
|
@Override
|
public DualCrnCommand getPutCommand(String targetLocNo, Integer taskNo, Integer crnNo, Integer station) {
|
DualCrnCommand crnCommand = new DualCrnCommand();
|
crnCommand.setCrnNo(crnNo); // 堆垛机编号
|
crnCommand.setTaskNo(taskNo); // 工作号
|
crnCommand.setTaskMode(DualCrnTaskModeType.PUT.id); // 任务模式: 放货
|
crnCommand.setSourcePosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setSourcePosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setSourcePosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setDestinationPosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setDestinationPosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setDestinationPosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setStation(station);//工位
|
crnCommand.setCommand(1); // 任务确认
|
return crnCommand;
|
}
|
|
@Override
|
public DualCrnCommand getMoveCommand(String targetLocNo, Integer taskNo, Integer crnNo) {
|
DualCrnCommand crnCommand = new DualCrnCommand();
|
crnCommand.setCrnNo(crnNo); // 堆垛机编号
|
crnCommand.setTaskNo(taskNo); // 工作号
|
crnCommand.setTaskMode(DualCrnTaskModeType.MOVE.id); // 任务模式: 堆垛机移动
|
crnCommand.setSourcePosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setSourcePosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setSourcePosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setDestinationPosX(Utils.getRow(targetLocNo)); // 目标库位排
|
crnCommand.setDestinationPosY(Utils.getBay(targetLocNo)); // 目标库位列
|
crnCommand.setDestinationPosZ(Utils.getLev(targetLocNo)); // 目标库位层
|
crnCommand.setCommand(1); // 任务确认
|
return crnCommand;
|
}
|
|
@Override
|
public DualCrnCommand getResetCommand(Integer crnNo, Integer station) {
|
DualCrnCommand crnCommand = new DualCrnCommand();
|
crnCommand.setCrnNo(crnNo); // 堆垛机编号
|
crnCommand.setTaskNo(0); // 工作号
|
crnCommand.setTaskMode(DualCrnTaskModeType.CONFIRM.id); // 任务模式: 确认
|
crnCommand.setSourcePosX(0); // 源库位排
|
crnCommand.setSourcePosY(0); // 源库位列
|
crnCommand.setSourcePosZ(0); // 源库位层
|
crnCommand.setDestinationPosX(0); // 目标库位排
|
crnCommand.setDestinationPosY(0); // 目标库位列
|
crnCommand.setDestinationPosZ(0); // 目标库位层
|
crnCommand.setStation(station);//工位
|
crnCommand.setCommand(1); // 任务确认
|
return crnCommand;
|
}
|
|
@Override
|
public CommandResponse sendCommand(DualCrnCommand command) {
|
this.crnProtocol.setLastCommandTime(System.currentTimeMillis());
|
CommandResponse response = null;
|
try {
|
response = zyDualCrnConnectDriver.sendCommand(command);
|
return response;
|
} finally {
|
String sourceLocNo = Utils.getLocNo(command.getSourcePosX(), command.getSourcePosY(), command.getSourcePosZ());
|
String targetLocNo = Utils.getLocNo(command.getDestinationPosX(), command.getDestinationPosY(), command.getDestinationPosZ());
|
BasDualCrnpOptService bean = SpringUtils.getBean(BasDualCrnpOptService.class);
|
ZyDualCrnStatusEntity statusEntity = zyDualCrnConnectDriver.getStatus();
|
BasDualCrnpOpt basDualCrnpOpt = new BasDualCrnpOpt(
|
command.getTaskNo().intValue(),
|
command.getCrnNo(),
|
new Date(),
|
String.valueOf(command.getTaskMode()),
|
sourceLocNo,
|
targetLocNo,
|
null,
|
null,
|
null,
|
JSON.toJSONString(command),
|
JSON.toJSONString(statusEntity),
|
1,
|
JSON.toJSONString(response)
|
);
|
if (bean != null) {
|
bean.insert(basDualCrnpOpt);
|
}
|
}
|
}
|
}
|