Browse Source

初始化东方钛业项目,添加西门子PLCS7连接协议包

zhifei 1 năm trước cách đây
mục cha
commit
76d203493a

+ 21 - 0
pom.xml

@@ -35,6 +35,9 @@
         <velocity.version>2.3</velocity.version>
         <jwt.version>0.9.1</jwt.version>
         <skipTests>true</skipTests>
+        <guava.version>23.0</guava.version>
+        <guava.retry.version>2.0.0</guava.retry.version>
+        <iotCommunication.version>1.4.2</iotCommunication.version>
     </properties>
 
     <!-- 依赖声明 -->
@@ -222,6 +225,24 @@
                 <version>${warewms.version}</version>
             </dependency>
 
+            <dependency>
+                <groupId>com.google.guava</groupId>
+                <artifactId>guava</artifactId>
+                <version>${guava.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.github.rholder</groupId>
+                <artifactId>guava-retrying</artifactId>
+                <version>${guava.retry.version}</version>
+            </dependency>
+
+            <dependency>
+                <groupId>com.github.xingshuangs</groupId>
+                <artifactId>iot-communication</artifactId>
+                <version>${iotCommunication.version}</version>
+            </dependency>
+
         </dependencies>
     </dependencyManagement>
 

+ 1 - 1
ruoyi-admin/src/main/resources/application-dev.yml

@@ -6,7 +6,7 @@ spring:
         druid:
             # 主库数据源
             master:
-                url: jdbc:mysql://47.100.220.92:3306/wareams?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
+                url: jdbc:mysql://47.100.220.92:3306/wareams_dongfangtaiye?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&serverTimezone=GMT%2B8
                 username: warewms
                 password: warewms123
             # 从库数据源

+ 10 - 1
ruoyi-system/pom.xml

@@ -23,6 +23,15 @@
             <artifactId>ruoyi-common</artifactId>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.rholder</groupId>
+            <artifactId>guava-retrying</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>com.github.xingshuangs</groupId>
+            <artifactId>iot-communication</artifactId>
+        </dependency>
     </dependencies>
 
-</project>
+</project>

+ 37 - 0
ruoyi-system/src/main/java/com/ruoyi/system/config/PlcConfig.java

@@ -0,0 +1,37 @@
+package com.ruoyi.system.config;
+
+import com.github.xingshuangs.iot.protocol.s7.enums.EPlcType;
+import lombok.Data;
+
+/**
+ * Created with IntelliJ IDEA.
+ *
+ * @author: liuzhifei
+ * Date: 2023/8/7
+ * Description: pcl配置类
+ **/
+@Data
+public class PlcConfig {
+
+    private String ip;
+
+    private Boolean enable;
+
+    private String name;
+
+    private byte slot;
+
+    private byte rack;
+
+    private EPlcType ePlcType;
+
+    private String heartbeat;
+
+    private String confirmTheStatus;
+
+    public void setSiemensPLCS(String  ePlcType) {
+        this.ePlcType = EPlcType.valueOf(ePlcType);
+    }
+
+
+}

+ 22 - 0
ruoyi-system/src/main/java/com/ruoyi/system/config/PlcProperties.java

@@ -0,0 +1,22 @@
+package com.ruoyi.system.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * Created with IntelliJ IDEA.
+ *
+ * @author: liuzhifei
+ * Date: 2023/8/7.
+ * Description:
+ **/
+@Data
+@Component
+@ConfigurationProperties(prefix = "plc")
+public class PlcProperties {
+
+    private List<PlcConfig> plcList;
+}

+ 145 - 0
ruoyi-system/src/main/java/com/ruoyi/system/init/PlcConnectServiceRunner.java

@@ -0,0 +1,145 @@
+package com.ruoyi.system.init;
+
+
+import cn.hutool.core.util.ObjectUtil;
+import com.github.rholder.retry.*;
+import com.github.xingshuangs.iot.protocol.s7.service.S7PLC;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.config.PlcConfig;
+import com.ruoyi.system.config.PlcProperties;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.core.annotation.Order;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * plc连接
+ */
+@Component
+@Order(1)
+@Slf4j
+public class PlcConnectServiceRunner implements CommandLineRunner {
+
+    @Resource
+    private PlcProperties plcProperties;
+
+    @Resource
+    ThreadPoolTaskExecutor threadPoolTaskExecutor;
+
+
+
+    @Resource
+    private ScheduledExecutorService scheduledExecutorService;
+
+    @Override
+    public void run(String... args) throws Exception {
+        initConnect();
+        log.info("PLC initialization complete!");
+    }
+
+    private HashMap<String, S7PLC> plcToolsMap = new HashMap<>();
+
+    private ArrayList<String> reTryPlc = new ArrayList<>();
+
+    /**
+     * 初始化
+     */
+    private void initConnect() throws InterruptedException {
+        for (PlcConfig plcConfig : plcProperties.getPlcList()) {
+            if (plcConfig.getEnable()) {
+                log.info("初始化:{},ip:{}", plcConfig.getName(), plcConfig.getIp());
+                try {
+                    S7PLC s7PLC = new S7PLC(plcConfig.getEPlcType(), plcConfig.getIp());
+                    s7PLC.connect();
+                    if (s7PLC.checkConnected()){
+                        plcToolsMap.put(plcConfig.getName(),s7PLC);
+                        log.info("plc:{},ip:{},The connection was successful",plcConfig.getName(),plcConfig.getIp());
+                    }
+                }catch (Exception e){
+                    log.info("plc:{},ip:{},Connection failed",plcConfig.getName(),plcConfig.getIp());
+                    retry(plcConfig);
+                }
+            }
+        }
+
+    }
+
+    public void retry(PlcConfig plcConfig) {
+        reTryPlc.add(plcConfig.getName());
+        threadPoolTaskExecutor.execute (() -> {
+            Retryer<Boolean> retryer = RetryerBuilder.<Boolean>newBuilder()
+                    .retryIfResult(Boolean.FALSE::equals)
+                    .retryIfExceptionOfType(Exception.class)
+                    .withStopStrategy(StopStrategies.neverStop())
+                    .withWaitStrategy(WaitStrategies.fixedWait(7, TimeUnit.SECONDS))
+                    .build();
+            try {
+                retryer.call(() -> {
+                    log.info("重试:{},ip:{}", plcConfig.getName(), plcConfig.getIp());
+                    try {
+                        S7PLC s7PLC = new S7PLC(plcConfig.getEPlcType(), plcConfig.getIp());
+                        s7PLC.connect();
+                        if (s7PLC.checkConnected()){
+                            plcToolsMap.put(plcConfig.getName(),s7PLC);
+                            log.info("plc:{},ip:{},Retry the connection succeeded",plcConfig.getName(),plcConfig.getIp());
+                            reTryPlc.remove(plcConfig.getName());
+                            plcConnectsTheHeartbeat(plcConfig,s7PLC);
+                            return true;
+                        }
+                    }catch (Exception e){
+                        log.info("plc:{},ip:{},Retry connection failed,meg:{}",plcConfig.getName(),plcConfig.getIp(),e.getMessage());
+                        return false;
+                    }
+                    return false;
+                });
+            } catch (RetryException | ExecutionException e) {
+                e.printStackTrace();
+            }
+        });
+    }
+
+    /**
+     *  plc连接心跳
+     * @param plcConfig
+     * @param s7PLC
+     */
+    private void plcConnectsTheHeartbeat(PlcConfig plcConfig,S7PLC s7PLC){
+        String heartbeatAdd = plcConfig.getHeartbeat();
+        if (StringUtils.isNotEmpty(heartbeatAdd)){
+            scheduledExecutorService.scheduleWithFixedDelay(()->{
+                if (!reTryPlc.contains(plcConfig.getName())){
+                    try {
+                        byte b = s7PLC.readByte(plcConfig.getHeartbeat());
+                        s7PLC.writeByte(plcConfig.getConfirmTheStatus(),b);
+                    }catch (Exception e){
+                        log.error("device:{},The connection is lost",plcConfig.getName());
+                        retry(plcConfig);
+                    }
+                }
+            },0,3,TimeUnit.SECONDS);
+        }
+    }
+
+
+    /**
+     *
+     * @param pclName plc设备名
+     * @return
+     */
+    public S7PLC getPlcServer(String pclName) {
+        S7PLC s7PLC = plcToolsMap.get(pclName);
+        if(ObjectUtil.isNull(s7PLC)){
+            throw new ServiceException("The device is not connected");
+        }
+        return plcToolsMap.get(pclName);
+    }
+}

+ 85 - 93
warewms-ams/src/main/java/com/ruoyi/ams/business/BusinessServiceImpl.java

@@ -655,14 +655,6 @@ public class BusinessServiceImpl implements IBusinessService {
                     break;
                 }
 
-                //转发任务
-                if (StringUtils.isNotEmpty(wcsTask.getTaskType())
-                        && wcsTask.getTaskType().equals(Constant.TASK_TYPE.FORWARD.getValue())) {
-                    sendTask(wcsTask);
-                    wcsTask.setState(10L);
-                    wcsTaskService.updateWcsTask(wcsTask);
-                    break;
-                }
 
                 try {
                     //任务下发判断
@@ -720,7 +712,7 @@ public class BusinessServiceImpl implements IBusinessService {
         //起始库位
         basLocationInfoFrom = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationFrom()));
         //目标库位
-        BaseLocationInfo locationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationTo()));
+//        BaseLocationInfo locationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(wcsTask.getLocationTo()));
         //TODO 前置任务未完成不进行下发
         if (businessService.taskDispatchCheck(wcsTask) == false) {
             return false;
@@ -735,99 +727,99 @@ public class BusinessServiceImpl implements IBusinessService {
             }
 
             //起始库位巷道检测(起始库位检测是否同巷道)
-            if (!StringUtils.isEmpty(basLocationInfoFrom.getColNo())) {
-                List<BaseLocationInfo> locationInfoList = baseLocationInfoMapper.laneCheck(basLocationInfoFrom.getColNo(), "LANE_FROM", Constant.WAREHOUSE_ID);
-                if (locationInfoList != null && locationInfoList.size() > 0) {
-                    wcsTask.setRemark("起始库位同列或同巷道有车辆在任务中,等待其他任务完成");
-                    wcsTaskService.updateWcsTask(wcsTask);
-                    return false;
-                }
-            }
+//            if (!StringUtils.isEmpty(basLocationInfoFrom.getColNo())) {
+//                List<BaseLocationInfo> locationInfoList = baseLocationInfoMapper.laneCheck(basLocationInfoFrom.getColNo(), "LANE_FROM", Constant.WAREHOUSE_ID);
+//                if (locationInfoList != null && locationInfoList.size() > 0) {
+//                    wcsTask.setRemark("起始库位同列或同巷道有车辆在任务中,等待其他任务完成");
+//                    wcsTaskService.updateWcsTask(wcsTask);
+//                    return false;
+//                }
+//            }
         }
 
         //起始库位是地堆需要判断是否有阻挡
