add:新增rfid读写器查询接口以及输送线驱动

This commit is contained in:
2025-08-29 17:41:54 +08:00
parent 9c8077751a
commit 8e3176795d
32 changed files with 2263 additions and 277 deletions

View File

@@ -16,6 +16,7 @@ import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.FeedLmsRealFailed;
import org.nl.acs.device_driver.agv.utils.TwoAgvPhase;
import org.nl.acs.device_driver.conveyor.belt_conveyor.BeltConveyorDeviceDriver;
import org.nl.acs.device_driver.conveyor.standard_inspect_site.StandardInspectSiteDeviceDriver;
import org.nl.acs.device_driver.conveyor.standard_ordinary_site.StandardOrdinarySiteDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractDeviceDriver;
@@ -43,9 +44,7 @@ import org.nl.system.service.param.ISysParamService;
import org.nl.config.SpringContextHolder;
import java.time.LocalTime;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.*;
import java.util.concurrent.ThreadPoolExecutor;
@@ -165,8 +164,8 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic
//普通站点
StandardOrdinarySiteDeviceDriver standardOrdinarySiteDeviceDriver;
//标准-光电检测
StandardInspectSiteDeviceDriver standardInspectSiteDeviceDriver;
//标准-输送线
BeltConveyorDeviceDriver beltConveyorDeviceDriver;
if (phase == 0x02) {
@@ -233,6 +232,18 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
standardOrdinarySiteDeviceDriver.setOption(0);
} else if (device.getDeviceDriver() instanceof BeltConveyorDeviceDriver) {
beltConveyorDeviceDriver = (BeltConveyorDeviceDriver) device.getDeviceDriver();
if (beltConveyorDeviceDriver.getAction() == 1 && beltConveyorDeviceDriver.getMode() == 2 && beltConveyorDeviceDriver.getError() == 0&& beltConveyorDeviceDriver.getMove() == 1) {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
} else {
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(beltConveyorDeviceDriver.getDevice_code())
.content("未给agv进入信号原因是" + beltConveyorDeviceDriver.getDevice_code() + "动作信号不为1或者工作模式不为2或者有报警,当前的指令号为:" + inst.getInstruction_code())
.build();
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
}
} else {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
LuceneLogDto logDto = LuceneLogDto.builder()
@@ -306,6 +317,24 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic
standardOrdinarySiteDeviceDriver.setAgvphase(phase);
standardOrdinarySiteDeviceDriver.setIndex(index);
standardOrdinarySiteDeviceDriver.setInst(inst);
} else if (device.getDeviceDriver() instanceof BeltConveyorDeviceDriver) {
beltConveyorDeviceDriver = (BeltConveyorDeviceDriver) device.getDeviceDriver();
if (beltConveyorDeviceDriver.getAction() == 2 && beltConveyorDeviceDriver.getMode() == 2 && beltConveyorDeviceDriver.getError() == 0) {
List list1 = new ArrayList();
Map map = new HashMap();
map.put("code", "to_command");
map.put("value", "1");
list1.add(map);
beltConveyorDeviceDriver.writing(list1);
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
} else {
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(beltConveyorDeviceDriver.getDevice_code())
.content("未给agv离开信号原因是" + beltConveyorDeviceDriver.getDevice_code() + "动作信号不为2或者工作模式不为2或者有报警,当前的指令号为:" + inst.getInstruction_code())
.build();
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
}
} else {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
LuceneLogDto logDto = LuceneLogDto.builder()
@@ -367,6 +396,19 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic
luceneExecuteLogService.deviceExecuteLog(logDto);
standardOrdinarySiteDeviceDriver.setOption(0);
} else if (device.getDeviceDriver() instanceof BeltConveyorDeviceDriver) {
beltConveyorDeviceDriver = (BeltConveyorDeviceDriver) device.getDeviceDriver();
if (beltConveyorDeviceDriver.getAction() == 1 && beltConveyorDeviceDriver.getMode() == 2 && beltConveyorDeviceDriver.getError() == 0&&beltConveyorDeviceDriver.getMove()==0) {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
} else {
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(beltConveyorDeviceDriver.getDevice_code())
.content("未给agv进入信号原因是" + beltConveyorDeviceDriver.getDevice_code() + "动作信号不为1或者工作模式不为2或者有报警,当前的指令号为:" + inst.getInstruction_code())
.build();
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
}
} else {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
LuceneLogDto logDto = LuceneLogDto.builder()
@@ -430,6 +472,35 @@ public class AgvNdcTwoDeviceDriver extends AbstractDeviceDriver implements Devic
standardOrdinarySiteDeviceDriver.setAgvphase(phase);
standardOrdinarySiteDeviceDriver.setIndex(index);
standardOrdinarySiteDeviceDriver.setInst(inst);
} else if (device.getDeviceDriver() instanceof BeltConveyorDeviceDriver) {
beltConveyorDeviceDriver = (BeltConveyorDeviceDriver) device.getDeviceDriver();
if (beltConveyorDeviceDriver.getMode() == 2 && beltConveyorDeviceDriver.getError() == 0) {
List list = new ArrayList();
Map map1 = new HashMap();
map1.put("code", "to_command");
map1.put("value", "2");
Map map2 = new HashMap();
map2.put("code", "to_target");//目标楼层从wms下发的参数字段取
map2.put("value", "3");
list.add(map2);
Map map3 = new HashMap();
map3.put("code", "to_task");
map3.put("value", inst.getInstruction_code());
list.add(map3);
Map map4 = new HashMap();
map4.put("code", "to_barcode");
map4.put("value", inst.getVehicle_code());
list.add(map4);
beltConveyorDeviceDriver.writing(list);
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
} else {
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(beltConveyorDeviceDriver.getDevice_code())
.content("未给agv离开信号原因是" + beltConveyorDeviceDriver.getDevice_code() + "动作信号不为2或者工作模式不为2或者有报警,当前的指令号为:" + inst.getInstruction_code())
.build();
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
}
} else {
data = ndcAgvService.sendAgvOneModeInst(phase, index, 0);
LuceneLogDto logDto = LuceneLogDto.builder()

View File

@@ -1,5 +1,6 @@
package org.nl.acs.device_driver.conveyor.belt_conveyor;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpResponse;
@@ -28,6 +29,8 @@ import org.nl.acs.log.service.DeviceExecuteLogService;
import org.nl.acs.monitor.DeviceStageMonitor;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.opc.DeviceAppServiceImpl;
import org.nl.acs.rfid_manage.service.IbmVehicleRfidService;
import org.nl.acs.rfid_manage.service.dao.BmVehicleRfid;
import org.nl.acs.route.service.RouteLineService;
import org.nl.acs.task.service.TaskService;
import org.nl.acs.utils.DeviceErrorUtil;
@@ -69,6 +72,8 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
AgvService agvService = SpringContextHolder.getBean(AgvService.class);
@Autowired
DeviceErrorLogService errorLogServer = SpringContextHolder.getBean(DeviceErrorLogServiceImpl.class);
@Autowired
IbmVehicleRfidService ibmVehicleRfidService = SpringContextHolder.getBean(IbmVehicleRfidService.class);
LuceneExecuteLogService luceneExecuteLogService = SpringContextHolder.getBean("luceneExecuteLogServiceImpl");
@@ -105,8 +110,8 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
/**
* 托盘方向
*/
int container_direction = 0;
int last_container_direction = 0;
int actionRequest = 0;
int last_actionRequest = 0;
/**
* 报警
*/
@@ -123,15 +128,15 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
int task = 0;
int last_task = 0;
/**
* 托盘类型
* 出入库信号
*/
int container_type = 0;
int last_container_type = 0;
int type = 0;
int last_type = 0;
/**
* 纯数字托盘号
*/
int container_no = 0;
int last_container_no = 0;
String barcode = null;
String last_barcode = null;
int inventory_qty = 0;
int out_finish = 0;
@@ -153,16 +158,14 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
/**
* 下发接纯数字托盘号
*/
int to_container_no = 0;
int last_to_container_no = 0;
String to_barcode = null;
String last_to_barcode = null;
/**
* 下发托盘类型
*/
int to_container_type = 0;
int last_to_container_type = 0;
String to_taskNum = null;
String last_to_taskNum = null;
int to_height_level = 0;
int last_to_height_level = 0;
//子卷条码
@@ -228,21 +231,20 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
mode = this.itemProtocol.getMode();
move = this.itemProtocol.getMove();
action = this.itemProtocol.getAction();
container_direction = this.itemProtocol.getContainer_direction();
container_type = this.itemProtocol.getContainer_type();
type = this.itemProtocol.getType();
actionRequest = this.itemProtocol.getActionRequest();
barcode = this.itemProtocol.getBarcode();
error = this.itemProtocol.getError();
task = this.itemProtocol.getTask();
to_command = this.itemProtocol.getTo_command();
to_target = this.itemProtocol.getTotarget();
to_task = this.itemProtocol.getTo_task();
to_container_no = this.itemProtocol.getContainer_direction();
to_barcode = this.itemProtocol.getTo_barcode();
to_taskNum = this.itemProtocol.getTo_taskNum();
if (move != last_move && last_move == 1 && mode > 0) {
requireSucess = false;
}
if (mode != last_mode) {
if (actionRequest != last_actionRequest) {
requireSucess = false;
}
@@ -269,7 +271,7 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
}
if (mode == 0) {
if (mode == 1) {
this.setIsonline(false);
message = "脱机";
} else if (error != 0) {
@@ -283,17 +285,19 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
Instruction instruction = null;
List toInstructions;
switch (mode) {
case 1:
switch (actionRequest) {
case 0:
log.debug("弃用(留作兼容)");
break;
case 2:
case 5:
//申请任务
if (move == 1 && !requireSucess) {
instruction_require();
boolean b = instruction_require();
if (b) {
requireSucess = false;
}
} else {
String remark = "";
;
if (mode != 2) {
remark = "universal_remark2";
}
@@ -313,7 +317,8 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
//}
}
break;
case 3:
case 6:
//更新出库任务数
log.info(this.device_code + ",运行中");
break;
default:
@@ -353,95 +358,96 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
last_mode = mode;
last_move = move;
last_error = error;
last_container_direction = container_direction;
last_container_no = container_no;
last_container_type = container_type;
last_type = type;
last_barcode = barcode;
last_actionRequest = actionRequest;
last_action = action;
last_task = task;
last_to_command = to_command;
last_to_target = to_target;
last_to_task = to_task;
last_to_container_no = to_container_no;
last_to_container_type = to_container_type;
last_to_barcode = to_barcode;
last_to_taskNum = to_taskNum;
}
public void writing(int command) {
String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
+ "." + org.nl.acs.device_driver.conveyor.belt_conveyor.ItemProtocol.item_to_command;
Map<String, Object> itemMap = new HashMap<String, Object>();
itemMap.put(to_command, command);
this.control(itemMap);
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(device_code)
.content("下发多个电气信号" + itemMap)
.build();
logDto.setLog_level(3);
luceneExecuteLogService.deviceExecuteLog(logDto);
}
// public void writing(int command) {
// String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
// + "." + org.nl.acs.device_driver.conveyor.belt_conveyor.ItemProtocol.item_to_command;
// Map<String, Object> itemMap = new HashMap<String, Object>();
// itemMap.put(to_command, command);
// this.control(itemMap);
// LuceneLogDto logDto = LuceneLogDto.builder()
// .device_code(device_code)
// .content("下发多个电气信号" + itemMap)
// .build();
// logDto.setLog_level(3);
// luceneExecuteLogService.deviceExecuteLog(logDto);
// }
private void applyEmptyTask(String type, int mode) {
/**
* 申请任务
*/
public synchronized boolean
instruction_require() {
Date date = new Date();
if (date.getTime() - this.require_apply_strangulation_time.getTime()
< (long) this.require_apply_strangulation_time_out) {
if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) {
log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out);
return;
return false;
} else {
this.require_apply_strangulation_time = date;
try {
this.instruction_require_time = date;
Device device = deviceAppService.findDeviceByCode(device_code);
List<String> list = device.getDeviceDriver().getExtraDeviceCodes("link_device_code");
if (CollUtil.isNotEmpty(getDeviceCodeList)) {
//关联的RFID设备
String linkDeviceCode = list.get(0);
BmVehicleRfid bmVehicleRfid = ibmVehicleRfidService.findByDeviceCode(linkDeviceCode);
String rfid = bmVehicleRfid.getRfid();
if (!StrUtil.isEmpty(rfid)) {
JSONObject param = new JSONObject();
param.put("device_code", device_code);
param.put("container_type", container_type);
param.put("type", type);
param.put("vehicle_code", rfid);
LuceneLogDto logDto = LuceneLogDto.builder()
.device_code(device_code)
.content("申请空托盘出入库,参数:" + param)
.content("申请入库任务,接口请求参数:" + param)
.build();
logDto.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto);
HttpResponse httpResponse = acsToWmsService.applyTwo(param);
HttpResponse httpResponse = acsToWmsService.applyIn(param);
JSONObject jsonObject = null;
if(ObjectUtil.isNotEmpty(httpResponse)){
String body = httpResponse.body();
jsonObject = JSONObject.parseObject(body);
}
message = "申请空托盘出入库,返回参数:" + jsonObject;
message = "申请入库任务,接口返回参数:" + jsonObject;
if (ObjectUtil.isNotNull(jsonObject) && jsonObject.getInteger("status") == 200) {
LuceneLogDto logDto2 = LuceneLogDto.builder()
.device_code(device_code)
.content("申请空托盘出入库,参数,接口返回:" + jsonObject)
.content("申请入库任务成功,接口返回参数:" + jsonObject)
.build();
logDto2.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto2);
List list1 = new ArrayList();
Map map = new HashMap();
map.put("code", "to_command");
map.put("value", mode);
map.put("value", 5);
list1.add(map);
this.writing(list1);
this.requireSucess = true;
} else {
this.iserror = true;
message = "申请空托盘出入库出错,返回参数:" + jsonObject;
message = "申请入库任务出错,接口返回参数:" + jsonObject;
LuceneLogDto logDto2 = LuceneLogDto.builder()
.device_code(device_code)
.content("申请空托盘出入库,返回参数:" + jsonObject)
.content("申请入库任务出错,接口返回参数:" + jsonObject)
.build();
logDto2.setLog_level(4);
luceneExecuteLogService.deviceExecuteLog(logDto2);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 申请任务
*/
public synchronized Boolean
instruction_require() {
return true;
}
@@ -533,11 +539,11 @@ public class BeltConveyorDeviceDriver extends AbstractOpcDeviceDriver implements
jo.put("hasGoods", true);
}
String container_type = "";
if (this.container_type == 1) {
container_type = LangProcess.msg("universal_small_pallets");
} else if (this.container_type == 2) {
container_type = LangProcess.msg("universal_large_pallets");
}
// if (this.container_type == 1) {
// container_type = LangProcess.msg("universal_small_pallets");
// } else if (this.container_type == 2) {
// container_type = LangProcess.msg("universal_large_pallets");
// }
jo.put("move", move);
jo.put("task", task);
jo.put("type", container_type);

View File

@@ -34,13 +34,17 @@ public class ItemProtocol {
*/
public static String item_error = "error";
/**
* 托盘方向
* 出入库信号
*/
public static String item_container_direction = "container_direction";
public static String item_type = "type";
/**
* 动作请求
*/
public static String item_actionRequest = "actionRequest";
/**
* 托盘类型
*/
public static String item_container_type = "container_type";
public static String item_barcode = "barcode";
/**
* 任务号
*/
@@ -51,9 +55,9 @@ public class ItemProtocol {
*/
public static String item_to_command = "to_command";
/**
* 下发托盘类型
* 下发托盘
*/
public static String item_to_container_type = "to_container_type";
public static String item_to_barcode = "to_barcode";
/**
* 下发任务号
*/
@@ -62,6 +66,10 @@ public class ItemProtocol {
* 下发目标站
*/
public static String item_to_target = "to_target";
/**
* 下发出库任务数
*/
public static String item_to_taskNum = "to_taskNum";
@@ -89,18 +97,22 @@ public class ItemProtocol {
return this.getOpcIntegerValue(item_move);
}
public int getContainer_direction() {
return this.getOpcIntegerValue(item_container_direction);
public int getActionRequest() {
return this.getOpcIntegerValue(item_actionRequest);
}
public int getContainer_type() {
return this.getOpcIntegerValue(item_container_type);
public String getBarcode() {
return this.getOpcStringValue(item_barcode);
}
public int getAction() {
return this.getOpcIntegerValue(item_action);
}
public int getType() {
return this.getOpcIntegerValue(item_type);
}
public int getError() {
return this.getOpcIntegerValue(item_error);
@@ -125,8 +137,12 @@ public class ItemProtocol {
return this.getOpcStringValue(item_to_command);
}
public int getTo_container_type() {
return this.getOpcIntegerValue(item_to_container_type);
public String getTo_barcode() {
return this.getOpcStringValue(item_to_barcode);
}
public String getTo_taskNum() {
return this.getOpcStringValue(item_to_taskNum);
}
Boolean isonline;
@@ -170,10 +186,11 @@ public class ItemProtocol {
list.add(new ItemDto(item_heartbeat, "心跳", "DB101.B0"));
list.add(new ItemDto(item_mode, "工作模式", "DB101.B2"));
list.add(new ItemDto(item_move, "光电信号", "DB101.B3"));
list.add(new ItemDto(item_container_direction, "托盘方向", "DB101.B4"));
list.add(new ItemDto(item_container_type, "托盘类型", "DB101.B5"));
list.add(new ItemDto(item_type, "出入库信号", "DB101.B4"));
list.add(new ItemDto(item_actionRequest, "动作请求", "DB101.B5"));
list.add(new ItemDto(item_action, "动作类型", "DB101.B6"));
list.add(new ItemDto(item_error, "报警", "DB101.B58"));
list.add(new ItemDto(item_barcode, "载具号", "DB101.B60"));
list.add(new ItemDto(item_task, "任务号", "DB101.D68"));
return list;
}
@@ -183,8 +200,8 @@ public class ItemProtocol {
list.add(new ItemDto(item_to_target, "下发仓位号", "DB102.W2"));
list.add(new ItemDto(item_to_command, "下发命令", "DB102.W4"));
list.add(new ItemDto(item_to_task, "下发任务号", "DB102.D1"));
list.add(new ItemDto(item_to_container_type, "下发托盘类型", "DB102.B5"));
list.add(new ItemDto(item_to_barcode, "下发托盘", "DB102.B5"));
list.add(new ItemDto(item_to_taskNum, "下发出库任务数", "DB102.B6"));
return list;
}

View File

@@ -0,0 +1,46 @@
package org.nl.acs.device_driver.standard_storage;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.enums.DeviceType;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.DeviceDriverDefination;
import org.springframework.stereotype.Service;
import java.util.LinkedList;
import java.util.List;
@Service
public class StandardStorageDefination implements DeviceDriverDefination {
@Override
public String getDriverCode() {
return "standard_storage";
}
@Override
public String getDriverName() {
return "标准版-货架";
}
@Override
public String getDriverDescription() {
return "标准版-货架";
}
@Override
public DeviceDriver getDriverInstance(Device device) {
return (new StandardStorageDeviceDriver()).setDevice(device).setDriverDefination(this);
}
@Override
public Class<? extends DeviceDriver> getDeviceDriverType() {
return StandardStorageDeviceDriver.class;
}
@Override
public List<DeviceType> getFitDeviceTypes() {
List<DeviceType> types = new LinkedList();
types.add(DeviceType.storage);
return types;
}
}

View File

@@ -0,0 +1,29 @@
package org.nl.acs.device_driver.standard_storage;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.RouteableDeviceDriver;
import org.nl.acs.device_driver.StorageDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractDeviceDriver;
import org.nl.acs.monitor.DeviceStageMonitor;
/**
* 标准版货架
*/
@Slf4j
@Data
public class StandardStorageDeviceDriver extends AbstractDeviceDriver implements RouteableDeviceDriver, StorageDeviceDriver, DeviceDriver, DeviceStageMonitor {
@Override
public JSONObject getDeviceStatusName() throws Exception {
JSONObject jo = new JSONObject();
jo.put("mode", 2);
jo.put("isOnline", true);
return jo;
}
@Override
public void setDeviceStatus(JSONObject data) {
}
}

View File

@@ -89,7 +89,7 @@ public interface AcsToWmsService {
* @param param
* @return
*/
HttpResponse applyTwo(JSONObject param);
HttpResponse applyIn(JSONObject param);
/**
* 二期发货申请任务

View File

@@ -163,13 +163,13 @@ public class AcsToWmsServiceImpl implements AcsToWmsService {
}
@Override
public HttpResponse applyTwo(JSONObject param) {
public HttpResponse applyIn(JSONObject param) {
HttpResponse result2 = null;
try {
MDC.put(log_file_type, log_type);
log.info("applyTwo-----输入参数{}", param);
log.info("申请入库-----请求参数{}", param);
String wmsurl = paramService.findByCode(AcsConfig.WMSURL).getValue();
AddressDto addressDto = addressService.findByCode("applyTwo");
AddressDto addressDto = addressService.findByCode("applyIn");
String url = wmsurl + addressDto.getMethods_url();
try {
result2 = HttpRequest.post(url)
@@ -180,14 +180,12 @@ public class AcsToWmsServiceImpl implements AcsToWmsService {
.execute();
} catch (Exception e) {
String msg = e.getMessage();
log.info("applyTaskToWmsError-----请求异常输出参数{}", msg);
log.info("申请入库-----请求异常输出参数{}", msg);
//网络不通
}
log.info("applyTwo-----输出参数{}", result2.body());
LuceneLogDto luceneLogDto = new LuceneLogDto(4, "applyTwo", String.valueOf(result2.getStatus()),
JSON.toJSONString(param), String.valueOf(result2.body()), "ACS向LMS申请"
+ ("1".equals(param.getString("type")) ? "子卷装箱入库任务" : "2".equals(param.getString("type")) ? "空盘入库" : "3".equals(param.getString("type")) ? "空盘出库" : "5".equals(param.getString("type")) ? "木箱入库" :
"6".equals(param.getString("type")) ? "退货入库" : "异常处理位"));
log.info("申请入库-----输出参数{}", result2.body());
LuceneLogDto luceneLogDto = new LuceneLogDto(4, "applyIn", String.valueOf(result2.getStatus()),
JSON.toJSONString(param), String.valueOf(result2.body()), "ACS向WMS申请入库任务");
luceneLogService.interfaceExecuteLog(luceneLogDto);
return result2;

View File

@@ -504,4 +504,6 @@ public interface InstructionService extends CommonService<InstructionMybatis> {
List<Instruction> findReadyIns2();
Instruction findByStarCodeAndExcute(String deviceCode);
int queryInstructionCount(String deviceCode);
}

View File

@@ -463,32 +463,6 @@ public class InstructionServiceImpl extends CommonServiceImpl<InstructionMapper,
NDCAgvService ndcAgvService = SpringContextHolder.getBean(NDCAgvService.class);
ndcAgvService.sendAgvInstToNDC(task.getAgv_system_type(), dto);
}
//判断是否是仙工AGV
if (StrUtil.equals(paramService.findByCode(AcsConfig.AGVTYPE).getValue(), "3")) {
if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.XG_System_Type.getIndex())) {
String interactionJson = task.getInteraction_json();
if (StrUtil.isEmpty(interactionJson)) {
throw new BadRequestException("agv叉车调整长宽参数为空");
}
InteractionJsonDTO interactionJsonDTO = JSON.parseObject(interactionJson, InteractionJsonDTO.class);
//仙工叉车
HttpResponse response = xiangGongAgvService.sendOrderSequencesToForklift(dto, interactionJsonDTO);
if (ObjectUtils.isEmpty(response) || response.getStatus() != 200) {
dto.setSend_status("2");
} else {
dto.setSend_status("1");
}
} else if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.One_NDC_System_Type.getIndex())) {
//一楼agv任务创建运单序列
HttpResponse response = xiangGongAgvService.sendOrderSequencesToXZ(dto);
if (ObjectUtils.isEmpty(response) || response.getStatus() != 200) {
dto.setSend_status("2");
} else {
dto.setSend_status("1");
}
}
}
} catch (Exception e) {
dto.setSend_status("2");
log.error(e.getMessage());
@@ -619,31 +593,7 @@ public class InstructionServiceImpl extends CommonServiceImpl<InstructionMapper,
throw new BadRequestException(LangProcess.msg("error_isNull", "route"));
}
//判断是否是仙工AGV
if (shortPathsList.size() > 0 && StrUtil.equals(shortPathsList.get(0).getType(), CommonFinalParam.ONE)) {
Device deviceByCode = deviceAppService.findDeviceByCode(dto.getStart_device_code());
if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.XG_System_Type.getIndex())) {
String interactionJson = task.getInteraction_json();
if (StrUtil.isEmpty(interactionJson)) {
throw new BadRequestException("agv叉车调整长宽参数为空");
}
InteractionJsonDTO interactionJsonDTO = JSON.parseObject(interactionJson, InteractionJsonDTO.class);
//仙工叉车
HttpResponse response = xiangGongAgvService.sendOrderSequencesToForklift(dto, interactionJsonDTO);
if (ObjectUtils.isEmpty(response) || response.getStatus() != 200) {
dto.setSend_status("2");
} else {
dto.setSend_status("1");
}
} else if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.One_NDC_System_Type.getIndex())) {
//一楼agv任务创建运单序列
HttpResponse response = xiangGongAgvService.sendOrderSequencesToXZ(dto);
if (ObjectUtils.isEmpty(response) || response.getStatus() != 200) {
dto.setSend_status("2");
} else {
dto.setSend_status("1");
}
} else if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.Two_NDC_System_Type.getIndex())) {
if (dto.getAgv_system_type().equals(AgvSystemTypeEnum.Two_NDC_System_Type.getIndex())) {
NDCAgvService ndcAgvService = SpringContextHolder.getBean(NDCAgvService.class);
log.warn("下发AGV指令数据," + "指令号:" + dto.getInstruction_code() + ",AGV系统类型:" + dto.getAgv_system_type());
try {
@@ -662,7 +612,6 @@ public class InstructionServiceImpl extends CommonServiceImpl<InstructionMapper,
luceneExecuteLogService.deviceExecuteLog(logDto1);
}
}
}
} catch (Exception e) {
dto.setSend_status("2");
log.error(e.getMessage());
@@ -1976,13 +1925,22 @@ public class InstructionServiceImpl extends CommonServiceImpl<InstructionMapper,
return optionalInstruction.orElse(null);
}
@Override
public int queryInstructionCount(String deviceCode) {
List<Instruction> instructionsList = instructions.stream()
.filter(item -> StrUtil.equals(item.getNext_device_code(), deviceCode)
&& StrUtil.equals(item.getInstruction_status(), TaskStatusEnum.READY.getIndex())
&& StrUtil.equals(item.getInstruction_status(), TaskStatusEnum.BUSY.getIndex())).collect(Collectors.toList());
return instructionsList.size();
}
public List<Instruction> findReadyInstructions() {
//根据时间升序取第一个
List<Instruction> instructionsList = instructions.stream()
.filter(item -> StrUtil.equals(item.getInstruction_type(), TaskTypeEnum.Truss_Task.getIndex())
&& StrUtil.equals(item.getInstruction_status(), TaskStatusEnum.READY.getIndex())).collect(Collectors.toList());
&& !StrUtil.equals(item.getInstruction_status(), TaskStatusEnum.READY.getIndex())).collect(Collectors.toList());
return instructionsList;
}

View File

@@ -0,0 +1,110 @@
package org.nl.acs.rfid_manage.controller;
import cn.dev33.satoken.annotation.SaIgnore;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.rfid_manage.service.IbmVehicleRfidService;
import org.nl.acs.rfid_manage.service.dto.BmVehicleRfidParam;
import org.nl.common.base.TableDataInfo;
import org.nl.common.domain.query.PageQuery;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;
@RestController
@RequiredArgsConstructor
@RequestMapping("/api/rfid")
@Slf4j
@SaIgnore
public class BmVehicleRfidController {
@Resource
private IbmVehicleRfidService bmVehicleRfidService;
/**
* 分页查询
*
* @param whereJson 查询条件
* @param page 分页参数
*/
@GetMapping
//@SaCheckPermission("@el.check(BmVehicleRfid:list")
public ResponseEntity<Object> query(@RequestParam Map whereJson, PageQuery page) {
//写入标签
//bmVehicleRfidService.writeEpc("1");
return new ResponseEntity<>(TableDataInfo.build(bmVehicleRfidService.query(whereJson, page)), HttpStatus.OK);
}
/**
* 条件查询
*
* @param params 查询条件
*/
@PostMapping("/selectList")
//@SaCheckPermission("@el.check(BmVehicleRfid:list")
public ResponseEntity<Object> selectList(@RequestBody BmVehicleRfidParam params) {
return new ResponseEntity<>(bmVehicleRfidService.selectList(params), HttpStatus.OK);
}
/**
* 新增数据
*
* @param params 实体对象
* @return 新增结果
*/
@PostMapping
//@SaCheckPermission("@el.check(BmVehicleRfid:add")
public ResponseEntity<Object> create(@RequestBody BmVehicleRfidParam params) {
bmVehicleRfidService.create(params);
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* 连接测试
* @return 结果
*/
@PostMapping("/open")
//@SaCheckPermission("@el.check(BmVehicleRfid:add")
public ResponseEntity<Object> connectRfid(@RequestBody BmVehicleRfidParam params) {
bmVehicleRfidService.connectRfid(params);
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* 修改数据
*
* @param params 实体对象
* @return 修改结果
*/
@PutMapping
//@SaCheckPermission("@el.check(BmVehicleRfid:edit')")
public ResponseEntity<Object> update(@RequestBody BmVehicleRfidParam params) {
bmVehicleRfidService.update(params);
return new ResponseEntity<>(HttpStatus.OK);
}
/**
* 删除数据
*
* @param ids 多个主键Id
* @return 删除结果
*/
//@SaCheckPermission("@el.check(BmVehicleRfid:del')")
@DeleteMapping
public ResponseEntity<Object> delete(@RequestBody Set<String> ids) {
bmVehicleRfidService.deleteAll(ids);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -0,0 +1,60 @@
package org.nl.acs.rfid_manage.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import org.nl.acs.rfid_manage.service.dao.BmVehicleRfid;
import org.nl.acs.rfid_manage.service.dto.BmVehicleRfidParam;
import org.nl.common.domain.query.PageQuery;
import java.util.List;
import java.util.Map;
import java.util.Set;
public interface IbmVehicleRfidService extends IService<BmVehicleRfid> {
/**
* 分页查询
*
* @param whereJson 查询条件
* @return IPage<BmVehicleRfid>
*/
IPage<BmVehicleRfid> query(Map whereJson, PageQuery page);
/**
* 条件查询
*
* @param params 查询条件
* @return List<BmVehicleRfid>
*/
List<BmVehicleRfid> selectList(BmVehicleRfidParam params);
/**
* 创建
*
* @param params 对象实体
*/
void create(BmVehicleRfidParam params);
/**
* 编辑
*
* @param params 对象实体
*/
void update(BmVehicleRfidParam params);
/**
* 多选删除
*
* @param ids /
*/
void deleteAll(Set<String> ids);
void connectRfid(BmVehicleRfidParam params);
void writeEpc(String id);
BmVehicleRfid findByDeviceCode(String linkDeviceCode);
}

View File

@@ -0,0 +1,122 @@
package org.nl.acs.rfid_manage.service.dao;
import com.baomidou.mybatisplus.annotation.*;
import com.baomidou.mybatisplus.extension.activerecord.Model;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.io.Serializable;
@Data
@EqualsAndHashCode(callSuper = true)
@TableName("bm_vehicle_rfid")
public class BmVehicleRfid extends Model<BmVehicleRfid> {
private static final long serialVersionUID = -7739291296662381393L;
//@TableId(type = IdType.ASSIGN_ID)
/**
* 主键id
*/
@TableId(value = "id", type = IdType.NONE)
private String id;
/**
* ip
*/
private String ip;
/**
* 端口
*/
private String port;
/**
* 设备编号
*/
private String device_code;
/**
* rfid号码
*/
private String rfid;
/**
* 开始连接时间
*/
private String start_time;
/**
* 创建人
*/
private String create_id;
/**
* 创建人姓名
*/
private String create_name;
/**
* 创建时间
*/
@TableField(fill = FieldFill.INSERT)
private String create_time;
/**
* 修改人
*/
private String update_id;
/**
* 修改人姓名
*/
private String update_name;
/**
* 在线时间
*/
@TableField(exist = false)
private String online_time;
/**
* 日志
*/
private String log;
/**
* 修改时间
*/
@TableField(fill = FieldFill.INSERT_UPDATE)
private String update_time;
/**
* 是否启用
*/
private Integer is_used;
/**
* 状态
*/
private Integer status;
/**
* 获取主键值
*
* @return 主键值
*/
@Override
protected Serializable pkVal() {
return this.id;
}
}

View File

@@ -0,0 +1,7 @@
package org.nl.acs.rfid_manage.service.dao.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.nl.acs.rfid_manage.service.dao.BmVehicleRfid;
public interface BmVehicleRfidMapper extends BaseMapper<BmVehicleRfid> {
}

View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.nl.acs.rfid_manage.service.dao.mapper.BmVehicleRfidMapper">
</mapper>

View File

@@ -0,0 +1,70 @@
package org.nl.acs.rfid_manage.service.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BmVehicleRfidDto implements Serializable {
private static final long serialVersionUID = -7739291296662381396L;
/**
* 设备id
*/
private String id;
/**
* ip
*/
private String ip;
/**
* 端口
*/
private String port;
/**
* 设备编号
*/
private String device_code;
/**
* rfid号码
*/
private String rfid;
/**
* 开始连接时间
*/
private String start_time;
/**
* 创建人
*/
private String create_id;
/**
* 创建人姓名
*/
private String create_name;
/**
* 创建时间
*/
private String create_time;
/**
* 修改人
*/
private String update_id;
/**
* 修改人姓名
*/
private String update_name;
/**
* 修改时间
*/
private String update_time;
/**
* 是否启用
*/
private Integer is_used;
}

View File

@@ -0,0 +1,68 @@
package org.nl.acs.rfid_manage.service.dto;
import lombok.*;
import org.nl.acs.rfid_manage.service.dao.BmVehicleRfid;
import org.nl.common.domain.query.BaseQuery;
@Data
@Builder
@ToString
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode(callSuper = false)
public class BmVehicleRfidParam extends BaseQuery<BmVehicleRfid> {
/**
* 设备id
*/
private String id;
/**
* ip
*/
private String ip;
/**
* 端口
*/
private String port;
/**
* 设备编号
*/
private String device_code;
/**
* rfid号码
*/
private String rfid;
/**
* 开始连接时间
*/
private String start_time;
/**
* 创建人
*/
private String create_id;
/**
* 创建人姓名
*/
private String create_name;
/**
* 创建时间
*/
private String create_time;
/**
* 修改人
*/
private String update_id;
/**
* 修改人姓名
*/
private String update_name;
/**
* 修改时间
*/
private String update_time;
/**
* 开启或关闭
*/
private String isOpen;
}

View File

@@ -0,0 +1,11 @@
package org.nl.acs.rfid_manage.service.dto;
public class EpcRecord {
public String epc;
public long timestamp;
public EpcRecord(String epc, long timestamp) {
this.epc = epc;
this.timestamp = timestamp;
}
}

View File

@@ -0,0 +1,521 @@
package org.nl.acs.rfid_manage.service.impl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gg.reader.api.dal.GClient;
import com.gg.reader.api.dal.HandlerTagEpcLog;
import com.gg.reader.api.dal.HandlerTcpDisconnected;
import com.gg.reader.api.protocol.gx.*;
import org.apache.commons.lang3.StringUtils;
import org.nl.acs.rfid_manage.service.IbmVehicleRfidService;
import org.nl.acs.rfid_manage.service.dao.BmVehicleRfid;
import org.nl.acs.rfid_manage.service.dao.mapper.BmVehicleRfidMapper;
import org.nl.acs.rfid_manage.service.dto.BmVehicleRfidParam;
import org.nl.acs.rfid_manage.service.dto.EpcRecord;
import org.nl.acs.utils.StructUtil;
import org.nl.common.domain.query.PageQuery;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
@Service("bmVehicleRfidService")
public class BmVehicleRfidServiceImpl extends ServiceImpl<BmVehicleRfidMapper, BmVehicleRfid> implements IbmVehicleRfidService {
@Resource
private BmVehicleRfidMapper bmVehicleRfidMapper;
// EPC 缓存设备ID -> 天线号 -> EPC记录对象包含EPC值 + 时间戳)
private static final ConcurrentHashMap<String, ConcurrentHashMap<String, EpcRecord>> epcCache = new ConcurrentHashMap<>();
//rfid读写器列表
private static final ConcurrentHashMap<String, GClient> clientMap = new ConcurrentHashMap<>();
// 缓存过期时间单位毫秒例如5分钟
private static final long EXPIRE_MILLIS = 5 * 60 * 1000;
@Override
public void connectRfid(BmVehicleRfidParam params) {
//reconnectAllDisconnectedClients();
List<BmVehicleRfid> clientList = this.list(new QueryWrapper<BmVehicleRfid>().eq("is_used", '1'));
for (BmVehicleRfid r : clientList) {
String deviceId = r.getId();
GClient client = clientMap.get(deviceId);
String port = StringUtils.isNotBlank(params.getPort()) ? params.getPort() : r.getPort();
String ip = r.getIp() + ":" + port;
// 打开连接命令 "1" 为开启所有设备连接,"0" 为关闭所有设备连接
if ("1".equals(params.getIsOpen())) {
// 如果客户端连接对象不存在或未打开,创建新连接
if (client == null) {
client = new GClient();
if (client.openTcp(ip, 2000)) {
addClient(deviceId, client);
client.setSendHeartBeat(true);
stopEpc(deviceId);
// 发送扫码启动命令
MsgBaseInventoryEpc msgBaseInventoryEpc = new MsgBaseInventoryEpc();
msgBaseInventoryEpc.setAntennaEnable(EnumG.AntennaNo_1); // 默认1号天线
msgBaseInventoryEpc.setInventoryMode(EnumG.InventoryMode_Inventory);
client.sendSynMsg(msgBaseInventoryEpc);
if (msgBaseInventoryEpc.getRtCode() == 0x00) {
System.out.println("设备[" + ip + "] 开始扫码任务成功");
} else {
System.err.println("设备[" + ip + "] 扫码配置失败: " + msgBaseInventoryEpc.getRtMsg());
}
//写入数据
// MsgBaseWriteEpc msg = new MsgBaseWriteEpc();
// msg.setAntennaEnable(EnumG.AntennaNo_1);
// //字起始地址 第0个为CRC不可写
// msg.setStart(1);//word
// //写EPC数据默认为 hex 432
// msg.setArea(EnumG.WriteArea_Epc);
// String sWriteHexData = "888"; // 写入数据 16进制
// System.out.println("Write hex " + sWriteHexData);
// int iWordLen = StructUtil.getValueLen(sWriteHexData);
// // PC值为EPC区域的长度标识前5个bit标记长度参考文档说明
// sWriteHexData = StructUtil.getPc(iWordLen) + StructUtil.padLeft(sWriteHexData.toUpperCase(), 4 * iWordLen, '0'); // PC值+数据内容
// msg.setHexWriteData(sWriteHexData);
// // 若需要写入带特殊编码数据,请自行进行编码并使用 "BwriteData" 属性。
// // msg.setBwriteData(HexUtils.hexString2Bytes(sWriteHexData));
// client.sendSynMsg(msg);
// if (0 == msg.getRtCode()) {
// System.out.println("写入:" + sWriteHexData + "成功!");
// } else {
// System.out.println("写入:" + sWriteHexData + "失败!");
// }
// 订阅标签事件
subscribeHandler(client, deviceId);
MsgAppGetBaseVersion msgAppGetBaseVersion = new MsgAppGetBaseVersion();
//获取版本号
client.sendSynMsg(msgAppGetBaseVersion);
if (0x00 == msgAppGetBaseVersion.getRtCode()) {
System.out.println("msgAppGetBaseVersion[OK].");
} else {
System.out.println(msgAppGetBaseVersion.getRtMsg());
}
//获取设备信息
MsgAppGetReaderInfo msgAppGetReaderInfo = new MsgAppGetReaderInfo();
client.sendSynMsg(msgAppGetReaderInfo);
if (0x00 == msgAppGetReaderInfo.getRtCode()) {
System.out.println("msgAppGetReaderInfo[OK].");
} else {
System.out.println(msgAppGetReaderInfo.getRtMsg());
}
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(deviceId);
updated.setStart_time(DateUtil.now());
updated.setStatus(1);
updated.setLog(DateUtil.now() + ":设备:" + r.getDevice_code() + "连接服务器成功!");
this.updateById(updated);
} else {
System.err.println("设备[" + ip + "] TCP连接失败");
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(deviceId);
updated.setRfid(null);
updated.setLog(DateUtil.now() + ":设备:" + r.getDevice_code() + "连接服务器失败!");
updated.setStatus(0);
this.updateById(updated);
continue;
}
}
// 检查连接有效性(通过版本获取判断)
if (!checkConnection(client)) {
System.err.println("设备[" + ip + "] 连接无效,关闭重试");
removeClient(deviceId);
}
} else if ("0".equals(params.getIsOpen())) {
// 关闭连接
if (client != null) {
// MsgBaseStop stopMsg = new MsgBaseStop();
// client.sendSynMsg(stopMsg);
// if (stopMsg.getRtCode() == 0x00) {
// System.out.println("设备[" + ip + "] 停止扫码任务成功");
// } else {
// System.err.println("设备[" + ip + "] 停止扫码失败: " + stopMsg.getRtMsg());
// }
// client.close();
// removeClient(deviceId);
disconnectAllClients();
System.out.println("设备[" + ip + "] 已断开连接");
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(deviceId);
updated.setRfid(null);
updated.setLog(DateUtil.now() + ":设备:" + r.getDevice_code() + "已与服务器断开连接!");
updated.setStart_time(null);
updated.setStatus(0);
this.updateById(updated);
} else {
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(deviceId);
updated.setLog(DateUtil.now() + ":设备:" + r.getDevice_code() + "未连接,无需断开");
updated.setStart_time(null);
updated.setStatus(0);
this.updateById(updated);
System.out.println("设备[" + ip + "] 未连接,无需断开");
}
}
}
}
@Override
public void writeEpc(String id) {
GClient client = getClient("1");
if (client != null) {
MsgBaseWriteEpc msg = new MsgBaseWriteEpc();
stopEpc(id);
msg.setAntennaEnable(EnumG.AntennaNo_1);
//字起始地址 第0个为CRC不可写
msg.setStart(1);//word
//写EPC数据默认为 hex 432
msg.setArea(EnumG.WriteArea_Epc);
String sWriteHexData = "666"; // 写入数据 16进制
System.out.println("Write hex " + sWriteHexData);
int iWordLen = StructUtil.getValueLen(sWriteHexData);
// PC值为EPC区域的长度标识前5个bit标记长度参考文档说明
sWriteHexData = StructUtil.getPc(iWordLen) + StructUtil.padLeft(sWriteHexData.toUpperCase(), 4 * iWordLen, '0'); // PC值+数据内容
msg.setHexWriteData(sWriteHexData);
// 若需要写入带特殊编码数据,请自行进行编码并使用 "BwriteData" 属性。
// msg.setBwriteData(HexUtils.hexString2Bytes(sWriteHexData));
client.sendSynMsg(msg);
if (0 == msg.getRtCode()) {
System.out.println("写入:" + sWriteHexData + "成功!");
} else {
System.out.println("写入:" + sWriteHexData + "失败!");
}
}
}
@Override
public BmVehicleRfid findByDeviceCode(String linkDeviceCode) {
List<BmVehicleRfid> bmVehicleRfids = bmVehicleRfidMapper.selectList(new LambdaQueryWrapper<BmVehicleRfid>().eq(BmVehicleRfid::getDevice_code, linkDeviceCode));
if (bmVehicleRfids.size() > 0) {
return bmVehicleRfids.get(0);
}
return null;
}
public void stopEpc(String id) {
GClient client = getClient("1");
if (client != null) {
MsgBaseStop msgBaseStop = new MsgBaseStop();
client.sendSynMsg(msgBaseStop);
if (0 == msgBaseStop.getRtCode()) {
System.out.println("停止成功!");
} else {
System.out.println("停止失败!");
}
}
}
/**
* 判断设备是否已连接(通过获取版本信息判断)
*/
private boolean checkConnection(GClient client) {
try {
MsgAppGetBaseVersion versionMsg = new MsgAppGetBaseVersion();
client.sendSynMsg(versionMsg);
return versionMsg.getRtCode() == 0x00;
} catch (Exception e) {
return false;
}
}
/**
* 定时器执行断线重连
*/
public void reconnectAllDisconnectedClients() {
List<BmVehicleRfid> clientList = this.list(new QueryWrapper<BmVehicleRfid>().eq("is_used", '1'));
for (BmVehicleRfid r : clientList) {
String ip = r.getIp() + ":" + r.getPort();
System.out.println("设备[" + ip + "] 连接异常,开始重连...");
if (tryReconnect(r.getId(), ip)) {
System.out.println("设备[" + ip + "] 重连成功");
} else {
System.err.println("设备[" + ip + "] 重连失败");
}
}
}
public boolean tryReconnect(String deviceId, String ip) {
final int MAX_RETRY = 3;
final int WAIT_MS = 500;
for (int i = 1; i <= MAX_RETRY; i++) {
System.out.println("设备[" + ip + "] 第" + i + "次重连尝试...");
GClient oldClient = clientMap.remove(deviceId);
if (oldClient != null) {
try {
oldClient.close();
} catch (Exception ignored) {
}
}
GClient newClient = new GClient();
if (newClient.openTcp(ip, 2000)) {
addClient(deviceId, newClient);
subscribeHandler(newClient, deviceId);
newClient.setSendHeartBeat(true);
if (checkConnection(newClient)) {
System.out.println("设备[" + ip + "] 重连成功");
return true;
} else {
try {
newClient.close();
} catch (Exception ignored) {
}
}
}
try {
Thread.sleep(WAIT_MS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return false;
}
}
return false;
}
public static GClient getClient(String deviceId) {
return clientMap.get(deviceId);
}
public static void disconnectAllClients() {
for (String deviceId : clientMap.keySet()) {
removeClient(deviceId);
}
}
public static void addClient(String deviceId, GClient client) {
clientMap.put(deviceId, client);
}
public static void removeClient(String deviceId) {
GClient client = clientMap.remove(deviceId);
if (client != null) {
client.close();
// try {
// MsgBaseStop stopMsg = new MsgBaseStop();
// client.sendSynMsg(stopMsg);
// if (stopMsg.getRtCode() == 0x00) {
// System.out.println("停止扫码任务成功: " + deviceId);
// } else {
// System.err.println("停止扫码失败: " + stopMsg.getRtMsg());
// }
// } catch (Exception e) {
// System.err.println("停止扫码任务异常: " + e.getMessage());
// } finally {
// client.close();
// System.out.println("已断开设备连接: " + deviceId);
// }
}
}
/**
* 上报RFID信息
*/
private void subscribeHandler(GClient client, String id) {
//上报标签信息
client.onTagEpcLog = new HandlerTagEpcLog() {
@Override
public void log(String s, LogBaseEpcInfo logBaseEpcInfo) {
if (logBaseEpcInfo != null && logBaseEpcInfo.getResult() == 0) {
String epc = logBaseEpcInfo.getEpc();
handleEpc(epc, id, "1");
}
}
};
//断开连接通知
client.onDisconnected = new HandlerTcpDisconnected() {
@Override
public void log(String s) {
System.out.println("command log output5:onDisconnected:" + "connect" + s + "close..........");
client.close();//释放当前连接资源
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(id);
updated.setRfid(null);
// updated.setLog(DateUtil.now() + ":设备:" + r.getDevice_code() + "已与服务器断开连接!");
updated.setStart_time(null);
updated.setStatus(0);
//todo 更新断开状态
// this.updateById(updated);
}
};
}
/**
* 主处理方法:如果 EPC 不同或过期,则更新数据库
*/
private void handleEpc(String epc, String deviceId, String antenna) {
if (epc == null) {
return;
}
ConcurrentHashMap<String, EpcRecord> antennaMap = epcCache.get(deviceId);
EpcRecord record = antennaMap != null ? antennaMap.get(antenna) : null;
boolean isSame = record != null && epc.equals(record.epc)
&& System.currentTimeMillis() - record.timestamp < EXPIRE_MILLIS;
if (isSame) {
System.out.println(epc + "与上次标签值相同,不上报,跳过....");
return; // EPC 相同且未过期,跳过
}
epcCache.computeIfAbsent(deviceId, k -> new ConcurrentHashMap<>())
.put(antenna, new EpcRecord(epc, System.currentTimeMillis()));
BmVehicleRfid currentDevice = this.getById(deviceId);
if (currentDevice != null && !epc.equals(currentDevice.getRfid())) {
BmVehicleRfid updated = new BmVehicleRfid();
updated.setId(deviceId);
updated.setRfid(epc);
updated.setLog(DateUtil.now() + ":设备:" + currentDevice.getDevice_code() + "读取RFID值:" + epc + "成功!");
this.updateById(updated);
System.out.println("读取RFID值:" + epc + "成功!");
}
}
/**
* 定期清理过期 EPC 缓存(建议由定时任务调用)
*/
private void clearExpiredCache() {
long now = System.currentTimeMillis();
for (Map.Entry<String, ConcurrentHashMap<String, EpcRecord>> deviceEntry : epcCache.entrySet()) {
ConcurrentHashMap<String, EpcRecord> antennaMap = deviceEntry.getValue();
for (Map.Entry<String, EpcRecord> antennaEntry : antennaMap.entrySet()) {
if (now - antennaEntry.getValue().timestamp >= EXPIRE_MILLIS) {
antennaMap.remove(antennaEntry.getKey());
}
}
if (antennaMap.isEmpty()) {
epcCache.remove(deviceEntry.getKey());
}
}
}
/**
* 查询数据分页
*
* @param whereJson 查询条件
* @param page 分页参数
*/
@Override
public IPage<BmVehicleRfid> query(Map whereJson, PageQuery page) {
IPage<BmVehicleRfid> resultPage = new Page<>(page.getPage(), page.getSize());
LambdaQueryWrapper<BmVehicleRfid> queryWrapper = new LambdaQueryWrapper<>();
IPage<BmVehicleRfid> list = bmVehicleRfidMapper.selectPage(resultPage, queryWrapper);
list.getRecords().forEach(r -> {
if (r.getStart_time() != null) {
LocalDateTime createTime = LocalDateTime.parse(r.getStart_time(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
LocalDateTime updateTime = DateTime.now().toLocalDateTime();
// 计算时间间隔
Duration duration = Duration.between(createTime, updateTime);
if (duration.toMinutes() > 0) {
r.setOnline_time(duration.toMinutes() + "分钟");
} else {
r.setOnline_time(duration.getSeconds() + "秒钟");
}
}
});
return list;
}
/**
* 根据条件查询
*
* @param params 查询条件
*/
@Override
public List<BmVehicleRfid> selectList(BmVehicleRfidParam params) {
return bmVehicleRfidMapper.selectList(new QueryWrapper<BmVehicleRfid>()
.lambda()
//.eq(ObjectUtil.isNotEmpty(params), BmVehicleRfid::getId, params.getFuzzy())
//.or()
//.eq(ObjectUtil.isNotEmpty(params), BmVehicleRfid::getDjid, params.getFuzzy())
);
}
/**
* 创建
*
* @param params 对象实体
*/
@Override
public void create(BmVehicleRfidParam params) {
bmVehicleRfidMapper.insert(getBasicInfo(params, true));
}
/**
* 编辑
*
* @param params 对象实体
*/
@Override
public void update(BmVehicleRfidParam params) {
// BmVehicleRfid dto = bmVehicleRfidMapper.selectById(params.getId());
// if (dto == null) {
// throw new BadRequestException("不存在该数据!");
// }
bmVehicleRfidMapper.updateById(getBasicInfo(params, false));
}
/**
* 多选删除
*
* @param ids 多个Id主键
*/
@Override
public void deleteAll(Set<String> ids) {
UpdateWrapper<BmVehicleRfid> updateWrapper = new UpdateWrapper<>();
updateWrapper.set("is_delete", "1")
//.set("update_optid", SecurityUtils.getCurrentUserId())
//.set("update_optname", SecurityUtils.getCurrentNickName())
//.set("update_time", DateUtil.now())
.in("id", ids);
bmVehicleRfidMapper.update(null, updateWrapper);
//bmVehicleRfidMapper.deleteBatchIds(ids);
}
/**
* 获取实体基础信息
*
* @param params 对象实体
* @param isCreate 是否创建
*/
private BmVehicleRfid getBasicInfo(BmVehicleRfidParam params, boolean isCreate) {
// if (isCreate) {
// params.setId(IdUtil.getStringId());
// params.setCreate_id(Long.valueOf(SecurityUtils.getCurrentUserId()));
// params.setCreate_name(SecurityUtils.getCurrentNickName());
// params.setCreate_time(DateUtil.now());
// params.setIs_delete(IOSEnum.IS_NOTANDYES.code("否"));
// }
// params.setUpdate_optid(Long.valueOf(SecurityUtils.getCurrentUserId()));
// params.setUpdate_optname(SecurityUtils.getCurrentNickName());
// params.setUpdate_time(DateUtil.now());
BmVehicleRfid bmVehicleRfid = new BmVehicleRfid();
BeanUtils.copyProperties(params, bmVehicleRfid);
return bmVehicleRfid;
}
}

View File

@@ -11,8 +11,10 @@ import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;
@@ -72,4 +74,11 @@ public class StorageCellController {
public void download(HttpServletResponse response, @RequestParam Map whereJson) throws IOException {
storageCellService.download(storageCellService.queryAll(whereJson), response);
}
@PostMapping("/excelImport")
@Log("excel导入")
public ResponseEntity<Object> excelImport(@RequestParam("file") MultipartFile file, HttpServletRequest request) {
storageCellService.excelImport(file, request);
return new ResponseEntity<>(HttpStatus.OK);
}
}

View File

@@ -6,7 +6,9 @@ import org.nl.acs.storage_cell.domain.StorageCell;
import org.nl.acs.storage_cell.service.dto.StorageCellDto;
import org.nl.acs.storage_cell.service.dto.StorageCellQueryParam;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.List;
@@ -155,4 +157,12 @@ public interface StorageCellService extends CommonService<StorageCell> {
* @throws IOException /
*/
void download(List<StorageCellDto> dtos, HttpServletResponse response) throws IOException;
/**
* excel导入
*
* @param file
* @param request
*/
void excelImport(MultipartFile file, HttpServletRequest request);
}

View File

@@ -4,9 +4,13 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelReader;
import cn.hutool.poi.excel.ExcelUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
@@ -14,7 +18,9 @@ import lombok.AllArgsConstructor;
import org.nl.acs.common.base.PageInfo;
import org.nl.acs.common.base.QueryHelpMybatisPlus;
import org.nl.acs.common.base.impl.CommonServiceImpl;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device.service.dto.DeviceDto;
import org.nl.common.exception.BadRequestException;
import org.nl.acs.utils.ConvertUtil;
import org.nl.common.utils.FileUtil;
@@ -35,9 +41,12 @@ import org.springframework.transaction.annotation.Transactional;
//import org.springframework.cache.annotation.CacheEvict;
//import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Pageable;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
/**
@@ -178,6 +187,16 @@ public class StorageCellServiceImpl extends CommonServiceImpl<StorageCellMapper,
return null;
}
public StorageCellDto findByCode(String storage_code) {
StorageCell storageCell = storageCellMapper.selectOne(new QueryWrapper<StorageCell>().eq("storage_code", storage_code));
if (ObjectUtil.isNotEmpty(storageCell)) {
final StorageCellDto obj = ConvertUtil.convert(storageCell, StorageCellDto.class);
return obj;
}
return null;
}
// @Override
// public StorageCellDto findByCode(String code) {
// WQLObject wo = WQLObject.getWQLObject("acs_storage_cell");
@@ -260,4 +279,60 @@ public class StorageCellServiceImpl extends CommonServiceImpl<StorageCellMapper,
}
FileUtil.downloadExcel(list, response);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void excelImport(MultipartFile file, HttpServletRequest request) {
if (file.isEmpty()) {
throw new BadRequestException(LangProcess.msg("error_nullPoint"));
}
Long currentUserId = Long.valueOf(SecurityUtils.getCurrentUserId());
String nickName = SecurityUtils.getCurrentNickName();
String now = DateUtil.now();
// 1.获取上传文件输入流
InputStream inputStream = null;
try {
inputStream = file.getInputStream();
} catch (Exception e) {
e.printStackTrace();
}
// WQLObject wo = WQLObject.getWQLObject("acs_device");
// 调用用 hutool 方法读取数据 默认调用第一个sheet
ExcelReader excelReader = ExcelUtil.getReader(inputStream);
// 从第二行开始获取数据 excelReader.read的结果是一个2纬的list外层是行内层是行对应的所有列
List<List<Object>> read = excelReader.read(1, excelReader.getRowCount());
// 循环获取的数据
for (int i = 0; i < read.size(); i++) {
List list = read.get(i);
JSONObject param = new JSONObject();
String storage_code = list.get(0).toString();
String parent_storage_code = list.get(1).toString();
if (StrUtil.isEmpty(storage_code)) {
throw new BadRequestException(LangProcess.msg("error_checkNull", "storage_code"));
}
if (StrUtil.isEmpty(parent_storage_code)) {
throw new BadRequestException(LangProcess.msg("error_checkNull", "parent_storage_code"));
}
StorageCellDto dto = this.findByCode(storage_code);
if (ObjectUtil.isNotEmpty(dto)) {
continue;
}
//按照列获取
param.put("device_id", IdUtil.getSnowflake(1, 1).nextId());
param.put("storage_code", storage_code);
param.put("parent_storage_code", parent_storage_code);
param.put("create_by", nickName);
param.put("create_time", now);
param.put("update_by", nickName);
param.put("update_time", now);
StorageCell entity = ConvertUtil.convert(param, StorageCell.class);
storageCellMapper.insert(entity);
}
}
}

View File

@@ -0,0 +1,66 @@
package org.nl.acs.utils;
import com.gg.reader.api.utils.BitBuffer;
import com.gg.reader.api.utils.HexUtils;
public class StructUtil {
public static String getZdPoint(int row,String source_code) {
if (row == 2 || row == 3) {
return source_code;
}
int blockRow = row == 1 ? 2 : 3;
String replace = source_code.replaceFirst("L0" + row, "L0%s");
return String.format(replace, blockRow);
}
public static String getDeepPoint(int row,String source_code) {
if (row == 1 || row == 4) {
return source_code;
}
int blockRow = row == 2 ? 1 : 4;
String replace = source_code.replaceFirst("L0" + row, "L0%s");
return String.format(replace, blockRow);
}
public static String getPc(int pcLen) {
int iPc = pcLen << 11;
BitBuffer buffer = BitBuffer.allocateDynamic();
buffer.put(iPc);
buffer.position(16);
byte[] bTmp = new byte[2];
buffer.get(bTmp);
return HexUtils.bytes2HexString(bTmp);
}
public static String getGbPc(int pcLen) {
int iPc = pcLen << 8;
BitBuffer buffer = BitBuffer.allocateDynamic();
buffer.put(iPc);
buffer.position(16);
byte[] bTmp = new byte[2];
buffer.get(bTmp);
return HexUtils.bytes2HexString(bTmp);
}
//写入数据不足4位后面补'0' AA00
public static String padLeft(String src, int len, char ch) {
int diff = len - src.length();
if (diff <= 0) {
return src;
}
char[] chars = new char[len];
System.arraycopy(src.toCharArray(), 0, chars, 0, src.length());
for (int i = src.length(); i < len; i++) {
chars[i] = ch;
}
return new String(chars);
}
public static int getValueLen(String data) {
data = data.trim();
return data.length() % 4 == 0 ? data.length() / 4
: (data.length() / 4) + 1;
}
}

View File

@@ -31,8 +31,8 @@ public class BaseQuery<T> {
/**
* 创建时间范围查询
*/
private Date start_time;
private Date end_time;
private String start_time;
private String end_time;
/**

View File

@@ -10,6 +10,7 @@ import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.nl.acs.common.base.CommonFinalParam;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device_driver.conveyor.belt_conveyor.BeltConveyorDeviceDriver;
import org.nl.acs.instruction.domain.InstructionMybatis;
import org.nl.acs.instruction.enums.InstructionStatusEnum;
import org.nl.acs.instruction.service.InstructionService;
@@ -57,12 +58,6 @@ public class AutoCreateInst {
List<TaskDto> list = taskserver.queryAllByStatus("0");
for (int i = 0; i < list.size(); i++) {
TaskDto acsTask = list.get(i);
if (StrUtil.equals(acsTask.getTask_type(), TaskTypeEnum.AGV_Task.getIndex()) && !StrUtil.startWith(acsTask.getTask_code(), "-")) {
continue;
}
if (StrUtil.equals(acsTask.getTask_type(), TaskTypeEnum.Truss_Task.getIndex()) && !StrUtil.startWith(acsTask.getTask_code(), "-")) {
continue;
}
String taskid = acsTask.getTask_id();
String taskcode = acsTask.getTask_code();
String task_type = acsTask.getTask_type();
@@ -137,11 +132,25 @@ public class AutoCreateInst {
}
next_device_code = pathlist.get(index);
Device nextdevice = appService.findDeviceByCode(next_device_code);
if (StrUtil.equals(appService.findDeviceTypeByCode(next_device_code), "storage")) {
next_point_code = next_device_code + "-" + acsTask.getTo_y() + "-" + acsTask.getTo_z();
} else {
next_point_code = next_device_code;
}
BeltConveyorDeviceDriver beltConveyorDeviceDriver;
if (nextdevice.getDeviceDriver() instanceof BeltConveyorDeviceDriver) {
beltConveyorDeviceDriver = (BeltConveyorDeviceDriver) nextdevice.getDeviceDriver();
if (beltConveyorDeviceDriver.getType() != 2) {
beltConveyorDeviceDriver.writing("to_command","7");
log.info("当前输送线出入库信号不为出库");
continue;
}
//满足出库,查询当前出库任务
// int count = instructionService.queryInstructionCount(next_device_code);
// count = count + 1;
// beltConveyorDeviceDriver.writing("to_taskNum",count+"");
}
Instruction instdto = new Instruction();
@@ -182,34 +191,7 @@ public class AutoCreateInst {
instdto.setStart_height(start_height);
instdto.setNext_height(next_height);
instdto.setAgv_action_type(agvActionType);
//判断agv系统
//1、1楼叉车系统
//2、2楼1区域AGV系统
//3、2楼2区域AGV系统 -已废弃
if (StrUtil.equals(agv_system_type, CommonFinalParam.TWO)) {
// task_type
//1、生箔 Itype=1:取空,取满,放空,放满;
//2、分切 Itype=3取满、取空、放满、放空
//3、普通任务 Itype=2:取货、放货;
//4、叉车任务
//5、输送任务
//6、行架
//7、立库
if (StrUtil.equals(task_type, CommonFinalParam.ONE)) {
instdto.setAgv_inst_type(CommonFinalParam.ONE);
} else if (StrUtil.equals(task_type, "3")) {
instdto.setAgv_inst_type("2");
} else if (StrUtil.equals(task_type, "2")) {
instdto.setAgv_inst_type("3");
} else if (StrUtil.equals(task_type, "8")) {
instdto.setAgv_inst_type("2");
} else {
log.info("未找到对应的AGV指令类型任务号:" + acsTask.getTask_code() + ",task_type:" + acsTask.getTask_type());
continue;
}
} else {
instdto.setAgv_inst_type("4");
}
try {
instructionService.create(instdto);
} catch (Exception e) {

View File

@@ -10,7 +10,7 @@ spring:
driverClassName: net.sf.log4jdbc.sql.jdbcapi.DriverSpy
# url: jdbc:log4jdbc:mysql://${DB_HOST:192.168.81.252}:${DB_PORT:3306}/${DB_NAME:stand_acs}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true
# url: jdbc:log4jdbc:mysql://${DB_HOST:47.111.78.178}:${DB_PORT:3306}/${DB_NAME:lzhl_two_acs}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true
url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:lzhl_acs_97}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
url: jdbc:log4jdbc:mysql://${DB_HOST:127.0.0.1}:${DB_PORT:3306}/${DB_NAME:ynfj_acs}?serverTimezone=Asia/Shanghai&characterEncoding=utf8&useSSL=false&useOldAliasMetadataBehavior=true&allowPublicKeyRetrieval=true
username: ${DB_USER:root}
# password: ${DB_PWD:Root.123456}

View File

@@ -24,4 +24,12 @@ export function edit(data) {
})
}
export default { add, edit, del }
export function excelImport(data) {
return request({
url: 'api/storageCell/excelImport',
method: 'post',
data
})
}
export default { add, edit, del, excelImport }

View File

@@ -82,6 +82,7 @@ import agv_ndc_two from '@/views/acs/device/driver/agv/agv_ndc_two'
import xg_agv from '@/views/acs/device/driver/agv/xg_agv'
import xg_agv_car from '@/views/acs/device/driver/agv/xg_agv_car.vue'
import standard_manipulator from '@/views/acs/device/driver/one_manipulator/standard_manipulator.vue'
import standard_storage from '@/views/acs/device/driver/standard_storage'
export default {
name: 'DeviceConfig',
components: {
@@ -93,7 +94,8 @@ export default {
xg_agv,
belt_conveyor,
standard_manipulator,
xg_agv_car
xg_agv_car,
standard_storage
},
dicts: ['device_type'],
mixins: [crud],

View File

@@ -0,0 +1,315 @@
<template>
<!-- 标准版-货架-->
<div>
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix">
<span class="role-span">指令相关</span>
</div>
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="78px">
<el-row>
<el-col :span="8">
<el-form-item label="是否请求wms" label-width="150px">
<el-switch v-model="form.reqWms" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix">
<span class="role-span">设备协议</span>
</div>
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="78px">
<el-row>
<el-col :span="12">
<el-form-item label="排:" label-width="150px" prop="x">
<el-input v-model.number="form.x" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="巷道:" label-width="150px" prop="tunnel">
<el-input v-model.number="form.tunnel" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="最大列:" label-width="150px" prop="maxY">
<el-input v-model.number="form.maxY" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最小列:" label-width="150px" prop="minY">
<el-input v-model.number="form.minY" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="最大层:" label-width="150px" prop="maxZ">
<el-input v-model.number="form.maxZ" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="最小层:" label-width="150px" prop="minZ">
<el-input v-model.number="form.minZ" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</el-card>
<el-card class="box-card" shadow="never">
<div slot="header" class="clearfix">
<span class="role-span" />
<el-button
:loading="false"
icon="el-icon-check"
size="mini"
style="float: right; padding: 6px 9px"
type="primary"
@click="doSubmit"
>保存
</el-button>
</div>
</el-card>
</div>
</template>
<script>
import {
queryDriverConfig,
updateConfig,
testRead,
testwrite
} from '@/api/acs/device/driverConfig'
import { selectOpcList } from '@/api/acs/device/opc'
import { selectPlcList } from '@/api/acs/device/opcPlc'
import { selectListByOpcID } from '@/api/acs/device/opcPlc'
import crud from '@/mixins/crud'
import deviceCrud from '@/api/acs/device/device'
export default {
name: 'StandardStorage',
mixins: [crud],
props: {
parentForm: {
type: Object,
required: true
}
},
data() {
const checkMaxY = (rule, value, callback) => {
if (value < this.form.minY) {
callback(new Error('最大列应大于最小列!'))
} else {
callback()
}
}
const checkMinY = (rule, value, callback) => {
if (value > this.form.maxY) {
callback(new Error('最小列应小于最大列!'))
} else {
callback()
}
}
const checkMaxZ = (rule, value, callback) => {
if (value < this.form.minZ) {
callback(new Error('最大层应大于最小层!'))
} else {
callback()
}
}
const checkMinZ = (rule, value, callback) => {
if (value > this.form.maxZ) {
callback(new Error('最小层应小于最大层!'))
} else {
callback()
}
}
return {
device_code: '',
device_id: '',
plc_id: '',
plc_code: '',
opc_id: '',
opc_code: '',
configLoading: false,
dataOpcservers: [],
dataOpcPlcs: [],
deviceList: [],
data1: [],
data2: [],
form: {
x: 0,
tunnel: 0,
maxY: 0,
maxZ: 0,
minY: 0,
minZ: 0,
reqWms: true
},
rules: {
x: [
{ required: true, message: '排不能为空', trigger: 'blur' }
],
tunnel: [
{ required: true, type: 'number', min: 0, message: '请输入大于0的数字', trigger: 'blur' }
],
maxY: [
{ required: true, type: 'number', min: 0, message: '请输入大于0的数字', trigger: 'blur' },
{ validator: checkMaxY, trigger: 'blur' }
],
maxZ: [
{ required: true, type: 'number', min: 0, message: '请输入大于0的数字', trigger: 'blur' },
{ validator: checkMaxZ, trigger: 'blur' }
],
minY: [
{ required: true, type: 'number', min: 0, message: '请输入大于0的数字', trigger: 'blur' },
{ validator: checkMinY, trigger: 'blur' }
],
minZ: [
{ required: true, type: 'number', min: 0, message: '请输入大于0的数字', trigger: 'blur' },
{ validator: checkMinZ, trigger: 'blur' }
]
}
}
},
created() {
this.$nextTick(() => {
// 从父表单获取设备编码
this.device_id = this.$props.parentForm.device_id
this.device_code = this.$props.parentForm.device_code
queryDriverConfig(this.device_id, this.$props.parentForm.driver_code).then(data => {
// 给表单赋值,并且属性不能为空
if (data.form) {
const arr = Object.keys(data.form)
// 不为空
if (arr.length > 0) {
data.form.x = parseInt(data.form.x)
data.form.tunnel = parseInt(data.form.tunnel)
data.form.minY = parseInt(data.form.minY)
data.form.maxY = parseInt(data.form.maxY)
data.form.minZ = parseInt(data.form.minZ)
data.form.maxZ = parseInt(data.form.maxZ)
this.form = data.form
}
}
// 给表单赋值,并且属性不能为空
if (data.parentForm) {
const arr = Object.keys(data.parentForm)
// 不为空
if (arr.length > 0) {
this.opc_code = data.parentForm.opc_code
this.plc_code = data.parentForm.plc_code
}
}
this.data1 = data.rs
this.data2 = data.ws
this.sliceItem()
})
selectPlcList().then(data => {
this.dataOpcPlcs = data
this.plc_id = this.$props.parentForm.opc_plc_id
})
selectOpcList().then(data => {
this.dataOpcservers = data
this.opc_id = this.$props.parentForm.opc_server_id
})
deviceCrud.selectDeviceList().then(data => {
this.deviceList = data
})
})
},
methods: {
changeOpc(val) {
this.dataOpcservers.forEach(item => {
if (item.opc_id === val) {
this.opc_code = item.opc_code
}
})
selectListByOpcID(val).then(data => {
this.dataOpcPlcs = data
this.plc_id = ''
this.plc_code = ''
if (this.dataOpcPlcs && this.dataOpcPlcs.length > 0) {
this.plc_id = this.dataOpcPlcs[0].plc_id
this.plc_code = this.dataOpcPlcs[0].plc_code
}
this.sliceItem()
})
},
changePlc(val) {
this.dataOpcPlcs.forEach(item => {
if (item.plc_id === val) {
this.plc_code = item.plc_code
this.sliceItem()
return
}
})
},
test_read1() {
testRead(this.data1, this.opc_id).then(data => {
this.data1 = data
this.notify('操作成功!', 'success')
}).catch(err => {
console.log(err.response.data.message)
})
},
test_write1() {
testwrite(this.data2, this.opc_id).then(data => {
this.notify('操作成功!', 'success')
}).catch(err => {
console.log(err.response.data.message)
})
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.configLoading = true
// 根据驱动类型判断是否为路由设备
const parentForm = this.parentForm
parentForm.is_route = true
parentForm.plc_id = this.plc_id
parentForm.opc_id = this.opc_id
updateConfig(parentForm, this.form, this.data1, this.data2).then(res => {
this.notify('保存成功', 'success')
this.configLoading = false
}).catch(err => {
this.configLoading = false
console.log(err.response.data.message)
})
}
})
},
sliceItem() { // 拼接DB的Item值
this.data1.forEach(item => {
const str = item.code
// 是否包含.
if (str.search('.') !== -1) {
// 截取最后一位
item.code = this.opc_code + '.' + this.plc_code + '.' + this.device_code + '.' + str.slice(str.lastIndexOf('.') + 1)
} else {
item.code = this.opc_code + '.' + this.plc_code + '.' + this.device_code + '.' + item.code
}
})
this.data2.forEach(item => {
const str = item.code
// 是否包含.
if (str.search('.') !== -1) {
// 截取最后一位
item.code = this.opc_code + '.' + this.plc_code + '.' + this.device_code + '.' + str.slice(str.lastIndexOf('.') + 1)
} else {
item.code = this.opc_code + '.' + this.plc_code + '.' + this.device_code + '.' + item.code
}
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,116 @@
<template>
<el-dialog
title="导入Excel文件"
append-to-body
:visible.sync="dialogVisible"
destroy-on-close
width="400px"
:show-close="true"
@close="close"
@open="open"
>
<el-upload
ref="upload"
class="upload-demo"
action=""
drag
:on-exceed="is_one"
:limit="1"
:auto-upload="false"
:multiple="false"
:show-file-list="true"
:on-change="uploadByJsqd"
:file-list="fileList"
accept=".xlsx,.xls"
>
<i class="el-icon-upload" />
<div class="el-upload__text">
将文件拖到此处
<em>点击上传</em>
</div>
<div slot="tip" class="el-upload__tip">只能上传Excel文件且不超过10MB</div>
</el-upload>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="submit"> </el-button>
</span>
</el-dialog>
</template>
<script>
import crudStorageCell from '@/api/acs/device/storageCell'
import CRUD, { crud } from '@crud/crud'
export default {
name: 'UploadDialog',
mixins: [crud()],
components: {},
props: {
dialogShow: {
type: Boolean,
default: false
},
openParam: {
type: String
}
},
data() {
return {
dialogVisible: false,
fileList: [],
file1: ''
}
},
watch: {
dialogShow: {
handler(newValue, oldValue) {
this.dialogVisible = newValue
}
},
openParam: {
handler(newValue, oldValue) {
this.opendtlParam = newValue
}
}
},
methods: {
open() {
},
close() {
this.$emit('update:dialogShow', false)
},
is_one() {
this.crud.notify('只能上传一个excel文件', CRUD.NOTIFICATION_TYPE.WARNING)
},
// 文件校验方法
beforeAvatarUpload(file) {
// 不能导入大小超过2Mb的文件
if (file.size > 10 * 1024 * 1024) {
return false
}
return true
},
// 文件发生改变就会触发的事件
uploadByJsqd(file) {
this.file1 = file
},
submit() {
if (this.beforeAvatarUpload(this.file1)) {
this.fileList.name = this.file1.name
this.fileList.url = ''
var formdata = new FormData()
formdata.append('file', this.file1.raw)
// excelImport请求接口 formdata传递参数
crudStorageCell.excelImport(formdata).then((res) => {
this.crud.notify('导入成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
this.$emit('tableChanged3', '')
this.$emit('update:dialogShow', false)
})
} else {
this.crud.notify('文件过大请上传小于10MB的文件〜', CRUD.NOTIFICATION_TYPE.WARNING)
}
}
}
}
</script>

View File

@@ -40,7 +40,18 @@
class="filter-item"
/>
</el-form-item>
<rrOperation />
<rrOperation :permission="permission">
<el-button
slot="right"
class="filter-item"
type="warning"
icon="el-icon-upload2"
size="mini"
@click="uploadShow = true"
>
{{ $t('auto.common.import') }}
</el-button>
</rrOperation>
</el-form>
</div>
<!--如果想在工具栏加入更多按钮可以使用插槽方式 slot = 'left' or 'right'-->
@@ -101,6 +112,7 @@
<!--分页组件-->
<pagination />
</div>
<UploadDialog :dialog-show.sync="uploadShow" @tableChanged3="tableChanged3" />
</div>
</template>
@@ -112,11 +124,12 @@ import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
import rrOperation from '@crud/RR.operation'
import i18n from '@/i18n'
import UploadDialog from '@/views/acs/device/storageCell/UploadDialog'
const defaultForm = { storage_id: null, storage_code: null, x: null, y: null, z: null, address: null, remark: null, is_active: null, is_delete: null, create_by: null, create_time: null, update_by: null, update_time: null, parent_storage_code: null }
export default {
name: 'StorageCell',
components: { pagination, crudOperation, udOperation, rrOperation },
components: { pagination, crudOperation, udOperation, rrOperation, UploadDialog },
mixins: [presenter(), header(), form(defaultForm), crud()],
cruds() {
return CRUD({ title: i18n.t('storageCell.title'), url: 'api/storageCell', idField: 'storage_id', sort: 'storage_id,desc', crudMethod: { ...crudStorageCell }})
@@ -128,6 +141,7 @@ export default {
edit: ['admin', 'storageCell:edit'],
del: ['admin', 'storageCell:del']
},
uploadShow: false,
rules: {
storage_id: [
{ required: true, message: '货位标识不能为空', trigger: 'blur' }
@@ -166,6 +180,9 @@ export default {
// 钩子在获取表格数据之前执行false 则代表不获取数据
[CRUD.HOOK.beforeRefresh]() {
return true
},
tableChanged3() {
this.crud.toQuery()
}
}
}

View File

@@ -0,0 +1,235 @@
<template>
<div class="app-container">
<!-- 工具栏 -->
<div class="head-container">
<el-form
:inline="true"
class="demo-form-inline"
label-position="right"
label-width="80px"
label-suffix=":"
>
<el-form-item label="监听端口">
<el-input
v-model="query.search"
clearable
style="width: 300px"
size="mini"
placeholder="请输入监听端口"
class="filter-item"
/>
</el-form-item>
<!-- 新增滑块开关 -->
<el-form-item label="设备监听">
<el-switch
v-model="rfidStatus"
active-color="#13ce66"
inactive-color="#ccc"
@change="open"
/>
</el-form-item>
<rrOperation />
</el-form>
<crudOperation :permission="permission" />
<!-- 表格 -->
<el-table
ref="table"
v-loading="crud.loading"
:data="crud.data"
size="mini"
style="width: 100%;"
@selection-change="crud.selectionChangeHandler"
>
<el-table-column prop="device_code" label="设备编号" />
<el-table-column prop="ip" label="IP" />
<el-table-column prop="status" label="连接状态">
<template slot-scope="scope">
<span :style="{ color: scope.row.status === 1 ? '#13ce66' : '#ff4949' }">
{{ scope.row.status === 1 ? '已连接' : '未连接' }}
</span>
</template>
</el-table-column>
<el-table-column prop="start_time" label="开始连接时间" />
<el-table-column
prop="online_time"
label="在线时间"
:min-width="flexWidth('online_time', crud.data, '在线时间')"
/>
<el-table-column
prop="rfid"
label="当前rfid值"
:min-width="flexWidth('rfid', crud.data, '当前rfid值')"
/>
<!-- <el-table-column prop="is_used" label="是否启用 ">-->
<!-- <template slot-scope="scope">-->
<!-- <el-switch-->
<!-- v-model="scope.row.is_used"-->
<!-- active-color="#409EFF"-->
<!-- inactive-color="#F56C6C"-->
<!-- @change="changeEnabled(scope.row, scope.row.is_used)"-->
<!-- />-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
v-permission="['admin', 'mdPbMeasureunit:edit', 'mdPbMeasureunit:del']"
fixed="right"
label="操作"
width="150px"
align="center"
>
<template slot-scope="scope">
<udOperation :data="scope.row" :permission="permission" />
</template>
</el-table-column>
</el-table>
<el-input
v-model="logText"
type="textarea"
:rows="15"
placeholder="设备运行日志..."
readonly
style="width: 100%; margin-top: 5px;"
/>
<!-- 分页 -->
<pagination />
</div>
</div>
</template>
<script>
import crudRfid from './vehicle_rfid'
import CRUD, { presenter, header, form, crud } from '@crud/crud'
import crudOperation from '@crud/CRUD.operation'
import udOperation from '@crud/UD.operation'
import pagination from '@crud/Pagination'
const defaultForm = {
id: null,
ip: null,
port: null,
device_code: null,
is_used: true,
online_time: null,
create_id: null,
create_name: null,
create_time: null,
update_id: null,
update_name: null,
update_time: null,
status: null,
start_time: null
}
export default {
dicts: ['is_used'],
name: 'VehicleRfid',
components: { pagination, crudOperation, udOperation },
mixins: [presenter(), header(), form(defaultForm), crud()],
cruds() {
return CRUD({
title: '计量单位',
url: 'api/rfid',
optShow: {
add: true
},
idField: 'id',
sort: 'id,desc',
crudMethod: { ...crudRfid }
})
},
data() {
return {
intervalId: null,
permission: {},
rfidStatus: false, // 新增开关状态变量
logText: '', // 展示日志内容
logTextList: [], // 存储日志行数组最多10条
query: {
search: '8160' // 设置默认监听端口
}
}
},
mounted() {
// 读写器定时器
this.intervalId = setInterval(() => {
this.crud.toQuery()
this.updateLogFromResult()
}, 3000)
},
beforeDestroy() {
if (this.intervalId) {
clearInterval(this.intervalId)
}
},
methods: {
[CRUD.HOOK.beforeRefresh]() {
return true
},
// updateLogFromResult() {
// const logList = this.crud.data.map(item => item.log).filter(log => !!log)
// if (logList.length === 0) return
// const newLog = logList.join('\n')
// //每次都添加日志
// this.logTextList.unshift(newLog) // 新日志放最前
// if (this.logTextList.length > 15) {
// this.logTextList.pop() // 最多保留10条
// }
// this.logText = this.logTextList.join('\n\n') // 更新展示内容
// },
updateLogFromResult() {
const s = this.crud.data
const logList = this.crud.data.map(item => item.log).filter(log => !!log)
if (logList.length === 0) {
return
}
const newLog = logList.join('\n')
// 判断最新日志是否和旧的重复,避免重复添加
if (!this.logTextList.includes(newLog)) {
this.logTextList.unshift(newLog) // 新日志放最前
if (this.logTextList.length > 15) {
this.logTextList.pop() // 最多保留10条
}
this.logText = this.logTextList.join('\n\n') // 更新展示内容
}
},
changeEnabled(data, val) {
this.$confirm('此操作将改变' + data.device_code + '状态, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
crudRfid.edit(data).then(() => {
this.crud.notify('操作成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
}).catch(() => {
data.is_used = !val
})
}).catch(() => {
data.is_used = !val
})
},
open(val) {
debugger
const payload = {
port: this.query.search == null ? '8160' : this.query.search,
isOpen: val ? '1' : '0'
}
crudRfid.open(JSON.stringify(payload)).then(res => {
this.crud.toQuery()
this.crud.notify('操作成功', CRUD.NOTIFICATION_TYPE.SUCCESS)
}).catch(() => {
this.$message.error('操作失败')
this.rfidStatus = !val
})
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,49 @@
import request from '@/utils/request'
export function open(data) {
return request({
url: 'api/rfid/open',
method: 'post',
data
})
}
export function add(data) {
return request({
url: 'api/rfid/add',
method: 'post',
data
})
}
export function del(ids) {
return request({
url: 'api/rfid/delete',
method: 'post',
data: ids
})
}
export function edit(data) {
return request({
url: 'api/rfid/update',
method: 'post',
data
})
}
export function getUnit(params) {
return request({
url: 'api/rfid',
method: 'get',
params
})
}
export function getSelect() {
return request({
url: 'api/rfid/select',
method: 'get'
})
}
export default { add, edit, del, getUnit, getSelect, open }