1
0

设备mqtt收发数据

This commit is contained in:
2025-07-30 08:50:44 +08:00
parent 2b2edf096d
commit ac353b1078
21 changed files with 679 additions and 105 deletions

View File

@ -1,5 +1,6 @@
package com.fuyuanshen.app.controller;
import com.alibaba.fastjson2.JSONObject;
import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo;
import com.fuyuanshen.app.domain.dto.APPReNameDTO;
import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto;
@ -122,4 +123,44 @@ public class AppDeviceController extends BaseController {
return R.ok();
}
/**
* 灯光模式
* 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式
*/
@PostMapping("/lightModeSettings")
public R<Void> lightModeSettings(@RequestBody JSONObject params) {
appDeviceService.lightModeSettings(params);
return R.ok();
}
/**
* 灯光亮度设置
*
*/
@PostMapping("/lightBrightnessSettings")
public R<Void> lightBrightnessSettings(@RequestBody JSONObject params) {
appDeviceService.lightBrightnessSettings(params);
return R.ok();
}
/**
* 激光模式设置
*
*/
@PostMapping("/laserModeSettings")
public R<Void> laserModeSettings(@RequestBody JSONObject params) {
appDeviceService.laserModeSettings(params);
return R.ok();
}
/**
* 地图逆解析
*
*/
@PostMapping("/mapReverseGeocoding")
public R<Void> mapReverseGeocoding(@RequestBody JSONObject params) {
String mapJson = appDeviceService.mapReverseGeocoding(params);
return R.ok(mapJson);
}
}

View File

@ -0,0 +1,13 @@
package com.fuyuanshen.app.domain.dto;
import lombok.Data;
@Data
public class AppLightModeDto {
private Long deviceId;
//0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式
private Integer mode;
}

View File

@ -1,6 +1,7 @@
package com.fuyuanshen.app.service;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
@ -21,6 +22,7 @@ import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
import com.fuyuanshen.common.core.utils.MapstructUtils;
import com.fuyuanshen.common.core.utils.ObjectUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.mybatis.core.page.PageQuery;
import com.fuyuanshen.common.mybatis.core.page.TableDataInfo;
import com.fuyuanshen.common.redis.utils.RedisUtils;
@ -40,8 +42,8 @@ import static com.fuyuanshen.common.core.utils.Bitmap80x12Generator.*;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
import com.fuyuanshen.equipment.utils.c.ReliableTextToBitmap;
import com.fuyuanshen.system.mqtt.config.MqttGateway;
import com.fuyuanshen.system.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@ -352,7 +354,7 @@ public class AppDeviceBizService {
System.out.println("原始数据大小: " + largeData.length + " 字节");
int[] ints = convertHexToDecimal(largeData);
RedisUtils.setCacheObject("app_logo_data:"+device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(24*60*60L));
RedisUtils.setCacheObject("app_logo_data:"+device.getDeviceImei(), Arrays.toString(ints), Duration.ofSeconds(30*60L));
String data = RedisUtils.getCacheObject("app_logo_data:"+device.getDeviceImei());
@ -377,4 +379,96 @@ public class AppDeviceBizService {
e.printStackTrace();
}
}
/**
* 灯光模式
* 0关灯1强光模式2弱光模式, 3爆闪模式, 4泛光模式
*/
public void lightModeSettings(JSONObject params) {
try {
Long deviceId = params.getLong("deviceId");
Device device = deviceMapper.selectById(deviceId);
if(device == null){
throw new ServiceException("设备不存在");
}
Integer instructValue = params.getInteger("instructValue");
ArrayList<Integer> intData = new ArrayList<>();
intData.add(1);
intData.add(instructValue);
intData.add(0);
intData.add(0);
intData.add(0);
Map<String, Object> map = new HashMap<>();
map.put("instruct", intData);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map));
log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map));
} catch (Exception e){
e.printStackTrace();
}
}
//灯光亮度设置
public void lightBrightnessSettings(JSONObject params) {
try {
Long deviceId = params.getLong("deviceId");
Device device = deviceMapper.selectById(deviceId);
if(device == null){
throw new ServiceException("设备不存在");
}
String instructValue = params.getString("instructValue");
ArrayList<Integer> intData = new ArrayList<>();
intData.add(5);
String[] values = instructValue.split("\\.");
String value1 = values[0];
String value2 = values[1];
if(StringUtils.isNoneBlank(value1)){
intData.add(Integer.parseInt(value1));
}
if(StringUtils.isNoneBlank(value2)){
intData.add(Integer.parseInt(value2));
}
intData.add(0);
intData.add(0);
intData.add(0);
Map<String, Object> map = new HashMap<>();
map.put("instruct", intData);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map));
log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map));
} catch (Exception e){
e.printStackTrace();
}
}
//激光模式设置
public void laserModeSettings(JSONObject params) {
try {
Long deviceId = params.getLong("deviceId");
Device device = deviceMapper.selectById(deviceId);
if(device == null){
throw new ServiceException("设备不存在");
}
Integer instructValue = params.getInteger("instructValue");
ArrayList<Integer> intData = new ArrayList<>();
intData.add(4);
intData.add(instructValue);
intData.add(0);
intData.add(0);
intData.add(0);
Map<String, Object> map = new HashMap<>();
map.put("instruct", intData);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(), 1 , JSON.toJSONString(map));
log.info("发送点阵数据到设备消息=>topic:{},payload:{}", MqttConstants.GLOBAL_PUB_KEY+device.getDeviceImei(),JSON.toJSONString(map));
} catch (Exception e){
e.printStackTrace();
}
}
public String mapReverseGeocoding(JSONObject params) {
Long deviceId = params.getLong("deviceId");
Device device = deviceMapper.selectById(deviceId);
if(device == null){
throw new ServiceException("设备不存在");
}
return RedisUtils.getCacheObject("device:location:" + device.getDeviceImei());
}
}

