1
0

访问控制

This commit is contained in:
2025-08-14 11:51:27 +08:00
parent a8efbb2768
commit 8a6c196fb9
29 changed files with 568 additions and 344 deletions

View File

@ -19,8 +19,8 @@ import com.fuyuanshen.app.domain.vo.AppPersonnelInfoVo;
import com.fuyuanshen.app.mapper.AppDeviceBindRecordMapper;
import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper;
import com.fuyuanshen.app.mapper.equipment.APPDeviceMapper;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.RealTimeStatusEngine;
import com.fuyuanshen.app.service.device.status.base.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.base.RealTimeStatusEngine;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.*;

View File

@ -211,7 +211,6 @@ public class AppDeviceBJQBizService {
}
@FunctionAccessAnnotation("uploadDeviceLogo")
public void uploadDeviceLogo(AppDeviceLogoUploadDto bo) {
try {
Device device = deviceMapper.selectById(bo.getDeviceId());
@ -281,7 +280,6 @@ public class AppDeviceBJQBizService {
}
//灯光亮度设置
@FunctionAccessAnnotation("lightBrightnessSettings")
public void lightBrightnessSettings(DeviceInstructDto params) {
try {
Long deviceId = params.getDeviceId();
@ -314,7 +312,6 @@ public class AppDeviceBJQBizService {
}
//激光模式设置
@FunctionAccessAnnotation("laserModeSettings")
public void laserModeSettings(DeviceInstructDto params) {
try {
Long deviceId = params.getDeviceId();

View File

@ -0,0 +1,77 @@
package com.fuyuanshen.app.service.device.status;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.base.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;
@Slf4j
@Component
public class FunctionAccessBatchStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_2";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getBatchId());
log.info("FunctionAccessBatchStatusRule:{}",functionAccess);
if(StringUtils.isBlank(functionAccess)){
status.put("functionAccess", FunctionAccessStatus.OK.getCode());
return status;
}
List<String> cachedDeviceImeiList = JSONUtil.toList(functionAccess, String.class);
if(cachedDeviceImeiList.isEmpty()){
status.put("functionAccess", FunctionAccessStatus.OK.getCode());
return status;
}
for (String key : cachedDeviceImeiList) {
String item = RedisUtils.getCacheObject(FUNCTION_ACCESS_KEY + key);
if("ACTIVE".equals(item)){
status.put("functionAccess", FunctionAccessStatus.ACTIVE.getCode());
break;
}else {
status.put("functionAccess", FunctionAccessStatus.OK.getCode());
}
// if (StringUtils.isBlank(item)) {
// String timeOut = RedisUtils.getCacheObject(FUNCTION_ACCESS_TIMEOUT_KEY + dto.getDeviceImei());
// if ("TIMEOUT".equals(timeOut)) {
// status.put("functionAccess", FunctionAccessStatus.TIMEOUT.getCode());
// break;
// } else {
// status.put("functionAccess", FunctionAccessStatus.OK.getCode());
// }
// } else {
// if (!FunctionAccessStatus.OK.getCode().equals(item)) {
// status.put("functionAccess", FunctionAccessStatus.FAILED.getCode());
// break;
// } else {
// status.put("functionAccess", FunctionAccessStatus.OK.getCode());
// }
// }
}
return status;
}
}

View File

@ -0,0 +1,51 @@
package com.fuyuanshen.app.service.device.status;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.base.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;
// 上传开机图片
@Slf4j
@Component
public class FunctionAccessStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_1";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getDeviceImei());
log.info("FunctionAccessStatusRule:{}",functionAccess);
if(StringUtils.isBlank(functionAccess)){
String timeOut = RedisUtils.getCacheObject(FUNCTION_ACCESS_TIMEOUT_KEY + dto.getDeviceImei());
if("TIMEOUT".equals(timeOut)){
status.put("functionAccess", FunctionAccessStatus.TIMEOUT.getCode());
RedisUtils.deleteObject(FUNCTION_ACCESS_TIMEOUT_KEY + dto.getDeviceImei());
}else{
status.put("functionAccess", FunctionAccessStatus.OK.getCode());
}
}else{
status.put("functionAccess", functionAccess);
}
return status;
}
}

View File

@ -1,7 +1,6 @@
package com.fuyuanshen.app.service.device.status;
package com.fuyuanshen.app.service.device.status.base;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.equipment.domain.Device;
import java.util.Map;

View File

@ -1,4 +1,4 @@
package com.fuyuanshen.app.service.device.status;
package com.fuyuanshen.app.service.device.status.base;
import org.springframework.stereotype.Component;

View File

@ -1,55 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import cn.hutool.json.JSONObject;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
@Slf4j
@Component
public class AlarmStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_5";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getBatchId());
if(StringUtils.isBlank(functionAccess)){
status.put("functionAccess", "OK");
return status;
}
JSONObject jsonObj = new JSONObject(functionAccess);
AtomicBoolean isActive = new AtomicBoolean(false);
jsonObj.forEach((key, value) -> {
if(value.equals("ACTIVE")){
isActive.set(true);
}
});
if(!isActive.get()){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -1,41 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
// 上传开机图片
@Slf4j
@Component
public class BootLogoStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_3";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getDeviceImei());
if(functionAccess==null){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -1,45 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
// 激光模式设置
@Slf4j
@Component
public class LaserModeSettingsStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_2";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
/**
* @param dto
* @return
*/
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getDeviceImei());
if(functionAccess==null){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -1,42 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
// 灯光状态
@Slf4j
@Component
public class ModeStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_1";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getDeviceImei());
if(functionAccess==null){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -1,41 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
@Slf4j
@Component
public class RegisterPersonInfoStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_4";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getDeviceImei());
if(functionAccess==null){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -1,55 +0,0 @@
package com.fuyuanshen.app.service.device.status.jbq;
import cn.hutool.json.JSONObject;
import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto;
import com.fuyuanshen.app.service.device.status.DeviceStatusRule;
import com.fuyuanshen.app.service.device.status.constants.DeviceTypeConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
@Slf4j
@Component
public class SendMessageStatusRule implements DeviceStatusRule {
@Override
public String getCommandType() {
return DeviceTypeConstants.TYPE_BJQ6170+"_6";
}
@Override
public boolean supports(String deviceType) {
return true; // 适用于所有设备类型
}
@Override
public Map<String, Object> getStatus(AppRealTimeStatusDto dto) {
Map<String, Object> status = new HashMap<>();
String functionAccess = RedisUtils.getCacheObject(
FUNCTION_ACCESS_KEY + dto.getBatchId());
if(StringUtils.isBlank(functionAccess)){
status.put("functionAccess", "OK");
return status;
}
JSONObject jsonObj = new JSONObject(functionAccess);
AtomicBoolean isActive = new AtomicBoolean(false);
jsonObj.forEach((key, value) -> {
if(value.equals("ACTIVE")){
isActive.set(true);
}
});
if(!isActive.get()){
status.put("functionAccess", "OK");
}else{
status.put("functionAccess", "ACTIVE");
}
return status;
}
}

View File

@ -0,0 +1,38 @@
package com.fuyuanshen.global.mqtt.listener;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.HashMap;
import java.util.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;
@Component
@Slf4j
public class RedisKeyExpirationListener implements MessageListener {
@Override
public void onMessage(Message message, byte[] pattern) {
String expiredKey = new String(message.getBody());
if (expiredKey.startsWith(FUNCTION_ACCESS_KEY)) {
String element = expiredKey.substring(FUNCTION_ACCESS_KEY.length());
handleFunctionAccessExpired(element);
}
}
/**
* 访问key过期事件
* @param element 批次ID
*/
private void handleFunctionAccessExpired(String element) {
RedisUtils.setCacheObject(FUNCTION_ACCESS_TIMEOUT_KEY + element, FunctionAccessStatus.TIMEOUT.getCode(), Duration.ofSeconds(30L));
}
}

View File

@ -0,0 +1,25 @@
package com.fuyuanshen.global.mqtt.listener.config;
import com.fuyuanshen.global.mqtt.listener.RedisKeyExpirationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.listener.PatternTopic;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
@Configuration
public class RedisListenerConfig {
@Bean
RedisMessageListenerContainer redisMessageListenerContainer(RedisConnectionFactory connectionFactory,
RedisKeyExpirationListener redisKeyExpirationListener) {
RedisMessageListenerContainer container = new RedisMessageListenerContainer();
container.setConnectionFactory(connectionFactory);
// 监听过期事件
container.addMessageListener(redisKeyExpirationListener, new PatternTopic("__keyevent@*__:expired"));
return container;
}
}

View File

@ -0,0 +1,96 @@
package com.fuyuanshen.global.mqtt.listener.domain;
import lombok.Data;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
/**
* 功能访问状态对象
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class FunctionAccessResult {
/**
* 状态码
*/
private String status;
/**
* 消息描述
*/
private String message;
/**
* 时间戳
*/
private Long timestamp;
/**
* 设备IMEI可选
*/
private String deviceImei;
/**
* 批次ID可选
*/
private String batchId;
public FunctionAccessResult(String status, String message) {
this.status = status;
this.message = message;
this.timestamp = System.currentTimeMillis();
}
/**
* 创建失败状态对象
* @param message 消息
* @return FunctionAccessResult
*/
public static FunctionAccessResult failed(String message) {
return new FunctionAccessResult("FAILED", message);
}
/**
* 创建成功状态对象
* @param message 消息
* @return FunctionAccessResult
*/
public static FunctionAccessResult ok(String message) {
return new FunctionAccessResult("OK", message);
}
/**
* 创建超时状态对象
* @param message 消息
* @return FunctionAccessResult
*/
public static FunctionAccessResult timeout(String message) {
return new FunctionAccessResult("TIMEOUT", message);
}
/**
* 判断是否为失败状态
* @return boolean
*/
public boolean isFailed() {
return "FAILED".equals(this.status);
}
/**
* 判断是否为成功状态
* @return boolean
*/
public boolean isOk() {
return "OK".equals(this.status);
}
/**
* 判断是否为超时状态
* @return boolean
*/
public boolean isTimeout() {
return "TIMEOUT".equals(this.status);
}
}

View File

@ -0,0 +1,62 @@
package com.fuyuanshen.global.mqtt.listener.domain;
/**
* 功能访问状态枚举
*/
public enum FunctionAccessStatus {
/**
* 失败状态
*/
FAILED("FAILED", "失败"),
/**
* 成功状态
*/
OK("OK", "成功"),
/**
* 激活中状态
*/
ACTIVE("ACTIVE", "处理中"),
/**
* 超时状态
*/
TIMEOUT("TIMEOUT", "超时");
private final String code;
private final String description;
FunctionAccessStatus(String code, String description) {
this.code = code;
this.description = description;
}
public String getCode() {
return code;
}
public String getDescription() {
return description;
}
/**
* 根据代码获取状态枚举
* @param code 状态代码
* @return 对应的状态枚举
*/
public static FunctionAccessStatus fromCode(String code) {
for (FunctionAccessStatus status : FunctionAccessStatus.values()) {
if (status.getCode().equals(code)) {
return status;
}
}
throw new IllegalArgumentException("未知的状态代码: " + code);
}
@Override
public String toString() {
return code;
}
}

View File

@ -7,14 +7,17 @@ import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_STATUS_KEY_PREFIX;
/**
@ -44,16 +47,16 @@ public class BjqActiveReportingDeviceDataRule implements MqttMessageRule {
String chargeState = convertArr[4].toString();
String batteryRemainingTime = convertArr[5].toString();
// 异步发送设备状态和位置信息到Redis
// 发送设备状态和位置信息到Redis
asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(), mainLightMode, laserLightMode,
batteryPercentage, chargeState, batteryRemainingTime);
} catch (Exception e) {
log.error("处理定位数据命令时出错", e);
log.error("处理上报数据命令时出错", e);
}
}
/**
* 异步发送设备状态信息和位置信息到Redis使用CompletableFuture
* 发送设备状态信息和位置信息到Redis
*
* @param deviceImei 设备IMEI
* @param mainLightMode 主灯档位

View File

@ -7,12 +7,15 @@ import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.concurrent.CompletableFuture;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
/**
@ -30,38 +33,38 @@ public class BjqAlarmRule implements MqttMessageRule {
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Object[] convertArr = context.getConvertArr();
String mainLightMode = convertArr[1].toString();
if(StringUtils.isNotBlank(mainLightMode)){
// 异步发送设备状态和位置信息到Redis
asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode);
// 发送设备状态和位置信息到Redis
syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode);
}
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
} catch (Exception e) {
log.error("处理灯光模式命令时出错", e);
log.error("处理告警命令时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
}
}
/**
* 异步发送设备状态信息和位置信息到Redis使用CompletableFuture
* 发送设备状态信息和位置信息到Redis使用CompletableFuture
*
* @param deviceImei 设备IMEI
*/
public void asyncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) {
CompletableFuture.runAsync(() -> {
try {
// 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_KEY_PREFIX;
public void syncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) {
try {
// 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_ALARM_KEY_PREFIX;
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
} catch (Exception e) {
log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
});
} catch (Exception e) {
log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
}

View File

@ -9,14 +9,17 @@ import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
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.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_BOOT_LOGO_KEY_PREFIX;
@ -39,9 +42,11 @@ public class BjqBootLogoRule implements MqttMessageRule {
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Byte val2 = (Byte) context.getConvertArr()[1];
if (val2 == 100) {
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
return;
}
@ -53,7 +58,6 @@ public class BjqBootLogoRule implements MqttMessageRule {
byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data);
byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, (val2 - 1), 512);
log.info("第{}块数据大小: {} 字节", val2, specificChunk.length);
// System.out.println("第" + val2 + "块数据: " + Arrays.toString(specificChunk));
ArrayList<Integer> intData = new ArrayList<>();
intData.add(3);
@ -71,8 +75,10 @@ public class BjqBootLogoRule implements MqttMessageRule {
log.info("发送开机LOGO点阵数据到设备消息=>topic:{},payload:{}",
MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(),
JsonUtils.toJsonString(map));
} catch (Exception e) {
log.error("处理开机LOGO时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
}
}
}

View File

@ -0,0 +1,80 @@
package com.fuyuanshen.global.mqtt.rule.bjq;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
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.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.time.Duration;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LIGHT_MODE_KEY_PREFIX;
/**
* 灯光模式订阅设备回传消息
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class BjqLaserModeSettingsRule implements MqttMessageRule {
@Override
public String getCommandType() {
return LightingCommandTypeConstants.LASER_LIGHT;
}
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Object[] convertArr = context.getConvertArr();
String mainLightMode = convertArr[1].toString();
if(StringUtils.isNotBlank(mainLightMode)){
if("0".equals(mainLightMode)){
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0", Duration.ofSeconds(60*15));
}
// 发送设备状态和位置信息到Redis
syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode);
}
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(30));
} catch (Exception e) {
log.error("处理灯光模式命令时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(30));
}
}
/**
* 发送设备状态信息和位置信息到Redis
*
* @param deviceImei 设备IMEI
*/
public void syncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) {
// CompletableFuture.runAsync(() -> {
//
// });
try {
// 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX;
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
} catch (Exception e) {
log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
}
}

View File

@ -13,16 +13,19 @@ import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
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;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LOCATION_KEY_PREFIX;
@ -44,6 +47,7 @@ public class BjqLocationDataRule implements MqttMessageRule {
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Object[] convertArr = context.getConvertArr();
// Latitude, longitude
@ -58,8 +62,10 @@ public class BjqLocationDataRule implements MqttMessageRule {
log.info("发送定位数据到设备=>topic:{},payload:{}",
MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(),
JsonUtils.toJsonString(map));
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
} catch (Exception e) {
log.error("处理定位数据命令时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
}
}

View File

@ -7,6 +7,7 @@ import com.fuyuanshen.global.mqtt.base.MqttMessageRule;
import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -33,6 +34,7 @@ public class BjqModeRule implements MqttMessageRule {
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Object[] convertArr = context.getConvertArr();
@ -42,37 +44,35 @@ public class BjqModeRule implements MqttMessageRule {
String deviceOnlineStatusRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX+ context.getDeviceImei() + DeviceRedisKeyConstants.DEVICE_ONLINE_STATUS_KEY_PREFIX ;
RedisUtils.setCacheObject(deviceOnlineStatusRedisKey, "0", Duration.ofSeconds(60*15));
}
// 异步发送设备状态和位置信息到Redis
asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode);
// 发送设备状态和位置信息到Redis
syncSendDeviceDataToRedisWithFuture(context.getDeviceImei(),mainLightMode);
}
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
} catch (Exception e) {
log.error("处理灯光模式命令时出错", e);
}finally {
log.info("处理灯光模式命令完成");
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
RedisUtils.deleteObject(functionAccess);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
}
}
/**
* 异步发送设备状态信息和位置信息到Redis使用CompletableFuture
* 发送设备状态信息和位置信息到Redis
*
* @param deviceImei 设备IMEI
*/
public void asyncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) {
CompletableFuture.runAsync(() -> {
try {
// 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX;
public void syncSendDeviceDataToRedisWithFuture(String deviceImei,Object convertValue) {
// CompletableFuture.runAsync(() -> {
//
// });
try {
// 将设备状态信息存储到Redis中
String deviceRedisKey = GlobalConstants.GLOBAL_REDIS_KEY+DeviceRedisKeyConstants.DEVICE_KEY_PREFIX + deviceImei + DEVICE_LIGHT_MODE_KEY_PREFIX;
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
// 存储到Redis
RedisUtils.setCacheObject(deviceRedisKey, convertValue.toString());
} catch (Exception e) {
log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
});
} catch (Exception e) {
log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e);
}
}

View File

@ -0,0 +1,58 @@
package com.fuyuanshen.global.mqtt.rule.bjq;
import com.alibaba.fastjson2.JSONObject;
import com.fuyuanshen.common.core.constant.GlobalConstants;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.json.utils.JsonUtils;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import com.fuyuanshen.equipment.utils.map.GetAddressFromLatUtil;
import com.fuyuanshen.equipment.utils.map.LngLonUtil;
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.DeviceRedisKeyConstants;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
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;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.*;
/**
* 定位数据命令处理
*/
@Component
@RequiredArgsConstructor
@Slf4j
public class BjqPersonnelInfoDataRule implements MqttMessageRule {
private final MqttGateway mqttGateway;
@Override
public String getCommandType() {
return LightingCommandTypeConstants.PERSONNEL_INFO;
}
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Object[] convertArr = context.getConvertArr();
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(30));
} catch (Exception e) {
log.error("处理定位数据命令时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(30));
}
}
}

