diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java index beb899ef..d414cff7 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/AppDeviceController.java @@ -1,12 +1,14 @@ package com.fuyuanshen.app.controller; import com.fuyuanshen.app.domain.dto.APPReNameDTO; +import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto; import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo; import com.fuyuanshen.app.service.AppDeviceBizService; import com.fuyuanshen.common.core.domain.R; import com.fuyuanshen.common.mybatis.core.page.PageQuery; import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.equipment.domain.Device; import com.fuyuanshen.equipment.domain.dto.AppDeviceBo; import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; @@ -15,6 +17,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; /** * APP设备信息管理 @@ -72,4 +75,19 @@ public class AppDeviceController extends BaseController { appDeviceService.reName(reNameDTO); return R.ok("重命名成功!!!"); } + + + @GetMapping("/realTimeStatus") + public R> getRealTimeStatus(AppRealTimeStatusDto statusDto) { + Map status = appDeviceService.getRealTimeStatus(statusDto); + return R.ok(status); + } + + /** + * 根据mac查询设备信息 + */ + @GetMapping("/getDeviceInfoByDeviceMac") + public R getDeviceInfo(String deviceMac) { + return R.ok(appDeviceService.getDeviceInfo(deviceMac)); + } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java index 2f7caf8b..7427f8eb 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/controller/device/AppDeviceBJQController.java @@ -7,6 +7,8 @@ import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; import com.fuyuanshen.app.service.device.AppDeviceBJQBizService; import com.fuyuanshen.common.core.domain.R; import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessBatcAnnotation; import com.fuyuanshen.common.web.core.BaseController; import com.fuyuanshen.equipment.domain.dto.AppDeviceSendMsgBo; import jakarta.validation.constraints.NotNull; @@ -41,6 +43,7 @@ public class AppDeviceBJQController extends BaseController { * 人员信息登记 */ @PostMapping(value = "/registerPersonInfo") + @FunctionAccessAnnotation("registerPersonInfo") public R registerPersonInfo(@Validated(AddGroup.class) @RequestBody AppPersonnelInfoBo bo) { return toAjax(appDeviceService.registerPersonInfo(bo)); } @@ -49,6 +52,7 @@ public class AppDeviceBJQController extends BaseController { * 发送信息 */ @PostMapping(value = "/sendMessage") + @FunctionAccessBatcAnnotation("sendMessage") public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { return toAjax(appDeviceService.sendMessage(bo)); } @@ -57,6 +61,7 @@ public class AppDeviceBJQController extends BaseController { * 发送报警信息 */ @PostMapping(value = "/sendAlarmMessage") + @FunctionAccessBatcAnnotation("sendAlarmMessage") public R sendAlarmMessage(@RequestBody AppDeviceSendMsgBo bo) { return toAjax(appDeviceService.sendAlarmMessage(bo)); } @@ -65,6 +70,7 @@ public class AppDeviceBJQController extends BaseController { * 上传设备logo图片 */ @PostMapping("/uploadLogo") + @FunctionAccessAnnotation("uploadLogo") public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { MultipartFile file = bo.getFile(); @@ -80,6 +86,7 @@ public class AppDeviceBJQController extends BaseController { * 灯光模式 * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) */ + @FunctionAccessAnnotation("lightModeSettings") @PostMapping("/lightModeSettings") public R lightModeSettings(@RequestBody DeviceInstructDto params) { // params 转 JSONObject @@ -91,6 +98,7 @@ public class AppDeviceBJQController extends BaseController { * 灯光亮度设置 * */ + @FunctionAccessAnnotation("lightBrightnessSettings") @PostMapping("/lightBrightnessSettings") public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { appDeviceService.lightBrightnessSettings(params); @@ -102,18 +110,10 @@ public class AppDeviceBJQController extends BaseController { * */ @PostMapping("/laserModeSettings") + @FunctionAccessAnnotation("laserModeSettings") public R laserModeSettings(@RequestBody DeviceInstructDto params) { appDeviceService.laserModeSettings(params); return R.ok(); } - /** - * 地图逆解析 - * - */ - @PostMapping("/mapReverseGeocoding") - public R mapReverseGeocoding(@RequestBody DeviceInstructDto params) { - String mapJson = appDeviceService.mapReverseGeocoding(params); - return R.ok(mapJson); - } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppDeviceLogoUploadDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppDeviceLogoUploadDto.java index 76dc5e2c..26db3c16 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppDeviceLogoUploadDto.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppDeviceLogoUploadDto.java @@ -8,6 +8,7 @@ public class AppDeviceLogoUploadDto { private Long deviceId; + private String deviceImei; /** * 文件 */ diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppRealTimeStatusDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppRealTimeStatusDto.java new file mode 100644 index 00000000..01a13d3a --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppRealTimeStatusDto.java @@ -0,0 +1,30 @@ +package com.fuyuanshen.app.domain.dto; + +import lombok.Data; + +/** + * 设备实时状态 + */ +@Data +public class AppRealTimeStatusDto { + + /** + * 设备IMEI + */ + private String deviceImei; + + /** + * 设备类型 + */ + private String typeName; + + /** + * 功能类型 + */ + private String functionMode; + + /** + * 批次号 + */ + private String batchId; +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java index 80e74f1d..93ea7c2a 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/AppDeviceBizService.java @@ -11,6 +11,7 @@ import com.fuyuanshen.app.domain.AppPersonnelInfo; import com.fuyuanshen.app.domain.bo.AppPersonnelInfoBo; import com.fuyuanshen.app.domain.dto.APPReNameDTO; import com.fuyuanshen.app.domain.dto.AppDeviceLogoUploadDto; +import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto; import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo; import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; @@ -18,6 +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.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.exception.ServiceException; import com.fuyuanshen.common.core.utils.*; @@ -35,7 +38,7 @@ import com.fuyuanshen.equipment.enums.BindingStatusEnum; import com.fuyuanshen.equipment.enums.CommunicationModeEnum; import com.fuyuanshen.equipment.mapper.DeviceMapper; import com.fuyuanshen.equipment.mapper.DeviceTypeMapper; -import com.fuyuanshen.equipment.utils.c.ReliableTextToBitmap; +import com.fuyuanshen.equipment.service.DeviceService; import com.fuyuanshen.global.mqtt.config.MqttGateway; import com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants; import com.fuyuanshen.global.mqtt.constants.MqttConstants; @@ -68,6 +71,9 @@ public class AppDeviceBizService { private final DeviceTypeMapper deviceTypeMapper; private final MqttGateway mqttGateway; private final AppDeviceBindRecordMapper appDeviceBindRecordMapper; + private final RealTimeStatusEngine realTimeStatusEngine; + private final DeviceService deviceService; + public List getTypeList() { @@ -602,4 +608,28 @@ public class AppDeviceBizService { } return 1; } + + public Map getRealTimeStatus(AppRealTimeStatusDto statusDto) { + try { + String commandType = statusDto.getTypeName()+"_" + statusDto.getFunctionMode(); + DeviceStatusRule rule = realTimeStatusEngine.getDeviceStatusRule(commandType); + if(rule == null){ + throw new ServiceException("未匹配到处理命令"); + } + return rule.getStatus(statusDto); + } catch (Exception e){ + e.printStackTrace(); + } + return null; + } + + public Device getDeviceInfo(String deviceMac) { + QueryWrapper queryWrapper = new QueryWrapper<>(); + queryWrapper.eq("device_mac", deviceMac); + List devices = deviceMapper.selectList(queryWrapper); + if(ObjectUtils.length(devices) ==0){ + return null; + } + return devices.get(0); + } } diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java index db998b66..026ee4f8 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/AppDeviceBJQBizService.java @@ -14,6 +14,7 @@ import com.fuyuanshen.app.mapper.AppPersonnelInfoMapper; import com.fuyuanshen.common.core.constant.GlobalConstants; import com.fuyuanshen.common.core.exception.ServiceException; import com.fuyuanshen.common.core.utils.*; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; import com.fuyuanshen.common.redis.utils.RedisUtils; import com.fuyuanshen.common.satoken.utils.AppLoginHelper; import com.fuyuanshen.equipment.domain.Device; @@ -62,12 +63,10 @@ public class AppDeviceBJQBizService { if (device == null) { throw new ServiceException("设备不存在" + deviceId); } - try { ClassPathResource resource = new ClassPathResource("image/background.png"); InputStream inputStream = resource.getInputStream(); -// String backgroundImagePath = "D:\\background.png"; // 替换为实际背景图片路径 byte[] largeData = ImageWithTextGenerate.generate160x80ImageWithText2(bo.getSendMsg(), inputStream, 25600); int[] ints = convertHexToDecimal(largeData); RedisUtils.setCacheObject(GLOBAL_REDIS_KEY+ DEVICE_KEY_PREFIX + device.getDeviceImei() + ":app_send_message_data" , Arrays.toString(ints), Duration.ofSeconds(30 * 60L)); @@ -77,7 +76,6 @@ public class AppDeviceBJQBizService { byte[] arr = ImageToCArrayConverter.convertStringToByteArray(data); byte[] specificChunk = ImageToCArrayConverter.getChunk(arr, 0, 512); log.info("发送信息第0块数据大小: {} 字节",specificChunk.length); -// log.info("第0块数据: {}", Arrays.toString(specificChunk)); ArrayList intData = new ArrayList<>(); intData.add(6); @@ -167,6 +165,7 @@ public class AppDeviceBJQBizService { } + public boolean registerPersonInfo(AppPersonnelInfoBo bo) { Long deviceId = bo.getDeviceId(); Device deviceObj = deviceMapper.selectById(deviceId); @@ -212,6 +211,7 @@ public class AppDeviceBJQBizService { } + @FunctionAccessAnnotation("uploadDeviceLogo") public void uploadDeviceLogo(AppDeviceLogoUploadDto bo) { try { Device device = deviceMapper.selectById(bo.getDeviceId()); @@ -256,6 +256,7 @@ public class AppDeviceBJQBizService { * 灯光模式 * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) */ + public void lightModeSettings(DeviceInstructDto params) { try { Long deviceId = params.getDeviceId(); @@ -280,6 +281,7 @@ public class AppDeviceBJQBizService { } //灯光亮度设置 + @FunctionAccessAnnotation("lightBrightnessSettings") public void lightBrightnessSettings(DeviceInstructDto params) { try { Long deviceId = params.getDeviceId(); @@ -312,6 +314,7 @@ public class AppDeviceBJQBizService { } //激光模式设置 + @FunctionAccessAnnotation("laserModeSettings") public void laserModeSettings(DeviceInstructDto params) { try { Long deviceId = params.getDeviceId(); diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/DeviceStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/DeviceStatusRule.java new file mode 100644 index 00000000..2c83a367 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/DeviceStatusRule.java @@ -0,0 +1,20 @@ +package com.fuyuanshen.app.service.device.status; + +import com.fuyuanshen.app.domain.dto.AppRealTimeStatusDto; +import com.fuyuanshen.equipment.domain.Device; + +import java.util.Map; + +// 规则接口 +public interface DeviceStatusRule { + + /** + * 获取命令类型 + * @return 命令类型 + */ + String getCommandType(); + + boolean supports(String deviceType); + + Map getStatus(AppRealTimeStatusDto statusDto); +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/constants/DeviceTypeConstants.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/constants/DeviceTypeConstants.java new file mode 100644 index 00000000..271f6330 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/constants/DeviceTypeConstants.java @@ -0,0 +1,6 @@ +package com.fuyuanshen.app.service.device.status.constants; + +public class DeviceTypeConstants { + public static final String TYPE_BJQ6170 = "BJQ6170"; + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/AlarmStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/AlarmStatusRule.java new file mode 100644 index 00000000..14956de5 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/AlarmStatusRule.java @@ -0,0 +1,50 @@ +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 AlarmStatusRule implements DeviceStatusRule { + @Override + public String getCommandType() { + return DeviceTypeConstants.TYPE_BJQ6170+"_5"; + } + + @Override + public boolean supports(String deviceType) { + return true; // 适用于所有设备类型 + } + + @Override + public Map getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + String functionAccess = RedisUtils.getCacheObject( + + FUNCTION_ACCESS_KEY + dto.getDeviceImei()); + if(functionAccess==null){ + status.put("functionAccess", "OK"); + }else{ + status.put("functionAccess", "ACTIVE"); + } + // + +// String alarmStatus = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX); +// +// if (StringUtils.isNotBlank(alarmStatus)) { +// status.put("alarmStatus", alarmStatus); +// } + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/BootLogoStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/BootLogoStatusRule.java new file mode 100644 index 00000000..6eea5b3e --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/BootLogoStatusRule.java @@ -0,0 +1,49 @@ +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 getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + String functionAccess = RedisUtils.getCacheObject( + FUNCTION_ACCESS_KEY + dto.getDeviceImei()); + if(functionAccess==null){ + status.put("functionAccess", "OK"); + }else{ + status.put("functionAccess", "ACTIVE"); + } +// String location = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_LOCATION_KEY_PREFIX); +// +// if (StringUtils.isNotBlank(location)) { +// JSONObject jsonObject = JSONObject.parseObject(location); +// status.put("latitude", jsonObject.getString("latitude")); +// status.put("longitude", jsonObject.getString("longitude")); +// } + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/LaserModeSettingsStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/LaserModeSettingsStatusRule.java new file mode 100644 index 00000000..1004dbad --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/LaserModeSettingsStatusRule.java @@ -0,0 +1,48 @@ +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 getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + String functionAccess = RedisUtils.getCacheObject( + FUNCTION_ACCESS_KEY + dto.getDeviceImei()); + if(functionAccess==null){ + status.put("functionAccess", "OK"); + }else{ + status.put("functionAccess", "ACTIVE"); + } +// String onlineStatus = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_ONLINE_STATUS_KEY_PREFIX); +// status.put("onlineStatus", StringUtils.isNotBlank(onlineStatus) ? 1 : 0); + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/ModeStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/ModeStatusRule.java new file mode 100644 index 00000000..a20c024a --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/ModeStatusRule.java @@ -0,0 +1,47 @@ +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 getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + String functionAccess = RedisUtils.getCacheObject( + FUNCTION_ACCESS_KEY + dto.getDeviceImei()); + status.put("functionAccess", functionAccess); +// String deviceStatus = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_STATUS_KEY_PREFIX); +// +// if (StringUtils.isNotBlank(deviceStatus)) { +// JSONObject jsonObject = JSONObject.parseObject(deviceStatus); +// status.put("battery", jsonObject.getString("batteryPercentage")); +// } else { +// status.put("battery", "0"); +// } + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/RegisterPersonInfoStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/RegisterPersonInfoStatusRule.java new file mode 100644 index 00000000..f7288faf --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/RegisterPersonInfoStatusRule.java @@ -0,0 +1,47 @@ +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 getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + String functionAccess = RedisUtils.getCacheObject( + FUNCTION_ACCESS_KEY + dto.getDeviceImei()); + if(functionAccess==null){ + status.put("functionAccess", "OK"); + }else{ + status.put("functionAccess", "ACTIVE"); + } +// String alarmStatus = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX); +// +// if (StringUtils.isNotBlank(alarmStatus)) { +// status.put("alarmStatus", alarmStatus); +// } + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/SendMessageStatusRule.java b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/SendMessageStatusRule.java new file mode 100644 index 00000000..d4382ecd --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/service/device/status/jbq/SendMessageStatusRule.java @@ -0,0 +1,48 @@ +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.List; +import java.util.Map; + +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 getStatus(AppRealTimeStatusDto dto) { + Map status = new HashMap<>(); + List functionAccess = RedisUtils.getCacheObject( + FUNCTION_ACCESS_KEY + dto.getBatchId()); + if(functionAccess==null){ + status.put("functionAccess", "OK"); + }else{ + status.put("functionAccess", "ACTIVE"); + } +// String alarmStatus = RedisUtils.getCacheObject( +// GLOBAL_REDIS_KEY + DEVICE_KEY_PREFIX + dto.getDeviceImei() + DEVICE_ALARM_KEY_PREFIX); +// +// if (StringUtils.isNotBlank(alarmStatus)) { +// status.put("alarmStatus", alarmStatus); +// } + return status; + } +} \ No newline at end of file diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java index 97fd0f30..309d20bd 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqBootLogoRule.java @@ -23,7 +23,7 @@ import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVIC import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_KEY_PREFIX; /** - * 人员信息命令处理 + * 上传开机图片命令处理 */ @Component @RequiredArgsConstructor diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java index 09aeaccb..6904edb5 100644 --- a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/bjq/BjqModeRule.java @@ -14,6 +14,7 @@ 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.DEVICE_KEY_PREFIX; import static com.fuyuanshen.global.mqtt.constants.DeviceRedisKeyConstants.DEVICE_LIGHT_MODE_KEY_PREFIX; @@ -47,6 +48,10 @@ public class BjqModeRule implements MqttMessageRule { } catch (Exception e) { log.error("处理灯光模式命令时出错", e); + }finally { + log.info("处理灯光模式命令完成"); + String functionAccess = FUNCTION_ACCESS_KEY + context.getDeviceImei(); + RedisUtils.deleteObject(functionAccess); } } diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/constant/GlobalConstants.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/constant/GlobalConstants.java index ccec3718..305b5b03 100644 --- a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/constant/GlobalConstants.java +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/constant/GlobalConstants.java @@ -36,4 +36,7 @@ public interface GlobalConstants { * 三方认证 redis key */ String SOCIAL_AUTH_CODE_KEY = GLOBAL_REDIS_KEY + "social_auth_codes:"; + + + String FUNCTION_ACCESS_KEY = GLOBAL_REDIS_KEY + "device:function_access:"; } diff --git a/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessAnnotation.java b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessAnnotation.java new file mode 100644 index 00000000..635b5b9f --- /dev/null +++ b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessAnnotation.java @@ -0,0 +1,11 @@ +package com.fuyuanshen.common.ratelimiter.annotation;// DeviceRedisKeyAnnotation.java +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface FunctionAccessAnnotation { + String value() default ""; +} diff --git a/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessBatcAnnotation.java b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessBatcAnnotation.java new file mode 100644 index 00000000..3f59cd96 --- /dev/null +++ b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/annotation/FunctionAccessBatcAnnotation.java @@ -0,0 +1,11 @@ +package com.fuyuanshen.common.ratelimiter.annotation;// DeviceRedisKeyAnnotation.java +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface FunctionAccessBatcAnnotation { + String value() default ""; +} diff --git a/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessAspect.java b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessAspect.java new file mode 100644 index 00000000..a46a17f7 --- /dev/null +++ b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessAspect.java @@ -0,0 +1,103 @@ +package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java +import com.fuyuanshen.common.core.exception.ServiceException; +import com.fuyuanshen.common.core.utils.StringUtils; +import com.fuyuanshen.common.ratelimiter.annotation.FunctionAccessAnnotation; +import com.fuyuanshen.common.redis.utils.RedisUtils; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +import java.time.Duration; + +import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY; + +@Slf4j +@Aspect +@Component +public class FunctionAccessAspect { + + // 定义切点,拦截带有DeviceRedisKeyAnnotation注解的方法 + @Around("@annotation(functionAccessAnnotation)") + public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessAnnotation functionAccessAnnotation) throws Throwable { + Object result; + String deviceImei = null; + + // 获取方法参数,查找设备ID + Object[] args = joinPoint.getArgs(); + deviceImei = extractDeviceImei(args); + + if (StringUtils.isNotBlank(deviceImei)) { + // 生成全局Redis key + String redisKey = generateDeviceRedisKey(deviceImei); + String cacheKey = RedisUtils.getCacheObject(redisKey); + if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){ + throw new ServiceException("设备已存在访问限制,请稍后再试", 500); + } + // 存储到Redis中,设置过期时间 + RedisUtils.setCacheObject(redisKey, "ACTIVE", Duration.ofMinutes(30)); + log.info("设备Redis key已添加: {}", redisKey); + } + + // 执行原方法 + result = joinPoint.proceed(); + + return result; + } + + /** + * 从方法参数中提取设备ID + */ + private String extractDeviceImei(Object[] args) { + if (args == null || args.length == 0) { + return null; + } + + for (Object arg : args) { + if (arg == null) continue; + + // 如果参数本身就是设备ID (Long类型) + if (arg instanceof Long) { + return arg.toString(); + } + + // 如果参数是对象,尝试获取deviceId字段 + try { + // 使用反射获取deviceId字段 + java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields(); + for (java.lang.reflect.Field field : fields) { + if ("deviceImei".equalsIgnoreCase(field.getName()) || + "device_imei".equalsIgnoreCase(field.getName())) { + field.setAccessible(true); + Object value = field.get(arg); + if (value != null) { + return value.toString(); + } + } + } + + // 尝试获取getId方法 + try { + java.lang.reflect.Method getIdMethod = arg.getClass().getMethod("getDeviceImei"); + Object value = getIdMethod.invoke(arg); + if (value != null) { + return value.toString(); + } + } catch (Exception ignored) {} + + } catch (Exception e) { + log.debug("从参数中提取设备ID时出错: {}", e.getMessage()); + } + } + + return null; + } + + /** + * 生成设备的全局Redis key + */ + private String generateDeviceRedisKey(String deviceImei) { + return FUNCTION_ACCESS_KEY + deviceImei; + } +} diff --git a/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessBatchAspect.java b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessBatchAspect.java new file mode 100644 index 00000000..0d6f79bc --- /dev/null +++ b/fys-common/fys-common-ratelimiter/src/main/java/com/fuyuanshen/common/ratelimiter/aspectj/FunctionAccessBatchAspect.java @@ -0,0 +1,184 @@ +package com.fuyuanshen.common.ratelimiter.aspectj;// DeviceRedisKeyAspect.java +import cn.hutool.json.JSON; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; +import com.fuyuanshen.common.core.exception.ServiceException; +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; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.springframework.stereotype.Component; + +import java.time.Duration; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static com.fuyuanshen.common.core.constant.GlobalConstants.FUNCTION_ACCESS_KEY; + +@Slf4j +@Aspect +@Component +public class FunctionAccessBatchAspect { + + // 定义切点,拦截带有DeviceRedisKeyAnnotation注解的方法 + @Around("@annotation(functionAccessBatchAspect)") + public Object addDeviceRedisKey(ProceedingJoinPoint joinPoint, FunctionAccessBatcAnnotation functionAccessBatchAspect) throws Throwable { + Object result; + String batchId = null; + List deviceImeiList = null; + + // 获取方法参数,查找设备ID + Object[] args = joinPoint.getArgs(); + batchId = extractDeviceBatchId(args); + deviceImeiList = extractDeviceImeiList(args); + if (StringUtils.isNotBlank(batchId)) { + // 生成全局Redis key + String redisKey = generateDeviceRedisKey(batchId); + String cacheKey = RedisUtils.getCacheObject(redisKey); + if(StringUtils.isNotBlank(cacheKey) && "ACTIVE".equals(cacheKey)){ + throw new ServiceException("设备已存在访问限制,请稍后再试", 500); + } + // 存储到Redis中,设置过期时间 + RedisUtils.setCacheObject(redisKey, JSONUtil.toJsonStr(deviceImeiList), Duration.ofMinutes(30)); + log.info("设备Redis key已添加: {}", redisKey); + } + + // 执行原方法 + result = joinPoint.proceed(); + + return result; + } + + /** + * 从方法参数中提取设备IMEI列表 + */ + private List extractDeviceImeiList(Object[] args) { + if (args == null || args.length == 0) { + return null; + } + + for (Object arg : args) { + if (arg == null) continue; + + // 如果参数本身就是List类型 + if (arg instanceof List) { + List list = (List) arg; + if (!list.isEmpty() && list.get(0) instanceof String) { + // 检查是否为deviceImeiList + return (List) list; + } + } + + // 如果参数是对象,尝试获取deviceImeiList字段 + try { + // 使用反射获取deviceImeiList字段 + java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields(); + for (java.lang.reflect.Field field : fields) { + if ("deviceImeiList".equalsIgnoreCase(field.getName()) || + "device_imei_list".equalsIgnoreCase(field.getName()) || + "deviceImeis".equalsIgnoreCase(field.getName()) || + "device_imeis".equalsIgnoreCase(field.getName())) { + field.setAccessible(true); + Object value = field.get(arg); + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty() && list.get(0) instanceof String) { + return (List) list; + } + } + } + } + + // 尝试获取getDeviceImeiList方法 + try { + java.lang.reflect.Method getDeviceImeiListMethod = arg.getClass().getMethod("getDeviceImeiList"); + Object value = getDeviceImeiListMethod.invoke(arg); + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty() && list.get(0) instanceof String) { + return (List) list; + } + } + } catch (Exception ignored) {} + + // 尝试获取getDeviceImeis方法 + try { + java.lang.reflect.Method getDeviceImeisMethod = arg.getClass().getMethod("getDeviceImeis"); + Object value = getDeviceImeisMethod.invoke(arg); + if (value instanceof List) { + List list = (List) value; + if (!list.isEmpty() && list.get(0) instanceof String) { + return (List) list; + } + } + } catch (Exception ignored) {} + + } catch (Exception e) { + log.debug("从参数中提取设备IMEI列表时出错: {}", e.getMessage()); + } + } + + return null; + } + + + /** + * 从方法参数中提取设备ID + */ + private String extractDeviceBatchId(Object[] args) { + if (args == null || args.length == 0) { + return null; + } + + for (Object arg : args) { + if (arg == null) continue; + + // 如果参数本身就是设备ID (Long类型) + if (arg instanceof Long) { + return arg.toString(); + } + + // 如果参数是对象,尝试获取deviceId字段 + try { + // 使用反射获取deviceId字段 + java.lang.reflect.Field[] fields = arg.getClass().getDeclaredFields(); + for (java.lang.reflect.Field field : fields) { + if ("batchId".equalsIgnoreCase(field.getName()) || + "batch_id".equalsIgnoreCase(field.getName())) { + field.setAccessible(true); + Object value = field.get(arg); + if (value != null) { + return value.toString(); + } + } + } + + // 尝试获取getId方法 + try { + java.lang.reflect.Method getIdMethod = arg.getClass().getMethod("batchId"); + Object value = getIdMethod.invoke(arg); + if (value != null) { + return value.toString(); + } + } catch (Exception ignored) {} + + } catch (Exception e) { + log.debug("从参数中提取批次号时出错: {}", e.getMessage()); + } + } + + return null; + } + + /** + * 生成设备的全局Redis key + */ + private String generateDeviceRedisKey(String batchId) { + return FUNCTION_ACCESS_KEY + batchId; + } +} diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppPersonnelInfoBo.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppPersonnelInfoBo.java index da469ac4..70a79188 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppPersonnelInfoBo.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/bo/AppPersonnelInfoBo.java @@ -25,6 +25,11 @@ public class AppPersonnelInfoBo extends BaseEntity { */ private Long id; + /** + * 设备IMEI + */ + private String deviceImei; + /** * 设备id */ diff --git a/fys-modules/fys-app/src/main/resources/mapper/app/AppDeviceShareMapper.xml b/fys-modules/fys-app/src/main/resources/mapper/app/AppDeviceShareMapper.xml index 9b3b29c5..b3b69d3d 100644 --- a/fys-modules/fys-app/src/main/resources/mapper/app/AppDeviceShareMapper.xml +++ b/fys-modules/fys-app/src/main/resources/mapper/app/AppDeviceShareMapper.xml @@ -5,8 +5,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"