-        if (basLocationInfoFrom.getLocationType().equals("2")) {
-            //判断队列中是否有阻挡在当前任务之前
-            List<WcsTaskLocationDTO> locationDTOS = wcsTaskService.selectTaskByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex(), basLocationInfoFrom.getZoneId(), null);
-            if (locationDTOS.size() > 0) {
-                wcsTask.setRemark("队列中有其他任务阻挡,让其他任务先执行");
-                wcsTaskService.updateWcsTask(wcsTask);
-                return false;
-            }
-
-            //判断出库库位前是否有阻挡
-            List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex());
-            if (beforeLoc != null) {
-                for (BaseLocationInfo b : beforeLoc) {
-                    //如果前面库位不为空,或者状态占用
-                    //TODO 去除已经在任务中的
-                    if (b.getIsEmpty().equals("N")) {
-                        wcsTask.setRemark("有阻挡物,任务无法执行");
-                        wcsTaskService.updateWcsTask(wcsTask);
-                        return false;
-                    }
-                }
-            }
-        }
+//        if (basLocationInfoFrom.getLocationType().equals("2")) {
+//            //判断队列中是否有阻挡在当前任务之前
+//            List<WcsTaskLocationDTO> locationDTOS = wcsTaskService.selectTaskByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex(), basLocationInfoFrom.getZoneId(), null);
+//            if (locationDTOS.size() > 0) {
+//                wcsTask.setRemark("队列中有其他任务阻挡,让其他任务先执行");
+//                wcsTaskService.updateWcsTask(wcsTask);
+//                return false;
+//            }
+//
+//            //判断出库库位前是否有阻挡
+//            List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(basLocationInfoFrom.getColNo(), basLocationInfoFrom.getColIndex());
+//            if (beforeLoc != null) {
+//                for (BaseLocationInfo b : beforeLoc) {
+//                    //如果前面库位不为空,或者状态占用
+//                    //TODO 去除已经在任务中的
+//                    if (b.getIsEmpty().equals("N")) {
+//                        wcsTask.setRemark("有阻挡物,任务无法执行");
+//                        wcsTaskService.updateWcsTask(wcsTask);
+//                        return false;
+//                    }
+//                }
+//            }
+//        }
 
         currentTask = wcsTask;
 
         //目标库位如果是地堆需要判断是否有阻挡