View File

@ -0,0 +1,26 @@
package com.fuyuanshen.global.mqtt.base;
/**
* MQTT消息处理接口
*/
public interface MqttMessageRule {
/**
* 获取命令类型
* @return 命令类型
*/
Integer getCommandType();
/**
* 执行处理
* @param context 处理上下文
*/
void execute(MqttRuleContext context);
/**
* 获取优先级,数值越小优先级越高
* @return 优先级
*/
default int getPriority() {
return 0;
}
}

View File

@ -0,0 +1,32 @@
package com.fuyuanshen.global.mqtt.base;
import lombok.Data;
import java.util.Map;
/**
* MQTT消息处理上下文
*/
@Data
public class MqttRuleContext {
/**
* 命令类型
*/
private byte commandType;
/**
* 转换后的参数数组
*/
private Object[] convertArr;
/**
* 设备IMEI
*/
private String deviceImei;
/**
* 数据来源Redis
*/
private String dataFromRedis;
/**
* MQTT消息负载字典
*/
private Map<String, Object> payloadDict;
}

View File

@ -0,0 +1,38 @@
package com.fuyuanshen.global.mqtt.base;
import org.springframework.stereotype.Component;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
/**
* MQTT消息引擎
*/
@Component
public class MqttRuleEngine {
private final LinkedHashMap<Integer, MqttMessageRule> rulesMap = new LinkedHashMap<>();
public MqttRuleEngine(List<MqttMessageRule> rules) {
// 按优先级排序
rules.sort(Comparator.comparing(MqttMessageRule::getPriority));
rules.forEach(rule -> rulesMap.put(rule.getCommandType(), rule));
}
/**
* 执行匹配
* @param context 处理上下文
* @return
*/
public boolean executeRule(MqttRuleContext context) {
int commandType = context.getCommandType();
MqttMessageRule mqttMessageRule = rulesMap.get(commandType);
if (mqttMessageRule != null) {
mqttMessageRule.execute(context);
return true;
}
return false;
}
}

View File

