From 87fda255732e4709e923f5b4c1e6b401e20c6002 Mon Sep 17 00:00:00 2001
From: luxiaotao1123 <t1341870251@163.com>
Date: 星期六, 09 十一月 2024 15:25:20 +0800
Subject: [PATCH] #

---
 zy-acs-flow/src/map/http.js                                                             |   21 +++++
 zy-acs-flow/src/i18n/en.js                                                              |    2 
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/PatrolService.java                 |  103 +++++++++++++++++++++++++
 zy-acs-flow/src/map/insight/agv/AgvMain.jsx                                             |   40 +++++++++
 zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java             |   19 ++++
 zy-acs-flow/src/i18n/zh.js                                                              |    2 
 zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/MapController.java   |    4 +
 zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/result/MapAgvVo.java |    2 
 8 files changed, 190 insertions(+), 3 deletions(-)

diff --git a/zy-acs-flow/src/i18n/en.js b/zy-acs-flow/src/i18n/en.js
index 933ea92..ff8e64d 100644
--- a/zy-acs-flow/src/i18n/en.js
+++ b/zy-acs-flow/src/i18n/en.js
@@ -647,6 +647,8 @@
                 enable: 'ENABLE',
                 reset: 'RESET',
                 restoreALl: 'Restore All',
+                startPatrol: 'START PATROL',
+                stopPatrol: 'STOP PATROL',
             },
             mode: {
                 observer: 'OBSERVER',
diff --git a/zy-acs-flow/src/i18n/zh.js b/zy-acs-flow/src/i18n/zh.js
index f54e55b..607b965 100644
--- a/zy-acs-flow/src/i18n/zh.js
+++ b/zy-acs-flow/src/i18n/zh.js
@@ -646,6 +646,8 @@
                 enable: '鍚敤',
                 reset: '閲嶇疆',
                 restoreALl: '鎭㈠鎵�鏈�',
+                startPatrol: '寮�鍚贰閫�',
+                stopPatrol: '鍋滄宸¢��',
             },
             mode: {
                 observer: '瑙傚療妯″紡',
diff --git a/zy-acs-flow/src/map/http.js b/zy-acs-flow/src/map/http.js
index 2fce322..b059e6c 100644
--- a/zy-acs-flow/src/map/http.js
+++ b/zy-acs-flow/src/map/http.js
@@ -283,3 +283,24 @@
         console.error(error.message);
     })
 }
+
+export const handleAgvPatrol = async (param) => {
+    try {
+        const res = await request.post('/handler/agv/patrol', param, {
+            headers: {
+                'appKey': HANDLE_APP_KEY
+            }
+        });
+        const { code, msg, data } = res.data;
+        if (code === 200) {
+            notify.success(msg);
+            return true;
+        } else {
+            notify.error(msg);
+        }
+    } catch (error) {
+        notify.error(error.message);
+        console.error(error.message);
+    }
+    return false;
+}
\ No newline at end of file
diff --git a/zy-acs-flow/src/map/insight/agv/AgvMain.jsx b/zy-acs-flow/src/map/insight/agv/AgvMain.jsx
index c5aaf5b..2c981e6 100644
--- a/zy-acs-flow/src/map/insight/agv/AgvMain.jsx
+++ b/zy-acs-flow/src/map/insight/agv/AgvMain.jsx
@@ -14,7 +14,7 @@
 } from '@mui/material';
 import { useNotification } from '../../Notification';
 import AgvThree from './AgvThree';
-import { handleRestoreAgvAll } from '../../http';
+import { handleRestoreAgvAll, handleAgvPatrol } from '../../http';
 import BoolValueIcon from '../BoolValueIcon';
 import ConfirmButton from '../../../page/components/ConfirmButton';
 import { grey } from '@mui/material/colors';
@@ -122,6 +122,13 @@
         });
     }
 
+    const patrolControl = async () => {
+        const res = await handleAgvPatrol({ agvNo: info.agvNo })
+        if (res) {
+            fetchAgvInfo(curAgvNo);
+        }
+    }
+
     return (
         <Box display="flex" height="100%">
             <Box
@@ -193,7 +200,8 @@
                     }}>
                         <Grid container spacing={2} style={{ marginTop: '0px' }}>
                             <Grid item xs={12}>
