diff --git a/.idea/workspace.xml b/.idea/workspace.xml
index 6cc1b2c..8c8d42a 100644
--- a/.idea/workspace.xml
+++ b/.idea/workspace.xml
@@ -5,33 +5,42 @@
-
-
-
+
+
+
+
+
-
-
-
+
+
-
-
+
-
+
-
-
+
-
-
-
+
+
+
+
+
+
+
+
+
+
-
+
-
+
+
+
+
@@ -81,6 +90,7 @@
"Application.XmlRpcHttpDirectCall.executor": "Run",
"Application.test111.executor": "Run",
"Maven.commoms [clean].executor": "Run",
+ "Maven.commoms [install].executor": "Run",
"Maven.commoms [package].executor": "Run",
"Maven.core [clean].executor": "Run",
"Maven.core [install].executor": "Run",
@@ -97,7 +107,10 @@
"Maven.web-server [clean].executor": "Run",
"Maven.web-server [compile].executor": "Run",
"Maven.web-server [dependency:resolve,-U].executor": "Run",
+ "Maven.web-server [install].executor": "Run",
"Maven.web-server [package].executor": "Run",
+ "Maven.web-server [validate].executor": "Run",
+ "Maven.web-server [verify].executor": "Run",
"RequestMappingsPanelOrder0": "0",
"RequestMappingsPanelOrder1": "1",
"RequestMappingsPanelWidth0": "75",
@@ -107,7 +120,7 @@
"Spring Boot.WebServerApplication.executor": "Debug",
"git-widget-placeholder": "master",
"kotlin-language-version-configured": "true",
- "last_opened_file_path": "D:/andy/ideaWorker/andy/blc/download/应用端/backend",
+ "last_opened_file_path": "D:/andy/ideaWorker/station-control/web-server/src/main/resources/mapper",
"node.js.detected.package.eslint": "true",
"node.js.detected.package.tslint": "true",
"node.js.selected.package.eslint": "(autodetect)",
@@ -125,21 +138,21 @@
+
+
-
-
-
-
-
-
-
+
+
+
+
+
@@ -391,7 +404,14 @@
-
+
+
+
+
+
+
+
+
@@ -399,6 +419,15 @@
+
+
+
+ file://$PROJECT_DIR$/web-server/src/main/java/com/evotech/hd/webserver/controller/TestController.java
+ 1480
+
+
+
+
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/AccessStrategyDTO.java b/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/AccessStrategyDTO.java
index 5b9c46e..9d8cfda 100644
--- a/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/AccessStrategyDTO.java
+++ b/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/AccessStrategyDTO.java
@@ -46,7 +46,8 @@ public class AccessStrategyDTO extends BaseDTO {
@ApiModelProperty("生效的Rgv编号")
String effectiveRgvNo;
-
+ @ApiModelProperty("电池预取, true是, false 否")
+ Boolean batteryPrefetching;
@ApiModelProperty(value = "数据是否有效: valid有效 invalid 无效", hidden = true)
String valid;
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/BatteryCompartmentDTO.java b/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/BatteryCompartmentDTO.java
index 5904ae9..81451ce 100644
--- a/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/BatteryCompartmentDTO.java
+++ b/commoms/core/src/main/java/com/evotech/hd/core/dtos/business/BatteryCompartmentDTO.java
@@ -1,6 +1,8 @@
package com.evotech.hd.core.dtos.business;
import com.evotech.hd.core.dtos.BaseDTO;
+import com.evotech.hd.query.Query;
+import com.evotech.hd.query.QueryType;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
@@ -26,9 +28,11 @@ public class BatteryCompartmentDTO extends BaseDTO {
String batteryCompartmentNo;
@ApiModelProperty("电池仓状态:1-正常,2-检修, 3-坏")
+ @Query(javaField = "status", tableColumn = "a.status", type = QueryType.EQ)
Integer status;
@ApiModelProperty("运行状态:1正常, 2-禁用")
+ @Query(javaField = "state", tableColumn = "a.state", type = QueryType.EQ)
Integer state;
@ApiModelProperty("排序")
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/MessageMqttDTO.java b/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/MessageMqttDTO.java
new file mode 100644
index 0000000..c35a0b1
--- /dev/null
+++ b/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/MessageMqttDTO.java
@@ -0,0 +1,59 @@
+package com.evotech.hd.core.dtos.system;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.evotech.hd.core.dtos.BaseDTO;
+import com.evotech.hd.query.Query;
+import com.evotech.hd.query.QueryType;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.util.Date;
+
+/**
+ * mqtt消息
+ *
+ * @ClassName:Log
+ * @date: 2025年08月18日 10:06
+ * @author: andy.shi
+ * @contact: 17330188597
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Data
+@ApiModel("mqtt消息")
+public class MessageMqttDTO extends BaseDTO {
+
+
+ @ApiModelProperty( "换电站")
+ private String stationCode;
+
+ @ApiModelProperty("传送方向")
+ private String direction;
+
+ @ApiModelProperty("消息ID")
+ private String messageId;
+
+ @ApiModelProperty("qos")
+ private Integer qos;
+
+ @ApiModelProperty( "消息类型: 状态信息类、事件记录类、请求与响应类")
+ private String type;
+
+ @ApiModelProperty("方法 stationInfo")
+ private String messageFunction;
+
+ @ApiModelProperty("消息的topic")
+ private String topic;
+
+ @ApiModelProperty("内容,解密后的")
+ private String content;
+
+ @ApiModelProperty("创建时间")
+ @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+ private Date ctime;
+
+
+}
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/ParamsDTO.java b/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/ParamsDTO.java
index 9d0327d..5772db8 100644
--- a/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/ParamsDTO.java
+++ b/commoms/core/src/main/java/com/evotech/hd/core/dtos/system/ParamsDTO.java
@@ -30,6 +30,8 @@ public class ParamsDTO extends BaseDTO {
@ApiModelProperty("参数值")
@Query(javaField = "paramValue", tableColumn = "a.param_value", type = QueryType.LIKE)
String paramValue;
+ @ApiModelProperty("是否影响换电, true 影响, false 不影响")
+ Boolean effectBatterySwapping;
@ApiModelProperty("预期结果, 不满足预期返回错误信息")
String expectedResults;
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/entity/system/AccessStrategy.java b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/AccessStrategy.java
index a249efb..03b935e 100644
--- a/commoms/core/src/main/java/com/evotech/hd/core/entity/system/AccessStrategy.java
+++ b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/AccessStrategy.java
@@ -50,6 +50,10 @@ public class AccessStrategy extends BaseEntity {
*生效的RGV编号
*/
String effectiveRgvNo;
+ /***
+ *电池预取
+ */
+ Boolean batteryPrefetching;
/***
* 数据是否有效: valid有效 invalid 无效
*/
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/entity/system/MessageMqtt.java b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/MessageMqtt.java
new file mode 100644
index 0000000..a6937b4
--- /dev/null
+++ b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/MessageMqtt.java
@@ -0,0 +1,43 @@
+package com.evotech.hd.core.entity.system;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.evotech.hd.core.entity.BaseEntity;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * @author zrb
+ * @since 2024-11-06
+ */
+@Getter
+@Setter
+@TableName("sc_sys_message_mqtt")
+public class MessageMqtt extends BaseEntity {
+
+ private String stationCode;
+
+ private String direction;
+
+ private String messageId;
+
+ private Integer qos;
+
+ private String type;
+
+ private String messageFunction;
+
+ private String topic;
+
+ private String content;
+
+
+ public MessageMqtt() {
+ }
+
+ public MessageMqtt(String stationCode, String direction, String type, String messageFunction) {
+ this.stationCode = stationCode;
+ this.direction = direction;
+ this.type = type;
+ this.messageFunction = messageFunction;
+ }
+}
diff --git a/commoms/core/src/main/java/com/evotech/hd/core/entity/system/Params.java b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/Params.java
index fdec9ec..293aac4 100644
--- a/commoms/core/src/main/java/com/evotech/hd/core/entity/system/Params.java
+++ b/commoms/core/src/main/java/com/evotech/hd/core/entity/system/Params.java
@@ -32,6 +32,8 @@ public class Params extends BaseEntity {
String expectedResults;
+ Boolean effectBatterySwapping;
+
Boolean verifyResult;
String errMessage;
diff --git a/commoms/core/src/main/java/com/evotech/hd/utils/Global.java b/commoms/core/src/main/java/com/evotech/hd/utils/Global.java
new file mode 100644
index 0000000..278144f
--- /dev/null
+++ b/commoms/core/src/main/java/com/evotech/hd/utils/Global.java
@@ -0,0 +1,59 @@
+package com.evotech.hd.utils;
+
+import lombok.Data;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 全局属性配置
+ * @author andy.shi
+ * @ClassName:Global
+ * @date: 2026年01月10日 10:16
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Configuration
+@ConfigurationProperties(prefix = "ythd", ignoreInvalidFields = true)
+@Data
+public class Global{
+ /***
+ * 云平台私钥
+ */
+ @Value("${ythd.cloud-private-key}")
+ public String cloudPrivateKey;
+ /***
+ * 云平台公钥
+ */
+ @Value("${ythd.cloud-public-key}")
+ public String cloudPublicKey;
+
+ @Value("${ythd.static-public-key}")
+ public String staticPublicKey;
+ //单例模式全局属性
+ private static volatile Global global;
+
+
+ public static Global newInstance() {
+ if(global == null){
+ synchronized (Global.class){
+ if(global == null){
+ global = SpringUtils.getBean(Global.class);
+ }
+ }
+ }
+ return global;
+ }
+
+
+ public String getCloudPrivateKey() {
+ return cloudPrivateKey;
+ }
+
+ public String getCloudPublicKey() {
+ return cloudPublicKey;
+ }
+
+ public String getStaticPublicKey() {
+ return staticPublicKey;
+ }
+}
diff --git a/commoms/core/src/main/java/com/evotech/hd/utils/SpringUtils.java b/commoms/core/src/main/java/com/evotech/hd/utils/SpringUtils.java
new file mode 100644
index 0000000..fcd2356
--- /dev/null
+++ b/commoms/core/src/main/java/com/evotech/hd/utils/SpringUtils.java
@@ -0,0 +1,55 @@
+package com.evotech.hd.utils;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+
+/**
+ * SpringUtils
+ *
+ * @author andy.shi
+ * @ClassName:SpringUtils
+ * @date: 2026年01月10日 11:11
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Component
+public class SpringUtils implements ApplicationContextAware {
+
+
+ private static ApplicationContext applicationContext;
+
+ /**
+ * Spring容器启动时,会自动调用这个方法,注入上下文对象
+ */
+ @Override
+ public void setApplicationContext(ApplicationContext context) throws BeansException {
+ // 将Spring上下文赋值给静态变量
+ SpringUtils.applicationContext = context;
+ }
+
+ /**
+ * 静态方法:根据Bean类型获取实例
+ * @param clazz Bean的类型
+ * @return 对应的Bean实例
+ */
+ public static T getBean(Class clazz) {
+ // 校验上下文是否初始化完成
+ if (applicationContext == null) {
+ throw new RuntimeException("Spring上下文未初始化,无法获取Bean");
+ }
+ return applicationContext.getBean(clazz);
+ }
+
+ /**
+ * 静态方法:根据Bean名称获取实例(备用,优先用类型获取)
+ * @param beanName Bean的名称
+ * @return 对应的Bean实例
+ */
+ public static Object getBean(String beanName) {
+ if (applicationContext == null) {
+ throw new RuntimeException("Spring上下文未初始化,无法获取Bean");
+ }
+ return applicationContext.getBean(beanName);
+ }
+}
diff --git a/commoms/core/src/main/resources/application-core.yml b/commoms/core/src/main/resources/application-core.yml
new file mode 100644
index 0000000..e0f2b41
--- /dev/null
+++ b/commoms/core/src/main/resources/application-core.yml
@@ -0,0 +1,5 @@
+
+ythd:
+ cloud-private-key: MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALEbx7j2XmAo3NiviJIk8/Mo1RF4yT/MYmZdZRnB9iSh4koIiu/KKCGSwvViFGfmP/q8TNLWsvpTVo3MxWBFJkWaALuo/iPu5RJ+tU1l0YXA35zZNxMuiDbmnI7wODRePUY1g5fa1ZNy5oDUQumfrXhDCoFC2AMUBn9KiMr+QQ97AgMBAAECgYAk/lF8X/Gckkx28ktLg251Nu0yZhFbQxy2lwF8HNiGFE5I+nnS1l4FjTstuBvdC+oHPHerfm8J/IhSvBfqIOd6PulJyuh5s31cdc+2SDWUzh8sBm48YHlDfjltZG2ijgM7h/+uvw1gHwXH8JQGF7ZjWguD3TJfqZ/jPFsuxoLKOQJBAOsp+f7kS5VXg6ziKzCMlWOAEfrsAO5ZhLJNMtoirbMQZYUfYxUc3KFWQMT9i9O2M752NXoeUed8a1DjmfyxaX8CQQDAzPs5EPNfpfuGsvJ79lGsH8mZcw7VdjDzmwNVVLLnSOaJxQIPTusjEJ2YmBs+ifCF30VIDpkRd/DGaj4yNgAFAkEAorh1B+6objoUHviQshNU+3iO+HV9X3AJ5eaNHWuJjbH2zVqekOlbsTehsa1Pp7sXqt7YuhtoySjKiTo0PynzuQJBAJsvovsBANQ5VubJ/NH4py6je3LPIN6Cvs4mNJ2nikUN8bps38aQoEVeJ2ve6vcAsqAe4bYpQd3ErAIZHCzwOD0CQF8hDwEGx1S4nJQpB9rmSQhoNzaEJuJKXgpAxNCQ9g4kLRZE+hpZk1kPw+VjGalyyZkY5ilXkWnqsvrprn+wW7Y=
+ cloud-public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCxG8e49l5gKNzYr4iSJPPzKNUReMk/zGJmXWUZwfYkoeJKCIrvyighksL1YhRn5j/6vEzS1rL6U1aNzMVgRSZFmgC7qP4j7uUSfrVNZdGFwN+c2TcTLog25pyO8Dg0Xj1GNYOX2tWTcuaA1ELpn614QwqBQtgDFAZ/SojK/kEPewIDAQAB
+ static-public-key: MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC32MZ8u1bK66Uj+Uh3eTfDLcGy4TosSLfksYvJBavX6fckS6vdV8VeYj9gQvTrB6b3VKIdsqf/uP4AjgiKlP34GVMfDr0bEPEccurEhs23QWSHGrVSJG5HPG0B1PBbRMMUwUkmQJxo65Ml6SSPyS/4ebdZ0qeY2/cWaK8laYj7sQIDAQAB
\ No newline at end of file
diff --git a/commoms/mongodb/src/main/resources/application-mongoDev.yml b/commoms/mongodb/src/main/resources/application-mongoDev.yml
index e1e486e..33ae722 100644
--- a/commoms/mongodb/src/main/resources/application-mongoDev.yml
+++ b/commoms/mongodb/src/main/resources/application-mongoDev.yml
@@ -1,6 +1,6 @@
yt:
base_properties:
- host: 192.168.16.128
+ host: 192.168.5.112
port: 27017
#用于账号密码验证的库
authentication-database: admin
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/cnstant/ParamSysConstants.java b/web-server/src/main/java/com/evotech/hd/webserver/cnstant/ParamSysConstants.java
index f13858b..3b2fba1 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/cnstant/ParamSysConstants.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/cnstant/ParamSysConstants.java
@@ -11,10 +11,6 @@ package com.evotech.hd.webserver.cnstant;
public class ParamSysConstants {
- /***
- * 检查电池仓是否存在电池
- */
- public final static String EXISTS_BATTERY = "BSL_BatExist";
/***
* 设置最大功率
*/
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/config/handler/GlobalExceptionHandler.java b/web-server/src/main/java/com/evotech/hd/webserver/config/handler/GlobalExceptionHandler.java
index 5585405..bfd4048 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/config/handler/GlobalExceptionHandler.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/config/handler/GlobalExceptionHandler.java
@@ -13,8 +13,6 @@ import javax.servlet.ServletException;
/**
* 全局异常处理器,将 Exception 翻译成 CommonResult + 对应的异常编号
- *
- * @author 芋道源码
*/
@RestControllerAdvice(basePackages = "com.evotech.hd")
@AllArgsConstructor
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttConfig.java b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttConfig.java
new file mode 100644
index 0000000..4e5b48c
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttConfig.java
@@ -0,0 +1,127 @@
+package com.evotech.hd.webserver.config.mqtt;
+
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.paho.client.mqttv3.*;
+import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.springframework.boot.CommandLineRunner;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PreDestroy;
+import javax.annotation.Resource;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * MqttClientManager
+ *
+ * @author andy.shi
+ * @ClassName:MqttClientManager
+ * @date: 2025年12月23日 15:59
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Configuration
+@Component
+@Slf4j
+public class MqttConfig implements CommandLineRunner {
+
+ @Resource
+ MqttProperties mqttProperties;
+
+ static ConcurrentHashMap mqttClientMap = new ConcurrentHashMap<>();
+ // 已重试次数
+ private final AtomicInteger retryCount = new AtomicInteger(0);
+ // 重连执行器
+ private final ScheduledExecutorService reconnectExecutor = Executors.newSingleThreadScheduledExecutor();
+
+ @Override
+ public void run(String... args) throws Exception {
+ new Thread(this::connectMqtt, "mqtt-connect-thread").start();
+ }
+
+ public MqttConnectOptions mqttConnectOptions() {
+ MqttConnectOptions options = new MqttConnectOptions();
+ // 设置服务器地址(支持多个,用数组)
+ options.setServerURIs(new String[]{mqttProperties.getBroker()});
+ // 配置认证信息(如果有)
+ if (StringUtils.isNotEmpty(mqttProperties.getUsername())) {
+ options.setUserName(mqttProperties.getUsername());
+ }
+ if (StringUtils.isNotEmpty(mqttProperties.getPassword())) {
+ options.setPassword(mqttProperties.getPassword().toCharArray());
+ }
+ // 其他连接参数
+ options.setKeepAliveInterval(mqttProperties.getKeepAlive()); // 心跳间隔
+ options.setConnectionTimeout(10); // 连接超时时间(秒)
+ options.setAutomaticReconnect(true); // 自动重连
+ options.setCleanSession(true); // 断开后清除会话
+ return options;
+ }
+
+ /**
+ * 建立 MQTT 连接
+ */
+ private void connectMqtt() {
+ try {
+ // 1. 创建 MQTT 连接选项
+ MqttConnectOptions connOpts = mqttConnectOptions();
+ // 2. 创建 MQTT 客户端
+ MqttClient client = new MqttClient(mqttProperties.getBroker(), mqttProperties.getClientId(), new MemoryPersistence());
+ // 3. 设置回调(处理消息、连接断开等事件)
+ client.setCallback(new MqttMessageCallback());
+ // 4. 建立连接
+ if (!client.isConnected()) {
+ client.connect(connOpts);
+ mqttClientMap.put("cloudClient", client);
+ // 重置重试次数
+ retryCount.set(0);
+ }
+
+ } catch (MqttException e) {
+ log.error("MQTT 连接失败,错误码:{},原因:{}", e.getReasonCode(), e.getMessage(), e);
+ // 触发自定义重连逻辑
+ startReconnect();
+ }
+ }
+
+
+ /**
+ * 启动自动重连
+ */
+ private void startReconnect() {
+ // 检查是否超过最大重试次数(0 表示无限重试)
+ if (mqttProperties.getMaxRetry() > 0 && retryCount.get() >= mqttProperties.getMaxRetry()) {
+ log.error("MQTT 重连次数已达上限({}次),停止重连", mqttProperties.getMaxRetry());
+ reconnectExecutor.shutdown();
+ return;
+ }
+
+ int currentRetry = retryCount.incrementAndGet();
+ log.info("将在 {} 秒后进行第 {} 次 MQTT 重连", mqttProperties.getRetryInterval(), currentRetry);
+
+ // 延迟执行重连(避免频繁重试)
+ reconnectExecutor.schedule(() -> {
+ if (mqttClientMap.get("cloudClient") == null || !mqttClientMap.get("cloudClient").isConnected()) {
+ connectMqtt();
+ }
+ }, mqttProperties.getRetryInterval(), TimeUnit.SECONDS);
+ }
+
+ @PreDestroy
+ public void PreDestroyComplete() {
+ log.info("===>>>程序要关闭了...");
+ MqttClient cloudClient = mqttClientMap.get("cloudClient");
+ try {
+ cloudClient.disconnect();
+ cloudClient.close();
+ log.info("=====>>>关闭了MQTT");
+ } catch (MqttException e) {
+ e.printStackTrace();
+ }
+
+ }
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttMessageCallback.java b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttMessageCallback.java
index 5b854b1..57f7b6c 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttMessageCallback.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttMessageCallback.java
@@ -10,13 +10,22 @@ package com.evotech.hd.webserver.config.mqtt;
*/
import cn.hutool.extra.spring.SpringUtil;
+import com.alibaba.fastjson2.JSONObject;
import com.evotech.hd.core.dtos.system.ParamsDTO;
+import com.evotech.hd.utils.Collections;
+import com.evotech.hd.utils.Global;
+import com.evotech.hd.webserver.job.JobConstant;
+import com.evotech.hd.webserver.job.service.QuartzJobService;
import com.evotech.hd.webserver.mqtt.MessageTopic;
import com.evotech.hd.webserver.mqtt.MqttMessageHandleService;
+import com.evotech.hd.webserver.mqtt.MqttPublishUtils;
+import com.evotech.hd.webserver.mqtt.enums.MqttMessageTypeEnum;
import com.evotech.hd.webserver.service.ParamsService;
import com.evotech.hd.webserver.utils.ParamUtils;
+import com.evotech.hd.webserver.websocket.controller.WebSocketUtils;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
+import org.quartz.SchedulerException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
@@ -32,9 +41,11 @@ public class MqttMessageCallback implements MqttCallbackExtended, ApplicationCo
private ApplicationContext applicationContext;
+ private MqttMessageHandleService mqttMessageHandleService;
+
private static String stationCode;
- static String[] mqttMessageTypeArr = {"event","request", "state","keepalive"};
+ static String[] mqttMessageTypeArr = {MqttMessageTypeEnum.EVENT.getType(),MqttMessageTypeEnum.REQUEST.getType(), MqttMessageTypeEnum.STATE.getType(), MqttMessageTypeEnum.ENCRYRESP.getType()};
/**
* 建立连接后
@@ -60,6 +71,15 @@ public class MqttMessageCallback implements MqttCallbackExtended, ApplicationCo
log.error("\r\n=====>>>MQTT订阅主题 {} 失败。。。", topic);
}
}
+ //订阅完成之后, 获取秘钥信息
+ MqttPublishUtils.sendEncryptKeyReq();
+ //开启与服务端的心跳检查, 注意, 这里不是客户端和mq的心跳检查, 所以需要手动开启
+// try {
+// SpringUtil.getBean(QuartzJobService.class).resumeJob(JobConstant.KEEPALIVE_JOB, JobConstant.GroupEnum.BASE_GROUP.getType());
+// } catch (SchedulerException e) {
+// throw new RuntimeException(e);
+// }
+
}
/**
@@ -70,6 +90,14 @@ public class MqttMessageCallback implements MqttCallbackExtended, ApplicationCo
cause.printStackTrace();
logger.error("MQTT连接已断开,原因:{}", cause.getMessage());
// 自动重连由MqttConnectOptions的automaticReconnect控制
+ //页面推送广播, 云平台连接丢失
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","alarm","data",JSONObject.toJSONString(Collections.asMap("MQTT服务", "连接丢失")))));
+ //如果链接丢失, 关闭与服务端的心跳检查, 注意, 这里不是客户端和mq的心跳检查, 所以需要手动关闭
+// try {
+// SpringUtil.getBean(QuartzJobService.class).pauseJob(JobConstant.KEEPALIVE_JOB, JobConstant.GroupEnum.BASE_GROUP.getType());
+// } catch (SchedulerException e) {
+// throw new RuntimeException(e);
+// }
}
/**
@@ -95,13 +123,6 @@ public class MqttMessageCallback implements MqttCallbackExtended, ApplicationCo
*/
@Override
public void deliveryComplete(IMqttDeliveryToken token) {
- // 消息成功发布后的回调(可选处理)
-// try {
-// logger.info("消息已成功发布到主题:{}", token.getMessageId());
-// } catch (Exception e) {
-// logger.error("消息发布确认失败", e);
-// }
-
try {
// 核心:安全获取主题(优先用自定义 token 的主题,兼容原生 token)
String publishTopic = "未知主题";
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttPublishMessage.java b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttPublishMessage.java
index 27f9f8d..354227e 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttPublishMessage.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/config/mqtt/MqttPublishMessage.java
@@ -1,17 +1,28 @@
package com.evotech.hd.webserver.config.mqtt;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
+import com.alibaba.fastjson2.JSON;
+import com.evotech.hd.core.dtos.Result;
+import com.evotech.hd.utils.Collections;
+import com.evotech.hd.utils.Global;
import com.evotech.hd.webserver.mqtt.MessageTopic;
import com.evotech.hd.webserver.mqtt.MessageUtilService;
import com.evotech.hd.webserver.mqtt.MqttMessageHeader;
import com.evotech.hd.webserver.mqtt.MyMqttMessage;
+import com.evotech.hd.webserver.mqtt.enums.MqttMessageTypeEnum;
+import com.evotech.hd.webserver.service.MessageMqttService;
import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.*;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
+import java.util.Date;
@Component
@Slf4j
@@ -19,8 +30,10 @@ public class MqttPublishMessage {
@Resource
MessageUtilService messageUtilService;
+ @Resource
+ MessageMqttService messageMqttService;
- public MqttMessage publish(String message, String topic) {
+ private MqttMessage publish(String message, String topic) {
MqttClient cloudClient = MqttConfig.mqttClientMap.get("cloudClient");
MqttMessage mqttMessage = new MqttMessage();
/**
@@ -50,6 +63,53 @@ public class MqttPublishMessage {
return mqttMessage;
}
+ /**
+ * 发送 心跳
+ */
+ public void publishKeepaliveMessage() {
+ log.info("MQTT->>>>>>>>>>>>>请求发送心跳;");
+ MessageTopic topic = new MessageTopic();
+ topic.setMessageType(MqttMessageTypeEnum.KEEPALIVE.getType());
+ // 3. 发送MQTT消息
+ try {
+ MqttMessage mqttMessage = publish(DateUtil.formatDateTime(new Date()), topic.toString());
+ try {
+ messageMqttService.update(null, topic, mqttMessage.getId()+"", mqttMessage.getQos(), JSONUtil.parseObj(mqttMessage));
+ } catch (Exception e) {
+ log.error("MQTT->>>>>>>>>>>>>记录mqtt消息出现了错误{},topic:{}; message:{}",e.getMessage(),JSONUtil.toJsonStr(topic), JSONUtil.toJsonStr(mqttMessage));
+ throw new RuntimeException("记录mqtt消息出现了错误"+e.getMessage());
+ }
+ } catch (Exception e) {
+ log.error("MQTT->>>>>>>>>>>>>发送站端mqtt消息出现异常{},topic:{};",e.getMessage(),JSONUtil.toJsonStr(topic));
+ }
+ }
+
+ /**
+ * 发送 AES 加密消息
+ * @param topic
+ */
+ public void publishRSAMessage(MessageTopic topic) {
+ log.info("MQTT->>>>>>>>>>>>>请求发送mqtt消息: topic:{};", JSONUtil.toJsonStr(topic));
+
+ RSA rsa = SecureUtil.rsa(null, Global.newInstance().getStaticPublicKey());
+ Result addResult = messageMqttService.addResultId(topic.getStationCode());
+ Integer messageId = addResult.getData();
+ //数据加密
+ String encrypt = rsa.encryptBase64(JSON.toJSONString(Collections.asMap("messageId", messageId, "publicKey", Global.newInstance().getCloudPublicKey())), KeyType.PublicKey);
+ // 3. 发送MQTT消息
+ try {
+ MqttMessage mqttMessage = publish(encrypt, topic.toString());
+ try {
+ messageMqttService.update(messageId, topic, mqttMessage.getId()+"", mqttMessage.getQos(), JSONUtil.parseObj(mqttMessage));
+ } catch (Exception e) {
+ log.error("MQTT->>>>>>>>>>>>>记录mqtt消息出现了错误{},topic:{}; message:{}",e.getMessage(),JSONUtil.toJsonStr(topic), JSONUtil.toJsonStr(mqttMessage));
+ throw new RuntimeException("记录mqtt消息出现了错误"+e.getMessage());
+ }
+ } catch (Exception e) {
+ log.error("MQTT->>>>>>>>>>>>>发送站端mqtt消息出现异常{},topic:{};",e.getMessage(),JSONUtil.toJsonStr(topic));
+ }
+ }
+
/**
* 发送 AES 加密消息
* @param topic
@@ -70,8 +130,7 @@ public class MqttPublishMessage {
try {
MqttMessage mqttMessage = publish(encrypt, topic.toString());
try {
- //dataBody.set("header", JSONUtil.toJsonStr(header));
- // addMqttMessage(topic, mqttMessage.getId()+"", mqttMessage.getQos(), JSONUtil.parseObj(message));
+ messageMqttService.update(null, topic, mqttMessage.getId()+"", mqttMessage.getQos(), JSONUtil.parseObj(message));
} catch (Exception e) {
log.error("MQTT->>>>>>>>>>>>>记录mqtt消息出现了错误{},topic:{}; header:{}, data:{}; message:{}",e.getMessage(),JSONUtil.toJsonStr(topic),JSONUtil.toJsonStr(header),JSONUtil.toJsonStr(dataBody), JSONUtil.toJsonStr(mqttMessage));
throw new RuntimeException("记录mqtt消息出现了错误"+e.getMessage());
@@ -80,47 +139,4 @@ public class MqttPublishMessage {
log.error("MQTT->>>>>>>>>>>>>发送站端mqtt消息出现异常{},topic:{}; header:{}, data:{}",e.getMessage(),JSONUtil.toJsonStr(topic),JSONUtil.toJsonStr(header),JSONUtil.toJsonStr(dataBody));
}
}
-
-// public SymmetricCrypto getAes(String stationCode) {
-// JSONObject aesJo = getAESKey(stationCode);
-// String aesSecretKey = aesJo.getStr("encryptKey");
-// String aesIv = aesJo.getStr("encryptVector");
-// SymmetricCrypto aes = new AES(Mode.CBC, Padding.PKCS5Padding, Base64.getDecoder().decode(aesSecretKey), aesIv.getBytes());
-// return aes;
-// }
-
-// public JSONObject getAESKey(String stationCode) {
-// JSONObject jo = new JSONObject();
-// Object o1 = null;
-// try {
-// o1 = redisUtil.get(HDConstant.HD_STATION_SECRET_KEY_AES_PREFIX + stationCode + ":key");
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// Object o2 = null;
-// try {
-// o2 = redisUtil.get(HDConstant.HD_STATION_SECRET_KEY_AES_PREFIX + stationCode + ":iv");
-// } catch (Exception e) {
-// e.printStackTrace();
-// }
-// if (!ObjectUtil.isEmpty(o1) && !ObjectUtil.isEmpty(o2)) {
-//// jo.set("aesSecretKey", o1.toString());
-//// jo.set("aesIv", o2.toString());
-// jo.set("encryptKey", o1.toString());
-// jo.set("encryptVector", o2.toString());
-// return jo;
-// }
-// BatteryStationSecretKey bssk = batteryStationSecretKeyDao.selectOne(new QueryWrapper().eq("type", 2).eq("station_code", stationCode));
-// if (bssk == null) {
-// throw new RuntimeException("AES秘钥未获取到,请站端重新登陆!");
-//// return setAesKey(stationCode);
-// }
-// redisUtil.set(HDConstant.HD_STATION_SECRET_KEY_AES_PREFIX + stationCode + ":key", bssk.getPublicKey());
-// redisUtil.set(HDConstant.HD_STATION_SECRET_KEY_AES_PREFIX + stationCode + ":iv", bssk.getPrivateKey());
-//// jo.set("aesSecretKey", o1.toString());
-//// jo.set("aesIv", o2.toString());
-// jo.set("encryptKey", o1.toString());
-// jo.set("encryptVector", o2.toString());
-// return jo;
-// }
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/controller/OrderSwapController.java b/web-server/src/main/java/com/evotech/hd/webserver/controller/OrderSwapController.java
index a8e6dbb..7cc4181 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/controller/OrderSwapController.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/controller/OrderSwapController.java
@@ -76,9 +76,20 @@ public class OrderSwapController {
@ApiOperation("手动换电完成")
@PostMapping("/manualBatterySwappingCompleted")
@ApiLog(value = "手动换电完成", type=LogTypeEnum.OPERATION)
- public Result ManualBatterySwappingCompleted(@RequestBody OrderSwapDTO orderSwapDTO) throws Exception {
+ public Result manualBatterySwappingCompleted(@RequestBody OrderSwapDTO orderSwapDTO) throws Exception {
return orderSwapService.updateOrderSwapDTO(orderSwapDTO);
}
+ /**
+ * 手动换电完成
+ * @return
+ */
+ @ApiOperation("订单关闭")
+ @PostMapping("/close")
+ @ApiLog(value = "订单关闭", type=LogTypeEnum.OPERATION)
+ public Result close(@RequestBody OrderSwapDTO orderSwapDTO) throws Exception {
+ return orderSwapService.close(orderSwapDTO);
+ }
+
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/controller/TestController.java b/web-server/src/main/java/com/evotech/hd/webserver/controller/TestController.java
index 8a4c2c1..b454146 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/controller/TestController.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/controller/TestController.java
@@ -5,14 +5,11 @@ import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.evotech.hd.core.dtos.Result;
import com.evotech.hd.core.dtos.business.AccessStrategyDTO;
-import com.evotech.hd.core.entity.business.OrderCharging;
-import com.evotech.hd.core.enums.SwapBatteryStepEnum;
import com.evotech.hd.entity.BatData;
import com.evotech.hd.entity.ChargingData;
import com.evotech.hd.exception.InstructionException;
import com.evotech.hd.service.MongoDBService;
import com.evotech.hd.utils.Collections;
-import com.evotech.hd.utils.DateUtils;
import com.evotech.hd.webserver.job.service.ExecutionBatterySwapService;
import com.evotech.hd.webserver.logging.annotation.ApiLog;
import com.evotech.hd.webserver.logging.enums.LogTypeEnum;
@@ -27,19 +24,11 @@ import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
-import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
-import springfox.documentation.spring.web.scanners.ApiDescriptionLookup;
import javax.annotation.Resource;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
@@ -48,7 +37,6 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.stream.Collectors;
/**
* TestController
@@ -184,7 +172,7 @@ public class TestController {
}
@ApiOperation("开始")
- @PostMapping("/start/{category}")
+ @RequestMapping("/start/{category}")
@ApiLog(value = "开始", type = LogTypeEnum.OPERATION)
public Result start(@PathVariable("category") final String category,
@RequestParam("rgvNo") final String rgvNo,
@@ -710,11 +698,9 @@ public class TestController {
closeRunMap.put(rgv, new AtomicBoolean(false));
categoryRunMap.put(rgv,category);
-
+ AccessStrategyDTO accessStrategyDTO = AccessStrategyUtil.getValidAccessStrategyDTO();
CompletableFuture future = CompletableFuture.runAsync(() ->{
-
-
if(true) {
// Boolean isError = true;
//如果是拆装
@@ -747,13 +733,11 @@ public class TestController {
InstructionWriteUtils.startCorrectInstitution();
Boolean openResult = false;
do {
- Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
//检查是否存在异常
if (openResult = executionBatterySwapService.checkCenOpenExecutionResult()) {
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构正在执行", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
Boolean result = false;
do {
- Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
if(result = executionBatterySwapService.checkCenExecutionResult()){
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构已锁定", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
// 推送云端, 并查询是否存在异常 没有异常, 开始启动换电
@@ -897,11 +881,11 @@ public class TestController {
if (checkJt(rgv, category, runNun)) {
return;
}
-
//取
String finalLoadingRgv = loadingRgv;
- CompletableFuture takeFuture = openFuture.thenApplyAsync((openDoorResult) -> {
- if(openDoorResult){
+ CompletableFuture takeFuture;
+ if(accessStrategyDTO.getBatteryPrefetching()){
+ takeFuture = CompletableFuture.supplyAsync(()->{
try {
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发取出命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
InstructionWriteUtils.takeNewBattery(finalLoadingRgv, Integer.valueOf(takeCwNo));
@@ -941,10 +925,57 @@ public class TestController {
stopRgv(rgv, finalLoadingRgv, e.getMessage());
return false;
}
- }
+ return false;
+ });
+ }else{
+ takeFuture = openFuture.thenApplyAsync((openDoorResult) -> {
+ if(openDoorResult){
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发取出命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
+ InstructionWriteUtils.takeNewBattery(finalLoadingRgv, Integer.valueOf(takeCwNo));
+ Boolean openResult = false;
+ do {
+ errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //跳开查询
+ if (openResult = executionBatterySwapService.checkOpenExecutionResult(finalLoadingRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
+ Boolean endResult = false;
+ do {
+ errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //执行结束查询
+ if (endResult = executionBatterySwapService.executionResult(finalLoadingRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
+ errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ return true;
+
+ }
+ } while (!endResult);
+ }
+ } while (!openResult);
+ } catch (Exception e) {
+ log.error("急停异常");
+ e.printStackTrace();
+ stopRgv(rgv, finalLoadingRgv, e.getMessage());
+ return false;
+ }
+ }
+
+ return false;
+ });
+ }
+
- return false;
- });
//检查是否停止循环
if (checkJt(rgv, category, runNun)) {
@@ -1042,13 +1073,11 @@ public class TestController {
InstructionWriteUtils.closeCorrectInstitution();
Boolean openResult = false;
do {
- Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
//检查是否存在异常
if (openResult = executionBatterySwapService.checkCenOpenExecutionResult()) {
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构正在执行", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
Boolean result = false;
do {
- Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
if(result = executionBatterySwapService.checkCenExecutionResult()){
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构已释放", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
// 推送云端, 并查询是否存在异常 没有异常, 开始启动换电
@@ -1070,406 +1099,17 @@ public class TestController {
//关门完成. 执行下次换电
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; >>>>>全部执行完成, 准备执行下一次循环任务>>>>>>>>>>>>>>>>>>>>>", (runNun + 1), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
//如果当前为最后一次循环, 调整异常为false
-// if(maxNum-1 == runNun){
-// isError = false;
-// }
}
}
-
- //等待装完, 关门
-// Boolean finalIsError = isError;
-// CompletableFuture closeFuture =CompletableFuture.supplyAsync(() ->{
-// //开始执行拆除
-// try {
-// if(!finalIsError){
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("%s 下发关闭开合门命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-// InstructionWriteUtils.closeCenDoor();
-// Boolean result = false;
-// do{
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// if(result = InstructionReadUtils.getCenRbDoorCloseStatus()){
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("%s 开合门已关闭", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-// return true;
-// }
-// }while (!result);
-// }
-// //开门完成
-// } catch (Exception e) {
-// throw new RuntimeException("关闭开合门出现异常:", e);
-// }
-// return false;
-// });
-
-// if(closeFuture.join()){
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("%s 执行次数{%s}全部完成", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), maxNum))));
-// }
}
},
// 延迟执行器:延迟 3 秒
CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS)
);
-
-
-
-
-// CompletableFuture future = CompletableFuture.runAsync(
-// () -> {
-// //如果是拆装
-// for (int runNun=0 ; runNun < maxNum; runNun++){
-// //检查是否停止循环
-// if(checkJt(rgv, category, runNun)){
-// return;
-// }
-// //计算存旧仓位和取新仓位
-// //拆
-// String splitStorageRgv = splitStorageRgvNo;
-// //装
-// String loadingRgv = takePackRgvNo;
-//
-// if(rgvTotal.size() > 1){
-// splitStorageRgv = (runNun % 2 == 0 ? splitStorageRgvNo : takePackRgvNo);
-// loadingRgv = (runNun % 2 == 0 ? takePackRgvNo : splitStorageRgvNo);
-// }
-// //存
-// String putCwNo = (runNun % 2 == 0 ? putNo : takeNo);
-// //取
-// String takeCwNo = (runNun % 2 == 0 ? takeNo : putNo);
-//
-// int finalRunNun = runNun+1;
-//
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; 拆存rgv[%s], 取装rgv[%s], 存仓[%s], 取仓[%s]>>>>>>",(runNun+1), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), splitStorageRgv, loadingRgv, putCwNo, takeCwNo))));
-//
-//// //执行开门
-//// int finalRunNun = runNun+1;
-//// CompletableFuture openFuture = CompletableFuture.supplyAsync(()->{
-//// try {
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; 下发打开开合门命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-//// InstructionWriteUtils.openCenDoor();
-//// Boolean result = false;
-//// do{
-//// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-//// if(result = InstructionReadUtils.getCenRbDoorOpenStatus()){
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; 开合门已打开", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-//// return true;
-//// }
-//// }while (!result);
-//// } catch (Exception e) {
-//// throw new RuntimeException("打开开合门出现异常:",e);
-//// }
-//// return false;
-//// });
-//
-// //检查是否停止循环
-//// if(checkJt(rgv, category, runNun)){
-//// return;
-//// }
-//
-//
-// String finalSplitStorageRgv = splitStorageRgv;
-// //根据开门结果, 执行拆除
-// CompletableFuture splitFuture = openFuture.thenApplyAsync(openResult ->{
-// //开门完成
-// if(openResult){
-// //开始执行拆除
-// try {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>下发拆电池命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv))));
-// InstructionWriteUtils.splitOldBattery(finalSplitStorageRgv);
-// Boolean oResult = false;
-// do {
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //跳开查询
-// if (oResult = executionBatterySwapService.executionOpenResult(finalSplitStorageRgv)) {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行拆电池操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv))));
-// Boolean result = false;
-// do {
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// if (result = executionBatterySwapService.executionResult(finalSplitStorageRgv)) {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>拆电执行完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv))));
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// return true;
-// }
-// } while (!result);
-// }
-// }while (!oResult);
-// } catch (Exception e) {
-// stopRgv(rgv, finalSplitStorageRgv);
-// return false;
-// }
-// }
-// return false;
-// });
-//
-// //检查是否停止循环
-// if(checkJt(rgv, category, runNun)){
-// return;
-// }
-//
-// //根据拆除结果执行存
-// CompletableFuture put = splitFuture.thenApplyAsync(splitResult->{
-// if(splitResult){
-// try {
-// //拆除完成, 准备执行存
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发存入命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv, putCwNo))));
-// InstructionWriteUtils.putOldBattery(finalSplitStorageRgv, Integer.valueOf(putCwNo));
-// Boolean openResult = false;
-// do{
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //跳开查询
-// if(openResult = executionBatterySwapService.executionOpenResult(finalSplitStorageRgv)){
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行存入操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()),finalSplitStorageRgv, putCwNo))));
-// Boolean endResult = false;
-// do{
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //执行结束查询
-// if(endResult = executionBatterySwapService.executionResult(finalSplitStorageRgv)){
-// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>存入操作完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv, putCwNo))));
-// return true;
-//
-//// InstructionWriteUtils.rgvResetToZero(finalSplitStorageRgv);
-//// openResult = false;
-//// do{
-//// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-//// if(checkJt(rgv, category, finalRunNun)){
-//// return false;
-//// }
-//// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-//// //跳开查询
-//// if(openResult = executionBatterySwapService.executionOpenResult(finalSplitStorageRgv)){
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行归位操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()),finalSplitStorageRgv))));
-//// endResult = false;
-//// do{
-//// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-//// if(checkJt(rgv, category, finalRunNun)){
-//// return false;
-//// }
-//// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-//// //执行结束查询
-//// if(endResult = executionBatterySwapService.executionResult(finalSplitStorageRgv)){
-//// //输出
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>归位操作完成",finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalSplitStorageRgv))));
-//// errorCheck(rgv, finalSplitStorageRgv, category, finalRunNun);
-//// if(checkJt(rgv, category, finalRunNun)){
-//// return false;
-//// }
-//// return true;
-//// }
-//// }while(!endResult);
-//// }
-//// }while (!openResult);
-// }
-// }while(!endResult);
-// }
-// }while (!openResult);
-// } catch (Exception e) {
-// stopRgv(rgv, finalSplitStorageRgv);
-// return false;
-// }
-// }
-// return false;
-// });
-//
-// //检查是否停止循环
-// if(checkJt(rgv, category, runNun)){
-// return;
-// }
-//
-// //取
-// String finalLoadingRgv = loadingRgv;
-// CompletableFuture takeFuture = CompletableFuture.supplyAsync(()->{
-//
-// try {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发取出命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
-// InstructionWriteUtils.takeNewBattery(finalLoadingRgv, Integer.valueOf(takeCwNo));
-// Boolean openResult = false;
-// do {
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //跳开查询
-// if (openResult = executionBatterySwapService.executionOpenResult(finalLoadingRgv)) {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
-// Boolean endResult = false;
-// do {
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //执行结束查询
-// if (endResult = executionBatterySwapService.executionResult(finalLoadingRgv)) {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv, takeCwNo))));
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if (checkJt(rgv, category, finalRunNun)) {
-// return false;
-// }
-// return true;
-//
-// }
-// } while (!endResult);
-// }
-// }while (!openResult);
-// } catch (Exception e) {
-// e.printStackTrace();
-// stopRgv(rgv, finalLoadingRgv);
-// return false;
-// }
-// return false;
-// });
-//
-// //检查是否停止循环
-// if(checkJt(rgv, category, runNun)){
-// return;
-// }
-//
-// //装
-// //根据拆除结果, 和取出结果执行装
-// CompletableFuture loading = CompletableFuture.allOf(splitFuture, takeFuture).thenApplyAsync(voidResult -> {
-// Boolean split = splitFuture.join();
-// Boolean take = takeFuture.join();
-// try {
-// if(split && take){
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行拆电池操作完成, 下发装电池命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-// InstructionWriteUtils.loadingNewBattery(finalLoadingRgv);
-// Boolean openResult = false;
-// do {
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// //跳开查询
-// if (openResult = executionBatterySwapService.executionOpenResult(finalLoadingRgv)) {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行装电池操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-// Boolean result = false;
-// do {
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// if(result = executionBatterySwapService.executionResult(finalLoadingRgv)){
-// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-// if(checkJt(rgv, category, finalRunNun)){
-// return false;
-// }
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行装电池操作完成", finalRunNun,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-// return true;
-//// InstructionWriteUtils.rgvResetToZero(finalLoadingRgv);
-//// openResult = false;
-//// do {
-//// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-//// if(checkJt(rgv, category, finalRunNun)){
-//// return false;
-//// }
-//// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-//// //跳开查询
-//// if (openResult = executionBatterySwapService.executionOpenResult(finalLoadingRgv)) {
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行归位操作", finalRunNun,new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-//// result = false;
-//// do{
-//// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-//// if(checkJt(rgv, category, finalRunNun)){
-//// return false;
-//// }
-//// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-//// if(result = executionBatterySwapService.executionResult(finalLoadingRgv)){
-//// //输出
-//// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>归位操作完成",finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-//// errorCheck(rgv, finalLoadingRgv, category, finalRunNun);
-//// if (checkJt(rgv, category, finalRunNun)) {
-//// return false;
-//// }
-//// return true;
-//// }
-//// }while (!result);
-//// }
-//// }while (!openResult);
-// }
-// }while(!result);
-// }
-// }while (!openResult);
-//
-// }else{
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>进行安装失败", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalLoadingRgv))));
-// stopRgv(rgv, finalLoadingRgv);
-// return false;
-// }
-// } catch (Exception e) {
-// e.printStackTrace();
-// stopRgv(rgv, finalLoadingRgv);
-// return false;
-// }
-// return false;
-// });
-//
-// //检查是否停止循环
-// if(checkJt(rgv, category, runNun)){
-// return;
-// }
-//
-// //等待装完, 关门
-// CompletableFuture closeFuture =loading.thenApplyAsync(loadingResult ->{
-// //开门完成
-// if(loadingResult){
-// //开始执行拆除
-// try {
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("%s 下发关闭开合门命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-// InstructionWriteUtils.closeCenDoor();
-// Boolean result = false;
-// do{
-// Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
-// if(result = InstructionReadUtils.getCenRbDoorCloseStatus()){
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("%s 开合门已关闭", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-// return true;
-// }
-// }while (!result);
-// } catch (Exception e) {
-// stopRgv(rgv, finalLoadingRgv);
-// throw new RuntimeException("关闭开合门出现异常:", e);
-// }
-// }
-// return false;
-// });
-//
-// if(openFuture.join() && splitFuture.join() && put.join() && takeFuture.join() && loading.join() && closeFuture.join()){
-// //关门完成. 执行下次换电
-// WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("第[%s]次执行: 执行时间:[%s]; >>>>>全部执行完成, 准备执行下一次循环任务>>>>>>>>>>>>>>>>>>>>>",(runNun+1), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
-// }
-// }
-// taskRgvMap.remove(rgv);
-// System.out.println("CompletableFuture 任务执行:" + Thread.currentThread().getName() + ",时间:" + System.currentTimeMillis());
-// },
-// // 延迟执行器:延迟 3 秒
-// CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS)
-// );
//
// 可选:监听任务状态
future.whenComplete((unused, throwable) -> {
@@ -1652,18 +1292,6 @@ public class TestController {
public Result startDoor(@PathVariable("category") final String category,
@RequestParam("maxNum") final Integer maxNum) throws InstructionException, InterruptedException {
Boolean startRun = true;
-// for (String rgv : AccessStrategyUtil.getEffectiveRgvNoList()){
-// if(executionBatterySwapService.executionResult(rgv)){
-// Thread.sleep(1000);
-// if(executionBatterySwapService.executionResult(rgv)){
-// startRun = true;
-// }else{
-// startRun = false;
-// }
-// }else{
-// startRun = false;
-// }
-// }
//检查RGV是否运作
if(startRun){
closeRunMap.put("door", new AtomicBoolean(false));
@@ -1778,4 +1406,547 @@ public class TestController {
}
+
+
+ @ApiOperation("单仓测试开始")
+ @PostMapping("/start/one/{category}")
+ @ApiLog(value = "全量测试开始", type = LogTypeEnum.OPERATION)
+ public Result startAll(@PathVariable("category") final String category,
+ @RequestParam("maxNum") final Integer maxNum,
+ @RequestParam("splitStorageRgvNo") final String splitStorageRgvNo,
+ @RequestParam(value = "putNo", required = false) final String putNo,
+ @RequestParam(value = "takeNo", required = false) final String takeNo) throws InstructionException, InterruptedException {
+
+ //检查RGV是否运作
+ if(executionBatterySwapService.executionResult(splitStorageRgvNo)){
+ //睡了1秒再次检查, 防止空闲冲突
+ Thread.sleep(1000);
+ if(executionBatterySwapService.executionResult(splitStorageRgvNo)){
+ //进入循环之前, 只查询一次, 防止数据错乱
+ List rgvTotal = AccessStrategyUtil.getEffectiveRgvNoList();
+ if(Collections.isEmpty(rgvTotal)){
+ return Result.getInstance().error("没有生效的RGV");
+ }
+ String rgv = splitStorageRgvNo;
+
+ closeRunMap.put(rgv, new AtomicBoolean(false));
+ categoryRunMap.put(rgv,category);
+ CompletableFuture future = CompletableFuture.runAsync(() ->{
+
+ if(true) {
+ //如果是拆装
+ for (int runNun = 0; runNun < maxNum; runNun++) {
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //拆
+ String splitStorageRgv = splitStorageRgvNo;
+ //存
+ String putCwNo = (runNun % 2 == 0 ? putNo : takeNo);
+ //取
+ String takeCwNo = (runNun % 2 == 0 ? takeNo : putNo);
+
+ int finalRunNun = runNun + 1;
+
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; 执行rgv[%s], 存仓[%s], 取仓[%s]>>>>>>", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), splitStorageRgv, putCwNo, takeCwNo))));
+ String finalRgv = splitStorageRgv;
+ //启动对中机构
+ CompletableFuture correctFuture = CompletableFuture.supplyAsync(()->{
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 下发启动对中机构命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ InstructionWriteUtils.startCorrectInstitution();
+ Boolean openResult = false;
+ do {
+ //检查是否存在异常
+ if (openResult = executionBatterySwapService.checkCenOpenExecutionResult()) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构正在执行", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ Boolean result = false;
+ do {
+ if(result = executionBatterySwapService.checkCenExecutionResult()){
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构已锁定", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ // 推送云端, 并查询是否存在异常 没有异常, 开始启动换电
+ return true;
+ }
+ }while (!result);
+ //如果为true,则证明执行结束
+ }
+ }while (!openResult);
+ } catch (Exception e) {
+ throw new RuntimeException("启动对中机构出现异常:",e);
+ }
+ return false;
+ });
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //执行开门
+ CompletableFuture openFuture = correctFuture.thenApplyAsync((correctResult)->{
+ if(correctResult){
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 下发打开开合门命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ InstructionWriteUtils.openCenDoor();
+ Boolean result = false;
+ do{
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ if(result = InstructionReadUtils.getCenRbDoorOpenStatus()){
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 开合门已打开", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ return true;
+ }
+ }while (!result);
+ } catch (Exception e) {
+ throw new RuntimeException("打开开合门出现异常:",e);
+ }
+ }
+ return false;
+ });
+
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //根据开门结果, 执行拆除
+ CompletableFuture splitFuture = openFuture.thenApplyAsync((openResult) -> {
+ if(openResult){
+ //开始执行拆除
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>下发拆电池命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ InstructionWriteUtils.splitOldBattery(finalRgv);
+ Boolean oResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //跳开查询
+ if (oResult = executionBatterySwapService.checkOpenExecutionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行拆电池操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ Boolean result = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ if (result = executionBatterySwapService.executionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>拆电执行完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ return true;
+ }
+ } while (!result);
+ }
+ } while (!oResult);
+ } catch (Exception e) {
+ log.error("急停异常");
+ e.printStackTrace();
+ stopRgv(rgv, finalRgv, e.getMessage());
+ return false;
+ }
+ }
+
+ return false;
+ });
+
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //根据拆除结果执行存
+ CompletableFuture putFuture = splitFuture.thenApplyAsync(splitResult -> {
+ if (splitResult) {
+ try {
+ //拆除完成, 准备执行存
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发存入命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, putCwNo))));
+ InstructionWriteUtils.putOldBattery(finalRgv, Integer.valueOf(putCwNo));
+ Boolean openResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //跳开查询
+ if (openResult = executionBatterySwapService.checkOpenExecutionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行存入操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, putCwNo))));
+ Boolean endResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //执行结束查询
+ if (endResult = executionBatterySwapService.executionResult(finalRgv)) {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>存入操作完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, putCwNo))));
+ return true;
+ }
+ } while (!endResult);
+ }
+ } while (!openResult);
+ } catch (Exception e) {
+ log.error("急停异常");
+ e.printStackTrace();
+ stopRgv(rgv, finalRgv, e.getMessage());
+ return false;
+ }
+ }
+ return false;
+ });
+
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //取
+ CompletableFuture takeFuture = putFuture.thenApplyAsync((openDoorResult) -> {
+ if(openDoorResult){
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>下发取出命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, takeCwNo))));
+ InstructionWriteUtils.takeNewBattery(finalRgv, Integer.valueOf(takeCwNo));
+ Boolean openResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //跳开查询
+ if (openResult = executionBatterySwapService.checkOpenExecutionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, takeCwNo))));
+ Boolean endResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //执行结束查询
+ if (endResult = executionBatterySwapService.executionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s], 电池仓位[%s]>>>>>执行取出完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv, takeCwNo))));
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ return true;
+
+ }
+ } while (!endResult);
+ }
+ } while (!openResult);
+ } catch (Exception e) {
+ log.error("急停异常");
+ e.printStackTrace();
+ stopRgv(rgv, finalRgv, e.getMessage());
+ return false;
+ }
+ }
+
+ return false;
+ });
+
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //装
+ //根据拆除结果, 和取出结果执行装
+ CompletableFuture loading = CompletableFuture.allOf(splitFuture, takeFuture).thenApplyAsync(voidResult -> {
+ Boolean split = splitFuture.join();
+ Boolean take = takeFuture.join();
+ try {
+ if (split && take) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行拆电池操作完成, 下发装电池命令", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ InstructionWriteUtils.loadingNewBattery(finalRgv);
+ Boolean openResult = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ //跳开查询
+ if (openResult = executionBatterySwapService.checkOpenExecutionResult(finalRgv)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行装电池操作", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ Boolean result = false;
+ do {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ if (result = executionBatterySwapService.executionResult(finalRgv)) {
+ errorCheck(rgv, finalRgv, category, finalRunNun);
+ if (checkJt(rgv, category, finalRunNun)) {
+ return false;
+ }
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>执行装电池操作完成", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ return true;
+ }
+ } while (!result);
+ }
+ } while (!openResult);
+
+ } else {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; RRG:[%s]>>>>>进行安装失败", finalRunNun, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), finalRgv))));
+ log.error("安装失败");
+ stopRgv(rgv, finalRgv, "安装失败");
+ return false;
+ }
+ } catch (Exception e) {
+ log.error("急停异常");
+ e.printStackTrace();
+ stopRgv(rgv, finalRgv, e.getMessage());
+ return false;
+ }
+ return false;
+ });
+
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //执行关门
+ CompletableFuture closeFuture =loading.thenApplyAsync((loadingResult) ->{
+ if(loadingResult){
+ //开始执行拆除
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data", String.format("%s 下发关闭开合门命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ InstructionWriteUtils.closeCenDoor();
+ Boolean result = false;
+ do{
+ Thread.sleep(ParamUtils.getInstructionIntervalRequestMilliseconds());
+ if(result = InstructionReadUtils.getCenRbDoorCloseStatus()){
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("%s 开合门已关闭", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ return true;
+ }
+ }while (!result);
+ //开门完成
+ } catch (Exception e) {
+ throw new RuntimeException("关闭开合门出现异常:", e);
+ }
+ }
+ return false;
+ });
+ //检查是否停止循环
+ if (checkJt(rgv, category, runNun)) {
+ return;
+ }
+ //释放对中机构
+ CompletableFuture closeCorrectFuture = closeFuture.thenApplyAsync((closeDoorFuture)->{
+ if(closeDoorFuture){
+ try {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 下发释放对中机构命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ InstructionWriteUtils.closeCorrectInstitution();
+ Boolean openResult = false;
+ do {
+ //检查是否存在异常
+ if (openResult = executionBatterySwapService.checkCenOpenExecutionResult()) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构正在执行", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ Boolean result = false;
+ do {
+ if(result = executionBatterySwapService.checkCenExecutionResult()){
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format(" 执行时间:[%s]; 对中机构已释放", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ // 推送云端, 并查询是否存在异常 没有异常, 开始启动换电
+ return true;
+ }
+ }while (!result);
+ //如果为true,则证明执行结束
+ }
+ }while (!openResult);
+ } catch (Exception e) {
+ throw new RuntimeException("释放对中机构出现异常:",e);
+ }
+ }
+
+ return false;
+ });
+ //只需要检查存电完成, 和 对中机构释放就可以执行下一次循环
+ if (putFuture.join() && closeCorrectFuture.join()) {
+ //关门完成. 执行下次换电
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("第[%s]次执行: 执行时间:[%s]; >>>>>全部执行完成, 准备执行下一次循环任务>>>>>>>>>>>>>>>>>>>>>", (runNun + 1), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ //如果当前为最后一次循环, 调整异常为false
+ }
+
+ }
+
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",String.format("%s 执行次数{%s}全部完成", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), maxNum))));
+ }
+
+ },
+ // 延迟执行器:延迟 3 秒
+ CompletableFuture.delayedExecutor(3, TimeUnit.SECONDS)
+ );
+//
+ // 可选:监听任务状态
+ future.whenComplete((unused, throwable) -> {
+ if (throwable instanceof java.util.concurrent.CancellationException) {
+ System.out.println("开始---->任务已被取消");
+ } else if (throwable != null) {
+ String message = throwable.getMessage();
+ if(StringUtils.isNotEmpty(message)){
+ message = message.replace("java.lang.RuntimeException: ","");
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",message)));
+ String[] mesArray = message.split(";");
+ // RRG:[1] 出现异常; 机构区间为:{1}; 执行类型为:{取存}; 执行次数为:{1}; 异常信息为:{/ by zero}
+ CloudSendInfoUtils.sendAlarmWx(Collections.asMap("area","红旗换电站", "message", mesArray[4].replace("异常信息为:{","").replace("}","")));
+ }
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data","时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())+ "异常信息"+throwable.getMessage())));
+ } else {
+ System.out.println("开始---->任务正常完成");
+ taskRgvMap.remove(rgv);
+ }
+ });
+ try {
+ taskRgvMap.put(rgv, future);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
+ }
+ return Result.getInstance().success();
+ }else{
+ return Result.getInstance().error("当前RGV正在运行");
+ }
+ }else{
+ return Result.getInstance().error("当前RGV正在运行");
+ }
+
+ }
+
+
+ @ApiOperation("单仓结束")
+ @PostMapping("/stop/one/{category}")
+ @ApiLog(value = "全量结束", type = LogTypeEnum.OPERATION)
+ public Result stopOne(@PathVariable("category") final String category, @RequestParam("splitStorageRgvNo") final String splitStorageRgvNo) throws Exception {
+
+ String rgv = splitStorageRgvNo;
+
+ //检查RGV是否运作
+ if(executionBatterySwapService.executionResult(splitStorageRgvNo) && taskRgvMap.containsKey(rgv)){
+ //睡了1秒再次检查, 防止空闲冲突
+ Thread.sleep(1000);
+ if(executionBatterySwapService.executionResult(splitStorageRgvNo)){
+ CompletableFuture future = taskRgvMap.get(rgv);
+ if(future == null){
+ return Result.getInstance().success("当前任务已停止");
+ }
+ future.cancel(true);
+ closeRunMap.put(rgv, new AtomicBoolean(true));
+ InstructionWriteUtils.rgvStopMove(splitStorageRgvNo);
+ checkJt(rgv, category, 0);
+ taskRgvMap.remove(rgv);
+ }
+ }else{
+ CompletableFuture future = taskRgvMap.get(rgv);
+ if(future == null){
+ return Result.getInstance().success("当前任务已停止");
+ }
+ future.cancel(true);
+ closeRunMap.put(rgv, new AtomicBoolean(true));
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("执行时间[%s]; >>>>>下发停止操作命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ CompletableFuture closeFuture = CompletableFuture.runAsync(
+ () -> {
+ try {
+ Boolean openResult = false;
+ InstructionWriteUtils.rgvStopMove(splitStorageRgvNo);
+ do {
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ if(checkJt(rgv, category, 0)){
+ return;
+ }
+ //跳开查询
+ if (openResult = (executionBatterySwapService.checkOpenExecutionResult(splitStorageRgvNo))) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("执行时间[%s]; RGV[%s]>>>>>开始执行停止操作", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), splitStorageRgvNo))));
+ Boolean result = false;
+ do {
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ if(checkJt(rgv, category, 0)){
+ return;
+ }
+ if(result = (executionBatterySwapService.executionResult(splitStorageRgvNo))) {
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ if(checkJt(rgv, category, 0)){
+ return;
+ }
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("执行时间[%s]; RGV[%s]>>>>>停止操作完成, 下发归零操作命令", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), splitStorageRgvNo))));
+ InstructionWriteUtils.rgvResetToZero(splitStorageRgvNo);
+ Integer num = 0;
+ do {
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ if(checkJt(rgv, category, 0)){
+ return;
+ }
+ num += 1;
+ //跳开查询
+ if (openResult = ((executionBatterySwapService.checkOpenExecutionResult(splitStorageRgvNo)) || num > 10)) {
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("执行时间[%s]; RGV[%s]>>>>>开始执行归零操作", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), splitStorageRgvNo))));
+ result = false;
+ do {
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ if(checkJt(rgv, category, 0)){
+ return;
+ }
+ if (result = (executionBatterySwapService.executionResult(splitStorageRgvNo))) {
+ //输出
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "testRgv" + category, "data", String.format("执行时间[%s]>>>>>归零操作完成, 任务停止", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())))));
+ errorCheck(rgv, splitStorageRgvNo, category, 0);
+ }
+ } while (!result);
+ }
+ }while (!openResult);
+ }
+ }while(!result);
+ }
+ }while (!openResult);
+
+ } catch (Exception e) {
+ try {
+ String message = e.getMessage();
+ Map error = executionBatterySwapService.executionErrorResult(splitStorageRgvNo);
+ if(Collections.isNotEmpty(error)){
+ message = JSONObject.toJSONString(error);
+ }
+ closeRunMap.put(rgv, new AtomicBoolean(true));
+ throw new RuntimeException(String.format(" 执行时间:[%s]; RRG:[%s] 出现异常; 机构区间为:{%s}; 执行类型为:{%s}; 异常信息为:{%s}",new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()), rgv, category, "拆装", message), e);
+ } catch (InstructionException ex) {
+ throw new RuntimeException(ex);
+ }
+ }
+ },
+ // 延迟执行器:延迟 3 秒
+ CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS)
+ );
+
+ // 可选:监听任务状态
+ closeFuture.whenComplete((unused, throwable) -> {
+ if (throwable instanceof java.util.concurrent.CancellationException) {
+ System.out.println("开始---->任务已被取消");
+ } else if (throwable != null) {
+ String message = throwable.getMessage();
+ if(StringUtils.isNotEmpty(message)){
+ message = message.replace("java.lang.RuntimeException: ","");
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data",message)));
+ String[] mesArray = message.split(";");
+ // RRG:[1] 出现异常; 机构区间为:{1}; 执行类型为:{取存}; 执行次数为:{1}; 异常信息为:{/ by zero}
+ CloudSendInfoUtils.sendAlarmWx(Collections.asMap("area","红旗换电站", "message", mesArray[4].replace("异常信息为:{","").replace("}","")));
+ }
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","testRgv"+category,"data","执行停止操作出现异常, 时间:"+new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date())+ "异常信息"+throwable.getMessage())));
+ } else {
+ System.out.println("开始---->任务正常完成");
+ taskRgvMap.remove(rgv);
+ }
+ });
+ }
+
+ return Result.getInstance().success();
+ }
+
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/job/JobConstant.java b/web-server/src/main/java/com/evotech/hd/webserver/job/JobConstant.java
index 7f1bc1c..354e8fa 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/job/JobConstant.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/job/JobConstant.java
@@ -2,6 +2,7 @@ package com.evotech.hd.webserver.job;
import com.evotech.hd.core.enums.BaseEnum;
import com.evotech.hd.webserver.job.job.ArrivalSignalJob;
+import com.evotech.hd.webserver.job.job.KeepaliveJob;
import com.evotech.hd.webserver.job.job.LicensePlateMachineJob;
import lombok.AllArgsConstructor;
import lombok.Getter;
@@ -97,7 +98,10 @@ public class JobConstant {
*/
// public static String VEHICLE_ABDICATION_JOB = VehicleAbdicationJob.class.getSimpleName();
-
+ /***
+ * 客户端与服务端的心跳检查
+ */
+ public static String KEEPALIVE_JOB = KeepaliveJob.class.getSimpleName();
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/job/job/CheckAlarmJob.java b/web-server/src/main/java/com/evotech/hd/webserver/job/job/CheckAlarmJob.java
index 3840294..f62f4c6 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/job/job/CheckAlarmJob.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/job/job/CheckAlarmJob.java
@@ -1,18 +1,23 @@
package com.evotech.hd.webserver.job.job;
+import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.evotech.hd.core.dtos.Result;
import com.evotech.hd.core.dtos.ResultUtil;
import com.evotech.hd.core.dtos.business.AccessStrategyDTO;
+import com.evotech.hd.core.dtos.business.BatteryCompartmentDTO;
import com.evotech.hd.core.dtos.business.RunningInstructionsDetailDTO;
import com.evotech.hd.core.dtos.system.ParamsDTO;
import com.evotech.hd.exception.InstructionException;
import com.evotech.hd.utils.Collections;
import com.evotech.hd.webserver.controller.TestController;
+import com.evotech.hd.webserver.mqtt.MqttPublishUtils;
import com.evotech.hd.webserver.service.ParamsService;
import com.evotech.hd.webserver.utils.AccessStrategyUtil;
+import com.evotech.hd.webserver.utils.ParamUtils;
import com.evotech.hd.webserver.utils.instruction.InstructionReadUtils;
import com.evotech.hd.webserver.utils.instruction.InstructionUtils;
+import com.evotech.hd.webserver.utils.query.QueryWrapperGenerator;
import com.evotech.hd.webserver.utils.sendCloud.CloudSendInfoUtils;
import com.evotech.hd.webserver.websocket.controller.WebSocketUtils;
import lombok.extern.slf4j.Slf4j;
@@ -21,6 +26,7 @@ import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
+import java.util.stream.Collectors;
/**
* 首页告警扫描
@@ -35,9 +41,11 @@ public class CheckAlarmJob implements BaseJob{
// 任务执行方法(必须定义为public void run())
- public void run(Map params) throws InstructionException {
+ public void run(Map params) throws Exception {
log.info("===== 执行检查报警任务 =====");
Map alarmMessage = Collections.emptyMap();
+ //默认不影响
+ Boolean effectBatterySwapping = false;
//获取所有的异常指令
List instructions = getRunningInstructionsDetailService().findDictDetailDTOByTypeCode("check_alarm");
if(Collections.isNotEmpty(instructions)){
@@ -51,20 +59,9 @@ public class CheckAlarmJob implements BaseJob{
for (String rgvNo : rgvArrays){
if(!InstructionUtils.getBoolean(paramsDTO, InstructionReadUtils.executionInteger(paramsDTO, rgvNo))){
alarmMessage.put(paramsDTO.getName().replace(":num", rgvNo), paramsDTO.getErrMessage().replace(":num", rgvNo));
- }
- }
- }else{
- alarmMessage.put("RGV连接", "没有可用的RGV设备");
- }
- }if("RGV_RB_ErrorCode".equals(paramsDTO.getParamCode())){
- AccessStrategyDTO accessStrategyDTO = AccessStrategyUtil.getValidAccessStrategyDTO();
- if(StringUtils.isNotEmpty(accessStrategyDTO.getEffectiveRgvNo())){
- String[] rgvArrays = accessStrategyDTO.getEffectiveRgvNo().split(",");
- for (String rgvNo : rgvArrays){
- Map result = getExecutionBatterySwapService().executionErrorResult(rgvNo);
- if(Collections.isNotEmpty(result)){
- alarmMessage.put(paramsDTO.getName().replace(":num", rgvNo), String.valueOf(result.get("errorMsg")));
- TestController.getInstance().stopRgv(rgvNo, rgvNo, String.valueOf(result.get("errorMsg")));
+ if(paramsDTO.getEffectBatterySwapping()){
+ effectBatterySwapping = true;
+ }
}
}
}else{
@@ -73,9 +70,11 @@ public class CheckAlarmJob implements BaseJob{
}else{
if(!InstructionUtils.getBoolean(paramsDTO, InstructionReadUtils.executionInteger(paramsDTO, null))){
alarmMessage.put(paramsDTO.getName(), paramsDTO.getErrMessage());
+ if(paramsDTO.getEffectBatterySwapping()){
+ effectBatterySwapping = true;
+ }
}
}
-
}
}
//检查云平台链接
@@ -85,10 +84,12 @@ public class CheckAlarmJob implements BaseJob{
alarmMessage.put("云平台", "连接丢失");
}
+ //检查电池仓,电池信号
+ alarmMessage = checkBatteryCompartmentSignal(alarmMessage);
+
//存在告警, 推送数据
if(Collections.isNotEmpty(alarmMessage)){
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","alarm","data",JSONObject.toJSONString(alarmMessage))));
-
if(keepalive != null && keepalive){
//推送数据
Map alarmMap = Collections.emptyMap();
@@ -104,9 +105,47 @@ public class CheckAlarmJob implements BaseJob{
if(alarmMessage.containsKey("急停")){
alarmMap.put("stop", 2); //2为云平台现有的定义的站控的报警标识
}
- CloudSendInfoUtils.sendAlarm(alarmMap);
+ CloudSendInfoUtils.sendAlarm(alarmMap, effectBatterySwapping);
}
}
log.info("检查报警任务执行完成");
}
+
+
+ BatteryCompartmentDTO params = new BatteryCompartmentDTO(){{
+ setStatus(1);
+ setState(1);
+ }};
+ //
+ public Map checkBatteryCompartmentSignal(Map alarmMessage) throws Exception {
+ //获取所有的仓位
+ List list = getBatteryCompartmentService().findList(QueryWrapperGenerator.buildQueryCondition(params, BatteryCompartmentDTO.class));
+ StringBuilder sb = new StringBuilder("");
+ //有电池,无信号
+ List existsBatteryList = list.stream().filter(BatteryCompartmentDTO::getExistsBattery).collect(Collectors.toList());
+ if(Collections.isNotEmpty(existsBatteryList)){
+ for (BatteryCompartmentDTO bc : existsBatteryList){
+ //如果有电池, 返回的无电池信号, 直接锁定电池仓, 做电池仓禁用
+ if(!InstructionReadUtils.checkExistsBattery(String.valueOf(bc.getId()))){
+ getBatteryCompartmentService().settingState(bc.getId(), 2);
+ sb.append("电池仓: ").append(bc.getId()).append("号, 电池信号丢失, 请确认;");
+ }
+ }
+ }
+ //没电池, 有信号
+ List notExistsBatteryList = list.stream().filter(data -> !data.getExistsBattery()).collect(Collectors.toList());
+ if(Collections.isNotEmpty(notExistsBatteryList)){
+ for (BatteryCompartmentDTO bc : notExistsBatteryList){
+ //如果有电池, 返回的无电池信号, 直接锁定电池仓, 做电池仓禁用
+ if(InstructionReadUtils.checkExistsBattery(String.valueOf(bc.getId()))){
+ getBatteryCompartmentService().settingState(bc.getId(), 2);
+ sb.append("电池仓: ").append(bc.getId()).append("号, 出现未知电池信号, 请确认;");
+ }
+ }
+ }
+ if(sb.length() > 0){
+ alarmMessage.put("电池仓", sb.toString());
+ }
+ return alarmMessage;
+ }
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/job/job/KeepaliveJob.java b/web-server/src/main/java/com/evotech/hd/webserver/job/job/KeepaliveJob.java
new file mode 100644
index 0000000..96e8805
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/job/job/KeepaliveJob.java
@@ -0,0 +1,26 @@
+package com.evotech.hd.webserver.job.job;
+
+import com.evotech.hd.webserver.mqtt.MqttPublishUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * KeepaliveJob
+ *
+ * @author andy.shi
+ * @ClassName:KeepaliveLob
+ * @date: 2026年01月13日 11:34
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Slf4j
+@Component
+public class KeepaliveJob implements BaseJob{
+
+
+ @Override
+ public void run(Map params) throws Exception {
+ MqttPublishUtils.sendKeepalive();
+ }
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/job/service/ExecutionBatterySwapService.java b/web-server/src/main/java/com/evotech/hd/webserver/job/service/ExecutionBatterySwapService.java
index 33f0881..1b798a8 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/job/service/ExecutionBatterySwapService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/job/service/ExecutionBatterySwapService.java
@@ -1,6 +1,7 @@
package com.evotech.hd.webserver.job.service;
import cn.hutool.extra.spring.SpringUtil;
+import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.evotech.hd.core.dtos.Result;
@@ -109,6 +110,16 @@ public class ExecutionBatterySwapService {
WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method","order","data",JSONObject.toJSONString(ResultUtil.getValue(runningOrderResult)))));
//下发物理接口, 抬杆放行 TODO
InstructionWriteUtils.openRolling(ParamUtils.getDoorParams("入口"));
+ //如果是双RGV, 并且开启了预取,
+ AccessStrategyDTO accessStrategyDTO = AccessStrategyUtil.getValidAccessStrategyDTO();
+ //如果开启了预存
+ if(accessStrategyDTO.getBatteryPrefetching() && AccessStrategyUtil.getEffectiveRgvNoList(accessStrategyDTO).size() > 1){
+ //获取仓位信息
+ Map resultMap = calculationPosition(accessStrategyDTO);
+ RedisUtil.set("rgvInfo", JSONObject.toJSONString(resultMap));
+ //执行取点数据
+ buildTakeFuture(resultMap.get("loadingRgv"), Integer.valueOf(resultMap.get("takeNo")), runningOrderResult.getData().getId());
+ }
try {
//开启车辆到位扫秒
quartzJobService.resumeJob(new QuartzJobInfo(JobConstant.ARRIVAL_SIGNAL_JOB, JobConstant.GroupEnum.SWAP_GROUP.getType()));
@@ -143,7 +154,12 @@ public class ExecutionBatterySwapService {
//打开开合门
if(buildOpenFuture().get()){
//获取仓位信息
- Map result = calculationPosition(accessStrategyDTO);
+ Map result = Collections.emptyMap();
+ if(accessStrategyDTO.getBatteryPrefetching() && AccessStrategyUtil.getEffectiveRgvNoList(accessStrategyDTO).size() > 1){
+ result = JSON.to(Map.class, RedisUtil.get("rgvInfo"));
+ }else{
+ result = calculationPosition(accessStrategyDTO);
+ }
//查询当前运行订单
Result running = orderSwapService.runningOrder();
OrderSwapDTO orderSwapDTO = running.getData();
@@ -284,7 +300,27 @@ public class ExecutionBatterySwapService {
return false;
});
//取
- CompletableFuture takeFuture =buildTakeFuture(loadingRgv, takeNo, orderId);
+ CompletableFuture takeFuture;
+ if(AccessStrategyUtil.getValidAccessStrategyDTO().getBatteryPrefetching()){
+ takeFuture = CompletableFuture.supplyAsync(() -> {
+ try {
+ Boolean result = false;
+ //下发拆除命令
+ do {
+ if(result = Boolean.valueOf(String.valueOf(RedisUtil.get("buildTakeFuture")))){
+ return true;
+ }
+ }while (!result);
+ } catch (Exception e) {
+ log.error("预取失败, {}", e.getMessage(), e);
+ return false;
+ }
+ return false;
+ });
+ }else{
+ //取
+ takeFuture =buildTakeFuture(loadingRgv, takeNo, orderId);
+ }
//装. 依托于 拆, 取
CompletableFuture loadingFuture = CompletableFuture.allOf(splitFuture, takeFuture).thenApplyAsync(voidResult->{
Boolean split = splitFuture.join();
@@ -323,6 +359,7 @@ public class ExecutionBatterySwapService {
});
}
//启动对中机构
+ //对中机构启动速度过快, 无法短频查询, 所以取消sleep();
public CompletableFuture buildCenOpenFuture(){
return CompletableFuture.supplyAsync(()->{
try {
@@ -333,12 +370,10 @@ public class ExecutionBatterySwapService {
if(checkCenError()){
return false;
}
- sleep();
if (openResult = checkCenOpenExecutionResult()) {
log.info("对中机构正在运行, 当前时间为: "+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
Boolean result = false;
do {
- sleep();
if(result = checkCenExecutionResult()){
log.info("对中机构执行完成, 当前时间为: "+ new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").format(new Date()));
// 推送云端, 并查询是否存在异常 没有异常, 开始启动换电
@@ -494,6 +529,7 @@ public class ExecutionBatterySwapService {
public CompletableFuture buildTakeFuture(final String rgv, final Integer taskNo, final Integer orderId){
return CompletableFuture.supplyAsync(() -> {
try {
+ RedisUtil.set("buildTakeFuture", false);
OrderSwap orderSwap = orderSwapService.getById(orderId);
orderSwap.setRentBatNo(String.valueOf(taskNo));
Battery battery = batteryService.getBatteryByCompartmentId(taskNo);
@@ -531,6 +567,7 @@ public class ExecutionBatterySwapService {
log.error("取新电池后, BMS下电出现错误", e);
e.printStackTrace();
}
+ RedisUtil.set("buildTakeFuture", true);
return true;
}
return false;
@@ -795,9 +832,12 @@ public class ExecutionBatterySwapService {
orderSwapService.updateById(orderSwapWrapper.toEntity(orderSwapDTO));//更新换电完成状态
//执行换电完成
executionResultPush(orderSwapDTO, SwapBatteryStepEnum.COMPLETED, false, Collections.emptyMap());
+ //换电完成, 预取结果重置为false
+ RedisUtil.set("buildTakeFuture", false);
+ //重置rgv信息
+ RedisUtil.set("rgvInfo", JSONObject.toJSONString(Collections.emptyMap()));
//关闭开合门
if(buildCloseFuture().get()){
-
//释放对中机构
InstructionWriteUtils.closeCorrectInstitution();
//推送空对象推送websocket, 刷新首页数据
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mapper/BasicMapper.java b/web-server/src/main/java/com/evotech/hd/webserver/mapper/BasicMapper.java
new file mode 100644
index 0000000..fe73d96
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mapper/BasicMapper.java
@@ -0,0 +1,12 @@
+package com.evotech.hd.webserver.mapper;
+
+/**
+ * BasicMapper
+ *
+ * @author andy.shi
+ * @ClassName:BasicMapper
+ * @date: 2026年01月12日 11:27
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+public interface BasicMapper {
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mapper/BatteryCompartmentMapper.java b/web-server/src/main/java/com/evotech/hd/webserver/mapper/BatteryCompartmentMapper.java
index 5117007..bb49050 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/mapper/BatteryCompartmentMapper.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mapper/BatteryCompartmentMapper.java
@@ -27,6 +27,8 @@ public interface BatteryCompartmentMapper extends BaseMapper
*/
IPage findPage(Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper);
+ List findList( @Param(Constants.WRAPPER) QueryWrapper queryWrapper);
+
BatteryCompartmentDTO getInfo(@Param("id")Integer id);
List findChargingPositionIds(@Param("notAllPower") Boolean isNotAllPower);
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mapper/MessageMqttMapper.java b/web-server/src/main/java/com/evotech/hd/webserver/mapper/MessageMqttMapper.java
new file mode 100644
index 0000000..1bb05c9
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mapper/MessageMqttMapper.java
@@ -0,0 +1,30 @@
+package com.evotech.hd.webserver.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Constants;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.evotech.hd.core.dtos.system.LogDTO;
+import com.evotech.hd.core.dtos.system.MessageMqttDTO;
+import com.evotech.hd.core.entity.system.Log;
+import com.evotech.hd.core.entity.system.MessageMqtt;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 接口
+ *
+ * @ClassName:LogMapper
+ * @date: 2025年08月18日 14:45
+ * @author: andy.shi
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+public interface MessageMqttMapper extends BaseMapper {
+ /**
+ * 获日志列表
+ *
+ * @param queryWrapper
+ * @return
+ */
+ IPage findPage(Page page, @Param(Constants.WRAPPER) QueryWrapper queryWrapper);
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MessageUtilService.java b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MessageUtilService.java
index 2ca026e..1717c9d 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MessageUtilService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MessageUtilService.java
@@ -2,10 +2,14 @@ package com.evotech.hd.webserver.mqtt;
import cn.hutool.crypto.Mode;
import cn.hutool.crypto.Padding;
+import cn.hutool.crypto.SecureUtil;
+import cn.hutool.crypto.asymmetric.KeyType;
+import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.symmetric.AES;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
+import com.evotech.hd.utils.Global;
import com.evotech.hd.webserver.config.redis.utils.RedisUtil;
import com.evotech.hd.webserver.utils.ParamUtils;
import lombok.extern.slf4j.Slf4j;
@@ -22,6 +26,13 @@ public class MessageUtilService {
@Resource
private RedisUtil redisUtil;
+ public JSONObject decryptEncryptKeyReqMessage(MqttMessage message) {
+ byte[] payload = message.getPayload();
+ RSA rsa = SecureUtil.rsa(Global.newInstance().getCloudPrivateKey(), null);
+ byte[] decrypt = rsa.decrypt(new String(payload), KeyType.PrivateKey);
+ return JSONUtil.parseObj(new String(decrypt));
+ }
+
/**
* 解密AES类型的消息
* @param topic
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttMessageHandleService.java b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttMessageHandleService.java
index d6e141e..eed14f5 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttMessageHandleService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttMessageHandleService.java
@@ -3,8 +3,11 @@ package com.evotech.hd.webserver.mqtt;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.evotech.hd.webserver.job.service.ExecutionBatterySwapService;
+import com.evotech.hd.webserver.mqtt.enums.MqttMessageTypeEnum;
import com.evotech.hd.webserver.service.BatteryStrategyService;
+import com.evotech.hd.webserver.service.MessageMqttService;
import com.evotech.hd.webserver.service.OrderReservationService;
+import com.evotech.hd.webserver.utils.ParamUtils;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.stereotype.Service;
@@ -24,25 +27,42 @@ public class MqttMessageHandleService {
BatteryStrategyService batteryStrategyService;
@Resource
ExecutionBatterySwapService executionBatterySwapService;
+ @Resource
+ MessageMqttService messageMqttService;
public void handle(MessageTopic topic, MqttMessage message) throws Exception {
+ //获取秘钥
+ if (MqttMessageTypeEnum.ENCRYRESP.getType().equals(topic.getMessageType())) {
+ ParamUtils.encryptKeyReq(messageUtilService.decryptEncryptKeyReqMessage(message));
+ return;
+ }
+ // 2. keepalive不加密,单独处理
+ if (MqttMessageTypeEnum.KEEPALIVE.getType().equals(topic.getMessageType())) {
+ JSONObject jo = JSONUtil.parseObj(message);
+ MqttMessageHeader header = new MqttMessageHeader();
+ header.setFunction(MqttMessageTypeEnum.KEEPALIVE.getType());
+ jo.set("header", JSONUtil.parseObj(header));
+ messageMqttService.update(null, topic, null, 2, jo);
+ return;
+ }
+
JSONObject jo = messageUtilService.decryptAesMessage(topic, message);
- MqttMessageHeader header = JSONUtil.toBean(jo.getJSONObject("header"), MqttMessageHeader.class);
- com.alibaba.fastjson2.JSONObject dataBody = com.alibaba.fastjson2.JSONObject.parseObject(jo.getStr("dataBody"));
- //站端比较特殊, 只有2个mq消息, 1个是下发预约单, 一个是点击开始
- //不做特殊设计, 直接if-else 判定就好了
- if ("pushReservation".equalsIgnoreCase(header.getFunction())){
- //接收云端订单
- orderReservationService.acceptReservations(dataBody);
- }else if("BatterySwapReq".equalsIgnoreCase(header.getFunction())){
- //接收云端的开始换电, 启动对中机构
- try {
- executionBatterySwapService.activateAlignmentMechanism();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }else if("chargingStrategy".equalsIgnoreCase(header.getFunction())){
- batteryStrategyService.manageCloudData(dataBody);
+ MqttMessageHeader header = JSONUtil.toBean(jo.getJSONObject("header"), MqttMessageHeader.class);
+ com.alibaba.fastjson2.JSONObject dataBody = com.alibaba.fastjson2.JSONObject.parseObject(jo.getStr("dataBody"));
+ //站端比较特殊, 只有2个mq消息, 1个是下发预约单, 一个是点击开始
+ //不做特殊设计, 直接if-else 判定就好了
+ if ("pushReservation".equalsIgnoreCase(header.getFunction())){
+ //接收云端订单
+ orderReservationService.acceptReservations(dataBody);
+ }else if("BatterySwapReq".equalsIgnoreCase(header.getFunction())){
+ //接收云端的开始换电, 启动对中机构
+ try {
+ executionBatterySwapService.activateAlignmentMechanism();
+ } catch (Exception e) {
+ e.printStackTrace();
}
+ }else if("chargingStrategy".equalsIgnoreCase(header.getFunction())){
+ batteryStrategyService.manageCloudData(dataBody);
+ }
}
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttPublishUtils.java b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttPublishUtils.java
index b58ca50..fc2ff32 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttPublishUtils.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/MqttPublishUtils.java
@@ -2,6 +2,7 @@ package com.evotech.hd.webserver.mqtt;
import cn.hutool.json.JSONObject;
import com.evotech.hd.webserver.config.mqtt.MqttPublishMessage;
+import com.evotech.hd.webserver.mqtt.enums.MqttMessageTypeEnum;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -23,12 +24,22 @@ public class MqttPublishUtils {
this.mqttPublishMessage = mqttPublishMessage;
}
+ public static void sendKeepalive(){
+ mqttPublishMessage.publishKeepaliveMessage();
+ }
+
+ public static void sendEncryptKeyReq(){
+ MessageTopic topic = new MessageTopic();
+ topic.setMessageType(MqttMessageTypeEnum.ENCRYREQ.getType());
+ mqttPublishMessage.publishRSAMessage(topic);
+ }
+
public static void sendState(String messageType, JSONObject dataBody){
MessageTopic topic = new MessageTopic();
- topic.setMessageType("state");
+ topic.setMessageType(MqttMessageTypeEnum.STATE.getType());
MqttMessageHeader header = new MqttMessageHeader();
header.setTimeStamp(String.valueOf(System.currentTimeMillis()));
- header.setIndex("1");
+ header.setIndex(MqttMessageTypeEnum.STATE.getId());
header.setFunction(messageType);
mqttPublishMessage.publishAESMessage(topic,header, dataBody);
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/mqtt/enums/MqttMessageTypeEnum.java b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/enums/MqttMessageTypeEnum.java
new file mode 100644
index 0000000..5cc0854
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/mqtt/enums/MqttMessageTypeEnum.java
@@ -0,0 +1,45 @@
+package com.evotech.hd.webserver.mqtt.enums;
+
+/**
+ * 如下 8 种类型:
+ 1)state 换电站状态类信息,站控发送,支持变化实时上送、周期上送和查询上
+送三种方式,云平台无需回复。云平台可根据需要随时向站控系统召唤状态类信息。
+ 2)event 事件类信息,站控发送,包括故障告警事件记录、充换电事件记录等, 事件发生时上送,需接收者回复确认,站控 15 秒内收不到回复则要重复发送,直到收
+到云平台的回复。云平台可通过召唤历史事件流水号的方式,检查事件是否丢失。
+ 3)confirm 事件确认回复,云平台收到事件后的回复信息。
+ 4)request 主动请求,云平台、站控均可发起请求。
+ 5)response 收到请求后,接收者的回复。
+ 6)keepalive 心跳报文,站控周期发送,周期30秒,云平台收到后立即回复。报文内容为当前时标字符串:“yyyy-MM-dd hh:mm:ss”。云平台和站控连续 3 个周期收不到对方的任何报文,则认为通信中断。通信中断后,站控不发送心跳外的任何报文,直到收到心跳回复报文。
+ 7)encryptKeyReq 站控发送,请求密钥。
+ 8)encryptKeyResp 云平台回复站控的密钥请求。
+ *
+ */
+public enum MqttMessageTypeEnum {
+
+ STATE("1", "state"),
+ EVENT("2", "event"),
+ CONFIRM("3", "confirm"),
+ REQUEST("4", "request"),
+ RESPONSE("5", "response"),
+ KEEPALIVE("6", "keepalive"),
+ ENCRYREQ("7", "encryptKeyReq"),
+ ENCRYRESP("8", "encryptKeyResp");
+
+
+ String id;
+ String type;
+
+ public String getId() {
+ return id;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ MqttMessageTypeEnum(String id, String type) {
+ this.id = id;
+ this.type = type;
+ }
+
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/BatteryCompartmentService.java b/web-server/src/main/java/com/evotech/hd/webserver/service/BatteryCompartmentService.java
index bf6787e..91a0cf8 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/BatteryCompartmentService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/BatteryCompartmentService.java
@@ -33,6 +33,8 @@ public interface BatteryCompartmentService extends IService
* @return
*/
IPage findPageList(Page page, QueryWrapper queryWrapper);
+
+ List findList( QueryWrapper queryWrapper);
/***
* 获取非全额充电中的仓位信息
* @return
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/MessageMqttService.java b/web-server/src/main/java/com/evotech/hd/webserver/service/MessageMqttService.java
new file mode 100644
index 0000000..cc0969b
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/MessageMqttService.java
@@ -0,0 +1,15 @@
+package com.evotech.hd.webserver.service;
+
+import cn.hutool.json.JSONObject;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.evotech.hd.core.dtos.Result;
+import com.evotech.hd.core.entity.system.MessageMqtt;
+import com.evotech.hd.webserver.mqtt.MessageTopic;
+
+public interface MessageMqttService extends IService {
+
+ public Result addResultId(String stationCode);
+
+ public Result update(Integer id, MessageTopic topic, String messageId, int qos, JSONObject jo);
+
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/OrderSwapService.java b/web-server/src/main/java/com/evotech/hd/webserver/service/OrderSwapService.java
index 9d2e0c5..32e4436 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/OrderSwapService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/OrderSwapService.java
@@ -8,6 +8,7 @@ import com.evotech.hd.core.dtos.Result;
import com.evotech.hd.core.dtos.business.OrderSwapDTO;
import com.evotech.hd.core.entity.business.OrderReservation;
import com.evotech.hd.core.entity.business.OrderSwap;
+import org.springframework.web.bind.annotation.RequestBody;
import java.io.Serializable;
@@ -35,4 +36,6 @@ public interface OrderSwapService extends IService {
Result sendOrderCompleted(Serializable orderId);
Result updateOrderSwapDTO(OrderSwapDTO orderSwapDTO) throws Exception ;
+
+ Result close(OrderSwapDTO orderSwapDTO) throws Exception;
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/ParamsService.java b/web-server/src/main/java/com/evotech/hd/webserver/service/ParamsService.java
index 35dfa00..f1caf48 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/ParamsService.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/ParamsService.java
@@ -31,4 +31,6 @@ public interface ParamsService extends IService {
ParamsDTO getParamsDTOByCode(String code);
ParamsDTO saveParamsDTO(ParamsDTO paramsDTO);
+
+ ParamsDTO getOrUpdateParamsDTO(String name, String code, String defVal, String des);
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/BatteryCompartmentServiceImpl.java b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/BatteryCompartmentServiceImpl.java
index 5888742..f56fe19 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/BatteryCompartmentServiceImpl.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/BatteryCompartmentServiceImpl.java
@@ -77,6 +77,12 @@ public class BatteryCompartmentServiceImpl extends ServiceImpl findList(QueryWrapper queryWrapper) {
+ queryWrapper.orderByAsc("a.id");// 根据预约日期和预约时间段倒序排序
+ return getBaseMapper().findList( queryWrapper);
+ }
+
@Override
public List findChargingPositionIds(Boolean isNotAllPower) {
return getBaseMapper().findChargingPositionIds(isNotAllPower);
@@ -133,7 +139,7 @@ public class BatteryCompartmentServiceImpl extends ServiceImpl0){
//检查充电机 PS: 这种情况是不会出现的, 但是以防万一, 做个处理, 不做数据调整, 但是需要返回异常信息,需要站控人员调整
- if(!InstructionReadUtils.queryBatExist(id)){
+ if(!InstructionReadUtils.checkExistsBattery(String.valueOf(id))){
return Result.getInstance().build(Boolean.class).error("当前仓位返回没有电池, 请确认电池是否存在,或者是否对接到位", false);
}
//下发充电
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/MessageMqttServiceImpl.java b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/MessageMqttServiceImpl.java
new file mode 100644
index 0000000..b53cbb4
--- /dev/null
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/MessageMqttServiceImpl.java
@@ -0,0 +1,64 @@
+package com.evotech.hd.webserver.service.impl;
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.evotech.hd.core.dtos.Result;
+import com.evotech.hd.core.dtos.system.LogDTO;
+import com.evotech.hd.core.entity.system.Log;
+import com.evotech.hd.core.entity.system.MessageMqtt;
+import com.evotech.hd.webserver.mapper.LogMapper;
+import com.evotech.hd.webserver.mapper.MessageMqttMapper;
+import com.evotech.hd.webserver.mqtt.MessageTopic;
+import com.evotech.hd.webserver.mqtt.MqttMessageHeader;
+import com.evotech.hd.webserver.service.LogService;
+import com.evotech.hd.webserver.service.MessageMqttService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 类
+ *
+ * @ClassName:LogServiceImpl
+ * @date: 2025年08月18日 14:44
+ * @author: andy.shi
+ * @remark: 开发人员联系方式 1042025947@qq.com/微信同步
+ */
+@Service
+public class MessageMqttServiceImpl extends ServiceImpl implements MessageMqttService {
+
+ @Override
+ public Result addResultId(String stationCode) {
+ MessageMqtt messageMqtt = new MessageMqtt();
+ messageMqtt.setStationCode(stationCode);
+ if(save(messageMqtt)){
+ return Result.getInstance().build(Integer.class).success(messageMqtt.getId());
+ }
+ return Result.getInstance().build(Integer.class).error("保存失败");
+ }
+
+ @Override
+ public Result update(Integer id, MessageTopic topic, String messageId, int qos, JSONObject jo) {
+ MqttMessageHeader header = JSONUtil.toBean(jo.getJSONObject("header"), MqttMessageHeader.class);
+ MessageMqtt mm = getById(id);
+ if(mm == null){
+ mm = new MessageMqtt();
+ }
+ mm.setContent(jo.toJSONString(0));
+ mm.setDirection(topic.getDataDirection());
+ if(header != null){
+ mm.setMessageFunction(header.getFunction());
+ }
+ mm.setMessageId(messageId);
+ mm.setQos(qos);
+ mm.setStationCode(topic.getStationCode());
+ mm.setTopic(topic.toString());
+ mm.setType(topic.getMessageType());
+ if(saveOrUpdate(mm)){
+ return Result.getInstance().build(MessageMqtt.class).success(mm);
+ }
+ return Result.getInstance().build(MessageMqtt.class).error("更改失败");
+ }
+}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderReservationServiceImpl.java b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderReservationServiceImpl.java
index 0f161a3..545c50a 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderReservationServiceImpl.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderReservationServiceImpl.java
@@ -74,7 +74,8 @@ public class OrderReservationServiceImpl extends ServiceImpl result = CloudSendInfoUtils.sendOrderReservation(Collections.asMap("source",orderReservationDTO.getSource(),"stationCode",ParamUtils.findStationCode(),"stationName",ParamUtils.findStationName(),"reservationTime",orderReservationDTO.getReservationTime(),"swapDay",DateUtils.parseDateToStr("yyyyMMdd", reservationTime),"swapDuration",orderReservationDTO.getSwapDuration(),"uname",orderReservationDTO.getReservationName(),"phone",orderReservationDTO.getReservationPhone(),"plateNum",orderReservationDTO.getPlateNum()));
+ //"stationCode",ParamUtils.findStationCode(),"stationName",ParamUtils.findStationName(),
+ Result result = CloudSendInfoUtils.sendOrderReservation(Collections.asMap("source",orderReservationDTO.getSource(),"reservationTime",orderReservationDTO.getReservationTime(),"swapDay",DateUtils.parseDateToStr("yyyyMMdd", reservationTime),"swapDuration",orderReservationDTO.getSwapDuration(),"uname",orderReservationDTO.getReservationName(),"phone",orderReservationDTO.getReservationPhone(),"plateNum",orderReservationDTO.getPlateNum()));
JSONObject cloudResult = ResultUtil.getValue(result);
if(cloudResult != null){
//防止并发, 停止车牌机扫描,
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderSwapServiceImpl.java b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderSwapServiceImpl.java
index 67b898d..c553c82 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderSwapServiceImpl.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/OrderSwapServiceImpl.java
@@ -1,5 +1,6 @@
package com.evotech.hd.webserver.service.impl;
+import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
@@ -8,6 +9,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evotech.hd.core.dtos.Result;
import com.evotech.hd.core.dtos.ResultUtil;
+import com.evotech.hd.core.dtos.business.AccessStrategyDTO;
import com.evotech.hd.core.dtos.business.BatterySwapStepDTO;
import com.evotech.hd.core.dtos.business.OrderSwapDTO;
import com.evotech.hd.core.entity.business.Battery;
@@ -16,9 +18,14 @@ import com.evotech.hd.core.entity.business.OrderSwap;
import com.evotech.hd.core.enums.OrderStatusEnums;
import com.evotech.hd.core.enums.SwapBatteryStepEnum;
import com.evotech.hd.core.mapstruct.OrderSwapWrapper;
+import com.evotech.hd.exception.InstructionException;
import com.evotech.hd.utils.Collections;
import com.evotech.hd.utils.CommonUtil;
+import com.evotech.hd.webserver.config.redis.utils.RedisUtil;
+import com.evotech.hd.webserver.job.JobConstant;
+import com.evotech.hd.webserver.job.entity.QuartzJobInfo;
import com.evotech.hd.webserver.job.service.ExecutionBatterySwapService;
+import com.evotech.hd.webserver.job.service.QuartzJobService;
import com.evotech.hd.webserver.mapper.OrderSwapMapper;
import com.evotech.hd.webserver.service.BatteryCompartmentService;
import com.evotech.hd.webserver.service.BatteryService;
@@ -26,7 +33,10 @@ import com.evotech.hd.webserver.service.BatterySwapStepService;
import com.evotech.hd.webserver.service.OrderSwapService;
import com.evotech.hd.webserver.utils.AccessStrategyUtil;
import com.evotech.hd.webserver.utils.ParamUtils;
+import com.evotech.hd.webserver.utils.instruction.InstructionReadUtils;
+import com.evotech.hd.webserver.utils.instruction.InstructionWriteUtils;
import com.evotech.hd.webserver.utils.sendCloud.CloudSendInfoUtils;
+import com.evotech.hd.webserver.websocket.controller.WebSocketUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
@@ -35,8 +45,13 @@ import org.springframework.stereotype.Service;
import java.io.Serializable;
import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/**
@@ -61,6 +76,8 @@ public class OrderSwapServiceImpl extends ServiceImpl findPageList(Page page, QueryWrapper queryWrapper) {
@@ -195,6 +212,60 @@ public class OrderSwapServiceImpl extends ServiceImpl close(OrderSwapDTO orderSwapDTO) throws Exception {
+ AccessStrategyDTO accessStrategyDTO = AccessStrategyUtil.getValidAccessStrategyDTO();
+ if(accessStrategyDTO.getBatteryPrefetching() && AccessStrategyUtil.getEffectiveRgvNoList(accessStrategyDTO).size() > 1){
+ //重置预取标识
+ RedisUtil.set("buildTakeFuture", false);
+ //将电池送回仓位
+ Map resultMap = JSON.to(Map.class, RedisUtil.get("rgvInfo"));
+ //获取格位信息
+ if(executionBatterySwapService.buildPutFuture(resultMap.get("loadingRgv"), Integer.valueOf(resultMap.get("takeNo")), orderSwapDTO.getId()).join()){
+ //存完之后, 关闭订单信息
+ orderSwapDTO.setStatus(OrderStatusEnums.CANCLE.getCode());
+ if(updateById(orderSwapWrapper.toEntity(orderSwapDTO))){
+ //预取结果重置为false
+ RedisUtil.set("buildTakeFuture", false);
+ //重置rgv信息
+ RedisUtil.set("rgvInfo", JSONObject.toJSONString(Collections.emptyMap()));
+ //关闭车辆到位检查
+ quartzJobService.pauseJob(new QuartzJobInfo(JobConstant.ARRIVAL_SIGNAL_JOB, JobConstant.GroupEnum.SWAP_GROUP.getType()));
+ //打开出口闸门, 执行开门操作
+ InstructionWriteUtils.openRolling(ParamUtils.getDoorParams("出口"));
+ //打开车牌机扫描
+ quartzJobService.resumeJob(JobConstant.LICENSE_PLATE_MACHINE_JOB, JobConstant.GroupEnum.SWAP_GROUP.getType());
+ //推送云端, 订单关闭
+ CloudSendInfoUtils.closeOrderStatus(Collections.asMap("pkId", orderSwapDTO.getCloudOrderId(), "status", orderSwapDTO.getStatus()));
+ //推送空对象推送websocket, 刷新首页数据
+ WebSocketUtils.broadCastMessage(JSONObject.toJSONString(Collections.asMap("method", "order", "data", JSONObject.toJSONString(new OrderSwapDTO((AccessStrategyUtil.getEffectiveRgvNoList(accessStrategyDTO).size()))))));
+ //关门
+ CompletableFuture.runAsync(
+ () -> {
+ //关闭进门栏杆
+ try {
+ InstructionWriteUtils.closeRolling(ParamUtils.getDoorParams("出口"));
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ },
+ // 延迟执行器:延迟 5 分钟
+ CompletableFuture.delayedExecutor(ParamUtils.getVehicleAbdicationWaitingMilliseconds(), TimeUnit.MILLISECONDS)
+ );
+
+
+ }
+ }
+
+ }
+// else{
+// result = calculationPosition(accessStrategyDTO);
+// }
+
+
+ return Result.getInstance().build(Boolean.class).success(true);
+ }
+
// public static void sendCloud(final Integer id){
// CompletableFuture.runAsync(() -> {
// try {
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/ParamsServiceImpl.java b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/ParamsServiceImpl.java
index 1119bc1..53fa53a 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/service/impl/ParamsServiceImpl.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/service/impl/ParamsServiceImpl.java
@@ -10,6 +10,7 @@ import com.evotech.hd.core.entity.system.Params;
import com.evotech.hd.core.mapstruct.ParamsWrapper;
import com.evotech.hd.core.enums.CacheNames;
import com.evotech.hd.webserver.mapper.ParamsMapper;
+import com.evotech.hd.webserver.mqtt.MqttPublishUtils;
import com.evotech.hd.webserver.service.ParamsService;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
@@ -64,7 +65,6 @@ public class ParamsServiceImpl extends ServiceImpl implemen
@Override
@Cacheable(cacheNames = CacheNames.SYSTEM_RUNNING_PARAMS, key = "#code")
-// @CacheEvict(value = CacheNames.SYSTEM_RUNNING_PARAMS, key = "#code", allEntries = true)
public ParamsDTO getParamsDTOByCode(String code) {
Params param = getOne(new LambdaQueryWrapper().eq(Params::getParamCode, code), false);
return paramsWrapper.toDTO(param);
@@ -75,12 +75,34 @@ public class ParamsServiceImpl extends ServiceImpl implemen
}
@Override
-// @Cacheable(cacheNames = CacheNames.SYSTEM_RUNNING_PARAMS, key = "#paramsDTO.paramCode")
@CacheEvict(value = CacheNames.SYSTEM_RUNNING_PARAMS, allEntries = true)
public ParamsDTO saveParamsDTO(ParamsDTO paramsDTO) {
saveOrUpdate(paramsWrapper.toEntity(paramsDTO));
+ //如果当前是参数设置, 并且当前操作的是站点编码, 则更新秘钥
+ if(Integer.valueOf(1).equals(paramsDTO.getGroupId()) && "station_code".equals(paramsDTO.getParamCode())){
+ MqttPublishUtils.sendEncryptKeyReq();
+ }
return paramsDTO;
}
+ @Override
+ @CacheEvict(value = CacheNames.SYSTEM_RUNNING_PARAMS, allEntries = true)
+ @Cacheable(cacheNames = CacheNames.SYSTEM_RUNNING_PARAMS, key = "#code")
+ public ParamsDTO getOrUpdateParamsDTO(String name, String code, String defVal, String des) {
+ Params param = getOne(new LambdaQueryWrapper().eq(Params::getParamCode, code), false);
+ if(ObjectUtils.isEmpty(param)){
+ param = new Params();
+ param.setName(name);
+ param.setParamCode(code);
+ param.setParamValue(defVal);
+ param.setDescription(des);
+ save(param);
+ }else{
+ param.setParamValue(defVal);
+ updateById(param);
+ }
+ return paramsWrapper.toDTO(param);
+ }
+
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/utils/AccessStrategyUtil.java b/web-server/src/main/java/com/evotech/hd/webserver/utils/AccessStrategyUtil.java
index 397bc43..5097fc1 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/utils/AccessStrategyUtil.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/utils/AccessStrategyUtil.java
@@ -7,6 +7,7 @@ import com.evotech.hd.webserver.service.AccessStrategyService;
import com.evotech.hd.webserver.utils.sendCloud.CloudSendInfoUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
+import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@@ -44,4 +45,11 @@ public class AccessStrategyUtil {
return Collections.emptyList();
}
+ public static List getEffectiveRgvNoList(@NotNull AccessStrategyDTO accessStrategyDTO){
+ if(StringUtils.isNotEmpty(accessStrategyDTO.getEffectiveRgvNo())){
+ return Collections.asList(accessStrategyDTO.getEffectiveRgvNo().split(","));
+ }
+ return Collections.emptyList();
+ }
+
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/utils/ParamUtils.java b/web-server/src/main/java/com/evotech/hd/webserver/utils/ParamUtils.java
index 0e65aed..70f856d 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/utils/ParamUtils.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/utils/ParamUtils.java
@@ -54,11 +54,6 @@ public class ParamUtils {
* 站端私钥
*/
static final String STATION_SECRET_KEY = "station_secret_key";
- /***
- * 站端公钥
- */
- static final String STATION_PUBLIC_KEY = "station_public_key";
-
/***
* 站端AES私钥
*/
@@ -149,15 +144,6 @@ public class ParamUtils {
ParamsDTO param= paramService.getParamsDTO("站点私钥", ParamsConstant.STATION_SECRET_KEY,"MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAKXEG3/V8DUxpOzb8lJLkJaZGAHSfS+oHoPzZy+Xbr7mb8Jfc7tXRd+H1mmQOXz36HGdPiMP7nK1kPr+ddEJe+yofCkpr5y/Mavki9cLQ3Z/BHUH/t0E7mjyXKhlyn7pfudlW7rqNfQx3eboir+9ppgFe0knW6xHffFECIdfmrt9AgMBAAECgYARw9AMpbFeCgl6RuIT1rxSn2qWu2emJVbL3liHHawFMm30v0UIZUR8PbMJUicPEQRstKTVnh34ViQI+h9HPUR1/rmdI/jdM2n44ai+4AvT1iONgLS4JBBpc5a+ctV9uAgfSU65cRVAzKTzq3Etcqwgzrn8sWultKAyb3pHmjeYswJBANFHjh5LfGSSEpAOdfcNopNAGSaEhNKpm2/0f1VwEyM3/utpTMfHVo/M2OtdpU7JH0+BdtJfAEXtMOMAfzka6EcCQQDKxbuEeYit5zqTbsMLG9y016KjH6oySPnCL4RnA1eeCwK9j0LuYC+rhBg8Km2iLsDwoUDZUjaX/oipB1Ydc+QbAkEAjCG4tOpgucrhqRo1vR6hLK4v6Q21DoZJMXbqyF/KQLve8uzIX8FHYfSNj1ReO1oKoCcVVBoOycPgBzAvACLXQwJBAMCbyl8vwnDN74oT8BkhQihVnBsu/M//GZ8m27GuLw/kjZnZ903O9/kH5K1h7/naR1NLGPpVaZ4/HTjRyy724nkCQQDLEogix/P5ZwI6RmKKAkyyZkMPJIn9kA1j/zeFACdVBzar87GB4DNHiuwByzL4V/CLnQOEocpoq5PciXy2Nbi6","软件初始安装时, 直接初始化");
return param.getParamValue();
}
- /***
- * 站点公钥
- * @return
- */
- public static String findStationPublicKey(){
- ParamsDTO param= paramService.getParamsDTO("站点公钥", ParamsConstant.STATION_PUBLIC_KEY,"MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQClxBt/1fA1MaTs2/JSS5CWmRgB0n0vqB6D82cvl26+5m/CX3O7V0Xfh9ZpkDl89+hxnT4jD+5ytZD6/nXRCXvsqHwpKa+cvzGr5IvXC0N2fwR1B/7dBO5o8lyoZcp+6X7nZVu66jX0Md3m6Iq/vaaYBXtJJ1usR33xRAiHX5q7fQIDAQAB","软件初始安装时, 直接初始化");
- return param.getParamValue();
- }
-
/***
* 站点对称AES私钥
* @return
@@ -391,4 +377,20 @@ public class ParamUtils {
return paramService.getParamsDTOByCode(code);
}
+ public static void encryptKeyReq(cn.hutool.json.JSONObject jsonObject){
+ try {
+ String encryptVector = jsonObject.getStr("encryptVector");
+ if(StringUtils.isNotEmpty(encryptVector)){
+ paramService.getOrUpdateParamsDTO("站点AES私钥", ParamsConstant.STATION_AES_SECRET_KEY,encryptVector,"软件初始安装时, 直接初始化");
+ }
+ String encryptKey = jsonObject.getStr("encryptKey");
+ if(StringUtils.isNotEmpty(encryptKey)){
+ paramService.getOrUpdateParamsDTO("站点AES公钥", ParamsConstant.STATION_AES_PUBLIC_KEY,encryptKey,"软件初始安装时, 直接初始化");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ log.error("更新站控的AES秘钥出现异常", e.getMessage());
+ }
+ }
+
}
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/utils/instruction/InstructionReadUtils.java b/web-server/src/main/java/com/evotech/hd/webserver/utils/instruction/InstructionReadUtils.java
index 6dc14d2..c1f7d39 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/utils/instruction/InstructionReadUtils.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/utils/instruction/InstructionReadUtils.java
@@ -107,17 +107,6 @@ public class InstructionReadUtils {
return InstructionUtils.getJson(execution(paramsDTO, String.valueOf(batteryCompartmentNo)));
}
- /*** 检查电池仓是否存在电池
- * @param: batteryCompartmentNo
- * @return true 存在 false 不存在
- */
- public static Boolean queryBatExist(Integer batteryCompartmentNo) throws InstructionException {
- ParamsDTO paramsDTO = ParamUtils.getParamsDTO(ParamSysConstants.EXISTS_BATTERY);
- return InstructionUtils.getBoolean(paramsDTO, executionInteger(paramsDTO, String.valueOf(batteryCompartmentNo)));
-
- }
-
-
/*** 检查空调是否连接
* @return true 连接 false 未连接
*/
@@ -406,7 +395,9 @@ public class InstructionReadUtils {
}
- /***消防设备是否连接
+ /*** 检查电池仓是否存在电池
+ * @param: batteryCompartmentNo
+ * @return true 存在 false 不存在
*/
public static Boolean checkExistsBattery(String batteryCompartmentNo) throws InstructionException {
ParamsDTO paramsDTO = ParamUtils.getParamsDTO(ParamSysConstants.BSL_BAT_EXIST);
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/CloudSendInfoUtils.java b/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/CloudSendInfoUtils.java
index f300341..f15c0f0 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/CloudSendInfoUtils.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/CloudSendInfoUtils.java
@@ -1,5 +1,6 @@
package com.evotech.hd.webserver.utils.sendCloud;
+import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@@ -7,6 +8,7 @@ import com.evotech.hd.core.dtos.Result;
import com.evotech.hd.utils.Collections;
import com.evotech.hd.webserver.logging.AsyncLogService;
import com.evotech.hd.webserver.logging.LogUtils;
+import com.evotech.hd.webserver.mqtt.MqttPublishUtils;
import com.evotech.hd.webserver.utils.ParamUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.HttpClient;
@@ -86,16 +88,6 @@ public class CloudSendInfoUtils {
return JSONObject.parseObject(result.toString(),Result.class);
}
- /***
- * 站端获取预约单数据
- * @param map
- * @return
- */
- public static Result findOrderReservationList(Map map){
- JSONObject result = send("获取云端预约单数据", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"orderSwapBatteryPreProcessor","findOrderSwapBatteryPre"))));
- return JSONObject.parseObject(result.toString(),Result.class);
- }
-
/***
* 站端推送预约单数据状态
* @param map
@@ -121,19 +113,33 @@ public class CloudSendInfoUtils {
* @param map
* @return
*/
- public static void sendAlarm(Map map){
+ public static void sendAlarm(Map map, Boolean effectBatterySwapping){
+ map.put("state", effectBatterySwapping ? 3 : (ParamUtils.findStationRunningStatus() ? 1 : 3));
+ MqttPublishUtils.sendState("stationState", JSONUtil.parseObj(map));
+
//结合云端接口增加站端运行状态
- map.put("state", (ParamUtils.findStationRunningStatus() ? 1 : 3));
- send("推送告警信息", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"alarmProcessor","alarmMessage"))));
+ //如果影响换电, 直接给3 进入检修, 如果不影响, 则检查当前站端的运行状态
+// map.put("state", effectBatterySwapping ? 3 : (ParamUtils.findStationRunningStatus() ? 1 : 3));
+// send("推送告警信息", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"alarmProcessor","alarmMessage"))));
}
/***
- * 站端推送车辆到位信息
+ * 站端推送换电步骤信息
* @param map
* @return
*/
public static Result sendArrivalSignal(Map map){
- JSONObject result = send("创建订单", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"orderSwapProcessor","arrivalSignal"))));
+ JSONObject result = send("换电步骤", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"orderSwapProcessor","arrivalSignal"))));
+ return JSONObject.parseObject(result.toString(),Result.class);
+ }
+
+ /***
+ * 订单关闭
+ * @param map
+ * @return
+ */
+ public static Result closeOrderStatus(Map map){
+ JSONObject result = send("订单关闭", JSONObject.parseObject(JSONObject.toJSONString(buildBaseInfo(map,"orderSwapProcessor","closeOrderStatus"))));
return JSONObject.parseObject(result.toString(),Result.class);
}
@@ -190,7 +196,7 @@ public class CloudSendInfoUtils {
}
public static void sendAlarmWx(Map map){
- JSONObject result = doPost("https://api.evo-techina.com/cloud/alarm/send/hq_web", map, Collections.asMap("Content-Type", "application/json","Accept-Language", "zh-CN"));
+ doPost("https://api.evo-techina.com/cloud/alarm/send/hq_web", map, Collections.asMap("Content-Type", "application/json","Accept-Language", "zh-CN"));
}
private static JSONObject doPost(String url, Map map, Map headersMap) {
diff --git a/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/RsaEcbPkcsFullUtil.java b/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/RsaEcbPkcsFullUtil.java
index 6d8f745..3381b56 100644
--- a/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/RsaEcbPkcsFullUtil.java
+++ b/web-server/src/main/java/com/evotech/hd/webserver/utils/sendCloud/RsaEcbPkcsFullUtil.java
@@ -1,18 +1,10 @@
package com.evotech.hd.webserver.utils.sendCloud;
import cn.hutool.crypto.SecureUtil;
-import cn.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import com.evotech.hd.webserver.utils.ParamUtils;
-import javax.crypto.Cipher;
-import java.security.KeyFactory;
-import java.security.PrivateKey;
-import java.security.PublicKey;
-import java.security.Signature;
-import java.security.spec.PKCS8EncodedKeySpec;
-import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
/**
@@ -25,23 +17,6 @@ import java.util.Base64;
*/
public class RsaEcbPkcsFullUtil {
- // 签名算法:SHA256哈希 + RSA/ECB/PKCS1Padding
- private static final String SIGNATURE_ALGORITHM = "SHA256withRSA/ECB/PKCS1Padding";
- // RSA密钥算法
- private static final String KEY_ALGORITHM = "RSA";
- private static byte[] privateKeyStr = null;
- private static PrivateKey privateKey = null;
- private static PublicKey publicKey = null;
-// static{
-// try {
-// privateKeyStr = Base64.getDecoder().decode(ParamUtils.findStationSecretKey());
-// privateKey = base64ToPrivateKey();
-// publicKey = base64ToPublicKey();
-// } catch (Exception e) {
-// throw new RuntimeException(e);
-// }
-// }
-
/**
* 用私钥对消息签名(SHA256withRSA/ECB/PKCS1Padding)
* @param message 原始消息
@@ -52,92 +27,4 @@ public class RsaEcbPkcsFullUtil {
return Base64.getEncoder().encodeToString(sign.sign(message));
}
- /***
- * 私钥消息加密
- * @param message
- * @return
- * @throws Exception
- */
- public static String encrypt(String message) throws Exception {
-// e.getBytes("UTF-8"));
- return Base64.getEncoder().encodeToString(SecureUtil.desede(privateKeyStr).encrypt(message));
- }
-
-
- /**
- * 用公钥验证签名(SHA256withRSA/ECB/PKCS1Padding)
- * @param message 解密后的消息
- * @param signature 接收的签名(Base64编码)
- * @return 验证是否通过
- */
- public static boolean verify(String message, String signature) throws Exception {
- Signature verifier = Signature.getInstance(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue());
- verifier.initVerify(publicKey); // 公钥验证模式
- verifier.update(message.getBytes("UTF-8"));
- byte[] signBytes = Base64.getDecoder().decode(signature);
- return verifier.verify(signBytes);
- }
-
- /**
- * 用私钥解密消息(RSA/ECB/PKCS1Padding)
- * @param encryptedMessage 加密后的消息(Base64编码)
- * @return 解密后的原始消息
- */
- public static String decrypt(String encryptedMessage) throws Exception {
- Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue());
- cipher.init(Cipher.DECRYPT_MODE, privateKey); // 私钥解密模式
- byte[] encryptedBytes = Base64.getDecoder().decode(encryptedMessage);
- byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
- return new String(decryptedBytes, "UTF-8");
- }
-
-
- /***
- * 私钥消息加密
- * @param message
- * @return
- * @throws Exception
- */
- public static String encryptWithPrivateKey(String message) throws Exception {
-// Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue());
-// cipher.init(Cipher.ENCRYPT_MODE, privateKey); // 私钥加密模式
-// // 3. 加密并返回Base64结果
-// byte[] encryptedBytes = cipher.doFinal(message.getBytes("UTF-8"));
- return Base64.getEncoder().encodeToString(SecureUtil.desede(privateKeyStr).encrypt(message));
- }
-
- /**
- * 用公钥解密(私钥加密的数据必须用对应公钥解密)
- * @param encryptedMessage 加密后的消息(Base64)
- * @return 解密后的原始消息
- */
- public static String decryptWithPublicKey(String encryptedMessage) throws Exception {
- Cipher cipher = Cipher.getInstance(AsymmetricAlgorithm.RSA_ECB_PKCS1.getValue());
- cipher.init(Cipher.DECRYPT_MODE, publicKey); // 公钥解密模式
- byte[] encryptedBytes = Base64.getDecoder().decode(encryptedMessage);
- byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
- return new String(decryptedBytes, "UTF-8");
- }
-
-
- /**
- * Base64字符串私钥转为PrivateKey对象(PKCS#8格式)
- */
- private static PrivateKey base64ToPrivateKey() throws Exception {
- byte[] keyBytes = Base64.getDecoder().decode(ParamUtils.findStationSecretKey());
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); // 私钥用PKCS8规范
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- return keyFactory.generatePrivate(keySpec);
- }
-
- /**
- * Base64字符串转为PublicKey对象(X.509格式)
- */
- private static PublicKey base64ToPublicKey() throws Exception {
- byte[] keyBytes = Base64.getDecoder().decode(ParamUtils.findStationPublicKey());
- X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); // 公钥用X.509规范
- KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
- return keyFactory.generatePublic(keySpec);
- }
-
}
diff --git a/web-server/src/main/resources/application-dev.yml b/web-server/src/main/resources/application-dev.yml
index 2312033..6b28ab8 100644
--- a/web-server/src/main/resources/application-dev.yml
+++ b/web-server/src/main/resources/application-dev.yml
@@ -1,6 +1,6 @@
spring:
redis:
- host: 192.168.16.128
+ host: 192.168.5.112
port: 6379
database: 13
password: hbyt2025
@@ -17,7 +17,7 @@ spring:
# #连接池最大阻塞等待时间(使用负值表示没有限制)
max-wait: -1ms
mqtt:
- broker: tcp://192.168.16.128:1883 # MQTT服务器地址(如Mosquitto默认端口1883)
+ broker: tcp://192.168.5.112:1883 # MQTT服务器地址(如Mosquitto默认端口1883)
client-id: springboot-mqtt-${random.value} # 客户端ID(添加随机数确保唯一)
username: admin # 可选,MQTT服务器认证用户名
password: hbyt12345 # 可选,MQTT服务器认证密码
diff --git a/web-server/src/main/resources/application.yml b/web-server/src/main/resources/application.yml
index 02411e4..0f9f099 100644
--- a/web-server/src/main/resources/application.yml
+++ b/web-server/src/main/resources/application.yml
@@ -27,7 +27,7 @@ spring:
initialize-schema: always
job-store-type: jdbc
profiles:
- active: ${profiles.active:pro},mongo${profiles.active:},quartz #development
+ active: ${profiles.active:pro},mongo${profiles.active:},quartz,core #development
# 服务模块
devtools:
restart:
@@ -141,6 +141,8 @@ jwt:
accessToken:
expireTime: 1000000
+cloudPublicKey:
+
#
#mqtt:
# broker: tcp://192.168.16.128:1883 # MQTT服务器地址(如Mosquitto默认端口1883)
diff --git a/web-server/src/main/resources/mapper/AccessStrategyMapper.xml b/web-server/src/main/resources/mapper/AccessStrategyMapper.xml
index 0a4027d..4701d8e 100644
--- a/web-server/src/main/resources/mapper/AccessStrategyMapper.xml
+++ b/web-server/src/main/resources/mapper/AccessStrategyMapper.xml
@@ -4,7 +4,7 @@
id, `name`, create_time, extendeds,
- strategy,power_strategy, charging_strategy, instant_charge_power, minimum_safety_stock, effective_rgv_no, minimum_safety_stock,lowest_battery_swap_soc,full_of_limit_soc,
+ strategy,power_strategy, charging_strategy, instant_charge_power, minimum_safety_stock, effective_rgv_no, minimum_safety_stock,lowest_battery_swap_soc,full_of_limit_soc,battery_prefetching,
valid
diff --git a/web-server/src/main/resources/mapper/BaseMapper.xml b/web-server/src/main/resources/mapper/BaseMapper.xml
new file mode 100644
index 0000000..73b214e
--- /dev/null
+++ b/web-server/src/main/resources/mapper/BaseMapper.xml
@@ -0,0 +1,7 @@
+
+
+
+
+ a.id, a.`name`, a.create_time, a.extendeds
+
+
diff --git a/web-server/src/main/resources/mapper/BatteryCompartmentMapper.xml b/web-server/src/main/resources/mapper/BatteryCompartmentMapper.xml
index 852415c..f7aecac 100644
--- a/web-server/src/main/resources/mapper/BatteryCompartmentMapper.xml
+++ b/web-server/src/main/resources/mapper/BatteryCompartmentMapper.xml
@@ -72,6 +72,14 @@
${ew.customSqlSegment}
+
+