View File

@ -9,14 +9,17 @@ import com.fuyuanshen.global.mqtt.base.MqttRuleContext;
import com.fuyuanshen.global.mqtt.config.MqttGateway;
import com.fuyuanshen.global.mqtt.constants.LightingCommandTypeConstants;
import com.fuyuanshen.global.mqtt.constants.MqttConstants;
import com.fuyuanshen.global.mqtt.listener.domain.FunctionAccessStatus;
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.Map;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.GLOBAL_REDIS_KEY;
import static com.fuyuanshen.common.core.utils.ImageToCArrayConverter.convertHexToDecimal;
import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX;
@ -38,9 +41,11 @@ public class BjqSendMessageRule implements MqttMessageRule {
@Override
public void execute(MqttRuleContext context) {
String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei();
try {
Byte val2 = (Byte) context.getConvertArr()[1];
if (val2 == 100) {
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.OK.getCode(), Duration.ofSeconds(20));
return;
}
@ -70,8 +75,10 @@ public class BjqSendMessageRule implements MqttMessageRule {
log.info("发送设备信息数据到设备消息=>topic:{},payload:{}",
MqttConstants.GLOBAL_PUB_KEY + context.getDeviceImei(),
JsonUtils.toJsonString(map));
} catch (Exception e) {
log.error("处理发送设备信息时出错", e);
RedisUtils.setCacheObject(functionAccess, FunctionAccessStatus.FAILED.getCode(), Duration.ofSeconds(20));
}
}
}