-                                <Stack spacing={2} mt={2}>
+                                <Stack spacing={1} mt={2}>
+                                    {/* more */}
                                     <Button
                                         color="primary"
                                         variant="contained"
@@ -203,8 +211,33 @@
                                     >
                                         {translate('page.map.settings.map.more.title')}
                                     </Button>
+                                    {/* patrol */}
                                     {info && (
-                                        info.status === 1
+                                        info.patrol
+                                            ?
+                                            <Button variant="contained" color="error" fullWidth onClick={() => {
+                                                patrolControl();
+                                            }}>
+                                                {translate('page.map.action.stopPatrol')}
+                                            </Button>
+                                            :
+                                            // <Button variant="contained" fullWidth onClick={() => {
+                                            //     patrolControl();
+                                            // }}>
+                                            //     {translate('page.map.action.startPatrol')}
+                                            // </Button>
+                                            <ConfirmButton
+                                                label="page.map.action.startPatrol"
+                                                color="primary"
+                                                variant="contained"
+                                                onConfirm={() => {
+                                                    patrolControl();
+                                                }}
+                                            />
+                                    )}
+                                    {/* status */}
+                                    {info && (
+                                        info.status === 0
                                             ? <Button variant="contained" color="error" fullWidth onClick={() => {
                                                 updateStatus();
                                             }}>
@@ -216,6 +249,7 @@
                                                 {translate('page.map.action.enable')}
                                             </Button>
                                     )}
+                                    {/* restore all */}
                                     <ConfirmButton
                                         label="page.map.action.restoreALl"
                                         color="inherit"
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
index 2573042..63d395e 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/HandlerController.java
@@ -65,6 +65,8 @@
     private MapDataDispatcher mapDataDispatcher;
     @Autowired
     private AvoidWaveCalculator avoidWaveCalculator;
+    @Autowired
+    private PatrolService patrolService;
 
     @RequestMapping(value = "/control/agv", method = {RequestMethod.GET, RequestMethod.POST})
     @Transactional
@@ -277,4 +279,21 @@
         return R.ok();
     }
 
