From b5cd16b295a728f502f1bb8502e81047a560b164 Mon Sep 17 00:00:00 2001 From: "USER-20220102CG\\noblelift" <546428999@qq.com> Date: Tue, 31 Oct 2023 16:02:14 +0800 Subject: [PATCH 01/14] =?UTF-8?q?rev=20=E4=BF=A1=E5=8F=B7=E4=B8=8B?= =?UTF-8?q?=E5=8F=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../OvenGantryManipulatorDeviceDriver.java | 4 +- ...CoveyorControlWithScannerDeviceDriver.java | 38 +++++++++++++++++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/oven_manipulator/OvenGantryManipulatorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/oven_manipulator/OvenGantryManipulatorDeviceDriver.java index 745870ba0..c9a4b4fb0 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/oven_manipulator/OvenGantryManipulatorDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/oven_manipulator/OvenGantryManipulatorDeviceDriver.java @@ -383,7 +383,7 @@ public class OvenGantryManipulatorDeviceDriver extends AbstractOpcDeviceDriver i //存在行架->暂存的AGV任务 需要过滤 // 6 行架任务 8烘箱任务 - if(!StrUtil.equals(taskDto.getTask_type(),"6") || StrUtil.equals(taskDto.getTask_type(),"8")){ + if(!StrUtil.equals(taskDto.getTask_type(),"6") && !StrUtil.equals(taskDto.getTask_type(),"8")){ taskDto = null; continue; } @@ -478,7 +478,7 @@ public class OvenGantryManipulatorDeviceDriver extends AbstractOpcDeviceDriver i taskDtoList = this.sortTask(taskDtoList); task = taskDtoList.get(j); // 6 行架任务 8烘箱任务 - if(!StrUtil.equals(task.getTask_type(),"6") || StrUtil.equals(task.getTask_type(),"8")){ + if(!StrUtil.equals(task.getTask_type(),"6") && !StrUtil.equals(task.getTask_type(),"8")){ task = null; continue; } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java index 4b31e481c..591b2e6b0 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java @@ -936,8 +936,16 @@ public class StandardCoveyorControlWithScannerDeviceDriver extends AbstractOpcDe + "." + param; Map itemMap = new HashMap(); itemMap.put(to_param, Integer.parseInt(value)); - this.control(itemMap); - + try { + this.checkcontrol(itemMap); + } catch (Exception e) { + e.printStackTrace(); + try{ + this.checkcontrol(itemMap); + } catch (Exception e1){ + e1.printStackTrace(); + } + } } // 申请贴标 @@ -1017,6 +1025,21 @@ public class StandardCoveyorControlWithScannerDeviceDriver extends AbstractOpcDe } else { message = "申请贴标失败," + applyLabelingAndBindingResponse.getMessage(); logServer.deviceExecuteLog(this.device_code, "", "", "申请贴标,返回参数:" + JSON.toJSONString(applyLabelingAndBindingResponse)); + List list = new ArrayList(); + Map map = new HashMap(); + map.put("code", "to_target"); + map.put("value", "1011"); + list.add(map); + Map map2 = new HashMap(); + map2.put("code", "to_command"); + map2.put("value", "1"); + list.add(map2); + Map map3 = new HashMap(); + map3.put("code", "to_task"); + map3.put("value", "0"); + list.add(map3); + this.writing(list); + requireSucess = true; } } @@ -1034,7 +1057,16 @@ public class StandardCoveyorControlWithScannerDeviceDriver extends AbstractOpcDe } } logServer.deviceExecuteLog(device_code, "", "", "下发电气信号:" + itemMap); - this.control(itemMap); + try { + this.checkcontrol(itemMap); + } catch (Exception e) { + e.printStackTrace(); + try{ + this.checkcontrol(itemMap); + } catch (Exception e1){ + e1.printStackTrace(); + } + } } @Override From 772a6e8efa4f78b5963b9e5a90f9d63459a0ba64 Mon Sep 17 00:00:00 2001 From: "USER-20220102CG\\noblelift" <546428999@qq.com> Date: Thu, 2 Nov 2023 11:24:39 +0800 Subject: [PATCH 02/14] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9E=E7=BA=B8?= =?UTF-8?q?=E7=AE=A1=E5=BA=93=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/device_driver/DriverTypeEnum.java | 6 +- .../paper_tube_device2/ItemProtocol.java | 226 +++++++++++++++++ .../PaperTubeConveyor2Defination.java | 61 +++++ .../PaperTubeConveyor2DeviceDriver.java | 232 ++++++++++++++++++ ...CoveyorControlWithScannerDeviceDriver.java | 1 + .../wms/service/impl/WmsToAcsServiceImpl.java | 7 + 6 files changed, 532 insertions(+), 1 deletion(-) create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2Defination.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java index 998f6f584..d0db77776 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java @@ -55,7 +55,11 @@ public enum DriverTypeEnum { PAPER_TUBE_DEVICE(22, "paper_tube_conveyor", "纸管库设备", "conveyor"), - DEVICE_STATUS(23,"device_status","立库设备状态","conveyor"); + DEVICE_STATUS(23,"device_status","立库设备状态","conveyor"), + + PACKAGE_MANIPULATOR(24,"package_manipulator","内包间行架机械手","station"), + + PAPER_TUBE_DEVICE2(22, "paper_tube_conveyor2", "纸管库设备2", "conveyor"); //驱动索引 private int index; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java new file mode 100644 index 000000000..9e975fe10 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java @@ -0,0 +1,226 @@ +package org.nl.acs.device_driver.basedriver.paper_tube_device2; + +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Data +public class ItemProtocol { + + //心跳 + public static String item_heartbeat = "heartbeat"; + //工作模式 + public static String item_mode = "mode"; + //光电信号 + public static String item_move = "move"; + //托盘方向 + public static String item_carrier_direction = "carrier_direction"; + //报警 + public static String item_error = "error"; + //任务号 + public static String item_task = "task"; + //出库顺序数组 + public static String item_out_seq_arr = "out_seq_arr"; + //出库数量数组 + public static String item_out_qty_arr = "out_qty_arr"; + //物料1 + public static String item_material1 = "material1"; + //物料2 + public static String item_material2 = "material2"; + //物料3 + public static String item_material3 = "material3"; + //物料4 + public static String item_material4 = "material4"; + //物料5 + public static String item_material5 = "material5"; + //物料6 + public static String item_material6 = "material6"; + //物料7 + public static String item_material7 = "material7"; + //物料8 + public static String item_material8 = "material8"; + //物料9 + public static String item_material9 = "material9"; + //物料10 + public static String item_material10 = "material10"; + //物料11 + public static String item_material11 = "material11"; + //物料12 + public static String item_material12 = "material12"; + //数量1 + public static String item_qty1 = "qty1"; + //数量2 + public static String item_qty2 = "qty2"; + //数量3 + public static String item_qty3 = "qty3"; + //数量4 + public static String item_qty4 = "qty4"; + //数量5 + public static String item_qty5 = "qty5"; + //数量6 + public static String item_qty6 = "qty6"; + //数量7 + public static String item_qty7 = "qty7"; + //数量8 + public static String item_qty8 = "qty8"; + //数量9 + public static String item_qty9 = "qty9"; + //数量10 + public static String item_qty10 = "qty10"; + //数量11 + public static String item_qty11 = "qty11"; + //数量12 + public static String item_qty12 = "qty12"; + + + //下发命令 + public static String item_to_command = "to_command"; + //下发目标站 + public static String item_to_target = "to_target"; + + public static String item_to_task = "to_task"; + public static String item_to_material1 = "to_material1"; + public static String item_to_out_qty1 = "to_out_qty1"; + public static String item_to_seq1 = "to_seq1"; + public static String item_to_position1 = "to_position1"; + + public static String item_to_material2 = "to_material2"; + public static String item_to_out_qty2 = "to_out_qty2"; + public static String item_to_seq2 = "to_seq2"; + public static String item_to_position2 = "to_position2"; + + public static String item_to_material3 = "to_material3"; + public static String item_to_out_qty3 = "to_out_qty3"; + public static String item_to_seq3 = "to_seq3"; + public static String item_to_position3 = "to_position3"; + + + private PaperTubeConveyor2DeviceDriver driver; + + public ItemProtocol(PaperTubeConveyor2DeviceDriver driver) { + this.driver = driver; + } + + public int getHeartbeat() { + return this.getOpcIntegerValue(item_heartbeat); + } + + public int getMode() { + return this.getOpcIntegerValue(item_mode); + } + + public int getError() { + return this.getOpcIntegerValue(item_error); + } + + public String getMaterial1() { + return this.getOpcStringValue(item_material1); + } + + public String getMaterial2() { + return this.getOpcStringValue(item_material2); + } + + public String getMaterial3() { + return this.getOpcStringValue(item_material3); + } + + public String getMaterial4() { + return this.getOpcStringValue(item_material4); + } + + public String getMaterial5() { + return this.getOpcStringValue(item_material5); + } + + public String getMaterial6() { + return this.getOpcStringValue(item_material6); + } + + public String getMaterial7() { + return this.getOpcStringValue(item_material7); + } + + public String getMaterial8() { + return this.getOpcStringValue(item_material8); + } + + public String getMaterial9() { + return this.getOpcStringValue(item_material9); + } + + public String getMaterial10() { + return this.getOpcStringValue(item_material10); + } + + public String getMaterial11() { + return this.getOpcStringValue(item_material11); + } + + public String getMaterial12() { + return this.getOpcStringValue(item_material12); + } + + + public int getTotarget() { + return this.getOpcIntegerValue(item_to_target); + } + + public int getTo_command() { + return this.getOpcIntegerValue(item_to_command); + } + + Boolean isonline; + + public int getOpcIntegerValue(String protocol) { + Integer value = this.driver.getIntegeregerValue(protocol); + if (value == null) { + setIsonline(false); + } else { + setIsonline(true); + return value; + } + return 0; + + } + + + public String getOpcStringValue(String protocol) { + String value = this.driver.getStringValue(protocol); + if (StrUtil.isBlank(value)) { + + } else { + return value; + } + return "0"; + } + + public static List getReadableItemDtos() { + ArrayList list = new ArrayList(); + list.add(new ItemDto(item_heartbeat, "心跳", "DB101.W0")); + list.add(new ItemDto(item_mode, "模式", "DB101.W2")); + + list.add(new ItemDto(item_error, "error", "DB101.W58")); + return list; + } + + public static List getWriteableItemDtos() { + ArrayList list = new ArrayList(); + list.add(new ItemDto(item_to_target , "下发仓位号", "DB102.W2")); + list.add(new ItemDto(item_to_command, "下发命令", "DB102.W4")); + + return list; + } + + @Override + public String toString() { + return ""; + } + +} + diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2Defination.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2Defination.java new file mode 100644 index 000000000..5ae32d885 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2Defination.java @@ -0,0 +1,61 @@ +package org.nl.acs.device_driver.basedriver.paper_tube_device2; + +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; +import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.defination.OpcDeviceDriverDefination; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceType; +import org.springframework.stereotype.Service; + +import java.util.LinkedList; +import java.util.List; + +/** + * 油漆线 + */ +@Service +public class PaperTubeConveyor2Defination implements OpcDeviceDriverDefination { + @Override + public String getDriverCode() { + return "paper_tube_conveyor2"; + } + + @Override + public String getDriverName() { + return "纸管库2"; + } + + @Override + public String getDriverDescription() { + return "纸管库2"; + } + + @Override + public DeviceDriver getDriverInstance(Device device) { + return (new PaperTubeConveyor2DeviceDriver()).setDevice(device).setDriverDefination(this); + + } + + @Override + public Class getDeviceDriverType() { + return PaperTubeConveyor2DeviceDriver.class; + } + + @Override + public List getFitDeviceTypes() { + List types = new LinkedList(); + types.add(DeviceType.conveyor); + return types; + } + + @Override + public List getReadableItemDtos() { + return ItemProtocol.getReadableItemDtos(); + } + + @Override + public List getWriteableItemDtos() { + return ItemProtocol.getWriteableItemDtos(); + } + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java new file mode 100644 index 000000000..276a66c8f --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java @@ -0,0 +1,232 @@ +package org.nl.acs.device_driver.basedriver.paper_tube_device2; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.agv.server.AgvService; +import org.nl.acs.device.service.DeviceService; +import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.RouteableDeviceDriver; +import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; +import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; +import org.nl.acs.ext.wms.service.AcsToWmsService; +import org.nl.acs.ext.wms.service.impl.AcsToWmsServiceImpl; +import org.nl.acs.history.ErrorUtil; +import org.nl.acs.instruction.service.InstructionService; +import org.nl.acs.log.service.DeviceExecuteLogService; +import org.nl.acs.monitor.DeviceStageMonitor; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceAppService; +import org.nl.acs.route.service.RouteLineService; +import org.nl.acs.task.service.TaskService; +import org.nl.modules.system.service.ParamService; +import org.nl.modules.wql.util.SpringContextHolder; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 纸管库 + */ +@Slf4j +@Data +@RequiredArgsConstructor +public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor { + protected ItemProtocol itemProtocol = new ItemProtocol(this); + @Autowired + DeviceAppService deviceAppservice = SpringContextHolder.getBean(DeviceAppService.class); + @Autowired + InstructionService instructionService = SpringContextHolder.getBean(InstructionService.class); + @Autowired + DeviceService deviceservice = SpringContextHolder.getBean(DeviceService.class); + @Autowired + TaskService taskserver = SpringContextHolder.getBean(TaskService.class); + @Autowired + RouteLineService routeLineService = SpringContextHolder.getBean(RouteLineService.class); + @Autowired + AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsServiceImpl.class); + @Autowired + ParamService paramService = SpringContextHolder.getBean(ParamService.class); + @Autowired + DeviceExecuteLogService logServer = SpringContextHolder.getBean(DeviceExecuteLogService.class); + @Autowired + AgvService agvService = SpringContextHolder.getBean(AgvService.class); + + private Date instruction_require_time = new Date(); + private Date instruction_finished_time = new Date(); + private Date instruction_apply_time = new Date(); + private int instruction_require_time_out = 3000; + + int heartbeat = 0; + int mode = 0; + int inventory_qty =0; + int out_finish =0; + int error =0; + int to_command =0; + int to_target =0; + String material = null; + + Boolean isonline = true; + + Boolean iserror = false; + + //1-执行任务;2-取货完成;3-放货完成; + int flag; + + int last_mode = 0; + int last_inventory_qty =0; + int last_out_finish =0; + int last_error = 0; + String last_material = null; + + String device_code; + + @Override + public Device getDevice() { + return this.device; + } + + //请求成功标记 + Boolean requireSucess = false; + + @Override + public void execute() { + String message = null; + + device_code = this.getDeviceCode(); + heartbeat = this.itemProtocol.getHeartbeat(); + mode = this.itemProtocol.getMode(); + error = this.itemProtocol.getError(); + to_command = this.itemProtocol.getTo_command(); + to_target = this.itemProtocol.getTotarget(); + + if (mode != last_mode) { + this.setRequireSucess(false); + if (mode == 0) { + this.setIsonline(false); + message = "未联机"; + } else { + this.setIsonline(true); + } + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode); + } + if (inventory_qty != last_inventory_qty) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号inventory_qty:" + last_inventory_qty + "->" + inventory_qty); + } + if (out_finish != last_out_finish) { + if(out_finish == 1){ + this.writing(0); + this.writing("to_target","0"); + this.writing("to_out_qty","0"); + + } + logServer.deviceExecuteLog(this.device_code, "", "", "信号out_finish:" + last_out_finish + "->" + out_finish); + } + if (!StrUtil.equals(material,last_material)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material:" + last_material + "->" + material); + } + if (error != last_error) { + if(error > 0){ + this.setIserror(true); + } else { + if(error > 0){ + this.setIserror(false); + } + } + logServer.deviceExecuteLog(this.device_code, "", "", "信号out_finish:" + last_out_finish + "->" + out_finish); + } + + + last_mode = mode; + last_inventory_qty = inventory_qty; + last_out_finish = out_finish; + last_error = error; + last_material = material; + } + + + 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.basedriver.standard_conveyor_control_with_scanner.ItemProtocol.item_to_command; + + Map itemMap = new HashMap(); + this.control(itemMap); + } + + + public void writing(List list) { + + Map itemMap = new HashMap(); + for (int i = 0; i < list.size(); i++) { + Object ob = list.get(i); + JSONObject json = (JSONObject) JSONObject.toJSON(ob); + if (!StrUtil.isEmpty(json.getString("value"))) { + String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + + "." + json.getString("code"); + itemMap.put(to_param, json.getString("value")); + } + } + logServer.deviceExecuteLog(device_code, "", "", "下发电气信号:" + itemMap); + try { + this.checkcontrol(itemMap); + } catch (Exception e) { + e.printStackTrace(); + try{ + this.checkcontrol(itemMap); + } catch (Exception e1){ + e1.printStackTrace(); + } + } + + } + public void writing(String key, String param) { + + String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + + "." + param; + //String opcservcerid = this.getDevice().getOpc_server_id(); +//Server server = ReadUtil.getServer(opcservcerid); + Map itemMap = new HashMap(); + + itemMap.put(to_param, Integer.parseInt(param)); +// itemMap.put(to_param, Integer.parseInt(value)); + this.control(itemMap); + logServer.deviceExecuteLog(device_code, "", "", "下发电气信号设备号:" + device_code + ",下发电气:" + to_param + ",下发电气值:" + param); + } + + @Override + public JSONObject getDeviceStatusName() { + JSONObject jo = new JSONObject(); + String mode = ""; + + if (this.getMode() == 0) { + mode = "未联机"; + } else if (this.getMode() == 1) { + mode = "单机"; + } else if (this.getMode() == 2) { + mode = "联机"; + } else if (this.getMode() == 3) { + mode = "入库中"; + } else if (this.getMode() == 4) { + mode = "出库中"; + } + jo.put("device_name", this.getDevice().getDevice_name()); + jo.put("mode", mode); + jo.put("error", ErrorUtil.getDictDetail("ssx_error_type", String.valueOf(this.getError()))); + jo.put("inventory_qty", inventory_qty); + jo.put("out_finish", out_finish); + jo.put("material", material); + jo.put("isOnline", this.getIsonline()); + + return jo; + } + + @Override + public void setDeviceStatus(JSONObject data) { + + } +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java index 591b2e6b0..23a9448d5 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/standard_conveyor_control_with_scanner/StandardCoveyorControlWithScannerDeviceDriver.java @@ -393,6 +393,7 @@ public class StandardCoveyorControlWithScannerDeviceDriver extends AbstractOpcDe last_error = error; last_move = move; last_task = task; + last_height = height; last_plcbarcode_length = plcbarcode_length; last_plcbarcode = plcbarcode; last_weight = weight; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java index bfedc6cb0..4ac9b6396 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java @@ -1255,6 +1255,13 @@ public class WmsToAcsServiceImpl implements WmsToAcsService { e.printStackTrace(); } + } else if(StrUtil.equals(type, "3")){ + List list = new ArrayList(); + Map map = new HashMap(); + map.put("code", "to_command"); + map.put("value", 3); + list.add(map); + paperTubeConveyorDeviceDriver.writing(list); } } From 84d12e41ddbd50211a7663ea983ab5c5eb91bfc7 Mon Sep 17 00:00:00 2001 From: "USER-20220102CG\\noblelift" <546428999@qq.com> Date: Fri, 3 Nov 2023 13:50:17 +0800 Subject: [PATCH 03/14] =?UTF-8?q?add=20=E6=96=B0=E5=A2=9Elms=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/ApplyManipulatorActionRequest.java | 28 +++++++++++ .../data/ApplyManipulatorActionResponse.java | 48 +++++++++++++++++++ .../ext/wms/data/ApplyPaperActionRequest.java | 42 ++++++++++++++++ .../wms/data/ApplyPaperActionResponse.java | 14 ++++++ 4 files changed, 132 insertions(+) create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionRequest.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionResponse.java diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java new file mode 100644 index 000000000..9ee34077f --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java @@ -0,0 +1,28 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +@Data +public class ApplyManipulatorActionRequest extends BaseRequest { + private String vehicle_code; + private String device_code; + /** + * 2-尺寸交互反馈,反馈任务类型 + * 3-反馈新放货点 + * 4-反馈新取货点 + * 5-反馈二次放货点 + */ + private String type; + + /** + * 任务号 + */ + private String task_code; + + /** + * 气胀轴尺寸 3/6寸 + */ + private String size; + + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java new file mode 100644 index 000000000..be4283be7 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java @@ -0,0 +1,48 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class ApplyManipulatorActionResponse extends BaseResponse { + + private Map data = new HashMap(); + + /** + * 放货点 + */ + private String put_device_code; + + /** + * 取货点 + */ + private String get_device_code; + + /** + * 二次放货点 + */ + private String put_device_code2; + + /** + * 下发的指令类型 + */ + private String detail_type; + + /** + * 气胀轴代数 + */ + private String version; + + /** + * 套管数量 + */ + private String bushing_num; + + /** + * 是否套管 + */ + private String is_bushing; + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionRequest.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionRequest.java new file mode 100644 index 000000000..c289be887 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionRequest.java @@ -0,0 +1,42 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +@Data +public class ApplyPaperActionRequest extends BaseRequest { + + private String device_code; + + /** + * 1 纸管库出库申请 + * 2 套管请求 + */ + private String type; + + /** + * 任务号:输送任务号 + */ + private String task_code; + + + /** + * 出库物料1 + */ + private String material1; + + /** + * 出库物料2 + */ + private String material2; + + /** + * 出库物料数量1 + */ + private String qty1; + + /** + * 出库物料数量2 + */ + private String qty2; + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionResponse.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionResponse.java new file mode 100644 index 000000000..71cd02ae2 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyPaperActionResponse.java @@ -0,0 +1,14 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class ApplyPaperActionResponse extends BaseResponse { + + private Map data = new HashMap(); + + +} From 82c46653e651cc63242a981e0b060f1c1408501c Mon Sep 17 00:00:00 2001 From: "USER-20220102CG\\noblelift" <546428999@qq.com> Date: Fri, 3 Nov 2023 14:32:40 +0800 Subject: [PATCH 04/14] =?UTF-8?q?rev=20=E6=96=B0=E5=A2=9E=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/nl/acs/task/service/dto/TaskDto.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java index 7c5875db1..1353df4f9 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java @@ -307,6 +307,26 @@ public class TaskDto implements Serializable { */ private String next_height = "0"; + /** + * 行架任务类型 + */ + private String truss_type; + + + /** + * 气胀轴代数 + */ + private String version; + + /** + * 是否套管 + */ + private String is_bushing; + + //array device_code\material_code\qty + private String paper_array; + + @Override public String toString(){ From 2e634be0ce432e92d89f803aae716e17cc78c6d1 Mon Sep 17 00:00:00 2001 From: yanps Date: Tue, 7 Nov 2023 10:47:16 +0800 Subject: [PATCH 05/14] =?UTF-8?q?=E7=BA=B8=E7=AE=A1=E5=BA=93=E5=92=8C?= =?UTF-8?q?=E5=A5=97=E7=AE=A1=E5=B7=A5=E4=BD=8D=E9=A9=B1=E5=8A=A8=E7=BC=96?= =?UTF-8?q?=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- acs/nladmin-system/pom.xml | 10 +- .../device/device_driver/DriverTypeEnum.java | 4 +- .../paper_tube_device/ItemProtocol.java | 1 + .../PaperTubeConveyorDeviceDriver.java | 4 +- .../paper_tube_device2/ItemProtocol.java | 105 +++- .../PaperTubeConveyor2DeviceDriver.java | 508 ++++++++++++++++-- .../device_driver/driver/OpcDeviceDriver.java | 5 + .../acs/ext/wms/service/AcsToWmsService.java | 7 + .../wms/service/impl/AcsToWmsServiceImpl.java | 36 +- .../task/service/impl/TaskServiceImpl.java | 5 + .../main/resources/config/application-dev.yml | 2 +- .../src/views/acs/device/config.vue | 6 +- 12 files changed, 620 insertions(+), 73 deletions(-) diff --git a/acs/nladmin-system/pom.xml b/acs/nladmin-system/pom.xml index aa9a18954..32af48f4c 100644 --- a/acs/nladmin-system/pom.xml +++ b/acs/nladmin-system/pom.xml @@ -40,11 +40,11 @@ jansi 1.9 - + org.apache.commons @@ -90,6 +90,12 @@ org.openscada.utgard org.openscada.opc.lib 1.5.0 + + + org.bouncycastle + bcprov-jdk15on + + com.squareup.okhttp3 diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java index d0db77776..14685d63c 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java @@ -59,7 +59,9 @@ public enum DriverTypeEnum { PACKAGE_MANIPULATOR(24,"package_manipulator","内包间行架机械手","station"), - PAPER_TUBE_DEVICE2(22, "paper_tube_conveyor2", "纸管库设备2", "conveyor"); + PAPER_TUBE_DEVICE2(25, "paper_tube_conveyor2", "纸管库设备2", "conveyor"), + + CASING_STATION(26, "casing_station", "套管工位", "conveyor"); //驱动索引 private int index; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/ItemProtocol.java index fdabd5ac7..dd690e4e8 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/ItemProtocol.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/ItemProtocol.java @@ -4,6 +4,7 @@ import cn.hutool.core.util.StrUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.nl.acs.device.device_driver.standard_inspect.ItemDto; +import org.nl.acs.device_driver.basedriver.paper_tube_device2.PaperTubeConveyor2DeviceDriver; import java.util.ArrayList; import java.util.List; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/PaperTubeConveyorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/PaperTubeConveyorDeviceDriver.java index 07e25a1dc..e0b5f3136 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/PaperTubeConveyorDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device/PaperTubeConveyorDeviceDriver.java @@ -123,7 +123,7 @@ public class PaperTubeConveyorDeviceDriver extends AbstractOpcDeviceDriver imple } if (out_finish != last_out_finish) { if(out_finish == 1){ - this.writing(0); + //this.writing(0); this.writing("to_target","0"); this.writing("to_out_qty","0"); @@ -197,7 +197,7 @@ public class PaperTubeConveyorDeviceDriver extends AbstractOpcDeviceDriver imple itemMap.put(to_param, Integer.parseInt(param)); // itemMap.put(to_param, Integer.parseInt(value)); - this.control(itemMap); + //this.control(itemMap); logServer.deviceExecuteLog(device_code, "", "", "下发电气信号设备号:" + device_code + ",下发电气:" + to_param + ",下发电气值:" + param); } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java index 9e975fe10..8a14a2ad5 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java @@ -1,8 +1,12 @@ package org.nl.acs.device_driver.basedriver.paper_tube_device2; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.apache.poi.ss.formula.functions.T; import org.nl.acs.device.device_driver.standard_inspect.ItemDto; import java.util.ArrayList; @@ -82,7 +86,7 @@ public class ItemProtocol { public static String item_to_command = "to_command"; //下发目标站 public static String item_to_target = "to_target"; - + //下发任务号 public static String item_to_task = "to_task"; public static String item_to_material1 = "to_material1"; public static String item_to_out_qty1 = "to_out_qty1"; @@ -114,10 +118,40 @@ public class ItemProtocol { return this.getOpcIntegerValue(item_mode); } + public int getMove() { + return this.getOpcIntegerValue(item_move); + } + + public int getCarrier_direction() { + return this.getOpcIntegerValue(item_carrier_direction); + } + public int getError() { return this.getOpcIntegerValue(item_error); } + public int getTask() { + return this.getOpcIntegerValue(item_task); + } + + public int getTo_task() { + return this.getOpcIntegerValue(item_to_task); + } + + public String getItem_out_seq_arr() { + return this.getOpcStringValue(item_out_seq_arr); + } + + public List getItem_out_seq_arr1() { + return this.getOpcArrayValue1(item_out_seq_arr); + } + + public int[] getItem_out_qty_arr() { + return this.getOpcArrayValue(item_out_qty_arr); + } + + + public String getMaterial1() { return this.getOpcStringValue(item_material1); } @@ -200,12 +234,61 @@ public class ItemProtocol { return "0"; } + public int[] getOpcArrayValue(String protocol) { + int[] arrayValue = this.driver.getIntegeregerArrayValue(protocol); + if (ObjectUtil.isNull(arrayValue)) { + + } else { + return arrayValue; + } + return new int[3]; + } + + public List getOpcArrayValue1(String protocol) { + List arrayValue = this.driver.getArrayValue(protocol); + if (ObjectUtil.isNull(arrayValue)) { + + } else { + return arrayValue; + } + return new ArrayList(); + } + + public static List getReadableItemDtos() { ArrayList list = new ArrayList(); list.add(new ItemDto(item_heartbeat, "心跳", "DB101.W0")); - list.add(new ItemDto(item_mode, "模式", "DB101.W2")); - - list.add(new ItemDto(item_error, "error", "DB101.W58")); + list.add(new ItemDto(item_mode, "工作模式", "DB101.W2")); + list.add(new ItemDto(item_move, "光电信号", "DB101.W3")); + list.add(new ItemDto(item_carrier_direction, "托盘方向", "DB101.W4")); + list.add(new ItemDto(item_error, "报警", "DB101.W58")); + list.add(new ItemDto(item_task, "任务号", "DB101.W68")); + list.add(new ItemDto(item_out_seq_arr, "出库顺序数组", "DB101.W5")); + list.add(new ItemDto(item_out_qty_arr, "出库数量数组", "DB101.W6")); + list.add(new ItemDto(item_material1, "物料1", "DB101.W7")); + list.add(new ItemDto(item_qty1, "数量1", "DB101.W19")); + list.add(new ItemDto(item_material2, "物料2", "DB101.W8")); + list.add(new ItemDto(item_qty2, "数量2", "DB101.W20")); + list.add(new ItemDto(item_material3, "物料3", "DB101.W9")); + list.add(new ItemDto(item_qty3, "数量3", "DB101.W21")); + list.add(new ItemDto(item_material4, "物料4", "DB101.W10")); + list.add(new ItemDto(item_qty4, "数量4", "DB101.W22")); + list.add(new ItemDto(item_material5, "物料5", "DB101.W11")); + list.add(new ItemDto(item_qty5, "数量5", "DB101.W23")); + list.add(new ItemDto(item_material6, "物料6", "DB101.W12")); + list.add(new ItemDto(item_qty6, "数量6", "DB101.W24")); + list.add(new ItemDto(item_material7, "物料7", "DB101.W13")); + list.add(new ItemDto(item_qty7, "数量7", "DB101.W25")); + list.add(new ItemDto(item_material8, "物料8", "DB101.W14")); + list.add(new ItemDto(item_qty8, "数量8", "DB101.W26")); + list.add(new ItemDto(item_material9, "物料9", "DB101.W15")); + list.add(new ItemDto(item_qty9, "数量9", "DB101.W27")); + list.add(new ItemDto(item_material10, "物料10", "DB101.W16")); + list.add(new ItemDto(item_qty10, "数量10", "DB101.W28")); + list.add(new ItemDto(item_material11, "物料11", "DB101.W17")); + list.add(new ItemDto(item_qty11, "数量11", "DB101.W29")); + list.add(new ItemDto(item_material12, "物料12", "DB101.W18")); + list.add(new ItemDto(item_qty12, "数量12", "DB101.W30")); return list; } @@ -213,7 +296,19 @@ public class ItemProtocol { ArrayList list = new ArrayList(); 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.W1")); + list.add(new ItemDto(item_to_material1, "下发物料1", "DB102.W3")); + list.add(new ItemDto(item_to_out_qty1, "下发物料1数量", "DB102.W7")); + list.add(new ItemDto(item_to_seq1, "出库顺序1", "DB102.W10")); + list.add(new ItemDto(item_to_position1, "仓位1", "DB102.W13")); + list.add(new ItemDto(item_to_material2, "下发物料2", "DB102.W5")); + list.add(new ItemDto(item_to_out_qty2, "下发物料2数量", "DB102.W8")); + list.add(new ItemDto(item_to_seq2, "出库顺序2", "DB102.W11")); + list.add(new ItemDto(item_to_position2, "仓位2", "DB102.W14")); + list.add(new ItemDto(item_to_material3, "下发物料3", "DB102.W6")); + list.add(new ItemDto(item_to_out_qty3, "下发物料3数量", "DB102.W9")); + list.add(new ItemDto(item_to_seq3, "出库顺序3", "DB102.W12")); + list.add(new ItemDto(item_to_position3, "仓位3", "DB102.W15")); return list; } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java index 276a66c8f..8bee5865e 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java @@ -1,6 +1,12 @@ package org.nl.acs.device_driver.basedriver.paper_tube_device2; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSON; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONObject; import lombok.Data; import lombok.RequiredArgsConstructor; @@ -11,24 +17,29 @@ import org.nl.acs.device_driver.DeviceDriver; import org.nl.acs.device_driver.RouteableDeviceDriver; import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; +import org.nl.acs.ext.wms.data.ApplyPaperActionRequest; +import org.nl.acs.ext.wms.data.ApplyPaperActionResponse; import org.nl.acs.ext.wms.service.AcsToWmsService; import org.nl.acs.ext.wms.service.impl.AcsToWmsServiceImpl; import org.nl.acs.history.ErrorUtil; +import org.nl.acs.history.service.DeviceErrorLogService; +import org.nl.acs.history.service.dto.DeviceErrorLogDto; +import org.nl.acs.history.service.impl.DeviceErrorLogServiceImpl; import org.nl.acs.instruction.service.InstructionService; +import org.nl.acs.instruction.service.dto.Instruction; import org.nl.acs.log.service.DeviceExecuteLogService; import org.nl.acs.monitor.DeviceStageMonitor; import org.nl.acs.opc.Device; import org.nl.acs.opc.DeviceAppService; import org.nl.acs.route.service.RouteLineService; +import org.nl.acs.route.service.dto.RouteLineDto; import org.nl.acs.task.service.TaskService; +import org.nl.acs.task.service.dto.TaskDto; import org.nl.modules.system.service.ParamService; import org.nl.modules.wql.util.SpringContextHolder; import org.springframework.beans.factory.annotation.Autowired; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; /** * 纸管库 @@ -56,19 +67,57 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl DeviceExecuteLogService logServer = SpringContextHolder.getBean(DeviceExecuteLogService.class); @Autowired AgvService agvService = SpringContextHolder.getBean(AgvService.class); + @Autowired + DeviceErrorLogService deviceErrorLogService = SpringContextHolder.getBean(DeviceErrorLogServiceImpl.class); + private Date instruction_update_time = new Date(); + private Date require_apply_strangulation_time = new Date(); + private int instruction_update_time_out = 500; private Date instruction_require_time = new Date(); private Date instruction_finished_time = new Date(); private Date instruction_apply_time = new Date(); private int instruction_require_time_out = 3000; + //心跳 int heartbeat = 0; + int last_heartbeat = 0; + //工作模式 int mode = 0; - int inventory_qty =0; - int out_finish =0; - int error =0; - int to_command =0; - int to_target =0; + int last_mode = 0; + //光电信号 + int move = 0; + int last_move = 0; + //托盘方向 + int carrier_direction = 0; + int last_carrier_direction = 0; + //报警 + int error = 0; + int last_error = 0; + //任务号 + int task = 0; + int last_task = 0; + + int inventory_qty = 0; + int out_finish = 0; + //下发命令 + int to_command = 0; + int last_to_command = 0; + //下发目标站 + int to_target = 0; + int last_to_target = 0; + //下发任务号 + int to_task = 0; + int last_to_task = 0; + + String item_out_seq_arr = null; + List item_out_seq_arr1 = null; + String last_item_out_seq_arr = null; + int[] item_out_qty_arr = null; + int[] last_item_out_qty_arr = null; + + //当前指令 + Instruction inst = null; + String material = null; Boolean isonline = true; @@ -78,13 +127,16 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl //1-执行任务;2-取货完成;3-放货完成; int flag; - int last_mode = 0; - int last_inventory_qty =0; - int last_out_finish =0; - int last_error = 0; - String last_material = null; + int last_inventory_qty = 0; + int last_out_finish = 0; + + String last_material = null; + String message = null; String device_code; + String task_code = null; + String vehicle_code; + String inst_message; @Override public Device getDevice() { @@ -96,57 +148,125 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl @Override public void execute() { - String message = null; + try { + String message = null; + device_code = this.getDeviceCode(); + heartbeat = this.itemProtocol.getHeartbeat(); + mode = this.itemProtocol.getMode(); + move = this.itemProtocol.getMove(); + carrier_direction = this.itemProtocol.getCarrier_direction(); + 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(); + //item_out_seq_arr1 = this.itemProtocol.getItem_out_seq_arr1(); + item_out_seq_arr = this.itemProtocol.getItem_out_seq_arr(); + item_out_qty_arr = this.itemProtocol.getItem_out_qty_arr(); - device_code = this.getDeviceCode(); - heartbeat = this.itemProtocol.getHeartbeat(); - mode = this.itemProtocol.getMode(); - error = this.itemProtocol.getError(); - to_command = this.itemProtocol.getTo_command(); - to_target = this.itemProtocol.getTotarget(); - if (mode != last_mode) { - this.setRequireSucess(false); - if (mode == 0) { - this.setIsonline(false); - message = "未联机"; - } else { - this.setIsonline(true); + if (to_command != last_to_command) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_command:" + last_to_command + "->" + to_command); } - logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode); - } - if (inventory_qty != last_inventory_qty) { - logServer.deviceExecuteLog(this.device_code, "", "", "信号inventory_qty:" + last_inventory_qty + "->" + inventory_qty); - } - if (out_finish != last_out_finish) { - if(out_finish == 1){ - this.writing(0); - this.writing("to_target","0"); - this.writing("to_out_qty","0"); - + if (to_target != last_to_target) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_target:" + last_to_target + "->" + to_target); } - logServer.deviceExecuteLog(this.device_code, "", "", "信号out_finish:" + last_out_finish + "->" + out_finish); - } - if (!StrUtil.equals(material,last_material)) { - logServer.deviceExecuteLog(this.device_code, "", "", "信号material:" + last_material + "->" + material); - } - if (error != last_error) { - if(error > 0){ - this.setIserror(true); - } else { - if(error > 0){ - this.setIserror(false); + if (to_task != last_to_task) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_task:" + last_to_task + "->" + to_task); + } + + if (mode != last_mode) { + JSONObject param = new JSONObject(); + param.put("device_code", this.device_code); + param.put("mode", Math.min(mode, 3)); + param.put("device_name", this.getDevice().getDevice_name()); + param.put("device_type", "1"); + param.put("product_area", paramService.findByCode("productArea").getValue()); + acsToWmsService.sendDeviceStatus(param); + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode + "复位请求标记:" + requireSucess); + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode); + } + if (move != last_move) { + logServer.deviceItemValue(this.device_code, "move", String.valueOf(move)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号move:" + last_move + "->" + move); + } + if (carrier_direction != last_carrier_direction) { + logServer.deviceItemValue(this.device_code, "carrier_direction", String.valueOf(carrier_direction)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号carrier_direction:" + last_carrier_direction + "->" + carrier_direction); + } + if (error != last_error) { + if (error != 0) { + DeviceErrorLogDto dto = new DeviceErrorLogDto(); + dto.setDevice_code(device_code); + dto.setError_code(String.valueOf(error)); + String errorInfo = ErrorUtil.getDictDetail("ssx_error_type", String.valueOf(error)); + dto.setError_info(errorInfo); + deviceErrorLogService.create(dto); } + logServer.deviceItemValue(this.device_code, "error", String.valueOf(error)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号error:" + last_error + "->" + error); } - logServer.deviceExecuteLog(this.device_code, "", "", "信号out_finish:" + last_out_finish + "->" + out_finish); + if (task != last_task) { + logServer.deviceItemValue(this.device_code, "task", String.valueOf(task)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号task:" + last_task + "->" + task); + } + + if (move != 0 && task > 0) { + update_instruction_status(); + } + + } catch (Exception var17) { + var17.printStackTrace(); + logServer.deviceExecuteLog(this.device_code, "", "", "读取信号值时出现异常:" + var17.getMessage() + ",this.itemProtocol is null:" + ObjectUtil.isEmpty(this.itemProtocol)); } + if (mode == 0) { + this.setIsonline(false); + message = "未联机"; + } else if (error != 0) { + this.setIserror(true); + message = "有报警"; + } else { + this.setIsonline(true); + this.setIserror(false); + message = ""; + Instruction instruction = null; + List toInstructions; + + //纸管库申请任务 + switch (mode) { + case 1: + log.debug("弃用(留作兼容)"); + break; + case 2: + //申请任务 + if (move > 0 && !requireSucess) { + instruction_require(); + } + break; + case 3: + log.info("运行中"); + break; + case 4: + //申请出货 + if (move == 1 && !requireSucess) { + request_for_shipment(String.valueOf(mode), item_out_seq_arr, item_out_qty_arr); + } + break; + } + } + last_heartbeat = heartbeat; last_mode = mode; - last_inventory_qty = inventory_qty; - last_out_finish = out_finish; last_error = error; - last_material = material; + last_carrier_direction = carrier_direction; + last_task = task; + last_to_command = to_command; + last_to_target = to_target; + last_to_task = to_task; + last_item_out_seq_arr = item_out_seq_arr; + last_item_out_qty_arr = item_out_qty_arr; + } @@ -160,7 +280,6 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl public void writing(List list) { - Map itemMap = new HashMap(); for (int i = 0; i < list.size(); i++) { Object ob = list.get(i); @@ -176,28 +295,240 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl this.checkcontrol(itemMap); } catch (Exception e) { e.printStackTrace(); - try{ + try { this.checkcontrol(itemMap); - } catch (Exception e1){ + } catch (Exception e1) { e1.printStackTrace(); } } } + + public void writing(Map map) { + DeviceExecuteLogService logServer = SpringContextHolder.getBean("deviceExecuteLogServiceImpl"); + Map itemMap = new LinkedHashMap<>(); + map.forEach((key, value) -> { + if (ObjectUtil.isNotEmpty(value)) { + itemMap.put(getToParam() + key, value); + } + }); + if (ObjectUtil.isNotEmpty(itemMap)) { + this.control(itemMap); + logServer.deviceExecuteLog(this.getDevice().getDevice_code(), "", "", "下发多个电气信号:" + itemMap); + } + } + + + public synchronized void request_for_shipment(String mode, String item_out_seq_arr, int[] item_out_qty_arr) { + Date date = new Date(); + if (date.getTime() - this.require_apply_strangulation_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + } else { + this.require_apply_strangulation_time = date; + ApplyPaperActionRequest applyPaperActionRequest = new ApplyPaperActionRequest(); + applyPaperActionRequest.setDevice_code(this.device_code); + applyPaperActionRequest.setType("1"); + applyPaperActionRequest.setTask_code(String.valueOf(task)); + //获取出库顺序 + boolean contains = item_out_seq_arr.contains(","); + //String s = item_out_seq_arr.replaceAll("[\\[\\]]", ""); + if (contains) { + String[] split = item_out_seq_arr.split(","); + applyPaperActionRequest.setMaterial1(split[0]); + applyPaperActionRequest.setMaterial2(split[1]); + } else { + applyPaperActionRequest.setMaterial1(item_out_seq_arr); + } + /*if (item_out_qty_arr.length == 2) { + // 去除方括号 + applyPaperActionRequest.setMaterial1(String.valueOf(item_out_qty_arr[0])); + applyPaperActionRequest.setMaterial2(String.valueOf(item_out_qty_arr[1])); + } else if (item_out_qty_arr.length == 1) { + applyPaperActionRequest.setMaterial1(String.valueOf(item_out_qty_arr[0])); + }*/ + if (item_out_qty_arr.length >= 1 && item_out_qty_arr.length < 4) { + applyPaperActionRequest.setQty1(String.valueOf(item_out_qty_arr[0])); + applyPaperActionRequest.setQty2(String.valueOf(item_out_qty_arr[1])); + } + ApplyPaperActionResponse applyPaperActionResponse = acsToWmsService.applyPaperActionRequest(applyPaperActionRequest); + Map map3 = new HashMap(); + if (applyPaperActionResponse.getstatus() == 200) { + map3.put("to_command", "4"); + this.writing(map3); + requireSucess = true; + logServer.deviceExecuteLog(this.device_code, "", "", "申请出纸管,返回参数:" + applyPaperActionResponse); + message = "申请出货成功"; + } else { + message = applyPaperActionResponse.getMessage(); + map3.put("to_command", "5"); + this.writing(map3); + requireSucess = false; + message = "出库顺序错误"; + logServer.deviceExecuteLog(this.device_code, "", "", "申请出纸管,返回参数:" + applyPaperActionResponse); + } + } + } + + + /** + * 申请任务 + */ + public synchronized Boolean instruction_require() { + Date date = new Date(); + if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + return false; + } else { + this.instruction_require_time = date; + //查找有没有对应的指令 + //找指令类型是10的 + Instruction inst = instructionService.findByDeviceCodeFromCache(this.device_code); + if (ObjectUtil.isNull(inst)) { + return false; + } + if (ObjectUtil.isNotNull(inst) && "10".equals(inst.getInstruction_code())) { + Device nextdevice = deviceAppservice.findDeviceByCode(inst.getNext_device_code()); + String next_addr = nextdevice.getExtraValue().get("address").toString(); + TaskDto taskDto = taskserver.findByCodeFromCache(inst.getTask_code()); + List paperArray = getPaperArray(taskDto.getPaper_array()); + if (ObjectUtil.isEmpty(inst)) { + return false; + } + Map map = new HashMap(); + if (paperArray.size() == 1) { + writeStatus(paperArray, map, 1); + } else if (paperArray.size() == 2) { + writeStatus(paperArray, map, 1); + writeStatus(paperArray, map, 2); + } else if (paperArray.size() == 3) { + writeStatus(paperArray, map, 1); + writeStatus(paperArray, map, 2); + writeStatus(paperArray, map, 3); + } + writeData(next_addr, inst, map); + this.writing(map); + requireSucess = true; + return true; + } else { + //判断是否有相同起点的,任务状态就绪的任务 + //任务类型是10 + TaskDto taskdto = taskserver.findByStartCodeAndReady(device_code); + if (ObjectUtil.isNull(taskdto)) { + return false; + } + List paperArray = getPaperArray(taskdto.getPaper_array()); + if (ObjectUtil.isNotNull(taskdto) && "10".equals(taskdto.getTask_type())) { + //判断指令的起点和当前的设备号相同 + if (!taskdto.getStart_device_code().equals(device_code)) { + return false; + } + //判断当前任务号是否存在指令 + Instruction inst1 = instructionService.findByTaskcodeAndStatus(taskdto.getTask_code()); + Device nextdevice = deviceAppservice.findDeviceByCode(inst1.getNext_device_code()); + String next_addr = nextdevice.getExtraValue().get("address").toString(); + Device pointdevice = deviceAppservice.findDeviceByCode(inst1.getNext_point_code()); + String point_addr = pointdevice.getExtraValue().get("address").toString(); + //没有就创建指令 + String taskid = taskdto.getTask_id(); + String taskcode = taskdto.getTask_code(); + String priority = taskdto.getPriority(); + String start_point_code = taskdto.getStart_point_code(); + String start_device_code = taskdto.getStart_device_code(); + String route_plan_code = taskdto.getRoute_plan_code(); + + Instruction instdto = new Instruction(); + instdto.setInstruction_id(IdUtil.simpleUUID()); + instdto.setRoute_plan_code(route_plan_code); + instdto.setRemark(taskdto.getRemark()); + instdto.setMaterial(taskdto.getMaterial()); + instdto.setQuantity(taskdto.getQuantity()); + instdto.setTask_id(taskid); + instdto.setTask_code(taskcode); + String now = DateUtil.now(); + instdto.setCreate_time(now); + instdto.setCreate_by("auto"); + instdto.setStart_device_code(start_device_code); + instdto.setNext_device_code(next_addr); + instdto.setStart_point_code(start_point_code); + instdto.setNext_point_code(point_addr); + instdto.setPriority(priority); + instdto.setInstruction_status("0"); + instdto.setExecute_device_code(start_point_code); + try { + instructionService.create(instdto); + } catch (Exception e) { + e.printStackTrace(); + log.error("指令创建失败!", e.getMessage()); + return false; + } + taskdto.setTask_status("1"); + taskserver.update(taskdto); + requireSucess = true; + Map map = new HashMap(); + if (paperArray.size() == 1) { + writeStatus(paperArray, map, 1); + } else if (paperArray.size() == 2) { + writeStatus(paperArray, map, 1); + writeStatus(paperArray, map, 2); + } else if (paperArray.size() == 3) { + writeStatus(paperArray, map, 1); + writeStatus(paperArray, map, 2); + writeStatus(paperArray, map, 3); + } + writeData(next_addr, instdto, map); + this.writing(map); + requireSucess = true; + return true; + } + //并且指令的起点和当前的设备号相同 + //找到就要下发数据 + //查找就绪状态的任务 + //并且任务的起点和当前的设备号相同 + //找到创建指令 + //入库顺序 + } + return false; + } + } + + public void writeData(String next_addr, Instruction instdto, Map map) { + map.put("to_target", next_addr); + map.put("to_task", instdto.getInstruction_code()); + map.put("to_command", "1"); + } + + public String getToParam() { + return this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + "."; + } + + public void writeStatus(List paperArray, Map map, Integer status) { + Paper paper = paperArray.get(status); + map.put("to_material" + status, paper.getMeterial_code()); + map.put("to_out_qty" + status, paper.getQty()); + map.put("to_seq" + status, "1"); + map.put("to_position" + status, paper.getDevice_code()); + } + + public void writing(String key, String param) { String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + "." + param; //String opcservcerid = this.getDevice().getOpc_server_id(); -//Server server = ReadUtil.getServer(opcservcerid); + //Server server = ReadUtil.getServer(opcservcerid); Map itemMap = new HashMap(); itemMap.put(to_param, Integer.parseInt(param)); -// itemMap.put(to_param, Integer.parseInt(value)); + //itemMap.put(to_param, Integer.parseInt(value)); this.control(itemMap); logServer.deviceExecuteLog(device_code, "", "", "下发电气信号设备号:" + device_code + ",下发电气:" + to_param + ",下发电气值:" + param); } + public synchronized boolean finish_instruction() throws Exception { + instructionService.finish(inst); + return true; + } + @Override public JSONObject getDeviceStatusName() { JSONObject jo = new JSONObject(); @@ -225,6 +556,65 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl return jo; } + /** + * 解析出库的顺序 + */ + public List getPaperArray(String paper_array) { + JSONArray jsonArray = JSONUtil.parseArray(paper_array); + List papers = jsonArray.toList(Paper.class); + return papers; + } + + + /** + * 更新指令状态 + */ + public synchronized void update_instruction_status() throws Exception { + Date date = new Date(); + if (date.getTime() - this.instruction_update_time.getTime() < (long) this.instruction_update_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_update_time_out); + + } else { + this.instruction_update_time = date; + inst = checkInst(); + if (inst != null) { + //a点到b点,给状态说允许取货 + if (StrUtil.equals(inst.getInstruction_status(), "0") && StrUtil.equals(this.getDeviceCode(), inst.getStart_device_code())) { + inst.setInstruction_status("1"); + inst.setExecute_device_code(this.device_code); + instructionService.update(inst); + logServer.deviceExecuteLog(device_code, "", "", "入库输送线任务开始反馈执行中状态,反馈成功,指令号:" + task); + } + //当货物到达b点,实现完成指令 + if (StrUtil.equals(inst.getInstruction_status(), "1") || StrUtil.equals(inst.getInstruction_status(), "0")) { + if (StrUtil.equals(this.getDeviceCode(), inst.getNext_device_code())) { + inst.setExecute_device_code(this.device_code); + finish_instruction(); + logServer.deviceExecuteLog(device_code, "", "", "入库输送线任务开始反馈完成状态,反馈成功,指令号:" + task); + } + } + } + } + } + + public Instruction checkInst() { + if (ObjectUtil.isNotEmpty(this.inst)) { + if (this.task > 0) { + if (this.inst.getInstruction_code().equals(String.valueOf(this.task))) { + return this.inst; + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + } + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + return null; + } + + @Override public void setDeviceStatus(JSONObject data) { diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java index 04f4baedb..157d4f3f1 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java @@ -81,6 +81,11 @@ public interface OpcDeviceDriver extends DeviceDriver { return (String) this.getOpcValueAccessor().getValue(this.getItem(protocol)); } + default List getArrayValue(String protocol) { + return (List) this.getOpcValueAccessor().getValue(this.getItem(protocol)); + } + + default Object getValue(String protocol) { return this.getOpcValueAccessor().getValue(this.getItem(protocol)); } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java index 8fab0c4a7..57d5fff79 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java @@ -98,6 +98,13 @@ public interface AcsToWmsService { */ ApplyLabelingAndBindingResponse applyLabelingAndBindingRequest(ApplyLabelingAndBindingRequest param); + /** + * 申请出纸管,套纸管 + * @param param + * @return + */ + ApplyPaperActionResponse applyPaperActionRequest(ApplyPaperActionRequest param); + LiKuApplyTakResponse liKuApplyTaskRequest(LiKuApplyTaskRequest liKuApplyTaskRequest); UpdateLKTaskResponse updateLKTaskRequest(UpdateLKTaskRequest updateLKTaskRequest); diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java index 69a717c7f..00c9ec05f 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java @@ -444,10 +444,42 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { } finally { MDC.remove(log_file_type); } - - } + @Override + public ApplyPaperActionResponse applyPaperActionRequest(ApplyPaperActionRequest param) { + try { + MDC.put(log_file_type, log_type); + ApplyPaperActionResponse applyPaperActionResponse = new ApplyPaperActionResponse(); + if (StrUtil.equals(paramService.findByCode(AcsConfig.HASWMS).getValue(), "1")) { + String wmsUrl = paramService.findByCode(AcsConfig.WMSURL).getValue(); + AddressDto addressDto = addressService.findByCode("applyPaperAction"); + String methods_url = addressDto.getMethods_url(); + String url = wmsUrl + methods_url; + log.info("ApplyPaperActionRequest----请求参数{}", param); + try { +// String result = ""; + String result = HttpRequest.post(url) + .body(JSON.toJSONString(param)) + .execute().body(); + JSONObject jsonObject = JSONObject.parseObject(result); + log.info("ApplyPaperActionResponse----返回参数{}", result); + applyPaperActionResponse = JSONObject.toJavaObject(jsonObject, ApplyPaperActionResponse.class); + } catch (Exception e) { + JSONObject map = new JSONObject(); + map.put("status", 400); + map.put("message", e.getMessage()); + return JSONObject.toJavaObject(map, ApplyPaperActionResponse.class); + } + } + return applyPaperActionResponse; + } finally { + MDC.remove(log_file_type); + } + } + + + @Override public LiKuApplyTakResponse liKuApplyTaskRequest(LiKuApplyTaskRequest param) { try { diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java index e23b40625..0792a31cc 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java @@ -1186,6 +1186,11 @@ public class TaskServiceImpl implements TaskService, ApplicationAutoInitial { return null; } + /** + * 根据任务号查询任务 + * @param task_code + * @return + */ public TaskDto findByCodeFromCache(String task_code) { Iterator var3 = tasks.iterator(); diff --git a/acs/nladmin-system/src/main/resources/config/application-dev.yml b/acs/nladmin-system/src/main/resources/config/application-dev.yml index 7a0351aed..acaab12ad 100644 --- a/acs/nladmin-system/src/main/resources/config/application-dev.yml +++ b/acs/nladmin-system/src/main/resources/config/application-dev.yml @@ -1,5 +1,5 @@ server: - port: 8010 + port: 8011 tomcat: accept-count: 1000 max-connections: 10000 diff --git a/acs/nladmin-ui/src/views/acs/device/config.vue b/acs/nladmin-ui/src/views/acs/device/config.vue index 8ccbaac84..f18b4a266 100644 --- a/acs/nladmin-ui/src/views/acs/device/config.vue +++ b/acs/nladmin-ui/src/views/acs/device/config.vue @@ -100,6 +100,8 @@ import photoelectric_inspection_site from '@/views/acs/device/driver/photoelectr import standard_autodoor from '@/views/acs/device/driver/standard_autodoor' import lamp_three_color from '@/views/acs/device/driver/lamp_three_color' import paper_tube_conveyor from '@/views/acs/device/driver/paper_tube_conveyor' +import paper_tube_conveyor2 from '@/views/acs/device/driver/paper_tube_conveyor2' +import casing_station from '@/views/acs/device/driver/casing_station' import device_status from '@/views/acs/device/driver/device_status' export default { @@ -132,7 +134,9 @@ export default { standard_autodoor, lamp_three_color, paper_tube_conveyor, - device_status + device_status, + paper_tube_conveyor2, + casing_station }, dicts: ['device_type'], mixins: [crud], From 4d53aaaf4e9adb04d7a1205c5b95a1a4b5d90314 Mon Sep 17 00:00:00 2001 From: yanps Date: Tue, 7 Nov 2023 10:57:10 +0800 Subject: [PATCH 06/14] =?UTF-8?q?=E7=BA=B8=E7=AE=A1=E5=BA=93=E5=92=8C?= =?UTF-8?q?=E5=A5=97=E7=AE=A1=E5=B7=A5=E4=BD=8D=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../acs/device/driver/casing_station.vue | 500 ++++++++++++++++++ .../device/driver/paper_tube_conveyor2.vue | 500 ++++++++++++++++++ 2 files changed, 1000 insertions(+) create mode 100644 acs/nladmin-ui/src/views/acs/device/driver/casing_station.vue create mode 100644 acs/nladmin-ui/src/views/acs/device/driver/paper_tube_conveyor2.vue diff --git a/acs/nladmin-ui/src/views/acs/device/driver/casing_station.vue b/acs/nladmin-ui/src/views/acs/device/driver/casing_station.vue new file mode 100644 index 000000000..032907b97 --- /dev/null +++ b/acs/nladmin-ui/src/views/acs/device/driver/casing_station.vue @@ -0,0 +1,500 @@ + + + + + diff --git a/acs/nladmin-ui/src/views/acs/device/driver/paper_tube_conveyor2.vue b/acs/nladmin-ui/src/views/acs/device/driver/paper_tube_conveyor2.vue new file mode 100644 index 000000000..032907b97 --- /dev/null +++ b/acs/nladmin-ui/src/views/acs/device/driver/paper_tube_conveyor2.vue @@ -0,0 +1,500 @@ + + + + + From cf9213eab401341943e237fa40fb1ebcbd1857e9 Mon Sep 17 00:00:00 2001 From: tuqiang <437016993@qq.com> Date: Tue, 7 Nov 2023 11:01:34 +0800 Subject: [PATCH 07/14] =?UTF-8?q?add:=E6=96=B0=E5=A2=9E=E5=86=85=E5=8C=85?= =?UTF-8?q?=E9=97=B4=E8=A1=8C=E6=9E=B6=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../device/device_driver/DriverTypeEnum.java | 5 +- .../java/org/nl/acs/device/wql/task_inst.xls | Bin 196096 -> 167424 bytes .../IndoorManipulatorDefination.java | 61 ++ .../IndoorManipulatorDeviceDriver.java | 842 ++++++++++++++++++ .../indoor_manipulator/ItemProtocol.java | 224 +++++ .../data/ApplyManipulatorActionRequest.java | 28 + .../data/ApplyManipulatorActionResponse.java | 48 + .../acs/ext/wms/rest/AcsToWmsController.java | 8 + .../acs/ext/wms/service/AcsToWmsService.java | 2 + .../wms/service/impl/AcsToWmsServiceImpl.java | 34 + .../org/nl/acs/task/service/TaskService.java | 8 + .../task/service/impl/TaskServiceImpl.java | 14 + .../src/views/acs/device/config.vue | 4 +- .../acs/device/driver/indoor_manipulator.vue | 546 ++++++++++++ 14 files changed, 1822 insertions(+), 2 deletions(-) create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDefination.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/ItemProtocol.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java create mode 100644 acs/nladmin-ui/src/views/acs/device/driver/indoor_manipulator.vue diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java index 998f6f584..0fa6c196c 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device/device_driver/DriverTypeEnum.java @@ -55,7 +55,10 @@ public enum DriverTypeEnum { PAPER_TUBE_DEVICE(22, "paper_tube_conveyor", "纸管库设备", "conveyor"), - DEVICE_STATUS(23,"device_status","立库设备状态","conveyor"); + DEVICE_STATUS(23,"device_status","立库设备状态","conveyor"), + + INDOOR_MANIPULATOR(24,"indoor_manipulator","内包间-行架机械手","station"); + //驱动索引 private int index; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls b/acs/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls index 5861314cf76cef243ebd2321d61f8f76f4e43634..7470984f1b975aa75f7771b3840aaf0f499a2cc4 100644 GIT binary patch delta 58673 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 L3VecY{m}mfnx3b< literal 196096 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�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 diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDefination.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDefination.java new file mode 100644 index 000000000..16e1a20ec --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDefination.java @@ -0,0 +1,61 @@ +package org.nl.acs.device_driver.basedriver.indoor_manipulator; + +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; +import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.defination.OpcDeviceDriverDefination; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceType; +import org.springframework.stereotype.Service; + +import java.util.LinkedList; +import java.util.List; + +/** + * 内包间-行架机械手 + * + */ +@Service +public class IndoorManipulatorDefination implements OpcDeviceDriverDefination { + @Override + public String getDriverCode() { + return "indoor_manipulator"; + } + + @Override + public String getDriverName() { + return "内包间-行架机械手"; + } + + @Override + public String getDriverDescription() { + return "内包间-行架机械手"; + } + + @Override + public DeviceDriver getDriverInstance(Device device) { + return (new IndoorManipulatorDeviceDriver()).setDevice(device).setDriverDefination(this); + } + + @Override + public Class getDeviceDriverType() { + return IndoorManipulatorDeviceDriver.class; + } + + @Override + public List getFitDeviceTypes() { + List types = new LinkedList(); + types.add(DeviceType.station); + return types; + } + + + @Override + public List getReadableItemDtos() { + return ItemProtocol.getReadableItemDtos(); + } + + @Override + public List getWriteableItemDtos() { + return ItemProtocol.getWriteableItemDtos(); + } +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java new file mode 100644 index 000000000..a94e8d44e --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java @@ -0,0 +1,842 @@ +package org.nl.acs.device_driver.basedriver.indoor_manipulator; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.AcsConfig; +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.RouteableDeviceDriver; +import org.nl.acs.device_driver.basedriver.hongxiang_device.HongXiangConveyorDeviceDriver; +import org.nl.acs.device_driver.basedriver.lamp_three_color.LampThreecolorDeviceDriver; +import org.nl.acs.device_driver.basedriver.photoelectric_inspection_site.PhotoelectricInspectionSiteDeviceDriver; +import org.nl.acs.device_driver.basedriver.siemens_conveyor.SiemensConveyorDeviceDriver; +import org.nl.acs.device_driver.basedriver.standard_inspect_site.StandardInspectSiteDeviceDriver; +import org.nl.acs.device_driver.basedriver.standard_ordinary_site.StandardOrdinarySiteDeviceDriver; +import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; +import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; +import org.nl.acs.ext.wms.data.ApplyLabelingAndBindingRequest; +import org.nl.acs.ext.wms.data.ApplyLabelingAndBindingResponse; +import org.nl.acs.ext.wms.data.ApplyManipulatorActionRequest; +import org.nl.acs.ext.wms.data.ApplyManipulatorActionResponse; +import org.nl.acs.ext.wms.service.AcsToWmsService; +import org.nl.acs.history.ErrorUtil; +import org.nl.acs.history.service.DeviceErrorLogService; +import org.nl.acs.history.service.dto.DeviceErrorLogDto; +import org.nl.acs.history.service.impl.DeviceErrorLogServiceImpl; +import org.nl.acs.instruction.service.InstructionService; +import org.nl.acs.instruction.service.dto.Instruction; +import org.nl.acs.log.service.DeviceExecuteLogService; +import org.nl.acs.monitor.DeviceStageMonitor; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceAppService; +import org.nl.acs.opc.DeviceAppServiceImpl; +import org.nl.acs.route.service.RouteLineService; +import org.nl.acs.task.service.TaskService; +import org.nl.acs.task.service.dto.TaskDto; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.system.service.ParamService; +import org.nl.modules.system.service.impl.ParamServiceImpl; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.SpringContextHolder; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; + + +/** + * 内包间-行架机械手 + */ +@Slf4j +@Data +@RequiredArgsConstructor +public class IndoorManipulatorDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver { + protected org.nl.acs.device_driver.basedriver.indoor_manipulator.ItemProtocol itemProtocol = new ItemProtocol(this); + @Autowired + InstructionService instructionService = SpringContextHolder.getBean("instructionServiceImpl"); + @Autowired + DeviceService deviceservice = SpringContextHolder.getBean("deviceServiceImpl"); + @Autowired + RouteLineService routelineserver = SpringContextHolder.getBean("routeLineServiceImpl"); + @Autowired + TaskService taskserver = SpringContextHolder.getBean("taskServiceImpl"); + @Autowired + DeviceExecuteLogService logServer = SpringContextHolder.getBean("deviceExecuteLogServiceImpl"); + @Autowired + AcsToWmsService acsToWmsService = SpringContextHolder.getBean("acsToWmsServiceImpl"); + @Autowired + DeviceAppService deviceAppService = SpringContextHolder.getBean(DeviceAppServiceImpl.class); + @Autowired + DeviceErrorLogService deviceErrorLogService = SpringContextHolder.getBean(DeviceErrorLogServiceImpl.class); + @Autowired + ParamService paramService = SpringContextHolder.getBean(ParamServiceImpl.class); + + + //工作模式 + int mode = 0; + int last_mode = 0; + //光电信号 + int move = 0; + int last_move = 0; + //动作信号 + int action = 0; + int last_action = 0; + //行走列 + int walk_y = 0; + int last_walk_y = 0; + //报警信号 + int error = 0; + int last_error = 0; + //任务号 + int task = 0; + int last_task = 0; + // x坐标 + float x_position = 0; + float last_x_position = 0; + // y坐标 + float y_position = 0; + float last_y_position = 0; + //气胀轴尺寸 + int inflatable_shaft_size = 0; + int last_inflatable_shaft_size = 0; + + int heartbeat = 0; + int last_heartbeat = 0; + int to_command = 0; + int last_to_command = 0; + + int to_target = 0; + int last_to_target = 0; + + int to_task = 0; + int last_to_task = 0; + + int to_onset = 0; + int last_to_onset = 0; + + int to_putpoint = 0; + int last_to_putpoint = 0; + + int to_new_getpoint = 0; + int last_to_new_getpoint = 0; + + int to_two_putpoint = 0; + int last_to_two_putpoint = 0; + + int to_task_type = 0; + int last_to_task_type = 0; + + //气胀轴代数 + int inflatableShaftVersion = 0; + int last_inflatableShaftVersion = 0; + + //套管数量 + int tube_num = 0; + int last_tube_num = 0; + + //是否套轴 + int is_wrapped = 0; + int last_is_wrapped = 0; + + Boolean isonline = true; + int hasGoods = 0; + String message = null; + Boolean iserror = false; + private Date instruction_update_time = new Date(); + private int instruction_update_time_out = 1000; + Integer heartbeat_tag; + private Date instruction_require_time = new Date(); + + private int instruction_require_time_out = 3000; + private Date instruction_apply_time = new Date(); + //行架机械手申请任务成功标识 + boolean requireSucess = false; + //反馈成功表示 + boolean feedbackSucess = false; + + private int instruction_finished_time_out; + + int branchProtocol = 0; + private String error_type = "hxhj_error_type"; + + //暂定 0就绪 1请求取货 2取货完成 3请求放货 4放货完成 5取货完成离开 6放货完成离开 7请求进入区域 8请求离开区域 + int flag; + + String device_code; + + //当前指令 + Instruction inst = null; + + //0 无任务执行 1更新指令状态 2下发电气信号 3允许取货 允许放货 5放货完成 + int now_steps_type = 0; + String notCreateTaskMessage = ""; + String notCreateInstMessage = ""; + String feedMessage = ""; + + + List getDeviceCodeList = null; + + List putDeviceCodeList = null; + + + @Override + public Device getDevice() { + return this.device; + } + + @Override + public void execute() { + String message = null; + try { + device_code = this.getDeviceCode(); + mode = this.itemProtocol.getMode(); + move = this.itemProtocol.getMove(); + if(mode==2){ + log.info("123"); + } + action = this.itemProtocol.getAction(); + walk_y = this.itemProtocol.getWalk_y(); + error = this.itemProtocol.getError(); + task = this.itemProtocol.getTask(); + heartbeat = this.itemProtocol.getHeartbeat(); + to_command = this.itemProtocol.getTo_command(); + to_target = this.itemProtocol.getTo_target(); + to_task = this.itemProtocol.getTo_task(); + to_onset = this.itemProtocol.getTo_onset(); + x_position = this.itemProtocol.getX_position(); + y_position = this.itemProtocol.getY_position(); + inflatable_shaft_size = this.itemProtocol.getInflatable_shaft_size(); + to_putpoint = this.itemProtocol.getTo_putpoint(); + to_new_getpoint = this.itemProtocol.getTo_new_getpoint(); + to_two_putpoint = this.itemProtocol.getTo_two_putpoint(); + to_task_type = this.itemProtocol.getTo_task_type(); + tube_num = this.itemProtocol.getTube_num(); + inflatableShaftVersion = this.itemProtocol.getInflatableShaftVersion(); + is_wrapped = this.itemProtocol.getIs_wrapped(); + + if (to_onset != last_to_onset) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_onset:" + last_to_onset + "->" + to_onset); + } + if (to_command != last_to_command) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_command:" + last_to_command + "->" + to_command); + } + if (to_target != last_to_target) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_target:" + last_to_target + "->" + to_target); + } + if (to_task != last_to_task) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_task:" + last_to_task + "->" + to_task); + } + if (mode != last_mode) { + JSONObject param = new JSONObject(); + param.put("device_code", this.device_code); + param.put("mode", Math.min(mode, 3)); + param.put("device_name", this.getDevice().getDevice_name()); + param.put("device_type", "2"); + param.put("product_area", paramService.findByCode("productArea").getValue()); + acsToWmsService.sendDeviceStatus(param); + + if (mode == 2) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号复位前requireSuccess:" + requireSucess); + this.setRequireSucess(false); + logServer.deviceExecuteLog(this.device_code, "", "", "信号复位后requireSuccess:" + requireSucess); +// if (move == 0 && task == 0 && action == 0 && this.getNow_steps_type() != 0){ +// logServer.deviceExecuteLog(this.device_code, "", "", "当前执行步骤复位前:" + this.getNow_steps_type()); +// this.setNow_steps_type(0); +// logServer.deviceExecuteLog(this.device_code, "", "", "当前执行步骤复位后:" + this.getNow_steps_type()); +// } + feedMessage = ""; + notCreateInstMessage = ""; + notCreateTaskMessage = ""; + inst = null; + message = null; + } + logServer.deviceItemValue(this.device_code, "mode", String.valueOf(mode)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode); + } + if (move != last_move) { + logServer.deviceItemValue(this.device_code, "move", String.valueOf(move)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号move:" + last_move + "->" + move); + } + if (action != last_action) { + this.setFeedbackSucess(false); + logServer.deviceItemValue(this.device_code, "action", String.valueOf(action)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号action:" + last_action + "->" + action); + } + if (error != last_error) { + if (error != 0) { + DeviceErrorLogDto dto = new DeviceErrorLogDto(); + dto.setDevice_code(device_code); + dto.setError_code(String.valueOf(error)); + String errorInfo = ErrorUtil.getDictDetail("hxhj_error_type", String.valueOf(error)); + dto.setError_info(errorInfo); + deviceErrorLogService.create(dto); + } + + JSONObject param = new JSONObject(); + param.put("device_code", this.device_code); + param.put("error", error); + param.put("error_msg", error == 0 ? "" : ErrorUtil.getDictDetail("hxhj_error_type", String.valueOf(error))); + param.put("device_name", this.getDevice().getDevice_name()); + param.put("device_type", "2"); + param.put("product_area", paramService.findByCode("productArea").getValue()); + acsToWmsService.sendDeviceStatus(param); + + logServer.deviceItemValue(this.device_code, "error", String.valueOf(error)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号error:" + last_error + "->" + error); + } + if (walk_y != last_walk_y) { + logServer.deviceItemValue(this.device_code, "walk_y", String.valueOf(walk_y)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号walk_y:" + last_walk_y + "->" + walk_y); + } + if (task != last_task) { + logServer.deviceItemValue(this.device_code, "task", String.valueOf(task)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号task:" + last_task + "->" + task); + } + if (x_position != last_x_position) { + logServer.deviceItemValue(this.device_code, "x_position", String.valueOf(x_position)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号x_position:" + last_x_position + "->" + x_position); + } + if (y_position != last_y_position) { + logServer.deviceItemValue(this.device_code, "y_position", String.valueOf(y_position)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号y_position:" + last_y_position + "->" + y_position); + } + if (inflatable_shaft_size != last_inflatable_shaft_size) { + logServer.deviceItemValue(this.device_code, "inflatable_shaft_size", String.valueOf(inflatable_shaft_size)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号inflatable_shaft_size:" + last_inflatable_shaft_size + "->" + inflatable_shaft_size); + } + if (task > 0) { + update_instruction_status(); + } + + } catch (Exception var17) { + var17.printStackTrace(); + feedMessage = var17.getMessage(); + logServer.deviceExecuteLog(this.device_code, "", "", "读取信号值时出现异常:" + var17.getMessage() + ",this.itemProtocol is null:" + ObjectUtil.isEmpty(this.itemProtocol)); + + } + if (mode == 0) { + this.setIsonline(false); + message = "未联机"; + //有报警 + } else if (error != 0) { + this.setIserror(true); + message = "有报警"; + //无报警 + } else { + this.setIsonline(true); + this.setIserror(false); + message = ""; + Instruction instruction = null; + List toInstructions; + + //行架机械手申请任务 + if (mode == 2 && move == 0 && !requireSucess) { + boolean res = applyTask(); + if (res) { + notCreateInstMessage = ""; + notCreateTaskMessage = ""; + feedMessage = ""; + } + } else { + if (mode == 2) { + //if (!requireSucess) { + String remark = "未查找任务原因为:"; + if (mode != 2) { + remark = remark + "工作模式(mode)不是待机状态,"; + } + if (move != 0) { + remark = remark + "光电信号(move)为有货状态,"; + } + if (task != 0) { + remark = remark + "当前上报任务号(task)应该为0,"; + if (ObjectUtil.isNotEmpty(this.inst)) { + this.inst = null; + } + } + if (requireSucess) { + remark = remark + "请右击该图标,将请求任务复位标记(requireSucess)改为否。"; + } + this.setNotCreateTaskMessage(remark); + } + } + if (mode == 3 && !feedbackSucess && action > 0) { + apply_feedback(); + } + + } + last_mode = mode; + last_move = move; + last_action = action; + last_walk_y = walk_y; + last_error = error; + last_task = task; + last_heartbeat = heartbeat; + last_to_task = to_task; + last_to_command = to_command; + last_to_target = to_target; + last_to_onset = to_onset; + last_x_position = x_position; + last_y_position = y_position; + last_inflatable_shaft_size = inflatable_shaft_size; + } + + /** + * 抽取统一下发电气信号前缀 + * + * @return + */ + public String getToParam() { + return this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + "."; + } + + /** + * 多个信号一起下发电气 + * + * @param map + */ + public void writing(Map map) { + DeviceExecuteLogService logServer = SpringContextHolder.getBean("deviceExecuteLogServiceImpl"); + Map itemMap = new LinkedHashMap<>(); + map.forEach((key, value) -> { + if (ObjectUtil.isNotEmpty(value)) { + itemMap.put(getToParam() + key, value); + } + }); + if (ObjectUtil.isNotEmpty(itemMap)) { + this.control(itemMap); + logServer.deviceExecuteLog(this.getDevice().getDevice_code(), "", "", "下发多个电气信号:" + itemMap); + } + } + + public synchronized boolean apply_feedback() { + Date date = new Date(); + if (date.getTime() - this.instruction_apply_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + return false; + } else { + ApplyManipulatorActionRequest applyManipulatorActionRequest = new ApplyManipulatorActionRequest(); + ApplyManipulatorActionResponse applyManipulatorActionResponse; + if (action == 2) { + this.instruction_apply_time = date; + message = "完成反馈LMS..."; + JSONObject device_json = WQLObject.getWQLObject("acs_storage_cell").query("storage_code ='" + this.device_code + "'").uniqueResult(0); + String start_point_code = null; + if (!ObjectUtil.isEmpty(device_json)) { + start_point_code = (String) device_json.get("parent_storage_code") == null ? this.device_code : (String) device_json.get("parent_storage_code"); + } + applyManipulatorActionRequest.setDevice_code(start_point_code); + applyManipulatorActionRequest.setType("2"); + applyManipulatorActionRequest.setTask_code(String.valueOf(task)); + applyManipulatorActionRequest.setSize(String.valueOf(inflatable_shaft_size)); + applyManipulatorActionResponse = acsToWmsService.applyManipulatorActionRequest(applyManipulatorActionRequest); + logServer.deviceExecuteLog(this.device_code, "", "", "反馈请求参数:" + JSON.toJSONString(applyManipulatorActionRequest)); + if (applyManipulatorActionResponse.getstatus() == 200) { + requireSucess = true; + message = "反馈LMS成功..."; + logServer.deviceExecuteLog(this.device_code, "", "", "反馈完成请求成功,响应参数:" + JSON.toJSONString(applyManipulatorActionResponse)); + String version = applyManipulatorActionResponse.getVersion(); + String bushing_num = applyManipulatorActionResponse.getBushing_num(); + String is_bushing = applyManipulatorActionResponse.getIs_bushing(); + String detail_type = applyManipulatorActionResponse.getDetail_type(); + Map map = new LinkedHashMap<>(); + map.put("to_command", "2"); + map.put("to_task_type", detail_type); + map.put("inflatableShaftVersion", version); + map.put("tube_num", bushing_num); + map.put("is_wrapped", is_bushing); + this.writing(map); + this.setFeedbackSucess(true); + } else { + requireSucess = true; + message = "完成反馈LMS失败," + String.valueOf(applyManipulatorActionResponse); + logServer.deviceExecuteLog(this.device_code, "", "", "反馈完成请求失败,响应参数:" + JSON.toJSONString(applyManipulatorActionResponse)); + } + + } + if (action == 3) { + applyManipulatorActionRequest.setType("3"); + applyManipulatorActionRequest.setTask_code(String.valueOf(task)); + applyManipulatorActionResponse = acsToWmsService.applyManipulatorActionRequest(applyManipulatorActionRequest); + String put_device_code = applyManipulatorActionResponse.getPut_device_code(); + String detail_type = applyManipulatorActionResponse.getDetail_type(); + Map map = new LinkedHashMap<>(); + map.put("to_command", "3"); + map.put("to_task_type", detail_type); + map.put("to_putpoint", put_device_code); + this.writing(map); + this.setFeedbackSucess(true); + } + if (action == 4) { + applyManipulatorActionRequest.setType("4"); + applyManipulatorActionRequest.setTask_code(String.valueOf(task)); + applyManipulatorActionResponse = acsToWmsService.applyManipulatorActionRequest(applyManipulatorActionRequest); + String get_device_code = applyManipulatorActionResponse.getGet_device_code(); + Map map = new LinkedHashMap<>(); + map.put("to_command", "4"); + map.put("to_new_getpoint", get_device_code); + this.writing(map); + this.setFeedbackSucess(true); + } + if (action == 5) { + applyManipulatorActionRequest.setType("5"); + applyManipulatorActionRequest.setTask_code(String.valueOf(task)); + applyManipulatorActionResponse = acsToWmsService.applyManipulatorActionRequest(applyManipulatorActionRequest); + String put_device_code2 = applyManipulatorActionResponse.getPut_device_code2(); + String detail_type = applyManipulatorActionResponse.getDetail_type(); + Map map = new LinkedHashMap<>(); + map.put("to_command", "5"); + map.put("to_task_type", detail_type); + map.put("to_two_putpoint", put_device_code2); + this.writing(map); + this.setFeedbackSucess(true); + } + return true; + } + } + + public synchronized boolean finish_instruction(Instruction inst) throws Exception { + instructionService.finish(inst); + return true; + } + + private synchronized void update_instruction_status() { + Date date = new Date(); + if (date.getTime() - this.instruction_update_time.getTime() < (long) this.instruction_update_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_update_time_out); + + } else { + this.instruction_update_time = date; + //更改任务状态 + if (task > 0 && action == 2) { + //inst_message + Instruction inst1 = checkInst(); + if (inst1 != null) { + if (StrUtil.equals(inst1.getInstruction_status(), "0")) { + inst1.setInstruction_status("1"); + inst1.setExecute_device_code(this.device_code); + instructionService.update(inst1); + } + } + } + + if (task > 0 && action == 3) { + //inst_message + Instruction inst1 = checkInst(); + if (inst1 != null) { + if (StrUtil.equals(inst1.getInstruction_status(), "0")) { + inst1.setInstruction_status("1"); + inst1.setExecute_device_code(this.device_code); + instructionService.update(inst1); + } + } + } + + if (task > 0 && action == 4) { + //inst_message + Instruction inst1 = checkInst(); + if (inst1 != null) { + if (StrUtil.equals(inst1.getInstruction_status(), "0")) { + inst1.setInstruction_status("1"); + inst1.setExecute_device_code(this.device_code); + instructionService.update(inst1); + } + } + } + + if (task > 0 && action == 5) { + //inst_message + Instruction inst1 = checkInst(); + if (inst1 != null) { + if (StrUtil.equals(inst1.getInstruction_status(), "0")) { + inst1.setInstruction_status("1"); + inst1.setExecute_device_code(this.device_code); + instructionService.update(inst1); + } + } + } + + + //放货完成 + if (mode == 3 && action == 6 && move == 0 && task > 0) { + Instruction inst2 = checkInst(); + if (inst2 != null) { + try { + finish_instruction(inst2); + this.writing("to_command", "6"); + } catch (Exception e) { + e.printStackTrace(); + } + feedMessage = ""; + } + } else { + feedMessage = "行架机械手:"; + if (mode != 3) { + feedMessage = feedMessage + "工作模式(mode)不为运行中状态,"; + } + if (action != 6) { + feedMessage = feedMessage + "动作信号(action)不为放货完成状态,"; + } + if (move != 0) { + feedMessage = feedMessage + "光电信号(move)不为无货状态,"; + } + if (task == 0) { + feedMessage = feedMessage + "当前上报任务号(task)不应该为0。"; + } + } + + + } + } + + public Instruction checkInst() { + if (ObjectUtil.isNotEmpty(this.inst)) { + if (this.task > 0) { + if (this.inst.getInstruction_code().equals(String.valueOf(this.task))) { + return this.inst; + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + } + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + return null; + } + + + public boolean exe_error() { + if (this.error == 0) { + return true; + } else { + log.debug("设备报警"); + return false; + } + } + + //将扩展表中的字符串数据转换成集合 + public List getExtraDeviceCodes(String extraName) { + String extraValue = (String) this.getDevice().getExtraValue().get(extraName); + if (StrUtil.isEmpty(extraValue)) { + return new ArrayList<>(); + } + String devicesString = extraValue.substring(1, extraValue.length() - 1); + List devicesList = new ArrayList<>(); + String[] devices = devicesString.split(","); + for (int i = 0; i < devices.length; i++) { + String s = devices[i].replace("\"", "").replace("\"", ""); + devicesList.add(s); + } + return devicesList; + } + + public List sortTask(List taskDtos) { + Collections.sort(taskDtos, new Comparator() { + @Override + public int compare(TaskDto t1, TaskDto t2) { + //优先级从大到小 + int i = t2.getPriority().compareTo(t1.getPriority()); + //如果优先级相等 + if (i == 0) { + //时间从早到晚 + i = t1.getCreate_time().compareTo(t2.getCreate_time()); + } + return i; + } + }); + return taskDtos; + } + + public void writing(String param, String value) { + + String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + + "." + param; + //String opcservcerid = this.getDevice().getOpc_server_id(); +//Server server = ReadUtil.getServer(opcservcerid); + Map itemMap = new HashMap(); + + itemMap.put(to_param, Integer.parseInt(value)); +// itemMap.put(to_param, Integer.parseInt(value)); + this.control(itemMap); + logServer.deviceExecuteLog(device_code, "", "", "下发电气信号设备号:" + device_code + ",下发电气:" + to_param + ",下发电气值:" + value); + } + + /** + * 申请任务 + * + * @param + */ + public synchronized boolean applyTask() { + Date date = new Date(); + if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + return false; + } else { + this.instruction_require_time = date; + //抓取工位 + if (ObjectUtil.isEmpty(getDeviceCodeList)) { + getDeviceCodeList = this.getExtraDeviceCodes("get_device_code"); + } + //放货工位 + if (ObjectUtil.isEmpty(putDeviceCodeList)) { + putDeviceCodeList = this.getExtraDeviceCodes("put_device_code"); + } + TaskDto task = null; + for (int i = 0; i < getDeviceCodeList.size(); i++) { + String startDeviceCode = getDeviceCodeList.get(i); + List taskDtos = taskserver.queryTaskByDeviceCodeAndStatus(startDeviceCode); + if (ObjectUtil.isNotEmpty(taskDtos)) { + //按照优先级排序 优先级相等按照创建时间排序 + taskDtos = this.sortTask(taskDtos); + TaskDto taskDto = taskDtos.get(0); + + //存在行架->暂存的AGV任务 需要过滤 + // 9 行架任务 + if (!StrUtil.equals(taskDto.getTask_type(), "9")) { + taskDto = null; + continue; + } + Instruction instruction = instructionService.findByTaskcodeAndStatus(taskDto.getTask_code()); + String start_device_code = instruction.getStart_device_code(); + String next_device_code = instruction.getNext_device_code(); + Device nextdevice = deviceAppService.findDeviceByCode(next_device_code); + Device startdevice = deviceAppService.findDeviceByCode(start_device_code); + SiemensConveyorDeviceDriver siemensConveyorDeviceDriver; + StandardOrdinarySiteDeviceDriver standardOrdinarySiteDeviceDriver; + instruction.setInstruction_status("1"); + instruction.setUpdate_time(DateUtil.now()); + instructionService.update(instruction); + Device startDevice = deviceAppService.findDeviceByCode(start_device_code); + Device nextDevice = deviceAppService.findDeviceByCode(next_device_code); + if (ObjectUtil.isEmpty(startDevice.getExtraValue().get("address"))) { + throw new BadRequestException("设备:" + startDevice.getDevice_code() + "未设置电气调度号!"); + } + if (ObjectUtil.isEmpty(nextDevice.getExtraValue().get("address"))) { + throw new BadRequestException("设备:" + nextDevice.getDevice_code() + "未设置电气调度号!"); + } + String start_addr = startDevice.getExtraValue().get("address").toString(); + String next_addr = nextDevice.getExtraValue().get("address").toString(); + logServer.deviceExecuteLog(device_code, "", "", "当前设备:" + device_code + ",下发指令:" + + instruction.getInstruction_code() + ",指令起点:" + instruction.getStart_device_code() + + ",指令终点:" + instruction.getNext_device_code()); + Map map = new LinkedHashMap<>(); + map.put("to_command", "1"); + map.put("to_onset", start_addr); + map.put("to_task", instruction.getInstruction_code()); + map.put("to_target", next_addr); + this.writing(map); + this.setRequireSucess(true); + return true; + } else { + List taskDtoList = taskserver.queryTaskByDeviceCode(startDeviceCode); + if (ObjectUtil.isNotEmpty(taskDtoList)) { + for (int j = 0; j < taskDtoList.size(); j++) { + //按照优先级排序 优先级相等按照创建时间排序 + taskDtoList = this.sortTask(taskDtoList); + task = taskDtoList.get(j); + // 9 行架任务 + if (!StrUtil.equals(task.getTask_type(), "9")) { + task = null; + continue; + } + if (ObjectUtil.isNotEmpty(task)) break; + } + } + } + } + if (!ObjectUtil.isEmpty(task)) { + Device nextdevice = deviceAppService.findDeviceByCode(task.getNext_device_code()); + Device startdevice = deviceAppService.findDeviceByCode(task.getStart_device_code()); + StandardOrdinarySiteDeviceDriver standardOrdinarySiteDeviceDriver; + SiemensConveyorDeviceDriver siemensConveyorDeviceDriver; + if (startdevice.getDeviceDriver() instanceof SiemensConveyorDeviceDriver) { + siemensConveyorDeviceDriver = (SiemensConveyorDeviceDriver) startdevice.getDeviceDriver(); + if (siemensConveyorDeviceDriver.getMove() != 1) { + notCreateInstMessage = "就绪任务未创建指令原因->取货位-分切输送线出口:" + siemensConveyorDeviceDriver.getDevice_code() + "光电无货,无法生成指令!"; + return false; + } + } + String taskid = task.getTask_id(); + String taskcode = task.getTask_code(); + String vehiclecode = task.getVehicle_code(); + String priority = task.getPriority(); + String start_point_code = task.getStart_point_code(); + String start_device_code = task.getStart_device_code(); + String route_plan_code = task.getRoute_plan_code(); + String next_point_code = task.getNext_point_code(); + String next_device_code = task.getNext_device_code(); + + Instruction instdto = new Instruction(); + instdto.setInstruction_id(IdUtil.simpleUUID()); + instdto.setRoute_plan_code(route_plan_code); + instdto.setRemark(task.getRemark()); + instdto.setMaterial(task.getMaterial()); + instdto.setQuantity(task.getQuantity()); + instdto.setTask_id(taskid); + instdto.setTask_code(taskcode); + instdto.setVehicle_code(vehiclecode); + String now = DateUtil.now(); + instdto.setCreate_time(now); + instdto.setCreate_by("auto"); + instdto.setStart_device_code(start_device_code); + instdto.setNext_device_code(next_device_code); + instdto.setStart_point_code(start_point_code); + instdto.setNext_point_code(next_point_code); + instdto.setPriority(priority); + instdto.setInstruction_status("0"); + instdto.setExecute_device_code(start_point_code); + + try { + instructionService.create(instdto); + } catch (Exception e) { + notCreateInstMessage = e.getMessage(); + logServer.deviceExecuteLog(this.getDevice_code(), "", "", "创建指令时出现异常:" + e.getMessage()); + return false; + } + //创建指令后修改任务状态 + task.setTask_status("1"); + task.setUpdate_time(DateUtil.now()); + taskserver.update(task); + + Device startDevice = deviceAppService.findDeviceByCode(instdto.getStart_device_code()); + Device nextDevice = deviceAppService.findDeviceByCode(instdto.getNext_device_code()); + if (ObjectUtil.isEmpty(startDevice.getExtraValue().get("address"))) { + notCreateInstMessage = "设备:" + startDevice.getDevice_code() + "未设置电气调度号!"; + logServer.deviceExecuteLog(this.getDevice_code(), "", "", "设备:" + startDevice.getDevice_code() + "未设置电气调度号!"); + throw new BadRequestException("设备:" + startDevice.getDevice_code() + "未设置电气调度号!"); + } + if (ObjectUtil.isEmpty(nextDevice.getExtraValue().get("address"))) { + notCreateInstMessage = "设备:" + nextDevice.getDevice_code() + "未设置电气调度号!"; + logServer.deviceExecuteLog(this.getDevice_code(), "", "", "设备:" + nextDevice.getDevice_code() + "未设置电气调度号!"); + throw new BadRequestException("设备:" + nextDevice.getDevice_code() + "未设置电气调度号!"); + } + String start_addr = startDevice.getExtraValue().get("address").toString(); + String next_addr = nextDevice.getExtraValue().get("address").toString(); + logServer.deviceExecuteLog(device_code, "", "", "当前设备:" + device_code + ",下发指令:" + + instdto.getInstruction_code() + ",指令起点:" + instdto.getStart_device_code() + + ",指令终点:" + instdto.getNext_device_code()); + this.writing("to_command", "1"); + this.writing("to_onset", start_addr); + this.writing("to_target", next_addr); + this.writing("to_task", instdto.getInstruction_code()); + this.writing("to_task_type", "1"); + this.setRequireSucess(true); + notCreateInstMessage = ""; + notCreateTaskMessage = ""; + } else { + notCreateInstMessage = "未找到关联设备的任务,指令无法创建"; + } + return true; + } + } +} + diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/ItemProtocol.java new file mode 100644 index 000000000..ed425f955 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/ItemProtocol.java @@ -0,0 +1,224 @@ +package org.nl.acs.device_driver.basedriver.indoor_manipulator; + +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; + + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Data +public class ItemProtocol { + //心跳 + public static String item_heartbeat = "heartbeat"; + //工作模式 + public static String item_mode = "mode"; + //光电信号 + public static String item_move = "move"; + //动作信号 + public static String item_action = "action"; + //行走列 + public static String item_walk_y = "walk_y"; + //任务号 + public static String item_task = "task"; + //报警 + public static String item_error = "error"; + //x轴坐标 + public static String item_x_position = "x_position"; + //y轴坐标 + public static String item_y_position = "y_position"; + //气胀轴尺寸 + public static String item_inflatable_shaft_size = "inflatable_shaft_size"; + + //下发命令 + public static String item_to_command = "to_command"; + //下发起始站 + public static String item_to_onset = "to_onset"; + //下发目标站 + public static String item_to_target = "to_target"; + //下发任务号 + public static String item_to_task = "to_task"; + //反馈放货点 + public static String item_to_putpoint = "to_putpoint"; + //反馈新取货点 + public static String item_to_new_getpoint = "to_new_getpoint"; + //反馈二次放货点 + public static String item_to_two_putpoint = "to_two_putpoint"; + //下发任务类型 + public static String item_to_task_type = "to_task_type"; + //气胀轴代数 + public static String item_inflatableShaftVersion = "inflatableShaftVersion"; + //套管数量 + public static String item_tube_num = "tube_num"; + //是否套轴 + public static String item_is_wrapped = "is_wrapped"; + + + private IndoorManipulatorDeviceDriver driver; + + public ItemProtocol(IndoorManipulatorDeviceDriver driver) { + this.driver = driver; + } + + public int getHeartbeat() { + return this.getOpcIntegerValue(item_heartbeat); + } + + public int getMode() { + return this.getOpcIntegerValue(item_mode); + } + + public int getMove() { + return this.getOpcIntegerValue(item_move); + } + + public int getAction() { + return this.getOpcIntegerValue(item_action); + } + + public int getWalk_y() { + return this.getOpcIntegerValue(item_walk_y); + } + + public int getInflatable_shaft_size() { + return this.getOpcIntegerValue(item_inflatable_shaft_size); + } + + public int getError() { + return this.getOpcIntegerValue(item_error); + } + + public int getTask() { + return this.getOpcIntegerValue(item_task); + } + + public int getTo_command() { + return this.getOpcIntegerValue(item_to_command); + } + + public int getTo_target() { + return this.getOpcIntegerValue(item_to_target); + } + + public int getTo_task() { + return this.getOpcIntegerValue(item_to_task); + } + + public int getTo_onset() { + return this.getOpcIntegerValue(item_to_onset); + } + + public float getX_position() { + return this.getOpcFloatValue(item_x_position); + } + + public float getY_position() { + return this.getOpcFloatValue(item_y_position); + } + + public int getTo_putpoint() { + return this.getOpcIntegerValue(item_to_putpoint); + } + + public int getTo_new_getpoint() { + return (int) this.getOpcIntegerValue(item_to_new_getpoint); + } + + public int getTo_two_putpoint() { + return this.getOpcIntegerValue(item_to_two_putpoint); + } + + public int getTo_task_type() { + return this.getOpcIntegerValue(item_to_task_type); + } + + public int getTube_num() { + return this.getOpcIntegerValue(item_tube_num); + } + + public int getInflatableShaftVersion() { + return this.getOpcIntegerValue(item_inflatableShaftVersion); + } + + public int getIs_wrapped() { + return this.getOpcIntegerValue(item_is_wrapped); + } + + + Boolean isonline; + + public int getOpcIntegerValue(String protocol) { + Integer value = this.driver.getIntegeregerValue(protocol); + if (value == null) { + // log.error(this.getDriver().getDeviceCode() + ":protocol " + protocol + " 信号同步异常!"); + setIsonline(false); + } else { + setIsonline(true); + return value; + } + return 0; + + } + public String getOpcStringValue(String protocol) { + String value = this.driver.getStringValue(protocol); + if (StrUtil.isEmpty(value)) { + + } else { + return value; + } + return "0"; + } + + public float getOpcFloatValue(String protocol) { + Float value = this.driver.getDoubleValue(protocol); + if (value == null) { + // log.error(this.getDriver().getDeviceCode() + ":protocol " + protocol + " 信号同步异常!"); + setIsonline(false); + } else { + setIsonline(true); + return value; + } + return 0; + + } + + public static List getReadableItemDtos() { + ArrayList list = new ArrayList<>(); + list.add(new ItemDto(item_heartbeat, "心跳", "DB1.B0")); + list.add(new ItemDto(item_mode, "工作模式", "DB1.B1")); + list.add(new ItemDto(item_move, "光电信号", "DB1.B2")); + list.add(new ItemDto(item_action, "动作信号", "DB1.B3")); + list.add(new ItemDto(item_walk_y, "行走列", "DB1.B4")); + list.add(new ItemDto(item_error, "报警信号", "DB1.B5")); + list.add(new ItemDto(item_task, "任务号", "DB1.D6")); + list.add(new ItemDto(item_x_position, "x坐标", "DB1.REAL10")); + list.add(new ItemDto(item_y_position, "y坐标", "DB1.REAL14")); + list.add(new ItemDto(item_inflatable_shaft_size, "气胀轴尺寸", "DB1.C1")); + return list; + } + + public static List getWriteableItemDtos() { + ArrayList list = new ArrayList<>(); + list.add(new ItemDto(item_to_command, "下发命令", "DB2.W0")); + list.add(new ItemDto(item_to_onset, "下发起始站", "DB2.W2")); + list.add(new ItemDto(item_to_target, "下发目标站", "DB2.W4")); + list.add(new ItemDto(item_to_task, "下发任务号", "DB2.D1")); + list.add(new ItemDto(item_to_putpoint, "反馈放货点", "DB2.D2")); + list.add(new ItemDto(item_to_new_getpoint, "反馈新取货点", "DB2.D3")); + list.add(new ItemDto(item_to_two_putpoint, "反馈二次放货点", "DB2.D4")); + list.add(new ItemDto(item_to_task_type, "下发任务类型", "DB2.D5")); + list.add(new ItemDto(item_inflatableShaftVersion, "气胀轴代数", "DB2.D6")); + list.add(new ItemDto(item_tube_num, "套管数量", "DB2.D7")); + list.add(new ItemDto(item_is_wrapped, "是否套轴", "DB2.D8")); + return list; + } + + @Override + public String toString() { + return ""; + } + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java new file mode 100644 index 000000000..9ee34077f --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionRequest.java @@ -0,0 +1,28 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +@Data +public class ApplyManipulatorActionRequest extends BaseRequest { + private String vehicle_code; + private String device_code; + /** + * 2-尺寸交互反馈,反馈任务类型 + * 3-反馈新放货点 + * 4-反馈新取货点 + * 5-反馈二次放货点 + */ + private String type; + + /** + * 任务号 + */ + private String task_code; + + /** + * 气胀轴尺寸 3/6寸 + */ + private String size; + + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java new file mode 100644 index 000000000..be4283be7 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/ApplyManipulatorActionResponse.java @@ -0,0 +1,48 @@ +package org.nl.acs.ext.wms.data; + +import lombok.Data; + +import java.util.HashMap; +import java.util.Map; + +@Data +public class ApplyManipulatorActionResponse extends BaseResponse { + + private Map data = new HashMap(); + + /** + * 放货点 + */ + private String put_device_code; + + /** + * 取货点 + */ + private String get_device_code; + + /** + * 二次放货点 + */ + private String put_device_code2; + + /** + * 下发的指令类型 + */ + private String detail_type; + + /** + * 气胀轴代数 + */ + private String version; + + /** + * 套管数量 + */ + private String bushing_num; + + /** + * 是否套管 + */ + private String is_bushing; + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/rest/AcsToWmsController.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/rest/AcsToWmsController.java index 35965e4a6..41b51958b 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/rest/AcsToWmsController.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/rest/AcsToWmsController.java @@ -9,6 +9,7 @@ import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.nl.acs.ext.wms.data.ApplyLabelingAndBindingRequest; +import org.nl.acs.ext.wms.data.ApplyManipulatorActionRequest; import org.nl.acs.ext.wms.data.LiKuApplyTaskRequest; import org.nl.acs.ext.wms.service.AcsToWmsService; import org.nl.modules.logging.InterfaceLogType; @@ -99,6 +100,13 @@ public class AcsToWmsController { return new ResponseEntity<>(acstowmsService.applyLabelingAndBindingRequest(param), HttpStatus.OK); } + @PostMapping("/applyManipulatorActionRequest") + @Log(value = "申请行架任务",isInterfaceLog = true,interfaceLogType= InterfaceLogType.ACS_TO_LMS) + @ApiOperation("申请行架任务") + public ResponseEntity applyManipulatorActionRequest(@RequestBody ApplyManipulatorActionRequest param) { + return new ResponseEntity<>(acstowmsService.applyManipulatorActionRequest(param), HttpStatus.OK); + } + @PostMapping("/liKuApplyTaskRequest") @Log(value = "立库申请任务",isInterfaceLog = true,interfaceLogType= InterfaceLogType.ACS_TO_LMS) @ApiOperation("立库申请任务") diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java index 8fab0c4a7..b5ec1fee7 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/AcsToWmsService.java @@ -106,4 +106,6 @@ public interface AcsToWmsService { HttpResponse shipDeviceUpdate(JSONObject param); void sendDeviceStatus(JSONObject param); + + ApplyManipulatorActionResponse applyManipulatorActionRequest(ApplyManipulatorActionRequest param); } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java index 69a717c7f..129e2bee9 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java @@ -414,6 +414,40 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { return null; } + @Override + public ApplyManipulatorActionResponse applyManipulatorActionRequest(ApplyManipulatorActionRequest param) { + try { + MDC.put(log_file_type, log_type); + ApplyManipulatorActionResponse applyManipulatorActionResponse = new ApplyManipulatorActionResponse(); + if (StrUtil.equals(paramService.findByCode(AcsConfig.HASWMS).getValue(), "1")) { + String wmsUrl = paramService.findByCode(AcsConfig.WMSURL).getValue(); + AddressDto addressDto = addressService.findByCode("applyLabelingAndBinding"); + String methods_url = addressDto.getMethods_url(); + String url = wmsUrl + methods_url; + log.info("ApplyManipulatorActionRequest----请求参数{}", param); + try { +// String result = ""; + String result = HttpRequest.post(url) + .body(JSON.toJSONString(param)) + .execute().body(); + JSONObject jsonObject = JSONObject.parseObject(result); + log.info("ApplyManipulatorActionResponse----返回参数{}", result); + applyManipulatorActionResponse = JSONObject.toJavaObject(jsonObject, ApplyManipulatorActionResponse.class); + } catch (Exception e) { + JSONObject map = new JSONObject(); + map.put("status", 400); + map.put("message", e.getMessage()); + return JSONObject.toJavaObject(map, ApplyManipulatorActionResponse.class); + } + } + return applyManipulatorActionResponse; + } finally { + MDC.remove(log_file_type); + } + + + } + @Override public ApplyLabelingAndBindingResponse applyLabelingAndBindingRequest(ApplyLabelingAndBindingRequest param) { try { diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/TaskService.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/TaskService.java index e8d5b91fa..70e9b8981 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/TaskService.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/TaskService.java @@ -127,6 +127,14 @@ public interface TaskService { */ List queryTaskByDeviceCodeAndStatus(String device_code); + /** + * 根据任务类型查询 + * @param task_type + * @return + */ + List queryTaskByType(String task_type); + + /** * 根据前工位取货点查找执行中的任务 * @param head_start_device_code diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java index e23b40625..d8d4e1284 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/impl/TaskServiceImpl.java @@ -402,6 +402,20 @@ public class TaskServiceImpl implements TaskService, ApplicationAutoInitial { return list; } + @Override + public List queryTaskByType(String task_type) { + List list = new ArrayList<>(); + Iterator iterator = tasks.iterator(); + while (iterator.hasNext()) { + TaskDto task = iterator.next(); + if (!StrUtil.equals(task.getTask_type(), task_type)) { + continue; + } + list.add(task); + } + return list; + } + public List queryTaskByStartAndIntStatus(String head_start_device_code) { List list = new ArrayList<>(); Iterator iterator = tasks.iterator(); diff --git a/acs/nladmin-ui/src/views/acs/device/config.vue b/acs/nladmin-ui/src/views/acs/device/config.vue index 8ccbaac84..11759bbb1 100644 --- a/acs/nladmin-ui/src/views/acs/device/config.vue +++ b/acs/nladmin-ui/src/views/acs/device/config.vue @@ -101,6 +101,7 @@ import standard_autodoor from '@/views/acs/device/driver/standard_autodoor' import lamp_three_color from '@/views/acs/device/driver/lamp_three_color' import paper_tube_conveyor from '@/views/acs/device/driver/paper_tube_conveyor' import device_status from '@/views/acs/device/driver/device_status' +import indoor_manipulator from '@/views/acs/device/driver/indoor_manipulator' export default { name: 'DeviceConfig', @@ -132,7 +133,8 @@ export default { standard_autodoor, lamp_three_color, paper_tube_conveyor, - device_status + device_status, + indoor_manipulator }, dicts: ['device_type'], mixins: [crud], diff --git a/acs/nladmin-ui/src/views/acs/device/driver/indoor_manipulator.vue b/acs/nladmin-ui/src/views/acs/device/driver/indoor_manipulator.vue new file mode 100644 index 000000000..f4fde1d6a --- /dev/null +++ b/acs/nladmin-ui/src/views/acs/device/driver/indoor_manipulator.vue @@ -0,0 +1,546 @@ + + + + + From d5c2a0bd3e2fff8b744a302965da60a1df5502d2 Mon Sep 17 00:00:00 2001 From: yanps Date: Tue, 7 Nov 2023 11:07:49 +0800 Subject: [PATCH 08/14] =?UTF-8?q?=E5=A5=97=E7=AE=A1=E5=B7=A5=E4=BD=8D?= =?UTF-8?q?=E9=A9=B1=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CasingStationConveyorDeviceDriver.java | 408 ++++++++++++++++++ .../CasingStationDefination.java | 59 +++ .../casing_station/ItemProtocol.java | 125 ++++++ .../basedriver/paper_tube_device2/Paper.java | 19 + 4 files changed, 611 insertions(+) create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationDefination.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java create mode 100644 acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java new file mode 100644 index 000000000..48c33ca87 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java @@ -0,0 +1,408 @@ +package org.nl.acs.device_driver.basedriver.casing_station; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSONObject; +import lombok.Data; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.agv.server.AgvService; +import org.nl.acs.device.service.DeviceService; +import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.RouteableDeviceDriver; +import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver; +import org.nl.acs.device_driver.driver.ExecutableDeviceDriver; +import org.nl.acs.ext.wms.data.ApplyPaperActionRequest; +import org.nl.acs.ext.wms.data.ApplyPaperActionResponse; +import org.nl.acs.ext.wms.service.AcsToWmsService; +import org.nl.acs.ext.wms.service.impl.AcsToWmsServiceImpl; +import org.nl.acs.history.ErrorUtil; +import org.nl.acs.history.service.DeviceErrorLogService; +import org.nl.acs.history.service.dto.DeviceErrorLogDto; +import org.nl.acs.history.service.impl.DeviceErrorLogServiceImpl; +import org.nl.acs.instruction.service.InstructionService; +import org.nl.acs.instruction.service.dto.Instruction; +import org.nl.acs.log.service.DeviceExecuteLogService; +import org.nl.acs.monitor.DeviceStageMonitor; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceAppService; +import org.nl.acs.route.service.RouteLineService; +import org.nl.acs.task.service.TaskService; +import org.nl.acs.task.service.dto.TaskDto; +import org.nl.modules.system.service.ParamService; +import org.nl.modules.wql.util.SpringContextHolder; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.*; + +/** + * 套管工位 + */ +@Slf4j +@Data +@RequiredArgsConstructor +public class CasingStationConveyorDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor { + protected ItemProtocol itemProtocol = new ItemProtocol(this); + @Autowired + DeviceAppService deviceAppservice = SpringContextHolder.getBean(DeviceAppService.class); + @Autowired + InstructionService instructionService = SpringContextHolder.getBean(InstructionService.class); + @Autowired + DeviceService deviceservice = SpringContextHolder.getBean(DeviceService.class); + @Autowired + TaskService taskserver = SpringContextHolder.getBean(TaskService.class); + @Autowired + RouteLineService routeLineService = SpringContextHolder.getBean(RouteLineService.class); + @Autowired + AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsServiceImpl.class); + @Autowired + ParamService paramService = SpringContextHolder.getBean(ParamService.class); + @Autowired + DeviceExecuteLogService logServer = SpringContextHolder.getBean(DeviceExecuteLogService.class); + @Autowired + AgvService agvService = SpringContextHolder.getBean(AgvService.class); + @Autowired + DeviceErrorLogService deviceErrorLogService = SpringContextHolder.getBean(DeviceErrorLogServiceImpl.class); + + private Date instruction_update_time = new Date(); + private Date require_apply_casing_time = new Date(); + private int instruction_update_time_out = 500; + private Date instruction_require_time = new Date(); + private Date instruction_finished_time = new Date(); + private Date instruction_apply_time = new Date(); + private int instruction_require_time_out = 3000; + + //心跳 + int heartbeat = 0; + int last_heartbeat = 0; + //工作模式 + int mode = 0; + int last_mode = 0; + //光电信号 + int move = 0; + int last_move = 0; + //托盘方向 + int carrier_direction = 0; + int last_carrier_direction = 0; + //报警 + int error = 0; + int last_error = 0; + //任务号 + int task = 0; + int last_task = 0; + + String material1 = null; + String last_material1 = null; + + String material2 = null; + String last_material2 = null; + + + //下发命令 + int to_command = 0; + int last_to_command = 0; + + //当前指令 + Instruction inst = null; + + Boolean isonline = true; + + Boolean iserror = false; + //请求成功标记 + Boolean requireSucess = false; + + String message = null; + String device_code; + + + @Override + public Device getDevice() { + return this.device; + } + + @Override + public void execute() { + try { + String message = null; + device_code = this.getDeviceCode(); + heartbeat = this.itemProtocol.getHeartbeat(); + mode = this.itemProtocol.getMode(); + move = this.itemProtocol.getMove(); + carrier_direction = this.itemProtocol.getCarrier_direction(); + error = this.itemProtocol.getError(); + task = this.itemProtocol.getTask(); + material1 = this.itemProtocol.getMaterial1(); + material2 = this.itemProtocol.getMaterial2(); + + to_command = this.itemProtocol.getTo_command(); + + + if (to_command != last_to_command) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_command:" + last_to_command + "->" + to_command); + } + if (!material1.equals(last_material1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material1:" + last_material1 + "->" + material1); + } + if (!material2.equals(last_material2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material2:" + last_material2 + "->" + material2); + } + + if (carrier_direction != last_carrier_direction) { + logServer.deviceItemValue(this.device_code, "carrier_direction", String.valueOf(carrier_direction)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号carrier_direction:" + last_carrier_direction + "->" + carrier_direction); + } + if (task != last_task) { + logServer.deviceItemValue(this.device_code, "task", String.valueOf(task)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号task:" + last_task + "->" + task); + } + if (error != last_error) { + if (error != 0) { + DeviceErrorLogDto dto = new DeviceErrorLogDto(); + dto.setDevice_code(device_code); + dto.setError_code(String.valueOf(error)); + String errorInfo = ErrorUtil.getDictDetail("ssx_error_type", String.valueOf(error)); + dto.setError_info(errorInfo); + deviceErrorLogService.create(dto); + } + logServer.deviceItemValue(this.device_code, "error", String.valueOf(error)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号error:" + last_error + "->" + error); + } + if (mode != last_mode) { + JSONObject param = new JSONObject(); + param.put("device_code", this.device_code); + param.put("mode", Math.min(mode, 3)); + param.put("device_name", this.getDevice().getDevice_name()); + param.put("device_type", "1"); + param.put("product_area", paramService.findByCode("productArea").getValue()); + acsToWmsService.sendDeviceStatus(param); + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode + "复位请求标记:" + requireSucess); + logServer.deviceExecuteLog(this.device_code, "", "", "信号mode:" + last_mode + "->" + mode); + } + if (move != last_move) { + logServer.deviceItemValue(this.device_code, "move", String.valueOf(move)); + logServer.deviceExecuteLog(this.device_code, "", "", "信号move:" + last_move + "->" + move); + } + + if (move != 0 && task > 1) { + update_instruction_status(); + } + + } catch (Exception var17) { + var17.printStackTrace(); + logServer.deviceExecuteLog(this.device_code, "", "", "读取信号值时出现异常:" + var17.getMessage() + ",this.itemProtocol is null:" + ObjectUtil.isEmpty(this.itemProtocol)); + } + + if (mode == 0) { + this.setIsonline(false); + message = "未联机"; + } else if (error != 0) { + this.setIserror(true); + message = "有报警"; + } else { + this.setIsonline(true); + this.setIserror(false); + message = ""; + Instruction instruction = null; + List toInstructions; + + //纸管库申请任务 + switch (mode) { + case 1: + log.debug("弃用(留作兼容)"); + break; + case 2: + //申请任务 + /*if (move > 0 && !requireSucess) { + instruction_require(); + }*/ + break; + case 3: + log.info("运行中"); + break; + default: + if (move == 1 && !requireSucess) { + //申请套管校验 + apply_for_casing_inspection(material1, material2); + } + break; + } + } + last_heartbeat = heartbeat; + last_mode = mode; + last_move = move; + last_error = error; + last_carrier_direction = carrier_direction; + last_task = task; + last_material1 = material1; + last_material2 = material2; + last_to_command = to_command; + } + + + /** + * 更新指令状态 + */ + public synchronized void update_instruction_status() throws Exception { + Date date = new Date(); + if (date.getTime() - this.instruction_update_time.getTime() < (long) this.instruction_update_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_update_time_out); + + } else { + this.instruction_update_time = date; + inst = checkInst(); + if (inst != null) { + if (StrUtil.equals(inst.getInstruction_status(), "0") && StrUtil.equals(this.getDeviceCode(), inst.getStart_device_code())) { + inst.setInstruction_status("1"); + inst.setExecute_device_code(this.device_code); + instructionService.update(inst); + logServer.deviceExecuteLog(device_code, "", "", "入库输送线任务开始反馈执行中状态,反馈成功,指令号:" + task); + } + if (StrUtil.equals(inst.getInstruction_status(), "1") || StrUtil.equals(inst.getInstruction_status(), "0")) { + if (StrUtil.equals(this.getDeviceCode(), inst.getNext_device_code())) { + inst.setExecute_device_code(this.device_code); + finish_instruction(); + logServer.deviceExecuteLog(device_code, "", "", "入库输送线任务开始反馈完成状态,反馈成功,指令号:" + task); + } + } + } + } + } + + /** + * 申请套管校验 + */ + public synchronized void apply_for_casing_inspection(String material1, String material2) { + Date date = new Date(); + if (date.getTime() - this.require_apply_casing_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + } else { + this.require_apply_casing_time = date; + ApplyPaperActionRequest applyPaperActionRequest = new ApplyPaperActionRequest(); + applyPaperActionRequest.setDevice_code(this.device_code); + applyPaperActionRequest.setType("2"); + applyPaperActionRequest.setTask_code(String.valueOf(task)); + //获取出库顺序 + applyPaperActionRequest.setMaterial1(material1); + applyPaperActionRequest.setMaterial2(material2); + ApplyPaperActionResponse applyPaperActionResponse = acsToWmsService.applyPaperActionRequest(applyPaperActionRequest); + Map map = new HashMap(); + if (applyPaperActionResponse.getstatus() == 200) { + map.put("code", "to_command"); + map.put("value", "4"); + this.writing(map); + requireSucess = true; + logServer.deviceExecuteLog(this.device_code, "", "", "申请套管,返回参数:" + applyPaperActionResponse); + message = "申请套管成功"; + } else { + message = applyPaperActionResponse.getMessage(); + map.put("code", "to_command"); + map.put("value", "5"); + this.writing(map); + requireSucess = false; + message = "纸管不匹配"; + logServer.deviceExecuteLog(this.device_code, "", "", "申请套管,返回参数:" + applyPaperActionResponse); + } + } + } + + + /** + * 申请任务 + */ + public synchronized void instruction_require() { + Date date = new Date(); + if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) { + log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_require_time_out); + return; + } else { + //没有就绪状态的任务,查询就绪状态的指令 + TaskDto taskdto = taskserver.findByStartCodeAndReady(device_code); + Instruction inst = instructionService.findByDeviceCodeFromCache(this.device_code); + if (ObjectUtil.isNull(taskdto) && ObjectUtil.isNotNull(inst)) { + + } + } + } + + /** + * 完成指令 + * + * @return + * @throws Exception + */ + public synchronized boolean finish_instruction() throws Exception { + instructionService.finish(inst); + return true; + } + + @Override + public JSONObject getDeviceStatusName() throws Exception { + return null; + } + + @Override + public void setDeviceStatus(JSONObject data) { + + } + + public void writing(List list) { + Map itemMap = new HashMap(); + for (int i = 0; i < list.size(); i++) { + Object ob = list.get(i); + JSONObject json = (JSONObject) JSONObject.toJSON(ob); + if (!StrUtil.isEmpty(json.getString("value"))) { + String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + + "." + json.getString("code"); + itemMap.put(to_param, json.getString("value")); + } + } + logServer.deviceExecuteLog(device_code, "", "", "下发电气信号:" + itemMap); + try { + this.checkcontrol(itemMap); + } catch (Exception e) { + e.printStackTrace(); + try { + this.checkcontrol(itemMap); + } catch (Exception e1) { + e1.printStackTrace(); + } + } + } + + public void writing(Map map) { + DeviceExecuteLogService logServer = SpringContextHolder.getBean("deviceExecuteLogServiceImpl"); + Map itemMap = new LinkedHashMap<>(); + map.forEach((key, value) -> { + if (ObjectUtil.isNotEmpty(value)) { + itemMap.put(getToParam() + key, value); + } + }); + if (ObjectUtil.isNotEmpty(itemMap)) { + this.control(itemMap); + logServer.deviceExecuteLog(this.getDevice().getDevice_code(), "", "", "下发多个电气信号:" + itemMap); + } + } + + public String getToParam() { + return this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code() + "."; + } + + public Instruction checkInst() { + if (ObjectUtil.isNotEmpty(this.inst)) { + if (this.task > 0) { + if (this.inst.getInstruction_code().equals(String.valueOf(this.task))) { + return this.inst; + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + } + } else { + inst = instructionService.findByCodeFromCache(String.valueOf(task)); + return inst; + } + return null; + } +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationDefination.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationDefination.java new file mode 100644 index 000000000..158e279d5 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationDefination.java @@ -0,0 +1,59 @@ +package org.nl.acs.device_driver.basedriver.casing_station; + +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; +import org.nl.acs.device_driver.DeviceDriver; +import org.nl.acs.device_driver.defination.OpcDeviceDriverDefination; +import org.nl.acs.opc.Device; +import org.nl.acs.opc.DeviceType; +import org.springframework.stereotype.Service; + +import java.util.LinkedList; +import java.util.List; + +/** + * 套管工位 + */ +@Service +public class CasingStationDefination implements OpcDeviceDriverDefination { + @Override + public String getDriverCode() { + return "casing_station"; + } + + @Override + public String getDriverName() { + return "套管工位"; + } + + @Override + public String getDriverDescription() { + return "套管工位"; + } + + @Override + public DeviceDriver getDriverInstance(Device device) { + return (new CasingStationConveyorDeviceDriver().setDevice(device).setDriverDefination(this)); + } + + @Override + public Class getDeviceDriverType() { + return CasingStationConveyorDeviceDriver.class; + } + + @Override + public List getFitDeviceTypes() { + List types = new LinkedList(); + types.add(DeviceType.conveyor); + return types; + } + + @Override + public List getReadableItemDtos() { + return ItemProtocol.getReadableItemDtos(); + } + + @Override + public List getWriteableItemDtos() { + return ItemProtocol.getWriteableItemDtos(); + } +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java new file mode 100644 index 000000000..feb67bc19 --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java @@ -0,0 +1,125 @@ +package org.nl.acs.device_driver.basedriver.casing_station; + +import cn.hutool.core.util.StrUtil; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.nl.acs.device.device_driver.standard_inspect.ItemDto; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Data +public class ItemProtocol { + + //心跳 + public static String item_heartbeat = "heartbeat"; + //工作模式 + public static String item_mode = "mode"; + //光电信号 + public static String item_move = "move"; + //托盘方向 + public static String item_carrier_direction = "carrier_direction"; + //报警 + public static String item_error = "error"; + //任务号 + public static String item_task = "task"; + //物料1 + public static String item_material1 = "material1"; + //物料2 + public static String item_material2 = "material2"; + + //下发命令 + public static String item_to_command = "to_command"; + + public ItemProtocol(CasingStationConveyorDeviceDriver driver) { + this.driver = driver; + } + + public int getHeartbeat() { + return this.getOpcIntegerValue(item_heartbeat); + } + + public int getMode() { + return this.getOpcIntegerValue(item_mode); + } + + public int getMove() { + return this.getOpcIntegerValue(item_move); + } + + public int getCarrier_direction() { + return this.getOpcIntegerValue(item_carrier_direction); + } + + public int getError() { + return this.getOpcIntegerValue(item_error); + } + + public int getTask() { + return this.getOpcIntegerValue(item_task); + } + + public String getMaterial1() { + return this.getOpcStringValue(item_material1); + } + + public String getMaterial2() { + return this.getOpcStringValue(item_material2); + } + + public int getTo_command() { + return this.getOpcIntegerValue(item_to_command); + } + + Boolean isonline; + + private CasingStationConveyorDeviceDriver driver; + + public int getOpcIntegerValue(String protocol) { + Integer value = this.driver.getIntegeregerValue(protocol); + if (value == null) { + setIsonline(false); + } else { + setIsonline(true); + return value; + } + return 0; + + } + + public String getOpcStringValue(String protocol) { + String value = this.driver.getStringValue(protocol); + if (StrUtil.isBlank(value)) { + + } else { + return value; + } + return "0"; + } + + public static List getReadableItemDtos() { + ArrayList list = new ArrayList(); + list.add(new ItemDto(item_heartbeat, "心跳", "DB101.W0")); + list.add(new ItemDto(item_mode, "工作模式", "DB101.W2")); + list.add(new ItemDto(item_move, "光电信号", "DB101.W3")); + list.add(new ItemDto(item_carrier_direction, "托盘方向", "DB101.W4")); + list.add(new ItemDto(item_error, "报警", "DB101.W58")); + list.add(new ItemDto(item_task, "任务号", "DB101.W6")); + list.add(new ItemDto(item_material1, "物料1", "DB101.W7")); + list.add(new ItemDto(item_material2, "物料1", "DB101.W8")); + return list; + } + + public static List getWriteableItemDtos() { + ArrayList list = new ArrayList(); + list.add(new ItemDto(item_to_command, "下发命令", "DB102.W4")); + return list; + } + + @Override + public String toString() { + return ""; + } + +} diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java new file mode 100644 index 000000000..e088a576e --- /dev/null +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java @@ -0,0 +1,19 @@ +package org.nl.acs.device_driver.basedriver.paper_tube_device2; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@NoArgsConstructor +@AllArgsConstructor +public class Paper implements Serializable { + //设备号 + private String device_code; + // + private String meterial_code; + private String qty; + +} From fa1a3a4e6887ec9deb847a308e9fd3abb8c1b08a Mon Sep 17 00:00:00 2001 From: tuqiang <437016993@qq.com> Date: Tue, 7 Nov 2023 12:37:07 +0800 Subject: [PATCH 09/14] fix --- .../IndoorManipulatorDeviceDriver.java | 34 ++++++++++++++++--- .../org/nl/acs/task/service/dto/TaskDto.java | 26 ++++++++++++++ 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java index a94e8d44e..9693e066f 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/indoor_manipulator/IndoorManipulatorDeviceDriver.java @@ -728,8 +728,20 @@ public class IndoorManipulatorDeviceDriver extends AbstractOpcDeviceDriver imple logServer.deviceExecuteLog(device_code, "", "", "当前设备:" + device_code + ",下发指令:" + instruction.getInstruction_code() + ",指令起点:" + instruction.getStart_device_code() + ",指令终点:" + instruction.getNext_device_code()); + String is_bushing = taskDto.getIs_bushing(); + String version = taskDto.getVersion(); + String bushing_num = taskDto.getBushing_num(); + Map map = new LinkedHashMap<>(); map.put("to_command", "1"); + if (action==2) { + map.put("inflatableShaftVersion", version); + map.put("tube_num", bushing_num); + map.put("is_wrapped", is_bushing); + } + if (action==1||action==5){ + map.put("to_task_type", String.valueOf(action)); + } map.put("to_onset", start_addr); map.put("to_task", instruction.getInstruction_code()); map.put("to_target", next_addr); @@ -824,11 +836,23 @@ public class IndoorManipulatorDeviceDriver extends AbstractOpcDeviceDriver imple logServer.deviceExecuteLog(device_code, "", "", "当前设备:" + device_code + ",下发指令:" + instdto.getInstruction_code() + ",指令起点:" + instdto.getStart_device_code() + ",指令终点:" + instdto.getNext_device_code()); - this.writing("to_command", "1"); - this.writing("to_onset", start_addr); - this.writing("to_target", next_addr); - this.writing("to_task", instdto.getInstruction_code()); - this.writing("to_task_type", "1"); + String is_bushing = task.getIs_bushing(); + String version = task.getVersion(); + String bushing_num = task.getBushing_num(); + Map map = new LinkedHashMap<>(); + map.put("to_command", "1"); + if (action==2) { + map.put("inflatableShaftVersion", version); + map.put("tube_num", bushing_num); + map.put("is_wrapped", is_bushing); + } + if (action==1||action==5){ + map.put("to_task_type", String.valueOf(action)); + } + map.put("to_onset", start_addr); + map.put("to_task", instdto.getInstruction_code()); + map.put("to_target", next_addr); + this.writing(map); this.setRequireSucess(true); notCreateInstMessage = ""; notCreateTaskMessage = ""; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java index 7c5875db1..f770f33b3 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java @@ -307,6 +307,32 @@ public class TaskDto implements Serializable { */ private String next_height = "0"; + /** + * 行架任务类型 + */ + private String truss_type; + + + /** + * 气胀轴代数 + */ + private String version; + + /** + * 是否套管 + */ + private String is_bushing; + + /** + * 套管数量 + */ + private String bushing_num; + + + + //array device_code\material_code\qty + private String paper_array; + @Override public String toString(){ From 7b142f95c47f673c4468468406d1d1c01e48ab6e Mon Sep 17 00:00:00 2001 From: liuxy Date: Tue, 7 Nov 2023 16:10:19 +0800 Subject: [PATCH 10/14] =?UTF-8?q?add:=20=E6=96=B0=E5=A2=9E=E6=88=90?= =?UTF-8?q?=E5=93=81=E6=8A=A5=E5=BA=9F=E5=AE=A1=E6=A0=B8=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/nl/wms/basedata/st/wql/stivt.xls | Bin 309248 -> 317440 bytes .../instor/rest/ProductScrapController.java | 79 +++ .../instor/service/ProductScrapService.java | 52 ++ .../service/impl/ProductScrapServiceImpl.java | 287 +++++++++++ .../st/instor/wql/QST_IVT_PRODUCTSCRAP.wql | 112 +++++ .../wms/st/inStor/productscrap/AddDialog.vue | 476 ++++++++++++++++++ .../wms/st/inStor/productscrap/AddDtl.vue | 231 +++++++++ .../wms/st/inStor/productscrap/index.vue | 290 +++++++++++ .../st/inStor/productscrap/productscrap.js | 55 ++ 9 files changed, 1582 insertions(+) create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/st/instor/rest/ProductScrapController.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/ProductScrapService.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/impl/ProductScrapServiceImpl.java create mode 100644 lms/nladmin-system/src/main/java/org/nl/wms/st/instor/wql/QST_IVT_PRODUCTSCRAP.wql create mode 100644 lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue create mode 100644 lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDtl.vue create mode 100644 lms/nladmin-ui/src/views/wms/st/inStor/productscrap/index.vue create mode 100644 lms/nladmin-ui/src/views/wms/st/inStor/productscrap/productscrap.js diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/basedata/st/wql/stivt.xls b/lms/nladmin-system/src/main/java/org/nl/wms/basedata/st/wql/stivt.xls index e0cc1c651e57681a5203d6f26d4440dd605d2e00..bc5a57a9dbb2f14d99644c6248aea364c27be389 100644 GIT binary patch delta 18167 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 QO2$+P9-6?lAE+Jv510*UsQ>@~ delta 12355 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 XdKtlIcTdy*`xkNT#JxA1WhMUu$3p5r diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/rest/ProductScrapController.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/rest/ProductScrapController.java new file mode 100644 index 000000000..34025866a --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/rest/ProductScrapController.java @@ -0,0 +1,79 @@ +package org.nl.wms.st.instor.rest; + +import com.alibaba.fastjson.JSONObject; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.modules.logging.annotation.Log; +import org.nl.wms.st.instor.service.ProductScrapService; +import org.springframework.data.domain.Pageable; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.Map; + +@RestController +@RequiredArgsConstructor +@Api(tags = "成品报废审核") +@RequestMapping("/api/productscrap") +@Slf4j +public class ProductScrapController { + private final ProductScrapService productScrapService; + + @GetMapping + @Log("查询成品报废审核单") + @ApiOperation("查询成品报废审核单") + public ResponseEntity query(@RequestParam Map whereJson, Pageable page) { + return new ResponseEntity<>(productScrapService.pageQuery(whereJson, page), HttpStatus.OK); + } + + @GetMapping("/getOutBillDtl") + @Log("查询明细") + @ApiOperation("查询明细") + public ResponseEntity getOutBillDtl(@RequestParam Map whereJson) { + return new ResponseEntity<>(productScrapService.getOutBillDtl(whereJson), HttpStatus.OK); + } + + @Log("删除") + @ApiOperation("删除") + @DeleteMapping + public ResponseEntity delete(@RequestBody Long[] ids) { + productScrapService.deleteAll(ids); + return new ResponseEntity<>(HttpStatus.OK); + } + + @PutMapping + @Log("修改") + @ApiOperation("修改") + public ResponseEntity update(@RequestBody JSONObject whereJson) { + productScrapService.update(whereJson); + return new ResponseEntity<>(HttpStatus.NO_CONTENT); + } + + @PostMapping() + @Log("新增") + @ApiOperation("新增") + public ResponseEntity insertDtl(@RequestBody JSONObject whereJson) { + productScrapService.insertDtl(whereJson); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PostMapping("/auditPass") + @Log("审核通过") + @ApiOperation("审核通过") + public ResponseEntity auditPass(@RequestBody JSONObject whereJson) { + productScrapService.auditPass(whereJson); + return new ResponseEntity<>(HttpStatus.CREATED); + } + + @PostMapping("/auditOut") + @Log("不通过") + @ApiOperation("不通过") + public ResponseEntity auditOut(@RequestBody JSONObject whereJson) { + productScrapService.auditOut(whereJson); + return new ResponseEntity<>(HttpStatus.CREATED); + } + +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/ProductScrapService.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/ProductScrapService.java new file mode 100644 index 000000000..b4452140e --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/ProductScrapService.java @@ -0,0 +1,52 @@ +package org.nl.wms.st.instor.service; + +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import org.springframework.data.domain.Pageable; + +import java.util.Map; + +public interface ProductScrapService { + /** + * 查询数据分页 + * + * @param whereJson 条件 + * @param page 分页参数 + * @return Map + */ + Map pageQuery(Map whereJson, Pageable page); + + /** + * 多选删除 + * @param ids / + */ + void deleteAll(Long[] ids); + /** + * 新增出库单 + * @param whereJson / + */ + void insertDtl (JSONObject whereJson); + /** + * 查询出库单明细 + * @param whereJson / + * @return + */ + JSONArray getOutBillDtl(Map whereJson); + /** + * 修改出库单 + * @param whereJson / + */ + void update(JSONObject whereJson); + + /** + * 审核通过 + * @param whereJson / + */ + void auditPass(JSONObject whereJson); + + /** + * 不通过 + * @param whereJson / + */ + void auditOut(JSONObject whereJson); +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/impl/ProductScrapServiceImpl.java b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/impl/ProductScrapServiceImpl.java new file mode 100644 index 000000000..d0c1eb0ed --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/service/impl/ProductScrapServiceImpl.java @@ -0,0 +1,287 @@ +package org.nl.wms.st.instor.service.impl; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.IdUtil; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.nl.common.utils.SecurityUtils; +import org.nl.modules.common.exception.BadRequestException; +import org.nl.modules.system.util.CodeUtil; +import org.nl.modules.wql.WQL; +import org.nl.modules.wql.core.bean.WQLObject; +import org.nl.modules.wql.util.WqlUtil; +import org.nl.wms.basedata.st.service.impl.UserStorServiceImpl; +import org.nl.wms.st.inbill.service.CheckOutBillService; +import org.nl.wms.st.instor.service.ProductScrapService; +import org.springframework.data.domain.Pageable; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * PC端成品报废审核 + */ +@Service +@RequiredArgsConstructor +@Slf4j +public class ProductScrapServiceImpl implements ProductScrapService { + private final CheckOutBillService checkOutBillService; + + @Override + public Map pageQuery(Map whereJson, Pageable page) { + HashMap map = new HashMap<>(whereJson); + map.put("flag", "1"); + if (StrUtil.isNotEmpty(map.get("bill_code"))) { + map.put("bill_code", "%" + map.get("bill_code") + "%"); + } + if (StrUtil.isNotEmpty(map.get("material_code"))) { + map.put("material_code", "%" + map.get("material_code") + "%"); + } + if (StrUtil.isNotEmpty(map.get("pcsn"))) { + map.put("pcsn", (String) whereJson.get("pcsn")); + } + + //获取人员对应的仓库 + UserStorServiceImpl userStorService = new UserStorServiceImpl(); + String in_stor_id = userStorService.getInStor(); + + if (ObjectUtil.isNotEmpty(in_stor_id)) map.put("in_stor_id", in_stor_id); + + JSONObject jo = WQL.getWO("QST_IVT_PRODUCTSCRAP").addParamMap(map).pageQuery(WqlUtil.getHttpContext(page), "scrap_code desc"); + return jo; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteAll(Long[] ids) { + WQLObject wo_mst = WQLObject.getWQLObject("ST_IVT_ProductScrapMst"); + + JSONObject jsonObject = new JSONObject(); + jsonObject.put("is_delete", "1"); + for (Long scrap_id : ids) { + wo_mst.update(jsonObject,"scrap_id = '"+scrap_id+"'"); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void insertDtl(JSONObject map) { + //主表 + WQLObject wo_mst = WQLObject.getWQLObject("ST_IVT_ProductScrapMst"); + + JSONArray rows = map.getJSONArray("tableData"); + map.remove("tableData"); + String currentUserId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + String changeinv_id = IdUtil.getSnowflake(1, 1).nextId() + ""; + JSONObject mst_jo = new JSONObject(); + mst_jo.put("scrap_id", changeinv_id); + mst_jo.put("scrap_code", CodeUtil.getNewCode("SCRAP_CODE")); + mst_jo.put("biz_date", DateUtil.today()); + mst_jo.put("stor_id", MapUtil.getStr(map, "stor_id")); + mst_jo.put("stor_code", MapUtil.getStr(map, "stor_code")); + mst_jo.put("stor_name", MapUtil.getStr(map, "stor_name")); + mst_jo.put("bill_status", "10"); + mst_jo.put("input_optid", currentUserId + ""); + mst_jo.put("input_optname", nickName); + mst_jo.put("input_time", now); + mst_jo.put("is_delete", "0"); + mst_jo.put("detail_count", rows.size()); + + //调用明细处理方法 + JSONObject ret = this.insertDtlByRows(mst_jo, rows); + mst_jo.put("total_qty", ret.getDoubleValue("total_qty")); + wo_mst.insert(mst_jo); + } + + /** + * 根据传进来的载具物料明细,查询载具所有库存记录,并生成移库明细 + * + * @param rows + */ + @Transactional(rollbackFor = Exception.class) + JSONObject insertDtlByRows(JSONObject jsonMst, JSONArray rows) { + WQLObject wo_dtl = WQLObject.getWQLObject("ST_IVT_ProductScrapDtl"); + + //定义返回数据 + JSONObject ret = new JSONObject(); + double total_qty = 0; + for (int i = 0; i < rows.size(); i++) { + JSONObject json = rows.getJSONObject(i); + + JSONObject jsonDtl = new JSONObject(); + jsonDtl.put("scrapdtl_id", IdUtil.getSnowflake(1, 1).nextId()); + jsonDtl.put("scrap_id", jsonMst.getLongValue("scrap_id")); + jsonDtl.put("seq_no", i); + jsonDtl.put("material_id", json.getLongValue("material_id")); + jsonDtl.put("pcsn", json.getString("pcsn")); + jsonDtl.put("package_box_sn", json.getString("storagevehicle_code")); + jsonDtl.put("fail_source", json.getString("fail_source")); + jsonDtl.put("qty_unit_id", json.getString("qty_unit_id")); + jsonDtl.put("qty_unit_name", json.getString("qty_unit_name")); + jsonDtl.put("qty", json.getDoubleValue("qty")); + jsonDtl.put("remark", json.getString("remark")); + wo_dtl.insert(jsonDtl); + + total_qty = NumberUtil.add(total_qty, json.getDoubleValue("qty")); + + } + ret.put("total_qty", total_qty); + return ret; + } + + @Override + public JSONArray getOutBillDtl(Map whereJson) { + whereJson.put("flag", "2"); + JSONArray jo = WQL.getWO("QST_IVT_PRODUCTSCRAP") + .addParamMap((HashMap) whereJson) + .process() + .getResultJSONArray(0); + return jo; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void update(JSONObject whereJson) { + //主表 + WQLObject wo_mst = WQLObject.getWQLObject("ST_IVT_ProductScrapMst"); + //主表 + WQLObject wo_dtl = WQLObject.getWQLObject("ST_IVT_ProductScrapDtl"); + + String currentUserId = SecurityUtils.getCurrentUserId(); + String nickName = SecurityUtils.getCurrentNickName(); + String now = DateUtil.now(); + String scrap_id = (String) whereJson.get("scrap_id"); + //查询主表 + JSONObject jo_mst = wo_mst.query("scrap_id='" + scrap_id + "'").uniqueResult(0); + + //删除所有明细 + wo_dtl.delete("scrap_id = '"+scrap_id+"'"); + + //获取明细 + JSONArray rows = whereJson.getJSONArray("tableData"); + //调用明细处理方法 + JSONObject ret = this.insertDtlByRows(jo_mst, rows); + jo_mst.put("remark", whereJson.get("remark")); + jo_mst.put("biz_date", whereJson.get("biz_date")); + jo_mst.put("detail_count", rows.size()); + jo_mst.put("total_qty", ret.getString("total_qty")); + jo_mst.put("update_optid", currentUserId + ""); + jo_mst.put("update_optname", nickName); + jo_mst.put("update_time", now); + //更新主表 + wo_mst.update(jo_mst); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void auditPass(JSONObject whereJson) { + /* + * 1.校验此些子卷是否都在库内并没有被锁定 + * 2.生成出库单 + * 3.更新单据 + */ + WQLObject mst = WQLObject.getWQLObject("ST_IVT_ProductScrapMst"); + WQLObject dtl = WQLObject.getWQLObject("ST_IVT_ProductScrapDtl"); + WQLObject ivt = WQLObject.getWQLObject("st_ivt_structivt"); + + // 查询所有明细 + JSONArray dtlArr = dtl.query("scrap_id = '" + whereJson.getString("scrap_id") + "'").getResultJSONArray(0); + + // 查询库存中这些子卷是否存在 + String pcsnJoining = dtlArr.stream() + .map(row -> JSON.parseObject(row.toString())) + .map(row -> row.getString("pcsn")) + .collect(Collectors.joining("','")); + + List ivtList = ivt.query("pcsn in ('" + pcsnJoining + "') and canuse_qty > 0") + .getResultJSONArray(0).toJavaList(JSONObject.class); + + if (dtlArr.size() != ivtList.size()) throw new BadRequestException("库存异常请检查!"); + + // 校验库存 + boolean is_pass = ivtList.stream() + .allMatch(row -> pcsnJoining.contains(row.getString("pcsn"))); + + if (!is_pass) throw new BadRequestException("库存异常请检查!"); + + /* List collect = ivtList.stream() + .filter(row -> !pcsnJoining.contains(row.getString("pcsn"))) + .map(row -> row.getString("pcsn")) + .collect(Collectors.toList()); + + if (ObjectUtil.isNotEmpty(collect)) { + throw new BadRequestException("子卷:"+collect.toString()+"异常请检查!"); + }*/ + + // 生成出库单 + JSONObject jsonOutMst = new JSONObject(); + jsonOutMst.put("stor_id",whereJson.getString("stor_id")); + jsonOutMst.put("stor_code", whereJson.getString("stor_code")); + jsonOutMst.put("stor_name", whereJson.getString("stor_name")); + jsonOutMst.put("detail_count", ivtList.size()); + jsonOutMst.put("bill_status", "10"); + jsonOutMst.put("create_mode", "03"); + jsonOutMst.put("biz_date", DateUtil.now()); + jsonOutMst.put("io_type", "1"); + jsonOutMst.put("buss_type", "1002"); + jsonOutMst.put("bill_type", "1002"); + jsonOutMst.put("source_name", "成品报废审核单"); + + JSONArray tableData = new JSONArray(); + for (int i = 0; i < dtlArr.size(); i++) { + JSONObject json = dtlArr.getJSONObject(i); + + JSONObject jsonDtl = new JSONObject(); + jsonDtl.put("pcsn", json.getString("pcsn")); + jsonDtl.put("box_no", json.getString("package_box_sn")); + jsonDtl.put("material_id", json.getString("material_id")); + jsonDtl.put("qty_unit_id", json.getLongValue("qty_unit_id")); + jsonDtl.put("qty_unit_name", json.getString("qty_unit_name")); + jsonDtl.put("plan_qty", json.getDoubleValue("qty")); + tableData.add(jsonDtl); + } + + // 调用出库新增并分配 + jsonOutMst.put("tableData", tableData); + String iostorinv_id = checkOutBillService.insertDtl(jsonOutMst); + JSONObject jsonObject = new JSONObject(); + jsonObject.put("iostorinv_id", iostorinv_id); + checkOutBillService.allDiv(jsonObject); + + // 更新主表为完成 + JSONObject param = new JSONObject(); + param.put("bill_status", "99"); + param.put("confirm_optid", SecurityUtils.getCurrentUserId()); + param.put("confirm_optname", SecurityUtils.getCurrentNickName()); + param.put("confirm_time", DateUtil.now()); + mst.update(param,"scrap_id = '"+whereJson.getString("scrap_id")+"'"); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void auditOut(JSONObject whereJson) { + WQLObject mst = WQLObject.getWQLObject("ST_IVT_ProductScrapMst"); + + // 更新主表为完成 + JSONObject param = new JSONObject(); + param.put("bill_status", "99"); + param.put("confirm_optid", SecurityUtils.getCurrentUserId()); + param.put("confirm_optname", SecurityUtils.getCurrentNickName()); + param.put("confirm_time", DateUtil.now()); + mst.update(param,"scrap_id = '"+whereJson.getString("scrap_id")+"'"); + } + +} diff --git a/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/wql/QST_IVT_PRODUCTSCRAP.wql b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/wql/QST_IVT_PRODUCTSCRAP.wql new file mode 100644 index 000000000..d3dcb1ca1 --- /dev/null +++ b/lms/nladmin-system/src/main/java/org/nl/wms/st/instor/wql/QST_IVT_PRODUCTSCRAP.wql @@ -0,0 +1,112 @@ +[交易说明] + 交易名: 成品报废审核分页查询 + 所属模块: + 功能简述: + 版权所有: + 表引用: + 版本经历: + +[数据库] + --指定数据库,为空采用默认值,默认为db.properties中列出的第一个库 + +[IO定义] + ################################################# + ## 表字段对应输入参数 + ################################################# + 输入.flag TYPEAS s_string + 输入.material_code TYPEAS s_string + 输入.bill_status TYPEAS s_string + 输入.bill_code TYPEAS s_string + 输入.stor_id TYPEAS s_string + 输入.end_time TYPEAS s_string + 输入.begin_time TYPEAS s_string + 输入.pcsn TYPEAS s_string + 输入.scrap_id TYPEAS s_string + 输入.in_stor_id TYPEAS f_string +[临时表] + --这边列出来的临时表就会在运行期动态创建 + +[临时变量] + --所有中间过程变量均可在此处定义 + +[业务过程] + + ########################################## + # 1、输入输出检查 # + ########################################## + + + ########################################## + # 2、主过程前处理 # + ########################################## + + + ########################################## + # 3、业务主过程 # + ########################################## + + IF 输入.flag = "1" + PAGEQUERY + SELECT DISTINCT + mst.* + FROM + ST_IVT_ProductScrapMst mst + LEFT JOIN ST_IVT_ProductScrapDtl dtl ON mst.scrap_id = dtl.scrap_id + WHERE + 1 = 1 + AND mst.is_delete = '0' + and mst.stor_id in 输入.in_stor_id + + OPTION 输入.bill_code <> "" + mst.scrap_code like 输入.bill_code + ENDOPTION + + OPTION 输入.pcsn <> "" + dtl.pcsn = 输入.pcsn + ENDOPTION + + OPTION 输入.stor_id <> "" + mst.stor_id = 输入.stor_id + ENDOPTION + + OPTION 输入.bill_status <> "" + mst.bill_status = 输入.bill_status + ENDOPTION + + OPTION 输入.begin_time <> "" + mst.input_time >= 输入.begin_time + ENDOPTION + + OPTION 输入.end_time <> "" + mst.input_time <= 输入.end_time + ENDOPTION + + ENDSELECT + ENDPAGEQUERY + ENDIF + + IF 输入.flag = "2" + QUERY + SELECT DISTINCT + dtl.*, + dtl.package_box_sn AS storagevehicle_code, + mater.material_code, + mater.material_name + FROM + ST_IVT_ProductScrapDtl dtl + LEFT JOIN ST_IVT_ProductScrapMst mst ON mst.scrap_id = dtl.scrap_id + LEFT JOIN md_me_materialbase mater ON mater.material_id = dtl.material_id + WHERE + 1 = 1 + OPTION 输入.scrap_id <> "" + dtl.scrap_id = 输入.scrap_id + ENDOPTION + + OPTION 输入.scrapdtl_id <> "" + dtl.scrapdtl_id = 输入.scrapdtl_id + ENDOPTION + + order by dtl.seq_no + ENDSELECT + ENDQUERY + ENDIF \ No newline at end of file diff --git a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue new file mode 100644 index 000000000..07af0dd6f --- /dev/null +++ b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue @@ -0,0 +1,476 @@ + + + + + + + diff --git a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDtl.vue b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDtl.vue new file mode 100644 index 000000000..a36dcb3ea --- /dev/null +++ b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDtl.vue @@ -0,0 +1,231 @@ + + + + diff --git a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/index.vue b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/index.vue new file mode 100644 index 000000000..6b8a33b65 --- /dev/null +++ b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/index.vue @@ -0,0 +1,290 @@ + + + + diff --git a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/productscrap.js b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/productscrap.js new file mode 100644 index 000000000..f5d578e96 --- /dev/null +++ b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/productscrap.js @@ -0,0 +1,55 @@ +import request from '@/utils/request' + +export function add(data) { + return request({ + url: 'api/productscrap', + method: 'post', + data + }) +} + +export function del(ids) { + return request({ + url: 'api/productscrap/', + method: 'delete', + data: ids + }) +} + +export function edit(data) { + return request({ + url: 'api/productscrap', + method: 'put', + data + }) +} + +export function getOutBillDtl(params) { + return request({ + url: '/api/productscrap/getOutBillDtl', + method: 'get', + params + }) +} +export function insertDtl(data) { + return request({ + url: '/api/productscrap/insertDtl', + method: 'post', + data + }) +} +export function auditPass(data) { + return request({ + url: '/api/productscrap/auditPass', + method: 'post', + data + }) +} +export function auditOut(data) { + return request({ + url: '/api/productscrap/auditOut', + method: 'post', + data + }) +} +export default { add, edit, del, getOutBillDtl, auditPass, auditOut } From 46463e7b6514eacdfd3417a756d5bfbbcdf38eb7 Mon Sep 17 00:00:00 2001 From: yanps Date: Wed, 8 Nov 2023 17:30:33 +0800 Subject: [PATCH 11/14] =?UTF-8?q?opt:=20=E7=BA=B8=E7=AE=A1=E5=BA=93,?= =?UTF-8?q?=E5=A5=97=E7=AE=A1=E5=B7=A5=E4=BD=8D=E9=A9=B1=E5=8A=A8=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/nl/acs/device/wql/task_inst.xls | Bin 167424 -> 167936 bytes .../CasingStationConveyorDeviceDriver.java | 2 +- .../casing_station/ItemProtocol.java | 2 +- .../paper_tube_device2/ItemProtocol.java | 94 +++++ .../basedriver/paper_tube_device2/Paper.java | 2 +- .../PaperTubeConveyor2DeviceDriver.java | 372 ++++++++++++++++-- .../device_driver/driver/OpcDeviceDriver.java | 16 + .../acs/ext/wms/data/CreateTaskRequest.java | 4 + .../wms/service/impl/AcsToWmsServiceImpl.java | 3 + .../wms/service/impl/WmsToAcsServiceImpl.java | 5 + .../org/nl/acs/task/service/dto/TaskDto.java | 10 +- 11 files changed, 465 insertions(+), 45 deletions(-) diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls b/acs/nladmin-system/src/main/java/org/nl/acs/device/wql/task_inst.xls index 7470984f1b975aa75f7771b3840aaf0f499a2cc4..136a812e81e915eea21b20e8461ad4313f33d810 100644 GIT binary patch delta 16461 zcmeHOd3aStmaqG^yd)$qkc1?>07(ctvM*sz++dV_O9%o95ENx>HWegt5dlFIfl>pq zyDM(^)VOpb-7{nNjLWD!w%vZywp-M3#h#uX_nz}RRj=N=H)YR%^L;blQ>c#Y(A8=`B>JTInLcJjl-P$*6JOB{m#BXD07bx;xOGeC2|6b1Cdn&UVD0F z$HbaY#0gxGE3Xc3a%LsI4j&F=JRh#9Ey#K*aX7lmiA97nMVu$5iRoe<-Ev4)quif$ zS?Ixe-769q*{eHc)e$HDBHa_0cD*wac}m>!_~Yvn`IV<*@{vBBVymgl5g}0^g5t#~ zp~SC-ttxe|xe8SRj&sqHmTe+WJhmBf$hp30=_P;KmAf2R+fIe8YPx*s#^znMz}BDz zr1#!5XMOplz;eaE9|IP2F4<9WP2pl_H9QC;0++f!M!k z65_QYAy>-sPB1!%?w%P!ywEJfBd$CuXE;^zj65#;ZYg!E94e&%#zZubM^O|aQ+P4> z@5hL(9R|~Wy&MacpN_fOa6vk#u@c56c^vFw(TiL3N-cU_EqZP@i(+?+Vwpv++@e?E z)B9dzQCp+SMClC?n!V}C8C+iP!tHBVbc08;->qJseJnRziuqIMXM_>OKG5TB) zcV%KEE(~^M;!~m%eIwF#oJb2hryCK-4@KIYNu!#yyCLmvB`y0=(uhDVDb8}{%+#Fa zhO=C8R{C0xglp%ioU?tj>m50jq~{-=JsI=r^|I*ow&?Y-==Dvh)TQY>7+z-6lqT;%_bR~Jx!PNv~nVX z#OeBoRi-19inKSAVzh#^w;}CqB}KR&5s&h9QY0@m01);hlKOO2A;SOIk5oiAq$(u8 zDM!&ACwWK?AV(7dQ#pqI0CM#4wCf~A3lk8!D#>t?Tzz7&c#uF}=meg+-aMi1mWy_+Ec8B&Ft6o^D*1<9y?xIv%rjKtd0b%j^kbL;{1`^CAHxXr zW5_FmB@-NZVL+YW=vF_52>P*H3r4Gkc6xb)W%wHBcC>(ukY_ z6y|zDUF=iD^o_qeX$6JMfnyFysY^XFKysHro1x>-bywOI;haOKr=xe#1LBl$vEplA z0K-AL@1{i=NFimDbT>U2k#~67`pHlyME5-cF;!AFNpM<89Y{hP!GKI71~-ic{$x=> zRNPBfCRYj*(oE`#B1}#+3xpViVRELK9=3`QY3g?gd=U>{g!vGBFhqn4LWEt3AjESS z9wNtWgc%;f3?{^L8OAc$!DbyLj0hV;G{xXjr6^P2@ePWohXMo0Mv9T=l;)jI=QY{7vCVARCTU zvf;=U8;-p3J~MD}CIML&k@@?%IBgC*xyWPkzn+=|}!W9WE4hEDfm=x{%V&h}%jZNmK@oNv8z ztDbQG>U@js8-~BXB^cg*4CB?0VFacySM3L}d`^K1!_wG~VMUydVMfB=4Ya(*z*dw0 zE|I)$r0EMfXwgjqjLFG=x8TdAkDIj;X8%3B=th+QRoWxU2vbskq;ew#Ny3U)m4!&c z(ojiZlCa)WQiLR|@HPe125m2WKQj?!*r1JGB(RKAVnFPp^;uF1dZds?3X6U6#{Kb0 zAQRQ79U`(t0xL8n1!$J;XQZG<3VEckXqKPvk2`y1)`58cW?o={BTNpaOQ?m#mnuW8 z83*DnJji1YuxFHFkk*J$0B;e4jTH1qA&(UHND*QgLiG?ZjA>XXU<(;+VW{TJfCX0! zGa^i+B$!A^Fp-jAVmQ@<2}}_%QOqW28A)X$G-s3>G15q|kdk1*O^Gm(l3-#KRfGx5 zI51JlCNkMXl_t$(6Qhj;6Jv}76R9#-NJ+3Tb{46^1cm`jl(7jU{H;>CdL~n z=#fGmDJ*W2V-Bjss$ecU4Wh%JiMn<+aqSb;MnaO-7zs(5DnpVU(p;6yg+qcyagNsS zz+C4V30&tH30$c%aQ$!)N!sO5y#GEiS?lFclI|0KV83vW`&8tYyu1DMp3V6I&nuXFcP}tA|s&@3yp+Eq$D&#&Og$Dr;#B{ zjbot}I(Agv=dMuPW^Mk4P;stnFAp)zc9^C>