-        if (locationInfoTo != null && locationInfoTo.getLocationType().equals("2")) {
-            List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
-            if (beforeLoc != null) {
-                for (BaseLocationInfo b : beforeLoc) {
-                    //跳过起始库位
-                    if (b.getId().equals(locationInfoTo.getId())) {
-                        continue;
-                    }
-                    //如果前面库位不为空,或者状态占用
-                    //TODO 排除已经在任务中的
-                    if (b.getIsEmpty().equals("N")) {
-                        currentTask.setRemark("目标库位前方有阻挡1");
-                        currentTask.setUpdateDate(new Date());
-                        wcsTaskService.updateWcsTask(currentTask);
-                        return false;
-                    }
-                }
-            }
-
-            List<WcsTaskLocationDTO> dtos = wcsTaskService.selectTaskByColNoAfter(locationInfoTo.getColNo(), locationInfoTo.getColIndex(), locationInfoTo.getZoneId(), null);
-            if (dtos != null && dtos.size() > 0) {
-                currentTask.setRemark("目标库位同列有未完成的任务");
-                wcsTaskService.updateWcsTask(currentTask);
-                return false;
-            }
-
-        }
+//        if (locationInfoTo != null && locationInfoTo.getLocationType().equals("2")) {
+//            List<BaseLocationInfo> beforeLoc = baseLocationInfoService.selectBeforeLocationByColNo(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
+//            if (beforeLoc != null) {
+//                for (BaseLocationInfo b : beforeLoc) {
+//                    //跳过起始库位
+//                    if (b.getId().equals(locationInfoTo.getId())) {
+//                        continue;
+//                    }
+//                    //如果前面库位不为空,或者状态占用
+//                    //TODO 排除已经在任务中的
+//                    if (b.getIsEmpty().equals("N")) {
+//                        currentTask.setRemark("目标库位前方有阻挡1");
+//                        currentTask.setUpdateDate(new Date());
+//                        wcsTaskService.updateWcsTask(currentTask);
+//                        return false;
+//                    }
+//                }
+//            }
+//
+//            List<WcsTaskLocationDTO> dtos = wcsTaskService.selectTaskByColNoAfter(locationInfoTo.getColNo(), locationInfoTo.getColIndex(), locationInfoTo.getZoneId(), null);
+//            if (dtos != null && dtos.size() > 0) {
+//                currentTask.setRemark("目标库位同列有未完成的任务");
+//                wcsTaskService.updateWcsTask(currentTask);
+//                return false;
+//            }
+//
+//        }
 
         //查询是否有更里面的位置可以存放