+    @RequestMapping(value = "/agv/patrol", method = {RequestMethod.GET, RequestMethod.POST})
+    public R agvPatrol(@RequestHeader String appKey,
+                        @RequestBody HandlerPublishParam param) throws ExecutionException, InterruptedException {
+        if (Cools.isEmpty(param.getAgvNo(), appKey)) {
+            return R.error();
+        }
+        if (!APP_KEY.equals(appKey)) {
+            return R.error();
+        }
+        String agvNo = param.getAgvNo();
+        if (patrolService.isPatrolling(agvNo)) {
+            return patrolService.shutdownPatrol(agvNo);
+        } else {
+            return patrolService.startupPatrol(agvNo);
+        }
+    }
+
 }
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/core/PatrolService.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/PatrolService.java
new file mode 100644
index 0000000..a40d879
--- /dev/null
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/core/PatrolService.java
@@ -0,0 +1,103 @@
+package com.zy.acs.manager.core;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.zy.acs.framework.common.R;
+import com.zy.acs.manager.manager.entity.Agv;
+import com.zy.acs.manager.manager.enums.StatusType;
+import com.zy.acs.manager.manager.service.AgvService;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+import java.util.Map;
+import java.util.concurrent.*;
+
+/**
+ * Created by vincent on 11/9/2024
+ */
+@Slf4j
+@Service
+public class PatrolService {
+
+    private static final int SCHEDULE_TIME_INTERVAL = 1;
+    private static final Map<String, ScheduledFuture<?>> AGV_PATROL_MAP = new ConcurrentHashMap<>();
+
+    private ScheduledExecutorService scheduler = null;
+
+    @Autowired
+    private AgvService agvService;
+
+    public boolean isPatrolling(String agvNo) {
+        ScheduledFuture<?> scheduledFuture = AGV_PATROL_MAP.get(agvNo);
+        if (scheduledFuture == null) {
+            return false;
+        }
+        return !scheduledFuture.isCancelled() && !scheduledFuture.isDone();
+    }
+
+    public R startupPatrol(String agvNo) {
+        if (AGV_PATROL_MAP.containsKey(agvNo)) {
+            return R.error("AGV " + agvNo + " 鐨勮窇搴撲换鍔″凡缁忓湪杩愯涓��");
+        }
+
+        Runnable patrolTask = () -> {
+            try {
+                executePatrolLogic(agvNo);
+            } catch (Exception e) {
+                log.error("鎵цAGV " + agvNo + " 璺戝簱浠诲姟鏃跺彂鐢熷紓甯�: " + e.getMessage());
+                e.printStackTrace();
+            }
+        };
+
+        ScheduledFuture<?> scheduledFuture = scheduler.scheduleAtFixedRate(patrolTask, 0, SCHEDULE_TIME_INTERVAL, TimeUnit.SECONDS);
+
+        AGV_PATROL_MAP.put(agvNo, scheduledFuture);
+        log.info("宸插惎鍔ˋGV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+        return R.ok();
+    }
+
+
+    public R shutdownPatrol(String agvNo) {
+        ScheduledFuture<?> scheduledFuture = AGV_PATROL_MAP.get(agvNo);
+        if (scheduledFuture == null) {
+            return R.error("AGV " + agvNo + " 娌℃湁姝e湪杩愯鐨勮窇搴撲换鍔°��");
+        }
+
+        boolean cancelled = scheduledFuture.cancel(true);
+        if (cancelled) {
+            AGV_PATROL_MAP.remove(agvNo);
+            log.info("宸插仠姝GV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+            return R.ok("宸插仠姝GV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+        } else {
+            log.error("鏈兘鎴愬姛鍋滄AGV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+            return R.error("鏈兘鎴愬姛鍋滄AGV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+        }
+    }
+
+    private void executePatrolLogic(String agvNo) {
+        // TODO: 鍦ㄨ繖閲屽疄鐜板叿浣撶殑璺戝簱涓氬姟閫昏緫
+        log.info("鎵цAGV " + agvNo + " 鐨勮窇搴撲换鍔°��");
+    }
+
+    @PostConstruct
+    public void init() {
+        int count = agvService.count(new LambdaQueryWrapper<Agv>().eq(Agv::getStatus, StatusType.ENABLE.val));
+        if (count > 0) {
+            this.scheduler = Executors.newScheduledThreadPool(count);
+        }
+    }
+
+    @PreDestroy
+    public void destroy() throws InterruptedException {
+        for (Map.Entry<String, ScheduledFuture<?>> entry : AGV_PATROL_MAP.entrySet()) {
+            entry.getValue().cancel(true);
+        }
+        scheduler.shutdown();
+        if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) {
+            scheduler.shutdownNow();
+        }
+    }
+
+}
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/MapController.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/MapController.java
index 90921f4..1843570 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/MapController.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/MapController.java
@@ -13,6 +13,7 @@
 import com.zy.acs.manager.common.domain.MapDto;
 import com.zy.acs.manager.common.domain.MapRouteDto;
 import com.zy.acs.manager.common.exception.BusinessException;
+import com.zy.acs.manager.core.PatrolService;
 import com.zy.acs.manager.core.domain.BackpackDto;
 import com.zy.acs.manager.core.service.MapService;
 import com.zy.acs.manager.core.service.floyd.FloydNavigateService;
@@ -68,6 +69,8 @@
     private LocService locService;
     @Autowired
     private ConfigService configService;
+    @Autowired
+    private PatrolService patrolService;
 
     @PreAuthorize("hasAuthority('manager:loc:update')")
     @PostMapping("/startupOrShutdown")
@@ -160,6 +163,7 @@
             vo.setCode(codeService.getById(agvDetail.getRecentCode()).getData());
             vo.setDirection(agvDetail.getAgvAngle());
             vo.setBackpack(GsonUtils.fromJsonToList(agvDetail.getBackpack(), BackpackDto.class));
+            vo.setPatrol(patrolService.isPatrolling(agvNo));
         }
         List<Task> tasks = taskService.selectInSts(agv.getId(), TaskStsType.WAITING, TaskStsType.ASSIGN, TaskStsType.PROGRESS);
         if (!Cools.isEmpty(tasks)) {
diff --git a/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/result/MapAgvVo.java b/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/result/MapAgvVo.java
index 3f1e798..b982081 100644
--- a/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/result/MapAgvVo.java
+++ b/zy-acs-manager/src/main/java/com/zy/acs/manager/manager/controller/result/MapAgvVo.java
@@ -36,4 +36,6 @@
 
     private List<Long> taskIds = new ArrayList<>();
 
+    private Boolean patrol;
+
 }

--
Gitblit v1.9.1