View File

@ -303,6 +303,6 @@ mqtt:
password: #YtvpSfCNG
url: tcp://47.120.79.150:2883
subClientId: fys_subClient
subTopic: A/#,B/#,worker/location/#
subTopic: worker/location/#
pubTopic: B/#
pubClientId: fys_pubClient

Binary file not shown.

Before

Width:  |  Height:  |  Size: 397 B

After

Width:  |  Height:  |  Size: 263 B

View File

@ -39,4 +39,6 @@ public interface GlobalConstants {
String FUNCTION_ACCESS_KEY = GLOBAL_REDIS_KEY + "device:function_access:";
String FUNCTION_ACCESS_TIMEOUT_KEY = GLOBAL_REDIS_KEY + "device:function_access_timeout:";
}

View File

@ -12,6 +12,7 @@ import org.springframework.stereotype.Component;
import java.time.Duration;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_TIMEOUT_KEY;
@Slf4j
@Aspect
@ -35,9 +36,8 @@ public class FunctionAccessAspect {
if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
throw new ServiceException("设备已存在访问限制,请稍后再试", 500);
}
// 存储到Redis中设置过期时间
//
RedisUtils.setCacheObject(redisKey, "ACTIVE", Duration.ofSeconds(30));
log.info("设备Redis key已添加: {}", redisKey);
}
// 执行原方法

