代码优化
This commit is contained in:
@@ -59,7 +59,6 @@
|
|||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.baomidou</groupId>
|
<groupId>com.baomidou</groupId>
|
||||||
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
|
<artifactId>mybatis-plus-spring-boot4-starter</artifactId>
|
||||||
@@ -94,6 +93,19 @@
|
|||||||
<artifactId>jackson-databind</artifactId>
|
<artifactId>jackson-databind</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- JSON 解析器和生成器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>2.0.23</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Hutool工具包 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.8.40</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package org.dromara.mica.mqtt.server.controller;
|
package org.dromara.mica.mqtt.server.controller;
|
||||||
|
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
|
||||||
import org.dromara.mica.mqtt.server.service.impl.ServerService;
|
import org.dromara.mica.mqtt.server.service.impl.ServerService;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
@@ -9,17 +7,35 @@ import org.springframework.web.bind.annotation.RequestBody;
|
|||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
@Tag(name = "Mqtt::服务端")
|
|
||||||
@RequestMapping("/mqtt/server")
|
@RequestMapping("/mqtt/server")
|
||||||
@RestController
|
@RestController
|
||||||
public class ServerController {
|
public class ServerController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ServerService service;
|
private ServerService service;
|
||||||
|
|
||||||
@Operation(summary = "publish")
|
|
||||||
@PostMapping("publish")
|
@PostMapping("publish")
|
||||||
public boolean publish(@RequestBody String body) {
|
public boolean publish(@RequestBody String body) {
|
||||||
return service.publish(body);
|
return service.publish(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("open")
|
||||||
|
public boolean open(@RequestBody String body) {
|
||||||
|
return service.open(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("open2")
|
||||||
|
public boolean open2(@RequestBody String body) {
|
||||||
|
return service.open2(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("check_offline_record")
|
||||||
|
public boolean check_offline_record(@RequestBody String body) {
|
||||||
|
return service.check_offline_record(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("offline_record")
|
||||||
|
public boolean offline_record(@RequestBody String body) {
|
||||||
|
return service.offline_record(body);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import lombok.Data;
|
|||||||
import java.io.Serial;
|
import java.io.Serial;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("car_info")
|
@TableName("car_info")
|
||||||
@@ -31,12 +32,21 @@ public class CarInfo implements Serializable {
|
|||||||
/** 车牌号 */
|
/** 车牌号 */
|
||||||
private String plate;
|
private String plate;
|
||||||
|
|
||||||
|
/** 车牌号 */
|
||||||
|
private List<String> plateList;
|
||||||
|
|
||||||
/** 是否启用时间段 */
|
/** 是否启用时间段 */
|
||||||
private String timeSegEnable;
|
private String timeSegEnable;
|
||||||
|
|
||||||
/** 时间段 */
|
/** 时间段 */
|
||||||
private String segTime;
|
private String segTime;
|
||||||
|
|
||||||
|
/** 时间段 */
|
||||||
|
private String segTimeStart = "00:00:00";
|
||||||
|
|
||||||
|
/** 时间段 */
|
||||||
|
private String segTimeEnd = "00:00:00";
|
||||||
|
|
||||||
/** 是否需要报警 */
|
/** 是否需要报警 */
|
||||||
private String needAlarm;
|
private String needAlarm;
|
||||||
|
|
||||||
@@ -57,8 +67,9 @@ public class CarInfo implements Serializable {
|
|||||||
|
|
||||||
private String sn;//设备序列号
|
private String sn;//设备序列号
|
||||||
|
|
||||||
private int num;
|
|
||||||
|
|
||||||
/** 超频设备识别标签 */
|
/** 超频设备识别标签 */
|
||||||
private String overclockCard;
|
private String overclockCard;
|
||||||
|
|
||||||
|
/** car_park_record表的主键id */
|
||||||
|
private Long carParkRecordId;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车场设备实体
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("car_park_item")
|
||||||
|
public class CarParkItem implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备id
|
||||||
|
*/
|
||||||
|
private String equipmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停车场id
|
||||||
|
*/
|
||||||
|
private String parkId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过车行驶方向 0 入场过车 1出场过车
|
||||||
|
*/
|
||||||
|
private String way;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 区域
|
||||||
|
*/
|
||||||
|
private String area;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.entity;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆授权对象 car_park_record
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CarParkRecord implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备id
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Long equipmentId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车场id
|
||||||
|
*/
|
||||||
|
|
||||||
|
private Long parkId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆id
|
||||||
|
*/
|
||||||
|
private Long customerId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否下发(0未下发1已下发)
|
||||||
|
*/
|
||||||
|
private String sync;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 摄像头mqtt协议的报文id
|
||||||
|
*/
|
||||||
|
private String clientId;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,87 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||||
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||||
|
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通行记录对象 car_pass_record
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@TableName("car_pass_record")
|
||||||
|
public class CarPassRecord implements Serializable {
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 停车场id
|
||||||
|
*/
|
||||||
|
private String parkId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过车信息唯一标识
|
||||||
|
*/
|
||||||
|
private String uniqueNo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 过车行驶方向 0 入场过车 1出场过车
|
||||||
|
*/
|
||||||
|
private String direction;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌号码
|
||||||
|
*/
|
||||||
|
private String license;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通行时间
|
||||||
|
*/
|
||||||
|
@JsonFormat(pattern = "yyyy-MM-dd")
|
||||||
|
private Date passTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发类型
|
||||||
|
*/
|
||||||
|
private String triggerType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌颜色
|
||||||
|
*/
|
||||||
|
private String colorType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆颜色
|
||||||
|
*/
|
||||||
|
private String carColor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌图片数据
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 数据类型 0 实时数据 1历史数据
|
||||||
|
*/
|
||||||
|
private String dataType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备序列号
|
||||||
|
*/
|
||||||
|
private String sn;
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,19 +1,28 @@
|
|||||||
package org.dromara.mica.mqtt.server.listener;
|
package org.dromara.mica.mqtt.server.listener;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.dromara.mica.mqtt.codec.message.MqttPublishMessage;
|
|
||||||
import org.dromara.mica.mqtt.server.constant.CacheConstants;
|
|
||||||
import org.dromara.mica.mqtt.server.enums.FlagEnums;
|
|
||||||
import org.dromara.mica.mqtt.server.pojo.User;
|
|
||||||
import org.dromara.mica.mqtt.core.annotation.MqttServerFunction;
|
import org.dromara.mica.mqtt.core.annotation.MqttServerFunction;
|
||||||
|
import org.dromara.mica.mqtt.server.constant.CacheConstants;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkItem;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkRecord;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarPassRecord;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.Equipment;
|
||||||
|
import org.dromara.mica.mqtt.server.enums.FlagEnums;
|
||||||
|
import org.dromara.mica.mqtt.server.pojo.WhiteListOperatorPO;
|
||||||
import org.dromara.mica.mqtt.server.redis.RedisService;
|
import org.dromara.mica.mqtt.server.redis.RedisService;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarParkItemService;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarParkRecordService;
|
||||||
|
import org.dromara.mica.mqtt.server.service.IEquipmentService;
|
||||||
|
import org.dromara.mica.mqtt.server.utils.AESUtil;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
|
||||||
import org.tio.core.ChannelContext;
|
|
||||||
import org.tio.core.Node;
|
|
||||||
|
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@@ -29,6 +38,23 @@ public class CarMessageListener {
|
|||||||
@Autowired
|
@Autowired
|
||||||
RedisService redisService;
|
RedisService redisService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ICarParkRecordService carParkRecordService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
IEquipmentService equipmentService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ICarParkItemService carParkItemService;
|
||||||
|
|
||||||
|
private static String key = "1234567898765432";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 心跳
|
||||||
|
* @param topic
|
||||||
|
* @param topicVars
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
@MqttServerFunction("device/${sn}/message/up/keep_alive")
|
@MqttServerFunction("device/${sn}/message/up/keep_alive")
|
||||||
public void onKeepAliveMessage(String topic, Map<String, String> topicVars, byte[] message) {
|
public void onKeepAliveMessage(String topic, Map<String, String> topicVars, byte[] message) {
|
||||||
String sn = topicVars.get("sn");
|
String sn = topicVars.get("sn");
|
||||||
@@ -38,13 +64,136 @@ public class CarMessageListener {
|
|||||||
redisService.setCacheObject(CacheConstants.EQUIPMENT_HEARTBEAT + sn, FlagEnums.ONLINE.getCode(), CacheConstants.OFFLINE_THRESHOLD, TimeUnit.MILLISECONDS);
|
redisService.setCacheObject(CacheConstants.EQUIPMENT_HEARTBEAT + sn, FlagEnums.ONLINE.getCode(), CacheConstants.OFFLINE_THRESHOLD, TimeUnit.MILLISECONDS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌下发结果监听
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
@MqttServerFunction("device/${sn}/message/down/white_list_operator/reply")
|
@MqttServerFunction("device/${sn}/message/down/white_list_operator/reply")
|
||||||
public void white_list_operator_reply(String topic, byte[] payload) {
|
@Transactional(rollbackFor = Exception.class)
|
||||||
log.info("接收到消息 -> Topic: {}, Payload: {}", topic, new String(payload));
|
public void white_list_operator_reply(String topic, byte[] message) {
|
||||||
// 在这里添加您的业务逻辑,例如:
|
log.info("接收到车牌下发消息 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
// 1. 解析 payload
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
// 2. 更新设备在线状态
|
WhiteListOperatorPO whiteListOperatorPO = JSONObject.parseObject(data, WhiteListOperatorPO.class);
|
||||||
// 3. 回复心跳响应等
|
if (null == whiteListOperatorPO || 200 != whiteListOperatorPO.getCode()) {
|
||||||
|
log.error("white_list_operator发布失败:{}", data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CarParkRecord carParkRecord = new CarParkRecord();
|
||||||
|
carParkRecord.setClientId(whiteListOperatorPO.getId());
|
||||||
|
//新增修改和删除车牌得回执信息一致,通过id区分
|
||||||
|
if (whiteListOperatorPO.getId().contains("del_")) {
|
||||||
|
carParkRecord.setSync("2");
|
||||||
|
} else {
|
||||||
|
carParkRecord.setSync("1");
|
||||||
|
}
|
||||||
|
carParkRecordService.updateByClientId(carParkRecord);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌入场出场识别监听
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@MqttServerFunction("device/${sn}/message/up/ivs_result")
|
||||||
|
public void ivs_result(String topic, Map<String, String> topicVars, byte[] message) throws Exception {
|
||||||
|
String sn = topicVars.get("sn");
|
||||||
|
log.info("接收到车辆识别消息 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
|
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||||
|
JSONObject payload = jsonObject.getJSONObject("payload");
|
||||||
|
JSONObject alarmInfoPlate = payload.getJSONObject("AlarmInfoPlate");
|
||||||
|
JSONObject result = alarmInfoPlate.getJSONObject("result");
|
||||||
|
JSONObject plateResult = result.getJSONObject("PlateResult");
|
||||||
|
String license = plateResult.getString("license");
|
||||||
|
String colorType = plateResult.getString("colorType");
|
||||||
|
String str = "";
|
||||||
|
if ("5".equals(colorType)) {
|
||||||
|
str = AESUtil.decrptyAES_ECB(license, key).substring(0, 20);
|
||||||
|
} else {
|
||||||
|
str = AESUtil.decrptyAES_ECB(license, key).substring(0, 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
license = AESUtil.UTF8decode(str);
|
||||||
|
log.info("解密前车牌:{},解谜后的车牌:{}", plateResult.getString("license"), license);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车辆离线识别监听
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@MqttServerFunction("device/${sn}/message/up/ivs_result_offline")
|
||||||
|
public void ivs_result_offline(String topic, Map<String, String> topicVars, byte[] message) throws Exception {
|
||||||
|
String sn = topicVars.get("sn");
|
||||||
|
log.info("接收到车辆离线识别消息 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
|
log.info("车牌离线识别监听:{}", data);
|
||||||
|
JSONObject jsonObject = JSONObject.parseObject(data);
|
||||||
|
JSONObject payload = jsonObject.getJSONObject("payload");
|
||||||
|
JSONObject alarmInfoPlate = payload.getJSONObject("AlarmInfoPlate");
|
||||||
|
JSONObject result = alarmInfoPlate.getJSONObject("result");
|
||||||
|
JSONObject plateResult = result.getJSONObject("PlateResult");
|
||||||
|
String license = plateResult.getString("license");
|
||||||
|
String colorType = plateResult.getString("colorType");
|
||||||
|
String str = "";
|
||||||
|
if ("5".equals(colorType)) {
|
||||||
|
str = AESUtil.decrptyAES_ECB(license, key).substring(0, 20);
|
||||||
|
} else {
|
||||||
|
str = AESUtil.decrptyAES_ECB(license, key).substring(0, 18);
|
||||||
|
}
|
||||||
|
|
||||||
|
license = AESUtil.UTF8decode(str);
|
||||||
|
log.info("离线-解密前车牌:{},解谜后的车牌:{}", plateResult.getString("license"), license);
|
||||||
|
CarParkItem carParkItem = carParkItemService.selectBySn(sn);
|
||||||
|
CarPassRecord carPassRecord = new CarPassRecord();
|
||||||
|
carPassRecord.setSn(sn);
|
||||||
|
carPassRecord.setParkId(carParkItem.getParkId());
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO输出事件监听
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@MqttServerFunction("device/${sn}/message/down/gpio_out/reply")
|
||||||
|
public void gpio_out(String topic, byte[] message) {
|
||||||
|
log.info("IO输出事件监听消息 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
|
|
||||||
|
log.info("IO输出事件监听:{}", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IO锁定事件监听
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@MqttServerFunction("device/${sn}/message/down/set_io_lock_status/reply")
|
||||||
|
public void set_io_lock_status(String topic, byte[] message) {
|
||||||
|
log.info("IO锁定事件监听消息 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
|
log.info("IO锁定事件监听:{}", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 订阅离线数据数量
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
@MqttServerFunction("device/${sn}/message/up/offline_record")
|
||||||
|
public void offline_record(String topic, byte[] message) {
|
||||||
|
log.info("订阅离线数据数量 -> Topic: {}, message: {}", topic, new String(message));
|
||||||
|
String data = new String(message, StandardCharsets.UTF_8);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,11 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Mapper
|
@Mapper
|
||||||
public interface CarInfoMapper extends BaseMapper<CarInfo> {
|
public interface CarInfoMapper extends BaseMapper<CarInfo> {
|
||||||
|
|
||||||
|
List<CarInfo> selectCarInfoList(CarInfo car);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkItem;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CarParkItemMapper extends BaseMapper<CarParkItem> {
|
||||||
|
|
||||||
|
@Select("SELECT p.id,p.park_id parkId,p.way,p.equipment_id equipmentId,p.area FROM car_park_item p left join sys_equipment e on p.equipment_id = e.id where e.sequence = #{sn} and e.product_id = 4 limit 1")
|
||||||
|
CarParkItem selectBySn(@Param("sn") String sn);
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkRecord;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CarParkRecordMapper extends BaseMapper<CarParkRecord> {
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
package org.dromara.mica.mqtt.server.pojo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class User<T> {
|
|
||||||
private String name;
|
|
||||||
private T girlfriend;
|
|
||||||
|
|
||||||
public static User newUser(){
|
|
||||||
User<User> user1 = new User();
|
|
||||||
user1.setName("name1");
|
|
||||||
|
|
||||||
User<User> user2 = new User();
|
|
||||||
user2.setName("name2");
|
|
||||||
user2.setGirlfriend(user1);
|
|
||||||
return user2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.pojo;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备报文数据实体
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class WhiteListOperatorPO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* id
|
||||||
|
*/
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 回执的code
|
||||||
|
*/
|
||||||
|
private Integer code;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 设备编码
|
||||||
|
*/
|
||||||
|
private String sn;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 报文名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 版本
|
||||||
|
*/
|
||||||
|
private String version = "1.0";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内容
|
||||||
|
*/
|
||||||
|
private JSONObject payload;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间戳(精确到秒)
|
||||||
|
*/
|
||||||
|
private Long timestamp = System.currentTimeMillis() / 1000;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -3,7 +3,11 @@ package org.dromara.mica.mqtt.server.service;
|
|||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface ICarInfoService extends IService<CarInfo> {
|
public interface ICarInfoService extends IService<CarInfo> {
|
||||||
|
|
||||||
CarInfo selectCarInfoBySn(String sn);
|
CarInfo selectCarInfoBySn(String sn);
|
||||||
|
|
||||||
|
List<CarInfo> selectCarInfoList(CarInfo car);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkItem;
|
||||||
|
|
||||||
|
public interface ICarParkItemService extends IService<CarParkItem> {
|
||||||
|
|
||||||
|
CarParkItem selectBySn(String sn);
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkRecord;
|
||||||
|
|
||||||
|
public interface ICarParkRecordService extends IService<CarParkRecord> {
|
||||||
|
|
||||||
|
int updateByClientId(CarParkRecord carParkRecord);
|
||||||
|
|
||||||
|
void delByClientId(CarParkRecord carParkRecord);
|
||||||
|
}
|
||||||
@@ -8,6 +8,8 @@ import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
|||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class CarInfoServiceImpl extends ServiceImpl<CarInfoMapper, CarInfo> implements ICarInfoService {
|
public class CarInfoServiceImpl extends ServiceImpl<CarInfoMapper, CarInfo> implements ICarInfoService {
|
||||||
|
|
||||||
@@ -20,4 +22,9 @@ public class CarInfoServiceImpl extends ServiceImpl<CarInfoMapper, CarInfo> impl
|
|||||||
|
|
||||||
return new CarInfo();
|
return new CarInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<CarInfo> selectCarInfoList(CarInfo car) {
|
||||||
|
return carInfoMapper.selectCarInfoList(car);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkItem;
|
||||||
|
import org.dromara.mica.mqtt.server.mapper.CarParkItemMapper;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarParkItemService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CarParkItemServiceImpl extends ServiceImpl<CarParkItemMapper, CarParkItem> implements ICarParkItemService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CarParkItemMapper carParkItemMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CarParkItem selectBySn(String sn) {
|
||||||
|
return carParkItemMapper.selectBySn(sn);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkRecord;
|
||||||
|
import org.dromara.mica.mqtt.server.mapper.CarParkRecordMapper;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarParkRecordService;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class CarParkRecordServiceImpl extends ServiceImpl<CarParkRecordMapper, CarParkRecord> implements ICarParkRecordService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
CarParkRecordMapper carParkRecordMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int updateByClientId(CarParkRecord carParkRecord) {
|
||||||
|
int id = carParkRecordMapper.update(carParkRecord, new QueryWrapper<CarParkRecord>().eq("client_id", carParkRecord.getClientId()));
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void delByClientId(CarParkRecord carParkRecord) {
|
||||||
|
carParkRecordMapper.delete(new QueryWrapper<CarParkRecord>().eq("client_id", carParkRecord.getClientId()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,8 +17,32 @@ public class ServerService {
|
|||||||
private MqttServerTemplate server;
|
private MqttServerTemplate server;
|
||||||
|
|
||||||
public boolean publish(String body) {
|
public boolean publish(String body) {
|
||||||
boolean result = server.publishAll("/test/123", body.getBytes(StandardCharsets.UTF_8));
|
boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/down/white_list_operator", body.getBytes(StandardCharsets.UTF_8));
|
||||||
log.info("Mqtt publishAll result:{}", result);
|
log.info("测试body:{},result:{}", body, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean open(String body) {
|
||||||
|
boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/down/gpio_out", body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("IO输出测试body:{},result:{}", body, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean open2(String body) {
|
||||||
|
boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/down/set_io_lock_status", body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("IO锁定测试body:{},result:{}", body, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean check_offline_record(String body) {
|
||||||
|
boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/down/check_offline_record", body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("发布离线记录推送body:{},result:{}", body, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean offline_record(String body) {
|
||||||
|
boolean result = server.publish("61e70b04-8e68be6a","device/61e70b04-8e68be6a/message/up/offline_record", body.getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("发布离线数据数量body:{},result:{}", body, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Service
|
@Service
|
||||||
public class HeartbeatOnLine {
|
public class HeartbeatOnLineTask {
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
RedisService redisService;
|
RedisService redisService;
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.task;
|
||||||
|
|
||||||
|
import cn.hutool.core.date.DatePattern;
|
||||||
|
import cn.hutool.core.date.DateUtil;
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.dromara.mica.mqtt.core.server.MqttServer;
|
||||||
|
import org.dromara.mica.mqtt.server.constant.CacheConstants;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarInfo;
|
||||||
|
import org.dromara.mica.mqtt.server.entity.CarParkRecord;
|
||||||
|
import org.dromara.mica.mqtt.server.pojo.WhiteListOperatorPO;
|
||||||
|
import org.dromara.mica.mqtt.server.redis.RedisService;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarInfoService;
|
||||||
|
import org.dromara.mica.mqtt.server.service.ICarParkRecordService;
|
||||||
|
import org.dromara.mica.mqtt.server.utils.UuidUtil;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.tio.utils.hutool.CollUtil;
|
||||||
|
import org.tio.utils.hutool.StrUtil;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 车牌下发设备定时任务
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Service
|
||||||
|
public class PlatePublishTask {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private MqttServer mqttServer;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ICarInfoService carInfoService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
ICarParkRecordService carParkRecordService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
RedisService redisService;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定时查询数据库需要下发的车辆进行下发
|
||||||
|
*/
|
||||||
|
@Scheduled(fixedDelay = 8 * 1000)
|
||||||
|
public void run() {
|
||||||
|
String whiteUrl = "device/%s/message/down/white_list_operator";
|
||||||
|
|
||||||
|
//新增&编辑车牌
|
||||||
|
CarInfo carInfo = new CarInfo();
|
||||||
|
carInfo.setDelFlag("0");
|
||||||
|
carInfo.setSync("0");
|
||||||
|
List<CarInfo> carInfoList = carInfoService.selectCarInfoList(carInfo);
|
||||||
|
if (CollUtil.isNotEmpty(carInfoList)) {
|
||||||
|
//向设备下发车辆信息
|
||||||
|
for (CarInfo car : carInfoList) {
|
||||||
|
//如果该设备没有心跳,不下发车牌信息
|
||||||
|
if (!redisService.hasKey(CacheConstants.EQUIPMENT_HEARTBEAT + car.getSn())) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
String topic = String.format(whiteUrl, car.getSn());
|
||||||
|
WhiteListOperatorPO po = new WhiteListOperatorPO();
|
||||||
|
String uuid = "add_" + UuidUtil.getUuid();
|
||||||
|
po.setId(uuid);
|
||||||
|
po.setSn(car.getSn());
|
||||||
|
po.setName("white_list_operator");
|
||||||
|
|
||||||
|
//构造数据
|
||||||
|
if (StrUtil.equals(car.getSn(), car.getSn())) {
|
||||||
|
po.setPayload(buildPayload(car));
|
||||||
|
}
|
||||||
|
|
||||||
|
//更新car_park_record表的clientId,用于回执消息更新下发状态
|
||||||
|
//必须在发送前更新,不然会导致发送后,还没更新完数据库,回执已经收到,无法更新数据,导致持续下发车牌
|
||||||
|
CarParkRecord carParkRecord = new CarParkRecord();
|
||||||
|
carParkRecord.setId(car.getCarParkRecordId());
|
||||||
|
carParkRecord.setClientId(uuid);
|
||||||
|
carParkRecordService.updateById(carParkRecord);
|
||||||
|
|
||||||
|
//发布车牌到设备(协议只能单条发布)
|
||||||
|
boolean publish = mqttServer.publish(car.getSn(), topic, JSON.toJSONString(po).getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("定时任务下发车牌topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(po), publish);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//删除车牌
|
||||||
|
CarInfo carDel = new CarInfo();
|
||||||
|
carDel.setDelFlag("2");
|
||||||
|
carDel.setSync("1");
|
||||||
|
List<CarInfo> carInfos = carInfoService.selectCarInfoList(carDel);
|
||||||
|
if (CollUtil.isNotEmpty(carInfos)) {
|
||||||
|
//需要下发的设备
|
||||||
|
List<String> snList = carInfos.stream().map(CarInfo::getSn).distinct().toList();
|
||||||
|
for (String sn : snList) {
|
||||||
|
if (!redisService.hasKey(CacheConstants.EQUIPMENT_HEARTBEAT + sn)) {
|
||||||
|
log.error("删除车牌,设备:{},无心跳", sn);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//车辆授权列表
|
||||||
|
List<CarParkRecord> carParkRecords = new ArrayList<>();
|
||||||
|
|
||||||
|
String topic = String.format(whiteUrl, sn);
|
||||||
|
WhiteListOperatorPO po = new WhiteListOperatorPO();
|
||||||
|
String uuid = "del_" + UuidUtil.getUuid();
|
||||||
|
po.setId(uuid);
|
||||||
|
po.setSn(sn);
|
||||||
|
po.setName("white_list_operator");
|
||||||
|
|
||||||
|
|
||||||
|
//构造内层数据
|
||||||
|
List<String> plates = new ArrayList<>();
|
||||||
|
for (CarInfo car : carInfos) {
|
||||||
|
if (StrUtil.equals(car.getSn(), car.getSn())) {
|
||||||
|
plates.add(car.getPlate());
|
||||||
|
|
||||||
|
CarParkRecord carParkRecord = new CarParkRecord();
|
||||||
|
carParkRecord.setClientId(uuid);
|
||||||
|
carParkRecord.setId(car.getCarParkRecordId());
|
||||||
|
carParkRecords.add(carParkRecord);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
po.setPayload(buildPayloadDel(plates));
|
||||||
|
|
||||||
|
//更新车辆授权信息
|
||||||
|
if (CollUtil.isNotEmpty(carParkRecords)) {
|
||||||
|
carParkRecordService.saveOrUpdateBatch(carParkRecords);
|
||||||
|
}
|
||||||
|
//发布车牌到设备
|
||||||
|
boolean publish = mqttServer.publish(sn, topic, JSON.toJSONString(po).getBytes(StandardCharsets.UTF_8));
|
||||||
|
log.info("定时任务删除车牌topic:{},报文数据:{},发送结果:{}", topic, JSON.toJSONString(po), publish);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private JSONObject buildPayload(CarInfo carInfo) {
|
||||||
|
//新增&更新车牌
|
||||||
|
if (StrUtil.isNotBlank(carInfo.getSegTime())) {
|
||||||
|
String[] split = carInfo.getSegTime().split("-");
|
||||||
|
carInfo.setSegTimeStart(split[0]);
|
||||||
|
carInfo.setSegTimeEnd(split[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
JSONObject dldbRec = new JSONObject();
|
||||||
|
dldbRec.put("create_time", DateUtil.format(new Date(), DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
dldbRec.put("enable_time", DateUtil.format(carInfo.getEnableTime(), DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
dldbRec.put("overdue_time", DateUtil.format(carInfo.getOverdueTime(), DatePattern.NORM_DATETIME_PATTERN));
|
||||||
|
dldbRec.put("enable", Integer.parseInt(carInfo.getEnable()));
|
||||||
|
dldbRec.put("plate", carInfo.getPlate());
|
||||||
|
dldbRec.put("time_seg_enable", Integer.parseInt(carInfo.getTimeSegEnable()));
|
||||||
|
dldbRec.put("seg_time_start", carInfo.getSegTimeStart() == null ? "00:00:00" : carInfo.getSegTimeStart());
|
||||||
|
dldbRec.put("seg_time_end", carInfo.getSegTimeEnd() == null ? "00:00:00" : carInfo.getSegTimeEnd());
|
||||||
|
dldbRec.put("need_alarm", Integer.parseInt(carInfo.getNeedAlarm()));
|
||||||
|
|
||||||
|
JSONObject body = new JSONObject();
|
||||||
|
body.put("operator_type", "update_or_add");
|
||||||
|
body.put("dldb_rec", dldbRec);
|
||||||
|
|
||||||
|
|
||||||
|
JSONObject payload = new JSONObject();
|
||||||
|
payload.put("type", "white_list_operator");
|
||||||
|
payload.put("body", body);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
private JSONObject buildPayloadDel(List<String> plates) {
|
||||||
|
JSONObject body = new JSONObject();
|
||||||
|
body.put("operator_type", "delete");
|
||||||
|
body.put("plate", plates);
|
||||||
|
JSONObject payload = new JSONObject();
|
||||||
|
payload.put("type", "white_list_operator");
|
||||||
|
payload.put("body", body);
|
||||||
|
return payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
package org.dromara.mica.mqtt.server.task;
|
|
||||||
|
|
||||||
import org.dromara.mica.mqtt.core.server.MqttServer;
|
|
||||||
import org.dromara.mica.mqtt.server.pojo.User;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author wsq
|
|
||||||
*/
|
|
||||||
@Service
|
|
||||||
public class PublishAllTask {
|
|
||||||
@Autowired
|
|
||||||
private MqttServer mqttServer;
|
|
||||||
|
|
||||||
// @Scheduled(fixedDelay = 1000)
|
|
||||||
// public void run() {
|
|
||||||
// mqttServer.publishAll("/test/123", "mica最牛皮".getBytes(StandardCharsets.UTF_8));
|
|
||||||
// mqttServer.publishAll("/test/object", User.newUser());
|
|
||||||
// }
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.spec.IvParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
import java.io.UnsupportedEncodingException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES加密工具类
|
||||||
|
*/
|
||||||
|
public class AESUtil {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密Key 需要16位 可用数字与字母组成
|
||||||
|
*/
|
||||||
|
private static String key = "1234567898765432";
|
||||||
|
/**
|
||||||
|
* 偏移量 需要16位
|
||||||
|
*/
|
||||||
|
private static String iv = "4w2Df1xSj5ff662d";
|
||||||
|
|
||||||
|
private static Logger log = LoggerFactory.getLogger(AESUtil.class);
|
||||||
|
|
||||||
|
private static Base64.Decoder decoder;
|
||||||
|
|
||||||
|
private static Base64.Encoder encoder;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static {
|
||||||
|
decoder = Base64.getDecoder();
|
||||||
|
encoder = Base64.getEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static String getSixteenBitString(){
|
||||||
|
StringBuffer sb = new StringBuffer();
|
||||||
|
String[] chars = new String[]{
|
||||||
|
"1","2","3","4","5","6","7","8","9","a","b",
|
||||||
|
"c","d","e","f","g","h","i","j","k","l","m",
|
||||||
|
"n","o","p","q","r","s","t","u","v","w","x",
|
||||||
|
"y","z","A","B","C","D","E","F","G","H","I",
|
||||||
|
"J","K","L","M","N","O","P","Q","R","S","T",
|
||||||
|
"U","V","W","X","Y","Z",
|
||||||
|
};
|
||||||
|
int len = chars.length;
|
||||||
|
Random random = new Random();
|
||||||
|
for (int i = 0; i < 16; i++) {
|
||||||
|
sb.append(chars[random.nextInt(len-1)]);
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES加密
|
||||||
|
* @param data
|
||||||
|
* @param key
|
||||||
|
* @param iv
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static String encryptAES_CBC(String data,String key,String iv) {
|
||||||
|
Cipher cipher = null;
|
||||||
|
try {
|
||||||
|
cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||||
|
|
||||||
|
int blockSize = cipher.getBlockSize();
|
||||||
|
byte[] dataBytes = data.getBytes();
|
||||||
|
int dataLength = dataBytes.length;
|
||||||
|
if (dataLength % blockSize != 0) {
|
||||||
|
dataLength = dataLength + (blockSize - (dataLength % blockSize));
|
||||||
|
}
|
||||||
|
byte[] plaintext = new byte[dataLength];
|
||||||
|
System.arraycopy(dataBytes, 0, plaintext, 0, dataBytes.length);
|
||||||
|
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
|
||||||
|
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
|
||||||
|
byte[] bytes = cipher.doFinal(plaintext);
|
||||||
|
return encoder.encodeToString(bytes);
|
||||||
|
|
||||||
|
}catch (Exception e) {
|
||||||
|
log.error("AES加密失败");
|
||||||
|
log.error(e.getMessage());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* AES解密
|
||||||
|
* @param data
|
||||||
|
* @param key
|
||||||
|
* @param iv
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static String decrptyAES_CBC(String data,String key,String iv){
|
||||||
|
try {
|
||||||
|
byte[] bytes = decoder.decode(data);
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
|
||||||
|
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
|
||||||
|
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
|
||||||
|
byte[] plainByte = cipher.doFinal(bytes);
|
||||||
|
return new String(plainByte).trim();
|
||||||
|
}catch (Exception e){
|
||||||
|
log.error("AES解密失败");
|
||||||
|
log.error(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES加密
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static String encryptAES_ECB(String data,String key) throws Exception{
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
||||||
|
int blockSize = cipher.getBlockSize();
|
||||||
|
byte[] dataBytes = data.getBytes();
|
||||||
|
int dataLength = dataBytes.length;
|
||||||
|
if(dataLength % blockSize != 0){
|
||||||
|
dataLength = dataLength + (blockSize - (dataLength % blockSize));
|
||||||
|
}
|
||||||
|
byte [] plaintext = new byte[dataLength];
|
||||||
|
System.arraycopy(dataBytes,0,plaintext,0,dataBytes.length);
|
||||||
|
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),"AES");
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE,secretKey);
|
||||||
|
byte[] bytes = cipher.doFinal(plaintext);
|
||||||
|
return encoder.encodeToString(bytes);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AES解密
|
||||||
|
* @param data
|
||||||
|
* @return
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public static String decrptyAES_ECB(String data,String key) throws Exception{
|
||||||
|
// byte[] bytes = decoder.decode(data);
|
||||||
|
byte[] bytes =Base64.getDecoder().decode(data);
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/ECB/NoPadding");
|
||||||
|
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(),"AES");
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE,secretKey);
|
||||||
|
byte[] plainByte = cipher.doFinal(bytes);
|
||||||
|
return bytesToHex(plainByte);
|
||||||
|
}
|
||||||
|
private static String bytesToHex(byte[] bytes) {
|
||||||
|
StringBuilder hexString = new StringBuilder();
|
||||||
|
for (byte b : bytes) {
|
||||||
|
String hex = Integer.toHexString(0xff & b);
|
||||||
|
if (hex.length() == 1) hexString.append('0');
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gb2312编码
|
||||||
|
*/
|
||||||
|
public static String gb2312decode( String string) throws UnsupportedEncodingException{
|
||||||
|
byte[] bytes = new byte[string.length() / 2];
|
||||||
|
for(int i = 0; i < bytes.length; i ++){
|
||||||
|
byte high = Byte.parseByte(string.substring(i * 2, i * 2 + 1), 16);
|
||||||
|
byte low = Byte.parseByte(string.substring(i * 2 + 1, i * 2 + 2), 16);
|
||||||
|
bytes[i] = (byte) (high << 4 | low);
|
||||||
|
}
|
||||||
|
return new String(bytes, "gb2312");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* UTF8编码
|
||||||
|
*/
|
||||||
|
public static String UTF8decode( String string) throws UnsupportedEncodingException{
|
||||||
|
byte[] bytes = new byte[string.length() / 2];
|
||||||
|
for(int i = 0; i < bytes.length; i ++){
|
||||||
|
byte high = Byte.parseByte(string.substring(i * 2, i * 2 + 1), 16);
|
||||||
|
byte low = Byte.parseByte(string.substring(i * 2 + 1, i * 2 + 2), 16);
|
||||||
|
bytes[i] = (byte) (high << 4 | low);
|
||||||
|
}
|
||||||
|
return new String(bytes, StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception{
|
||||||
|
String encrypt = "IcDSUR8fdtJ8gLYlZX9qLw==";
|
||||||
|
String str = decrptyAES_ECB(encrypt, key);
|
||||||
|
// String str1 = str.substring(0, 16);
|
||||||
|
String license = AESUtil.UTF8decode(str);
|
||||||
|
// System.out.println(gb2312decode(str1));
|
||||||
|
System.out.println(license);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package org.dromara.mica.mqtt.server.utils;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public class UuidUtil {
|
||||||
|
|
||||||
|
public static String[] chars = new String[] { "a", "b", "c", "d", "e", "f",
|
||||||
|
"g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s",
|
||||||
|
"t", "u", "v", "w", "x", "y", "z", "0", "1", "2", "3", "4", "5",
|
||||||
|
"6", "7", "8", "9", "A", "B", "C", "D", "E", "F", "G", "H", "I",
|
||||||
|
"J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V",
|
||||||
|
"W", "X", "Y", "Z" };
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取短UUID
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getShortUuid() {
|
||||||
|
StringBuffer shortBuffer = new StringBuffer();
|
||||||
|
String uuid = UuidUtil.getUuid();
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
String str = uuid.substring(i * 4, i * 4 + 4);
|
||||||
|
int x = Integer.parseInt(str, 16);
|
||||||
|
shortBuffer.append(chars[x % 0x3E]); // 对62取余
|
||||||
|
}
|
||||||
|
return shortBuffer.toString();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获得32位UUID
|
||||||
|
*/
|
||||||
|
public static String getUuid(){
|
||||||
|
String uuid = UUID.randomUUID().toString();
|
||||||
|
//去掉“-”符号
|
||||||
|
return uuid.replaceAll("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://127.0.0.1:3306/xa_cloud?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&nullCatalogMeansCurrent=true
|
url: jdbc:mysql://127.0.0.1:3306/xa_cloud?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
|
||||||
username: root
|
username: root
|
||||||
password: root
|
password: root
|
||||||
data:
|
data:
|
||||||
|
|||||||
@@ -19,6 +19,8 @@
|
|||||||
<result property="delFlag" column="del_flag" />
|
<result property="delFlag" column="del_flag" />
|
||||||
<result property="sync" column="sync" />
|
<result property="sync" column="sync" />
|
||||||
<result property="overclockCard" column="overclock_card" />
|
<result property="overclockCard" column="overclock_card" />
|
||||||
|
<result property="sn" column="sequence" />
|
||||||
|
<result property="carParkRecordId" column="carParkRecordId" />
|
||||||
</resultMap>
|
</resultMap>
|
||||||
|
|
||||||
<sql id="selectCarInfoVo">
|
<sql id="selectCarInfoVo">
|
||||||
@@ -33,7 +35,33 @@
|
|||||||
</sql>
|
</sql>
|
||||||
|
|
||||||
<select id="selectCarInfoList" parameterType="org.dromara.mica.mqtt.server.entity.CarInfo" resultMap="CarInfoResult">
|
<select id="selectCarInfoList" parameterType="org.dromara.mica.mqtt.server.entity.CarInfo" resultMap="CarInfoResult">
|
||||||
<include refid="selectCarInfoVo"/>
|
SELECT
|
||||||
|
ci.customer_id,
|
||||||
|
ci.enable_time,
|
||||||
|
ci.overdue_time,
|
||||||
|
ci.`enable`,
|
||||||
|
ci.plate,
|
||||||
|
ci.time_seg_enable,
|
||||||
|
ci.seg_time,
|
||||||
|
ci.need_alarm,
|
||||||
|
ci.vehicle_code,
|
||||||
|
ci.vehicle_comment,
|
||||||
|
ci.people_id,
|
||||||
|
ci.del_flag,
|
||||||
|
ci.sync,
|
||||||
|
ci.remark,
|
||||||
|
ci.create_by,
|
||||||
|
ci.create_time,
|
||||||
|
ci.update_by,
|
||||||
|
ci.update_time,
|
||||||
|
ci.overclock_card,
|
||||||
|
se.sequence,
|
||||||
|
cpr.id as carParkRecordId
|
||||||
|
FROM car_info ci
|
||||||
|
LEFT JOIN car_park cp ON ci.park_id = cp.id
|
||||||
|
LEFT JOIN sys_people p ON ci.people_id = p.id
|
||||||
|
LEFT JOIN car_park_record cpr ON cpr.customer_id = ci.customer_id
|
||||||
|
LEFT JOIN sys_equipment se ON cpr.equipment_id = se.id
|
||||||
<where>
|
<where>
|
||||||
<if test="enableTime != null "> and ci.enable_time = #{enableTime}</if>
|
<if test="enableTime != null "> and ci.enable_time = #{enableTime}</if>
|
||||||
<if test="overdueTime != null "> and ci.overdue_time = #{overdueTime}</if>
|
<if test="overdueTime != null "> and ci.overdue_time = #{overdueTime}</if>
|
||||||
|
|||||||
Reference in New Issue
Block a user