@ -0,0 +1,31 @@
package com.fuyuanshen.global.mqtt.config;
import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
@Configuration
public class MqttConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
/** 创建连接工厂 **/
@Bean
public MqttPahoClientFactory mqttPahoClientFactory(){
DefaultMqttPahoClientFactory factory = new DefaultMqttPahoClientFactory();
MqttConnectOptions options = new MqttConnectOptions();
options.setCleanSession(true); //设置新会话
options.setUserName(mqttPropertiesConfig.getUsername());
options.setPassword(mqttPropertiesConfig.getPassword().toCharArray());
options.setServerURIs(new String[]{mqttPropertiesConfig.getUrl()});
options.setAutomaticReconnect(true); // 启用自动重连
options.setConnectionTimeout(10); // 设置连接超时时间
options.setKeepAliveInterval(60); // 设置心跳间隔
factory.setConnectionOptions(options);
return factory;
}
}

View File

@ -0,0 +1,17 @@
package com.fuyuanshen.global.mqtt.config;
import org.springframework.integration.annotation.MessagingGateway;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
/**
* @Author: HarryLin
* @Date: 2025/3/20 17:06
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@MessagingGateway(defaultRequestChannel = "mqttOutboundChannel")
public interface MqttGateway {
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, String payload);
public abstract void sendMsgToMqtt(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload );
}

View File

@ -0,0 +1,58 @@
package com.fuyuanshen.global.mqtt.config;
import cn.hutool.core.lang.UUID;
import com.fuyuanshen.global.mqtt.receiver.ReceiverMessageHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.core.MessageProducer;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.inbound.MqttPahoMessageDrivenChannelAdapter;
import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@Configuration
public class MqttInboundConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
@Autowired
private MqttPahoClientFactory mqttPahoClientFactory;
@Autowired
private ReceiverMessageHandler receiverMessageHandler;
//消息通道
@Bean
public MessageChannel messageInboundChannel(){
return new DirectChannel();
}
/**
* 配置入站适配器
* 作用: 设置订阅主题,以及指定消息的通道 等相关属性
* */
@Bean
public MessageProducer messageProducer(){
// 生成一个不重复的随机数
String clientId = mqttPropertiesConfig.getSubClientId() + "_" + UUID.fastUUID();
MqttPahoMessageDrivenChannelAdapter mqttPahoMessageDrivenChannelAdapter = new MqttPahoMessageDrivenChannelAdapter(
mqttPropertiesConfig.getUrl(),
clientId,
mqttPahoClientFactory,
mqttPropertiesConfig.getSubTopic().split(",")
);
mqttPahoMessageDrivenChannelAdapter.setQos(1);
mqttPahoMessageDrivenChannelAdapter.setConverter(new DefaultPahoMessageConverter());
mqttPahoMessageDrivenChannelAdapter.setOutputChannel(messageInboundChannel());
return mqttPahoMessageDrivenChannelAdapter;
}
/** 指定处理消息来自哪个通道 */
@Bean
@ServiceActivator(inputChannel = "messageInboundChannel")
public MessageHandler messageHandler(){
return receiverMessageHandler;
}
}

View File

@ -0,0 +1,46 @@
package com.fuyuanshen.global.mqtt.config;
import cn.hutool.core.lang.UUID;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.channel.DirectChannel;
import org.springframework.integration.mqtt.core.MqttPahoClientFactory;
import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler;
import org.springframework.messaging.MessageChannel;
import org.springframework.messaging.MessageHandler;
@Configuration
@Slf4j
public class MqttOutboundConfiguration {
@Autowired
private MqttPropertiesConfig mqttPropertiesConfig;
@Autowired
private MqttPahoClientFactory mqttPahoClientFactory;
// 消息通道
@Bean
public MessageChannel mqttOutboundChannel(){
return new DirectChannel();
}
/** 配置出站消息处理器 */
@Bean
@ServiceActivator(inputChannel = "mqttOutboundChannel") // 指定处理器针对哪个通道的消息进行处理
public MessageHandler mqttOutboundMessageHandler(){
String clientId = mqttPropertiesConfig.getPubClientId() + "_" + UUID.fastUUID();
MqttPahoMessageHandler mqttPahoMessageHandler = new MqttPahoMessageHandler(
mqttPropertiesConfig.getUrl(),
clientId,
mqttPahoClientFactory
);
mqttPahoMessageHandler.setDefaultQos(1);
mqttPahoMessageHandler.setDefaultTopic("B/#");
mqttPahoMessageHandler.setAsync(true);
return mqttPahoMessageHandler;
}
}