View File

@ -1,11 +1,9 @@
package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java
import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.fuyuanshen.common.core.exception.ServiceException;
import com.fuyuanshen.common.core.utils.ObjectUtils;
import com.fuyuanshen.common.core.utils.StringUtils;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation;
import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation;
import com.fuyuanshen.common.redis.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
@ -15,7 +13,7 @@ import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
import java.time.Duration;
import java.util.*;
import java.util.List;
import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY;
@ -42,16 +40,11 @@ public class FunctionAccessBatchAspect {
if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){
throw new ServiceException("设备已存在访问限制,请稍后再试", 500);
}
Map<String, String> deviceImeiMap = new HashMap<>();
if(ObjectUtils.length(deviceImeiList)>0){
deviceImeiList.forEach(item->{
deviceImeiMap.put(item, "ACTIVE");
});
}
// 存储到Redis中设置过期时间
RedisUtils.setCacheObject(redisKey, JSONUtil.toJsonStr(deviceImeiMap), Duration.ofSeconds(15));
log.info("设备Redis key已添加: {}", redisKey);
deviceImeiList.forEach(item->{
RedisUtils.setCacheObject(FUNCTION_ACCESS_KEY + item, "ACTIVE", Duration.ofSeconds(30));
});
String deviceImeiListStr = JSONUtil.toJsonStr(deviceImeiList);
RedisUtils.setCacheObject(redisKey, deviceImeiListStr , Duration.ofSeconds(40));
}
// 执行原方法