feat():合并车辆网管
commit
a63d614a23
|
@ -16,5 +16,25 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
public class CloudVehicleGatewayApplication {
|
public class CloudVehicleGatewayApplication {
|
||||||
public static void main (String[] args) {
|
public static void main (String[] args) {
|
||||||
SpringApplication.run(CloudVehicleGatewayApplication.class, args);
|
SpringApplication.run(CloudVehicleGatewayApplication.class, args);
|
||||||
|
System.out.println(" _ooOoo_\n" +
|
||||||
|
" o8888888o\n" +
|
||||||
|
" 88\" . \"88\n" +
|
||||||
|
" (| -_- |)\n" +
|
||||||
|
" O\\ = /O\n" +
|
||||||
|
" ____/`---'\\____\n" +
|
||||||
|
" .' \\\\| |// `.\n" +
|
||||||
|
" / \\\\||| : |||// \\\n" +
|
||||||
|
" / _||||| -:- |||||- \\\n" +
|
||||||
|
" | | \\\\\\ - /// | |\n" +
|
||||||
|
" | \\_| ''\\---/'' | |\n" +
|
||||||
|
" \\ .-\\__ `-` ___/-. /\n" +
|
||||||
|
" ___`. .' /--.--\\ `. . __\n" +
|
||||||
|
" .\"\" '< `.___\\_<|>_/___.' >'\"\".\n" +
|
||||||
|
" | | : `- \\`.;`\\ _ /`;.`/ - ` : | |\n" +
|
||||||
|
" \\ \\ `-. \\_ __\\ /__ _/ .-` / /\n" +
|
||||||
|
" ======`-.____`-.___\\_____/___.-`____.-'======\n" +
|
||||||
|
" `=---='\n" +
|
||||||
|
" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
|
||||||
|
" // 佛祖保佑 永不宕机 永无BUG //");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
package com.muyu.vehiclegateway.instance;
|
package com.muyu.vehiclegateway.aliyun;
|
||||||
|
|
||||||
import com.aliyun.ecs20140526.Client;
|
import com.aliyun.ecs20140526.Client;
|
||||||
import com.aliyun.teaopenapi.models.Config;
|
import com.aliyun.teaopenapi.models.Config;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -0,0 +1,165 @@
|
||||||
|
package com.muyu.vehiclegateway.config;
|
||||||
|
|
||||||
|
import com.aliyun.ecs20140526.Client;
|
||||||
|
import com.aliyun.ecs20140526.models.*;
|
||||||
|
import com.aliyun.tea.TeaException;
|
||||||
|
import com.aliyun.teautil.Common;
|
||||||
|
import com.aliyun.teautil.models.RuntimeOptions;
|
||||||
|
import com.muyu.common.redis.service.RedisService;
|
||||||
|
import com.muyu.vehiclegateway.aliyun.CreateClient;
|
||||||
|
import com.muyu.vehiclegateway.domain.Instance;
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName AddClientConfig
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YiBo.Liu
|
||||||
|
* @Date 2024/10/8 16:13
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class ClientConfig {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private static StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private static RedisService redisService;
|
||||||
|
|
||||||
|
public static String addServer() throws Exception {
|
||||||
|
|
||||||
|
// 创建阿里云ECS客户端
|
||||||
|
Client client = CreateClient.createClient();
|
||||||
|
// 配置系统盘参数
|
||||||
|
RunInstancesRequest.RunInstancesRequestSystemDisk systemDisk = new RunInstancesRequest.RunInstancesRequestSystemDisk()
|
||||||
|
.setSize("40") // 设置系统盘大小为40GB
|
||||||
|
.setCategory("cloud_essd"); // 设置系统盘类型为cloud_essd
|
||||||
|
// 创建创建实例请求对象并设置参数
|
||||||
|
RunInstancesRequest runInstancesRequest = new RunInstancesRequest()
|
||||||
|
// 设置地域ID
|
||||||
|
.setRegionId("cn-shanghai")
|
||||||
|
// 设置镜像ID
|
||||||
|
.setImageId("m-uf6f7atj16s3cjn9q5l8")
|
||||||
|
// 设置实例类型
|
||||||
|
.setInstanceType("ecs.t6-c1m1.large")
|
||||||
|
// 设置安全组ID
|
||||||
|
.setSecurityGroupId("sg-uf6f6dvazjqv127a4yyt")
|
||||||
|
// 设置虚拟交换机ID
|
||||||
|
.setVSwitchId("vsw-uf6htez4ox9k2c4cs8505")
|
||||||
|
// 设置实例名称
|
||||||
|
.setInstanceName("server-mqtt")
|
||||||
|
// 设置实例付费类型为后付费按量付费
|
||||||
|
.setInstanceChargeType("PostPaid")
|
||||||
|
// 设置互联网最大出带宽为1 Mbps
|
||||||
|
.setInternetMaxBandwidthOut(1)
|
||||||
|
// 设置系统盘配置
|
||||||
|
.setSystemDisk(systemDisk)
|
||||||
|
// 设置主机名
|
||||||
|
.setHostName("root")
|
||||||
|
// 设置实例密码
|
||||||
|
.setPassword("Six@211206")
|
||||||
|
// 设置创建实例的数量
|
||||||
|
.setAmount(1);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 创建运行时选项对象
|
||||||
|
RuntimeOptions runtime = new RuntimeOptions();
|
||||||
|
|
||||||
|
// 尝试执行创建实例请求
|
||||||
|
try {
|
||||||
|
|
||||||
|
RunInstancesResponse runInstancesResponse = client.runInstancesWithOptions(runInstancesRequest, runtime);
|
||||||
|
RunInstancesResponseBody body = runInstancesResponse.getBody();
|
||||||
|
RunInstancesResponseBody.RunInstancesResponseBodyInstanceIdSets instanceIdSets = body.getInstanceIdSets();
|
||||||
|
|
||||||
|
List<Instance> instanceList = new ArrayList<>();
|
||||||
|
List<String> instanceIps = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
Thread.sleep(20000);
|
||||||
|
|
||||||
|
DescribeInstancesResponse describeInstancesResponse = queryInstanceDetails(client);
|
||||||
|
// 获取实例的ID、公网IP和状态
|
||||||
|
|
||||||
|
String ip = "";
|
||||||
|
|
||||||
|
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> bodyInstancesInstances = describeInstancesResponse.getBody().getInstances().getInstance();
|
||||||
|
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : bodyInstancesInstances) {
|
||||||
|
String id = instance.getInstanceId();
|
||||||
|
String ipAddress = instance.getPublicIpAddress().getIpAddress().toString();
|
||||||
|
String status = instance.getStatus();
|
||||||
|
Instance instance1 = new Instance(id,ipAddress,status);
|
||||||
|
instanceList.add(instance1);
|
||||||
|
instanceIps.add(ipAddress);
|
||||||
|
|
||||||
|
log.info("实例id为:{}",instance.getInstanceId());
|
||||||
|
log.info("实例ip为:{}",instance.getPublicIpAddress().ipAddress.get(0));
|
||||||
|
log.info("实例状态为{}",instance.getStatus());
|
||||||
|
|
||||||
|
ip = instance.getPublicIpAddress().ipAddress.get(0);
|
||||||
|
|
||||||
|
//每个 实例ip对应的绑定数量
|
||||||
|
redisTemplate.opsForHash().put("serverBindings", ipAddress, 0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("====>创建的实例集合:"+instanceList);
|
||||||
|
//把实例信息存入redis
|
||||||
|
redisService.setCacheList("instanceList",instanceList);
|
||||||
|
//实例ip存入redis方便做轮询
|
||||||
|
redisService.setCacheList("ipList",instanceIps);
|
||||||
|
|
||||||
|
return ip;
|
||||||
|
} catch (TeaException error) {
|
||||||
|
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||||
|
// 错误 message
|
||||||
|
log.error(error.getMessage());
|
||||||
|
// 诊断地址
|
||||||
|
log.error(error.getData().get("Recommend"));
|
||||||
|
Common.assertAsString(error.message);
|
||||||
|
} catch (Exception _error) {
|
||||||
|
TeaException error = new TeaException(_error.getMessage(), _error);
|
||||||
|
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||||
|
// 错误 message
|
||||||
|
log.error(error.getMessage());
|
||||||
|
// 诊断地址
|
||||||
|
log.error(error.getData().get("Recommend"));
|
||||||
|
Common.assertAsString(error.message);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DescribeInstancesResponse queryInstanceDetails(Client client) {
|
||||||
|
|
||||||
|
// 创建查询实例请求对象并设置参数
|
||||||
|
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||||||
|
.setInstanceName("server-mqtt")
|
||||||
|
.setRegionId("cn-shanghai"); // 设置地域ID // 设置实例ID
|
||||||
|
// 创建运行时选项对象
|
||||||
|
RuntimeOptions runtime = new RuntimeOptions();
|
||||||
|
|
||||||
|
// 尝试执行查询实例请求
|
||||||
|
try {
|
||||||
|
return client.describeInstancesWithOptions(describeInstancesRequest, runtime);
|
||||||
|
} catch (TeaException e) {
|
||||||
|
// 捕获特定的TeaException并打印详细信息
|
||||||
|
log.info("TeaException occurred: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 捕获其他所有异常
|
||||||
|
log.info("An error occurred: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.muyu.vehiclegateway.config;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName ConnectWeight
|
||||||
|
* @Description 连接权重配置类
|
||||||
|
* @Author YiBo.Liu
|
||||||
|
* @Date 2024/10/8 19:21
|
||||||
|
*/
|
||||||
|
@Log4j2
|
||||||
|
@Component
|
||||||
|
public class ConnectWeight {
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
package com.muyu.vehiclegateway.config;
|
||||||
|
|
||||||
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.Exchange;
|
||||||
|
import org.springframework.amqp.core.ExchangeBuilder;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
|
@Log4j2
|
||||||
|
@Configuration
|
||||||
|
public class RabbitmqConfig {
|
||||||
|
// 日志
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(RabbitmqConfig.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆上线队列
|
||||||
|
*/
|
||||||
|
public static final String GO_ONLINE_QUEUE = "GO_ONLINE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆下线队列
|
||||||
|
*/
|
||||||
|
public static final String GO_OFFLINE_QUEUE = "GO_OFFLINE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议解析队列
|
||||||
|
*/
|
||||||
|
public static final String SEND_OFFLINE_QUEUE = "GO_LINE";
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆上线交换机
|
||||||
|
*/
|
||||||
|
public static final String ONLINE_EXCHANGE = "ONLINE_EXCHANGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆下线交换机
|
||||||
|
*/
|
||||||
|
public static final String OFFLINE_EXCHANGE = "OFFLINE_EXCHANGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 协议解析交换机
|
||||||
|
*/
|
||||||
|
public static final String LINE_EXCHANGE = "LINE_EXCHANGE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆下线路由key
|
||||||
|
*/
|
||||||
|
public static final String GO_OFFLINE_ROUTING_KEY = "GO_OFFLINE";
|
||||||
|
/**
|
||||||
|
* 车辆上线路由key
|
||||||
|
*/
|
||||||
|
public static final String GO_ONLINE_ROUTING_KEY = "GO_ONLINE";
|
||||||
|
/**
|
||||||
|
* 协议解析路由key
|
||||||
|
*/
|
||||||
|
public static final String SEND_ONLINE_ROUTING_KEY = "GO_LINE";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明交换机,做持久化
|
||||||
|
*/
|
||||||
|
@Bean(ONLINE_EXCHANGE)
|
||||||
|
public Exchange exchangeTopicsInformON() {
|
||||||
|
try {
|
||||||
|
Exchange exchange = ExchangeBuilder.topicExchange(ONLINE_EXCHANGE).durable(true).build();
|
||||||
|
log.info("创建的交换机为: {}", ONLINE_EXCHANGE);
|
||||||
|
return exchange;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 交换机失败", ONLINE_EXCHANGE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明交换机,做持久化
|
||||||
|
*/
|
||||||
|
@Bean(OFFLINE_EXCHANGE)
|
||||||
|
public Exchange exchangeTopicsInformOFF() {
|
||||||
|
try {
|
||||||
|
Exchange exchange = ExchangeBuilder.topicExchange(OFFLINE_EXCHANGE).durable(true).build();
|
||||||
|
log.info("创建的交换机为: {}", OFFLINE_EXCHANGE);
|
||||||
|
return exchange;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 交换机失败", OFFLINE_EXCHANGE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 声明交换机,做持久化
|
||||||
|
*/
|
||||||
|
@Bean(LINE_EXCHANGE)
|
||||||
|
public Exchange exchangeTopicsInform() {
|
||||||
|
try {
|
||||||
|
Exchange exchange = ExchangeBuilder.topicExchange(LINE_EXCHANGE).durable(true).build();
|
||||||
|
log.info("创建的交换机为: {}", LINE_EXCHANGE);
|
||||||
|
return exchange;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 交换机失败", LINE_EXCHANGE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明QUEUE_INFORM_EMAIL队列
|
||||||
|
@Bean(GO_OFFLINE_QUEUE)
|
||||||
|
public Queue queueInformEmail() {
|
||||||
|
try {
|
||||||
|
Queue queue = new Queue(GO_OFFLINE_QUEUE);
|
||||||
|
log.info("创建的队列为: {}", GO_OFFLINE_QUEUE);
|
||||||
|
return queue;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 队列失败", GO_OFFLINE_QUEUE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明QUEUE_INFORM_SMS队列
|
||||||
|
@Bean(GO_ONLINE_QUEUE)
|
||||||
|
public Queue queueInformSms() {
|
||||||
|
try {
|
||||||
|
Queue queue = new Queue(GO_ONLINE_QUEUE);
|
||||||
|
log.info("创建的队列为: {}", GO_ONLINE_QUEUE);
|
||||||
|
return queue;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 队列失败", GO_ONLINE_QUEUE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 声明QUEUE_INFORM_SMS队列
|
||||||
|
@Bean(SEND_OFFLINE_QUEUE)
|
||||||
|
public Queue queueInformSend() {
|
||||||
|
try {
|
||||||
|
Queue queue = new Queue(SEND_OFFLINE_QUEUE);
|
||||||
|
log.info("创建的队列为: {}", SEND_OFFLINE_QUEUE);
|
||||||
|
return queue;
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("创建该: {} 队列失败", SEND_OFFLINE_QUEUE, e);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//ROUTINGKEY_EMAIL队列绑定交换机,指定routingKey
|
||||||
|
@Bean
|
||||||
|
public Binding bindingQueueInformEmail(@Qualifier(GO_OFFLINE_QUEUE) Queue queue,
|
||||||
|
@Qualifier(OFFLINE_EXCHANGE) Exchange exchange){
|
||||||
|
return BindingBuilder.bind(queue).to(exchange).with(GO_OFFLINE_ROUTING_KEY).noargs();
|
||||||
|
}
|
||||||
|
//ROUTINGKEY_SMS队列绑定交换机,指定routingKey
|
||||||
|
@Bean
|
||||||
|
public Binding bindingRoutingKeySms(@Qualifier(GO_ONLINE_QUEUE) Queue queue,
|
||||||
|
@Qualifier(ONLINE_EXCHANGE) Exchange exchange){
|
||||||
|
return BindingBuilder.bind(queue).to(exchange).with(GO_ONLINE_ROUTING_KEY).noargs();
|
||||||
|
}
|
||||||
|
|
||||||
|
//ROUTINGKEY_SMS队列绑定交换机,指定routingKey
|
||||||
|
@Bean
|
||||||
|
public Binding bindingRoutingKeySend(@Qualifier(SEND_OFFLINE_QUEUE) Queue queue,
|
||||||
|
@Qualifier(LINE_EXCHANGE) Exchange exchange){
|
||||||
|
return BindingBuilder.bind(queue).to(exchange).with(SEND_ONLINE_ROUTING_KEY).noargs();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
package com.muyu.vehiclegateway.controller;
|
package com.muyu.vehiclegateway.controller;
|
||||||
|
|
||||||
import com.muyu.common.core.domain.Result;
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.vehiclegateway.domain.MqttServerModel;
|
||||||
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
||||||
import com.muyu.vehiclegateway.service.ConnectService;
|
import com.muyu.vehiclegateway.service.ConnectService;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
@ -27,15 +28,15 @@ public class ConnectController {
|
||||||
private ConnectService connectService;
|
private ConnectService connectService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取车辆信息
|
* 车辆连接
|
||||||
* @param vehicleConnectionReq
|
* @param vehicleConnectionReq
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@PostMapping("/receiveMsg/connect")
|
@PostMapping("/receiveMsg/connect")
|
||||||
private Result receiveMsg(@RequestBody VehicleConnectionReq vehicleConnectionReq){
|
private Result<MqttServerModel> receiveMsg(@RequestBody VehicleConnectionReq vehicleConnectionReq) throws Exception {
|
||||||
log.info("=======>" + vehicleConnectionReq);
|
log.info("=======>" + vehicleConnectionReq);
|
||||||
connectService.receiveMsg(vehicleConnectionReq);
|
Result<MqttServerModel> mqttServerModelResult = connectService.receiveMsg(vehicleConnectionReq);
|
||||||
return Result.success();
|
return mqttServerModelResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.muyu.vehiclegateway.domain;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName ConnectWegight
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YiBo.Liu
|
||||||
|
* @Date 2024/10/6 16:27
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
@Tag(name = "连接权重")
|
||||||
|
public class ConnectWeight {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 服务器ip
|
||||||
|
*/
|
||||||
|
private String carServerIp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 权重值
|
||||||
|
*/
|
||||||
|
private String weightValue;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.muyu.vehiclegateway.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName MqttProperties
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YiBo.Liu
|
||||||
|
* @Date 2024/10/10 20:04
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class MqttProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT服务节点
|
||||||
|
*/
|
||||||
|
private String broker;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MQTT订阅主题
|
||||||
|
*/
|
||||||
|
private String topic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 客户端id
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上报级别
|
||||||
|
*/
|
||||||
|
private int qos = 0;
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.muyu.vehiclegateway.domain;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ClassName VinIp
|
||||||
|
* @Description 描述
|
||||||
|
* @Author YiBo.Liu
|
||||||
|
* @Date 2024/10/6 20:33
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Builder
|
||||||
|
public class VinIp {
|
||||||
|
|
||||||
|
private String vin;
|
||||||
|
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
}
|
|
@ -32,7 +32,7 @@ public class VehicleConnectionReq {
|
||||||
private String vehicleVin;
|
private String vehicleVin;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*时间戳
|
* 时间戳
|
||||||
*/
|
*/
|
||||||
private String timestamp;
|
private String timestamp;
|
||||||
|
|
||||||
|
@ -41,4 +41,17 @@ public class VehicleConnectionReq {
|
||||||
*/
|
*/
|
||||||
private String nonce;
|
private String nonce;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户名
|
||||||
|
*/
|
||||||
|
@JSONField(name = "username")
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码
|
||||||
|
*/
|
||||||
|
@JSONField(name = "password")
|
||||||
|
private String password;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,16 +9,23 @@ import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
|
||||||
import com.aliyun.tea.*;
|
import com.aliyun.tea.*;
|
||||||
import com.aliyun.teautil.Common;
|
import com.aliyun.teautil.Common;
|
||||||
import com.aliyun.teautil.models.RuntimeOptions;
|
import com.aliyun.teautil.models.RuntimeOptions;
|
||||||
|
import com.muyu.common.redis.service.RedisService;
|
||||||
|
import com.muyu.vehiclegateway.aliyun.CreateClient;
|
||||||
|
import com.muyu.vehiclegateway.service.ConnectService;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.beans.factory.DisposableBean;
|
import org.springframework.beans.factory.DisposableBean;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ClassName GenerateInstance
|
* @ClassName GenerateInstance
|
||||||
* @Description 描述
|
* @Description 停止程序时删除ECS服务器实例
|
||||||
* @Author YiBo.Liu
|
* @Author YiBo.Liu
|
||||||
* @Date 2024/9/28 19:39
|
* @Date 2024/9/28 19:39
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +34,7 @@ import java.util.ArrayList;
|
||||||
@Tag(name = "停止程序时删除ECS服务器实例")
|
@Tag(name = "停止程序时删除ECS服务器实例")
|
||||||
public class DelInstance implements DisposableBean {
|
public class DelInstance implements DisposableBean {
|
||||||
|
|
||||||
|
|
||||||
public static void delInstance() throws Exception {
|
public static void delInstance() throws Exception {
|
||||||
|
|
||||||
// 创建ECS客户端对象,用于后续调用ECS相关API
|
// 创建ECS客户端对象,用于后续调用ECS相关API
|
||||||
|
@ -75,9 +83,9 @@ public class DelInstance implements DisposableBean {
|
||||||
} catch (TeaException error) {
|
} catch (TeaException error) {
|
||||||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||||
// 错误 message
|
// 错误 message
|
||||||
System.out.println(error.getMessage());
|
log.info(error.getMessage());
|
||||||
// 诊断地址
|
// 诊断地址
|
||||||
System.out.println(error.getData().get("Recommend"));
|
log.info(error.getData().get("Recommend"));
|
||||||
Common.assertAsString(error.message);
|
Common.assertAsString(error.message);
|
||||||
} catch (Exception _error) {
|
} catch (Exception _error) {
|
||||||
TeaException error = new TeaException(_error.getMessage(), _error);
|
TeaException error = new TeaException(_error.getMessage(), _error);
|
||||||
|
@ -91,12 +99,12 @@ public class DelInstance implements DisposableBean {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void destroy() throws Exception {
|
public void destroy() throws Exception {
|
||||||
System.out.println("删除中=======================");
|
System.out.println("删除中=======================");
|
||||||
delInstance();
|
delInstance();
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,19 @@
|
||||||
package com.muyu.vehiclegateway.instance;
|
package com.muyu.vehiclegateway.instance;
|
||||||
|
|
||||||
import com.aliyun.ecs20140526.Client;
|
import com.aliyun.ecs20140526.Client;
|
||||||
import com.aliyun.ecs20140526.models.DescribeInstancesRequest;
|
import com.aliyun.ecs20140526.models.*;
|
||||||
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
|
|
||||||
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
|
|
||||||
import com.aliyun.ecs20140526.models.RunInstancesRequest;
|
|
||||||
import com.aliyun.tea.TeaException;
|
import com.aliyun.tea.TeaException;
|
||||||
import com.aliyun.teautil.Common;
|
import com.aliyun.teautil.Common;
|
||||||
import com.aliyun.teautil.models.RuntimeOptions;
|
import com.aliyun.teautil.models.RuntimeOptions;
|
||||||
import com.muyu.common.redis.service.RedisService;
|
import com.muyu.common.redis.service.RedisService;
|
||||||
|
import com.muyu.vehiclegateway.aliyun.CreateClient;
|
||||||
import com.muyu.vehiclegateway.domain.Instance;
|
import com.muyu.vehiclegateway.domain.Instance;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.extern.log4j.Log4j2;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.ApplicationArguments;
|
import org.springframework.boot.ApplicationArguments;
|
||||||
import org.springframework.boot.ApplicationRunner;
|
import org.springframework.boot.ApplicationRunner;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -35,18 +34,27 @@ public class GenerateInstance implements ApplicationRunner {
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedisService redisService;
|
private RedisService redisService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 启动自动创建实例
|
* 启动自动创建实例
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public List<Instance> generateInstance() throws Exception {
|
public void generateInstance() throws Exception {
|
||||||
|
|
||||||
// 创建ECS客户端对象,用于后续调用ECS相关API
|
redisService.deleteObject("vinIp");
|
||||||
|
redisService.deleteObject("ipList");
|
||||||
|
redisService.deleteObject("instanceList");
|
||||||
|
redisService.deleteObject("count");
|
||||||
|
|
||||||
|
// 创建阿里云ECS客户端
|
||||||
Client client = CreateClient.createClient();
|
Client client = CreateClient.createClient();
|
||||||
|
// 配置系统盘参数
|
||||||
RunInstancesRequest.RunInstancesRequestSystemDisk systemDisk = new RunInstancesRequest.RunInstancesRequestSystemDisk()
|
RunInstancesRequest.RunInstancesRequestSystemDisk systemDisk = new RunInstancesRequest.RunInstancesRequestSystemDisk()
|
||||||
.setSize("40")
|
.setSize("40") // 设置系统盘大小为40GB
|
||||||
.setCategory("cloud_essd");
|
.setCategory("cloud_essd"); // 设置系统盘类型为cloud_essd
|
||||||
|
// 创建创建实例请求对象并设置参数
|
||||||
RunInstancesRequest runInstancesRequest = new RunInstancesRequest()
|
RunInstancesRequest runInstancesRequest = new RunInstancesRequest()
|
||||||
// 设置地域ID
|
// 设置地域ID
|
||||||
.setRegionId("cn-shanghai")
|
.setRegionId("cn-shanghai")
|
||||||
|
@ -71,68 +79,104 @@ public class GenerateInstance implements ApplicationRunner {
|
||||||
// 设置实例密码
|
// 设置实例密码
|
||||||
.setPassword("Six@211206")
|
.setPassword("Six@211206")
|
||||||
// 设置创建实例的数量
|
// 设置创建实例的数量
|
||||||
.setAmount(1);
|
.setAmount(2);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 创建运行时选项对象
|
||||||
RuntimeOptions runtime = new RuntimeOptions();
|
RuntimeOptions runtime = new RuntimeOptions();
|
||||||
|
|
||||||
|
// 尝试执行创建实例请求
|
||||||
try {
|
try {
|
||||||
// 复制代码运行请自行打印 API 的返回值
|
|
||||||
client.runInstancesWithOptions(runInstancesRequest, runtime);
|
RunInstancesResponse runInstancesResponse = client.runInstancesWithOptions(runInstancesRequest, runtime);
|
||||||
|
RunInstancesResponseBody body = runInstancesResponse.getBody();
|
||||||
|
RunInstancesResponseBody.RunInstancesResponseBodyInstanceIdSets instanceIdSets = body.getInstanceIdSets();
|
||||||
|
|
||||||
|
List<Instance> instanceList = new ArrayList<>();
|
||||||
|
List<String> instanceIps = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
Thread.sleep(20000);
|
||||||
|
|
||||||
|
DescribeInstancesResponse describeInstancesResponse = queryInstanceDetails(client);
|
||||||
|
// 获取实例的ID、公网IP和状态
|
||||||
|
|
||||||
|
List<DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance> bodyInstancesInstances = describeInstancesResponse.getBody().getInstances().getInstance();
|
||||||
|
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : bodyInstancesInstances) {
|
||||||
|
String id = instance.getInstanceId();
|
||||||
|
String ipAddress = instance.getPublicIpAddress().getIpAddress().get(0);
|
||||||
|
String status = instance.getStatus();
|
||||||
|
Instance instance1 = new Instance(id,ipAddress,status);
|
||||||
|
instanceList.add(instance1);
|
||||||
|
instanceIps.add(ipAddress);
|
||||||
|
|
||||||
|
log.info("实例id为:{}",instance.getInstanceId());
|
||||||
|
log.info("实例ip为:{}",instance.getPublicIpAddress().ipAddress.get(0));
|
||||||
|
log.info("实例状态为{}",instance.getStatus());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("====>创建的实例集合:"+instanceList);
|
||||||
|
//把实例信息存入redis
|
||||||
|
redisService.setCacheList("instanceList",instanceList);
|
||||||
|
//实例ip存入redis方便做轮询
|
||||||
|
redisService.setCacheList("ipList",instanceIps);
|
||||||
|
|
||||||
|
|
||||||
} catch (TeaException error) {
|
} catch (TeaException error) {
|
||||||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||||
// 错误 message
|
// 错误 message
|
||||||
System.out.println(error.getMessage());
|
log.error(error.getMessage());
|
||||||
// 诊断地址
|
// 诊断地址
|
||||||
System.out.println(error.getData().get("Recommend"));
|
log.error(error.getData().get("Recommend"));
|
||||||
Common.assertAsString(error.message);
|
Common.assertAsString(error.message);
|
||||||
} catch (Exception _error) {
|
} catch (Exception _error) {
|
||||||
TeaException error = new TeaException(_error.getMessage(), _error);
|
TeaException error = new TeaException(_error.getMessage(), _error);
|
||||||
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
// 此处仅做打印展示,请谨慎对待异常处理,在工程项目中切勿直接忽略异常。
|
||||||
// 错误 message
|
// 错误 message
|
||||||
System.out.println(error.getMessage());
|
log.error(error.getMessage());
|
||||||
// 诊断地址
|
// 诊断地址
|
||||||
System.out.println(error.getData().get("Recommend"));
|
log.error(error.getData().get("Recommend"));
|
||||||
Common.assertAsString(error.message);
|
Common.assertAsString(error.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
|
||||||
.setRegionId("cn-shanghai");
|
|
||||||
|
|
||||||
//创建运行时选择对象,用于配置运行时的选项参数
|
|
||||||
RuntimeOptions runtimeOptions = new RuntimeOptions();
|
|
||||||
|
|
||||||
//获取实例列表
|
|
||||||
DescribeInstancesResponse describeInstancesResponse = client.describeInstancesWithOptions(describeInstancesRequest, runtimeOptions);
|
|
||||||
|
|
||||||
//提取实例ID集合
|
|
||||||
List<Instance> list = new ArrayList<>();
|
|
||||||
|
|
||||||
DescribeInstancesResponseBody body = describeInstancesResponse.getBody();
|
|
||||||
|
|
||||||
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : body.getInstances().getInstance()) {
|
|
||||||
|
|
||||||
log.info("实例id为:"+instance.getInstanceId());
|
|
||||||
log.info("实例ip为:"+instance.getPublicIpAddress().ipAddress.get(0));
|
|
||||||
log.info("实例状态为:"+instance.getStatus());
|
|
||||||
|
|
||||||
Instance instance1 = new Instance(instance.getInstanceId(), instance.getPublicIpAddress().ipAddress.get(0), instance.getStatus());
|
|
||||||
|
|
||||||
list.add(instance1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Thread.sleep(20000);
|
|
||||||
// redisService.setCacheList("aaa",list);
|
|
||||||
|
|
||||||
return list;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static DescribeInstancesResponse queryInstanceDetails(Client client) {
|
||||||
|
|
||||||
|
// 创建查询实例请求对象并设置参数
|
||||||
|
DescribeInstancesRequest describeInstancesRequest = new DescribeInstancesRequest()
|
||||||
|
.setInstanceName("server-mqtt")
|
||||||
|
.setRegionId("cn-shanghai"); // 设置地域ID // 设置实例ID
|
||||||
|
// 创建运行时选项对象
|
||||||
|
RuntimeOptions runtime = new RuntimeOptions();
|
||||||
|
|
||||||
|
// 尝试执行查询实例请求
|
||||||
|
try {
|
||||||
|
return client.describeInstancesWithOptions(describeInstancesRequest, runtime);
|
||||||
|
} catch (TeaException e) {
|
||||||
|
// 捕获特定的TeaException并打印详细信息
|
||||||
|
log.info("TeaException occurred: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 捕获其他所有异常
|
||||||
|
log.info("An error occurred: " + e.getMessage());
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run(ApplicationArguments args) throws Exception {
|
public void run(ApplicationArguments args) throws Exception {
|
||||||
|
log.info("===============>开始执行创建实例方法");
|
||||||
generateInstance();
|
generateInstance();
|
||||||
System.out.println("创建实例成功");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,13 @@ package com.muyu.vehiclegateway.mapper;
|
||||||
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface ConnectMapper {
|
public interface ConnectMapper {
|
||||||
void addVehicle(VehicleConnectionReq vehicleConnectionReq);
|
void addVehicle(VehicleConnectionReq vehicleConnectionReq);
|
||||||
|
|
||||||
|
List<String> selectVehicleVin(String vehicleVin);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,11 @@
|
||||||
package com.muyu.vehiclegateway.service;
|
package com.muyu.vehiclegateway.service;
|
||||||
|
|
||||||
|
import com.muyu.common.core.domain.Result;
|
||||||
|
import com.muyu.vehiclegateway.domain.MqttServerModel;
|
||||||
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ConnectService {
|
public interface ConnectService {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,11 +15,12 @@ public interface ConnectService {
|
||||||
void createConnect() throws Exception;
|
void createConnect() throws Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取车辆信息
|
* 车辆连接
|
||||||
* @param vehicleConnectionReq
|
* @param vehicleConnectionReq
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
void receiveMsg(VehicleConnectionReq vehicleConnectionReq);
|
Result<MqttServerModel> receiveMsg(VehicleConnectionReq vehicleConnectionReq) throws Exception;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,19 +1,26 @@
|
||||||
package com.muyu.vehiclegateway.service.impl;
|
package com.muyu.vehiclegateway.service.impl;
|
||||||
|
|
||||||
import cn.hutool.json.JSON;
|
import com.muyu.common.core.domain.Result;
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.muyu.common.redis.service.RedisService;
|
||||||
import com.muyu.common.core.constant.GenConstants;
|
import com.muyu.vehiclegateway.config.ClientConfig;
|
||||||
import com.muyu.common.core.utils.uuid.UUID;
|
import com.muyu.vehiclegateway.domain.MqttProperties;
|
||||||
|
import com.muyu.vehiclegateway.domain.MqttServerModel;
|
||||||
|
import com.muyu.vehiclegateway.domain.VinIp;
|
||||||
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
import com.muyu.vehiclegateway.domain.req.VehicleConnectionReq;
|
||||||
import com.muyu.vehiclegateway.instance.GenerateInstance;
|
import com.muyu.vehiclegateway.instance.GenerateInstance;
|
||||||
import com.muyu.vehiclegateway.mapper.ConnectMapper;
|
import com.muyu.vehiclegateway.mapper.ConnectMapper;
|
||||||
import com.muyu.vehiclegateway.service.ConnectService;
|
import com.muyu.vehiclegateway.service.ConnectService;
|
||||||
import org.springframework.amqp.core.Message;
|
import lombok.extern.log4j.Log4j2;
|
||||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import static io.lettuce.core.pubsub.PubSubOutput.Type.message;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static com.muyu.vehiclegateway.config.RabbitmqConfig.LINE_EXCHANGE;
|
||||||
|
import static com.muyu.vehiclegateway.config.RabbitmqConfig.SEND_ONLINE_ROUTING_KEY;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @ClassName ConnectServiceImpl
|
* @ClassName ConnectServiceImpl
|
||||||
|
@ -22,15 +29,24 @@ import static io.lettuce.core.pubsub.PubSubOutput.Type.message;
|
||||||
* @Date 2024/10/2 16:25
|
* @Date 2024/10/2 16:25
|
||||||
*/
|
*/
|
||||||
@Service
|
@Service
|
||||||
|
@Log4j2
|
||||||
public class ConnectServiceImpl implements ConnectService {
|
public class ConnectServiceImpl implements ConnectService {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RabbitTemplate rabbitTemplate;
|
private RabbitTemplate rabbitTemplate;
|
||||||
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private ConnectMapper connectMapper;
|
private ConnectMapper connectMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StringRedisTemplate redisTemplate;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ClientConfig clientConfig;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private RedisService redisService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建实例
|
* 创建实例
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
|
@ -47,11 +63,128 @@ public class ConnectServiceImpl implements ConnectService {
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void receiveMsg(VehicleConnectionReq vehicleConnectionReq) {
|
public Result<MqttServerModel> receiveMsg(VehicleConnectionReq vehicleConnectionReq) throws Exception {
|
||||||
rabbitTemplate.convertAndSend("GO_OFFLINE", vehicleConnectionReq.getVehicleVin(),message1 -> {
|
|
||||||
message1.getMessageProperties().setMessageId(UUID.fastUUID().toString());
|
log.info("车辆连接请求:{}", vehicleConnectionReq);
|
||||||
return message1;
|
|
||||||
});
|
//生成密码
|
||||||
connectMapper.addVehicle(vehicleConnectionReq);
|
vehicleConnectionReq.setPassword(vehicleConnectionReq.getVehicleVin() + vehicleConnectionReq.getTimestamp()
|
||||||
|
+ vehicleConnectionReq.getNonce());
|
||||||
|
|
||||||
|
//查询有没有这辆车的vin码
|
||||||
|
List<String> selectVehicle = connectMapper.selectVehicleVin(vehicleConnectionReq.getVehicleVin());
|
||||||
|
|
||||||
|
if(selectVehicle.isEmpty()){
|
||||||
|
connectMapper.addVehicle(vehicleConnectionReq);
|
||||||
|
log.info("车辆预上线成功");
|
||||||
|
}else {
|
||||||
|
log.info("车辆无法重复预上线");
|
||||||
|
}
|
||||||
|
|
||||||
|
//先判断vin码
|
||||||
|
// String vin = redisTemplate.opsForValue().get(vehicleConnectionReq.getVehicleVin());
|
||||||
|
if(redisTemplate.hasKey(vehicleConnectionReq.getVehicleVin())){
|
||||||
|
log.info("车辆绑定ip失败,已经存在");
|
||||||
|
throw new RuntimeException("车辆已经绑定过了");
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断redis有没有count键
|
||||||
|
if(redisTemplate.hasKey("count")){
|
||||||
|
//取出count
|
||||||
|
Integer count = Integer.valueOf(redisTemplate.opsForValue().get("count"));
|
||||||
|
if(count == 1){
|
||||||
|
redisTemplate.opsForValue().set("count",String.valueOf(0));
|
||||||
|
}else {
|
||||||
|
redisTemplate.opsForValue().set("count",String.valueOf(count+1));
|
||||||
|
}
|
||||||
|
//根据游标count获取服务IP
|
||||||
|
Object ip = redisService.redisTemplate.opsForList().index("ipList", count);
|
||||||
|
//关联车辆和服务
|
||||||
|
this.insertVinIp(new VinIp(vehicleConnectionReq.getVehicleVin(),ip.toString()));
|
||||||
|
//响应信息
|
||||||
|
log.info("车辆:"+vehicleConnectionReq.getVehicleVin()+"成功绑定到:"+ip);
|
||||||
|
|
||||||
|
//发送mq到协议解析
|
||||||
|
MqttProperties mqttProperties = new MqttProperties();
|
||||||
|
mqttProperties.setBroker("tcp://" + ip + ":1883");
|
||||||
|
mqttProperties.setTopic("vehicle");
|
||||||
|
mqttProperties.setUsername(vehicleConnectionReq.getUsername());
|
||||||
|
mqttProperties.setPassword(vehicleConnectionReq.getPassword());
|
||||||
|
mqttProperties.setClientId(ip.toString());
|
||||||
|
mqttProperties.setQos(0);
|
||||||
|
|
||||||
|
rabbitTemplate.convertAndSend(LINE_EXCHANGE,SEND_ONLINE_ROUTING_KEY,mqttProperties);
|
||||||
|
|
||||||
|
return Result.success(new MqttServerModel("tcp://"+ip+":1883","vehicle"));
|
||||||
|
}else {
|
||||||
|
redisTemplate.opsForValue().set("count",String.valueOf(0));
|
||||||
|
//根据游标count获取服务器Ip
|
||||||
|
Object ip = redisService.redisTemplate.opsForList().index("ipList", 0);
|
||||||
|
log.info("ip为:{}",ip);
|
||||||
|
//关联车辆和服务
|
||||||
|
this.insertVinIp(new VinIp(vehicleConnectionReq.getVehicleVin(),ip.toString()));
|
||||||
|
//响应信息
|
||||||
|
log.info("车辆:{}",vehicleConnectionReq.getVehicleVin(),"成功绑定到:{}",ip);
|
||||||
|
return Result.success(new MqttServerModel("tcp://"+ip+":1883","vehicle"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加车辆绑定ip 存入redis
|
||||||
|
*/
|
||||||
|
private void insertVinIp(VinIp vinIp){
|
||||||
|
if (vinIp == null || vinIp.getVin() == null || vinIp.getVin().isEmpty() || vinIp.getIp() == null || vinIp.getIp().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("vin 或 ip 不能为空或无效");
|
||||||
|
}
|
||||||
|
|
||||||
|
redisTemplate.opsForValue().set(vinIp.getVin(),vinIp.getIp());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 增加服务器
|
||||||
|
*/
|
||||||
|
private String addNewServer() throws Exception {
|
||||||
|
// 这里调用你已经写好的方法来新增服务器
|
||||||
|
// 假设新增服务器的方法是addServer,返回新服务器的IP
|
||||||
|
String newIp = clientConfig.addServer();
|
||||||
|
// 将新服务器的IP添加到ipList中
|
||||||
|
redisTemplate.opsForList().rightPush("ipList", newIp);
|
||||||
|
// 将新服务器的绑定数量初始化为0
|
||||||
|
redisTemplate.opsForHash().put("serverBindings", newIp, 0);
|
||||||
|
return newIp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查服务器是否已满
|
||||||
|
*/
|
||||||
|
private boolean isServerFull(String ip) {
|
||||||
|
Integer bindingCount = (Integer)redisTemplate.opsForHash().get("serverBindings", ip);
|
||||||
|
return bindingCount >= 6;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 寻找下一个未满的服务器
|
||||||
|
*/
|
||||||
|
private String findAvailableServer() {
|
||||||
|
List<String> ipList = redisTemplate.opsForList().range("ipList", 0, -1);
|
||||||
|
for (String ip : ipList) {
|
||||||
|
if (!isServerFull(ip)) {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; // 如果所有服务器都满了,返回null
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新服务器绑定数量
|
||||||
|
*/
|
||||||
|
private void incrementServerBindingCount(String ip) {
|
||||||
|
// 获取当前服务器的绑定数量
|
||||||
|
Integer bindingCount = (Integer)redisTemplate.opsForHash().get("serverBindings", ip);
|
||||||
|
// 更新绑定数量
|
||||||
|
redisTemplate.opsForHash().put("serverBindings", ip, bindingCount + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,12 @@
|
||||||
<mapper namespace="com.muyu.vehiclegateway.mapper.ConnectMapper">
|
<mapper namespace="com.muyu.vehiclegateway.mapper.ConnectMapper">
|
||||||
|
|
||||||
<insert id="addVehicle">
|
<insert id="addVehicle">
|
||||||
insert into connect(id,vehicle_vin,timestamp,nonce)
|
insert into connect(id,vehicle_vin,username,password)
|
||||||
values (#{id},#{vehicleVin},#{timestamp},#{nonce})
|
values (#{id},#{vehicleVin},#{username},#{password})
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
|
<select id="selectVehicleVin" resultType="java.lang.String">
|
||||||
|
select connect.vehicle_vin from connect
|
||||||
|
where connect.vehicle_vin = #{vehicleVin}
|
||||||
|
</select>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
Loading…
Reference in New Issue