diff --git a/pom.xml b/pom.xml
index edb6138..a11c77b 100644
--- a/pom.xml
+++ b/pom.xml
@@ -75,6 +75,20 @@
fastjson2
2.0.42
+
+
+
+ com.dtflys.forest
+ forest-spring-boot-starter
+ 1.5.33
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.73
+
+
diff --git a/src/main/java/com/muyu/service/VehicleInstanceService.java b/src/main/java/com/muyu/service/VehicleInstanceService.java
index d14b083..9c8cc8a 100644
--- a/src/main/java/com/muyu/service/VehicleInstanceService.java
+++ b/src/main/java/com/muyu/service/VehicleInstanceService.java
@@ -23,11 +23,6 @@ public interface VehicleInstanceService {
*/
public void init(Vehicle vehicle);
- /**
- * 初始化链接客户端
- * @param vin 车辆VIN
- */
- public void initClient(String vin);
/**
* 车辆结果对象
diff --git a/src/main/java/com/muyu/service/impl/VehicleInstanceServiceImpl.java b/src/main/java/com/muyu/service/impl/VehicleInstanceServiceImpl.java
index ceaf33d..5b0d3cd 100644
--- a/src/main/java/com/muyu/service/impl/VehicleInstanceServiceImpl.java
+++ b/src/main/java/com/muyu/service/impl/VehicleInstanceServiceImpl.java
@@ -1,7 +1,6 @@
package com.muyu.service.impl;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
-import com.muyu.domain.PositionRouteInfo;
+import com.muyu.common.Result;
import com.muyu.domain.Vehicle;
import com.muyu.domain.model.PositionModel;
import com.muyu.domain.req.CheckPositionReq;
@@ -11,16 +10,20 @@ import com.muyu.domain.req.VehicleInstanceListReq;
import com.muyu.domain.resp.VehicleInstanceResp;
import com.muyu.service.PositionRouteService;
import com.muyu.service.VehicleInstanceService;
+import com.muyu.utils.MD5Util;
import com.muyu.vehicle.VehicleInstance;
+import com.muyu.vehicle.api.ClientAdmin;
+import com.muyu.vehicle.api.req.VehicleConnectionReq;
import com.muyu.vehicle.core.LocalContainer;
import com.muyu.vehicle.model.VehicleData;
import com.muyu.vehicle.model.properties.MqttProperties;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
import java.util.List;
+import java.util.UUID;
/**
* @author DongZeLiang
@@ -35,6 +38,12 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
@Autowired
private PositionRouteService positionRouteService;
+ @Autowired
+ private ClientAdmin clientAdmin;
+
+ @Value("${mqtt.server.host}")
+ private String broker;
+
/**
* 根据车辆生成车辆实例
*
@@ -49,23 +58,6 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
log.info("构建车辆对象: [{}]", vehicle.getVin());
}
- /**
- * 初始化链接客户端
- *
- * @param vin 车辆VIN
- */
- @Override
- public void initClient(String vin) {
- VehicleInstance vehicleInstance = LocalContainer.getVehicleInstance(vin);
- MqttProperties mqttProperties = MqttProperties.builder()
- .broker("tcp://fluxmq.muyu.icu:1883")
- .topic("test")
- .clientId(vin)
- .build();
- vehicleInstance.setMqttProperties(mqttProperties);
- vehicleInstance.initClient();
- }
-
/**
* 车辆结果对象
*
@@ -92,13 +84,25 @@ public class VehicleInstanceServiceImpl implements VehicleInstanceService {
if (vehicleInstance == null){
throw new RuntimeException("没有【"+vin+"】车辆");
}
- vehicleInstance.setMqttProperties(
- MqttProperties.builder()
- .broker("tcp://fluxmq.muyu.icu:1883")
- .topic("test")
- .clientId(vin)
- .build()
- );
+ String timestamp = String.valueOf(System.currentTimeMillis());
+ VehicleConnectionReq connectionReq = VehicleConnectionReq.builder()
+ .vin(vin)
+ .timestamp(timestamp)
+ .userName(MD5Util.encrypted(vin+timestamp))
+ .nonce(MD5Util.encrypted(UUID.randomUUID().toString().replace("-", "")))
+ .build();
+ Result result = clientAdmin.vehicleConnection(connectionReq);
+ if (result.getCode() != 200){
+ throw new RuntimeException("车辆:["+vin+"],连接异常:["+result.getMsg()+"]");
+ }
+ MqttProperties mqttProperties = MqttProperties.builder()
+ .broker(broker)
+ .topic(result.getData())
+ .clientId(vin)
+ .username(connectionReq.getUserName())
+ .password(vin+connectionReq.getTimestamp()+connectionReq.getNonce())
+ .build();
+ vehicleInstance.setMqttProperties(mqttProperties);
vehicleInstance.initClient();
}
diff --git a/src/main/java/com/muyu/utils/MD5Util.java b/src/main/java/com/muyu/utils/MD5Util.java
new file mode 100644
index 0000000..b1ae82d
--- /dev/null
+++ b/src/main/java/com/muyu/utils/MD5Util.java
@@ -0,0 +1,71 @@
+package com.muyu.utils;
+
+import lombok.extern.log4j.Log4j2;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+
+@Log4j2
+public class MD5Util {
+
+ private static final Integer SALT_LENGTH = 12;
+
+ /**
+ * 将指定byte数组转换成16进制字符串
+ * @param b 字节数组
+ * @return 返回结果字符串
+ */
+ public static String byteToHexString(byte[] b) {
+ StringBuilder hexString = new StringBuilder();
+ for (byte value : b) {
+ String hex = Integer.toHexString(value & 0xFF);
+ if (hex.length() == 1) {
+ hex = '0' + hex;
+ }
+ hexString.append(hex.toUpperCase());
+ }
+ return hexString.toString();
+ }
+
+ /**
+ * 获得加密后的口令
+ * @param str 需要加密的字符串
+ * @return 加密后的字符串
+ */
+ public static String encrypted (String str) {
+ try {
+ // 声明加密后的口令数组变量
+ byte[] pwd = null;
+ // 随机数生成器
+ SecureRandom random = new SecureRandom();
+ // 声明盐数组变量
+ byte[] salt = new byte[SALT_LENGTH];
+ // 将随机数放入盐变量中
+ random.nextBytes(salt);
+
+ // 声明消息摘要对象
+ MessageDigest md = null;
+ // 创建消息摘要
+ md = MessageDigest.getInstance("MD5");
+ // 将盐数据传入消息摘要对象
+ md.update(salt);
+ // 将口令的数据传给消息摘要对象
+ md.update(str.getBytes(StandardCharsets.UTF_8));
+ // 获得消息摘要的字节数组
+ byte[] digest = md.digest();
+
+ // 因为要在口令的字节数组中存放盐,所以加上盐的字节长度
+ pwd = new byte[digest.length + SALT_LENGTH];
+ // 将盐的字节拷贝到生成的加密口令字节数组的前12个字节,以便在验证口令时取出盐
+ System.arraycopy(salt, 0, pwd, 0, SALT_LENGTH);
+ // 将消息摘要拷贝到加密口令字节数组从第13个字节开始的字节
+ System.arraycopy(digest, 0, pwd, SALT_LENGTH, digest.length);
+ // 将字节数组格式加密后的口令转化为16进制字符串格式的口令
+ return byteToHexString(pwd);
+ }catch (Exception exception){
+ log.info("md5加密失败:[{}]", str, exception);
+ return str;
+ }
+ }
+}
diff --git a/src/main/java/com/muyu/vehicle/VehicleInstance.java b/src/main/java/com/muyu/vehicle/VehicleInstance.java
index 0784810..139b982 100644
--- a/src/main/java/com/muyu/vehicle/VehicleInstance.java
+++ b/src/main/java/com/muyu/vehicle/VehicleInstance.java
@@ -1,5 +1,6 @@
package com.muyu.vehicle;
+import com.alibaba.fastjson2.JSONObject;
import com.muyu.common.SystemConstant;
import com.muyu.common.ThreadPool;
import com.muyu.domain.Vehicle;
@@ -139,7 +140,8 @@ public class VehicleInstance {
options.setKeepAliveInterval(60);
// 连接
client.connect(options);
- log.info("车辆:[{}] 客户端初始化成功", getVin());
+ log.info("车辆:[{}] 客户端初始化成功连接配置:{}", getVin(),
+ JSONObject.toJSONString(this.mqttProperties));
} catch (MqttException e) {
log.error("车辆:[{}] 客户端初始化异常", getVin(), e);
}
diff --git a/src/main/java/com/muyu/vehicle/api/ClientAdmin.java b/src/main/java/com/muyu/vehicle/api/ClientAdmin.java
new file mode 100644
index 0000000..2383b2d
--- /dev/null
+++ b/src/main/java/com/muyu/vehicle/api/ClientAdmin.java
@@ -0,0 +1,21 @@
+package com.muyu.vehicle.api;
+
+import com.dtflys.forest.annotation.BaseRequest;
+import com.dtflys.forest.annotation.JSONBody;
+import com.dtflys.forest.annotation.Post;
+import com.muyu.common.Result;
+import com.muyu.vehicle.api.req.VehicleConnectionReq;
+
+/**
+ * @author DongZl
+ * @description: 客户端的管理
+ * @Date 2023-11-28 上午 10:20
+ */
+@BaseRequest(
+ baseURL = "${adminHost}"
+)
+public interface ClientAdmin {
+
+ @Post("${adminTopicUri}")
+ public Result vehicleConnection(@JSONBody VehicleConnectionReq vehicleConnectionReq);
+}
diff --git a/src/main/java/com/muyu/vehicle/api/req/VehicleConnectionReq.java b/src/main/java/com/muyu/vehicle/api/req/VehicleConnectionReq.java
new file mode 100644
index 0000000..3c6cb15
--- /dev/null
+++ b/src/main/java/com/muyu/vehicle/api/req/VehicleConnectionReq.java
@@ -0,0 +1,51 @@
+package com.muyu.vehicle.api.req;
+
+import com.alibaba.fastjson.annotation.JSONField;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/**
+ * @author DongZl
+ * @description: 车辆获取连接地址
+ * @Date 2023-11-28 上午 10:32
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class VehicleConnectionReq {
+
+ /**
+ * {
+ * "vehicleVin": "VIN1234567894",
+ * "timestamp": "11111",
+ * "username": "你好",
+ * "nonce": "33"
+ * }
+ */
+
+ /**
+ * vin
+ */
+ @JSONField(name = "vehicleVin")
+ private String vin;
+
+ /**
+ * 时间戳
+ */
+ private String timestamp;
+
+ /**
+ * 用户名
+ */
+ @JSONField(name = "username")
+ private String userName;
+
+ /**
+ * 随机字符串
+ */
+ private String nonce;
+
+}
diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml
index 409711c..309ed44 100644
--- a/src/main/resources/application.yml
+++ b/src/main/resources/application.yml
@@ -68,4 +68,19 @@ logging:
pattern:
file: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'
console: '%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n'
-
+# http调用框架
+forest:
+ max-connections: 1000 # 连接池最大连接数
+ connect-timeout: 3000 # 连接超时时间,单位为毫秒
+ read-timeout: 3000 # 数据读取超时时间,单位为毫秒
+ variables:
+ adminHost: ${mqtt.admin.host}
+ adminTopicUri: ${mqtt.admin.topic-uri}
+
+# 服务器配置
+mqtt:
+ server:
+ host: tcp://47.99.149.28:1883
+ admin:
+ host: http://47.120.48.139:9000
+ topic-uri: /verify/vehicleConnection
diff --git a/src/test/java/com/AdminTest.java b/src/test/java/com/AdminTest.java
new file mode 100644
index 0000000..7f6cf1e
--- /dev/null
+++ b/src/test/java/com/AdminTest.java
@@ -0,0 +1,34 @@
+package com;
+
+import com.muyu.VehicleSimulationApplication;
+import com.muyu.common.Result;
+import com.muyu.vehicle.api.ClientAdmin;
+import com.muyu.vehicle.api.req.VehicleConnectionReq;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+
+/**
+ * @author DongZl
+ * @description:
+ * @Date 2023-11-28 上午 10:36
+ */
+@SpringBootTest(classes = VehicleSimulationApplication.class)
+public class AdminTest {
+
+ @Autowired
+ private ClientAdmin clientAdmin;
+
+ @Test
+ public void vehicleConnTest(){
+ Result result = clientAdmin.vehicleConnection(
+ VehicleConnectionReq.builder()
+ .vin("VIN1234567894")
+ .timestamp(String.valueOf(System.currentTimeMillis()))
+ .userName("156841600")
+ .nonce("134812")
+ .build()
+ );
+ System.out.println(result);
+ }
+}