View File

@ -0,0 +1,19 @@
package com.fuyuanshen.global.mqtt.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@ConfigurationProperties(prefix = "mqtt")
@Component
public class MqttPropertiesConfig {
private String username;
private String password;
private String url;
private String subClientId;
private String subTopic;
private String pubClientId;
private String pubTopic;
}

View File

@ -0,0 +1,78 @@
package com.fuyuanshen.global.mqtt.constants;
/**
* 设备命令类型常量
* Device Command Type Constants
*/
public class DeviceCommandTypeConstants {
/**
* 灯光模式 (Light Mode)
*/
public static final int LIGHT_MODE = 1;
/**
* 人员信息 (Personnel Information)
*/
public static final int PERSONNEL_INFO = 2;
/**
* 开机LOGO (Boot Logo)
*/
public static final int BOOT_LOGO = 3;
/**
* 激光灯 (Laser Light)
*/
public static final int LASER_LIGHT = 4;
/**
* 主灯亮度 (Main Light Brightness)
*/
public static final int MAIN_LIGHT_BRIGHTNESS = 5;
/**
* 定位数据 (Location Data)
*/
public static final int LOCATION_DATA = 11;
/**
* 获取命令类型描述
*
* @param commandType 命令类型
* @return 命令类型描述
*/
public static String getCommandTypeDescription(int commandType) {
switch (commandType) {
case LIGHT_MODE:
return "灯光模式 (Light Mode)";
case PERSONNEL_INFO:
return "人员信息 (Personnel Information)";
case BOOT_LOGO:
return "开机LOGO (Boot Logo)";
case LASER_LIGHT:
return "激光灯 (Laser Light)";
case MAIN_LIGHT_BRIGHTNESS:
return "主灯亮度 (Main Light Brightness)";
case LOCATION_DATA:
return "定位数据 (Location Data)";
default:
return "未知命令类型 (Unknown Command Type)";
}
}
/**
* 检查是否为有效命令类型
*
* @param commandType 命令类型
* @return 是否有效
*/
public static boolean isValidCommandType(int commandType) {
return commandType == LIGHT_MODE ||
commandType == PERSONNEL_INFO ||
commandType == BOOT_LOGO ||
commandType == LASER_LIGHT ||
commandType == MAIN_LIGHT_BRIGHTNESS ||
commandType == LOCATION_DATA;
}
}

View File

@ -0,0 +1,16 @@
package com.fuyuanshen.global.mqtt.constants;
public interface MqttConstants {
/**
* 全局发布消息的key
*/
String GLOBAL_PUB_KEY = "B/";
/**
* 全局订阅消息的key
*/
String GLOBAL_SUB_KEY = "A/";
}

View File

@ -0,0 +1,23 @@
package com.fuyuanshen.global.mqtt.publish;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/")
@Slf4j
public class DeviceDataController {
@Autowired
private MqttClientTest mqttClientTest;
// @PostMapping("/{deviceId}/command")
public ResponseEntity<String> sendCommand() {
mqttClientTest.sendMsg();
return ResponseEntity.ok("success");
}
}

View File

@ -0,0 +1,22 @@
package com.fuyuanshen.global.mqtt.publish;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class MqttClientTest {
@Autowired
private MqttGateway mqttGateway;
public void sendMsg() {
mqttGateway.sendMsgToMqtt("worker/location/1", "hello mqtt spring boot");
log.info("message is send");
mqttGateway.sendMsgToMqtt("worker/alert/2", "hello mqtt spring boot2");
log.info("message is send2");
}
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.global.mqtt.publish;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.integration.mqtt.support.MqttHeaders;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.stereotype.Service;
/**
* @Author: HarryLin
* @Date: 2025/3/20 16:16
* @Company: 北京红山信息科技研究院有限公司
* @Email: linyun@***.com.cn
**/
@Service
public class MqttMessageSender {
@Autowired
private MqttGateway mqttGateway;
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, String payload) {
mqttGateway.sendMsgToMqtt(topic,payload);
}
public void sendMsg(@Header(value = MqttHeaders.TOPIC) String topic, @Header(value = MqttHeaders.QOS) int qos, String payload) {
mqttGateway.sendMsgToMqtt(topic,qos,payload);
}
}