^N3BaC|7U7qH_?Nk(rKu;a@F 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 Cvv!sM diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java index 48c33ca87..0c7406519 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/CasingStationConveyorDeviceDriver.java @@ -298,7 +298,7 @@ public class CasingStationConveyorDeviceDriver extends AbstractOpcDeviceDriver i } else { message = applyPaperActionResponse.getMessage(); map.put("code", "to_command"); - map.put("value", "5"); + map.put("value", "99"); this.writing(map); requireSucess = false; message = "纸管不匹配"; diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java index feb67bc19..6e560b925 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/casing_station/ItemProtocol.java @@ -107,7 +107,7 @@ public class ItemProtocol { list.add(new ItemDto(item_error, "报警", "DB101.W58")); list.add(new ItemDto(item_task, "任务号", "DB101.W6")); list.add(new ItemDto(item_material1, "物料1", "DB101.W7")); - list.add(new ItemDto(item_material2, "物料1", "DB101.W8")); + list.add(new ItemDto(item_material2, "物料2", "DB101.W8")); return list; } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java index 8a14a2ad5..79da1956a 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/ItemProtocol.java @@ -7,6 +7,7 @@ import cn.hutool.json.JSONUtil; import lombok.Data; import lombok.extern.slf4j.Slf4j; import org.apache.poi.ss.formula.functions.T; +import org.jinterop.dcom.core.JIUnsignedInteger; import org.nl.acs.device.device_driver.standard_inspect.ItemDto; import java.util.ArrayList; @@ -110,6 +111,47 @@ public class ItemProtocol { this.driver = driver; } + public String getTo_material1() { + return this.getOpcStringValue(item_to_material1); + } + public String getTo_material2() { + return this.getOpcStringValue(item_to_material2); + } + public String getTo_material3() { + return this.getOpcStringValue(item_to_material3); + } + + public int getTo_out_qty1() { + return this.getOpcIntegerValue(item_to_out_qty1); + } + public int getTo_out_qty2() { + return this.getOpcIntegerValue(item_to_out_qty2); + } + public int getTo_out_qty3() { + return this.getOpcIntegerValue(item_to_out_qty3); + } + + public int getTo_seq1() { + return this.getOpcIntegerValue(item_to_seq1); + } + public int getTo_seq2() { + return this.getOpcIntegerValue(item_to_seq2); + } + public int getTo_seq3() { + return this.getOpcIntegerValue(item_to_seq3); + } + + public int getTo_position1() { + return this.getOpcIntegerValue(item_to_position1); + } + public int getTo_position2() { + return this.getOpcIntegerValue(item_to_position2); + } + public int getTo_position3() { + return this.getOpcIntegerValue(item_to_position3); + } + + public int getHeartbeat() { return this.getOpcIntegerValue(item_heartbeat); } @@ -201,6 +243,48 @@ public class ItemProtocol { } + public int getQty1() { + return this.getOpcIntegerValue(item_qty1); + } + public int getQty2() { + return this.getOpcIntegerValue(item_qty2); + } + public int getQty3() { + return this.getOpcIntegerValue(item_qty3); + } + public int getQty4() { + return this.getOpcIntegerValue(item_qty4); + } + public int getQty5() { + return this.getOpcIntegerValue(item_qty5); + } + public int getQty6() { + return this.getOpcIntegerValue(item_qty6); + } + public int getQty7() { + return this.getOpcIntegerValue(item_qty7); + } + public int getQty8() { + return this.getOpcIntegerValue(item_qty8); + } + public int getQty9() { + return this.getOpcIntegerValue(item_qty9); + } + public int getQty10() { + return this.getOpcIntegerValue(item_qty10); + } + public int getQty11() { + return this.getOpcIntegerValue(item_qty11); + } + public int getQty12() { + return this.getOpcIntegerValue(item_qty12); + } + + + + + + public int getTotarget() { return this.getOpcIntegerValue(item_to_target); } @@ -244,6 +328,16 @@ public class ItemProtocol { return new int[3]; } + public int[] getJIUnsignedInteger(String protocol) { + int[] jiUnsignedIntegerArrayValue = this.driver.getJIUnsignedIntegerArrayValue(protocol); + if (ObjectUtil.isNull(jiUnsignedIntegerArrayValue)) { + + } else { + return jiUnsignedIntegerArrayValue; + } + return new int[3]; + } + public List getOpcArrayValue1(String protocol) { List arrayValue = this.driver.getArrayValue(protocol); if (ObjectUtil.isNull(arrayValue)) { diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java index e088a576e..fad8e0cd6 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/Paper.java @@ -13,7 +13,7 @@ public class Paper implements Serializable { //设备号 private String device_code; // - private String meterial_code; + private String material_code; private String qty; } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java index 8bee5865e..b522eb139 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/basedriver/paper_tube_device2/PaperTubeConveyor2DeviceDriver.java @@ -8,9 +8,12 @@ import cn.hutool.json.JSON; import cn.hutool.json.JSONArray; import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSONObject; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.jinterop.dcom.core.JIUnsignedInteger; import org.nl.acs.agv.server.AgvService; import org.nl.acs.device.service.DeviceService; import org.nl.acs.device_driver.DeviceDriver; @@ -108,13 +111,93 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl //下发任务号 int to_task = 0; int last_to_task = 0; - + //出库顺序数组 String item_out_seq_arr = null; - List item_out_seq_arr1 = null; String last_item_out_seq_arr = null; + //出库数量数组 int[] item_out_qty_arr = null; int[] last_item_out_qty_arr = null; + + String item_material1 = null; + String last_item_material1 = null; + String item_material2 = null; + String last_item_material2 = null; + String item_material3 = null; + String last_item_material3 = null; + String item_material4 = null; + String last_item_material4 = null; + String item_material5 = null; + String last_item_material5 = null; + String item_material6 = null; + String last_item_material6 = null; + String item_material7 = null; + String last_item_material7 = null; + String item_material8 = null; + String last_item_material8 = null; + String item_material9 = null; + String last_item_material9 = null; + String item_material10 = null; + String last_item_material10 = null; + String item_material11 = null; + String last_item_material11 = null; + String item_material12 = null; + String last_item_material12 = null; + + int item_qty1 = 0; + int last_item_qty1 = 0; + int item_qty2 = 0; + int last_item_qty2 = 0; + int item_qty3 = 0; + int last_item_qty3 = 0; + int item_qty4 = 0; + int last_item_qty4 = 0; + int item_qty5 = 0; + int last_item_qty5 = 0; + int item_qty6 = 0; + int last_item_qty6 = 0; + int item_qty7 = 0; + int last_item_qty7 = 0; + int item_qty8 = 0; + int last_item_qty8 = 0; + int item_qty9 = 0; + int last_item_qty9 = 0; + int item_qty10 = 0; + int last_item_qty10 = 0; + int item_qty11 = 0; + int last_item_qty11 = 0; + int item_qty12 = 0; + int last_item_qty12 = 0; + + String item_to_material1 = null; + String last_item_to_material1 = null; + String item_to_material2 = null; + String last_item_to_material2 = null; + String item_to_material3 = null; + String last_item_to_material3 = null; + + int item_to_out_qty1 = 0; + int last_item_to_out_qty1 = 0; + int item_to_out_qty2 = 0; + int last_item_to_out_qty2 = 0; + int item_to_out_qty3 = 0; + int last_item_to_out_qty3 = 0; + + int item_to_seq1 = 0; + int last_item_to_seq1 = 0; + int item_to_seq2 = 0; + int last_item_to_seq2 = 0; + int item_to_seq3 = 0; + int last_item_to_seq3 = 0; + + int item_to_position1 = 0; + int last_item_to_position1 = 0; + int item_to_position2 = 0; + int last_item_to_position2 = 0; + int item_to_position3 = 0; + int last_item_to_position3 = 0; + + //当前指令 Instruction inst = null; @@ -149,7 +232,6 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl @Override public void execute() { try { - String message = null; device_code = this.getDeviceCode(); heartbeat = this.itemProtocol.getHeartbeat(); mode = this.itemProtocol.getMode(); @@ -160,20 +242,48 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl to_command = this.itemProtocol.getTo_command(); to_target = this.itemProtocol.getTotarget(); to_task = this.itemProtocol.getTo_task(); - //item_out_seq_arr1 = this.itemProtocol.getItem_out_seq_arr1(); item_out_seq_arr = this.itemProtocol.getItem_out_seq_arr(); item_out_qty_arr = this.itemProtocol.getItem_out_qty_arr(); + item_material1 = this.itemProtocol.getMaterial1(); + item_material2 = this.itemProtocol.getMaterial2(); + item_material3 = this.itemProtocol.getMaterial3(); + item_material4 = this.itemProtocol.getMaterial4(); + item_material5 = this.itemProtocol.getMaterial5(); + item_material6 = this.itemProtocol.getMaterial6(); + item_material7 = this.itemProtocol.getMaterial7(); + item_material8 = this.itemProtocol.getMaterial8(); + item_material9 = this.itemProtocol.getMaterial9(); + item_material10 = this.itemProtocol.getMaterial10(); + item_material11 = this.itemProtocol.getMaterial11(); + item_material12 = this.itemProtocol.getMaterial12(); + item_qty1 = this.itemProtocol.getQty1(); + item_qty2 = this.itemProtocol.getQty2(); + item_qty3 = this.itemProtocol.getQty3(); + item_qty4 = this.itemProtocol.getQty4(); + item_qty5 = this.itemProtocol.getQty5(); + item_qty6 = this.itemProtocol.getQty6(); + item_qty7 = this.itemProtocol.getQty7(); + item_qty8 = this.itemProtocol.getQty8(); + item_qty9 = this.itemProtocol.getQty9(); + item_qty10 = this.itemProtocol.getQty10(); + item_qty11 = this.itemProtocol.getQty11(); + item_qty12 = this.itemProtocol.getQty12(); + item_to_material1 = this.itemProtocol.getTo_material1(); + item_to_material2 = this.itemProtocol.getTo_material2(); + item_to_material3 = this.itemProtocol.getTo_material3(); + item_to_out_qty1 = this.itemProtocol.getTo_out_qty1(); + item_to_out_qty2 = this.itemProtocol.getTo_out_qty2(); + item_to_out_qty3 = this.itemProtocol.getTo_out_qty3(); + item_to_seq1 = this.itemProtocol.getTo_seq1(); + item_to_seq2 = this.itemProtocol.getTo_seq2(); + item_to_seq3 = this.itemProtocol.getTo_seq3(); + item_to_position1 = this.itemProtocol.getTo_position1(); + item_to_position2 = this.itemProtocol.getTo_position2(); + item_to_position3 = this.itemProtocol.getTo_position3(); - if (to_command != last_to_command) { - logServer.deviceExecuteLog(this.device_code, "", "", "信号to_command:" + last_to_command + "->" + to_command); - } - if (to_target != last_to_target) { - logServer.deviceExecuteLog(this.device_code, "", "", "信号to_target:" + last_to_target + "->" + to_target); - } - if (to_task != last_to_task) { - logServer.deviceExecuteLog(this.device_code, "", "", "信号to_task:" + last_to_task + "->" + to_task); - } + //信号位置校验,记录日志 + signal_verification(); if (mode != last_mode) { JSONObject param = new JSONObject(); @@ -254,10 +364,13 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl request_for_shipment(String.valueOf(mode), item_out_seq_arr, item_out_qty_arr); } break; + default: + break; } } last_heartbeat = heartbeat; last_mode = mode; + last_move = move; last_error = error; last_carrier_direction = carrier_direction; last_task = task; @@ -266,6 +379,42 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl last_to_task = to_task; last_item_out_seq_arr = item_out_seq_arr; last_item_out_qty_arr = item_out_qty_arr; + last_item_material1 = item_material1; + last_item_material2 = item_material2; + last_item_material3 = item_material3; + last_item_material4 = item_material4; + last_item_material5 = item_material5; + last_item_material6 = item_material6; + last_item_material7 = item_material7; + last_item_material8 = item_material8; + last_item_material9 = item_material9; + last_item_material10 = item_material10; + last_item_material11 = item_material11; + last_item_material12 = item_material12; + last_item_qty1 = item_qty1; + last_item_qty2 = item_qty2; + last_item_qty3 = item_qty3; + last_item_qty4 = item_qty4; + last_item_qty5 = item_qty5; + last_item_qty6 = item_qty6; + last_item_qty7 = item_qty7; + last_item_qty8 = item_qty8; + last_item_qty9 = item_qty9; + last_item_qty10 = item_qty10; + last_item_qty11 = item_qty11; + last_item_qty12 = item_qty12; + last_item_to_material1 = item_to_material1; + last_item_to_material2 = item_to_material2; + last_item_to_material3 = item_to_material3; + last_item_to_out_qty1 = item_to_out_qty1; + last_item_to_out_qty2 = item_to_out_qty2; + last_item_to_out_qty3 = item_to_out_qty3; + last_item_to_seq1 = item_to_seq1; + last_item_to_seq2 = item_to_seq2; + last_item_to_seq3 = item_to_seq3; + last_item_to_position1 = item_to_position1; + last_item_to_position2 = item_to_position2; + last_item_to_position3 = item_to_position3; } @@ -331,26 +480,29 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl applyPaperActionRequest.setTask_code(String.valueOf(task)); //获取出库顺序 boolean contains = item_out_seq_arr.contains(","); - //String s = item_out_seq_arr.replaceAll("[\\[\\]]", ""); + boolean contains1 = item_out_seq_arr.contains(","); + if (contains) { String[] split = item_out_seq_arr.split(","); applyPaperActionRequest.setMaterial1(split[0]); - applyPaperActionRequest.setMaterial2(split[1]); + applyPaperActionRequest.setMaterial1(split[1]); + } else if (contains1) { + String[] split = item_out_seq_arr.split(","); + applyPaperActionRequest.setMaterial1(split[0]); + applyPaperActionRequest.setMaterial1(split[1]); } else { applyPaperActionRequest.setMaterial1(item_out_seq_arr); } - /*if (item_out_qty_arr.length == 2) { - // 去除方括号 - applyPaperActionRequest.setMaterial1(String.valueOf(item_out_qty_arr[0])); - applyPaperActionRequest.setMaterial2(String.valueOf(item_out_qty_arr[1])); - } else if (item_out_qty_arr.length == 1) { - applyPaperActionRequest.setMaterial1(String.valueOf(item_out_qty_arr[0])); - }*/ if (item_out_qty_arr.length >= 1 && item_out_qty_arr.length < 4) { applyPaperActionRequest.setQty1(String.valueOf(item_out_qty_arr[0])); applyPaperActionRequest.setQty2(String.valueOf(item_out_qty_arr[1])); } ApplyPaperActionResponse applyPaperActionResponse = acsToWmsService.applyPaperActionRequest(applyPaperActionRequest); + if (ObjectUtil.isNull(applyPaperActionResponse)) { + message = "请求失败"; + requireSucess = false; + return; + } Map map3 = new HashMap(); if (applyPaperActionResponse.getstatus() == 200) { map3.put("to_command", "4"); @@ -383,10 +535,7 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl //查找有没有对应的指令 //找指令类型是10的 Instruction inst = instructionService.findByDeviceCodeFromCache(this.device_code); - if (ObjectUtil.isNull(inst)) { - return false; - } - if (ObjectUtil.isNotNull(inst) && "10".equals(inst.getInstruction_code())) { + if (ObjectUtil.isNotNull(inst) && "10".equals(inst.getInstruction_type())) { Device nextdevice = deviceAppservice.findDeviceByCode(inst.getNext_device_code()); String next_addr = nextdevice.getExtraValue().get("address").toString(); TaskDto taskDto = taskserver.findByCodeFromCache(inst.getTask_code()); @@ -424,10 +573,12 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl } //判断当前任务号是否存在指令 Instruction inst1 = instructionService.findByTaskcodeAndStatus(taskdto.getTask_code()); - Device nextdevice = deviceAppservice.findDeviceByCode(inst1.getNext_device_code()); - String next_addr = nextdevice.getExtraValue().get("address").toString(); - Device pointdevice = deviceAppservice.findDeviceByCode(inst1.getNext_point_code()); - String point_addr = pointdevice.getExtraValue().get("address").toString(); + /*if(ObjectUtil.isNotNull(inst1)){ + Device nextdevice = deviceAppservice.findDeviceByCode(inst1.getNext_device_code()); + String next_addr = nextdevice.getExtraValue().get("address").toString(); + Device pointdevice = deviceAppservice.findDeviceByCode(inst1.getNext_point_code()); + String point_addr = pointdevice.getExtraValue().get("address").toString(); + }*/ //没有就创建指令 String taskid = taskdto.getTask_id(); String taskcode = taskdto.getTask_code(); @@ -435,7 +586,6 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl String start_point_code = taskdto.getStart_point_code(); String start_device_code = taskdto.getStart_device_code(); String route_plan_code = taskdto.getRoute_plan_code(); - Instruction instdto = new Instruction(); instdto.setInstruction_id(IdUtil.simpleUUID()); instdto.setRoute_plan_code(route_plan_code); @@ -448,9 +598,9 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl instdto.setCreate_time(now); instdto.setCreate_by("auto"); instdto.setStart_device_code(start_device_code); - instdto.setNext_device_code(next_addr); + instdto.setNext_device_code(taskdto.getNext_device_code()); instdto.setStart_point_code(start_point_code); - instdto.setNext_point_code(point_addr); + instdto.setNext_point_code(taskdto.getNext_point_code()); instdto.setPriority(priority); instdto.setInstruction_status("0"); instdto.setExecute_device_code(start_point_code); @@ -475,7 +625,7 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl writeStatus(paperArray, map, 2); writeStatus(paperArray, map, 3); } - writeData(next_addr, instdto, map); + writeData(taskdto.getNext_device_code(), instdto, map); this.writing(map); requireSucess = true; return true; @@ -502,11 +652,13 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl } public void writeStatus(List paperArray, Map map, Integer status) { - Paper paper = paperArray.get(status); - map.put("to_material" + status, paper.getMeterial_code()); + Paper paper = paperArray.get(status - 1); + map.put("to_material" + status, paper.getMaterial_code()); map.put("to_out_qty" + status, paper.getQty()); - map.put("to_seq" + status, "1"); - map.put("to_position" + status, paper.getDevice_code()); + map.put("to_seq" + status, status); + Device nextdevice = deviceAppservice.findDeviceByCode(paper.getDevice_code()); + String next_addr = nextdevice.getExtraValue().get("address").toString(); + map.put("to_position" + status, next_addr); } @@ -560,8 +712,7 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl * 解析出库的顺序 */ public List getPaperArray(String paper_array) { - JSONArray jsonArray = JSONUtil.parseArray(paper_array); - List papers = jsonArray.toList(Paper.class); + List papers = JSONUtil.toList(paper_array, Paper.class); return papers; } @@ -573,7 +724,6 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl Date date = new Date(); if (date.getTime() - this.instruction_update_time.getTime() < (long) this.instruction_update_time_out) { log.trace("触发时间因为小于{}毫秒,而被无视", this.instruction_update_time_out); - } else { this.instruction_update_time = date; inst = checkInst(); @@ -614,9 +764,149 @@ public class PaperTubeConveyor2DeviceDriver extends AbstractOpcDeviceDriver impl return null; } + private void signal_verification() { + if (!item_out_seq_arr.equals(last_item_out_seq_arr)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号item_out_seq_arr:" + last_item_out_seq_arr + "->" + item_out_seq_arr); + } + if (!arrayEquals(item_out_qty_arr, last_item_out_qty_arr)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号item_out_qty_arr:" + Arrays.toString(last_item_out_qty_arr) + "->" + Arrays.toString(item_out_qty_arr)); + } + if (item_qty1 != (last_item_qty1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty1:" + last_item_qty1 + "->" + item_qty1); + } + if (item_qty2 != (last_item_qty2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty2:" + last_item_qty2 + "->" + item_qty2); + } + if (item_qty3 != (last_item_qty3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty3:" + last_item_qty3 + "->" + item_qty3); + } + if (item_qty4 != (last_item_qty4)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty4:" + last_item_qty4 + "->" + item_qty4); + } + if (item_qty5 != (last_item_qty5)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty5:" + last_item_qty5 + "->" + item_qty5); + } + if (item_qty6 != (last_item_qty6)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty6:" + last_item_qty6 + "->" + item_qty6); + } + if (item_qty7 != (last_item_qty7)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty7:" + last_item_qty7 + "->" + item_qty7); + } + if (item_qty8 != (last_item_qty8)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty8:" + last_item_qty8 + "->" + item_qty8); + } + if (item_qty9 != (last_item_qty9)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty9:" + last_item_qty9 + "->" + item_qty9); + } + if (item_qty10 != (last_item_qty10)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty10:" + last_item_qty10 + "->" + item_qty10); + } + if (item_qty11 != (last_item_qty11)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty11:" + last_item_qty11 + "->" + item_qty11); + } + if (item_qty12 != (last_item_qty12)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号qty12:" + last_item_qty12 + "->" + item_qty12); + } + if (item_material1.equals(last_item_material1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material1:" + last_item_material1 + "->" + item_material1); + } + if (!item_material2.equals(last_item_material2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material2:" + last_item_material2 + "->" + item_material2); + } + if (!item_material3.equals(last_item_material3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material3:" + last_item_material3 + "->" + item_material3); + } + if (!item_material4.equals(last_item_material4)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material4:" + last_item_material4 + "->" + item_material4); + } + if (!item_material5.equals(last_item_material5)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material5:" + last_item_material5 + "->" + item_material5); + } + if (!item_material6.equals(last_item_material6)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material6:" + last_item_material6 + "->" + item_material6); + } + if (!item_material7.equals(last_item_material7)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material7:" + last_item_material7 + "->" + item_material7); + } + if (!item_material8.equals(last_item_material8)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material8:" + last_item_material8 + "->" + item_material8); + } + if (!item_material9.equals(last_item_material9)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material9:" + last_item_material9 + "->" + item_material9); + } + if (!item_material10.equals(last_item_material10)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material10:" + last_item_material10 + "->" + item_material10); + } + if (!item_material11.equals(last_item_material11)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material11:" + last_item_material11 + "->" + item_material11); + } + if (!item_material12.equals(last_item_material12)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号material12:" + last_item_material12 + "->" + item_material12); + } + if (to_command != last_to_command) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_command:" + last_to_command + "->" + to_command); + } + if (to_target != last_to_target) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_target:" + last_to_target + "->" + to_target); + } + if (to_task != last_to_task) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_task:" + last_to_task + "->" + to_task); + } + if (!item_to_material1.equals(last_item_to_material1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_material1:" + last_item_to_material1 + "->" + item_to_material1); + } + if (!item_to_material2.equals(last_item_to_material2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_material2:" + last_item_to_material2 + "->" + item_to_material2); + } + if (!item_to_material3.equals(last_item_to_material3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_material3:" + last_item_to_material2 + "->" + item_to_material2); + } + if (item_to_out_qty1 != (last_item_to_out_qty1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_out_qty1:" + last_item_to_out_qty1 + "->" + item_to_out_qty1); + } + if (item_to_out_qty2 != (last_item_to_out_qty2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_out_qty2:" + last_item_to_out_qty2 + "->" + item_to_out_qty2); + } + if (item_to_out_qty3 != (last_item_to_out_qty3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_out_qty3:" + last_item_to_out_qty3 + "->" + item_to_out_qty3); + } + if (item_to_seq1 != (last_item_to_seq1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_seq1:" + last_item_to_seq1 + "->" + item_to_seq1); + } + if (item_to_seq2 != (last_item_to_seq2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_seq2:" + last_item_to_seq2 + "->" + item_to_seq2); + } + if (item_to_seq3 != (last_item_to_seq3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_seq3:" + last_item_to_seq3 + "->" + item_to_seq3); + } + if (item_to_position1 != (last_item_to_position1)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_position1:" + last_item_to_position1 + "->" + item_to_position1); + } + if (item_to_position2 != (last_item_to_position2)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_position2:" + last_item_to_position2 + "->" + item_to_position2); + } + if (item_to_position3 != (last_item_to_position3)) { + logServer.deviceExecuteLog(this.device_code, "", "", "信号to_position3:" + last_item_to_position3 + "->" + item_to_position3); + } + + } @Override public void setDeviceStatus(JSONObject data) { } + + public static boolean arrayEquals(int[] a, int[] b) { + // 判断两个数组长度是否相等 + if (a.length != b.length) { + return false; + } + // 判断两个数组对应位置上的元素是否相同 + for (int i = 0; i < a.length; i++) { + if (a[i] != b[i]) { + return false; + } + } + return true; + } } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java index 157d4f3f1..b51132023 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/device_driver/driver/OpcDeviceDriver.java @@ -4,6 +4,7 @@ package org.nl.acs.device_driver.driver; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import org.jinterop.dcom.core.JIUnsignedInteger; import org.nl.acs.device_driver.DeviceDriver; import org.nl.acs.opc.Device; import org.nl.acs.opc.OpcItemDto; @@ -77,6 +78,21 @@ public interface OpcDeviceDriver extends DeviceDriver { return (int[]) this.getOpcValueAccessor().getValue(this.getItem(protocol)); } + + default int[] getJIUnsignedIntegerArrayValue(String protocol) { + JIUnsignedInteger[] jiUnsignedIntegers = (JIUnsignedInteger[]) this.getOpcValueAccessor().getValue(this.getItem(protocol)); + if(ObjectUtil.isNull(jiUnsignedIntegers)){ + return new int[3]; + } + // 将 JIUnsignedInteger[] 转换为 int[] + int[] intArray = new int[jiUnsignedIntegers.length]; + for (int i = 0; i < jiUnsignedIntegers.length; i++) { + intArray[i] = jiUnsignedIntegers[i].getValue().intValue(); + } + + return intArray; + } + default String getStringValue(String protocol) { return (String) this.getOpcValueAccessor().getValue(this.getItem(protocol)); } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/CreateTaskRequest.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/CreateTaskRequest.java index d9b4cb330..226fb0a07 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/CreateTaskRequest.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/data/CreateTaskRequest.java @@ -1,7 +1,9 @@ package org.nl.acs.ext.wms.data; import lombok.Data; +import org.nl.acs.device_driver.basedriver.paper_tube_device2.Paper; +import java.util.List; import java.util.Map; @Data @@ -120,4 +122,6 @@ public class CreateTaskRequest extends BaseRequest { */ Map params; + private List paper_array; + } diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java index 4e305c38f..9ed99ea66 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/AcsToWmsServiceImpl.java @@ -488,6 +488,9 @@ public class AcsToWmsServiceImpl implements AcsToWmsService { if (StrUtil.equals(paramService.findByCode(AcsConfig.HASWMS).getValue(), "1")) { String wmsUrl = paramService.findByCode(AcsConfig.WMSURL).getValue(); AddressDto addressDto = addressService.findByCode("applyPaperAction"); + if(ObjectUtil.isNull(addressDto)){ + return null; + } String methods_url = addressDto.getMethods_url(); String url = wmsUrl + methods_url; log.info("ApplyPaperActionRequest----请求参数{}", param); diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java index 4ac9b6396..3ae28e74c 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/ext/wms/service/impl/WmsToAcsServiceImpl.java @@ -3,6 +3,7 @@ package org.nl.acs.ext.wms.service.impl; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -27,6 +28,7 @@ import org.nl.acs.device_driver.basedriver.hongxiang_device.HongXiangConveyorDev import org.nl.acs.device_driver.basedriver.lamp_three_color.LampThreecolorDeviceDriver; import org.nl.acs.device_driver.basedriver.oven_manipulator.OvenGantryManipulatorDeviceDriver; import org.nl.acs.device_driver.basedriver.paper_tube_device.PaperTubeConveyorDeviceDriver; +import org.nl.acs.device_driver.basedriver.paper_tube_device2.Paper; import org.nl.acs.device_driver.basedriver.plug_pull_device_site.PlugPullDeviceSiteDeviceDriver; import org.nl.acs.device_driver.basedriver.siemens_conveyor.SiemensConveyorDeviceDriver; import org.nl.acs.device_driver.basedriver.siemens_conveyor_ckk.SiemensConveyorCkkDeviceDriver; @@ -614,6 +616,7 @@ public class WmsToAcsServiceImpl implements WmsToAcsService { for (int i = 0; i < datas.size(); i++) { String data = datas.get(i).toString(); CreateTaskRequest request = JsonUtl.format(data, CreateTaskRequest.class); + List paper_array = request.getPaper_array(); String ext_task_id = request.getExt_task_id(); String task_code = request.getTask_code(); String start_device_code = request.getStart_device_code(); @@ -823,6 +826,8 @@ public class WmsToAcsServiceImpl implements WmsToAcsService { jo.put("remark", remark); jo.put("params", params); jo.put("task_type", StrUtil.isEmpty(task_type) ? 1 : Integer.parseInt(task_type)); + jo.put("paper_array", JSONUtil.toJsonStr(paper_array)); + if (!StrUtil.isEmpty(ext_task_id)) { jo.put("ext_task_id", ext_task_id); diff --git a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java index f770f33b3..3db2e300a 100644 --- a/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java +++ b/acs/nladmin-system/src/main/java/org/nl/acs/task/service/dto/TaskDto.java @@ -1,8 +1,16 @@ package org.nl.acs.task.service.dto; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; +import org.jinterop.dcom.core.JIUnsignedFactory; +import org.jinterop.dcom.core.JIUnsignedInteger; +import org.nl.acs.device_driver.basedriver.paper_tube_device2.Paper; import java.io.Serializable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; + /** * @author ldjun @@ -329,11 +337,11 @@ public class TaskDto implements Serializable { private String bushing_num; - //array device_code\material_code\qty private String paper_array; + @Override public String toString(){ return "task_code:" + this.getTask_code() From 61ed74e4ae0dd5e9e6a6c594dc8e623c6b5f9b4c Mon Sep 17 00:00:00 2001 From: liuxy Date: Wed, 8 Nov 2023 19:02:50 +0800 Subject: [PATCH 12/14] =?UTF-8?q?rev=EF=BC=9A=E6=88=90=E5=93=81=E6=8A=A5?= =?UTF-8?q?=E5=BA=9F=E5=AE=A1=E6=A0=B8=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wms/st/inStor/productscrap/AddDialog.vue | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue index 07af0dd6f..fac90b93f 100644 --- a/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue +++ b/lms/nladmin-ui/src/views/wms/st/inStor/productscrap/AddDialog.vue @@ -118,7 +118,7 @@ - + - 一键填充 + 填充

不合格品明细 @@ -198,6 +198,11 @@ + + +