-        if (locationInfoTo != null) {
-            if (locationInfoTo.getZoneId() != 10) {
-                String locationtoTmp = "";
-                List<BaseLocationInfoSameColDTO> b = baseLocationInfoService.selectSameColCanToLoc(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
-                for (BaseLocationInfoSameColDTO bt : b) {
-                    if (bt.getIsOb() == false) {
-                        locationtoTmp = bt.getId().toString();
-                    } else {
-                        break;
-                    }
-                }
-                if (!StringUtils.isEmpty(locationtoTmp)) {
-                    wcsTask.setLocationTo(locationtoTmp);
-                    wcsTaskService.updateWcsTask(wcsTask);
-
-                    //释放原库位
-                    locationInfoTo.setStockStatus("00");
-                    baseLocationInfoService.updateBaseLocationInfo(locationInfoTo);
-
-                    //占用新库位
-                    BaseLocationInfo newlocationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(locationtoTmp));
-                    newlocationInfoTo.setStockStatus("10");
-                    baseLocationInfoService.updateBaseLocationInfo(newlocationInfoTo);
-                }
-            }
-        }
+//        if (locationInfoTo != null) {
+//            if (locationInfoTo.getZoneId() != 10) {
+//                String locationtoTmp = "";
+//                List<BaseLocationInfoSameColDTO> b = baseLocationInfoService.selectSameColCanToLoc(locationInfoTo.getColNo(), locationInfoTo.getColIndex());
+//                for (BaseLocationInfoSameColDTO bt : b) {
+//                    if (bt.getIsOb() == false) {
+//                        locationtoTmp = bt.getId().toString();
+//                    } else {
+//                        break;
+//                    }
+//                }
+//                if (!StringUtils.isEmpty(locationtoTmp)) {
+//                    wcsTask.setLocationTo(locationtoTmp);
+//                    wcsTaskService.updateWcsTask(wcsTask);
+//
+//                    //释放原库位
+//                    locationInfoTo.setStockStatus("00");
+//                    baseLocationInfoService.updateBaseLocationInfo(locationInfoTo);
+//
+//                    //占用新库位
+//                    BaseLocationInfo newlocationInfoTo = baseLocationInfoService.selectBaseLocationInfoById(Long.parseLong(locationtoTmp));
+//                    newlocationInfoTo.setStockStatus("10");
+//                    baseLocationInfoService.updateBaseLocationInfo(newlocationInfoTo);
+//                }
+//            }
+//        }
 
         currentTask.setState(10L);
         currentTask.setRemark("");