View File

@ -0,0 +1,63 @@
package com.fuyuanshen.global.mqtt.receiver;
import cn.hutool.core.lang.Dict;
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.base.MqttRuleEngine;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHandler;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
@Slf4j
public class ReceiverMessageHandler implements MessageHandler {
@Autowired
private MqttRuleEngine ruleEngine;
@Override
public void handleMessage(Message<?> message) throws MessagingException {
Object payload = message.getPayload();
MessageHeaders headers = message.getHeaders();
String receivedTopic = Objects.requireNonNull(headers.get("mqtt_receivedTopic")).toString();
String receivedQos = Objects.requireNonNull(headers.get("mqtt_receivedQos")).toString();
String timestamp = Objects.requireNonNull(headers.get("timestamp")).toString();
log.info("MQTT payload= {} \n receivedTopic = {} \n receivedQos = {} \n timestamp = {}",
payload, receivedTopic, receivedQos, timestamp);
Dict payloadDict = JsonUtils.parseMap(payload.toString());
if (receivedTopic == null || payloadDict == null) {
return;
}
String state = payloadDict.getStr("state");
Object[] convertArr = ImageToCArrayConverter.convertByteStringToMixedObjectArray(state);
if (convertArr.length > 0) {
Byte val1 = (Byte) convertArr[0];
String[] subStr = receivedTopic.split("/");
System.out.println("收到设备id: " + subStr[1]);
String deviceImei = subStr[1];
MqttRuleContext context = new MqttRuleContext();
context.setCommandType(val1);
context.setConvertArr(convertArr);
context.setDeviceImei(deviceImei);
context.setPayloadDict(payloadDict);
boolean ruleExecuted = ruleEngine.executeRule(context);
if (!ruleExecuted) {
log.warn("未找到匹配的规则来处理命令类型: {}", val1);
}
}
}
}

View File

