From 3f797dd834a2de283cf5eff2ff1124e5a0ccb233 Mon Sep 17 00:00:00 2001
From: Administrator <XS@163.COM>
Date: 星期六, 25 四月 2026 11:18:50 +0800
Subject: [PATCH] 更改 2026-4-25
---
src/main/webapp/components/MapCanvas.js | 196 ++
src/main/java/com/zy/core/thread/impl/ZySiemensCrnV2Thread.java | 4
src/main/webapp/static/js/basDevp/basDevp.js | 2
src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java | 4
src/main/java/com/zy/core/model/protocol/DualCrnProtocol.java | 112 +
src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java | 24
src/main/java/com/zy/asrs/task/WrkMastScheduler.java | 40
src/main/java/com/zy/ai/service/LlmChatService.java | 727 +++++++---
src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java | 3
src/main/java/com/zy/core/network/entity/ZyDualCrnStatusEntity.java | 4
src/main/java/com/zy/core/plugin/XiaosongProcess.java | 13
src/main/java/com/zy/core/model/protocol/StationProtocol.java | 3
src/main/webapp/views/basDevp/basDevp.html | 13
src/main/java/com/zy/ai/service/PythonService.java | 60
src/main/java/com/zy/system/timer/LicenseTimer.java | 12
src/main/java/com/zy/core/thread/CrnThread.java | 2
src/main/java/com/zy/common/service/CommonService.java | 18
src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java | 202 ++
src/main/java/com/zy/core/plugin/FakeProcess.java | 108
src/main/java/com/zy/core/model/command/StationCommand.java | 6
src/main/webapp/views/watch/console.html | 28
src/main/java/com/zy/core/utils/StationOperateProcessUtils.java | 672 ++++++++++
src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java | 88
src/main/java/com/zy/common/model/NavigateNode.java | 1
src/main/java/com/zy/ai/controller/WcsDiagnosisController.java | 4
src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java | 3
src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java | 53
src/main/webapp/components/WatchDualCrnCard.js | 70 +
src/main/java/com/zy/system/entity/license/LinuxServerInfos.java | 8
src/main/java/com/zy/core/network/real/ZyDualCrnRealConnect.java | 132 +
src/main/java/com/zy/core/ServerBootstrap.java | 2
src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java | 21
src/main/java/com/zy/core/plugin/NormalProcess.java | 2
src/main/java/com/zy/core/network/ZyStationConnectDriver.java | 8
src/main/java/com/zy/core/network/real/ZyCrnV2RealConnect.java | 6
src/main/webapp/views/login.html | 3
src/main/java/com/zy/system/controller/LicenseCreatorController.java | 20
src/main/java/com/zy/asrs/controller/DualCrnController.java | 46
src/main/java/com/zy/system/entity/license/CustomLicenseManager.java | 22
src/main/java/com/zy/asrs/entity/BasDevp.java | 53
src/main/java/com/zy/asrs/domain/vo/DualCrnStateTableVo.java | 8
src/main/java/com/zy/common/utils/NavigateUtils.java | 213 ++
src/main/java/com/zy/asrs/controller/BasMapController.java | 40
src/main/java/com/zy/core/task/InitLocMapScheduler.java | 7
src/main/webapp/components/DevpCard.js | 210 +++
src/main/java/com/zy/ai/service/WcsDiagnosisService.java | 19
src/main/webapp/views/locMap/locMap.html | 232 +++
src/main/java/com/zy/asrs/utils/MapExcelUtils.java | 24
src/main/java/com/zy/asrs/controller/OpenController.java | 3
src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java | 3
src/main/java/com/zy/asrs/controller/CrnController.java | 2
src/main/java/com/zy/core/thread/DualCrnThread.java | 2
src/main/java/com/zy/asrs/controller/StationController.java | 90 +
src/main/java/com/zy/asrs/controller/ConsoleController.java | 16
src/main/java/com/zy/core/enums/WrkStsType.java | 1
src/main/java/com/zy/asrs/domain/enums/NotifyMsgType.java | 1
src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java | 3
src/main/java/com/zy/system/entity/license/WindowsServerInfos.java | 8
src/main/java/com/zy/core/enums/RedisKeyType.java | 13
src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java | 117 +
src/main/resources/application.yml | 8
61 files changed, 3,053 insertions(+), 762 deletions(-)
diff --git a/src/main/java/com/zy/ai/controller/WcsDiagnosisController.java b/src/main/java/com/zy/ai/controller/WcsDiagnosisController.java
index 15857a0..127c9ed 100644
--- a/src/main/java/com/zy/ai/controller/WcsDiagnosisController.java
+++ b/src/main/java/com/zy/ai/controller/WcsDiagnosisController.java
@@ -33,7 +33,7 @@
WcsDiagnosisRequest request = aiUtils.makeAiRequest(1000, "瀵瑰綋鍓嶇郴缁熻繘琛屽贰妫�锛屽鏋滄湁寮傚父鎯呭喌灏辫繘琛岃缁嗙殑鍒嗘瀽锛屽鏋滄病鏈夊紓甯告儏鍐靛垯褰撴垚涓�娆℃鏌n\n");
wcsDiagnosisService.diagnoseStream(request, emitter);
} catch (Exception e) {
- emitter.completeWithError(e);
+ try { emitter.complete(); } catch (Exception ignore) {}
}
}).start();
@@ -50,7 +50,7 @@
WcsDiagnosisRequest request = aiUtils.makeAiRequest(100, null);
wcsDiagnosisService.askStream(request, prompt, chatId, reset, emitter);
} catch (Exception e) {
- emitter.completeWithError(e);
+ try { emitter.complete(); } catch (Exception ignore) {}
}
}).start();
return emitter;
diff --git a/src/main/java/com/zy/ai/service/LlmChatService.java b/src/main/java/com/zy/ai/service/LlmChatService.java
index ddb333a..3e25561 100644
--- a/src/main/java/com/zy/ai/service/LlmChatService.java
+++ b/src/main/java/com/zy/ai/service/LlmChatService.java
@@ -1,7 +1,12 @@
package com.zy.ai.service;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
import com.zy.ai.entity.ChatCompletionRequest;
import com.zy.ai.entity.ChatCompletionResponse;
+import com.zy.ai.entity.LlmCallLog;
+import com.zy.ai.entity.LlmRouteConfig;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
@@ -9,37 +14,38 @@
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
-import reactor.core.publisher.Mono;
import reactor.core.publisher.Flux;
-import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Date;
import java.util.List;
-import java.util.function.Consumer;
+import java.util.UUID;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import com.alibaba.fastjson.JSON;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
+import java.util.function.Consumer;
@Slf4j
@Service
@RequiredArgsConstructor
public class LlmChatService {
- private final WebClient llmWebClient;
+ private static final int LOG_TEXT_LIMIT = 16000;
- @Value("${llm.api-key}")
- private String apiKey;
+ private final LlmRoutingService llmRoutingService;
+ private final LlmCallLogService llmCallLogService;
- @Value("${llm.model}")
- private String model;
+ @Value("${llm.base-url:}")
+ private String fallbackBaseUrl;
- @Value("${llm.pythonPlatformUrl}")
- private String pythonPlatformUrl;
+ @Value("${llm.api-key:}")
+ private String fallbackApiKey;
- @Value("${llm.thinking}")
- private String thinking;
+ @Value("${llm.model:}")
+ private String fallbackModel;
+
+ @Value("${llm.thinking:false}")
+ private String fallbackThinking;
/**
* 閫氱敤瀵硅瘽鏂规硶锛氫紶鍏� messages锛岃繑鍥炲ぇ妯″瀷鏂囨湰鍥炲
@@ -49,27 +55,12 @@
Integer maxTokens) {
ChatCompletionRequest req = new ChatCompletionRequest();
- req.setModel(model);
req.setMessages(messages);
req.setTemperature(temperature != null ? temperature : 0.3);
req.setMax_tokens(maxTokens != null ? maxTokens : 1024);
req.setStream(false);
- ChatCompletionResponse response = llmWebClient.post()
- .uri("/chat/completions")
- .header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON, MediaType.TEXT_EVENT_STREAM)
- .bodyValue(req)
- .exchangeToMono(resp -> resp.bodyToFlux(String.class)
- .collectList()
- .map(list -> {
- String payload = String.join("\n\n", list);
- return parseCompletion(payload);
- }))
- .doOnError(ex -> log.error("璋冪敤 LLM 澶辫触", ex))
- .onErrorResume(ex -> Mono.empty())
- .block();
+ ChatCompletionResponse response = complete(req, "chat");
if (response == null ||
response.getChoices() == null ||
@@ -88,45 +79,81 @@
Integer maxTokens,
List<Object> tools) {
ChatCompletionRequest req = new ChatCompletionRequest();
- req.setModel(model);
req.setMessages(messages);
req.setTemperature(temperature != null ? temperature : 0.3);
req.setMax_tokens(maxTokens != null ? maxTokens : 1024);
req.setStream(false);
-
- if(thinking.equals("enable")) {
- ChatCompletionRequest.Thinking thinking = new ChatCompletionRequest.Thinking();
- thinking.setType("enable");
- req.setThinking(thinking);
- }
if (tools != null && !tools.isEmpty()) {
req.setTools(tools);
req.setTool_choice("auto");
}
- return complete(req);
+ return complete(req, tools != null && !tools.isEmpty() ? "chat_completion_tools" : "chat_completion");
}
public ChatCompletionResponse complete(ChatCompletionRequest req) {
- try {
- return llmWebClient.post()
- .uri("/chat/completions")
- .header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.APPLICATION_JSON, MediaType.TEXT_EVENT_STREAM)
- .bodyValue(req)
- .exchangeToMono(resp -> resp.bodyToFlux(String.class)
- .collectList()
- .map(list -> {
- String payload = String.join("\n\n", list);
- return parseCompletion(payload);
- }))
- .doOnError(ex -> log.error("璋冪敤 LLM 澶辫触", ex))
- .onErrorResume(ex -> Mono.empty())
- .block();
- } catch (Exception e) {
- log.error("璋冪敤 LLM 澶辫触", e);
+ return complete(req, "completion");
+ }
+
+ private ChatCompletionResponse complete(ChatCompletionRequest req, String scene) {
+ String traceId = nextTraceId();
+ List<ResolvedRoute> routes = resolveRoutes();
+ if (routes.isEmpty()) {
+ log.error("璋冪敤 LLM 澶辫触: 鏈厤缃彲鐢� LLM 璺敱");
+ recordCall(traceId, scene, false, 1, null, false, null, 0L, req, null, "none",
+ new RuntimeException("鏈厤缃彲鐢� LLM 璺敱"), "no_route");
return null;
}
+
+ Throwable last = null;
+ for (int i = 0; i < routes.size(); i++) {
+ ResolvedRoute route = routes.get(i);
+ boolean hasNext = i < routes.size() - 1;
+ ChatCompletionRequest routeReq = applyRoute(cloneRequest(req), route, false);
+ long start = System.currentTimeMillis();
+ try {
+ CompletionCallResult callResult = callCompletion(route, routeReq);
+ ChatCompletionResponse resp = callResult.response;
+ if (!isValidCompletion(resp)) {
+ RuntimeException ex = new RuntimeException("LLM 鍝嶅簲涓虹┖");
+ boolean canSwitch = shouldSwitch(route, false);
+ markFailure(route, ex, canSwitch);
+ recordCall(traceId, scene, false, i + 1, route, false, callResult.statusCode,
+ System.currentTimeMillis() - start, routeReq, callResult.payload, "error", ex,
+ "invalid_completion");
+ if (hasNext && canSwitch) {
+ log.warn("LLM 鍒囨崲鍒颁笅涓�璺敱, current={}, reason={}", route.tag(), ex.getMessage());
+ continue;
+ }
+ log.error("璋冪敤 LLM 澶辫触, route={}", route.tag(), ex);
+ last = ex;
+ break;
+ }
+ markSuccess(route);
+ recordCall(traceId, scene, false, i + 1, route, true, callResult.statusCode,
+ System.currentTimeMillis() - start, routeReq, buildResponseText(resp, callResult.payload),
+ "none", null, null);
+ return resp;
+ } catch (Throwable ex) {
+ last = ex;
+ boolean quota = isQuotaExhausted(ex);
+ boolean canSwitch = shouldSwitch(route, quota);
+ markFailure(route, ex, canSwitch);
+ recordCall(traceId, scene, false, i + 1, route, false, statusCodeOf(ex),
+ System.currentTimeMillis() - start, routeReq, responseBodyOf(ex),
+ quota ? "quota" : "error", ex, null);
+ if (hasNext && canSwitch) {
+ log.warn("LLM 鍒囨崲鍒颁笅涓�璺敱, current={}, reason={}", route.tag(), errorText(ex));
+ continue;
+ }
+ log.error("璋冪敤 LLM 澶辫触, route={}", route.tag(), ex);
+ break;
+ }
+ }
+
+ if (last != null) {
+ log.error("璋冪敤 LLM 鍏ㄩ儴璺敱澶辫触: {}", errorText(last));
+ }
+ return null;
}
public void chatStream(List<ChatCompletionRequest.Message> messages,
@@ -137,92 +164,12 @@
Consumer<Throwable> onError) {
ChatCompletionRequest req = new ChatCompletionRequest();
- req.setModel(model);
req.setMessages(messages);
req.setTemperature(temperature != null ? temperature : 0.3);
req.setMax_tokens(maxTokens != null ? maxTokens : 1024);
req.setStream(true);
-
- Flux<String> flux = llmWebClient.post()
- .uri("/chat/completions")
- .header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.TEXT_EVENT_STREAM)
- .bodyValue(req)
- .retrieve()
- .bodyToFlux(String.class)
- .doOnError(ex -> log.error("璋冪敤 LLM 娴佸紡澶辫触", ex));
-
- AtomicBoolean doneSeen = new AtomicBoolean(false);
- AtomicBoolean errorSeen = new AtomicBoolean(false);
- LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
-
- Thread drain = new Thread(() -> {
- try {
- while (true) {
- String s = queue.poll(2, TimeUnit.SECONDS);
- if (s != null) {
- try { onChunk.accept(s); } catch (Exception ignore) {}
- }
- if (doneSeen.get() && queue.isEmpty()) {
- if (!errorSeen.get()) {
- try { if (onComplete != null) onComplete.run(); } catch (Exception ignore) {}
- }
- break;
- }
- }
- } catch (InterruptedException ignore) {
- ignore.printStackTrace();
- }
- });
- drain.setDaemon(true);
- drain.start();
-
- flux.subscribe(payload -> {
- if (payload == null || payload.isEmpty()) return;
- String[] events = payload.split("\\r?\\n\\r?\\n");
- for (String part : events) {
- String s = part;
- if (s == null || s.isEmpty()) continue;
- if (s.startsWith("data:")) {
- s = s.substring(5);
- if (s.startsWith(" ")) s = s.substring(1);
- }
- if ("[DONE]".equals(s.trim())) {
- doneSeen.set(true);
- continue;
- }
- try {
- JSONObject obj = JSON.parseObject(s);
- JSONArray choices = obj.getJSONArray("choices");
- if (choices != null && !choices.isEmpty()) {
- JSONObject c0 = choices.getJSONObject(0);
- JSONObject delta = c0.getJSONObject("delta");
- if (delta != null) {
- String content = delta.getString("content");
- if (content != null) {
- try { queue.offer(content); } catch (Exception ignore) {}
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }, err -> {
- errorSeen.set(true);
- doneSeen.set(true);
- if (onError != null) onError.accept(err);
- }, () -> {
- if (!doneSeen.get()) {
- errorSeen.set(true);
- doneSeen.set(true);
- if (onError != null) onError.accept(new RuntimeException("LLM 娴佹剰澶栧畬鎴�"));
- } else {
- doneSeen.set(true);
- }
- });
+ streamWithFailover(req, onChunk, onComplete, onError, "chat_stream");
}
public void chatStreamWithTools(List<ChatCompletionRequest.Message> messages,
@@ -233,120 +180,54 @@
Runnable onComplete,
Consumer<Throwable> onError) {
ChatCompletionRequest req = new ChatCompletionRequest();
- req.setModel(model);
req.setMessages(messages);
req.setTemperature(temperature != null ? temperature : 0.3);
req.setMax_tokens(maxTokens != null ? maxTokens : 1024);
req.setStream(true);
- if(thinking.equals("enable")) {
- ChatCompletionRequest.Thinking thinking = new ChatCompletionRequest.Thinking();
- thinking.setType("enable");
- req.setThinking(thinking);
- }
if (tools != null && !tools.isEmpty()) {
req.setTools(tools);
req.setTool_choice("auto");
}
- Flux<String> flux = llmWebClient.post()
- .uri("/chat/completions")
- .header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.TEXT_EVENT_STREAM)
- .bodyValue(req)
- .retrieve()
- .bodyToFlux(String.class)
- .doOnError(ex -> log.error("璋冪敤 LLM 娴佸紡澶辫触", ex));
-
- AtomicBoolean doneSeen = new AtomicBoolean(false);
- AtomicBoolean errorSeen = new AtomicBoolean(false);
- LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
-
- Thread drain = new Thread(() -> {
- try {
- while (true) {
- String s = queue.poll(5, TimeUnit.SECONDS);
- if (s != null) {
- try { onChunk.accept(s); } catch (Exception ignore) {}
- }
- if (doneSeen.get() && queue.isEmpty()) {
- if (!errorSeen.get()) {
- try { if (onComplete != null) onComplete.run(); } catch (Exception ignore) {}
- }
- break;
- }
- }
- } catch (InterruptedException ignore) {
- ignore.printStackTrace();
- }
- });
- drain.setDaemon(true);
- drain.start();
-
- flux.subscribe(payload -> {
- if (payload == null || payload.isEmpty()) return;
- String[] events = payload.split("\\r?\\n\\r?\\n");
- for (String part : events) {
- String s = part;
- if (s == null || s.isEmpty()) continue;
- if (s.startsWith("data:")) {
- s = s.substring(5);
- if (s.startsWith(" ")) s = s.substring(1);
- }
- if ("[DONE]".equals(s.trim())) {
- doneSeen.set(true);
- continue;
- }
- try {
- JSONObject obj = JSON.parseObject(s);
- JSONArray choices = obj.getJSONArray("choices");
- if (choices != null && !choices.isEmpty()) {
- JSONObject c0 = choices.getJSONObject(0);
- JSONObject delta = c0.getJSONObject("delta");
- if (delta != null) {
- String content = delta.getString("content");
- if (content != null) {
- try { queue.offer(content); } catch (Exception ignore) {}
- }
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }, err -> {
- errorSeen.set(true);
- doneSeen.set(true);
- if (onError != null) onError.accept(err);
- }, () -> {
- if (!doneSeen.get()) {
- errorSeen.set(true);
- doneSeen.set(true);
- if (onError != null) onError.accept(new RuntimeException("LLM 娴佹剰澶栧畬鎴�"));
- } else {
- doneSeen.set(true);
- }
- });
+ streamWithFailover(req, onChunk, onComplete, onError, tools != null && !tools.isEmpty() ? "chat_stream_tools" : "chat_stream");
}
- public void chatStreamRunPython(String prompt, String chatId, Consumer<String> onChunk,
+ private void streamWithFailover(ChatCompletionRequest req,
+ Consumer<String> onChunk,
Runnable onComplete,
- Consumer<Throwable> onError) {
- HashMap<String, Object> req = new HashMap<>();
- req.put("prompt", prompt);
- req.put("chatId", chatId);
+ Consumer<Throwable> onError,
+ String scene) {
+ String traceId = nextTraceId();
+ List<ResolvedRoute> routes = resolveRoutes();
+ if (routes.isEmpty()) {
+ recordCall(traceId, scene, true, 1, null, false, null, 0L, req, null, "none",
+ new RuntimeException("鏈厤缃彲鐢� LLM 璺敱"), "no_route");
+ if (onError != null) onError.accept(new RuntimeException("鏈厤缃彲鐢� LLM 璺敱"));
+ return;
+ }
+ attemptStream(routes, 0, req, onChunk, onComplete, onError, traceId, scene);
+ }
- Flux<String> flux = llmWebClient.post()
- .uri(pythonPlatformUrl)
- .header(HttpHeaders.AUTHORIZATION, "Bearer " + apiKey)
- .contentType(MediaType.APPLICATION_JSON)
- .accept(MediaType.TEXT_EVENT_STREAM)
- .bodyValue(req)
- .retrieve()
- .bodyToFlux(String.class)
- .doOnError(ex -> log.error("璋冪敤 LLM 娴佸紡澶辫触", ex));
+ private void attemptStream(List<ResolvedRoute> routes,
+ int index,
+ ChatCompletionRequest req,
+ Consumer<String> onChunk,
+ Runnable onComplete,
+ Consumer<Throwable> onError,
+ String traceId,
+ String scene) {
+ if (index >= routes.size()) {
+ if (onError != null) onError.accept(new RuntimeException("LLM 璺敱鍏ㄩ儴澶辫触"));
+ return;
+ }
+
+ ResolvedRoute route = routes.get(index);
+ ChatCompletionRequest routeReq = applyRoute(cloneRequest(req), route, true);
+ long start = System.currentTimeMillis();
+ StringBuilder outputBuffer = new StringBuilder();
AtomicBoolean doneSeen = new AtomicBoolean(false);
AtomicBoolean errorSeen = new AtomicBoolean(false);
+ AtomicBoolean emitted = new AtomicBoolean(false);
LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<>();
Thread drain = new Thread(() -> {
@@ -354,6 +235,7 @@
while (true) {
String s = queue.poll(2, TimeUnit.SECONDS);
if (s != null) {
+ emitted.set(true);
try {
onChunk.accept(s);
} catch (Exception ignore) {
@@ -370,13 +252,12 @@
}
}
} catch (InterruptedException ignore) {
- ignore.printStackTrace();
}
});
drain.setDaemon(true);
drain.start();
- flux.subscribe(payload -> {
+ streamFlux(route, routeReq).subscribe(payload -> {
if (payload == null || payload.isEmpty()) return;
String[] events = payload.split("\\r?\\n\\r?\\n");
for (String part : events) {
@@ -390,10 +271,6 @@
doneSeen.set(true);
continue;
}
- if("<think>".equals(s.trim()) || "</think>".equals(s.trim())) {
- queue.offer(s.trim());
- continue;
- }
try {
JSONObject obj = JSON.parseObject(s);
JSONArray choices = obj.getJSONArray("choices");
@@ -403,30 +280,200 @@
if (delta != null) {
String content = delta.getString("content");
if (content != null) {
- try {
- queue.offer(content);
- } catch (Exception ignore) {
- }
+ queue.offer(content);
+ appendLimited(outputBuffer, content);
}
}
}
} catch (Exception e) {
- e.printStackTrace();
+ log.warn("瑙f瀽 LLM stream 鐗囨澶辫触: {}", e.getMessage());
}
}
}, err -> {
errorSeen.set(true);
doneSeen.set(true);
+ boolean quota = isQuotaExhausted(err);
+ boolean canSwitch = shouldSwitch(route, quota);
+ markFailure(route, err, canSwitch);
+ recordCall(traceId, scene, true, index + 1, route, false, statusCodeOf(err),
+ System.currentTimeMillis() - start, routeReq, outputBuffer.toString(),
+ quota ? "quota" : "error", err, "emitted=" + emitted.get());
+ if (!emitted.get() && canSwitch && index < routes.size() - 1) {
+ log.warn("LLM 璺敱澶辫触锛岃嚜鍔ㄥ垏鎹紝current={}, reason={}", route.tag(), errorText(err));
+ attemptStream(routes, index + 1, req, onChunk, onComplete, onError, traceId, scene);
+ return;
+ }
if (onError != null) onError.accept(err);
}, () -> {
if (!doneSeen.get()) {
+ RuntimeException ex = new RuntimeException("LLM 娴佹剰澶栧畬鎴�");
errorSeen.set(true);
doneSeen.set(true);
- if (onError != null) onError.accept(new RuntimeException("LLM 娴佹剰澶栧畬鎴�"));
+ boolean canSwitch = shouldSwitch(route, false);
+ markFailure(route, ex, canSwitch);
+ recordCall(traceId, scene, true, index + 1, route, false, 200,
+ System.currentTimeMillis() - start, routeReq, outputBuffer.toString(),
+ "error", ex, "unexpected_stream_end");
+ if (!emitted.get() && canSwitch && index < routes.size() - 1) {
+ log.warn("LLM 璺敱娴佸紓甯稿畬鎴愶紝鑷姩鍒囨崲锛宑urrent={}", route.tag());
+ attemptStream(routes, index + 1, req, onChunk, onComplete, onError, traceId, scene);
+ } else {
+ if (onError != null) onError.accept(ex);
+ }
} else {
+ markSuccess(route);
+ recordCall(traceId, scene, true, index + 1, route, true, 200,
+ System.currentTimeMillis() - start, routeReq, outputBuffer.toString(),
+ "none", null, null);
doneSeen.set(true);
}
});
+ }
+
+ private Flux<String> streamFlux(ResolvedRoute route, ChatCompletionRequest req) {
+ WebClient client = WebClient.builder().baseUrl(route.baseUrl).build();
+ return client.post()
+ .uri("/chat/completions")
+ .header(HttpHeaders.AUTHORIZATION, "Bearer " + route.apiKey)
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.TEXT_EVENT_STREAM)
+ .bodyValue(req)
+ .exchangeToFlux(resp -> {
+ int status = resp.rawStatusCode();
+ if (status >= 200 && status < 300) {
+ return resp.bodyToFlux(String.class);
+ }
+ return resp.bodyToMono(String.class)
+ .defaultIfEmpty("")
+ .flatMapMany(body -> Flux.error(new LlmRouteException(status, body)));
+ })
+ .doOnError(ex -> log.error("璋冪敤 LLM 娴佸紡澶辫触, route={}", route.tag(), ex));
+ }
+
+ private CompletionCallResult callCompletion(ResolvedRoute route, ChatCompletionRequest req) {
+ WebClient client = WebClient.builder().baseUrl(route.baseUrl).build();
+ RawCompletionResult raw = client.post()
+ .uri("/chat/completions")
+ .header(HttpHeaders.AUTHORIZATION, "Bearer " + route.apiKey)
+ .contentType(MediaType.APPLICATION_JSON)
+ .accept(MediaType.APPLICATION_JSON, MediaType.TEXT_EVENT_STREAM)
+ .bodyValue(req)
+ .exchangeToMono(resp -> resp.bodyToFlux(String.class)
+ .collectList()
+ .map(list -> new RawCompletionResult(resp.rawStatusCode(), String.join("\\n\\n", list))))
+ .block();
+
+ if (raw == null) {
+ throw new RuntimeException("LLM 杩斿洖涓虹┖");
+ }
+ if (raw.statusCode < 200 || raw.statusCode >= 300) {
+ throw new LlmRouteException(raw.statusCode, raw.payload);
+ }
+ return new CompletionCallResult(raw.statusCode, raw.payload, parseCompletion(raw.payload));
+ }
+
+ private ChatCompletionRequest applyRoute(ChatCompletionRequest req, ResolvedRoute route, boolean stream) {
+ req.setModel(route.model);
+ req.setStream(stream);
+ if (route.thinkingEnabled) {
+ ChatCompletionRequest.Thinking t = new ChatCompletionRequest.Thinking();
+ t.setType("enable");
+ req.setThinking(t);
+ } else {
+ req.setThinking(null);
+ }
+ return req;
+ }
+
+ private ChatCompletionRequest cloneRequest(ChatCompletionRequest src) {
+ ChatCompletionRequest req = new ChatCompletionRequest();
+ req.setModel(src.getModel());
+ req.setMessages(src.getMessages());
+ req.setTemperature(src.getTemperature());
+ req.setMax_tokens(src.getMax_tokens());
+ req.setStream(src.getStream());
+ req.setTools(src.getTools());
+ req.setTool_choice(src.getTool_choice());
+ req.setThinking(src.getThinking());
+ return req;
+ }
+
+ private boolean isValidCompletion(ChatCompletionResponse response) {
+ if (response == null || response.getChoices() == null || response.getChoices().isEmpty()) {
+ return false;
+ }
+ ChatCompletionRequest.Message message = response.getChoices().get(0).getMessage();
+ if (message == null) {
+ return false;
+ }
+ if (!isBlank(message.getContent())) {
+ return true;
+ }
+ return message.getTool_calls() != null && !message.getTool_calls().isEmpty();
+ }
+
+ private boolean shouldSwitch(ResolvedRoute route, boolean quota) {
+ return quota ? route.switchOnQuota : route.switchOnError;
+ }
+
+ private void markSuccess(ResolvedRoute route) {
+ if (route.id != null) {
+ llmRoutingService.markSuccess(route.id);
+ }
+ }
+
+ private void markFailure(ResolvedRoute route, Throwable ex, boolean enterCooldown) {
+ if (route.id != null) {
+ llmRoutingService.markFailure(route.id, errorText(ex), enterCooldown, route.cooldownSeconds);
+ }
+ }
+
+ private String errorText(Throwable ex) {
+ if (ex == null) return "unknown";
+ if (ex instanceof LlmRouteException) {
+ LlmRouteException e = (LlmRouteException) ex;
+ String body = e.body == null ? "" : e.body;
+ if (body.length() > 240) {
+ body = body.substring(0, 240);
+ }
+ return "status=" + e.statusCode + ", body=" + body;
+ }
+ return ex.getMessage() == null ? ex.toString() : ex.getMessage();
+ }
+
+ private boolean isQuotaExhausted(Throwable ex) {
+ if (!(ex instanceof LlmRouteException)) return false;
+ LlmRouteException e = (LlmRouteException) ex;
+ if (e.statusCode == 429) return true;
+ String text = (e.body == null ? "" : e.body).toLowerCase();
+ return text.contains("insufficient_quota")
+ || text.contains("quota")
+ || text.contains("浣欓")
+ || text.contains("鐢ㄩ噺")
+ || text.contains("瓒呴檺")
+ || text.contains("rate limit");
+ }
+
+ private List<ResolvedRoute> resolveRoutes() {
+ List<ResolvedRoute> routes = new ArrayList<>();
+ List<LlmRouteConfig> dbRoutes = llmRoutingService.listAvailableRoutes();
+ for (LlmRouteConfig c : dbRoutes) {
+ routes.add(ResolvedRoute.fromDb(c));
+ }
+ // 鍏煎锛氭暟鎹簱涓虹┖鏃讹紝鍥為��鍒� yml
+ if (routes.isEmpty() && !isBlank(fallbackBaseUrl) && !isBlank(fallbackApiKey) && !isBlank(fallbackModel)) {
+ routes.add(ResolvedRoute.fromFallback(fallbackBaseUrl, fallbackApiKey, fallbackModel, isFallbackThinkingEnabled()));
+ }
+ return routes;
+ }
+
+ private boolean isFallbackThinkingEnabled() {
+ String x = fallbackThinking == null ? "" : fallbackThinking.trim().toLowerCase();
+ return "true".equals(x) || "1".equals(x) || "enable".equals(x);
+ }
+
+ private boolean isBlank(String s) {
+ return s == null || s.trim().isEmpty();
}
private ChatCompletionResponse mergeSseChunk(ChatCompletionResponse acc, String payload) {
@@ -452,7 +499,7 @@
ChatCompletionResponse.Choice choice = new ChatCompletionResponse.Choice();
ChatCompletionRequest.Message msg = new ChatCompletionRequest.Message();
choice.setMessage(msg);
- java.util.ArrayList<ChatCompletionResponse.Choice> list = new java.util.ArrayList<>();
+ ArrayList<ChatCompletionResponse.Choice> list = new ArrayList<>();
list.add(choice);
acc.setChoices(list);
}
@@ -490,7 +537,8 @@
if (created != null) acc.setCreated(created);
String object = obj.getString("object");
if (object != null && !object.isEmpty()) acc.setObjectName(object);
- } catch (Exception ignore) {}
+ } catch (Exception ignore) {
+ }
}
return acc;
}
@@ -502,7 +550,8 @@
if (r != null && r.getChoices() != null && !r.getChoices().isEmpty() && r.getChoices().get(0).getMessage() != null) {
return r;
}
- } catch (Exception ignore) {}
+ } catch (Exception ignore) {
+ }
ChatCompletionResponse sse = mergeSseChunk(new ChatCompletionResponse(), payload);
if (sse.getChoices() != null && !sse.getChoices().isEmpty() && sse.getChoices().get(0).getMessage() != null && sse.getChoices().get(0).getMessage().getContent() != null) {
return sse;
@@ -513,9 +562,181 @@
msg.setRole("assistant");
msg.setContent(payload);
choice.setMessage(msg);
- java.util.ArrayList<ChatCompletionResponse.Choice> list = new java.util.ArrayList<>();
+ ArrayList<ChatCompletionResponse.Choice> list = new ArrayList<>();
list.add(choice);
r.setChoices(list);
return r;
}
+
+ private String nextTraceId() {
+ return UUID.randomUUID().toString().replace("-", "");
+ }
+
+ private void appendLimited(StringBuilder sb, String text) {
+ if (sb == null || text == null || text.isEmpty()) {
+ return;
+ }
+ int remain = LOG_TEXT_LIMIT - sb.length();
+ if (remain <= 0) {
+ return;
+ }
+ if (text.length() <= remain) {
+ sb.append(text);
+ } else {
+ sb.append(text, 0, remain);
+ }
+ }
+
+ private Integer statusCodeOf(Throwable ex) {
+ if (ex instanceof LlmRouteException) {
+ return ((LlmRouteException) ex).statusCode;
+ }
+ return null;
+ }
+
+ private String responseBodyOf(Throwable ex) {
+ if (ex instanceof LlmRouteException) {
+ return cut(((LlmRouteException) ex).body, LOG_TEXT_LIMIT);
+ }
+ return null;
+ }
+
+ private String buildResponseText(ChatCompletionResponse resp, String fallbackPayload) {
+ if (resp != null && resp.getChoices() != null && !resp.getChoices().isEmpty()
+ && resp.getChoices().get(0) != null && resp.getChoices().get(0).getMessage() != null) {
+ ChatCompletionRequest.Message m = resp.getChoices().get(0).getMessage();
+ if (!isBlank(m.getContent())) {
+ return cut(m.getContent(), LOG_TEXT_LIMIT);
+ }
+ if (m.getTool_calls() != null && !m.getTool_calls().isEmpty()) {
+ return cut(JSON.toJSONString(m), LOG_TEXT_LIMIT);
+ }
+ }
+ return cut(fallbackPayload, LOG_TEXT_LIMIT);
+ }
+
+ private String safeName(Throwable ex) {
+ return ex == null ? null : ex.getClass().getSimpleName();
+ }
+
+ private String cut(String text, int maxLen) {
+ if (text == null) return null;
+ String clean = text.replace("\r", " ");
+ return clean.length() > maxLen ? clean.substring(0, maxLen) : clean;
+ }
+
+ private void recordCall(String traceId,
+ String scene,
+ boolean stream,
+ int attemptNo,
+ ResolvedRoute route,
+ boolean success,
+ Integer httpStatus,
+ long latencyMs,
+ ChatCompletionRequest req,
+ String response,
+ String switchMode,
+ Throwable err,
+ String extra) {
+ LlmCallLog item = new LlmCallLog();
+ item.setTraceId(cut(traceId, 64));
+ item.setScene(cut(scene, 64));
+ item.setStream((short) (stream ? 1 : 0));
+ item.setAttemptNo(attemptNo);
+ if (route != null) {
+ item.setRouteId(route.id);
+ item.setRouteName(cut(route.name, 128));
+ item.setBaseUrl(cut(route.baseUrl, 255));
+ item.setModel(cut(route.model, 128));
+ }
+ item.setSuccess((short) (success ? 1 : 0));
+ item.setHttpStatus(httpStatus);
+ item.setLatencyMs(latencyMs < 0 ? 0 : latencyMs);
+ item.setSwitchMode(cut(switchMode, 32));
+ item.setRequestContent(cut(JSON.toJSONString(req), LOG_TEXT_LIMIT));
+ item.setResponseContent(cut(response, LOG_TEXT_LIMIT));
+ item.setErrorType(cut(safeName(err), 128));
+ item.setErrorMessage(err == null ? null : cut(errorText(err), 1024));
+ item.setExtra(cut(extra, 512));
+ item.setCreateTime(new Date());
+ llmCallLogService.saveIgnoreError(item);
+ }
+
+ private static class CompletionCallResult {
+ private final int statusCode;
+ private final String payload;
+ private final ChatCompletionResponse response;
+
+ private CompletionCallResult(int statusCode, String payload, ChatCompletionResponse response) {
+ this.statusCode = statusCode;
+ this.payload = payload;
+ this.response = response;
+ }
+ }
+
+ private static class RawCompletionResult {
+ private final int statusCode;
+ private final String payload;
+
+ private RawCompletionResult(int statusCode, String payload) {
+ this.statusCode = statusCode;
+ this.payload = payload;
+ }
+ }
+
+ private static class LlmRouteException extends RuntimeException {
+ private final int statusCode;
+ private final String body;
+
+ private LlmRouteException(int statusCode, String body) {
+ super("http status=" + statusCode);
+ this.statusCode = statusCode;
+ this.body = body;
+ }
+ }
+
+ private static class ResolvedRoute {
+ private Long id;
+ private String name;
+ private String baseUrl;
+ private String apiKey;
+ private String model;
+ private boolean thinkingEnabled;
+ private boolean switchOnQuota;
+ private boolean switchOnError;
+ private Integer cooldownSeconds;
+
+ private static ResolvedRoute fromDb(LlmRouteConfig c) {
+ ResolvedRoute r = new ResolvedRoute();
+ r.id = c.getId();
+ r.name = c.getName();
+ r.baseUrl = c.getBaseUrl();
+ r.apiKey = c.getApiKey();
+ r.model = c.getModel();
+ r.thinkingEnabled = c.getThinking() != null && c.getThinking() == 1;
+ r.switchOnQuota = c.getSwitchOnQuota() == null || c.getSwitchOnQuota() == 1;
+ r.switchOnError = c.getSwitchOnError() == null || c.getSwitchOnError() == 1;
+ r.cooldownSeconds = c.getCooldownSeconds();
+ return r;
+ }
+
+ private static ResolvedRoute fromFallback(String baseUrl, String apiKey, String model, boolean thinkingEnabled) {
+ ResolvedRoute r = new ResolvedRoute();
+ r.name = "fallback-yml";
+ r.baseUrl = baseUrl;
+ r.apiKey = apiKey;
+ r.model = model;
+ r.thinkingEnabled = thinkingEnabled;
+ r.switchOnQuota = true;
+ r.switchOnError = true;
+ r.cooldownSeconds = 300;
+ return r;
+ }
+
+ private String tag() {
+ String showName = name == null ? "unnamed" : name;
+ String showModel = model == null ? "" : (" model=" + model);
+ return showName + showModel;
+ }
+ }
}
diff --git a/src/main/java/com/zy/ai/service/PythonService.java b/src/main/java/com/zy/ai/service/PythonService.java
index adc712b..82b77a9 100644
--- a/src/main/java/com/zy/ai/service/PythonService.java
+++ b/src/main/java/com/zy/ai/service/PythonService.java
@@ -12,36 +12,36 @@
@Autowired
private LlmChatService llmChatService;
- public boolean runPython(String prompt, String chatId, SseEmitter emitter) {
- try {
- llmChatService.chatStreamRunPython(prompt, chatId, s -> {
- try {
- String safe = s == null ? "" : s.replace("\r", "").replace("\n", "\\n");
- if (!safe.isEmpty()) {
- sse(emitter, safe);
- }
- } catch (Exception ignore) {
- }
- }, () -> {
- try {
- sse(emitter, "\\n\\n銆怉I銆戣繍琛屽凡鍋滄锛堟甯哥粨鏉燂級\\n\\n");
- log.info("AI MCP diagnose stopped: final end");
- emitter.complete();
- } catch (Exception ignore) {
- }
- }, e -> {
- sse(emitter, "\\n\\n銆怉I銆戝垎鏋愬嚭閿欙紝姝e湪鍥為��...\\n\\n");
- });
- return true;
- } catch (Exception e) {
- try {
- sse(emitter, "\\n\\n銆怉I銆戣繍琛屽凡鍋滄锛堝紓甯革級\\n\\n");
- log.error("AI MCP diagnose stopped: error", e);
- emitter.completeWithError(e);
- } catch (Exception ignore) {}
- return true;
- }
- }
+// public boolean runPython(String prompt, String chatId, SseEmitter emitter) {
+// try {
+// llmChatService.chatStreamRunPython(prompt, chatId, s -> {
+// try {
+// String safe = s == null ? "" : s.replace("\r", "").replace("\n", "\\n");
+// if (!safe.isEmpty()) {
+// sse(emitter, safe);
+// }
+// } catch (Exception ignore) {
+// }
+// }, () -> {
+// try {
+// sse(emitter, "\\n\\n銆怉I銆戣繍琛屽凡鍋滄锛堟甯哥粨鏉燂級\\n\\n");
+// log.info("AI MCP diagnose stopped: final end");
+// emitter.complete();
+// } catch (Exception ignore) {
+// }
+// }, e -> {
+// sse(emitter, "\\n\\n銆怉I銆戝垎鏋愬嚭閿欙紝姝e湪鍥為��...\\n\\n");
+// });
+// return true;
+// } catch (Exception e) {
+// try {
+// sse(emitter, "\\n\\n銆怉I銆戣繍琛屽凡鍋滄锛堝紓甯革級\\n\\n");
+// log.error("AI MCP diagnose stopped: error", e);
+// emitter.completeWithError(e);
+// } catch (Exception ignore) {}
+// return true;
+// }
+// }
private void sse(SseEmitter emitter, String data) {
if (data == null) return;
diff --git a/src/main/java/com/zy/ai/service/WcsDiagnosisService.java b/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
index 189e57d..45dea58 100644
--- a/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
+++ b/src/main/java/com/zy/ai/service/WcsDiagnosisService.java
@@ -11,7 +11,6 @@
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
@@ -28,8 +27,6 @@
private static final long CHAT_TTL_SECONDS = 7L * 24 * 3600;
- @Value("${llm.platform}")
- private String platform;
@Autowired
private LlmChatService llmChatService;
@Autowired
@@ -40,8 +37,6 @@
private AiUtils aiUtils;
@Autowired(required = false)
private McpController mcpController;
- @Autowired
- private PythonService pythonService;
public void diagnoseStream(WcsDiagnosisRequest request, SseEmitter emitter) {
List<ChatCompletionRequest.Message> messages = new ArrayList<>();
@@ -85,7 +80,7 @@
try {
try { emitter.send(SseEmitter.event().data("銆怉I銆戣繍琛屽凡鍋滄锛堝紓甯革級")); } catch (Exception ignore) {}
log.error("AI diagnose stream stopped: error", e);
- emitter.completeWithError(e);
+ emitter.complete();
} catch (Exception ignore) {}
});
}
@@ -95,11 +90,6 @@
String chatId,
boolean reset,
SseEmitter emitter) {
- if (platform.equals("python")) {
- pythonService.runPython(prompt, chatId, emitter);
- return;
- }
-
List<ChatCompletionRequest.Message> messages = new ArrayList<>();
List<ChatCompletionRequest.Message> history = null;
@@ -187,7 +177,10 @@
emitter.complete();
} catch (Exception ignore) {}
}, e -> {
- try { emitter.completeWithError(e); } catch (Exception ignore) {}
+ try {
+ try { emitter.send(SseEmitter.event().data("銆怉I銆戣繍琛屽凡鍋滄锛堝紓甯革級")); } catch (Exception ignore) {}
+ emitter.complete();
+ } catch (Exception ignore) {}
});
}
@@ -380,7 +373,7 @@
try {
sse(emitter, "\\n\\n銆怉I銆戣繍琛屽凡鍋滄锛堝紓甯革級\\n\\n");
log.error("AI MCP diagnose stopped: error", e);
- emitter.completeWithError(e);
+ emitter.complete();
} catch (Exception ignore) {}
return true;
}
diff --git a/src/main/java/com/zy/asrs/controller/BasMapController.java b/src/main/java/com/zy/asrs/controller/BasMapController.java
index 8a199cc..9dfa3f9 100644
--- a/src/main/java/com/zy/asrs/controller/BasMapController.java
+++ b/src/main/java/com/zy/asrs/controller/BasMapController.java
@@ -177,6 +177,8 @@
HashMap<Integer, List<StationObjModel>> inStationMap = new HashMap<>();
HashMap<Integer, List<StationObjModel>> outStationMap = new HashMap<>();
HashMap<Integer, List<StationObjModel>> runBlockReassignStationMap = new HashMap<>();
+ HashMap<Integer, List<StationObjModel>> isOutOrderStationMap = new HashMap<>();
+ HashMap<Integer, List<StationObjModel>> isLiftTransferStationMap = new HashMap<>();
for (Map.Entry<Integer, List<List<HashMap<String, Object>>>> entry : dataMap.entrySet()) {
Integer lev = entry.getKey();
@@ -192,17 +194,18 @@
HashMap<String, Object> nodeData = new HashMap<>();
nodeData.put("value", map.get("value"));
- String nodeType = map.get("bgColor").toString();
- if (nodeType.equals("RGB(0,176,80)")) {
+ String bgColor = map.get("bgColor").toString();
+ String nodeType = map.get("nodeType").toString();
+ if (nodeType.equals("shelf")) {
//璐ф灦
nodeData.put("type", "shelf");
- } else if (nodeType.equals("RGB(255,192,0)")) {
+ } else if (nodeType.equals("crn")) {
//鍫嗗灈鏈�
nodeData.put("type", "crn");
- } else if (nodeType.equals("RGB(255,255,0)")) {
+ } else if (nodeType.equals("dualCrn")) {
//鍙屽伐浣嶅爢鍨涙満
nodeData.put("type", "dualCrn");
- } else if (nodeType.equals("RGB(0,112,192)")) {
+ } else if (nodeType.equals("devp")) {
//杈撻�佺嚎
nodeData.put("type", "devp");
@@ -266,7 +269,21 @@
runBlockReassignStationList.add(stationObjModel);
runBlockReassignStationMap.put(deviceNo, runBlockReassignStationList);
}
- } else if (nodeType.equals("RGB(0,176,240)")) {
+
+ Integer isOutOrder = value.getInteger("isOutOrder");
+ if (isOutOrder != null && isOutOrder == 1) {
+ List<StationObjModel> isOutOrderStationList = isOutOrderStationMap.getOrDefault(deviceNo, new ArrayList<>());
+ isOutOrderStationList.add(stationObjModel);
+ isOutOrderStationMap.put(deviceNo, isOutOrderStationList);
+ }
+
+ Integer isLiftTransfer = value.getInteger("isLiftTransfer");
+ if (isLiftTransfer != null && isLiftTransfer == 1) {
+ List<StationObjModel> isLiftTransferStationList = isLiftTransferStationMap.getOrDefault(deviceNo, new ArrayList<>());
+ isLiftTransferStationList.add(stationObjModel);
+ isLiftTransferStationMap.put(deviceNo, isLiftTransferStationList);
+ }
+ } else if (nodeType.equals("rgv")) {
//RGV
nodeData.put("type", "rgv");
} else if (nodeType.equals("none")) {
@@ -275,6 +292,7 @@
} else if (nodeType.equals("merge")) {
//鍚堝苟鍖哄煙
nodeData.put("type", "merge");
+ nodeData.put("mergeType", map.get("mergeType"));
}
nodeData.put("cellWidth", map.get("cellWidth"));
@@ -314,6 +332,8 @@
List<StationObjModel> inStationList = inStationMap.get(deviceNo);
List<StationObjModel> outStationList = outStationMap.get(deviceNo);
List<StationObjModel> runBlockReassignStationList = runBlockReassignStationMap.get(deviceNo);
+ List<StationObjModel> isOutOrderStationList = isOutOrderStationMap.get(deviceNo);
+ List<StationObjModel> isLiftTransferStationList = isLiftTransferStationMap.get(deviceNo);
if (barcodeStationList != null) {
basDevp.setBarcodeStationList(JSON.toJSONString(barcodeStationList, SerializerFeature.DisableCircularReferenceDetect));
@@ -331,6 +351,14 @@
basDevp.setRunBlockReassignLocStationList(JSON.toJSONString(runBlockReassignStationList, SerializerFeature.DisableCircularReferenceDetect));
}
+ if (isOutOrderStationList != null) {
+ basDevp.setIsOutOrderList(JSON.toJSONString(isOutOrderStationList, SerializerFeature.DisableCircularReferenceDetect));
+ }
+
+ if (isLiftTransferStationList != null) {
+ basDevp.setIsLiftTransferList(JSON.toJSONString(isLiftTransferStationList, SerializerFeature.DisableCircularReferenceDetect));
+ }
+
basDevp.setStationList(JSON.toJSONString(stationList, SerializerFeature.DisableCircularReferenceDetect));
basDevp.setUpdateTime(new Date());
basDevpService.insertOrUpdate(basDevp);
diff --git a/src/main/java/com/zy/asrs/controller/ConsoleController.java b/src/main/java/com/zy/asrs/controller/ConsoleController.java
index 554305b..51b7777 100644
--- a/src/main/java/com/zy/asrs/controller/ConsoleController.java
+++ b/src/main/java/com/zy/asrs/controller/ConsoleController.java
@@ -57,6 +57,10 @@
private RedisUtil redisUtil;
@Autowired
private LocMastService locMastService;
+ @Autowired
+ private BasMapService basMapService;
+ @Autowired
+ private StationCycleCapacityService stationCycleCapacityService;
@PostMapping("/system/running/status")
@ManagerAuth(memo = "绯荤粺杩愯鐘舵��")
@@ -122,6 +126,7 @@
vo.setErrorMsg(stationProtocol.getErrorMsg()); // 鎶ヨ淇℃伅
vo.setBarcode(stationProtocol.getBarcode()); // 鏉$爜
vo.setWeight(stationProtocol.getWeight());//閲嶉噺
+ vo.setTaskWriteIdx(stationProtocol.getTaskWriteIdx());//浠诲姟鍙啓鍖�
String stationStatus = StationStatusType.process(stationProtocol).toString().toLowerCase().replaceAll("_", "-");
if (stationProtocol.isAutoing() && stationProtocol.isLoading() && stationProtocol.getTaskNo() > 0 && !stationProtocol.isRunBlock()) {
String taskClass = getStationTaskClass(stationProtocol.getTaskNo(), inTaskRange, outTaskRange);
@@ -264,6 +269,11 @@
return R.ok().add(vos);
}
+ @GetMapping("/latest/data/station/cycle/capacity")
+ public R stationCycleCapacity() {
+ return R.ok().add(stationCycleCapacityService.getLatestSnapshot());
+ }
+
// @PostMapping("/latest/data/barcode")
// @ManagerAuth(memo = "鏉$爜鎵弿浠疄鏃舵暟鎹�")
// public R barcodeLatestData(){
@@ -341,10 +351,10 @@
@GetMapping("/map/{lev}/auth")
public R getLocMap(@PathVariable Integer lev) {
Object object = redisUtil.get(RedisKeyType.LOC_MAP_BASE.key);
- if (object == null) {
- return R.error("鍦板浘鏈垵濮嬪寲");
+ List<List<HashMap<String, Object>>> mapNodeList = null;
+ if (object != null) {
+ mapNodeList = (List<List<HashMap<String, Object>>>) object;
}
- List<List<HashMap<String, Object>>> mapNodeList = (List<List<HashMap<String, Object>>>) object;
List<LocMast> locMastList = locMastService.selectLocByLev(lev);
for (LocMast locMast : locMastList) {
String[] locType = locMast.getLocType().split("-");
diff --git a/src/main/java/com/zy/asrs/controller/CrnController.java b/src/main/java/com/zy/asrs/controller/CrnController.java
index cacd496..ba23d00 100644
--- a/src/main/java/com/zy/asrs/controller/CrnController.java
+++ b/src/main/java/com/zy/asrs/controller/CrnController.java
@@ -173,7 +173,7 @@
return R.error("绾跨▼涓嶅瓨鍦�");
}
- CrnCommand command = crnThread.getResetCommand(crnNo);
+ CrnCommand command = crnThread.getResetCommand(9999, crnNo);
MessageQueue.offer(SlaveType.Crn, crnNo, new Task(2, command));
return R.ok();
}
diff --git a/src/main/java/com/zy/asrs/controller/DualCrnController.java b/src/main/java/com/zy/asrs/controller/DualCrnController.java
index 3a75fb3..48cb7b8 100644
--- a/src/main/java/com/zy/asrs/controller/DualCrnController.java
+++ b/src/main/java/com/zy/asrs/controller/DualCrnController.java
@@ -5,11 +5,14 @@
import com.core.common.Cools;
import com.core.common.R;
import com.zy.asrs.domain.param.DualCrnCommandParam;
+import com.zy.asrs.domain.param.DualCrnUpdateTaskNoParam;
import com.zy.asrs.domain.vo.DualCrnStateTableVo;
import com.zy.asrs.entity.BasDualCrnp;
import com.zy.asrs.service.BasDualCrnpService;
+import com.zy.common.utils.RedisUtil;
import com.zy.core.cache.MessageQueue;
import com.zy.core.cache.SlaveConnection;
+import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.SlaveType;
import com.zy.core.model.Task;
import com.zy.core.model.command.DualCrnCommand;
@@ -31,6 +34,8 @@
@Autowired
private BasDualCrnpService basDualCrnpService;
+ @Autowired
+ private RedisUtil redisUtil;
@PostMapping("/dualcrn/table/crn/state")
@ManagerAuth(memo = "鍙屽伐浣嶅爢鍨涙満淇℃伅琛�")
@@ -51,6 +56,8 @@
}
vo.setTaskNo(p.getTaskNo());
vo.setTaskNoTwo(p.getTaskNoTwo());
+ vo.setDeviceTaskNo(p.getDeviceTaskNo());
+ vo.setDeviceTaskNoTwo(p.getDeviceTaskNoTwo());
vo.setMode(p.getModeType() == null ? "-" : p.getModeType().desc);
vo.setStatus(p.getStatusType() == null ? "-" : p.getStatusType().desc);
vo.setStatusTwo(p.getStatusTypeTwo() == null ? "-" : p.getStatusTypeTwo().desc);
@@ -62,8 +69,10 @@
vo.setForkOffsetTwo(p.getForkPosTypeTwo() == null ? "-" : p.getForkPosTypeTwo().desc);
vo.setLiftPos(p.getLiftPosType() == null ? "-" : p.getLiftPosType().desc);
vo.setWalkPos(p.getWalkPos() != null && p.getWalkPos() == 0 ? "鍦ㄥ畾浣�" : "涓嶅湪瀹氫綅");
- vo.setTaskReceive(p.getTaskReceive() != null && p.getTaskReceive() == 1 ? "鎺ユ敹" : "鏃犱换鍔�");
- vo.setTaskReceiveTwo(p.getTaskReceiveTwo() != null && p.getTaskReceiveTwo() == 1 ? "鎺ユ敹" : "鏃犱换鍔�");
+ vo.setTaskReceive(String.valueOf(p.getTaskReceive()));
+ vo.setTaskReceiveTwo(String.valueOf(p.getTaskReceiveTwo()));
+ vo.setTaskSend(String.valueOf(p.getTaskSend()));
+ vo.setTaskSendTwo(String.valueOf(p.getTaskSendTwo()));
vo.setXspeed(String.format("%.2f", p.getXSpeed()));
vo.setYspeed(String.format("%.2f", p.getYSpeed()));
@@ -175,8 +184,39 @@
if (crnThread == null) {
return R.error("绾跨▼涓嶅瓨鍦�");
}
- DualCrnCommand command = crnThread.getResetCommand(crnNo, station);
+ DualCrnCommand command = crnThread.getResetCommand(9999, crnNo, station);
MessageQueue.offer(SlaveType.DualCrn, crnNo, new Task(3, command));
return R.ok();
}
+
+ @PostMapping("/dualcrn/command/updateTaskNo")
+ @ManagerAuth(memo = "鍙屽伐浣嶅爢鍨涙満缂栬緫浠诲姟鍙�")
+ public R dualCrnUpdateTaskNo(@RequestBody DualCrnUpdateTaskNoParam param) {
+ if (Cools.isEmpty(param) || param.getCrnNo() == null || param.getStation() == null || param.getTaskNo() == null) {
+ return R.error("缂哄皯鍙傛暟");
+ }
+ Integer station = param.getStation();
+ if (station != 1 && station != 2) {
+ return R.error("宸ヤ綅鍙傛暟閿欒");
+ }
+ Integer taskNo = param.getTaskNo();
+ if (taskNo < 0) {
+ return R.error("浠诲姟鍙蜂笉鑳藉皬浜�0");
+ }
+ Integer crnNo = param.getCrnNo();
+ DualCrnThread crnThread = (DualCrnThread) SlaveConnection.get(SlaveType.DualCrn, crnNo);
+ if (crnThread == null) {
+ return R.error("绾跨▼涓嶅瓨鍦�");
+ }
+ DualCrnProtocol protocol = crnThread.getStatus();
+ if (protocol == null) {
+ return R.error("璁惧鐘舵�佷笉瀛樺湪");
+ }
+ if (station == 1) {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION1_FLAG.key + crnNo, taskNo, 60 * 60 * 24);
+ } else {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION2_FLAG.key + crnNo, taskNo, 60 * 60 * 24);
+ }
+ return R.ok();
+ }
}
diff --git a/src/main/java/com/zy/asrs/controller/OpenController.java b/src/main/java/com/zy/asrs/controller/OpenController.java
index 3325ec3..fbc6706 100644
--- a/src/main/java/com/zy/asrs/controller/OpenController.java
+++ b/src/main/java/com/zy/asrs/controller/OpenController.java
@@ -235,8 +235,7 @@
// 鑾峰彇杈撻�佺珯鐐规暟鎹�
List<StationProtocol> stationProtocols = new ArrayList<>();
List<DeviceConfig> devpList = deviceConfigService.selectList(new EntityWrapper<DeviceConfig>()
- .eq("device_type", String.valueOf(SlaveType.Devp))
- );
+ .eq("device_type", String.valueOf(SlaveType.Devp)));
for (DeviceConfig device : devpList) {
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, device.getDeviceNo());
if (stationThread == null) {
diff --git a/src/main/java/com/zy/asrs/controller/StationController.java b/src/main/java/com/zy/asrs/controller/StationController.java
index d232d99..75a7367 100644
--- a/src/main/java/com/zy/asrs/controller/StationController.java
+++ b/src/main/java/com/zy/asrs/controller/StationController.java
@@ -1,12 +1,18 @@
package com.zy.asrs.controller;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.zy.asrs.domain.param.StationCommandBarcodeParam;
import com.zy.asrs.entity.BasDevp;
+import com.zy.asrs.entity.DeviceConfig;
import com.zy.asrs.service.BasDevpService;
+import com.zy.asrs.service.DeviceConfigService;
import com.zy.common.utils.RedisUtil;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.enums.StationCommandType;
import com.zy.core.model.StationObjModel;
+import com.zy.system.entity.Config;
+import com.zy.system.service.ConfigService;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
@@ -29,10 +35,16 @@
@RequestMapping("/station")
public class StationController {
+ @Value("${mainProcessPlugin}")
+ private String mainProcessPlugin;
@Autowired
private BasDevpService basDevpService;
@Autowired
private RedisUtil redisUtil;
+ @Autowired
+ private ConfigService configService;
+ @Autowired
+ private DeviceConfigService deviceConfigService;
@PostMapping("/command/move")
public R commandMove(@RequestBody StationCommandMoveParam param) {
@@ -44,21 +56,7 @@
Integer taskNo = param.getTaskNo();
Integer targetStationId = param.getTargetStationId();
- StationObjModel finalStation = null;
- List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
- for (BasDevp basDevp : basDevps) {
- List<StationObjModel> list = basDevp.getStationList$();
- for (StationObjModel entity : list) {
- if(entity.getStationId().equals(stationId)){
- finalStation = entity;
- break;
- }
- }
-
- if(finalStation != null){
- break;
- }
- }
+ StationObjModel finalStation = findStation(stationId);
if(finalStation == null){
return R.error("绔欑偣涓嶅瓨鍦�");
@@ -76,6 +74,51 @@
return R.ok();
}
+ @PostMapping("/command/barcode")
+ public R commandBarcode(@RequestBody StationCommandBarcodeParam param) {
+ if (Cools.isEmpty(param) || Cools.isEmpty(param.getStationId())) {
+ return R.error("缂哄皯鍙傛暟");
+ }
+
+ if (!mainProcessPlugin.contains("Fake")) {
+ return R.error("褰撳墠绯荤粺鏈惎鐢ㄤ豢鐪熸彃浠�");
+ }
+
+ Config enableFakeConfig = configService.selectOne(new EntityWrapper<Config>().eq("code", "enableFake"));
+ if (enableFakeConfig == null || !"Y".equals(enableFakeConfig.getValue())) {
+ return R.error("褰撳墠闈炰豢鐪熻繍琛屾ā寮忥紝绂佹淇敼鏉$爜");
+ }
+
+ Integer stationId = param.getStationId();
+ StationObjModel finalStation = findStation(stationId);
+ if (finalStation == null) {
+ return R.error("绔欑偣涓嶅瓨鍦�");
+ }
+
+ Integer devpNo = finalStation.getDeviceNo();
+ DeviceConfig deviceConfig = deviceConfigService.selectOne(new EntityWrapper<DeviceConfig>()
+ .eq("device_no", devpNo)
+ .eq("device_type", String.valueOf(SlaveType.Devp)));
+ if (deviceConfig == null || deviceConfig.getFake() == null || deviceConfig.getFake() != 1) {
+ return R.error("褰撳墠绔欑偣璁惧鏈惎鐢ㄤ豢鐪燂紝绂佹淇敼鏉$爜");
+ }
+
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, devpNo);
+ if (stationThread == null) {
+ return R.error("绾跨▼涓嶅瓨鍦�");
+ }
+
+ String barcode = param.getBarcode();
+ if (barcode == null) {
+ barcode = "";
+ }
+
+ StationCommand command = stationThread.getCommand(StationCommandType.WRITE_INFO, 9997, stationId, stationId, 0);
+ command.setBarcode(barcode.trim());
+ MessageQueue.offer(SlaveType.Devp, devpNo, new Task(2, command));
+ return R.ok();
+ }
+
@PostMapping("/command/reset")
public R commandReset(@RequestBody StationCommandMoveParam param) {
if (Cools.isEmpty(param)) {
@@ -87,4 +130,21 @@
return R.ok();
}
+ private StationObjModel findStation(Integer stationId) {
+ if (Cools.isEmpty(stationId)) {
+ return null;
+ }
+
+ List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
+ for (BasDevp basDevp : basDevps) {
+ List<StationObjModel> list = basDevp.getStationList$();
+ for (StationObjModel entity : list) {
+ if (entity.getStationId().equals(stationId)) {
+ return entity;
+ }
+ }
+ }
+ return null;
+ }
+
}
diff --git a/src/main/java/com/zy/asrs/domain/enums/NotifyMsgType.java b/src/main/java/com/zy/asrs/domain/enums/NotifyMsgType.java
index 25b9419..5f8ec1d 100644
--- a/src/main/java/com/zy/asrs/domain/enums/NotifyMsgType.java
+++ b/src/main/java/com/zy/asrs/domain/enums/NotifyMsgType.java
@@ -20,6 +20,7 @@
DUAL_CRN_TRANSFER_TASK_COMPLETE("dual_crn_transfer_task_complete", "鍙屽伐浣嶅爢鍨涙満绉诲簱浠诲姟鎵ц瀹屾垚"),
STATION_OUT_TASK_RUN("station_out_task_run","杈撻�佺珯鐐瑰嚭搴撲换鍔¤繍琛屼腑"),
+ STATION_OUT_TASK_RUN_COMPLETE("station_out_task_run_complete","杈撻�佺珯鐐瑰嚭搴撲换鍔¤繍琛屽畬鎴�"),
;
public String flag;
diff --git a/src/main/java/com/zy/asrs/domain/vo/DualCrnStateTableVo.java b/src/main/java/com/zy/asrs/domain/vo/DualCrnStateTableVo.java
index 0da191a..189150c 100644
--- a/src/main/java/com/zy/asrs/domain/vo/DualCrnStateTableVo.java
+++ b/src/main/java/com/zy/asrs/domain/vo/DualCrnStateTableVo.java
@@ -15,6 +15,10 @@
private Integer taskNoTwo = 0;
+ private Integer deviceTaskNo = 0;
+
+ private Integer deviceTaskNoTwo = 0;
+
private String status = "-";
private String statusTwo = "-";
@@ -31,6 +35,10 @@
private String taskReceiveTwo = "-";
+ private String taskSend = "-";
+
+ private String taskSendTwo = "-";
+
private Integer bay;
private Integer lev;
diff --git a/src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java b/src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java
index c41359e..749a635 100644
--- a/src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java
+++ b/src/main/java/com/zy/asrs/domain/vo/StationLatestDataVo.java
@@ -55,4 +55,7 @@
//閲嶉噺
private Double weight;
+ //浠诲姟鍙啓鍖�
+ private Integer taskWriteIdx;
+
}
diff --git a/src/main/java/com/zy/asrs/entity/BasDevp.java b/src/main/java/com/zy/asrs/entity/BasDevp.java
index cafa3fd..5b15930 100644
--- a/src/main/java/com/zy/asrs/entity/BasDevp.java
+++ b/src/main/java/com/zy/asrs/entity/BasDevp.java
@@ -113,6 +113,20 @@
@TableField("run_block_reassign_loc_station_list")
private String runBlockReassignLocStationList;
+ /**
+ * 鍑哄簱鎺掑簭浜や簰鐐�
+ */
+ @ApiModelProperty(value= "鍑哄簱鎺掑簭浜や簰鐐�")
+ @TableField("is_out_order_list")
+ private String isOutOrderList;
+
+ /**
+ * 椤跺崌绉绘牻鐐�
+ */
+ @ApiModelProperty(value= "椤跺崌绉绘牻鐐�")
+ @TableField("is_lift_transfer_list")
+ private String isLiftTransferList;
+
public BasDevp() {}
public BasDevp(Integer devpNo,Integer status,Long createBy,Date createTime,Long updateBy,Date updateTime,String memo,String stationList,String barcodeStationList,String inStationList,String outStationList) {
@@ -229,4 +243,43 @@
return list;
}
+ public List<StationObjModel> getOutOrderList$(){
+ List<StationObjModel> list = new ArrayList<>();
+ if (Cools.isEmpty(this.isOutOrderList)){
+ return list;
+ }
+
+ List<StationObjModel> jsonList = JSON.parseArray(this.isOutOrderList, StationObjModel.class);
+ for (StationObjModel json : jsonList){
+ list.add(json);
+ }
+ return list;
+ }
+
+ public List<Integer> getOutOrderIntList(){
+ List<Integer> list = new ArrayList<>();
+ if (Cools.isEmpty(this.isOutOrderList)){
+ return list;
+ }
+
+ List<StationObjModel> jsonList = JSON.parseArray(this.isOutOrderList, StationObjModel.class);
+ for (StationObjModel json : jsonList){
+ list.add(json.getStationId());
+ }
+ return list;
+ }
+
+ public List<StationObjModel> getLiftTransferList$(){
+ List<StationObjModel> list = new ArrayList<>();
+ if (Cools.isEmpty(this.isLiftTransferList)){
+ return list;
+ }
+
+ List<StationObjModel> jsonList = JSON.parseArray(this.isLiftTransferList, StationObjModel.class);
+ for (StationObjModel json : jsonList){
+ list.add(json);
+ }
+ return list;
+ }
+
}
diff --git a/src/main/java/com/zy/asrs/task/WrkMastScheduler.java b/src/main/java/com/zy/asrs/task/WrkMastScheduler.java
index 707d3b9..9f2a2bd 100644
--- a/src/main/java/com/zy/asrs/task/WrkMastScheduler.java
+++ b/src/main/java/com/zy/asrs/task/WrkMastScheduler.java
@@ -95,8 +95,8 @@
continue;
}
- if (!locMast.getLocSts().equals("R")) {
- log.info("[workNo={}]搴撲綅鐘舵�佷笉澶勪簬R", wrkMast.getWrkNo());
+ if (!(locMast.getLocSts().equals("R") || locMast.getLocSts().equals("O"))) {
+ log.info("[workNo={}]搴撲綅鐘舵�佷笉澶勪簬R or O", wrkMast.getWrkNo());
continue;
}
@@ -237,4 +237,40 @@
}
}
+ @Scheduled(cron = "0/1 * * * * ? ")
+ @Transactional
+ public void processOutStationRun(){
+ List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("wrk_sts", WrkStsType.STATION_RUN.sts));
+ if (wrkMasts.isEmpty()) {
+ return;
+ }
+
+ for (WrkMast wrkMast : wrkMasts) {
+ String locNo = wrkMast.getSourceLocNo();
+ LocMast locMast = locMastService.queryByLoc(locNo);
+ if (locMast == null) {
+ log.info("[workNo={}]搴撲綅涓嶅瓨鍦�", wrkMast.getWrkNo());
+ continue;
+ }
+
+ if (locMast.getLocSts().equals("O")) {
+ continue;
+ }
+
+ if (!locMast.getLocSts().equals("R")) {
+ log.info("[workNo={}]搴撲綅鐘舵�佷笉澶勪簬R", wrkMast.getWrkNo());
+ continue;
+ }
+
+ locMast.setLocSts("O");
+ locMast.setBarcode("");
+ locMast.setModiTime(new Date());
+ boolean result = locMastService.updateById(locMast);
+ if (!result) {
+ log.info("[workNo={}]搴撲綅鐘舵�丱鏇存柊澶辫触", wrkMast.getWrkNo());
+ continue;
+ }
+ }
+ }
+
}
diff --git a/src/main/java/com/zy/asrs/utils/MapExcelUtils.java b/src/main/java/com/zy/asrs/utils/MapExcelUtils.java
index cdca8ca..d61d64e 100644
--- a/src/main/java/com/zy/asrs/utils/MapExcelUtils.java
+++ b/src/main/java/com/zy/asrs/utils/MapExcelUtils.java
@@ -322,7 +322,9 @@
}
HashMap<String, Object> mapData = data.get(k - 2).get(l - 2);
- mapData.put("bgColor", "merge");
+ Object devp = map.get("nodeType");
+ mapData.put("nodeType", "merge");
+ mapData.put("mergeType", devp);
mapData.put("value", map.get("value"));
}
}
@@ -342,6 +344,7 @@
if (cell == null) {
HashMap<String, Object> map = new HashMap<>();
map.put("bgColor", "none");
+ map.put("nodeType", "none");
map.put("cellWidth", "");
map.put("cellHeight", "");
map.put("value", "");
@@ -354,6 +357,25 @@
String bgColor = getCellBackgroundColor(cell);
map.put("bgColor", bgColor);
+ if(bgColor.equals("RGB(0,176,80)")) {
+ //璐ф灦
+ map.put("nodeType", "shelf");
+ } else if (bgColor.equals("RGB(255,192,0)")) {
+ //鍫嗗灈鏈�
+ map.put("nodeType", "crn");
+ } else if (bgColor.equals("RGB(255,255,0)")) {
+ //鍙屽伐浣嶅爢鍨涙満
+ map.put("nodeType", "dualCrn");
+ } else if (bgColor.equals("RGB(0,112,192)")) {
+ //杈撻�佺嚎
+ map.put("nodeType", "devp");
+ } else if (bgColor.equals("RGB(0,176,240)")) {
+ //RGV
+ map.put("nodeType", "rgv");
+ }else {
+ //绌虹櫧鍖哄煙
+ map.put("nodeType", "none");
+ }
int columnIndex = cell.getColumnIndex();
int columnWidth = sheet.getColumnWidth(columnIndex);//鑾峰彇鍒楀
diff --git a/src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java b/src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java
index 6d3a357..63ef73c 100644
--- a/src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java
+++ b/src/main/java/com/zy/asrs/ws/ConsoleWebSocket.java
@@ -103,6 +103,9 @@
} else if ("/console/latest/data/dualcrn".equals(url)) {
ConsoleController consoleController = SpringUtils.getBean(ConsoleController.class);
resObj = consoleController.dualCrnLatestData();
+ } else if ("/console/latest/data/station/cycle/capacity".equals(url)) {
+ ConsoleController consoleController = SpringUtils.getBean(ConsoleController.class);
+ resObj = consoleController.stationCycleCapacity();
} else if ("/crn/table/crn/state".equals(url)) {
resObj = SpringUtils.getBean(CrnController.class).crnStateTable();
} else if ("/rgv/table/rgv/state".equals(url)) {
diff --git a/src/main/java/com/zy/common/model/NavigateNode.java b/src/main/java/com/zy/common/model/NavigateNode.java
index 360c464..63f2136 100644
--- a/src/main/java/com/zy/common/model/NavigateNode.java
+++ b/src/main/java/com/zy/common/model/NavigateNode.java
@@ -22,6 +22,7 @@
private NavigateNode Father;//鐖惰妭鐐�
private List<String> directionList;//鍏佽琛岃蛋鏂瑰悜
private Boolean isInflectionPoint;//鏄惁涓烘嫄鐐�
+ private Boolean isLiftTransferPoint;//鏄惁涓洪《鍗囩Щ鏍界偣
private String direction;//琛岃蛋鏂瑰悜
private String nodeValue;//鑺傜偣鏁版嵁
private String nodeType;//鑺傜偣绫诲瀷
diff --git a/src/main/java/com/zy/common/service/CommonService.java b/src/main/java/com/zy/common/service/CommonService.java
index 6026fd8..6c69e6f 100644
--- a/src/main/java/com/zy/common/service/CommonService.java
+++ b/src/main/java/com/zy/common/service/CommonService.java
@@ -12,19 +12,13 @@
import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
-import com.zy.core.enums.RedisKeyType;
-import com.zy.core.enums.SlaveType;
-import com.zy.core.enums.WrkIoType;
-import com.zy.core.enums.WrkStsType;
+import com.zy.core.enums.*;
import com.zy.core.model.StationObjModel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-import java.util.Random;
+import java.util.*;
@Slf4j
@Service
@@ -226,10 +220,10 @@
if (null == locMast) {
throw new CoolException(param.getLocNo() + "鐩爣搴撲綅涓嶅瓨鍦�");
}
-
if (!locMast.getLocSts().equals("O")) {
throw new CoolException(locMast.getLocNo() + "鐩爣搴撲綅涓嶅浜庣┖搴撶姸鎬�");
}
+ News.info("浠诲姟鍙�:{} 鐩爣搴撲綅淇℃伅:{}",param.getTaskNo(), param.getLocNo());
double ioPri = 100D;
if (param.getTaskPri() != null) {
@@ -261,7 +255,6 @@
if (findCrnResult.getCrnType().equals(SlaveType.Crn)) {
wrkMast.setCrnNo(findCrnResult.getCrnNo());
-
//缂撳瓨璁板綍褰撳墠鍛戒护鍫嗗灈鏈虹紪鍙�
redisUtil.set(RedisKeyType.CURRENT_CIRCLE_TASK_CRN_NO.key, crnNo, 60 * 60 * 24);
} else if (findCrnResult.getCrnType().equals(SlaveType.DualCrn)) {
@@ -400,10 +393,15 @@
}
public FindCrnNoResult findCrnNoByLocNo(String locNo) {
+ if (Objects.isNull(locNo)) {
+ News.error("浠诲姟鍙蜂负绌猴紒");
+ return null;
+ }
List<BasCrnp> basCrnps = basCrnpService.selectList(new EntityWrapper<>());
for (BasCrnp basCrnp : basCrnps) {
List<List<Integer>> rowList = basCrnp.getControlRows$();
for (List<Integer> rows : rowList) {
+// System.out.println("搴撲綅鍙凤細" + locNo);
if(rows.contains(Utils.getRow(locNo))) {
FindCrnNoResult result = new FindCrnNoResult();
result.setCrnNo(basCrnp.getCrnNo());
diff --git a/src/main/java/com/zy/common/utils/NavigateUtils.java b/src/main/java/com/zy/common/utils/NavigateUtils.java
index fb734e1..e6b004e 100644
--- a/src/main/java/com/zy/common/utils/NavigateUtils.java
+++ b/src/main/java/com/zy/common/utils/NavigateUtils.java
@@ -6,16 +6,20 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
+import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.zy.asrs.entity.BasDevp;
import com.zy.asrs.entity.BasStation;
+import com.zy.asrs.service.BasDevpService;
import com.zy.asrs.service.BasStationService;
import com.zy.core.News;
+import com.zy.core.model.StationObjModel;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
-import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.core.common.SpringUtils;
import com.core.exception.CoolException;
import com.zy.common.model.NavigateNode;
@@ -31,6 +35,11 @@
@Component
public class NavigateUtils {
+ private static final String CFG_STATION_PATH_LEN_WEIGHT_PERCENT = "stationPathLenWeightPercent";
+ private static final String CFG_STATION_PATH_CONG_WEIGHT_PERCENT = "stationPathCongWeightPercent";
+ private static final String CFG_STATION_PATH_PASS_OTHER_OUT_STATION_WEIGHT_PERCENT = "stationPathPassOtherOutStationWeightPercent";
+ private static final String CFG_STATION_PATH_PASS_OTHER_OUT_STATION_FORCE_SKIP = "stationPathPassOtherOutStationForceSkip";
+
@Autowired
private BasStationService basStationService;
@@ -45,12 +54,12 @@
List<List<NavigateNode>> stationMap = navigateSolution.getStationMap(lev);
NavigateNode startNode = navigateSolution.findStationNavigateNode(stationMap, startStationId);
- if (startNode == null){
+ if (startNode == null) {
throw new CoolException("鏈壘鍒拌 璧风偣 瀵瑰簲鐨勮妭鐐�");
}
NavigateNode endNode = navigateSolution.findStationNavigateNode(stationMap, endStationId);
- if (endNode == null){
+ if (endNode == null) {
throw new CoolException("鏈壘鍒拌 缁堢偣 瀵瑰簲鐨勮妭鐐�");
}
@@ -58,7 +67,8 @@
News.info("[WCS Debug] 绔欑偣璺緞寮�濮嬭绠�,startStationId={},endStationId={}", startStationId, endStationId);
List<List<NavigateNode>> allList = navigateSolution.allSimplePaths(stationMap, startNode, endNode, 120, 500, 300);
if (allList.isEmpty()) {
- throw new CoolException("鏈壘鍒拌璺緞");
+// throw new CoolException("鏈壘鍒拌璺緞");
+ return new ArrayList<>();
}
News.info("[WCS Debug] 绔欑偣璺緞璁$畻瀹屾垚锛岃�楁椂锛歿}ms", System.currentTimeMillis() - startTime);
@@ -70,9 +80,12 @@
//鍘婚噸
HashSet<Integer> set = new HashSet<>();
List<NavigateNode> fitlerList = new ArrayList<>();
- for(NavigateNode navigateNode : list){
+ for (NavigateNode navigateNode : list) {
JSONObject valuObject = JSON.parseObject(navigateNode.getNodeValue());
- if(set.add(valuObject.getInteger("stationId"))){
+ if (valuObject.containsKey("rgvCalcFlag")) {
+ continue;
+ }
+ if (set.add(valuObject.getInteger("stationId"))) {
fitlerList.add(navigateNode);
}
}
@@ -80,6 +93,20 @@
for (int i = 0; i < fitlerList.size(); i++) {
NavigateNode currentNode = fitlerList.get(i);
currentNode.setIsInflectionPoint(false);
+ currentNode.setIsLiftTransferPoint(false);
+
+ try {
+ JSONObject valueObject = JSON.parseObject(currentNode.getNodeValue());
+ if (valueObject != null) {
+ Object isLiftTransfer = valueObject.get("isLiftTransfer");
+ if (isLiftTransfer != null) {
+ String isLiftTransferStr = isLiftTransfer.toString();
+ if ("1".equals(isLiftTransferStr) || "true".equalsIgnoreCase(isLiftTransferStr)) {
+ currentNode.setIsLiftTransferPoint(true);
+ }
+ }
+ }
+ } catch (Exception ignore) {}
NavigateNode nextNode = (i + 1 < fitlerList.size()) ? fitlerList.get(i + 1) : null;
NavigateNode prevNode = (i - 1 >= 0) ? fitlerList.get(i - 1) : null;
@@ -112,7 +139,8 @@
News.info("[WCS Debug] RGV璺緞寮�濮嬭绠�,startTrackSiteNo:{},endTrackSiteNo={}", startTrackSiteNo, endTrackSiteNo);
NavigateNode res_node = navigateSolution.astarSearchJava(rgvTrackMap, startNode, endNode);
if (res_node == null) {
- throw new CoolException("鏈壘鍒拌璺緞");
+// throw new CoolException("鏈壘鍒拌璺緞");
+ return new ArrayList<>();
}
News.info("[WCS Debug] RGV璺緞璁$畻瀹屾垚锛岃�楁椂锛歿}ms", System.currentTimeMillis() - startTime);
@@ -214,10 +242,28 @@
}
} catch (Exception ignore) {}
+ Set<Integer> outStationIdSet = loadAllOutStationIdSet();
+
+ double lenWeightPercent = 50.0;
+ double congWeightPercent = 50.0;
+ double passOtherOutStationWeightPercent = 100.0;
+ boolean forceSkipPassOtherOutStation = false;
+ try {
+ ConfigService configService = SpringUtils.getBean(ConfigService.class);
+ if (configService != null) {
+ lenWeightPercent = loadDoubleConfig(configService, CFG_STATION_PATH_LEN_WEIGHT_PERCENT, lenWeightPercent);
+ congWeightPercent = loadDoubleConfig(configService, CFG_STATION_PATH_CONG_WEIGHT_PERCENT, congWeightPercent);
+ passOtherOutStationWeightPercent = loadDoubleConfig(configService, CFG_STATION_PATH_PASS_OTHER_OUT_STATION_WEIGHT_PERCENT, passOtherOutStationWeightPercent);
+ forceSkipPassOtherOutStation = loadBooleanConfig(configService, CFG_STATION_PATH_PASS_OTHER_OUT_STATION_FORCE_SKIP, false);
+ }
+ } catch (Exception ignore) {}
+
List<List<NavigateNode>> candidates = new ArrayList<>();
List<Integer> lens = new ArrayList<>();
List<Integer> tasksList = new ArrayList<>();
List<Double> congs = new ArrayList<>();
+ List<Integer> passOtherOutStationCounts = new ArrayList<>();
+ int skippedByPassOtherOutStation = 0;
for (List<NavigateNode> path : allList) {
if (path == null || path.isEmpty()) {
@@ -247,13 +293,27 @@
}
}
double cong = len <= 0 ? 0.0 : (double) tasks / (double) len;
+ int passOtherOutStationCount = countPassOtherOutStations(path, outStationIdSet);
+ if (forceSkipPassOtherOutStation && passOtherOutStationCount > 0) {
+ skippedByPassOtherOutStation++;
+ News.info("[WCS Debug] 绔欑偣璺緞鍊欓�夊凡璺宠繃锛屽洜缁忚繃鍏朵粬鍑哄簱绔欑偣,startStationId={},endStationId={},passOtherOutStationCount={}",
+ extractStationId(path.get(0)),
+ extractStationId(path.get(path.size() - 1)),
+ passOtherOutStationCount);
+ continue;
+ }
candidates.add(path);
lens.add(len);
tasksList.add(tasks);
congs.add(cong);
+ passOtherOutStationCounts.add(passOtherOutStationCount);
}
if (candidates.isEmpty()) {
+ if (forceSkipPassOtherOutStation && skippedByPassOtherOutStation > 0) {
+ News.info("[WCS Debug] 鎵�鏈夌珯鐐硅矾寰勫�欓�夊潎鍥犵粡杩囧叾浠栧嚭搴撶珯鐐硅寮哄埗璺宠繃");
+ return new ArrayList<>();
+ }
return allList.get(0);
}
@@ -261,59 +321,50 @@
int maxLen = Integer.MIN_VALUE;
double minCong = Double.MAX_VALUE;
double maxCong = -Double.MAX_VALUE;
+ int minPassOtherOutStationCount = Integer.MAX_VALUE;
+ int maxPassOtherOutStationCount = Integer.MIN_VALUE;
for (int i = 0; i < candidates.size(); i++) {
int l = lens.get(i);
double c = congs.get(i);
+ int p = passOtherOutStationCounts.get(i);
if (l < minLen) minLen = l;
if (l > maxLen) maxLen = l;
if (c < minCong) minCong = c;
if (c > maxCong) maxCong = c;
+ if (p < minPassOtherOutStationCount) minPassOtherOutStationCount = p;
+ if (p > maxPassOtherOutStationCount) maxPassOtherOutStationCount = p;
}
- //闀垮害鏉冮噸鐧惧垎姣�
- double lenWeightPercent = 50.0;
- //鎷ュ牭鏉冮噸鐧惧垎姣�
- double congWeightPercent = 50.0;
- try {
- ConfigService configService = SpringUtils.getBean(ConfigService.class);
- if (configService != null) {
- Config cfgLen = configService.selectOne(new EntityWrapper<Config>().eq("code", "stationPathLenWeightPercent"));
- if (cfgLen != null && cfgLen.getValue() != null) {
- String v = cfgLen.getValue().trim();
- if (v.endsWith("%")) v = v.substring(0, v.length() - 1);
- try { lenWeightPercent = Double.parseDouble(v); } catch (Exception ignore) {}
- }
- Config cfgCong = configService.selectOne(new EntityWrapper<Config>().eq("code", "stationPathCongWeightPercent"));
- if (cfgCong != null && cfgCong.getValue() != null) {
- String v = cfgCong.getValue().trim();
- if (v.endsWith("%")) v = v.substring(0, v.length() - 1);
- try { congWeightPercent = Double.parseDouble(v); } catch (Exception ignore) {}
- }
- }
- } catch (Exception ignore) {}
-
- double weightSum = lenWeightPercent + congWeightPercent;
+ double weightSum = lenWeightPercent + congWeightPercent + passOtherOutStationWeightPercent;
double lenW = weightSum <= 0 ? 0.5 : lenWeightPercent / weightSum;
double congW = weightSum <= 0 ? 0.5 : congWeightPercent / weightSum;
+ double passOtherOutStationW = weightSum <= 0 ? 0.0 : passOtherOutStationWeightPercent / weightSum;
List<NavigateNode> best = null;
double bestCost = Double.MAX_VALUE;
+ int bestPassOtherOutStationCount = Integer.MAX_VALUE;
int bestTasks = Integer.MAX_VALUE;
int bestLen = Integer.MAX_VALUE;
for (int i = 0; i < candidates.size(); i++) {
int l = lens.get(i);
int t = tasksList.get(i);
double c = congs.get(i);
+ int p = passOtherOutStationCounts.get(i);
//褰掍竴鍖�
double lenNorm = (maxLen - minLen) <= 0 ? 0.0 : (l - minLen) / (double) (maxLen - minLen);
double congNorm = (maxCong - minCong) <= 0 ? 0.0 : (c - minCong) / (double) (maxCong - minCong);
+ double passOtherOutStationNorm = (maxPassOtherOutStationCount - minPassOtherOutStationCount) <= 0
+ ? 0.0
+ : (p - minPassOtherOutStationCount) / (double) (maxPassOtherOutStationCount - minPassOtherOutStationCount);
//鑾峰彇鏉冮噸
- double cost = lenNorm * lenW + congNorm * congW;
+ double cost = lenNorm * lenW + congNorm * congW + passOtherOutStationNorm * passOtherOutStationW;
if (cost < bestCost
- || (cost == bestCost && t < bestTasks)
- || (cost == bestCost && t == bestTasks && l < bestLen)) {
+ || (cost == bestCost && p < bestPassOtherOutStationCount)
+ || (cost == bestCost && p == bestPassOtherOutStationCount && t < bestTasks)
+ || (cost == bestCost && p == bestPassOtherOutStationCount && t == bestTasks && l < bestLen)) {
best = candidates.get(i);
bestCost = cost;
+ bestPassOtherOutStationCount = p;
bestTasks = t;
bestLen = l;
}
@@ -325,6 +376,102 @@
return best;
}
+ private Set<Integer> loadAllOutStationIdSet() {
+ Set<Integer> outStationIdSet = new HashSet<>();
+ try {
+ BasDevpService basDevpService = SpringUtils.getBean(BasDevpService.class);
+ if (basDevpService == null) {
+ return outStationIdSet;
+ }
+ List<BasDevp> basDevpList = basDevpService.selectList(new EntityWrapper<BasDevp>().eq("status", 1));
+ for (BasDevp basDevp : basDevpList) {
+ List<StationObjModel> outStationList = basDevp.getOutStationList$();
+ for (StationObjModel stationObjModel : outStationList) {
+ if (stationObjModel != null && stationObjModel.getStationId() != null) {
+ outStationIdSet.add(stationObjModel.getStationId());
+ }
+ }
+ }
+ } catch (Exception ignore) {}
+ return outStationIdSet;
+ }
+
+ private int countPassOtherOutStations(List<NavigateNode> path, Set<Integer> outStationIdSet) {
+ if (path == null || path.size() < 3 || outStationIdSet == null || outStationIdSet.isEmpty()) {
+ return 0;
+ }
+ Integer startStationId = extractStationId(path.get(0));
+ Integer endStationId = extractStationId(path.get(path.size() - 1));
+ Set<Integer> hitStationIdSet = new HashSet<>();
+ for (int i = 1; i < path.size() - 1; i++) {
+ Integer stationId = extractStationId(path.get(i));
+ if (stationId == null) {
+ continue;
+ }
+ if (startStationId != null && startStationId.equals(stationId)) {
+ continue;
+ }
+ if (endStationId != null && endStationId.equals(stationId)) {
+ continue;
+ }
+ if (outStationIdSet.contains(stationId)) {
+ hitStationIdSet.add(stationId);
+ }
+ }
+ return hitStationIdSet.size();
+ }
+
+ private Integer extractStationId(NavigateNode node) {
+ if (node == null || node.getNodeValue() == null) {
+ return null;
+ }
+ try {
+ JSONObject value = JSON.parseObject(node.getNodeValue());
+ if (value == null) {
+ return null;
+ }
+ return value.getInteger("stationId");
+ } catch (Exception ignore) {}
+ return null;
+ }
+
+ private double loadDoubleConfig(ConfigService configService, String code, double defaultValue) {
+ if (configService == null || code == null) {
+ return defaultValue;
+ }
+ Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", code));
+ if (config == null || config.getValue() == null) {
+ return defaultValue;
+ }
+ String value = config.getValue().trim();
+ if (value.endsWith("%")) {
+ value = value.substring(0, value.length() - 1);
+ }
+ try {
+ return Double.parseDouble(value);
+ } catch (Exception ignore) {}
+ return defaultValue;
+ }
+
+ private boolean loadBooleanConfig(ConfigService configService, String code, boolean defaultValue) {
+ if (configService == null || code == null) {
+ return defaultValue;
+ }
+ Config config = configService.selectOne(new EntityWrapper<Config>().eq("code", code));
+ if (config == null || config.getValue() == null) {
+ return defaultValue;
+ }
+ String value = config.getValue().trim();
+ if (value.isEmpty()) {
+ return defaultValue;
+ }
+ return "1".equals(value)
+ || "true".equalsIgnoreCase(value)
+ || "yes".equalsIgnoreCase(value)
+ || "y".equalsIgnoreCase(value)
+ || "on".equalsIgnoreCase(value);
+ }
+
//鍒ゆ柇褰撳墠鑺傜偣鍒颁笅涓�涓妭鐐规槸鍚︿负鎷愮偣
public HashMap<String,Object> searchInflectionPoint(NavigateNode currentNode, NavigateNode fatherNode, NavigateNode nextNode) {
HashMap<String, Object> map = new HashMap<>();
diff --git a/src/main/java/com/zy/core/ServerBootstrap.java b/src/main/java/com/zy/core/ServerBootstrap.java
index a4a5e65..953f986 100644
--- a/src/main/java/com/zy/core/ServerBootstrap.java
+++ b/src/main/java/com/zy/core/ServerBootstrap.java
@@ -135,6 +135,8 @@
thread = new ZyStationThread(deviceConfig, redisUtil);
} else if (deviceConfig.getThreadImpl().equals("ZyStationV3Thread")) {
thread = new ZyStationV3Thread(deviceConfig, redisUtil);
+ } else if (deviceConfig.getThreadImpl().equals("ZyStationV4Thread")) {
+ thread = new ZyStationV4Thread(deviceConfig, redisUtil);
} else {
throw new CoolException("鏈煡鐨勭嚎绋嬪疄鐜�");
}
diff --git a/src/main/java/com/zy/core/enums/RedisKeyType.java b/src/main/java/com/zy/core/enums/RedisKeyType.java
index eff66b9..7f9a454 100644
--- a/src/main/java/com/zy/core/enums/RedisKeyType.java
+++ b/src/main/java/com/zy/core/enums/RedisKeyType.java
@@ -2,15 +2,11 @@
public enum RedisKeyType {
- SHUTTLE_WORK_FLAG("shuttle_wrk_no_"),
- SHUTTLE_FLAG("shuttle_"),
- FORK_LIFT_WORK_FLAG("fork_lift_wrk_no_"),
- FORK_LIFT_FLAG("fork_lift_"),
- LIFT_WORK_FLAG("lift_wrk_no_"),
- LIFT_FLAG("lift_"),
-
+ DUAL_CRN_STATION1_FLAG("dual_crn_station1_flag_"),
+ DUAL_CRN_STATION2_FLAG("dual_crn_station2_flag_"),
DUAL_CRN_COMMAND_("dual_crn_command_"),
DUAL_CRN_COMMAND_IDX("dual_crn_command_idx_"),
+ DUAL_CRN_COMMAND_LAST("dual_crn_command_LAST_"),
QUEUE_CRN("queue_crn_"),
QUEUE_DUAL_CRN("queue_dual_crn_"),
@@ -59,6 +55,9 @@
DUAL_CRN_OUT_TASK_COMPLETE_STATION_INFO("dual_crn_out_task_complete_station_info_"),
CRN_OUT_TASK_COMPLETE_STATION_INFO("crn_out_task_complete_station_info_"),
+ WATCH_CIRCLE_STATION_("watch_circle_station_"),
+ STATION_CYCLE_LOAD_RESERVE("station_cycle_load_reserve"),
+
CURRENT_CIRCLE_TASK_CRN_NO("current_circle_task_crn_no_"),
ASYNC_WMS_IN_TASK_REQUEST("async_wms_in_task_request_"),
ASYNC_WMS_IN_TASK_RESPONSE("async_wms_in_task_response_"),
diff --git a/src/main/java/com/zy/core/enums/WrkStsType.java b/src/main/java/com/zy/core/enums/WrkStsType.java
index 59b4665..381ccfc 100644
--- a/src/main/java/com/zy/core/enums/WrkStsType.java
+++ b/src/main/java/com/zy/core/enums/WrkStsType.java
@@ -15,6 +15,7 @@
OUTBOUND_RUN(102, "璁惧鎼繍涓�"),
OUTBOUND_RUN_COMPLETE(103, "璁惧鎼繍瀹屾垚"),
STATION_RUN(104, "绔欑偣杩愯涓�"),
+ STATION_RUN_COMPLETE(105, "绔欑偣杩愯瀹屾垚"),
COMPLETE_OUTBOUND(109, "鍑哄簱瀹屾垚"),
SETTLE_OUTBOUND(110, "鍑哄簱搴撳瓨鏇存柊"),
diff --git a/src/main/java/com/zy/core/model/command/StationCommand.java b/src/main/java/com/zy/core/model/command/StationCommand.java
index a896e33..44cf588 100644
--- a/src/main/java/com/zy/core/model/command/StationCommand.java
+++ b/src/main/java/com/zy/core/model/command/StationCommand.java
@@ -19,8 +19,14 @@
private List<Integer> navigatePath;
+ // 璺緞涓殑椤跺崌绉绘牻鐐癸紙鎸夎矾寰勯『搴忥級
+ private List<Integer> liftTransferPath;
+
private List<Integer> originalNavigatePath;
private StationCommandType commandType;
+ // 浠跨湡妯″紡涓嬪彲閫夛細鎵嬪伐鎸囧畾鏉$爜
+ private String barcode;
+
}
diff --git a/src/main/java/com/zy/core/model/protocol/DualCrnProtocol.java b/src/main/java/com/zy/core/model/protocol/DualCrnProtocol.java
index 44440a4..72848b9 100644
--- a/src/main/java/com/zy/core/model/protocol/DualCrnProtocol.java
+++ b/src/main/java/com/zy/core/model/protocol/DualCrnProtocol.java
@@ -1,9 +1,9 @@
package com.zy.core.model.protocol;
-import com.zy.core.enums.DualCrnForkPosType;
-import com.zy.core.enums.DualCrnLiftPosType;
-import com.zy.core.enums.DualCrnModeType;
-import com.zy.core.enums.DualCrnStatusType;
+import com.core.common.Cools;
+import com.core.common.SpringUtils;
+import com.zy.common.utils.RedisUtil;
+import com.zy.core.enums.*;
import lombok.Data;
@@ -12,31 +12,41 @@
@Data
public class DualCrnProtocol {
- private Integer crnNo;
+ private volatile Integer crnNo;
/**
* 1 = 鎵嬪姩妯″紡
* 2 = 鑷姩妯″紡
* 3 = 鐢佃剳妯″紡
*/
- public Integer mode;
+ public volatile Integer mode;
- public DualCrnModeType modeType;
+ public volatile DualCrnModeType modeType;
/**
* 寮傚父鐮�
*/
- public Integer alarm;
+ public volatile Integer alarm;
/**
- * 宸ヤ綅1浠诲姟鍙�
+ * WCS宸ヤ綅1浠诲姟鍙�
*/
- public Integer taskNo = 0;
+ public volatile Integer taskNo = 0;
/**
- * 宸ヤ綅2浠诲姟鍙�
+ * WCS宸ヤ綅2浠诲姟鍙�
*/
- public Integer taskNoTwo = 0;
+ public volatile Integer taskNoTwo = 0;
+
+ /**
+ * 璁惧宸ヤ綅1浠诲姟鍙�
+ */
+ public volatile Integer deviceTaskNo = 0;
+
+ /**
+ * 璁惧宸ヤ綅2浠诲姟鍙�
+ */
+ public volatile Integer deviceTaskNoTwo = 0;
/**
* 宸ヤ綅1褰撳墠鐘舵��
@@ -51,42 +61,42 @@
* 90锛氫换鍔″畬鎴愮瓑寰匴CS纭
* 99锛氭姤璀�
*/
- public Integer status;
+ public volatile Integer status;
/**
* 宸ヤ綅2褰撳墠鐘舵��
*/
- public Integer statusTwo;
+ public volatile Integer statusTwo;
/**
* 宸ヤ綅1鐘舵�佹灇涓�
*/
- public DualCrnStatusType statusType;
+ public volatile DualCrnStatusType statusType;
/**
* 宸ヤ綅2鐘舵�佹灇涓�
*/
- public DualCrnStatusType statusTypeTwo;
+ public volatile DualCrnStatusType statusTypeTwo;
/**
* 宸ヤ綅1鍫嗗灈鏈哄綋鍓嶅垪鍙�
*/
- public Integer bay;
+ public volatile Integer bay;
/**
* 宸ヤ綅2鍫嗗灈鏈哄綋鍓嶅垪鍙�
*/
- public Integer bayTwo;
+ public volatile Integer bayTwo;
/**
* 宸ヤ綅1鍫嗗灈鏈哄綋鍓嶅眰鍙�
*/
- public Integer level;
+ public volatile Integer level;
/**
* 宸ヤ綅2鍫嗗灈鏈哄綋鍓嶅眰鍙�
*/
- public Integer levelTwo;
+ public volatile Integer levelTwo;
/**
* 宸ヤ綅1褰撳墠璐у弶浣嶇疆
@@ -94,7 +104,7 @@
* 1 = 璐у弶鍦ㄥ乏渚�
* 2 = 璐у弶鍦ㄥ彸渚�
*/
- public Integer forkPos;
+ public volatile Integer forkPos;
/**
* 宸ヤ綅2褰撳墠璐у弶浣嶇疆
@@ -102,51 +112,55 @@
* 1 = 璐у弶鍦ㄥ乏渚�
* 2 = 璐у弶鍦ㄥ彸渚�
*/
- public Integer forkPosTwo;
+ public volatile Integer forkPosTwo;
- public DualCrnForkPosType forkPosType;
+ public volatile DualCrnForkPosType forkPosType;
- public DualCrnForkPosType forkPosTypeTwo;
+ public volatile DualCrnForkPosType forkPosTypeTwo;
/**
* 褰撳墠杞借揣鍙颁綅缃�
* 0 = 涓嬪畾浣�
* 1 = 涓婂畾浣�
*/
- public Integer liftPos;
+ public volatile Integer liftPos;
- public Integer liftPosTwo;
+ public volatile Integer liftPosTwo;
- public DualCrnLiftPosType liftPosType;
+ public volatile DualCrnLiftPosType liftPosType;
- public DualCrnLiftPosType liftPosTypeTwo;
+ public volatile DualCrnLiftPosType liftPosTypeTwo;
/**
* 璧拌鍦ㄥ畾浣�
* 0 = 鍦ㄥ畾浣�
* 1 = 涓嶅湪瀹氫綅
*/
- public Integer walkPos;
+ public volatile Integer walkPos;
- public Integer walkPosTwo;
+ public volatile Integer walkPosTwo;
/**
* 杞借揣鍙版湁鐗�
*/
- public Integer loaded;
+ public volatile Integer loaded;
- public Integer loadedTwo;
+ public volatile Integer loadedTwo;
/**
* 浠诲姟鎺ユ敹鐘舵��
* 0 = 鏈帴鏀�
* 1 = 宸叉帴鏀�
*/
- public Integer taskReceive;
+ public volatile Integer taskReceive;
- public Integer taskReceiveTwo;
+ public volatile Integer taskReceiveTwo;
- private Integer temp1;
+ public volatile Integer taskSend;
+
+ public volatile Integer taskSendTwo;
+
+ private volatile Integer temp1;
private Integer temp2;
@@ -292,4 +306,32 @@
this.statusTwo = DualCrnStatusType.get(type).id;
}
+ public Integer getTaskNo() {
+ RedisUtil redisUtil = null;
+ try {
+ redisUtil = SpringUtils.getBean(RedisUtil.class);
+ }catch (Exception e) {}
+ if (null != redisUtil) {
+ Object o = redisUtil.get(RedisKeyType.DUAL_CRN_STATION1_FLAG.key + this.crnNo);
+ if (!Cools.isEmpty(o)) {
+ this.taskNo = Integer.parseInt(String.valueOf(o));
+ }
+ }
+ return this.taskNo == null ? 0 : this.taskNo;
+ }
+
+ public Integer getTaskNoTwo() {
+ RedisUtil redisUtil = null;
+ try {
+ redisUtil = SpringUtils.getBean(RedisUtil.class);
+ }catch (Exception e) {}
+ if (null != redisUtil) {
+ Object o = redisUtil.get(RedisKeyType.DUAL_CRN_STATION2_FLAG.key + this.crnNo);
+ if (!Cools.isEmpty(o)) {
+ this.taskNoTwo = Integer.parseInt(String.valueOf(o));
+ }
+ }
+ return this.taskNoTwo == null ? 0 : this.taskNoTwo;
+ }
+
}
diff --git a/src/main/java/com/zy/core/model/protocol/StationProtocol.java b/src/main/java/com/zy/core/model/protocol/StationProtocol.java
index 0d4a589..d3406d8 100644
--- a/src/main/java/com/zy/core/model/protocol/StationProtocol.java
+++ b/src/main/java/com/zy/core/model/protocol/StationProtocol.java
@@ -64,6 +64,9 @@
//WCS绯荤粺鎶ヨ
private String systemWarning;
+ //浠诲姟鍙啓鍖�
+ private Integer taskWriteIdx;
+
/**
* 鎵╁睍鏁版嵁
*/
diff --git a/src/main/java/com/zy/core/network/ZyStationConnectDriver.java b/src/main/java/com/zy/core/network/ZyStationConnectDriver.java
index 59d0d1b..62b1b93 100644
--- a/src/main/java/com/zy/core/network/ZyStationConnectDriver.java
+++ b/src/main/java/com/zy/core/network/ZyStationConnectDriver.java
@@ -11,8 +11,10 @@
import java.util.List;
import com.zy.core.network.fake.ZyStationFakeConnect;
import com.zy.core.network.fake.ZyStationFakeSegConnect;
+import com.zy.core.network.fake.ZyStationV4FakeSegConnect;
import com.zy.core.network.real.ZyStationRealConnect;
import com.zy.core.network.real.ZyStationV3RealConnect;
+import com.zy.core.network.real.ZyStationV4RealConnect;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -27,6 +29,7 @@
private static final ZyStationFakeConnect zyStationFakeConnect = new ZyStationFakeConnect();
private static final ZyStationFakeSegConnect zyStationFakeSegConnect = new ZyStationFakeSegConnect();
+ private static final ZyStationV4FakeSegConnect zyStationV4FakeSegConnect = new ZyStationV4FakeSegConnect();
private boolean connected = false;
private DeviceConfig deviceConfig;
@@ -50,6 +53,8 @@
if (deviceConfig.getFake() == 0) {
if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) {
zyStationConnectApi = new ZyStationV3RealConnect(deviceConfig, redisUtil);
+ } else if ("ZyStationV4Thread".equals(deviceConfig.getThreadImpl())) {
+ zyStationConnectApi = new ZyStationV4RealConnect(deviceConfig, redisUtil);
} else {
zyStationConnectApi = new ZyStationRealConnect(deviceConfig, redisUtil);
}
@@ -57,6 +62,9 @@
if ("ZyStationV3Thread".equals(deviceConfig.getThreadImpl())) {
zyStationFakeSegConnect.addFakeConnect(deviceConfig, redisUtil);
zyStationConnectApi = zyStationFakeSegConnect;
+ } else if ("ZyStationV4Thread".equals(deviceConfig.getThreadImpl())) {
+ zyStationV4FakeSegConnect.addFakeConnect(deviceConfig, redisUtil);
+ zyStationConnectApi = zyStationV4FakeSegConnect;
} else {
zyStationFakeConnect.addFakeConnect(deviceConfig, redisUtil);
zyStationConnectApi = zyStationFakeConnect;
diff --git a/src/main/java/com/zy/core/network/entity/ZyDualCrnStatusEntity.java b/src/main/java/com/zy/core/network/entity/ZyDualCrnStatusEntity.java
index 33dd5f3..b2c516a 100644
--- a/src/main/java/com/zy/core/network/entity/ZyDualCrnStatusEntity.java
+++ b/src/main/java/com/zy/core/network/entity/ZyDualCrnStatusEntity.java
@@ -72,6 +72,10 @@
public Integer taskReceiveTwo;
+ public Integer taskSend;
+
+ public Integer taskSendTwo;
+
/**
* 鍫嗗灈鏈哄綋鍓嶅垪鍙�
*/
diff --git a/src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java b/src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java
index 40bdbfa..caf2695 100644
--- a/src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java
+++ b/src/main/java/com/zy/core/network/entity/ZyStationStatusEntity.java
@@ -50,6 +50,9 @@
//閲嶉噺
private Double weight;
+ //浠诲姟鍙啓鍖�
+ private Integer taskWriteIdx;
+
//杩愯鍫靛
private boolean runBlock = false;
diff --git a/src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java b/src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java
index d529843..79762ed 100644
--- a/src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java
+++ b/src/main/java/com/zy/core/network/fake/ZyDualCrnFakeConnect.java
@@ -2,7 +2,7 @@
import com.alibaba.fastjson.JSON;
import com.zy.asrs.entity.DeviceConfig;
-import com.zy.core.enums.CrnStatusType;
+import com.zy.core.enums.DualCrnStatusType;
import com.zy.core.enums.DualCrnTaskModeType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.DualCrnCommand;
@@ -20,6 +20,8 @@
private final ExecutorService executor = Executors
.newFixedThreadPool(9999);
private int taskExecuteStation = 0;
+ private DualCrnCommand station1LastCommand = null;
+ private DualCrnCommand station2LastCommand = null;
public ZyDualCrnFakeConnect(DeviceConfig deviceConfig) {
this.deviceConfig = deviceConfig;
@@ -71,13 +73,29 @@
this.crnStatus.setTaskNo(0);
}
this.crnStatus.setTaskReceive(0);
- this.crnStatus.setStatus(CrnStatusType.IDLE.id);
+ if (station1LastCommand == null) {
+ this.crnStatus.setStatus(DualCrnStatusType.IDLE.id);
+ }else {
+ if (station1LastCommand.getTaskMode().intValue() == DualCrnTaskModeType.PICK.id) {
+ this.crnStatus.setStatus(DualCrnStatusType.FETCH_COMPLETE.id);
+ }else {
+ this.crnStatus.setStatus(DualCrnStatusType.IDLE.id);
+ }
+ }
}else {
if (crnStatus.getLoadedTwo() == 0) {
this.crnStatus.setTaskNoTwo(0);
}
this.crnStatus.setTaskReceiveTwo(0);
- this.crnStatus.setStatusTwo(CrnStatusType.IDLE.id);
+ if (station2LastCommand == null) {
+ this.crnStatus.setStatusTwo(DualCrnStatusType.IDLE.id);
+ }else {
+ if (station1LastCommand.getTaskMode().intValue() == DualCrnTaskModeType.PICK.id) {
+ this.crnStatus.setStatusTwo(DualCrnStatusType.FETCH_COMPLETE.id);
+ }else {
+ this.crnStatus.setStatusTwo(DualCrnStatusType.IDLE.id);
+ }
+ }
}
}
@@ -103,16 +121,16 @@
if(command.getStation() == 1) {
this.crnStatus.setTaskNo(taskNo);
- this.crnStatus.setStatus(CrnStatusType.MOVING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.PUT_MOVING.id);
this.crnStatus.setTaskReceive(1);
moveYZ(this.crnStatus.getBay(), destinationPosY, this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatus(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.WAITING.id);
}else {
this.crnStatus.setTaskNoTwo(taskNo);
- this.crnStatus.setStatusTwo(CrnStatusType.MOVING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.PUT_MOVING.id);
this.crnStatus.setTaskReceive(1);
moveYZ(this.crnStatus.getBay(), destinationPosY, this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatusTwo(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.WAITING.id);
}
taskExecuteStation = 0;
@@ -143,48 +161,52 @@
if(command.getStation() == 1) {
this.crnStatus.setTaskNo(taskNo);
- this.crnStatus.setStatus(CrnStatusType.FETCH_MOVING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.FETCH_MOVING.id);
this.crnStatus.setTaskReceive(1);
moveYZ(this.crnStatus.getBay(), sourcePosY,this.crnStatus.getLevel(), sourcePosZ,command.getStation());
- this.crnStatus.setStatus(CrnStatusType.FETCHING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.FETCHING.id);
sleep(2000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoaded(1);
- this.crnStatus.setStatus(CrnStatusType.PUT_MOVING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.PUT_MOVING.id);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatus(CrnStatusType.PUTTING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.PUTTING.id);
sleep(2000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoaded(0);
- this.crnStatus.setStatus(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.WAITING.id);
+
+ this.station1LastCommand = command;
}else {
this.crnStatus.setTaskNoTwo(taskNo);
- this.crnStatus.setStatusTwo(CrnStatusType.FETCH_MOVING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.FETCH_MOVING.id);
this.crnStatus.setTaskReceiveTwo(1);
moveYZ(this.crnStatus.getBay(), sourcePosY,this.crnStatus.getLevel(), sourcePosZ, command.getStation());
- this.crnStatus.setStatusTwo(CrnStatusType.FETCHING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.FETCHING.id);
sleep(2000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoadedTwo(1);
- this.crnStatus.setStatusTwo(CrnStatusType.PUT_MOVING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.PUT_MOVING.id);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatusTwo(CrnStatusType.PUTTING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.PUTTING.id);
sleep(2000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoadedTwo(0);
- this.crnStatus.setStatusTwo(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.WAITING.id);
+
+ this.station2LastCommand = command;
}
taskExecuteStation = 0;
@@ -212,30 +234,34 @@
if(command.getStation() == 1) {
this.crnStatus.setTaskNo(taskNo);
- this.crnStatus.setStatus(CrnStatusType.FETCH_MOVING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.FETCH_MOVING.id);
this.crnStatus.setTaskReceive(1);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatus(CrnStatusType.FETCHING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.FETCHING.id);
sleep(3000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoaded(1);
- this.crnStatus.setStatus(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.WAITING.id);
+
+ this.station1LastCommand = command;
}else {
this.crnStatus.setTaskNoTwo(taskNo);
- this.crnStatus.setStatusTwo(CrnStatusType.FETCH_MOVING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.FETCH_MOVING.id);
this.crnStatus.setTaskReceiveTwo(1);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatusTwo(CrnStatusType.FETCHING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.FETCHING.id);
sleep(3000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoadedTwo(1);
- this.crnStatus.setStatusTwo(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.WAITING.id);
+
+ this.station2LastCommand = command;
}
taskExecuteStation = 0;
@@ -263,30 +289,34 @@
if(command.getStation() == 1) {
this.crnStatus.setTaskNo(taskNo);
- this.crnStatus.setStatus(CrnStatusType.PUT_MOVING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.PUT_MOVING.id);
this.crnStatus.setTaskReceive(1);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatus(CrnStatusType.PUTTING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.PUTTING.id);
sleep(3000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoaded(0);
- this.crnStatus.setStatus(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatus(DualCrnStatusType.WAITING.id);
+
+ this.station1LastCommand = command;
}else {
this.crnStatus.setTaskNoTwo(taskNo);
- this.crnStatus.setStatusTwo(CrnStatusType.PUT_MOVING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.PUT_MOVING.id);
this.crnStatus.setTaskReceiveTwo(1);
moveYZ(this.crnStatus.getBay(), destinationPosY,this.crnStatus.getLevel(), destinationPosZ, command.getStation());
- this.crnStatus.setStatusTwo(CrnStatusType.PUTTING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.PUTTING.id);
sleep(3000);
if (Thread.currentThread().isInterrupted()) {
return;
}
this.crnStatus.setLoadedTwo(0);
- this.crnStatus.setStatusTwo(CrnStatusType.WAITING.id);
+ this.crnStatus.setStatusTwo(DualCrnStatusType.WAITING.id);
+
+ this.station2LastCommand = command;
}
taskExecuteStation = 0;
diff --git a/src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java b/src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java
index 99d4dd9..c5ac97e 100644
--- a/src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java
+++ b/src/main/java/com/zy/core/network/fake/ZyStationFakeConnect.java
@@ -129,6 +129,10 @@
}
if(commandType == StationCommandType.WRITE_INFO){
+ if (command.getBarcode() != null) {
+ updateStationBarcode(deviceNo, stationId, command.getBarcode());
+ return;
+ }
if (taskNo == 9998 && targetStationId == 0) {
//鐢熸垚鍑哄簱绔欑偣浠跨湡鏁版嵁
generateFakeOutStationData(deviceNo, stationId);
@@ -199,6 +203,23 @@
}
}
+ private void updateStationBarcode(Integer deviceNo, Integer stationId, String barcode) {
+ List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
+ if (statusList == null) {
+ return;
+ }
+
+ ZyStationStatusEntity status = statusList.stream()
+ .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
+ if (status == null) {
+ return;
+ }
+
+ synchronized (status) {
+ status.setBarcode(barcode);
+ }
+ }
+
private void currentLevCommand(StationCommand command, boolean generateBarcode) {
NavigateUtils navigateUtils = SpringUtils.getBean(NavigateUtils.class);
if (navigateUtils == null) {
diff --git a/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java b/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
index 4530d45..b5a077f 100644
--- a/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
+++ b/src/main/java/com/zy/core/network/fake/ZyStationFakeSegConnect.java
@@ -144,12 +144,20 @@
if (command != null) {
taskLastUpdateTime.put(taskNo, System.currentTimeMillis());
- // 棣栨鎺ユ敹鍛戒护鏃跺垵濮嬪寲
- if (finalTargetStationId == null) {
- finalTargetStationId = command.getTargetStaNo();
- if (checkTaskNoInArea(taskNo)) {
- generateBarcode = true;
+ // 姣忔鎺ユ敹鍛戒护閮藉埛鏂扮洰鏍囷紝閬垮厤娌跨敤鏃х洰鏍囧鑷寸姸鎬佹姈鍔�
+ Integer commandTargetStationId = command.getTargetStaNo();
+ if (commandTargetStationId != null) {
+ if (!commandTargetStationId.equals(finalTargetStationId)) {
+ News.info("[WCS Debug] 浠诲姟{}鍒囨崲鐩爣: {} -> {}", taskNo, finalTargetStationId,
+ commandTargetStationId);
}
+ finalTargetStationId = commandTargetStationId;
+ // 褰撳墠绔欑偣鍏堝悓姝ユ渶鏂扮洰鏍囷紝閬垮厤涓婂眰鍦ㄧ獥鍙f湡閲嶅涓嬪彂鍚屼竴璺緞
+ syncCurrentStationTarget(taskNo, currentStationId, finalTargetStationId);
+ }
+
+ if (!generateBarcode && checkTaskNoInArea(taskNo)) {
+ generateBarcode = true;
}
// 灏嗘柊璺緞杩藉姞鍒板緟鎵ц闃熷垪
@@ -157,15 +165,7 @@
if (newPath != null && !newPath.isEmpty()) {
// 鑾峰彇闃熷垪涓渶鍚庝竴涓珯鐐癸紙鐢ㄤ簬琛旀帴鐐瑰幓閲嶏級
Integer lastInQueue = getLastInQueue(pendingPathQueue);
- if (lastInQueue == null) {
- lastInQueue = currentStationId;
- }
-
- int startIndex = 0;
- // 濡傛灉鏂拌矾寰勭殑璧风偣涓庡綋鍓嶄綅缃垨闃熷垪鏈熬閲嶅锛屽垯璺宠繃
- if (lastInQueue != null && !newPath.isEmpty() && newPath.get(0).equals(lastInQueue)) {
- startIndex = 1;
- }
+ int startIndex = getPathAppendStartIndex(newPath, currentStationId, lastInQueue);
for (int i = startIndex; i < newPath.size(); i++) {
pendingPathQueue.offer(newPath.get(i));
@@ -261,7 +261,7 @@
// 璺緞闃熷垪涓虹┖锛岀瓑寰呮柊鐨勫垎娈靛懡浠�
if (currentStationId != null && finalTargetStationId != null
&& currentStationId.equals(finalTargetStationId)) {
- // 宸插埌杈炬渶缁堢洰鏍囷紝姝e父缁撴潫
+ // 宸插埌杈剧洰鏍囷細绔嬪嵆娓呯┖褰撳墠闃熷垪骞剁粨鏉熸湰杞墽琛岋紝鍚庣画鏂板懡浠ら噸鏂板垱寤烘墽琛岀嚎绋�
if (generateBarcode) {
Integer targetDeviceNo = getDeviceNoByStationId(finalTargetStationId);
if (targetDeviceNo != null) {
@@ -269,10 +269,13 @@
News.info("[WCS Debug] 浠诲姟{}鍒拌揪鐩爣{}骞剁敓鎴愭潯鐮�", taskNo, finalTargetStationId);
}
}
+ commandQueue.clear();
+ pendingPathQueue.clear();
+ News.info("[WCS Debug] 浠诲姟{}鍒拌揪鐩爣鍚庢竻绌洪槦鍒楀苟缁撴潫锛岀瓑寰呭悗缁柊鍛戒护閲嶅惎", taskNo);
break;
}
- // 鏈埌杈炬渶缁堢洰鏍囷紝绛夊緟鏂扮殑鍒嗘鍛戒护
+ // 缁х画绛夊緟鏂扮殑鍒嗘鍛戒护
Long lastTime = taskLastUpdateTime.get(taskNo);
if (lastTime != null && System.currentTimeMillis() - lastTime > 30000) {
// 瓒呮椂锛�30绉掑唴娌℃湁鏀跺埌鏂板垎娈靛懡浠�
@@ -302,6 +305,67 @@
last = item;
}
return last;
+ }
+
+ /**
+ * 璁$畻鏂拌矾寰勫湪闃熷垪涓殑杩藉姞璧风偣锛岄伩鍏嶉噸澶嶄笅鍙戝鑷磋矾寰勬潵鍥炶烦
+ */
+ private int getPathAppendStartIndex(List<Integer> newPath, Integer currentStationId, Integer lastInQueue) {
+ if (newPath == null || newPath.isEmpty()) {
+ return 0;
+ }
+
+ if (lastInQueue != null) {
+ int idx = newPath.lastIndexOf(lastInQueue);
+ if (idx >= 0) {
+ return idx + 1;
+ }
+ }
+
+ if (currentStationId != null) {
+ int idx = newPath.lastIndexOf(currentStationId);
+ if (idx >= 0) {
+ return idx + 1;
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * 鍛戒护鍒氬埌杈炬椂鍚屾褰撳墠绔欑偣鐩爣锛岄檷浣庝笂灞傞噸澶嶅彂鍚屼竴璺緞鐨勬鐜�
+ */
+ private void syncCurrentStationTarget(Integer taskNo, Integer currentStationId, Integer targetStationId) {
+ if (currentStationId == null || targetStationId == null) {
+ return;
+ }
+ Integer currentDeviceNo = getDeviceNoByStationId(currentStationId);
+ if (currentDeviceNo == null) {
+ return;
+ }
+
+ lockStations(currentStationId);
+ try {
+ List<ZyStationStatusEntity> statusList = deviceStatusMap.get(currentDeviceNo);
+ if (statusList == null) {
+ return;
+ }
+
+ ZyStationStatusEntity currentStatus = statusList.stream()
+ .filter(item -> item.getStationId().equals(currentStationId)).findFirst().orElse(null);
+ if (currentStatus == null) {
+ return;
+ }
+
+ if (currentStatus.getTaskNo() != null && currentStatus.getTaskNo() > 0
+ && !currentStatus.getTaskNo().equals(taskNo) && currentStatus.isLoading()) {
+ return;
+ }
+
+ updateStationDataInternal(currentStationId, currentDeviceNo, taskNo, targetStationId, null, null, null);
+ } finally {
+ unlockStations(currentStationId);
+ }
}
/**
@@ -347,6 +411,10 @@
}
if (command.getCommandType() == StationCommandType.WRITE_INFO) {
+ if (command.getBarcode() != null) {
+ updateStationBarcode(deviceNo, stationId, command.getBarcode());
+ return;
+ }
if (taskNo == 9998 && targetStationId == 0) {
// 鐢熸垚鍑哄簱绔欑偣浠跨湡鏁版嵁
generateFakeOutStationData(deviceNo, stationId);
@@ -402,6 +470,23 @@
}
}
+ private void updateStationBarcode(Integer deviceNo, Integer stationId, String barcode) {
+ List<ZyStationStatusEntity> statusList = deviceStatusMap.get(deviceNo);
+ if (statusList == null) {
+ return;
+ }
+
+ ZyStationStatusEntity status = statusList.stream()
+ .filter(item -> item.getStationId().equals(stationId)).findFirst().orElse(null);
+ if (status == null) {
+ return;
+ }
+
+ synchronized (status) {
+ status.setBarcode(barcode);
+ }
+ }
+
// segmentedPathCommand 鏂规硶宸插垹闄わ紝鍔熻兘宸叉暣鍚堝埌 runTaskLoop
private Integer getDeviceNoByStationId(Integer stationId) {
diff --git a/src/main/java/com/zy/core/network/real/ZyCrnV2RealConnect.java b/src/main/java/com/zy/core/network/real/ZyCrnV2RealConnect.java
index 5e577af..6904c7f 100644
--- a/src/main/java/com/zy/core/network/real/ZyCrnV2RealConnect.java
+++ b/src/main/java/com/zy/core/network/real/ZyCrnV2RealConnect.java
@@ -109,7 +109,7 @@
Object lock = redisUtil.get(RedisKeyType.CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo());
if (lock == null) {
OperateResult taskClearResult = siemensNet.Write("DB100.0", array);
- redisUtil.set(RedisKeyType.CLEAR_CRN_TASK_LIMIT.key + deviceConfig.getDeviceNo(), "lock", 3);
+ redisUtil.set(RedisKeyType.CLEAR_CRN_TASK_LIMIT.key + deviceConfig.getDeviceNo(), "lock", 1);
}
}
}
@@ -131,7 +131,7 @@
@Override
public CommandResponse sendCommand(CrnCommand command) {
RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
- redisUtil.set(RedisKeyType.CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 10);
+ redisUtil.set(RedisKeyType.CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 2);
CommandResponse response = new CommandResponse(false);
try {
if (null == command) {
@@ -239,7 +239,7 @@
OutputQueue.CRN.offer(MessageFormat.format("銆恵0}銆慬id:{1}] >>>>> 鍛戒护涓嬪彂锛� {2}", DateUtils.convert(new Date()), command.getCrnNo(), JSON.toJSON(command)));
response.setResult(true);
response.setMessage("鍛戒护涓嬪彂鎴愬姛");
- redisUtil.set(RedisKeyType.CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 5);
+ redisUtil.set(RedisKeyType.CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 1);
} else {
News.error("鍐欏叆鍫嗗灈鏈簆lc鏁版嵁澶辫触 ===>> [id:{}]", command.getCrnNo());
OutputQueue.CRN.offer(MessageFormat.format("銆恵0}銆戝啓鍏ュ爢鍨涙満plc鏁版嵁澶辫触 ===>> [id:{1}]", DateUtils.convert(new Date()), command.getCrnNo()));
diff --git a/src/main/java/com/zy/core/network/real/ZyDualCrnRealConnect.java b/src/main/java/com/zy/core/network/real/ZyDualCrnRealConnect.java
index d73416b..3abf33b 100644
--- a/src/main/java/com/zy/core/network/real/ZyDualCrnRealConnect.java
+++ b/src/main/java/com/zy/core/network/real/ZyDualCrnRealConnect.java
@@ -17,6 +17,8 @@
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.OutputQueue;
+import com.zy.core.enums.CrnTaskModeType;
+import com.zy.core.enums.DualCrnTaskModeType;
import com.zy.core.enums.RedisKeyType;
import com.zy.core.model.CommandResponse;
import com.zy.core.model.command.DualCrnCommand;
@@ -25,6 +27,7 @@
import java.text.MessageFormat;
import java.util.Date;
+import java.util.HashMap;
public class ZyDualCrnRealConnect implements ZyDualCrnConnectApi {
@@ -97,20 +100,33 @@
crnStatus.setXDuration((double) siemensNet.getByteTransform().TransSingle(result.Content, 62));
crnStatus.setYDuration((double) siemensNet.getByteTransform().TransSingle(result.Content, 66));
- if ((crnStatus.getStatus() == 0 || crnStatus.getStatus() == 20) && crnStatus.getTaskReceive() == 0) {
- OperateResultExOne<byte[]> taskResult = siemensNet.Read("DB100.0", (short) 18);
- if (taskResult.IsSuccess) {
- short taskNo = siemensNet.getByteTransform().TransInt16(taskResult.Content, 0);
- short taskMode = siemensNet.getByteTransform().TransInt16(taskResult.Content, 2);
- short sourcePosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 4);
- short sourcePosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 6);
- short sourcePosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 8);
- short destinationPosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 10);
- short destinationPosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 12);
- short destinationPosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 14);
- short confirm = siemensNet.getByteTransform().TransInt16(taskResult.Content, 16);
+ OperateResultExOne<byte[]> taskResult = siemensNet.Read("DB100.0", (short) 18);
+ if (taskResult.IsSuccess) {
+ short taskNo = siemensNet.getByteTransform().TransInt16(taskResult.Content, 0);
+ short taskMode = siemensNet.getByteTransform().TransInt16(taskResult.Content, 2);
+ short sourcePosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 4);
+ short sourcePosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 6);
+ short sourcePosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 8);
+ short destinationPosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 10);
+ short destinationPosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 12);
+ short destinationPosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 14);
+ short confirm = siemensNet.getByteTransform().TransInt16(taskResult.Content, 16);
- if(taskNo != 0 || taskMode != 0 || sourcePosX != 0 || sourcePosY != 0 || sourcePosZ != 0 || destinationPosX != 0 || destinationPosY != 0 || destinationPosZ != 0 || confirm != 0) {
+ int hasData = 0;
+ if(taskNo != 0 || taskMode != 0 || sourcePosX != 0 || sourcePosY != 0 || sourcePosZ != 0 || destinationPosX != 0 || destinationPosY != 0 || destinationPosZ != 0 || confirm != 0) {
+ hasData = 1;
+ if (crnStatus.getTaskReceive() == 1) {
+ HashMap<String, Object> map = new HashMap<>();
+ map.put("taskNo", taskNo);
+ map.put("taskMode", taskMode);
+ map.put("sourcePosX", sourcePosX);
+ map.put("sourcePosY", sourcePosY);
+ map.put("sourcePosZ", sourcePosZ);
+ map.put("destinationPosX", destinationPosX);
+ map.put("destinationPosY", destinationPosY);
+ map.put("destinationPosZ", destinationPosZ);
+ map.put("confirm", confirm);
+
short[] array = new short[9];
array[0] = (short) 0;
array[1] = (short) 0;
@@ -122,30 +138,57 @@
array[7] = (short) 0;
array[8] = (short) 0;
- RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
- Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo());
- if (lock == null) {
- OperateResult taskClearResult = siemensNet.Write("DB100.0", array);
- redisUtil.set(RedisKeyType.CLEAR_DUAL_CRN_TASK_LIMIT.key + deviceConfig.getDeviceNo(), "lock", 3);
+ boolean clear = false;
+ if (taskMode == DualCrnTaskModeType.CONFIRM.id) {
+// if (crnStatus.getStatus() == 0) {
+// clear = true;
+// }
+ clear = true;
+ } else {
+ clear = true;
+ }
+
+ if (clear) {
+ RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
+ Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo());
+ if (lock == null) {
+ OperateResult taskClearResult = siemensNet.Write("DB100.0", array);
+ redisUtil.set(RedisKeyType.CLEAR_DUAL_CRN_TASK_LIMIT.key + deviceConfig.getDeviceNo(), "lock", 3);
+ News.info("鍙屽伐浣嶅爢鍨涙満:{}鍙穥}宸ヤ綅鍛戒护鍖哄煙娓呯┖锛屽師濮嬫暟鎹�:{}", deviceConfig.getDeviceNo(), 1, JSON.toJSONString(map));
+ }
}
}
}
+ crnStatus.setTaskSend(hasData);
}
- if ((crnStatus.getStatusTwo() == 0 || crnStatus.getStatusTwo() == 20) && crnStatus.getTaskReceiveTwo() == 0) {
- OperateResultExOne<byte[]> taskResult = siemensNet.Read("DB100.18", (short) 18);
- if (taskResult.IsSuccess) {
- short taskNo = siemensNet.getByteTransform().TransInt16(taskResult.Content, 0);
- short taskMode = siemensNet.getByteTransform().TransInt16(taskResult.Content, 2);
- short sourcePosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 4);
- short sourcePosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 6);
- short sourcePosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 8);
- short destinationPosX = siemensNet.getByteTransform().TransInt16(taskResult.Content, 10);
- short destinationPosY = siemensNet.getByteTransform().TransInt16(taskResult.Content, 12);
- short destinationPosZ = siemensNet.getByteTransform().TransInt16(taskResult.Content, 14);
- short confirm = siemensNet.getByteTransform().TransInt16(taskResult.Content, 16);
+ OperateResultExOne<byte[]> taskResult2 = siemensNet.Read("DB100.18", (short) 18);
+ if (taskResult2.IsSuccess) {
+ short taskNo = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 0);
+ short taskMode = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 2);
+ short sourcePosX = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 4);
+ short sourcePosY = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 6);
+ short sourcePosZ = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 8);
+ short destinationPosX = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 10);
+ short destinationPosY = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 12);
+ short destinationPosZ = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 14);
+ short confirm = siemensNet.getByteTransform().TransInt16(taskResult2.Content, 16);
- if(taskNo != 0 || taskMode != 0 || sourcePosX != 0 || sourcePosY != 0 || sourcePosZ != 0 || destinationPosX != 0 || destinationPosY != 0 || destinationPosZ != 0 || confirm != 0) {
+ int hasData = 0;
+ if(taskNo != 0 || taskMode != 0 || sourcePosX != 0 || sourcePosY != 0 || sourcePosZ != 0 || destinationPosX != 0 || destinationPosY != 0 || destinationPosZ != 0 || confirm != 0) {
+ hasData = 1;
+ if (crnStatus.getTaskReceiveTwo() == 1) {
+ HashMap<String, Object> map = new HashMap<>();
+ map.put("taskNo", taskNo);
+ map.put("taskMode", taskMode);
+ map.put("sourcePosX", sourcePosX);
+ map.put("sourcePosY", sourcePosY);
+ map.put("sourcePosZ", sourcePosZ);
+ map.put("destinationPosX", destinationPosX);
+ map.put("destinationPosY", destinationPosY);
+ map.put("destinationPosZ", destinationPosZ);
+ map.put("confirm", confirm);
+
short[] array = new short[9];
array[0] = (short) 0;
array[1] = (short) 0;
@@ -157,13 +200,28 @@
array[7] = (short) 0;
array[8] = (short) 0;
- RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
- Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo());
- if (lock == null) {
- OperateResult taskClearResult = siemensNet.Write("DB100.18", array);
+ boolean clear = false;
+ if (taskMode == DualCrnTaskModeType.CONFIRM.id) {
+// if (crnStatus.getStatusTwo() == 0) {
+// clear = true;
+// }
+ clear = true;
+ } else {
+ clear = true;
+ }
+
+ if (clear) {
+ RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
+ Object lock = redisUtil.get(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo());
+ if (lock == null) {
+ OperateResult taskClearResult = siemensNet.Write("DB100.18", array);
+ redisUtil.set(RedisKeyType.CLEAR_DUAL_CRN_TASK_LIMIT.key + deviceConfig.getDeviceNo(), "lock", 3);
+ News.info("鍙屽伐浣嶅爢鍨涙満:{}鍙穥}宸ヤ綅鍛戒护鍖哄煙娓呯┖锛屽師濮嬫暟鎹�:{}", deviceConfig.getDeviceNo(), 2, JSON.toJSONString(map));
+ }
}
}
}
+ crnStatus.setTaskSendTwo(hasData);
}
return crnStatus;
@@ -182,7 +240,7 @@
@Override
public CommandResponse sendCommand(DualCrnCommand command) {
RedisUtil redisUtil = SpringUtils.getBean(RedisUtil.class);
- redisUtil.set(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 10);
+ redisUtil.set(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 3);
CommandResponse response = new CommandResponse(false);
try {
if (null == command) {
@@ -261,7 +319,7 @@
OutputQueue.CRN.offer(MessageFormat.format("銆恵0}銆慬id:{1}] >>>>> 鍛戒护涓嬪彂锛� {2}", DateUtils.convert(new Date()), command.getCrnNo(), JSON.toJSON(command)));
response.setResult(true);
response.setMessage("鍛戒护涓嬪彂鎴愬姛");
- redisUtil.set(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 5);
+ redisUtil.set(RedisKeyType.DUAL_CRN_SEND_COMMAND_LOCK.key + deviceConfig.getDeviceNo(), "lock", 3);
} else {
News.error("鍙屽伐浣嶅爢鍨涙満鍐欏叆鍫嗗灈鏈簆lc鏁版嵁澶辫触 ===>> [id:{}]", command.getCrnNo());
OutputQueue.CRN.offer(MessageFormat.format("銆恵0}銆戝啓鍏ュ爢鍨涙満plc鏁版嵁澶辫触 ===>> [id:{1}]", DateUtils.convert(new Date()), command.getCrnNo()));
diff --git a/src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java b/src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
index 7781e5f..6da637a 100644
--- a/src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
+++ b/src/main/java/com/zy/core/network/real/ZyStationV3RealConnect.java
@@ -146,7 +146,8 @@
if (barcodeEntity == null) {
continue;
}
- String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 16 + 2, 14, "UTF-8");
+ byte length = 10;//result2.Content[1];
+ String barcode = siemensNet.getByteTransform().TransString(result2.Content, i * 16 + 2, length, "UTF-8");
barcode = barcode.trim();
barcodeEntity.setBarcode(barcode);
}
diff --git a/src/main/java/com/zy/core/plugin/FakeProcess.java b/src/main/java/com/zy/core/plugin/FakeProcess.java
index ffccad7..8bdb08f 100644
--- a/src/main/java/com/zy/core/plugin/FakeProcess.java
+++ b/src/main/java/com/zy/core/plugin/FakeProcess.java
@@ -125,6 +125,12 @@
stationOperateProcessUtils.crnStationOutExecute();
// 妫�娴嬭緭閫佺珯鐐瑰嚭搴撲换鍔℃墽琛屽畬鎴�
stationOperateProcessUtils.stationOutExecuteFinish();
+ // 妫�娴嬩换鍔¤浆瀹屾垚
+ stationOperateProcessUtils.checkTaskToComplete();
+ // 妫�娴嬪嚭搴撴帓搴�
+ stationOperateProcessUtils.checkStationOutOrder();
+ // 鐩戞帶缁曞湀绔欑偣
+ stationOperateProcessUtils.watchCircleStation();
// 鎵ц鍙屽伐浣嶅爢鍨涙満浠诲姟
dualCrnOperateProcessUtils.dualCrnIoExecute();
@@ -349,64 +355,68 @@
// 鐢熸垚浠跨湡妯℃嫙鍑哄簱浠诲姟
private synchronized void generateFakeOutTask() {
- if (!enableFake.equals("Y")) {
- return;
- }
-
- if (fakeRealTaskRequestWms.equals("Y")) {
- return;
- }
-
- if (!fakeGenerateOutTask.equals("Y")) {
- return;
- }
-
- List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
- for (BasDevp basDevp : basDevps) {
- StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
- if (stationThread == null) {
- continue;
+ try {
+ if (!enableFake.equals("Y")) {
+ return;
}
- Map<Integer, StationProtocol> stationMap = stationThread.getStatusMap();
+ if (fakeRealTaskRequestWms.equals("Y")) {
+ return;
+ }
- List<StationObjModel> list = basDevp.getOutStationList$();
- for (StationObjModel entity : list) {
- Integer stationId = entity.getStationId();
- if (!stationMap.containsKey(stationId)) {
+ if (!fakeGenerateOutTask.equals("Y")) {
+ return;
+ }
+
+ List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
+ for (BasDevp basDevp : basDevps) {
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
+ if (stationThread == null) {
continue;
}
- StationProtocol stationProtocol = stationMap.get(stationId);
- if (stationProtocol == null) {
- continue;
- }
+ Map<Integer, StationProtocol> stationMap = stationThread.getStatusMap();
- Object object = redisUtil.get(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId);
- if (object != null) {
- return;
- }
-
- // 婊¤冻鑷姩銆佹棤鐗┿�佸伐浣滃彿0锛岀敓鎴愬嚭搴撴暟鎹�
- if (stationProtocol.isAutoing()
- && !stationProtocol.isLoading()
- && stationProtocol.getTaskNo() == 0) {
- List<LocMast> locMastList = locMastService
- .selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.F)));
- if (locMastList.isEmpty()) {
+ List<StationObjModel> list = basDevp.getOutStationList$();
+ for (StationObjModel entity : list) {
+ Integer stationId = entity.getStationId();
+ if (!stationMap.containsKey(stationId)) {
continue;
}
- LocMast locMast = locMastList.get(0);
+ StationProtocol stationProtocol = stationMap.get(stationId);
+ if (stationProtocol == null) {
+ continue;
+ }
- CreateOutTaskParam taskParam = new CreateOutTaskParam();
- taskParam.setTaskNo(String.valueOf(commonService.getWorkNo(WrkIoType.OUT.id)));
- taskParam.setStaNo(stationId);
- taskParam.setLocNo(locMast.getLocNo());
- boolean result = commonService.createOutTask(taskParam);
- redisUtil.set(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId, "lock", 10);
+ Object object = redisUtil.get(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId);
+ if (object != null) {
+ return;
+ }
+
+ // 婊¤冻鑷姩銆佹棤鐗┿�佸伐浣滃彿0锛岀敓鎴愬嚭搴撴暟鎹�
+ if (stationProtocol.isAutoing()
+ && !stationProtocol.isLoading()
+ && stationProtocol.getTaskNo() == 0) {
+ List<LocMast> locMastList = locMastService
+ .selectList(new EntityWrapper<LocMast>().eq("loc_sts", String.valueOf(LocStsType.F)));
+ if (locMastList.isEmpty()) {
+ continue;
+ }
+
+ LocMast locMast = locMastList.get(0);
+
+ CreateOutTaskParam taskParam = new CreateOutTaskParam();
+ taskParam.setTaskNo(String.valueOf(commonService.getWorkNo(WrkIoType.OUT.id)));
+ taskParam.setStaNo(stationId);
+ taskParam.setLocNo(locMast.getLocNo());
+ boolean result = commonService.createOutTask(taskParam);
+ redisUtil.set(RedisKeyType.GENERATE_FAKE_OUT_TASK_LIMIT.key + stationId, "lock", 10);
+ }
}
}
+ } catch (Exception e) {
+ e.printStackTrace();
}
}
@@ -477,7 +487,7 @@
if (lock != null) {
continue;
}
- redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 10);
+ redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 3);
String barcode = stationProtocol.getBarcode();
Integer stationIdVal = stationProtocol.getStationId();
@@ -539,7 +549,7 @@
stationProtocol.getPalletHeight());
redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
- stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
+// stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
}
}
}
@@ -596,7 +606,7 @@
continue;
}
- if (System.currentTimeMillis() - stayTime > 1000 * 15) {
+ if (System.currentTimeMillis() - stayTime > 1000 * 60) {
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp,
stationObjModel.getDeviceNo());
if (stationThread == null) {
@@ -801,7 +811,7 @@
wrkMast.setSystemMsg("");
wrkMast.setIoTime(new Date());
if (wrkMastService.updateById(wrkMast)) {
- CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getCrnNo());
+ CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getTaskNo(), crnProtocol.getCrnNo());
MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, resetCommand));
News.info("鍫嗗灈鏈轰换鍔$姸鎬佹洿鏂版垚鍔燂紝鍫嗗灈鏈哄彿={}锛屽伐浣滃彿={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
}
diff --git a/src/main/java/com/zy/core/plugin/NormalProcess.java b/src/main/java/com/zy/core/plugin/NormalProcess.java
index ce5404f..7321111 100644
--- a/src/main/java/com/zy/core/plugin/NormalProcess.java
+++ b/src/main/java/com/zy/core/plugin/NormalProcess.java
@@ -190,7 +190,7 @@
wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
stationProtocol.getPalletHeight());
redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
- stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
+// stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
}
}
}
diff --git a/src/main/java/com/zy/core/plugin/XiaosongProcess.java b/src/main/java/com/zy/core/plugin/XiaosongProcess.java
index 2f1a2ba..b047396 100644
--- a/src/main/java/com/zy/core/plugin/XiaosongProcess.java
+++ b/src/main/java/com/zy/core/plugin/XiaosongProcess.java
@@ -77,6 +77,8 @@
stationOperateProcessUtils.dualCrnStationOutExecute();
//妫�娴嬭緭閫佺珯鐐瑰嚭搴撲换鍔℃墽琛屽畬鎴�
stationOperateProcessUtils.stationOutExecuteFinish();
+ // 妫�娴嬩换鍔¤浆瀹屾垚
+ stationOperateProcessUtils.checkTaskToComplete();
//妫�娴嬭緭閫佺珯鐐规槸鍚﹁繍琛屽牭濉�
stationOperateProcessUtils.checkStationRunBlock();
@@ -140,6 +142,10 @@
}
if (stationProtocol.getError() > 0) {
+ Object lock = redisUtil.get(RedisKeyType.GENERATE_STATION_BACK_LIMIT.key + stationProtocol.getTaskNo());
+ if (lock != null) {
+ continue;
+ }
StationObjModel backStation = entity.getBackStation();
StationCommand command = stationThread.getCommand(StationCommandType.MOVE, commonService.getWorkNo(WrkIoType.STATION_BACK.id), stationId, backStation.getStationId(), 0);
if (command == null) {
@@ -148,11 +154,14 @@
}
MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
News.taskInfo(stationProtocol.getTaskNo(), "{}鎵爜寮傚父锛屽凡閫�鍥炶嚦{}", backStation.getStationId());
+ redisUtil.set(RedisKeyType.GENERATE_STATION_BACK_LIMIT.key + stationProtocol.getTaskNo(), "lock", 10);
+ continue;
}
// 妫�娴嬩换鍔℃槸鍚︾敓鎴�
List<WrkMast> wrkMasts = wrkMastService
- .selectList(new EntityWrapper<WrkMast>().eq("barcode", stationProtocol.getBarcode()));
+ .selectList(new EntityWrapper<WrkMast>()
+ .eq("barcode", stationProtocol.getBarcode()));
if (!wrkMasts.isEmpty()) {
continue;
}
@@ -210,7 +219,7 @@
wmsOperateUtils.applyInTaskAsync(barcode, stationIdVal,
stationProtocol.getPalletHeight());
redisUtil.set(RedisKeyType.GENERATE_IN_TASK_LIMIT.key + stationId, "lock", 2);
- stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
+// stationProtocol.setSystemWarning("璇锋眰鍏ュ簱澶辫触锛學MS鏃犺繑鍥�");
}
}
}
diff --git a/src/main/java/com/zy/core/task/InitLocMapScheduler.java b/src/main/java/com/zy/core/task/InitLocMapScheduler.java
index b8b2314..e1d4da1 100644
--- a/src/main/java/com/zy/core/task/InitLocMapScheduler.java
+++ b/src/main/java/com/zy/core/task/InitLocMapScheduler.java
@@ -53,9 +53,14 @@
mapNode.put("id", i + "-" + j);
String nodeType = map.getString("type");
+ mapNode.put("type", nodeType);
if("shelf".equals(nodeType)) {
mapNode.put("value", MapNodeType.NORMAL_PATH.id);
- }else {
+ } else if ("devp".equals(nodeType)) {
+ mapNode.put("value", MapNodeType.DISABLE.id);
+ } else if ("crn".equals(nodeType) || "dualCrn".equals(nodeType) || "rgv".equals(nodeType)) {
+ mapNode.put("value", MapNodeType.MAIN_PATH.id);
+ } else {
mapNode.put("value", MapNodeType.DISABLE.id);
}
diff --git a/src/main/java/com/zy/core/thread/CrnThread.java b/src/main/java/com/zy/core/thread/CrnThread.java
index 46cbd00..341a7f9 100644
--- a/src/main/java/com/zy/core/thread/CrnThread.java
+++ b/src/main/java/com/zy/core/thread/CrnThread.java
@@ -13,7 +13,7 @@
CrnCommand getMoveCommand(String targetLocNo, Integer taskNo, Integer crnNo);//绉诲姩
- CrnCommand getResetCommand(Integer crnNo);//澶嶄綅
+ CrnCommand getResetCommand(Integer taskNo, Integer crnNo);//澶嶄綅
CommandResponse sendCommand(CrnCommand command);//涓嬪彂鍛戒护
diff --git a/src/main/java/com/zy/core/thread/DualCrnThread.java b/src/main/java/com/zy/core/thread/DualCrnThread.java
index b670bc1..fa4e454 100644
--- a/src/main/java/com/zy/core/thread/DualCrnThread.java
+++ b/src/main/java/com/zy/core/thread/DualCrnThread.java
@@ -17,7 +17,7 @@
DualCrnCommand getMoveCommand(String targetLocNo, Integer taskNo, Integer crnNo);//绉诲姩
- DualCrnCommand getResetCommand(Integer crnNo, Integer station);//澶嶄綅
+ DualCrnCommand getResetCommand(Integer taskNo, Integer crnNo, Integer station);//澶嶄綅
CommandResponse sendCommand(DualCrnCommand command);//涓嬪彂鍛戒护
diff --git a/src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java b/src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
index b680358..aa80bab 100644
--- a/src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZySiemensCrnThread.java
@@ -283,10 +283,10 @@
}
@Override
- public CrnCommand getResetCommand(Integer crnNo) {
+ public CrnCommand getResetCommand(Integer taskNo, Integer crnNo) {
CrnCommand crnCommand = new CrnCommand();
crnCommand.setCrnNo(crnNo); // 鍫嗗灈鏈虹紪鍙�
- crnCommand.setTaskNo(0); // 宸ヤ綔鍙�
+ crnCommand.setTaskNo(taskNo); // 宸ヤ綔鍙�
crnCommand.setAckFinish(1); // 浠诲姟瀹屾垚纭浣�
crnCommand.setTaskMode(CrnTaskModeType.NONE.id); // 浠诲姟妯″紡
crnCommand.setSourcePosX(0); // 婧愬簱浣嶆帓
diff --git a/src/main/java/com/zy/core/thread/impl/ZySiemensCrnV2Thread.java b/src/main/java/com/zy/core/thread/impl/ZySiemensCrnV2Thread.java
index d382648..15b0450 100644
--- a/src/main/java/com/zy/core/thread/impl/ZySiemensCrnV2Thread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZySiemensCrnV2Thread.java
@@ -283,10 +283,10 @@
}
@Override
- public CrnCommand getResetCommand(Integer crnNo) {
+ public CrnCommand getResetCommand(Integer taskNo, Integer crnNo) {
CrnCommand crnCommand = new CrnCommand();
crnCommand.setCrnNo(crnNo); // 鍫嗗灈鏈虹紪鍙�
- crnCommand.setTaskNo(0); // 宸ヤ綔鍙�
+ crnCommand.setTaskNo(taskNo); // 宸ヤ綔鍙�
crnCommand.setAckFinish(1); // 浠诲姟瀹屾垚纭浣�
crnCommand.setTaskMode(CrnTaskModeType.RESET.id); // 浠诲姟妯″紡
crnCommand.setSourcePosX(0); // 婧愬簱浣嶆帓
diff --git a/src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java b/src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java
index c33d25b..2f643ae 100644
--- a/src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java
+++ b/src/main/java/com/zy/core/thread/impl/ZySiemensDualCrnThread.java
@@ -9,6 +9,7 @@
import com.zy.asrs.entity.*;
import com.zy.asrs.service.BasDualCrnpOptService;
import com.zy.asrs.service.BasDualCrnpService;
+import com.zy.asrs.service.WrkMastService;
import com.zy.asrs.utils.Utils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
@@ -48,7 +49,7 @@
private RedisUtil redisUtil;
private ZyDualCrnConnectDriver zyDualCrnConnectDriver;
private DualCrnProtocol crnProtocol;
- private int deviceLogCollectTime = 200;
+ private volatile int deviceLogCollectTime = 200;
public ZySiemensDualCrnThread(DeviceConfig deviceConfig, RedisUtil redisUtil) {
this.deviceConfig = deviceConfig;
@@ -66,7 +67,7 @@
try {
deviceLogCollectTime = Utils.getDeviceLogCollectTime();
readStatus();
- Thread.sleep(50);
+ Thread.sleep(100);
} catch (Exception e) {
log.error("DualCrnThread Fail", e);
}
@@ -87,10 +88,14 @@
List<SendDualCrnCommandParam> commandList = (List<SendDualCrnCommandParam>) task.getData();
for (SendDualCrnCommandParam sendDualCrnCommandParam : commandList) {
DualCrnCommand dualCrnCommand = sendDualCrnCommandParam.getCommands().get(0);
- redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + dualCrnCommand.getTaskNo(), sendDualCrnCommandParam.getCommandIdx(), 60 * 60 * 24);
+ redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + dualCrnCommand.getTaskNo(), 0, 60 * 60 * 24);
+ redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + dualCrnCommand.getTaskNo(), JSON.toJSONString(sendDualCrnCommandParam, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24);
+ if (sendDualCrnCommandParam.getStation() == 1) {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION1_FLAG.key + crnProtocol.getCrnNo(), dualCrnCommand.getTaskNo(), 60 * 60 * 24);
+ } else {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION2_FLAG.key + crnProtocol.getCrnNo(), dualCrnCommand.getTaskNo(), 60 * 60 * 24);
+ }
}
-
- redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getCrnNo(), JSON.toJSONString(commandList, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24);
} else if (step == 3) {
sendCommand((DualCrnCommand) task.getData());
}
@@ -106,11 +111,13 @@
Thread commandThread = new Thread(() -> {
while (true) {
try {
- if(crnProtocol.getMode() != DualCrnModeType.AUTO.id) {
+ Thread.sleep(100);
+
+ if (crnProtocol.getMode() != DualCrnModeType.AUTO.id) {
continue;
}
- if(crnProtocol.getAlarm() != 0) {
+ if (crnProtocol.getAlarm() != 0) {
continue;
}
@@ -120,16 +127,11 @@
continue;
}
- Object commandListObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getCrnNo());
- if (commandListObj == null) {
- continue;
- }
- List<SendDualCrnCommandParam> commandList = JSON.parseArray(commandListObj.toString(), SendDualCrnCommandParam.class);
+ List<SendDualCrnCommandParam> commandList = getDualCrnCommandList();
for (SendDualCrnCommandParam commandParam : commandList) {
processStation(commandParam);
}
- Thread.sleep(100);
} catch (Exception e) {
log.error("DualCrnCommand Fail", e);
}
@@ -143,7 +145,7 @@
List<DualCrnCommand> commandList = commandParam.getCommands();
DualCrnCommand firstCommand = commandList.get(0);
Object idxObj = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo());
- if(idxObj == null) {
+ if (idxObj == null) {
return;
}
Integer idx = (Integer) idxObj;
@@ -153,29 +155,61 @@
DualCrnCommand dualCommand = commandList.get(idx);
boolean send = false;
+ //TODO 鍒ゆ柇绔欑偣1锛�2浠诲姟绫诲瀷鏄惁涓�鑷�
if (station == 1) {
- if (crnProtocol.getStatus().equals(DualCrnStatusType.FETCH_COMPLETE.id)
- || crnProtocol.getStatus().equals(DualCrnStatusType.IDLE.id)
- ) {
- send = true;
+ log.info("宸ヤ綅2浠诲姟==========>{}, 浠诲姟妯″紡---->{}", crnProtocol.getTaskNoTwo(), crnProtocol.getMode());
+ log.info("宸ヤ綅1浠诲姟==========>{}, 浠诲姟妯″紡---->{}", crnProtocol.getTaskNo(), crnProtocol.getMode());
+ Integer taskNo = crnProtocol.getTaskNoTwo();
+ if (crnProtocol.getTaskSend() == 0) {
+ //涓や釜宸ヤ綅鍙厑璁告斁鐩稿悓绫诲瀷浠诲姟
+// if (taskNo != null && taskNo > 0) {
+// WrkMastService mastService = SpringUtils.getBean(WrkMastService.class);
+// WrkMast wrkMast = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", taskNo));
+// WrkMast wrkMast1 = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", dualCommand.getTaskNo()));
+// if (!Objects.isNull(wrkMast) && !Objects.isNull(wrkMast1)) {
+// if (wrkMast1.getIoType() != wrkMast.getIoType()) {
+//// return;
+// }
+// }
+// }
+ // && sendComm(taskNo, dualCommand.getTaskNo())
+ if (dualCommand.getTaskMode().intValue() == DualCrnTaskModeType.PICK.id) {
+ if (crnProtocol.getStatus().equals(DualCrnStatusType.IDLE.id)) {
+ send = true;
+ }
+ } else if (dualCommand.getTaskMode().intValue() == DualCrnTaskModeType.PUT.id) {
+ if (crnProtocol.getStatus().equals(DualCrnStatusType.FETCH_COMPLETE.id)) {
+ send = true;
+ }
+ }
}
- }else {
- if (crnProtocol.getStatusTwo().equals(DualCrnStatusType.FETCH_COMPLETE.id)
- || crnProtocol.getStatusTwo().equals(DualCrnStatusType.IDLE.id)
- ) {
- send = true;
+ } else {
+ log.info("宸ヤ綅1浠诲姟==========>{}, 浠诲姟妯″紡---->{}", crnProtocol.getTaskNo(), crnProtocol.getMode());
+ log.info("宸ヤ綅2浠诲姟==========>{}, 浠诲姟妯″紡---->{}", crnProtocol.getTaskNoTwo(), crnProtocol.getMode());
+ Integer taskNo = crnProtocol.getTaskNo();
+ // && sendComm(taskNo, dualCommand.getTaskNo())
+ if (crnProtocol.getTaskSendTwo() == 0) {
+ if (dualCommand.getTaskMode().intValue() == DualCrnTaskModeType.PICK.id) {
+ if (crnProtocol.getStatusTwo().equals(DualCrnStatusType.IDLE.id)) {
+ send = true;
+ }
+ } else if (dualCommand.getTaskMode().intValue() == DualCrnTaskModeType.PUT.id) {
+ if (crnProtocol.getStatusTwo().equals(DualCrnStatusType.FETCH_COMPLETE.id)) {
+ send = true;
+ }
+ }
}
}
if (idx == 0) {
- if(send) {
+ if (send) {
idx++;
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo(), idx, 60 * 60 * 24);
sendCommand(dualCommand);
- redisUtil.set(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo(), "lock", 5);
+ redisUtil.set(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo(), "lock", 3);
}
return;
- }else {
+ } else {
if (dualCommand.getTaskMode() == DualCrnTaskModeType.PUT.id.shortValue()) {
//绛夊緟涓嬩竴涓换鍔�
Object wait = redisUtil.get(RedisKeyType.DUAL_CRN_PICK_WAIT_NEXT_TASK.key + crnProtocol.getCrnNo());
@@ -213,13 +247,29 @@
}
}
- if(send) {
+ if (send) {
idx++;
redisUtil.set(RedisKeyType.DUAL_CRN_COMMAND_IDX.key + firstCommand.getTaskNo(), idx, 60 * 60 * 24);
sendCommand(dualCommand);
}
return;
}
+ }
+
+ public boolean sendComm(Integer taskNo, Integer current) {
+ //涓や釜宸ヤ綅鍙厑璁告斁鐩稿悓绫诲瀷浠诲姟
+ if (taskNo != null && taskNo > 0) {
+ WrkMastService mastService = SpringUtils.getBean(WrkMastService.class);
+ WrkMast wrkMast = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", taskNo));
+ WrkMast wrkMast1 = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", current));
+ if (!Objects.isNull(wrkMast) && !Objects.isNull(wrkMast1)) {
+ if (wrkMast1.getIoType() != wrkMast.getIoType()) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
/**
@@ -234,6 +284,7 @@
//宸ヤ綅1
crnProtocol.setTaskNo(0);
+ crnProtocol.setDeviceTaskNo(0);
crnProtocol.setStatus(-1);
crnProtocol.setBay(0);
crnProtocol.setLevel(0);
@@ -244,6 +295,7 @@
//宸ヤ綅2
crnProtocol.setTaskNoTwo(0);
+ crnProtocol.setDeviceTaskNoTwo(0);
crnProtocol.setStatusTwo(-1);
crnProtocol.setBayTwo(0);
crnProtocol.setLevelTwo(0);
@@ -264,12 +316,12 @@
BasDualCrnpService basDualCrnpService = null;
try {
basDualCrnpService = SpringUtils.getBean(BasDualCrnpService.class);
- }catch (Exception e){
+ } catch (Exception e) {
}
if (basDualCrnpService != null) {
BasDualCrnp basDualCrnp = basDualCrnpService.selectOne(new EntityWrapper<BasDualCrnp>().eq("crn_no", deviceConfig.getDeviceNo()));
- if(basDualCrnp == null) {
+ if (basDualCrnp == null) {
basDualCrnp = new BasDualCrnp();
basDualCrnp.setCrnNo(deviceConfig.getDeviceNo());
basDualCrnp.setStatus(1);
@@ -294,7 +346,7 @@
/**
* 璇诲彇鐘舵��
*/
- private void readStatus(){
+ private void readStatus() {
ZyDualCrnStatusEntity crnStatus = zyDualCrnConnectDriver.getStatus();
if (crnStatus == null) {
OutputQueue.DUAL_CRN.offer(MessageFormat.format("銆恵0}銆戣鍙栧弻宸ヤ綅鍫嗗灈鏈簆lc鐘舵�佷俊鎭け璐� ===>> [id:{1}] [ip:{2}] [port:{3}]", DateUtils.convert(new Date()), deviceConfig.getDeviceNo(), deviceConfig.getIp(), deviceConfig.getPort()));
@@ -303,18 +355,20 @@
crnProtocol.setMode(crnStatus.getMode());
//宸ヤ綅1
- crnProtocol.setTaskNo(crnStatus.getTaskNo());
+ crnProtocol.setDeviceTaskNo(crnStatus.getTaskNo());
crnProtocol.setStatus(crnStatus.getStatus());
crnProtocol.setForkPos(crnStatus.getForkPos());
crnProtocol.setLoaded(crnStatus.getLoaded());
crnProtocol.setTaskReceive(crnStatus.getTaskReceive());
+ crnProtocol.setTaskSend(crnStatus.getTaskSend());
//宸ヤ綅2
- crnProtocol.setTaskNoTwo(crnStatus.getTaskNoTwo());
+ crnProtocol.setDeviceTaskNoTwo(crnStatus.getTaskNoTwo());
crnProtocol.setStatusTwo(crnStatus.getStatusTwo());
crnProtocol.setForkPosTwo(crnStatus.getForkPosTwo());
crnProtocol.setLoadedTwo(crnStatus.getLoadedTwo());
crnProtocol.setTaskReceiveTwo(crnStatus.getTaskReceiveTwo());
+ crnProtocol.setTaskSendTwo(crnStatus.getTaskSendTwo());
crnProtocol.setBay(crnStatus.getBay());
crnProtocol.setLevel(crnStatus.getLevel());
@@ -335,7 +389,7 @@
crnProtocol.setGoodsType(crnStatus.getGoodsType());
crnProtocol.setBarcode(crnStatus.getBarcode());
- OutputQueue.DUAL_CRN.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛",DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
+ OutputQueue.DUAL_CRN.offer(MessageFormat.format("銆恵0}銆慬id:{1}] <<<<< 瀹炴椂鏁版嵁鏇存柊鎴愬姛", DateUtils.convert(new Date()), deviceConfig.getDeviceNo()));
if (crnProtocol.getAlarm() > 0) {
crnProtocol.setLastCommandTime(-1L);
@@ -358,7 +412,7 @@
//鏇存柊閲囬泦鏃堕棿
crnProtocol.setDeviceDataLog(System.currentTimeMillis());
}
-
+
try {
BasDualCrnpErrLogService errLogService = SpringUtils.getBean(BasDualCrnpErrLogService.class);
if (errLogService != null) {
@@ -394,7 +448,8 @@
}
}
}
- } catch (Exception ignore) {}
+ } catch (Exception ignore) {
+ }
}
@Override
@@ -477,10 +532,10 @@
}
@Override
- public DualCrnCommand getResetCommand(Integer crnNo, Integer station) {
+ public DualCrnCommand getResetCommand(Integer taskNo, Integer crnNo, Integer station) {
DualCrnCommand crnCommand = new DualCrnCommand();
crnCommand.setCrnNo(crnNo); // 鍫嗗灈鏈虹紪鍙�
- crnCommand.setTaskNo(0); // 宸ヤ綔鍙�
+ crnCommand.setTaskNo(taskNo); // 宸ヤ綔鍙�
crnCommand.setTaskMode(DualCrnTaskModeType.CONFIRM.id); // 浠诲姟妯″紡: 纭
crnCommand.setSourcePosX(0); // 婧愬簱浣嶆帓
crnCommand.setSourcePosY(0); // 婧愬簱浣嶅垪
@@ -525,4 +580,77 @@
}
}
}
+
+ public List<SendDualCrnCommandParam> getDualCrnCommandList() {
+ List<SendDualCrnCommandParam> commandList = new ArrayList<>();
+ SendDualCrnCommandParam command1 = getDualCrnCommandList(1);
+ SendDualCrnCommandParam command2 = getDualCrnCommandList(2);
+ if (command1 != null) {
+ commandList.add(command1);
+ }
+
+ if (command2 != null) {
+ commandList.add(command2);
+ }
+
+ return commandList;
+ }
+
+ public SendDualCrnCommandParam getDualCrnCommandList(int station) {
+ SendDualCrnCommandParam sendDualCrnCommandParam = null;
+ String key = null;
+ if (station == 1 && crnProtocol.getTaskNo() > 0) {
+ key = RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getTaskNo();
+ } else if (station == 2 && crnProtocol.getTaskNoTwo() > 0) {
+ key = RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getTaskNoTwo();
+ }
+
+ if (key == null) {
+ return null;
+ }
+ Object commandObj = redisUtil.get(key);
+
+ if (commandObj == null) {
+ return null;
+ }
+
+ sendDualCrnCommandParam = JSON.parseObject(commandObj.toString(), SendDualCrnCommandParam.class);
+ if (sendDualCrnCommandParam == null) {
+ return null;
+ }
+
+ if (station == 1) {
+ if (crnProtocol.getTaskNoTwo() > 0) {
+ Object object = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getTaskNoTwo());
+ if (object != null) {
+ SendDualCrnCommandParam jsonObject = JSON.parseObject(object.toString(), SendDualCrnCommandParam.class);
+ ;
+ if (!jsonObject.getCommands().get(0).getTaskMode().equals(sendDualCrnCommandParam.getCommands().get(0).getTaskMode())) {
+ return null;
+ }
+ }
+ }
+ } else {
+ if (crnProtocol.getTaskNo() > 0) {
+ WrkMastService mastService = SpringUtils.getBean(WrkMastService.class);
+ WrkMast wrkMast = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", crnProtocol.getTaskNo()));
+ WrkMast wrkMast1 = mastService.selectOne(new EntityWrapper<WrkMast>().eq("wrk_no", crnProtocol.getTaskNoTwo()));
+ if (!Objects.isNull(wrkMast) && !Objects.isNull(wrkMast1)) {
+ if (!wrkMast1.getIoType().equals(wrkMast.getIoType())) {
+ return null;
+ }
+ }
+// Object object = redisUtil.get(RedisKeyType.DUAL_CRN_COMMAND_.key + crnProtocol.getTaskNo());
+// if (object != null) {
+// SendDualCrnCommandParam jsonObject = JSON.parseObject(object.toString(), SendDualCrnCommandParam.class);
+// ;
+// if (!jsonObject.getCommands().get(0).getTaskMode().equals(sendDualCrnCommandParam.getCommands().get(0).getTaskMode())) {
+// return null;
+// }
+// }
+ }
+ }
+
+ return sendDualCrnCommandParam;
+ }
}
diff --git a/src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java b/src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java
index c81bf43..85dd39c 100644
--- a/src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java
+++ b/src/main/java/com/zy/core/utils/CrnOperateProcessUtils.java
@@ -54,6 +54,8 @@
private CommonService commonService;
@Autowired
private NotifyUtils notifyUtils;
+ @Autowired
+ private StationOperateProcessUtils stationOperateProcessUtils;
public synchronized void crnIoExecute() {
Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
@@ -84,6 +86,7 @@
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
.eq("crn_no", basCrnp.getCrnNo())
.in("wrk_sts", WrkStsType.INBOUND_RUN.sts, WrkStsType.OUTBOUND_RUN.sts)
+ .orderBy("batch_seq", false)
);
if(!wrkMasts.isEmpty()){
continue;
@@ -257,11 +260,27 @@
return false;
}
+ int stationMaxTaskCount = 30;
+ Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
+ if (systemConfigMapObj != null) {
+ try {
+ HashMap<String, String> systemConfigMap = (HashMap<String, String>) systemConfigMapObj;
+ stationMaxTaskCount = Integer.parseInt(systemConfigMap.getOrDefault("stationMaxTaskCountLimit", "30"));
+ } catch (Exception ignore) {}
+ }
+
+ int currentStationTaskCount = stationOperateProcessUtils.getCurrentStationTaskCount();
+ if (stationMaxTaskCount > 0 && currentStationTaskCount >= stationMaxTaskCount) {
+ News.warn("杈撻�佺珯鐐逛换鍔℃暟閲忚揪鍒颁笂闄愶紝宸插仠姝换鍔′笅鍙戙�傚綋鍓嶄换鍔℃暟={}锛屼笂闄�={}", currentStationTaskCount, stationMaxTaskCount);
+ return false;
+ }
+
Integer crnNo = basCrnp.getCrnNo();
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
.eq("crn_no", crnNo)
.eq("wrk_sts", WrkStsType.NEW_OUTBOUND.sts)
+ .orderBy("batch_seq", false)
);
for (WrkMast wrkMast : wrkMasts) {
@@ -628,7 +647,7 @@
wrkMast.setSystemMsg("");
wrkMast.setIoTime(new Date());
if (wrkMastService.updateById(wrkMast)) {
- CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getCrnNo());
+ CrnCommand resetCommand = crnThread.getResetCommand(crnProtocol.getTaskNo(), crnProtocol.getCrnNo());
MessageQueue.offer(SlaveType.Crn, crnProtocol.getCrnNo(), new Task(2, resetCommand));
News.info("鍫嗗灈鏈轰换鍔$姸鎬佹洿鏂版垚鍔燂紝鍫嗗灈鏈哄彿={}锛屽伐浣滃彿={}", basCrnp.getCrnNo(), crnProtocol.getTaskNo());
}
@@ -813,8 +832,7 @@
String shallowLocNo = Utils.getLocNo(shallowRow, Utils.getBay(locNo), Utils.getLev(locNo));
LocMast shallowLocMast = locMastService.queryByLoc(shallowLocNo);
if (shallowLocMast == null) {
- News.taskInfo(taskNo, "娴呭簱浣�:{} 鏁版嵁涓嶅瓨鍦�", shallowLocNo);
- return false;
+ return true;
}
if (shallowLocMast.getLocSts().equals("O")) {
diff --git a/src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java b/src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java
index 39895fe..919e0b0 100644
--- a/src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java
+++ b/src/main/java/com/zy/core/utils/DualCrnOperateProcessUtils.java
@@ -91,6 +91,10 @@
continue;
}
+ if(dualCrnProtocol.getTaskSend() != 0 || dualCrnProtocol.getTaskSendTwo() != 0) {
+ continue;
+ }
+
this.crnExecute(basDualCrnp, dualCrnThread);
}
}
@@ -195,18 +199,19 @@
WrkMast stationOneWrkMast = null;
WrkMast stationTwoWrkMast = null;
- List<Integer> disableList = basDualCrnp.getDisableStationOneBays$();
+ List<Integer> disableOneList = basDualCrnp.getDisableStationOneBays$();
+ List<Integer> disableTwoList = basDualCrnp.getDisableStationTwoBays$();
for (WrkMast wrkMast : outTaskList) {
if (stationOneWrkMast == null) {
- if (!disableList.contains(Utils.getBay(wrkMast.getSourceLocNo()))) {
+ if (!disableOneList.contains(Utils.getBay(wrkMast.getSourceLocNo()))) {
stationOneWrkMast = wrkMast;
continue;
}
}
if (stationTwoWrkMast == null) {
- if (!disableList.contains(Utils.getBay(wrkMast.getSourceLocNo()))) {
+ if (!disableTwoList.contains(Utils.getBay(wrkMast.getSourceLocNo()))) {
stationTwoWrkMast = wrkMast;
continue;
}
@@ -461,6 +466,10 @@
Integer station = inStationObjModel.getDualCrnExecuteStation();
if (station == 1) {
+ if (dualCrnProtocol.getTaskNo() > 0) {
+ News.taskInfo(wrkMast.getWrkNo(), "宸ヤ綅1绯荤粺鍐呴儴璁板綍鏈変换鍔�");
+ return null;
+ }
List<Integer> basList = basDualCrnp.getDisableStationOneBays$();
if (basList.contains(Utils.getBay(wrkMast.getLocNo()))) {
//绂佹鏀捐揣鍒楋紝鐢宠閲嶆柊鍒嗛厤
@@ -468,6 +477,10 @@
return null;
}
}else {
+ if (dualCrnProtocol.getTaskNoTwo() > 0) {
+ News.taskInfo(wrkMast.getWrkNo(), "宸ヤ綅2绯荤粺鍐呴儴璁板綍鏈変换鍔�");
+ return null;
+ }
List<Integer> basList = basDualCrnp.getDisableStationTwoBays$();
if (basList.contains(Utils.getBay(wrkMast.getLocNo()))) {
//绂佹鏀捐揣鍒楋紝鐢宠閲嶆柊鍒嗛厤
@@ -516,6 +529,18 @@
if (outStationList.isEmpty()) {
News.info("鍙屽伐浣嶅爢鍨涙満:{} 鍑哄簱绔欑偣鏈缃�", basDualCrnp.getCrnNo());
return null;
+ }
+
+ if (station == 1) {
+ if (dualCrnProtocol.getTaskNo() > 0) {
+ News.taskInfo(wrkMast.getWrkNo(), "宸ヤ綅1绯荤粺鍐呴儴璁板綍鏈変换鍔�");
+ return null;
+ }
+ }else {
+ if (dualCrnProtocol.getTaskNoTwo() > 0) {
+ News.taskInfo(wrkMast.getWrkNo(), "宸ヤ綅2绯荤粺鍐呴儴璁板綍鏈変换鍔�");
+ return null;
+ }
}
Integer crnNo = basDualCrnp.getCrnNo();
@@ -684,12 +709,14 @@
continue;
}
- if(dualCrnProtocol.getTaskNo() > 0 && dualCrnProtocol.getStatus() == DualCrnStatusType.WAITING.id) {
+ if((dualCrnProtocol.getTaskNo() > 0 && dualCrnProtocol.getDeviceTaskNo() > 0) && dualCrnProtocol.getTaskSend() == 0 && dualCrnProtocol.getStatus().equals(DualCrnStatusType.WAITING.id)) {
executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNo(), 1);
+ continue;
}
- if(dualCrnProtocol.getTaskNoTwo() > 0 && dualCrnProtocol.getStatusTwo() == DualCrnStatusType.WAITING.id) {
+ if((dualCrnProtocol.getTaskNoTwo() > 0 && dualCrnProtocol.getDeviceTaskNoTwo() > 0) && dualCrnProtocol.getTaskSendTwo() == 0 && dualCrnProtocol.getStatusTwo().equals(DualCrnStatusType.WAITING.id)) {
executeFinish(basDualCrnp, dualCrnThread, dualCrnProtocol, dualCrnProtocol.getTaskNoTwo(), 2);
+ continue;
}
}
}
@@ -753,21 +780,28 @@
return;
}
- DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station);
+ DualCrnCommand resetCommand = dualCrnThread.getResetCommand(taskNo, dualCrnProtocol.getCrnNo(), station);
boolean offer = MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand));
if (offer) {
+ if (station == 1) {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION1_FLAG.key + basDualCrnp.getCrnNo(), 0, 60 * 60 * 24);
+ }else {
+ redisUtil.set(RedisKeyType.DUAL_CRN_STATION2_FLAG.key + basDualCrnp.getCrnNo(), 0, 60 * 60 * 24);
+ }
+
wrkMast.setWrkSts(updateWrkSts);
wrkMast.setSystemMsg("");
wrkMast.setIoTime(new Date());
if (wrkMastService.updateById(wrkMast)) {
News.info("鍙屽伐浣嶅爢鍨涙満浠诲姟鐘舵�佹洿鏂版垚鍔燂紝鍫嗗灈鏈哄彿={}锛屽伐浣滃彿={}", basDualCrnp.getCrnNo(), taskNo);
}
- redisUtil.set(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo, "lock", 10);
+ redisUtil.set(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo, "lock", 3);
}
}else {
- DualCrnCommand resetCommand = dualCrnThread.getResetCommand(dualCrnProtocol.getCrnNo(), station);
+ DualCrnCommand resetCommand = dualCrnThread.getResetCommand(taskNo, dualCrnProtocol.getCrnNo(), station);
MessageQueue.offer(SlaveType.DualCrn, dualCrnProtocol.getCrnNo(), new Task(3, resetCommand));
News.info("鍙屽伐浣嶅爢鍨涙満鍛戒护瀹屾垚纭鎴愬姛锛屽爢鍨涙満鍙�={}锛屽伐浣滃彿={}", basDualCrnp.getCrnNo(), taskNo);
+ redisUtil.set(RedisKeyType.DUAL_CRN_IO_EXECUTE_FINISH_LIMIT.key + basDualCrnp.getCrnNo() + "_" + taskNo, "lock", 3);
}
}
@@ -798,8 +832,7 @@
String shallowLocNo = Utils.getLocNo(shallowRow, Utils.getBay(locNo), Utils.getLev(locNo));
LocMast shallowLocMast = locMastService.queryByLoc(shallowLocNo);
if (shallowLocMast == null) {
- News.taskInfo(taskNo, "娴呭簱浣�:{} 鏁版嵁涓嶅瓨鍦�", shallowLocNo);
- return false;
+ return true;
}
if (shallowLocMast.getLocSts().equals("O")) {
diff --git a/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java b/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
index a41ff8a..72d192f 100644
--- a/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
+++ b/src/main/java/com/zy/core/utils/StationOperateProcessUtils.java
@@ -2,15 +2,21 @@
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
+import com.core.common.Cools;
import com.core.exception.CoolException;
import com.zy.asrs.domain.enums.NotifyMsgType;
+import com.zy.asrs.domain.vo.StationCycleCapacityVo;
+import com.zy.asrs.domain.vo.StationCycleLoopVo;
import com.zy.asrs.entity.*;
import com.zy.asrs.service.*;
import com.zy.asrs.utils.NotifyUtils;
import com.zy.common.entity.FindCrnNoResult;
+import com.zy.common.model.NavigateNode;
import com.zy.common.model.StartupDto;
import com.zy.common.service.CommonService;
+import com.zy.common.utils.NavigateUtils;
import com.zy.common.utils.RedisUtil;
import com.zy.core.News;
import com.zy.core.cache.MessageQueue;
@@ -28,6 +34,7 @@
@Component
public class StationOperateProcessUtils {
+ private static final int LOOP_LOAD_RESERVE_EXPIRE_SECONDS = 120;
@Autowired
private BasDevpService basDevpService;
@@ -36,10 +43,6 @@
@Autowired
private CommonService commonService;
@Autowired
- private BasCrnpService basCrnpService;
- @Autowired
- private BasDualCrnpService basDualCrnpService;
- @Autowired
private RedisUtil redisUtil;
@Autowired
private LocMastService locMastService;
@@ -47,10 +50,20 @@
private WmsOperateUtils wmsOperateUtils;
@Autowired
private NotifyUtils notifyUtils;
+ @Autowired
+ private NavigateUtils navigateUtils;
+ @Autowired
+ private BasStationService basStationService;
+ @Autowired
+ private StationCycleCapacityService stationCycleCapacityService;
//鎵ц杈撻�佺珯鐐瑰叆搴撲换鍔�
public synchronized void stationInExecute() {
try {
+ DispatchLimitConfig limitConfig = getDispatchLimitConfig();
+ int[] currentStationTaskCountRef = new int[]{countCurrentStationTask()};
+ LoadGuardState loadGuardState = buildLoadGuardState(limitConfig);
+
List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
for (BasDevp basDevp : basDevps) {
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
@@ -105,6 +118,12 @@
continue;
}
+ LoopHitResult loopHitResult = findPathLoopHit(limitConfig, stationProtocol.getStationId(), targetStationId, loadGuardState);
+
+ if (isDispatchBlocked(limitConfig, currentStationTaskCountRef[0], loadGuardState, loopHitResult.isThroughLoop())) {
+ return;
+ }
+
StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationId, targetStationId, 0);
if (command == null) {
News.taskInfo(wrkMast.getWrkNo(), "{}宸ヤ綔,鑾峰彇杈撻�佺嚎鍛戒护澶辫触", wrkMast.getWrkNo());
@@ -120,6 +139,8 @@
MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
News.info("杈撻�佺珯鐐瑰叆搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationId, wrkMast.getWrkNo(), JSON.toJSONString(command));
redisUtil.set(RedisKeyType.STATION_IN_EXECUTE_LIMIT.key + stationId, "lock", 5);
+ loadGuardState.reserveLoopTask(loopHitResult.getLoopNo());
+ saveLoopLoadReserve(wrkMast.getWrkNo(), loopHitResult);
}
}
}
@@ -132,10 +153,16 @@
//鎵ц鍫嗗灈鏈鸿緭閫佺珯鐐瑰嚭搴撲换鍔�
public synchronized void crnStationOutExecute() {
try {
+ DispatchLimitConfig limitConfig = getDispatchLimitConfig();
+ int[] currentStationTaskCountRef = new int[]{countCurrentStationTask()};
+ LoadGuardState loadGuardState = buildLoadGuardState(limitConfig);
+
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>()
.eq("wrk_sts", WrkStsType.OUTBOUND_RUN_COMPLETE.sts)
.isNotNull("crn_no")
);
+ List<Integer> outOrderList = getAllOutOrderList();
+
for (WrkMast wrkMast : wrkMasts) {
Object infoObj = redisUtil.get(RedisKeyType.CRN_OUT_TASK_COMPLETE_STATION_INFO.key + wrkMast.getWrkNo());
if (infoObj == null) {
@@ -165,7 +192,30 @@
&& stationProtocol.isLoading()
&& stationProtocol.getTaskNo() == 0
) {
- StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0);
+ Integer moveStaNo = wrkMast.getStaNo();
+
+ if (!outOrderList.isEmpty()) {
+ List<NavigateNode> nodes = navigateUtils.calcByStationId(stationProtocol.getStationId(), wrkMast.getStaNo());
+ for (int i = nodes.size() - 1; i >= 0; i--) {
+ NavigateNode node = nodes.get(i);
+ JSONObject v = JSONObject.parseObject(node.getNodeValue());
+ if (v != null) {
+ Integer stationId = v.getInteger("stationId");
+ if (outOrderList.contains(stationId)) {
+ moveStaNo = stationId;
+ break;
+ }
+ }
+ }
+ }
+
+ LoopHitResult loopHitResult = findPathLoopHit(limitConfig, stationProtocol.getStationId(), moveStaNo, loadGuardState);
+
+ if (isDispatchBlocked(limitConfig, currentStationTaskCountRef[0], loadGuardState, loopHitResult.isThroughLoop())) {
+ return;
+ }
+
+ StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), moveStaNo, 0);
if (command == null) {
News.taskInfo(wrkMast.getWrkNo(), "鑾峰彇杈撻�佺嚎鍛戒护澶辫触");
continue;
@@ -178,8 +228,10 @@
MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
News.info("杈撻�佺珯鐐瑰嚭搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId(), "lock", 5);
- redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_COMPLETE_LIMIT.key + wrkMast.getWrkNo(), "lock", 60);
redisUtil.del(RedisKeyType.CRN_OUT_TASK_COMPLETE_STATION_INFO.key + wrkMast.getWrkNo());
+ currentStationTaskCountRef[0]++;
+ loadGuardState.reserveLoopTask(loopHitResult.getLoopNo());
+ saveLoopLoadReserve(wrkMast.getWrkNo(), loopHitResult);
}
}
}
@@ -238,7 +290,6 @@
notifyUtils.notify(String.valueOf(SlaveType.Devp), stationObjModel.getDeviceNo(), String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.STATION_OUT_TASK_RUN, null);
News.info("杈撻�佺珯鐐瑰嚭搴撳懡浠や笅鍙戞垚鍔燂紝绔欑偣鍙�={}锛屽伐浣滃彿={}锛屽懡浠ゆ暟鎹�={}", stationProtocol.getStationId(), wrkMast.getWrkNo(), JSON.toJSONString(command));
redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_LIMIT.key + stationProtocol.getStationId(), "lock", 5);
- redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_COMPLETE_LIMIT.key + wrkMast.getWrkNo(), "lock", 60);
redisUtil.del(RedisKeyType.DUAL_CRN_OUT_TASK_STATION_INFO.key + wrkMast.getWrkNo());
}
}
@@ -254,26 +305,74 @@
List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("wrk_sts", WrkStsType.STATION_RUN.sts));
for (WrkMast wrkMast : wrkMasts) {
Integer wrkNo = wrkMast.getWrkNo();
+ Integer targetStaNo = wrkMast.getStaNo();
+
+ boolean complete = false;
+ BasStation basStation = basStationService.selectOne(new EntityWrapper<BasStation>().eq("station_id", targetStaNo));
+ if (basStation == null) {
+ continue;
+ }
+
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basStation.getDeviceNo());
+ if (stationThread == null) {
+ continue;
+ }
+
+ Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
+ StationProtocol stationProtocol = statusMap.get(basStation.getStationId());
+ if (stationProtocol == null) {
+ continue;
+ }
+
+ if (stationProtocol.getTaskNo().equals(wrkNo)) {
+ complete = true;
+ }
+
+ if (complete) {
+ wrkMast.setWrkSts(WrkStsType.STATION_RUN_COMPLETE.sts);
+ wrkMast.setIoTime(new Date());
+ wrkMastService.updateById(wrkMast);
+ notifyUtils.notify(String.valueOf(SlaveType.Devp), basStation.getDeviceNo(), String.valueOf(wrkMast.getWrkNo()), wrkMast.getWmsWrkNo(), NotifyMsgType.STATION_OUT_TASK_RUN_COMPLETE, null);
+ redisUtil.set(RedisKeyType.STATION_OUT_EXECUTE_COMPLETE_LIMIT.key + wrkMast.getWrkNo(), "lock", 60);
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // 妫�娴嬩换鍔¤浆瀹屾垚
+ public synchronized void checkTaskToComplete() {
+ try {
+ List<WrkMast> wrkMasts = wrkMastService.selectList(new EntityWrapper<WrkMast>().eq("wrk_sts", WrkStsType.STATION_RUN_COMPLETE.sts));
+ for (WrkMast wrkMast : wrkMasts) {
+ Integer wrkNo = wrkMast.getWrkNo();
+ Integer targetStaNo = wrkMast.getStaNo();
Object lock = redisUtil.get(RedisKeyType.STATION_OUT_EXECUTE_COMPLETE_LIMIT.key + wrkNo);
if (lock != null) {
continue;
}
- boolean complete = true;
- List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<>());
- for (BasDevp basDevp : basDevps) {
- StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
- if (stationThread == null) {
- continue;
- }
+ boolean complete = false;
+ BasStation basStation = basStationService.selectOne(new EntityWrapper<BasStation>().eq("station_id", targetStaNo));
+ if (basStation == null) {
+ continue;
+ }
- List<StationProtocol> list = stationThread.getStatus();
- for (StationProtocol stationProtocol : list) {
- if (stationProtocol.getTaskNo().equals(wrkNo)) {
- complete = false;
- }
- }
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basStation.getDeviceNo());
+ if (stationThread == null) {
+ continue;
+ }
+
+ Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
+ StationProtocol stationProtocol = statusMap.get(basStation.getStationId());
+ if (stationProtocol == null) {
+ continue;
+ }
+
+ if (!stationProtocol.getTaskNo().equals(wrkNo)) {
+ complete = true;
}
if (complete) {
@@ -426,10 +525,257 @@
//鑾峰彇杈撻�佺嚎浠诲姟鏁伴噺
public synchronized int getCurrentStationTaskCount() {
- int currentStationTaskCount = 0;
+ return countCurrentStationTask();
+ }
+
+ // 妫�娴嬪嚭搴撴帓搴�
+ public synchronized void checkStationOutOrder() {
List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
for (BasDevp basDevp : basDevps) {
StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getId());
+ if (stationThread == null) {
+ continue;
+ }
+ Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
+ List<StationObjModel> orderList = basDevp.getOutOrderList$();
+ for (StationObjModel stationObjModel : orderList) {
+ StationProtocol stationProtocol = statusMap.get(stationObjModel.getStationId());
+ if (stationProtocol == null) {
+ continue;
+ }
+
+ if (!stationProtocol.isAutoing()) {
+ continue;
+ }
+
+ if (!stationProtocol.isLoading()) {
+ continue;
+ }
+
+ if (stationProtocol.getTaskNo() <= 0) {
+ continue;
+ }
+
+ if (!stationProtocol.getStationId().equals(stationProtocol.getTargetStaNo())) {
+ continue;
+ }
+
+ WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
+ if (wrkMast == null) {
+ continue;
+ }
+
+ if (Cools.isEmpty(wrkMast.getBatch())) {
+ continue;
+ }
+
+ if (Cools.isEmpty(wrkMast.getBatchSeq())) {
+ continue;
+ }
+
+ List<WrkMast> batchWrkList = wrkMastService.selectList(new EntityWrapper<WrkMast>()
+ .notIn("wrk_sts", WrkStsType.STATION_RUN_COMPLETE.sts, WrkStsType.COMPLETE_OUTBOUND.sts)
+ .eq("batch", wrkMast.getBatch())
+ .orderBy("batch")
+ );
+ if (batchWrkList.isEmpty()) {
+ continue;
+ }
+ WrkMast firstWrkMast = batchWrkList.get(0);
+ Integer currentBatchSeq = firstWrkMast.getBatchSeq();
+
+ List<NavigateNode> initPath = navigateUtils.calcByStationId(wrkMast.getSourceStaNo(), wrkMast.getStaNo());
+
+ String commandType = "none";
+ Integer seq = getOutStationBatchSeq(initPath, stationProtocol.getStationId(), wrkMast.getBatch());
+ if (seq == null) {
+ if (currentBatchSeq.equals(wrkMast.getBatchSeq())) {
+ commandType = "toTarget";
+ }else {
+ commandType = "toCircle";
+ }
+ }else {
+ seq++;
+ if (seq.equals(wrkMast.getBatchSeq()) && currentBatchSeq.equals(wrkMast.getBatchSeq())) {
+ commandType = "toTarget";
+ }else {
+ commandType = "toCircle";
+ }
+ }
+
+ if (commandType.equals("toTarget")) {
+ StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), wrkMast.getStaNo(), 0);
+ if (command == null) {
+ News.taskInfo(wrkMast.getWrkNo(), "鑾峰彇杈撻�佺嚎鍛戒护澶辫触");
+ continue;
+ }
+ MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
+ News.info("{}浠诲姟鐩存帴鍘荤洰鏍囩偣", wrkMast.getWrkNo());
+ } else if (commandType.equals("toCircle")) {
+ Integer circleTarget = null;
+ for (NavigateNode node : initPath) {
+ JSONObject v = JSONObject.parseObject(node.getNodeValue());
+ if (v != null) {
+ Integer stationId = v.getInteger("stationId");
+ try {
+ List<NavigateNode> enableMovePath = navigateUtils.calcByStationId(stationProtocol.getStationId(), stationId);
+ if (enableMovePath.isEmpty()) {
+ continue;
+ }
+ } catch (Exception e) {
+ continue;
+ }
+
+ circleTarget = stationId;
+ break;
+ }
+ }
+
+ if (circleTarget == null) {
+ continue;
+ }
+
+ StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), circleTarget, 0);
+ if (command == null) {
+ News.taskInfo(wrkMast.getWrkNo(), "鑾峰彇杈撻�佺嚎鍛戒护澶辫触");
+ continue;
+ }
+ MessageQueue.offer(SlaveType.Devp, stationObjModel.getDeviceNo(), new Task(2, command));
+ redisUtil.set(RedisKeyType.WATCH_CIRCLE_STATION_.key + wrkMast.getWrkNo(), JSON.toJSONString(command, SerializerFeature.DisableCircularReferenceDetect), 60 * 60 * 24);
+ News.info("{}浠诲姟杩涜缁曞湀", wrkMast.getWrkNo());
+ }
+ }
+ }
+ }
+
+ // 鐩戞帶缁曞湀绔欑偣
+ public synchronized void watchCircleStation() {
+ List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
+ for (BasDevp basDevp : basDevps) {
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getId());
+ if (stationThread == null) {
+ continue;
+ }
+
+ List<Integer> outOrderList = basDevp.getOutOrderIntList();
+
+ for (StationProtocol stationProtocol : stationThread.getStatus()) {
+ if (!stationProtocol.isAutoing()) {
+ continue;
+ }
+
+ if (!stationProtocol.isLoading()) {
+ continue;
+ }
+
+ if (stationProtocol.getTaskNo() <= 0) {
+ continue;
+ }
+
+ Object circleObj = redisUtil.get(RedisKeyType.WATCH_CIRCLE_STATION_.key + stationProtocol.getTaskNo());
+ if (circleObj == null) {
+ continue;
+ }
+
+ StationCommand circleCommand = JSON.parseObject(circleObj.toString(), StationCommand.class);
+ if (!stationProtocol.getStationId().equals(circleCommand.getTargetStaNo())) {
+ continue;
+ }
+
+ WrkMast wrkMast = wrkMastService.selectByWorkNo(stationProtocol.getTaskNo());
+ if (wrkMast == null) {
+ continue;
+ }
+
+ Integer moveStaNo = wrkMast.getStaNo();
+
+ if (!outOrderList.isEmpty()) {
+ List<NavigateNode> nodes = navigateUtils.calcByStationId(stationProtocol.getStationId(), wrkMast.getStaNo());
+ for (int i = nodes.size() - 1; i >= 0; i--) {
+ NavigateNode node = nodes.get(i);
+ JSONObject v = JSONObject.parseObject(node.getNodeValue());
+ if (v != null) {
+ Integer stationId = v.getInteger("stationId");
+ if (outOrderList.contains(stationId)) {
+ moveStaNo = stationId;
+ break;
+ }
+ }
+ }
+ }
+
+ StationCommand command = stationThread.getCommand(StationCommandType.MOVE, wrkMast.getWrkNo(), stationProtocol.getStationId(), moveStaNo, 0);
+ if (command == null) {
+ News.taskInfo(wrkMast.getWrkNo(), "鑾峰彇杈撻�佺嚎鍛戒护澶辫触");
+ continue;
+ }
+ MessageQueue.offer(SlaveType.Devp, basDevp.getDevpNo(), new Task(2, command));
+ }
+ }
+ }
+
+ public List<Integer> getAllOutOrderList() {
+ List<Integer> list = new ArrayList<>();
+ List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
+ for (BasDevp basDevp : basDevps) {
+ List<Integer> orderList = basDevp.getOutOrderIntList();
+ list.addAll(orderList);
+ }
+ return list;
+ }
+
+ public Integer getOutStationBatchSeq(List<NavigateNode> pathList, Integer searchStationId, String searchBatch) {
+ List<Integer> checkList = new ArrayList<>();
+ for (int i = pathList.size() - 1; i >= 0; i--) {
+ NavigateNode node = pathList.get(i);
+ JSONObject v = JSONObject.parseObject(node.getNodeValue());
+ if (v != null) {
+ Integer stationId = v.getInteger("stationId");
+ if (searchStationId.equals(stationId)) {
+ break;
+ } else {
+ checkList.add(stationId);
+ }
+ }
+ }
+
+ HashMap<String, Integer> batchMap = new HashMap<>();
+ for (Integer station : checkList) {
+ BasStation basStation = basStationService.selectOne(new EntityWrapper<BasStation>().eq("station_id", station));
+ if (basStation == null) {
+ continue;
+ }
+
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basStation.getDeviceNo());
+ if (stationThread == null) {
+ continue;
+ }
+ Map<Integer, StationProtocol> statusMap = stationThread.getStatusMap();
+ StationProtocol checkStationProtocol = statusMap.get(station);
+ if (checkStationProtocol == null) {
+ continue;
+ }
+ if (checkStationProtocol.getTaskNo() > 0) {
+ WrkMast checkWrkMast = wrkMastService.selectByWorkNo(checkStationProtocol.getTaskNo());
+ if (checkWrkMast == null) {
+ continue;
+ }
+
+ if (!Cools.isEmpty(checkWrkMast.getBatch())) {
+ batchMap.put(checkWrkMast.getBatch(), checkWrkMast.getBatchSeq());
+ }
+ }
+ }
+
+ Integer seq = batchMap.get(searchBatch);
+ return seq;
+ }
+
+ private int countCurrentStationTask() {
+ int currentStationTaskCount = 0;
+ List<BasDevp> basDevps = basDevpService.selectList(new EntityWrapper<BasDevp>());
+ for (BasDevp basDevp : basDevps) {
+ StationThread stationThread = (StationThread) SlaveConnection.get(SlaveType.Devp, basDevp.getDevpNo());
if (stationThread == null) {
continue;
}
@@ -440,9 +786,291 @@
}
}
}
-
return currentStationTaskCount;
}
+ private boolean isDispatchBlocked(DispatchLimitConfig config,
+ int currentStationTaskCount,
+ LoadGuardState loadGuardState,
+ boolean needReserveLoopLoad) {
+ if (config.loopModeEnable) {
+ double currentLoad = loadGuardState.currentLoad();
+ if (currentLoad >= config.circleMaxLoadLimit) {
+ News.warn("褰撳墠鎵胯浇閲忚揪鍒颁笂闄愶紝宸插仠姝㈢珯鐐逛换鍔′笅鍙戙�傚綋鍓嶆壙杞介噺={}锛屼笂闄�={}", formatPercent(currentLoad), formatPercent(config.circleMaxLoadLimit));
+ return true;
+ }
+
+ if (needReserveLoopLoad) {
+ double reserveLoad = loadGuardState.loadAfterReserve();
+ if (reserveLoad >= config.circleMaxLoadLimit) {
+ News.warn("棰勫崰鍚庢壙杞介噺杈惧埌涓婇檺锛屽凡鍋滄绔欑偣浠诲姟涓嬪彂銆傞鍗犲悗鎵胯浇閲�={}锛屼笂闄�={}", formatPercent(reserveLoad), formatPercent(config.circleMaxLoadLimit));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private LoadGuardState buildLoadGuardState(DispatchLimitConfig config) {
+ LoadGuardState state = new LoadGuardState();
+ if (!config.loopModeEnable) {
+ return state;
+ }
+
+ StationCycleCapacityVo capacityVo = stationCycleCapacityService.getLatestSnapshot();
+ if (capacityVo == null) {
+ return state;
+ }
+
+ state.totalStationCount = toNonNegative(capacityVo.getTotalStationCount());
+ state.projectedTaskStationCount = toNonNegative(capacityVo.getTaskStationCount());
+
+ List<StationCycleLoopVo> loopList = capacityVo.getLoopList();
+ if (loopList != null) {
+ for (StationCycleLoopVo loopVo : loopList) {
+ if (loopVo == null || loopVo.getStationIdList() == null) {
+ continue;
+ }
+ Integer loopNo = loopVo.getLoopNo();
+ for (Integer stationId : loopVo.getStationIdList()) {
+ if (stationId != null) {
+ if (loopNo != null) {
+ state.stationLoopNoMap.put(stationId, loopNo);
+ }
+ }
+ }
+ }
+ }
+ return state;
+ }
+
+ private LoopHitResult findPathLoopHit(DispatchLimitConfig config,
+ Integer sourceStationId,
+ Integer targetStationId,
+ LoadGuardState loadGuardState) {
+ if (!config.loopModeEnable) {
+ return LoopHitResult.NO_HIT;
+ }
+ if (sourceStationId == null || targetStationId == null) {
+ return LoopHitResult.NO_HIT;
+ }
+ if (loadGuardState.stationLoopNoMap.isEmpty()) {
+ return LoopHitResult.NO_HIT;
+ }
+
+ try {
+ List<NavigateNode> nodes = navigateUtils.calcByStationId(sourceStationId, targetStationId);
+ if (nodes == null || nodes.isEmpty()) {
+ return LoopHitResult.NO_HIT;
+ }
+
+ for (NavigateNode node : nodes) {
+ Integer stationId = getStationIdFromNode(node);
+ if (stationId == null) {
+ continue;
+ }
+ Integer loopNo = loadGuardState.stationLoopNoMap.get(stationId);
+ if (loopNo != null) {
+ return new LoopHitResult(true, loopNo, stationId);
+ }
+ }
+ } catch (Exception e) {
+ return LoopHitResult.NO_HIT;
+ }
+
+ return LoopHitResult.NO_HIT;
+ }
+
+ private Integer getStationIdFromNode(NavigateNode node) {
+ if (node == null || isBlank(node.getNodeValue())) {
+ return null;
+ }
+ try {
+ JSONObject v = JSONObject.parseObject(node.getNodeValue());
+ if (v == null) {
+ return null;
+ }
+ return v.getInteger("stationId");
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private int toNonNegative(Integer value) {
+ if (value == null || value < 0) {
+ return 0;
+ }
+ return value;
+ }
+
+ private void saveLoopLoadReserve(Integer wrkNo, LoopHitResult loopHitResult) {
+ if (wrkNo == null || wrkNo <= 0 || loopHitResult == null || !loopHitResult.isThroughLoop()) {
+ return;
+ }
+ JSONObject reserveJson = new JSONObject();
+ reserveJson.put("wrkNo", wrkNo);
+ reserveJson.put("loopNo", loopHitResult.getLoopNo());
+ reserveJson.put("hitStationId", loopHitResult.getHitStationId());
+ reserveJson.put("createTime", System.currentTimeMillis());
+ redisUtil.hset(RedisKeyType.STATION_CYCLE_LOAD_RESERVE.key, String.valueOf(wrkNo), reserveJson.toJSONString());
+ redisUtil.expire(RedisKeyType.STATION_CYCLE_LOAD_RESERVE.key, LOOP_LOAD_RESERVE_EXPIRE_SECONDS);
+ }
+
+ private DispatchLimitConfig getDispatchLimitConfig() {
+ DispatchLimitConfig config = new DispatchLimitConfig();
+ Object systemConfigMapObj = redisUtil.get(RedisKeyType.SYSTEM_CONFIG_MAP.key);
+ if (!(systemConfigMapObj instanceof Map)) {
+ return config;
+ }
+ Map<?, ?> systemConfigMap = (Map<?, ?>) systemConfigMapObj;
+
+ config.circleMaxLoadLimit = parseLoadLimit(getConfigValue(systemConfigMap, "circleMaxLoadLimit"), config.circleMaxLoadLimit);
+ String loopModeValue = getConfigValue(systemConfigMap, "circleLoopModeEnable");
+ if (isBlank(loopModeValue)) {
+ loopModeValue = getConfigValue(systemConfigMap, "circleModeEnable");
+ }
+ if (isBlank(loopModeValue)) {
+ loopModeValue = getConfigValue(systemConfigMap, "isCircleMode");
+ }
+ config.loopModeEnable = parseBoolean(loopModeValue, config.loopModeEnable);
+
+ return config;
+ }
+
+ private String getConfigValue(Map<?, ?> configMap, String key) {
+ Object value = configMap.get(key);
+ if (value == null) {
+ return null;
+ }
+ return String.valueOf(value).trim();
+ }
+
+ private boolean parseBoolean(String value, boolean defaultValue) {
+ if (isBlank(value)) {
+ return defaultValue;
+ }
+ String lowValue = value.toLowerCase(Locale.ROOT);
+ if ("y".equals(lowValue) || "yes".equals(lowValue) || "true".equals(lowValue)
+ || "1".equals(lowValue) || "on".equals(lowValue)) {
+ return true;
+ }
+ if ("n".equals(lowValue) || "no".equals(lowValue) || "false".equals(lowValue)
+ || "0".equals(lowValue) || "off".equals(lowValue)) {
+ return false;
+ }
+ return defaultValue;
+ }
+
+ private double parseLoadLimit(String value, double defaultValue) {
+ if (isBlank(value)) {
+ return defaultValue;
+ }
+ try {
+ String normalized = value.replace("%", "").trim();
+ double parsed = Double.parseDouble(normalized);
+ if (parsed > 1.0) {
+ parsed = parsed / 100.0;
+ }
+ if (parsed < 0.0) {
+ return 0.0;
+ }
+ if (parsed > 1.0) {
+ return 1.0;
+ }
+ return parsed;
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ private int parseInt(String value, int defaultValue) {
+ if (isBlank(value)) {
+ return defaultValue;
+ }
+ try {
+ int parsed = Integer.parseInt(value.trim());
+ return parsed < 0 ? defaultValue : parsed;
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ private String formatPercent(double value) {
+ return String.format(Locale.ROOT, "%.1f%%", value * 100.0);
+ }
+
+ private boolean isBlank(String value) {
+ return value == null || value.trim().isEmpty();
+ }
+
+ private static class DispatchLimitConfig {
+ // 鍦堟渶澶ф壙杞借兘鍔涳紝榛樿80%
+ private double circleMaxLoadLimit = 0.8d;
+ // 鏄惁鍚敤缁曞湀妯″紡锛堜粎鍚敤鏃舵墠鐢熸晥鎵胯浇闄愬埗锛�
+ private boolean loopModeEnable = false;
+ }
+
+ private static class LoadGuardState {
+ private int totalStationCount = 0;
+ private int projectedTaskStationCount = 0;
+ private final Map<Integer, Integer> stationLoopNoMap = new HashMap<>();
+
+ private double currentLoad() {
+ return calcLoad(this.projectedTaskStationCount, this.totalStationCount);
+ }
+
+ private double loadAfterReserve() {
+ return calcLoad(this.projectedTaskStationCount + 1, this.totalStationCount);
+ }
+
+ private void reserveLoopTask(Integer loopNo) {
+ if (loopNo == null || loopNo <= 0) {
+ return;
+ }
+ if (this.totalStationCount <= 0) {
+ return;
+ }
+ this.projectedTaskStationCount++;
+ }
+
+ private double calcLoad(int taskCount, int stationCount) {
+ if (stationCount <= 0 || taskCount <= 0) {
+ return 0.0;
+ }
+ double load = (double) taskCount / (double) stationCount;
+ if (load < 0.0) {
+ return 0.0;
+ }
+ if (load > 1.0) {
+ return 1.0;
+ }
+ return load;
+ }
+ }
+
+ private static class LoopHitResult {
+ private static final LoopHitResult NO_HIT = new LoopHitResult(false, null, null);
+ private final boolean throughLoop;
+ private final Integer loopNo;
+ private final Integer hitStationId;
+
+ private LoopHitResult(boolean throughLoop, Integer loopNo, Integer hitStationId) {
+ this.throughLoop = throughLoop;
+ this.loopNo = loopNo;
+ this.hitStationId = hitStationId;
+ }
+
+ private boolean isThroughLoop() {
+ return throughLoop;
+ }
+
+ private Integer getLoopNo() {
+ return loopNo;
+ }
+
+ private Integer getHitStationId() {
+ return hitStationId;
+ }
+ }
}
diff --git a/src/main/java/com/zy/system/controller/LicenseCreatorController.java b/src/main/java/com/zy/system/controller/LicenseCreatorController.java
index 0817de4..f40ee5a 100644
--- a/src/main/java/com/zy/system/controller/LicenseCreatorController.java
+++ b/src/main/java/com/zy/system/controller/LicenseCreatorController.java
@@ -1,6 +1,5 @@
package com.zy.system.controller;
-import com.core.common.Cools;
import com.core.common.R;
import com.zy.system.entity.license.*;
import com.zy.system.timer.LicenseTimer;
@@ -37,24 +36,7 @@
*/
@RequestMapping(value = "/getServerInfos",produces = {MediaType.APPLICATION_JSON_UTF8_VALUE})
public LicenseCheck getServerInfos(@RequestParam(value = "osName",required = false) String osName) {
- //鎿嶄綔绯荤粺绫诲瀷
- if(Cools.isEmpty(osName)){
- osName = System.getProperty("os.name");
- }
- osName = osName.toLowerCase();
-
- AbstractServerInfos abstractServerInfos = null;
-
- //鏍规嵁涓嶅悓鎿嶄綔绯荤粺绫诲瀷閫夋嫨涓嶅悓鐨勬暟鎹幏鍙栨柟娉�
- if (osName.startsWith("windows")) {
- abstractServerInfos = new WindowsServerInfos();
- } else if (osName.startsWith("linux")) {
- abstractServerInfos = new LinuxServerInfos();
- }else{//鍏朵粬鏈嶅姟鍣ㄧ被鍨�
- abstractServerInfos = new WindowsServerInfos();
- }
-
- return abstractServerInfos.getServerInfos();
+ return LicenseUtils.getServerInfos();
}
/**
diff --git a/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java b/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
index f670480..223706d 100644
--- a/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
+++ b/src/main/java/com/zy/system/entity/license/CustomLicenseManager.java
@@ -124,7 +124,7 @@
//License涓彲琚厑璁哥殑鍙傛暟淇℃伅
LicenseCheck expectedCheckModel = (LicenseCheck) content.getExtra();
//褰撳墠鏈嶅姟鍣ㄧ湡瀹炵殑鍙傛暟淇℃伅
- LicenseCheck serverCheckModel = getServerInfos();
+ LicenseCheck serverCheckModel = LicenseUtils.getServerInfos();
if(expectedCheckModel != null && serverCheckModel != null){
//鏍¢獙IP鍦板潃
@@ -180,26 +180,6 @@
}
return null;
- }
-
- /**
- * 鑾峰彇褰撳墠鏈嶅姟鍣ㄩ渶瑕侀澶栨牎楠岀殑License鍙傛暟
- */
- private LicenseCheck getServerInfos(){
- //鎿嶄綔绯荤粺绫诲瀷
- String osName = System.getProperty("os.name").toLowerCase();
- AbstractServerInfos abstractServerInfos = null;
-
- //鏍规嵁涓嶅悓鎿嶄綔绯荤粺绫诲瀷閫夋嫨涓嶅悓鐨勬暟鎹幏鍙栨柟娉�
- if (osName.startsWith("windows")) {
- abstractServerInfos = new WindowsServerInfos();
- } else if (osName.startsWith("linux")) {
- abstractServerInfos = new LinuxServerInfos();
- }else{//鍏朵粬鏈嶅姟鍣ㄧ被鍨�
- abstractServerInfos = new WindowsServerInfos();
- }
-
- return abstractServerInfos.getServerInfos();
}
/**
diff --git a/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java b/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
index 0f40daf..088301a 100644
--- a/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
+++ b/src/main/java/com/zy/system/entity/license/LinuxServerInfos.java
@@ -36,7 +36,11 @@
if (inetAddresses != null && inetAddresses.size() > 0) {
//2. 鑾峰彇鎵�鏈夌綉缁滄帴鍙g殑Mac鍦板潃
- result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
+ result = inetAddresses.stream()
+ .map(this::getMacByInetAddress)
+ .filter(mac -> mac != null && !mac.trim().isEmpty())
+ .distinct()
+ .collect(Collectors.toList());
}
return result;
@@ -88,4 +92,4 @@
reader.close();
return serialNumber;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java b/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java
index c575e6d..fc13a11 100644
--- a/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java
+++ b/src/main/java/com/zy/system/entity/license/WindowsServerInfos.java
@@ -33,7 +33,11 @@
if(inetAddresses != null && inetAddresses.size() > 0){
//2. 鑾峰彇鎵�鏈夌綉缁滄帴鍙g殑Mac鍦板潃
- result = inetAddresses.stream().map(this::getMacByInetAddress).distinct().collect(Collectors.toList());
+ result = inetAddresses.stream()
+ .map(this::getMacByInetAddress)
+ .filter(mac -> mac != null && !mac.trim().isEmpty())
+ .distinct()
+ .collect(Collectors.toList());
}
return result;
@@ -82,4 +86,4 @@
scanner.close();
return serialNumber;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/com/zy/system/timer/LicenseTimer.java b/src/main/java/com/zy/system/timer/LicenseTimer.java
index f6a724f..758d92d 100644
--- a/src/main/java/com/zy/system/timer/LicenseTimer.java
+++ b/src/main/java/com/zy/system/timer/LicenseTimer.java
@@ -73,17 +73,7 @@
public void getRemoteLicense() {
try {
- AbstractServerInfos abstractServerInfos = null;
- String osName = System.getProperty("os.name");
- // 鏍规嵁涓嶅悓鎿嶄綔绯荤粺绫诲瀷閫夋嫨涓嶅悓鐨勬暟鎹幏鍙栨柟娉�
- if (osName.startsWith("windows")) {
- abstractServerInfos = new WindowsServerInfos();
- } else if (osName.startsWith("linux")) {
- abstractServerInfos = new LinuxServerInfos();
- } else {// 鍏朵粬鏈嶅姟鍣ㄧ被鍨�
- abstractServerInfos = new WindowsServerInfos();
- }
- LicenseCheck serverInfos = abstractServerInfos.getServerInfos();
+ LicenseCheck serverInfos = LicenseUtils.getServerInfos();
HashMap<String, Object> map = new HashMap<>();
map.put("subject", subject);
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 992768a..175c9f8 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -17,9 +17,9 @@
validation-timeout: 3000
connection-test-query: select 1
driver-class-name: com.mysql.jdbc.Driver
- url: jdbc:mysql://127.0.0.1:3306/wcs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
+ url: jdbc:mysql://192.168.238.31:3306/wcs?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: root
- password: root
+ password: zy@123
mvc:
static-path-pattern: /**
redis:
@@ -61,7 +61,7 @@
#License鐩稿叧閰嶇疆
license:
- subject: crnWcsDev
+ subject: jsxswcs1
publicAlias: publicCert
storePass: public_zhongyang_123456789
licensePath: license.lic
@@ -72,7 +72,7 @@
threadControlCount: 10
liftType: lift
-mainProcessPlugin: FakeProcess
+mainProcessPlugin: XiaosongProcess
deviceLogStorage:
# 璁惧鏃ュ織瀛樺偍鏂瑰紡 mysql file
diff --git a/src/main/webapp/components/DevpCard.js b/src/main/webapp/components/DevpCard.js
index ba28546..39e69eb 100644
--- a/src/main/webapp/components/DevpCard.js
+++ b/src/main/webapp/components/DevpCard.js
@@ -43,8 +43,22 @@
<el-descriptions-item label="杩愯闃诲">{{ item.runBlock ? 'Y' : 'N' }}</el-descriptions-item>
<el-descriptions-item label="鍚姩鍏ュ簱">{{ item.enableIn ? 'Y' : 'N' }}</el-descriptions-item>
<el-descriptions-item label="鎵樼洏楂樺害">{{ item.palletHeight }}</el-descriptions-item>
- <el-descriptions-item label="鏉$爜">{{ item.barcode }}</el-descriptions-item>
+ <el-descriptions-item label="鏉$爜">
+ <el-popover v-if="item.barcode" placement="top" width="460" trigger="hover">
+ <div style="text-align: center;">
+ <img
+ :src="getBarcodePreview(item.barcode)"
+ :alt="'barcode-' + item.barcode"
+ style="display: block; max-width: 100%; height: auto; margin: 0 auto; image-rendering: pixelated; background: #fff;"
+ />
+ <div style="margin-top: 4px; font-size: 12px; word-break: break-all;">{{ item.barcode }}</div>
+ </div>
+ <span slot="reference" @click.stop="handleBarcodeClick(item)" style="cursor: pointer; color: #409EFF;">{{ item.barcode }}</span>
+ </el-popover>
+ <span v-else @click.stop="handleBarcodeClick(item)" style="cursor: pointer; color: #409EFF;">-</span>
+ </el-descriptions-item>
<el-descriptions-item label="閲嶉噺">{{ item.weight }}</el-descriptions-item>
+ <el-descriptions-item label="浠诲姟鍙啓鍖�">{{ item.taskWriteIdx }}</el-descriptions-item>
<el-descriptions-item label="鏁呴殰浠g爜">{{ item.error }}</el-descriptions-item>
<el-descriptions-item label="鏁呴殰淇℃伅">{{ item.errorMsg }}</el-descriptions-item>
<el-descriptions-item label="鎵╁睍鏁版嵁">{{ item.extend }}</el-descriptions-item>
@@ -92,6 +106,7 @@
taskNo: "",
targetStationId: "",
},
+ barcodePreviewCache: {},
pageSize: 25,
currentPage: 1,
timer: null
@@ -136,6 +151,124 @@
this.pageSize = size;
this.currentPage = 1;
},
+ getBarcodePreview(barcode) {
+ const value = String(barcode || "").trim();
+ if (!value) {
+ return "";
+ }
+ if (this.barcodePreviewCache[value]) {
+ return this.barcodePreviewCache[value];
+ }
+ const encodeResult = this.encodeCode128(value);
+ if (!encodeResult) {
+ return "";
+ }
+ const svg = this.buildCode128Svg(encodeResult, value);
+ const dataUrl = "data:image/svg+xml;charset=UTF-8," + encodeURIComponent(svg);
+ this.$set(this.barcodePreviewCache, value, dataUrl);
+ return dataUrl;
+ },
+ encodeCode128(value) {
+ if (!value) {
+ return null;
+ }
+ const isNumeric = /^\d+$/.test(value);
+ if (isNumeric && value.length % 2 === 0) {
+ return this.encodeCode128C(value);
+ }
+ return this.encodeCode128B(value);
+ },
+ encodeCode128B(value) {
+ const codes = [104];
+ for (let i = 0; i < value.length; i++) {
+ const code = value.charCodeAt(i) - 32;
+ if (code < 0 || code > 94) {
+ return null;
+ }
+ codes.push(code);
+ }
+ return this.buildCode128Pattern(codes);
+ },
+ encodeCode128C(value) {
+ if (value.length % 2 !== 0) {
+ return null;
+ }
+ const codes = [105];
+ for (let i = 0; i < value.length; i += 2) {
+ codes.push(parseInt(value.substring(i, i + 2), 10));
+ }
+ return this.buildCode128Pattern(codes);
+ },
+ buildCode128Pattern(codes) {
+ const patterns = this.getCode128Patterns();
+ let checksum = codes[0];
+ for (let i = 1; i < codes.length; i++) {
+ checksum += codes[i] * i;
+ }
+ const checkCode = checksum % 103;
+ const fullCodes = codes.concat([checkCode, 106]);
+ let bars = "";
+ for (let i = 0; i < fullCodes.length; i++) {
+ const code = fullCodes[i];
+ if (patterns[code] == null) {
+ return null;
+ }
+ bars += patterns[code];
+ }
+ bars += "11";
+ return bars;
+ },
+ buildCode128Svg(bars, text) {
+ const quietModules = 20;
+ const modules = quietModules * 2 + bars.split("").reduce((sum, n) => sum + parseInt(n, 10), 0);
+ const moduleWidth = modules > 300 ? 1 : 2;
+ const width = modules * moduleWidth;
+ const barTop = 10;
+ const barHeight = 110;
+ let x = quietModules * moduleWidth;
+ let black = true;
+ let rects = "";
+ for (let i = 0; i < bars.length; i++) {
+ const w = parseInt(bars[i], 10) * moduleWidth;
+ if (black) {
+ rects += '<rect x="' + x + '" y="' + barTop + '" width="' + w + '" height="' + barHeight + '" fill="#000" shape-rendering="crispEdges" />';
+ }
+ x += w;
+ black = !black;
+ }
+ return (
+ '<svg xmlns="http://www.w3.org/2000/svg" width="' + width + '" height="145" viewBox="0 0 ' + width + ' 145">' +
+ '<rect width="100%" height="100%" fill="#fff" />' +
+ rects +
+ '<text x="' + (width / 2) + '" y="136" text-anchor="middle" font-family="monospace" font-size="14" fill="#111">' +
+ this.escapeXml(text) +
+ "</text>" +
+ "</svg>"
+ );
+ },
+ getCode128Patterns() {
+ return [
+ "212222", "222122", "222221", "121223", "121322", "131222", "122213", "122312", "132212", "221213",
+ "221312", "231212", "112232", "122132", "122231", "113222", "123122", "123221", "223211", "221132",
+ "221231", "213212", "223112", "312131", "311222", "321122", "321221", "312212", "322112", "322211",
+ "212123", "212321", "232121", "111323", "131123", "131321", "112313", "132113", "132311", "211313",
+ "231113", "231311", "112133", "112331", "132131", "113123", "113321", "133121", "313121", "211331",
+ "231131", "213113", "213311", "213131", "311123", "311321", "331121", "312113", "312311", "332111",
+ "314111", "221411", "431111", "111224", "111422", "121124", "121421", "141122", "141221", "112214",
+ "112412", "122114", "122411", "142112", "142211", "241211", "221114", "413111", "241112", "134111",
+ "111242", "121142", "121241", "114212", "124112", "124211", "411212", "421112", "421211", "212141",
+ "214121", "412121", "111143", "111341", "131141", "114113", "114311", "411113", "411311", "113141",
+ "114131", "311141", "411131", "211412", "211214", "211232", "2331112"
+ ];
+ },
+ escapeXml(text) {
+ return String(text)
+ .replace(/&/g, "&")
+ .replace(/</g, "<")
+ .replace(/>/g, ">")
+ .replace(/"/g, """)
+ .replace(/'/g, "'");
+ },
getDevpStateInfo() {
if (this.readOnly) {
// Frontend filtering for readOnly mode
@@ -171,6 +304,81 @@
}
}
},
+ handleBarcodeClick(item) {
+ if (this.readOnly || !item || item.stationId == null) {
+ return;
+ }
+
+ let that = this;
+ $.ajax({
+ url: baseUrl + "/openapi/getFakeSystemRunStatus",
+ headers: {
+ token: localStorage.getItem("token"),
+ },
+ method: "get",
+ success: (res) => {
+ if (res.code !== 200 || !res.data || !res.data.isFake || !res.data.running) {
+ that.$message({
+ message: "浠呬豢鐪熸ā寮忚繍琛屼腑鍙慨鏀规潯鐮�",
+ type: "warning",
+ });
+ return;
+ }
+
+ that.$prompt("璇疯緭鍏ユ柊鐨勬潯鐮佸�硷紙鍙暀绌烘竻绌猴級", "淇敼鏉$爜", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ inputValue: item.barcode || "",
+ inputPlaceholder: "璇疯緭鍏ユ潯鐮�",
+ }).then(({ value }) => {
+ that.updateStationBarcode(item.stationId, value == null ? "" : String(value).trim());
+ }).catch(() => {});
+ },
+ });
+ },
+ updateStationBarcode(stationId, barcode) {
+ let that = this;
+ $.ajax({
+ url: baseUrl + "/station/command/barcode",
+ headers: {
+ token: localStorage.getItem("token"),
+ },
+ contentType: "application/json",
+ method: "post",
+ data: JSON.stringify({
+ stationId: stationId,
+ barcode: barcode,
+ }),
+ success: (res) => {
+ if (res.code == 200) {
+ that.syncLocalBarcode(stationId, barcode);
+ that.$message({
+ message: "鏉$爜淇敼鎴愬姛",
+ type: "success",
+ });
+ } else {
+ that.$message({
+ message: res.msg || "鏉$爜淇敼澶辫触",
+ type: "warning",
+ });
+ }
+ },
+ });
+ },
+ syncLocalBarcode(stationId, barcode) {
+ let updateFn = (list) => {
+ if (!list || list.length === 0) {
+ return;
+ }
+ list.forEach((row) => {
+ if (row.stationId == stationId) {
+ row.barcode = barcode;
+ }
+ });
+ };
+ updateFn(this.stationList);
+ updateFn(this.fullStationList);
+ },
openControl() {
this.showControl = !this.showControl;
},
diff --git a/src/main/webapp/components/MapCanvas.js b/src/main/webapp/components/MapCanvas.js
index 3147540..f04f4ea 100644
--- a/src/main/webapp/components/MapCanvas.js
+++ b/src/main/webapp/components/MapCanvas.js
@@ -1,7 +1,21 @@
Vue.component('map-canvas', {
template: `
<div style="width: 100%; height: 100%; position: relative;">
- <div ref="pixiView"></div>
+ <div ref="pixiView" style="position: absolute; inset: 0;"></div>
+ <div style="position: absolute; top: 12px; left: 14px; z-index: 30; pointer-events: none; max-width: 52%;">
+ <div style="display: flex; flex-direction: column; gap: 6px; align-items: flex-start;">
+ <div v-for="item in cycleCapacity.loopList"
+ :key="'loop-' + item.loopNo"
+ @mouseenter="handleLoopCardEnter(item)"
+ @mouseleave="handleLoopCardLeave(item)"
+ style="padding: 6px 10px; border-radius: 4px; background: rgba(11, 35, 58, 0.72); color: #fff; font-size: 12px; line-height: 1.4; white-space: nowrap; pointer-events: auto;">
+ 鍦坽{ item.loopNo }} |
+ 绔欑偣: {{ item.stationCount || 0 }} |
+ 浠诲姟: {{ item.taskCount || 0 }} |
+ 鎵胯浇: {{ formatLoadPercent(item.currentLoad) }}
+ </div>
+ </div>
+ </div>
<div v-show="shelfTooltip.visible"
:style="shelfTooltipStyle()">
{{ shelfTooltip.text }}
@@ -80,14 +94,25 @@
item: null
},
shelfTooltipMinScale: 0.4,
+ containerResizeObserver: null,
timer: null,
adjustLabelTimer: null,
- isSwitchingFloor: false
+ isSwitchingFloor: false,
+ cycleCapacity: {
+ loopList: [],
+ totalStationCount: 0,
+ taskStationCount: 0,
+ currentLoad: 0
+ },
+ hoverLoopNo: null,
+ hoverLoopStationIdSet: new Set(),
+ loopHighlightColor: 0xfff34d
}
},
mounted() {
this.currentLev = this.lev || 1;
this.createMap();
+ this.startContainerResizeObserve();
this.loadMapTransformConfig();
this.loadLocList();
this.connectWs();
@@ -100,6 +125,7 @@
this.getCrnInfo();
this.getDualCrnInfo();
this.getSiteInfo();
+ this.getCycleCapacityInfo();
this.getRgvInfo();
}, 1000);
},
@@ -108,6 +134,7 @@
if (this.hoverRaf) { cancelAnimationFrame(this.hoverRaf); this.hoverRaf = null; }
if (this.pixiApp) { this.pixiApp.destroy(true, { children: true }); }
+ if (this.containerResizeObserver) { this.containerResizeObserver.disconnect(); this.containerResizeObserver = null; }
window.removeEventListener('resize', this.resizeToContainer);
if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
if (this.ws && (this.ws.readyState === WebSocket.OPEN || this.ws.readyState === WebSocket.CONNECTING)) { try { this.ws.close(); } catch (e) {} }
@@ -277,11 +304,33 @@
});
//*******************FPS*******************
},
+ startContainerResizeObserve() {
+ if (typeof ResizeObserver === 'undefined' || !this.$el) { return; }
+ this.containerResizeObserver = new ResizeObserver(() => {
+ this.resizeToContainer();
+ });
+ this.containerResizeObserver.observe(this.$el);
+ },
+ getViewportSize() {
+ if (!this.pixiApp || !this.pixiApp.renderer) { return { width: 0, height: 0 }; }
+ const screen = this.pixiApp.renderer.screen;
+ if (screen && screen.width > 0 && screen.height > 0) {
+ return { width: screen.width, height: screen.height };
+ }
+ const rect = this.pixiApp.view ? this.pixiApp.view.getBoundingClientRect() : null;
+ return { width: rect ? rect.width : 0, height: rect ? rect.height : 0 };
+ },
resizeToContainer() {
const w = this.$el.clientWidth || 0;
const h = this.$el.clientHeight || 0;
if (w > 0 && h > 0 && this.pixiApp) {
+ const vw = this.pixiApp.renderer && this.pixiApp.renderer.screen ? this.pixiApp.renderer.screen.width : 0;
+ const vh = this.pixiApp.renderer && this.pixiApp.renderer.screen ? this.pixiApp.renderer.screen.height : 0;
+ if (vw === w && vh === h) { return; }
this.pixiApp.renderer.resize(w, h);
+ if (this.mapContentSize && this.mapContentSize.width > 0 && this.mapContentSize.height > 0) {
+ this.applyMapTransform(true);
+ }
}
},
getMap() {
@@ -289,6 +338,7 @@
},
changeFloor(lev) {
this.currentLev = lev;
+ this.clearLoopStationHighlight();
this.isSwitchingFloor = true;
this.hideShelfTooltip();
this.hoveredShelfCell = null;
@@ -313,6 +363,7 @@
this.getMap();
},
createMapData(map) {
+ this.clearLoopStationHighlight();
this.hideShelfTooltip();
this.hoveredShelfCell = null;
this.mapRowOffsets = [];
@@ -627,21 +678,21 @@
sta.statusObj = null;
if (sta.textObj.parent !== sta) { sta.addChild(sta.textObj); sta.textObj.position.set(sta.width / 2, sta.height / 2); }
}
+ let baseColor = 0xb8b8b8;
if (status === "site-auto") {
- this.updateColor(sta, 0x78ff81);
+ baseColor = 0x78ff81;
} else if (status === "site-auto-run" || status === "site-auto-id" || status === "site-auto-run-id") {
- this.updateColor(sta, 0xfa51f6);
+ baseColor = 0xfa51f6;
} else if (status === "site-unauto") {
- this.updateColor(sta, 0xb8b8b8);
+ baseColor = 0xb8b8b8;
} else if (status === "machine-pakin") {
- this.updateColor(sta, 0x30bffc);
+ baseColor = 0x30bffc;
} else if (status === "machine-pakout") {
- this.updateColor(sta, 0x97b400);
+ baseColor = 0x97b400;
} else if (status === "site-run-block") {
- this.updateColor(sta, 0xe69138);
- } else {
- this.updateColor(sta, 0xb8b8b8);
+ baseColor = 0xe69138;
}
+ this.setStationBaseColor(sta, baseColor);
});
},
getCrnInfo() {
@@ -659,6 +710,38 @@
getRgvInfo() {
if (this.isSwitchingFloor) { return; }
this.sendWs(JSON.stringify({ url: "/console/latest/data/rgv", data: {} }));
+ },
+ getCycleCapacityInfo() {
+ if (this.isSwitchingFloor) { return; }
+ this.sendWs(JSON.stringify({ url: "/console/latest/data/station/cycle/capacity", data: {} }));
+ },
+ setCycleCapacityInfo(res) {
+ const payload = res && res.code === 200 ? res.data : null;
+ if (res && res.code === 403) { parent.location.href = baseUrl + "/login"; return; }
+ if (!payload) { return; }
+ const loopList = Array.isArray(payload.loopList) ? payload.loopList : [];
+ this.cycleCapacity = {
+ loopList: loopList,
+ totalStationCount: payload.totalStationCount || 0,
+ taskStationCount: payload.taskStationCount || 0,
+ currentLoad: typeof payload.currentLoad === 'number' ? payload.currentLoad : parseFloat(payload.currentLoad || 0)
+ };
+ if (this.hoverLoopNo != null) {
+ const targetLoop = loopList.find(v => v && v.loopNo === this.hoverLoopNo);
+ if (targetLoop) {
+ this.hoverLoopStationIdSet = this.buildStationIdSet(targetLoop.stationIdList);
+ this.applyLoopStationHighlight();
+ } else {
+ this.clearLoopStationHighlight();
+ }
+ }
+ },
+ formatLoadPercent(load) {
+ let value = typeof load === 'number' ? load : parseFloat(load || 0);
+ if (!isFinite(value)) { value = 0; }
+ if (value < 0) { value = 0; }
+ if (value > 1) { value = 1; }
+ return (value * 100).toFixed(1) + "%";
},
setCrnInfo(res) {
let crns = Array.isArray(res) ? res : (res && res.code === 200 ? res.data : null);
@@ -814,6 +897,7 @@
if (this.wsReconnectTimer) { clearTimeout(this.wsReconnectTimer); this.wsReconnectTimer = null; }
this.wsReconnectAttempts = 0;
this.getMap(this.currentLev);
+ this.getCycleCapacityInfo();
},
webSocketOnError(e) {
this.scheduleReconnect();
@@ -828,6 +912,8 @@
this.setDualCrnInfo(JSON.parse(result.data));
} else if (result.url === "/console/latest/data/rgv") {
this.setRgvInfo(JSON.parse(result.data));
+ } else if (result.url === "/console/latest/data/station/cycle/capacity") {
+ this.setCycleCapacityInfo(JSON.parse(result.data));
} else if (typeof result.url === "string" && result.url.indexOf("/basMap/lev/") === 0) {
this.setMap(JSON.parse(result.data));
}
@@ -1175,7 +1261,11 @@
text.position.set(sprite.width / 2, sprite.height / 2);
sprite.addChild(text);
sprite.textObj = text;
- if (siteId != null && siteId !== -1) { this.pixiStaMap.set(parseInt(siteId), sprite); }
+ const stationIdInt = parseInt(siteId, 10);
+ if (!isNaN(stationIdInt)) { this.pixiStaMap.set(stationIdInt, sprite); }
+ sprite._stationId = isNaN(stationIdInt) ? null : stationIdInt;
+ sprite._baseColor = 0x00ff7f;
+ sprite._loopHighlighted = false;
sprite.interactive = true;
sprite.buttonMode = true;
sprite.on('pointerdown', () => {
@@ -1376,6 +1466,74 @@
return;
}
sprite.tint = color;
+ },
+ setStationBaseColor(sprite, color) {
+ if (!sprite) { return; }
+ sprite._baseColor = color;
+ if (this.isStationInHoverLoop(sprite)) {
+ this.applyHighlightColor(sprite);
+ } else {
+ this.updateColor(sprite, color);
+ sprite._loopHighlighted = false;
+ }
+ },
+ applyHighlightColor(sprite) {
+ if (!sprite) { return; }
+ this.updateColor(sprite, this.loopHighlightColor);
+ sprite._loopHighlighted = true;
+ },
+ isStationInHoverLoop(sprite) {
+ if (!sprite || sprite._stationId == null || !this.hoverLoopStationIdSet) { return false; }
+ return this.hoverLoopStationIdSet.has(sprite._stationId);
+ },
+ buildStationIdSet(stationIdList) {
+ const set = new Set();
+ if (!Array.isArray(stationIdList)) { return set; }
+ stationIdList.forEach((id) => {
+ const v = parseInt(id, 10);
+ if (!isNaN(v)) { set.add(v); }
+ });
+ return set;
+ },
+ applyLoopStationHighlight() {
+ if (!this.pixiStaMap) { return; }
+ this.pixiStaMap.forEach((sprite) => {
+ if (!sprite) { return; }
+ if (this.isStationInHoverLoop(sprite)) {
+ this.applyHighlightColor(sprite);
+ } else if (sprite._loopHighlighted) {
+ const baseColor = (typeof sprite._baseColor === 'number') ? sprite._baseColor : 0xb8b8b8;
+ this.updateColor(sprite, baseColor);
+ sprite._loopHighlighted = false;
+ }
+ });
+ },
+ clearLoopStationHighlight() {
+ if (this.pixiStaMap) {
+ this.pixiStaMap.forEach((sprite) => {
+ if (!sprite || !sprite._loopHighlighted) { return; }
+ const baseColor = (typeof sprite._baseColor === 'number') ? sprite._baseColor : 0xb8b8b8;
+ this.updateColor(sprite, baseColor);
+ sprite._loopHighlighted = false;
+ });
+ }
+ this.hoverLoopNo = null;
+ this.hoverLoopStationIdSet = new Set();
+ },
+ handleLoopCardEnter(loopItem) {
+ if (!loopItem) { return; }
+ this.hoverLoopNo = loopItem.loopNo;
+ this.hoverLoopStationIdSet = this.buildStationIdSet(loopItem.stationIdList);
+ this.applyLoopStationHighlight();
+ },
+ handleLoopCardLeave(loopItem) {
+ if (!loopItem) {
+ this.clearLoopStationHighlight();
+ return;
+ }
+ if (this.hoverLoopNo === loopItem.loopNo) {
+ this.clearLoopStationHighlight();
+ }
},
isJson(str) {
try { JSON.parse(str); return true; } catch (e) { return false; }
@@ -1642,8 +1800,9 @@
adjustLabelScale() {
const s = this.pixiApp && this.pixiApp.stage ? Math.abs(this.pixiApp.stage.scale.x || 1) : 1;
const minPx = 14;
- const vw = this.pixiApp.view.width;
- const vh = this.pixiApp.view.height;
+ const viewport = this.getViewportSize();
+ const vw = viewport.width;
+ const vh = viewport.height;
const margin = 50;
const mirrorSign = this.mapMirrorX ? -1 : 1;
const inverseRotation = -((this.mapRotation % 360) * Math.PI / 180);
@@ -1821,8 +1980,9 @@
const contentW = size.width || 0;
const contentH = size.height || 0;
if (contentW <= 0 || contentH <= 0) { return; }
- const vw = this.pixiApp.view.width;
- const vh = this.pixiApp.view.height;
+ const viewport = this.getViewportSize();
+ const vw = viewport.width;
+ const vh = viewport.height;
let scale = Math.min(vw / contentW, vh / contentH) * 0.95;
if (!isFinite(scale) || scale <= 0) { scale = 1; }
const baseW = this.mapContentSize.width || contentW;
@@ -1856,12 +2016,6 @@
}
}
});
-
-
-
-
-
-
diff --git a/src/main/webapp/components/WatchDualCrnCard.js b/src/main/webapp/components/WatchDualCrnCard.js
index d221857..6845338 100644
--- a/src/main/webapp/components/WatchDualCrnCard.js
+++ b/src/main/webapp/components/WatchDualCrnCard.js
@@ -47,8 +47,28 @@
<el-descriptions border direction="vertical">
<el-descriptions-item label="妯″紡">{{ item.mode }}</el-descriptions-item>
<el-descriptions-item label="寮傚父鐮�">{{ item.warnCode }}</el-descriptions-item>
- <el-descriptions-item label="宸ヤ綅1浠诲姟鍙�">{{ item.taskNo }}</el-descriptions-item>
- <el-descriptions-item label="宸ヤ綅2浠诲姟鍙�">{{ item.taskNoTwo }}</el-descriptions-item>
+ <el-descriptions-item label="宸ヤ綅1浠诲姟鍙�">
+ <span v-if="readOnly">{{ item.taskNo }}</span>
+ <el-button
+ v-else
+ type="text"
+ size="mini"
+ style="padding:0;"
+ @click.stop="editTaskNo(item, 1)"
+ >{{ item.taskNo }}</el-button>
+ </el-descriptions-item>
+ <el-descriptions-item label="宸ヤ綅2浠诲姟鍙�">
+ <span v-if="readOnly">{{ item.taskNoTwo }}</span>
+ <el-button
+ v-else
+ type="text"
+ size="mini"
+ style="padding:0;"
+ @click.stop="editTaskNo(item, 2)"
+ >{{ item.taskNoTwo }}</el-button>
+ </el-descriptions-item>
+ <el-descriptions-item label="璁惧宸ヤ綅1浠诲姟鍙�">{{ item.deviceTaskNo }}</el-descriptions-item>
+ <el-descriptions-item label="璁惧宸ヤ綅2浠诲姟鍙�">{{ item.deviceTaskNoTwo }}</el-descriptions-item>
<el-descriptions-item label="宸ヤ綅1鐘舵��">{{ item.status }}</el-descriptions-item>
<el-descriptions-item label="宸ヤ綅2鐘舵��">{{ item.statusTwo }}</el-descriptions-item>
<el-descriptions-item label="宸ヤ綅1鏄惁鏈夌墿">{{ item.loading }}</el-descriptions-item>
@@ -57,6 +77,8 @@
<el-descriptions-item label="宸ヤ綅2璐у弶瀹氫綅">{{ item.forkOffsetTwo }}</el-descriptions-item>
<el-descriptions-item label="宸ヤ綅1浠诲姟鎺ユ敹">{{ item.taskReceive }}</el-descriptions-item>
<el-descriptions-item label="宸ヤ綅2浠诲姟鎺ユ敹">{{ item.taskReceiveTwo }}</el-descriptions-item>
+ <el-descriptions-item label="宸ヤ綅1涓嬪彂鏁版嵁">{{ item.taskSend }}</el-descriptions-item>
+ <el-descriptions-item label="宸ヤ綅2涓嬪彂鏁版嵁">{{ item.taskSendTwo }}</el-descriptions-item>
<el-descriptions-item label="鍒�">{{ item.bay }}</el-descriptions-item>
<el-descriptions-item label="灞�">{{ item.lev }}</el-descriptions-item>
<el-descriptions-item label="杞借揣鍙板畾浣�">{{ item.liftPos }}</el-descriptions-item>
@@ -161,6 +183,50 @@
openControl() {
this.showControl = !this.showControl;
},
+ editTaskNo(item, station) {
+ let that = this;
+ const isStationOne = station === 1;
+ const fieldName = isStationOne ? "taskNo" : "taskNoTwo";
+ const stationName = isStationOne ? "宸ヤ綅1" : "宸ヤ綅2";
+ const currentTaskNo = item[fieldName] == null ? "" : String(item[fieldName]);
+ that.$prompt("璇疯緭鍏�" + stationName + "浠诲姟鍙�", "缂栬緫浠诲姟鍙�", {
+ confirmButtonText: "纭畾",
+ cancelButtonText: "鍙栨秷",
+ inputValue: currentTaskNo,
+ inputPattern: /^\d+$/,
+ inputErrorMessage: "浠诲姟鍙峰繀椤绘槸闈炶礋鏁存暟",
+ }).then(({ value }) => {
+ const taskNo = Number(value);
+ $.ajax({
+ url: baseUrl + "/dualcrn/command/updateTaskNo",
+ headers: {
+ token: localStorage.getItem("token"),
+ },
+ contentType: "application/json",
+ method: "post",
+ data: JSON.stringify({
+ crnNo: item.crnNo,
+ station: station,
+ taskNo: taskNo,
+ }),
+ success: (res) => {
+ if (res.code == 200) {
+ item[fieldName] = taskNo;
+ that.$message({
+ message: stationName + "浠诲姟鍙锋洿鏂版垚鍔�",
+ type: "success",
+ });
+ that.getDualCrnStateInfo();
+ } else {
+ that.$message({
+ message: res.msg,
+ type: "warning",
+ });
+ }
+ },
+ });
+ }).catch(() => {});
+ },
getDualCrnStateInfo() {
if (this.$root.sendWs) {
this.$root.sendWs(JSON.stringify({
diff --git a/src/main/webapp/static/js/basDevp/basDevp.js b/src/main/webapp/static/js/basDevp/basDevp.js
index f323842..a373c0a 100644
--- a/src/main/webapp/static/js/basDevp/basDevp.js
+++ b/src/main/webapp/static/js/basDevp/basDevp.js
@@ -38,6 +38,8 @@
{ field: "inStationList", align: "center", title: "鍏ュ簱绔欑偣鏁版嵁" },
{ field: "outStationList", align: "center", title: "鍑哄簱绔欑偣鏁版嵁" },
{ field: "runBlockReassignLocStationList", align: "center", title: "杩愯鍫靛閲嶆柊鍒嗛厤搴撲綅绔欑偣鏁版嵁" },
+ { field: "isOutOrderList", align: "center", title: "鍑哄簱鎺掑簭浜や簰鐐�" },
+ { field: "isLiftTransferList", align: "center", title: "椤跺崌绉绘牻鐐�" },
{
fixed: "right",
diff --git a/src/main/webapp/views/basDevp/basDevp.html b/src/main/webapp/views/basDevp/basDevp.html
index 98bb472..215b640 100644
--- a/src/main/webapp/views/basDevp/basDevp.html
+++ b/src/main/webapp/views/basDevp/basDevp.html
@@ -149,6 +149,18 @@
<input class="layui-input" name="runBlockReassignLocStationList" placeholder="璇疯緭鍏ヨ繍琛屽牭濉為噸鏂板垎閰嶅簱浣嶇珯鐐规暟鎹�">
</div>
</div>
+ <div class="layui-form-item">
+ <label class="layui-form-label">鍑哄簱鎺掑簭浜や簰鐐�: </label>
+ <div class="layui-input-block">
+ <input class="layui-input" name="isOutOrderList" placeholder="璇疯緭鍏ュ嚭搴撴帓搴忎氦浜掔偣">
+ </div>
+ </div>
+ <div class="layui-form-item">
+ <label class="layui-form-label">椤跺崌绉绘牻鐐�: </label>
+ <div class="layui-input-block">
+ <input class="layui-input" name="isLiftTransferList" placeholder="璇疯緭鍏ョ數姊腑杞偣">
+ </div>
+ </div>
</div>
</div>
@@ -188,4 +200,3 @@
</form>
</script>
</html>
-
diff --git a/src/main/webapp/views/locMap/locMap.html b/src/main/webapp/views/locMap/locMap.html
index 5d34f56..36fdee8 100644
--- a/src/main/webapp/views/locMap/locMap.html
+++ b/src/main/webapp/views/locMap/locMap.html
@@ -59,9 +59,9 @@
>
<div v-if="drawerLocNoData!=null">
<div style="margin: 10px;">
- <div style="margin-top: 5px;">鎺掞細{{drawerLocNoData.row}}</div>
- <div style="margin-top: 5px;">鍒楋細{{drawerLocNoData.bay}}</div>
- <div style="margin-top: 5px;">灞傦細{{drawerLocNoData.lev}}</div>
+<!-- <div style="margin-top: 5px;">鎺掞細{{drawerLocNoData.row}}</div>-->
+<!-- <div style="margin-top: 5px;">鍒楋細{{drawerLocNoData.bay}}</div>-->
+<!-- <div style="margin-top: 5px;">灞傦細{{drawerLocNoData.lev}}</div>-->
<div style="margin-top: 5px;">搴撲綅鍙凤細{{drawerLocNoData.locNo}}</div>
<div style="margin-top: 5px;">搴撲綅鐘舵�侊細{{drawerLocNoData.locSts}}</div>
</div>
@@ -101,7 +101,12 @@
let pixiStageList = [];
let pixiStaMap = new Map();
let objectsContainer;
+ let objectsContainer3;
+ let tracksGraphics;
+ let mapRoot;
+ let mapContentSize = { width: 0, height: 0 };
let graphics0;
+ let graphicsF;
let graphics3;
let graphics4;
let graphics5;
@@ -125,6 +130,12 @@
currentLevStaList: [],//褰撳墠妤煎眰绔欑偣list
drawerSta: false,
drawerStaData: null,
+ mapRotation: 0,
+ mapMirrorX: false,
+ mapConfigCodes: {
+ rotate: 'map_canvas_rotation',
+ mirror: 'map_canvas_mirror_x'
+ }
},
mounted() {
this.init()
@@ -157,6 +168,7 @@
ws.onclose = this.webSocketClose
+ this.loadMapTransformConfig()
this.initLev()//鍒濆鍖栨ゼ灞備俊鎭�
setTimeout(() => {
that.getMap(this.currentLev)
@@ -205,6 +217,7 @@
},
changeFloor(lev) {
this.currentLev = lev
+ this.loadMapTransformConfig()
this.reloadMap = true
this.getMap(lev)
},
@@ -229,13 +242,18 @@
graphics67 = pixiApp.renderer.generateTexture(getContainer(67));
graphicsLock = pixiApp.renderer.generateTexture(getContainer(-999));
+ mapRoot = new PIXI.Container();
+ pixiApp.stage.addChild(mapRoot);
// 鍒涘缓涓�涓鍣ㄦ潵绠$悊澶ф壒閲忕殑鏄剧ず瀵硅薄
objectsContainer = new PIXI.Container();
- pixiApp.stage.addChild(objectsContainer);
+ mapRoot.addChild(objectsContainer);
+
+ tracksGraphics = new PIXI.Graphics();
+ mapRoot.addChild(tracksGraphics);
// 鍒涘缓涓�涓鍣ㄦ潵绠$悊澶ф壒閲忕殑鏄剧ず瀵硅薄
objectsContainer3 = new PIXI.Container();
- pixiApp.stage.addChild(objectsContainer3);
+ mapRoot.addChild(objectsContainer3);
//*******************鎷栧姩鐢诲竷*******************
let stageOriginalPos;
@@ -285,16 +303,22 @@
pixiApp.view.addEventListener('wheel', (event) => {
event.stopPropagation();
event.preventDefault();
- const sx = event.clientX;
- const sy = event.clientY;
- const oldZoom = pixiApp.stage.scale.x;
+ const rect = pixiApp.view.getBoundingClientRect();
+ const sx = event.clientX - rect.left;
+ const sy = event.clientY - rect.top;
+ const oldZoomX = pixiApp.stage.scale.x || 1;
+ const oldZoomY = pixiApp.stage.scale.y || 1;
+ const oldZoomAbs = Math.abs(oldZoomX) || 1;
const delta = event.deltaY;
- let newZoom = oldZoom * 0.999 ** delta;
- const worldX = (sx - pixiApp.stage.position.x) / oldZoom;
- const worldY = (sy - pixiApp.stage.position.y) / oldZoom;
- const newPosX = sx - worldX * newZoom;
- const newPosY = sy - worldY * newZoom;
- pixiApp.stage.setTransform(newPosX, newPosY, newZoom, newZoom, 0, 0, 0, 0, 0);
+ let newZoomAbs = oldZoomAbs * 0.999 ** delta;
+ const mirrorX = this.mapMirrorX ? -1 : 1;
+ const newZoomX = mirrorX * newZoomAbs;
+ const newZoomY = newZoomAbs;
+ const worldX = (sx - pixiApp.stage.position.x) / oldZoomX;
+ const worldY = (sy - pixiApp.stage.position.y) / oldZoomY;
+ const newPosX = sx - worldX * newZoomX;
+ const newPosY = sy - worldY * newZoomY;
+ pixiApp.stage.setTransform(newPosX, newPosY, newZoomX, newZoomY, 0, 0, 0, 0, 0);
});
//*******************缂╂斁鐢诲竷*******************
@@ -328,6 +352,7 @@
pixiStageList = [map.length]//鍒濆鍖栧垪琛�
pixiStaMap = new Map();//閲嶇疆
objectsContainer.removeChildren()
+ if (tracksGraphics) { tracksGraphics.clear(); }
map.forEach((item,index) => {
pixiStageList[index] = [item.length]
for (let idx = 0; idx < item.length; idx++) {
@@ -388,21 +413,160 @@
});
const b1 = objectsContainer.getLocalBounds();
- const minX = Math.min(b1.x);
- const minY = Math.min(b1.y);
- const maxX = Math.max(b1.x + b1.width);
- const maxY = Math.max(b1.y + b1.height);
+ const minX = b1.x;
+ const minY = b1.y;
+ const maxX = b1.x + b1.width;
+ const maxY = b1.y + b1.height;
const contentW = Math.max(0, maxX - minX);
const contentH = Math.max(0, maxY - minY);
- const vw = pixiApp.view.width;
- const vh = pixiApp.view.height;
- let scale = Math.min(vw / contentW, vh / contentH) * 0.95;
- if (!isFinite(scale) || scale <= 0) { scale = 1; }
- const posX = (vw - contentW * scale) / 2 - minX * scale;
- const posY = (vh - contentH * scale) / 2 - minY * scale;
- pixiApp.stage.setTransform(posX, posY, scale, scale, 0, 0, 0, 0, 0);
+ mapContentSize = { width: contentW, height: contentH };
+ this.drawTracks(map);
+ this.applyMapTransform(true);
}
this.map = map;
+ },
+ isTrackCell(cell) {
+ if (!cell) { return false; }
+ const type = cell.type ? String(cell.type).toLowerCase() : '';
+ if (type === 'track' || type === 'crn' || type === 'dualcrn' || type === 'rgv') { return true; }
+ if (cell.trackSiteNo != null) { return true; }
+ const v = parseInt(cell.value, 10);
+ if (v === 3 || v === 9) { return true; }
+ if (cell.value != null) {
+ try {
+ const obj = (typeof cell.value === 'string') ? JSON.parse(cell.value) : cell.value;
+ if (obj && (obj.trackSiteNo != null || (obj.deviceNo != null && (type === 'crn' || type === 'dualcrn' || type === 'rgv')))) {
+ return true;
+ }
+ } catch (e) {}
+ }
+ return false;
+ },
+ drawTracks(map) {
+ if (!tracksGraphics || !Array.isArray(map)) { return; }
+ tracksGraphics.clear();
+ const railColor = 0x6c727a;
+ const railWidth = Math.max(1, Math.round(Math.min(width, height) * 0.08));
+ tracksGraphics.lineStyle(railWidth, railColor, 1);
+
+ for (let r = 0; r < map.length; r++) {
+ const row = map[r];
+ if (!Array.isArray(row)) { continue; }
+ for (let c = 0; c < row.length; c++) {
+ const cell = row[c];
+ if (!this.isTrackCell(cell)) { continue; }
+ const cx = c * width + width / 2;
+ const cy = r * height + height / 2;
+ const up = (r - 1 >= 0 && Array.isArray(map[r - 1])) ? map[r - 1][c] : null;
+ const right = (c + 1 < row.length) ? row[c + 1] : null;
+ const down = (r + 1 < map.length && Array.isArray(map[r + 1])) ? map[r + 1][c] : null;
+ const left = (c - 1 >= 0) ? row[c - 1] : null;
+ const hasN = this.isTrackCell(up);
+ const hasE = this.isTrackCell(right);
+ const hasS = this.isTrackCell(down);
+ const hasW = this.isTrackCell(left);
+ const seg = Math.min(width, height) * 0.5;
+ let drew = false;
+ if (hasN) { tracksGraphics.moveTo(cx, cy); tracksGraphics.lineTo(cx, cy - seg); drew = true; }
+ if (hasE) { tracksGraphics.moveTo(cx, cy); tracksGraphics.lineTo(cx + seg, cy); drew = true; }
+ if (hasS) { tracksGraphics.moveTo(cx, cy); tracksGraphics.lineTo(cx, cy + seg); drew = true; }
+ if (hasW) { tracksGraphics.moveTo(cx, cy); tracksGraphics.lineTo(cx - seg, cy); drew = true; }
+ if (!drew) {
+ tracksGraphics.moveTo(cx - seg * 0.4, cy);
+ tracksGraphics.lineTo(cx + seg * 0.4, cy);
+ }
+ }
+ }
+ },
+ parseRotation(value) {
+ const num = parseInt(value, 10);
+ if (!isFinite(num)) { return 0; }
+ const rot = ((num % 360) + 360) % 360;
+ return (rot === 90 || rot === 180 || rot === 270) ? rot : 0;
+ },
+ parseMirror(value) {
+ if (value === true || value === false) { return value; }
+ if (value == null) { return false; }
+ const str = String(value).toLowerCase();
+ return str === '1' || str === 'true' || str === 'y';
+ },
+ loadMapTransformConfig() {
+ if (!window.$ || typeof baseUrl === 'undefined') { return; }
+ $.ajax({
+ url: baseUrl + "/config/listAll/auth",
+ headers: { 'token': localStorage.getItem('token') },
+ dataType: 'json',
+ method: 'GET',
+ success: (res) => {
+ if (!res || res.code !== 200 || !Array.isArray(res.data)) {
+ if (res && res.code === 403) { parent.location.href = baseUrl + "/login"; }
+ return;
+ }
+ const byCode = {};
+ res.data.forEach((item) => {
+ if (item && item.code) { byCode[item.code] = item; }
+ });
+ const rotateCfg = byCode[this.mapConfigCodes.rotate];
+ const mirrorCfg = byCode[this.mapConfigCodes.mirror];
+ if (rotateCfg && rotateCfg.value != null) {
+ this.mapRotation = this.parseRotation(rotateCfg.value);
+ }
+ if (mirrorCfg && mirrorCfg.value != null) {
+ this.mapMirrorX = this.parseMirror(mirrorCfg.value);
+ }
+ if (mapContentSize && mapContentSize.width > 0 && mapContentSize.height > 0) {
+ this.applyMapTransform(true);
+ }
+ }
+ });
+ },
+ getViewportSize() {
+ if (!pixiApp || !pixiApp.renderer) { return { width: 0, height: 0 }; }
+ const screen = pixiApp.renderer.screen;
+ if (screen && screen.width > 0 && screen.height > 0) {
+ return { width: screen.width, height: screen.height };
+ }
+ const rect = pixiApp.view ? pixiApp.view.getBoundingClientRect() : null;
+ return { width: rect ? rect.width : 0, height: rect ? rect.height : 0 };
+ },
+ getTransformedContentSize() {
+ const size = mapContentSize || { width: 0, height: 0 };
+ const w = size.width || 0;
+ const h = size.height || 0;
+ const rot = ((this.mapRotation % 360) + 360) % 360;
+ const swap = rot === 90 || rot === 270;
+ return { width: swap ? h : w, height: swap ? w : h };
+ },
+ fitStageToContent() {
+ if (!pixiApp || !mapContentSize) { return; }
+ const size = this.getTransformedContentSize();
+ const contentW = size.width || 0;
+ const contentH = size.height || 0;
+ if (contentW <= 0 || contentH <= 0) { return; }
+ const viewport = this.getViewportSize();
+ const vw = viewport.width;
+ const vh = viewport.height;
+ let scale = Math.min(vw / contentW, vh / contentH) * 0.95;
+ if (!isFinite(scale) || scale <= 0) { scale = 1; }
+ const baseW = mapContentSize.width || contentW;
+ const baseH = mapContentSize.height || contentH;
+ const mirrorX = this.mapMirrorX ? -1 : 1;
+ const scaleX = scale * mirrorX;
+ const scaleY = scale;
+ const posX = (vw / 2) - (baseW / 2) * scaleX;
+ const posY = (vh / 2) - (baseH / 2) * scaleY;
+ pixiApp.stage.setTransform(posX, posY, scaleX, scaleY, 0, 0, 0, 0, 0);
+ },
+ applyMapTransform(fitToView) {
+ if (!mapRoot || !mapContentSize) { return; }
+ const contentW = mapContentSize.width || 0;
+ const contentH = mapContentSize.height || 0;
+ if (contentW <= 0 || contentH <= 0) { return; }
+ mapRoot.pivot.set(contentW / 2, contentH / 2);
+ mapRoot.position.set(contentW / 2, contentH / 2);
+ mapRoot.rotation = (this.mapRotation % 360) * Math.PI / 180;
+ mapRoot.scale.set(1, 1);
+ if (fitToView) { this.fitStageToContent(); }
},
rightEvent(x, y, e) {
this.drawerLocNo = true
@@ -520,12 +684,16 @@
sprite = new PIXI.Sprite(graphics0);
}
sprite.position.set(x, y);
- sprite.interactive = true; // 蹇呴』瑕佽缃墠鑳芥帴鏀朵簨浠�
- sprite.buttonMode = true; // 璁╁厜鏍囧湪hover鏃跺彉涓烘墜鍨嬫寚閽�
-
- sprite.on('pointerdown', (e) => {
- pointerDownEvent(e)
- })
+ const type = item && item.type ? String(item.type).toLowerCase() : '';
+ const numVal = parseInt(value, 10);
+ const isTrackCell = numVal === 3 || numVal === 9 || type === 'track' || type === 'crn' || type === 'dualcrn' || type === 'rgv';
+ if (!isTrackCell) {
+ sprite.interactive = true; // 蹇呴』瑕佽缃墠鑳芥帴鏀朵簨浠�
+ sprite.buttonMode = true; // 璁╁厜鏍囧湪hover鏃跺彉涓烘墜鍨嬫寚閽�
+ sprite.on('pointerdown', (e) => {
+ pointerDownEvent(e)
+ })
+ }
return sprite;
}
@@ -542,4 +710,4 @@
</script>
</body>
-</html>
\ No newline at end of file
+</html>
diff --git a/src/main/webapp/views/login.html b/src/main/webapp/views/login.html
index 96fe62b..d82ce9a 100644
--- a/src/main/webapp/views/login.html
+++ b/src/main/webapp/views/login.html
@@ -184,7 +184,6 @@
$('#btn-server-info').click(function() {
$.ajax({
url: baseUrl + "/license/getServerInfos",
- headers: {'token': localStorage.getItem('token')},
method: 'GET',
success: function (res) {
var pretty = '';
@@ -254,7 +253,6 @@
layer.close(index);
$.ajax({
url: baseUrl + "/license/activate",
- headers: {'token': localStorage.getItem('token')},
method: 'POST',
success: function (res) {
if (res.code === 200){
@@ -275,7 +273,6 @@
$('#btn-project-name').click(function() {
$.ajax({
url: baseUrl + "/license/getProjectName",
- headers: {'token': localStorage.getItem('token')},
method: 'GET',
success: function (res) {
if (res.code === 200){
diff --git a/src/main/webapp/views/watch/console.html b/src/main/webapp/views/watch/console.html
index 12f2c63..3dbcc3c 100644
--- a/src/main/webapp/views/watch/console.html
+++ b/src/main/webapp/views/watch/console.html
@@ -1,15 +1,23 @@
<!DOCTYPE html>
<html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>WCS鎺у埗涓績</title>
- <link rel="stylesheet" href="../../static/css/animate.min.css">
- <link rel="stylesheet" href="../../static/vue/element/element.css">
- <link rel="stylesheet" href="../../static/css/watch/console_vue.css">
- <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
- <script type="text/javascript" src="../../static/layui/layui.js"></script>
- <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
- <script type="text/javascript" src="../../static/js/common.js"></script>
+ <head>
+ <meta charset="UTF-8">
+ <title>WCS鎺у埗涓績</title>
+ <link rel="stylesheet" href="../../static/css/animate.min.css">
+ <link rel="stylesheet" href="../../static/vue/element/element.css">
+ <link rel="stylesheet" href="../../static/css/watch/console_vue.css">
+ <style>
+ html, body, #app {
+ width: 100%;
+ height: 100%;
+ margin: 0;
+ overflow: hidden;
+ }
+ </style>
+ <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script>
+ <script type="text/javascript" src="../../static/layui/layui.js"></script>
+ <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script>
+ <script type="text/javascript" src="../../static/js/common.js"></script>
<script type="text/javascript" src="../../static/vue/js/vue.min.js"></script>
<script type="text/javascript" src="../../static/vue/element/element.js"></script>
<script src="../../static/js/gsap.min.js"></script>
--
Gitblit v1.9.1