@ -0,0 +1,143 @@
package com.fuyuanshen.global.mqtt.rule;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.utils.c.map.GetAddressFromLatUtil;
import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
/**
* 定位数据命令处理
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class LocationDataRule implements MqttMessageRule {
private final MqttGateway mqttGateway;
@Override
public Integer getCommandType() {
return DeviceCommandTypeConstants.LOCATION_DATA;
}
@Override
public void execute(MqttRuleContext context) {
try {
Object[] convertArr = context.getConvertArr();
// Latitude, longitude
String latitude = convertArr[1].toString();
String longitude = convertArr[2].toString();
// 异步发送经纬度到Redis
asyncSendLocationToRedisWithFuture(context.getDeviceImei(), latitude, longitude);
Map<String, Object> map = buildLocationDataMap(latitude, longitude);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), 1, JsonUtils.toJsonString(map));
log.info("发送定位数据到设备=>topic:{},payload:{}",
MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(),
JsonUtils.toJsonString(map));
} catch (Exception e) {
log.error("处理定位数据命令时出错", e);
}
}
/**
* 异步发送位置信息到Redis
*
* @param deviceImei 设备IMEI
* @param latitude 纬度
* @param longitude 经度
* @param timestamp 时间戳
*/
// @Async
// public void asyncSendLocationToRedis(String deviceImei, String latitude, String longitude, long timestamp) {
// try {
// // 构造位置信息对象
// Map<String, Object> locationInfo = new HashMap<>();
// locationInfo.put("deviceImei", deviceImei);
// locationInfo.put("latitude", latitude);
// locationInfo.put("longitude", longitude);
// locationInfo.put("timestamp", timestamp);
//
// // 将位置信息存储到Redis中使用设备IMEI作为key的一部分
// String redisKey = "device:location:" + deviceImei;
// String locationJson = JsonUtils.toJsonString(locationInfo);
//
// // 存储到Redis设置过期时间例如24小时
// RedisUtils.setCacheObject(redisKey, locationJson, Duration.ofSeconds(24 * 60 * 60));
//
// // 也可以存储到一个列表中,保留历史位置信息
// String locationHistoryKey = "device:location:history:" + deviceImei;
// RedisUtils.lPush(locationHistoryKey, locationJson, 24 * 60 * 60);
//
// log.info("位置信息已异步发送到Redis: device={}, lat={}, lon={}", deviceImei, latitude, longitude);
// } catch (Exception e) {
// log.error("异步发送位置信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
// }
// }
/**
* 异步发送位置信息到Redis使用CompletableFuture
*
* @param deviceImei 设备IMEI
* @param latitude 纬度
* @param longitude 经度
*/
public void asyncSendLocationToRedisWithFuture(String deviceImei, String latitude, String longitude) {
CompletableFuture.runAsync(() -> {
try {
// 构造位置信息对象
Map<String, Object> locationInfo = new LinkedHashMap<>();
locationInfo.put("deviceImei", deviceImei);
locationInfo.put("latitude", latitude);
locationInfo.put("longitude", longitude);
String address = GetAddressFromLatUtil.getAdd(longitude, latitude);
locationInfo.put("address", address);
locationInfo.put("timestamp", System.currentTimeMillis());
// 将位置信息存储到Redis中
String redisKey = "device:location:" + deviceImei;
String locationJson = JsonUtils.toJsonString(locationInfo);
// 存储到Redis
RedisUtils.setCacheObject(redisKey, locationJson, Duration.ofSeconds(24 * 60 * 60));
log.info("位置信息已异步发送到Redis: device={}, lat={}, lon={}", deviceImei, latitude, longitude);
} catch (Exception e) {
log.error("异步发送位置信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
});
}
private Map<String, Object> buildLocationDataMap(String latitude, String longitude) {
String[] latArr = latitude.split("\\.");
String[] lonArr = longitude.split("\\.");
ArrayList<Integer> intData = new ArrayList<>();
intData.add(DeviceCommandTypeConstants.LOCATION_DATA);
intData.add(Integer.parseInt(latArr[0]));
intData.add(Integer.parseInt(latArr[1]));
intData.add(Integer.parseInt(lonArr[0]));
intData.add(Integer.parseInt(lonArr[1]));
Map<String, Object> map = new HashMap<>();
map.put("instruct", intData);
return map;
}
}

View File

@ -0,0 +1,76 @@
package com.fuyuanshen.global.mqtt.rule;
import com.fuyuanshen.common.core.utils.ImageToCArrayConverter;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
/**
* 人员信息命令处理
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class PersonnelInfoRule implements MqttMessageRule {
private final MqttGateway mqttGateway;
@Override
public Integer getCommandType() {
return DeviceCommandTypeConstants.PERSONNEL_INFO;
}
@Override
public void execute(MqttRuleContext context) {
try {
Byte val2 = (Byte) context.getConvertArr()[1];
if (val2 == 100) {
return;
}
String data = RedisUtils.getCacheObject("894078:app_logo_data:" + context.getDeviceImei());
if (StringUtils.isEmpty(data)) {
return;
}
byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data);
byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512);
System.out.println("" + val2 + "块数据大小: " + specificChunk.length + " 字节");
System.out.println("" + val2 + "块数据: " + Arrays.toString(specificChunk));
ArrayList<Integer> intData = new ArrayList<>();
intData.add(3);
intData.add((int) val2);
ImageToCArrayConverter.buildArr(convertHexToDecimal(specificChunk), intData);
intData.add(0);
intData.add(0);
intData.add(0);
intData.add(0);
Map<String, Object> map = new HashMap<>();
map.put("instruct", intData);
mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(), 1, JsonUtils.toJsonString(map));
log.info("发送人员信息点阵数据到设备消息=>topic:{},payload:{}",
MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(),
JsonUtils.toJsonString(map));
} catch (Exception e) {
log.error("处理人员信息命令时出错", e);
}
}
}