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 31f02ef..d921708 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,7 +1,11 @@ package com.fuyuanshen.app.controller; +import cn.hutool.json.JSON; +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; +import com.fuyuanshen.app.domain.dto.DeviceInstructDto; import com.fuyuanshen.app.domain.vo.APPDeviceTypeVo; import com.fuyuanshen.app.domain.vo.AppDeviceDetailVo; import com.fuyuanshen.app.service.AppDeviceBizService; @@ -18,8 +22,10 @@ import jakarta.validation.constraints.NotNull; import lombok.RequiredArgsConstructor; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.util.List; +import java.util.Map; /** * APP设备信息管理 @@ -38,7 +44,6 @@ public class AppDeviceController extends BaseController { */ @GetMapping("/list") public TableDataInfo list(DeviceQueryCriteria bo, PageQuery pageQuery) { - return appDeviceService.queryAppDeviceList(bo,pageQuery); } @@ -105,4 +110,60 @@ public class AppDeviceController extends BaseController { public R sendMessage(@RequestBody AppDeviceSendMsgBo bo) { return toAjax(appDeviceService.sendMessage(bo)); } + + /** + * 上传设备logo图片 + */ + @PostMapping("/uploadLogo") + public R upload(@Validated @ModelAttribute AppDeviceLogoUploadDto bo) { + + MultipartFile file = bo.getFile(); + if(file.getSize()>1024*1024*2){ + return R.warn("图片不能大于2M"); + } + appDeviceService.uploadDeviceLogo(bo); + + return R.ok(); + } + + /** + * 灯光模式 + * 0(关灯),1(强光模式),2(弱光模式), 3(爆闪模式), 4(泛光模式) + */ + @PostMapping("/lightModeSettings") + public R lightModeSettings(@RequestBody DeviceInstructDto params) { + // params 转 JSONObject + appDeviceService.lightModeSettings(params); + return R.ok(); + } + + /** + * 灯光亮度设置 + * + */ + @PostMapping("/lightBrightnessSettings") + public R lightBrightnessSettings(@RequestBody DeviceInstructDto params) { + appDeviceService.lightBrightnessSettings(params); + return R.ok(); + } + + /** + * 激光模式设置 + * + */ + @PostMapping("/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 new file mode 100644 index 0000000..76dc5e2 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppDeviceLogoUploadDto.java @@ -0,0 +1,16 @@ +package com.fuyuanshen.app.domain.dto; + +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Data +public class AppDeviceLogoUploadDto { + + private Long deviceId; + + /** + * 文件 + */ + private MultipartFile file; + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppLightModeDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppLightModeDto.java new file mode 100644 index 0000000..732649c --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/AppLightModeDto.java @@ -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; + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java new file mode 100644 index 0000000..f176699 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/app/domain/dto/DeviceInstructDto.java @@ -0,0 +1,16 @@ +package com.fuyuanshen.app.domain.dto; + +import lombok.Data; + +@Data +public class DeviceInstructDto { + + private Long deviceId; + + private String deviceImei; + /** + * 下发指令 + */ + private Object instructValue; + +} 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 b5bc9e1..00fa94a 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 @@ -1,5 +1,6 @@ package com.fuyuanshen.app.service; +import cn.hutool.core.collection.CollectionUtil; import com.alibaba.fastjson2.JSON; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; @@ -122,27 +123,6 @@ public class AppDeviceBizService { if (device.getBindingStatus() != null && device.getBindingStatus() == BindingStatusEnum.BOUND.getCode()) { throw new RuntimeException("设备已绑定"); } - - QueryWrapper bindRecordQueryWrapper = new QueryWrapper<>(); - bindRecordQueryWrapper.eq("device_id", device.getId()); - AppDeviceBindRecord appDeviceBindRecord = appDeviceBindRecordMapper.selectOne(bindRecordQueryWrapper); - if (appDeviceBindRecord != null) { - UpdateWrapper deviceUpdateWrapper = new UpdateWrapper<>(); - deviceUpdateWrapper.eq("device_id", device.getId()) - .set("binding_status", BindingStatusEnum.BOUND.getCode()) - .set("binding_user_id", userId) - .set("update_time", new Date()) - .set("binding_time", new Date()); - return appDeviceBindRecordMapper.update(null, deviceUpdateWrapper); - }else{ - AppDeviceBindRecord bindRecord = new AppDeviceBindRecord(); - bindRecord.setDeviceId(device.getId()); - bindRecord.setBindingUserId(userId); - bindRecord.setBindingTime(new Date()); - bindRecord.setCreateBy(userId); - appDeviceBindRecordMapper.insert(bindRecord); - } - UpdateWrapper deviceUpdateWrapper = new UpdateWrapper<>(); deviceUpdateWrapper.eq("id", device.getId()) .set("binding_status", BindingStatusEnum.BOUND.getCode()) @@ -191,30 +171,48 @@ public class AppDeviceBizService { } + public int unBindDevice(Long id) { + return unBindDevice(id, null, 1); + } + + public int unBindDevice(Long id, Long userId, int type) { Device device = deviceMapper.selectById(id); if (device == null) { throw new RuntimeException("请先将设备入库!!!"); } UpdateWrapper deviceUpdateWrapper = new UpdateWrapper<>(); deviceUpdateWrapper.eq("id", device.getId()) - .set("binding_user_id", null) .set("binding_status", BindingStatusEnum.UNBOUND.getCode()) + .set("binding_user_id", null) .set("binding_time", null); deviceMapper.update(null, deviceUpdateWrapper); - Long userId = AppLoginHelper.getUserId(); + if (userId == null) { + userId = AppLoginHelper.getUserId(); + } QueryWrapper bindRecordQueryWrapper = new QueryWrapper<>(); bindRecordQueryWrapper.eq("device_id", device.getId()); - bindRecordQueryWrapper.eq("binding_user_id", userId); - AppDeviceBindRecord appDeviceBindRecord = appDeviceBindRecordMapper.selectOne(bindRecordQueryWrapper); - if (appDeviceBindRecord != null) { - return appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId()); + // 设备端解绑 0:设备端解绑 1:web端解绑 + if (type == 1) { + bindRecordQueryWrapper.eq("binding_user_id", userId); + } + + // AppDeviceBindRecord appDeviceBindRecord = appDeviceBindRecordMapper.selectOne(bindRecordQueryWrapper); + // if (appDeviceBindRecord != null) { + // return appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId()); + // } + + List appDeviceBindRecordList = appDeviceBindRecordMapper.selectList(bindRecordQueryWrapper); + if (CollectionUtil.isNotEmpty(appDeviceBindRecordList)) { + appDeviceBindRecordList.forEach(appDeviceBindRecord -> + appDeviceBindRecordMapper.deleteById(appDeviceBindRecord.getId())); } return 1; } + public AppDeviceDetailVo getInfo(Long id) { Device device = deviceMapper.selectById(id); if (device == null) { @@ -228,7 +226,7 @@ public class AppDeviceBizService { vo.setDeviceMac(device.getDeviceMac()); vo.setDeviceStatus(device.getDeviceStatus()); DeviceType deviceType = deviceTypeMapper.selectById(device.getDeviceType()); - if(deviceType!=null){ + if (deviceType != null) { vo.setCommunicationMode(Integer.valueOf(deviceType.getCommunicationMode())); vo.setTypeName(deviceType.getTypeName()); } @@ -239,7 +237,7 @@ public class AppDeviceBizService { QueryWrapper qw = new QueryWrapper() .eq("device_id", device.getId()); AppPersonnelInfo appPersonnelInfo = appPersonnelInfoMapper.selectOne(qw); - if(appPersonnelInfo != null){ + if (appPersonnelInfo != null) { AppPersonnelInfoVo personnelInfoVo = MapstructUtils.convert(appPersonnelInfo, AppPersonnelInfoVo.class); vo.setPersonnelInfo(personnelInfoVo); } @@ -269,19 +267,21 @@ public class AppDeviceBizService { mqttGateway.sendMsgToMqtt(MqttConstants.GLOBAL_PUB_KEY+deviceObj.getDeviceImei(), 1 ,personnelInfo); log.info("发送点阵数据到设备消息:{}", bo); - if(ObjectUtils.length(appPersonnelInfoVos) == 0){ + if (ObjectUtils.length(appPersonnelInfoVos) == 0) { AppPersonnelInfo appPersonnelInfo = MapstructUtils.convert(bo, AppPersonnelInfo.class); return appPersonnelInfoMapper.insertOrUpdate(appPersonnelInfo); - }else { + } else { UpdateWrapper uw = new UpdateWrapper<>(); uw.eq("device_id", deviceId) .set("name", bo.getName()) .set("position", bo.getPosition()) .set("unit_name", bo.getUnitName()) - .set("code",bo.getCode()); - return appPersonnelInfoMapper.update(null, uw)>0; + .set("code", bo.getCode()); + return appPersonnelInfoMapper.update(null, uw) > 0; } } + + } diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttMessageRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttMessageRule.java new file mode 100644 index 0000000..e69c06a --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttMessageRule.java @@ -0,0 +1,26 @@ +package com.fuyuanshen.global.mqtt.base; + +/** + * MQTT消息处理接口 + */ +public interface MqttMessageRule { + + /** + * 获取命令类型 + * @return 命令类型 + */ + String getCommandType(); + /** + * 执行处理 + * @param context 处理上下文 + */ + void execute(MqttRuleContext context); + + /** + * 获取优先级,数值越小优先级越高 + * @return 优先级 + */ + default int getPriority() { + return 0; + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleContext.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleContext.java new file mode 100644 index 0000000..cccbe15 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleContext.java @@ -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 payloadDict; +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleEngine.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleEngine.java new file mode 100644 index 0000000..66ea4dc --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/base/MqttRuleEngine.java @@ -0,0 +1,39 @@ +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 rulesMap = new LinkedHashMap<>(); + public MqttRuleEngine(List 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("Light_"+commandType); + if (mqttMessageRule != null) { + mqttMessageRule.execute(context); + return true; + } + + return false; + } +} diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttConfiguration.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttConfiguration.java similarity index 87% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttConfiguration.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttConfiguration.java index 002b6b5..745dd63 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttConfiguration.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttConfiguration.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.system.mqtt.config; +package com.fuyuanshen.global.mqtt.config; import org.eclipse.paho.client.mqttv3.MqttConnectOptions; import org.springframework.beans.factory.annotation.Autowired; @@ -7,12 +7,7 @@ import org.springframework.context.annotation.Configuration; import org.springframework.integration.mqtt.core.DefaultMqttPahoClientFactory; import org.springframework.integration.mqtt.core.MqttPahoClientFactory; -/** - * @Author: HarryLin - * @Date: 2025/3/20 14:40 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ + @Configuration public class MqttConfiguration { @Autowired diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttGateway.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java similarity index 94% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttGateway.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java index 0f24318..a1b8eb2 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttGateway.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttGateway.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.system.mqtt.config; +package com.fuyuanshen.global.mqtt.config; import org.springframework.integration.annotation.MessagingGateway; import org.springframework.integration.mqtt.support.MqttHeaders; diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttInboundConfiguration.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttInboundConfiguration.java similarity index 90% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttInboundConfiguration.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttInboundConfiguration.java index 14a83ec..102fe71 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttInboundConfiguration.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttInboundConfiguration.java @@ -1,8 +1,8 @@ -package com.fuyuanshen.system.mqtt.config; +package com.fuyuanshen.global.mqtt.config; import cn.hutool.core.lang.UUID; -import com.fuyuanshen.system.mqtt.receiver.ReceiverMessageHandler; +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; @@ -15,12 +15,7 @@ import org.springframework.integration.mqtt.support.DefaultPahoMessageConverter; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; -/** - * @Author: HarryLin - * @Date: 2025/3/20 14:54 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ + @Configuration public class MqttInboundConfiguration { @Autowired diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttOutboundConfiguration.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttOutboundConfiguration.java similarity index 89% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttOutboundConfiguration.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttOutboundConfiguration.java index 8ae31fc..01cddde 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttOutboundConfiguration.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttOutboundConfiguration.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.system.mqtt.config; +package com.fuyuanshen.global.mqtt.config; import cn.hutool.core.lang.UUID; import lombok.extern.slf4j.Slf4j; @@ -12,12 +12,6 @@ import org.springframework.integration.mqtt.outbound.MqttPahoMessageHandler; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; -/** - * @Author: HarryLin - * @Date: 2025/3/20 15:46 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ @Configuration @Slf4j public class MqttOutboundConfiguration { diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttPropertiesConfig.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttPropertiesConfig.java similarity index 70% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttPropertiesConfig.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttPropertiesConfig.java index 9ae3374..6c5d7db 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/config/MqttPropertiesConfig.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/config/MqttPropertiesConfig.java @@ -1,15 +1,10 @@ -package com.fuyuanshen.system.mqtt.config; +package com.fuyuanshen.global.mqtt.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; -/** - * @Author: HarryLin - * @Date: 2025/3/20 14:32 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ + @Data @ConfigurationProperties(prefix = "mqtt") @Component diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java new file mode 100644 index 0000000..5687f33 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/LightingCommandTypeConstants.java @@ -0,0 +1,76 @@ +package com.fuyuanshen.global.mqtt.constants; + +/** + * 设备命令类型常量 + * Device Command Type Constants + */ +public class LightingCommandTypeConstants { + + /** + * 灯光模式 (Light Mode) + */ + public static final String LIGHT_MODE = "Light_1"; + + /** + * 人员信息 (Personnel Information) + */ + public static final String PERSONNEL_INFO = "Light_2"; + + /** + * 开机LOGO (Boot Logo) + */ + public static final String BOOT_LOGO = "Light_3"; + + /** + * 激光灯 (Laser Light) + */ + public static final String LASER_LIGHT = "Light_4"; + + /** + * 主灯亮度 (Main Light Brightness) + */ + public static final String MAIN_LIGHT_BRIGHTNESS = "Light_5"; + + /** + * 定位数据 (Location Data) + */ + public static final String LOCATION_DATA = "Light_11"; + + /** + * 主动上报设备数据 (Active Reporting Device Data) + */ + public static final String ACTIVE_REPORTING_DEVICE_DATA = "Light_12"; + + /** + * 获取命令类型描述 + * + * @param commandType 命令类型 + * @return 命令类型描述 + */ + public static String getCommandTypeDescription(String commandType) { + return switch (commandType) { + case LIGHT_MODE -> "灯光模式 (Light Mode)"; + case PERSONNEL_INFO -> "人员信息 (Personnel Information)"; + case BOOT_LOGO -> "开机LOGO (Boot Logo)"; + case LASER_LIGHT -> "激光灯 (Laser Light)"; + case MAIN_LIGHT_BRIGHTNESS -> "主灯亮度 (Main Light Brightness)"; + case LOCATION_DATA -> "定位数据 (Location Data)"; + default -> "未知命令类型 (Unknown Command Type)"; + }; + } + + /** + * 检查是否为有效命令类型 + * + * @param commandType 命令类型 + * @return 是否有效 + */ + public static boolean isValidCommandType(String commandType) { + return commandType.equals(LIGHT_MODE) || + commandType.equals(PERSONNEL_INFO) || + commandType.equals(BOOT_LOGO) || + commandType.equals(LASER_LIGHT) || + commandType.equals(MAIN_LIGHT_BRIGHTNESS) || + commandType.equals(LOCATION_DATA); + } +} diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/constants/MqttConstants.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/MqttConstants.java similarity index 81% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/constants/MqttConstants.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/MqttConstants.java index 49398a1..7a80a1e 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/constants/MqttConstants.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/constants/MqttConstants.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.system.mqtt.constants; +package com.fuyuanshen.global.mqtt.constants; public interface MqttConstants { diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/DeviceDataController.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/DeviceDataController.java similarity index 93% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/DeviceDataController.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/DeviceDataController.java index e879402..8dacb88 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/DeviceDataController.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/DeviceDataController.java @@ -1,4 +1,4 @@ -package com.fuyuanshen.system.mqtt.publish; +package com.fuyuanshen.global.mqtt.publish; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttClientTest.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttClientTest.java similarity index 84% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttClientTest.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttClientTest.java index 2332809..776b499 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttClientTest.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttClientTest.java @@ -1,7 +1,7 @@ -package com.fuyuanshen.system.mqtt.publish; +package com.fuyuanshen.global.mqtt.publish; -import com.fuyuanshen.system.mqtt.config.MqttGateway; +import com.fuyuanshen.global.mqtt.config.MqttGateway; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttMessageSender.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java similarity index 89% rename from fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttMessageSender.java rename to fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java index 05bf77e..dcb429c 100644 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/publish/MqttMessageSender.java +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/publish/MqttMessageSender.java @@ -1,6 +1,6 @@ -package com.fuyuanshen.system.mqtt.publish; +package com.fuyuanshen.global.mqtt.publish; -import com.fuyuanshen.system.mqtt.config.MqttGateway; +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; diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java new file mode 100644 index 0000000..f7619a6 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/receiver/ReceiverMessageHandler.java @@ -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); + } + } + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java new file mode 100644 index 0000000..bad3faa --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/ActiveReportingDeviceDataRule.java @@ -0,0 +1,95 @@ +package com.fuyuanshen.global.mqtt.rule; + +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.LightingCommandTypeConstants; +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; + +/** + * 主动上报设备数据命令处理 + * "第1位为12表示设备主动上报设备硬件状态,第2为表示当时设备主灯档位,第3位表示当时激光灯档位,第4位电量百分比,第5位为充电状态(0没有充电,1正在充电,2为已充满) + * 第6位200代表电池剩余续航时间200分钟" + */ +@Component +@RequiredArgsConstructor +@Slf4j +public class ActiveReportingDeviceDataRule implements MqttMessageRule { + + private final MqttGateway mqttGateway; + + + @Override + public String getCommandType() { + return LightingCommandTypeConstants.ACTIVE_REPORTING_DEVICE_DATA; + } + + @Override + public void execute(MqttRuleContext context) { + try { + Object[] convertArr = context.getConvertArr(); + // Latitude, longitude + //主灯档位,激光灯档位,电量百分比,充电状态,电池剩余续航时间 + String mainLightMode = convertArr[1].toString(); + String laserLightMode = convertArr[2].toString(); + String batteryPercentage = convertArr[3].toString(); + String chargeState = convertArr[4].toString(); + String batteryRemainingTime = convertArr[5].toString(); + + // 异步发送设备状态和位置信息到Redis + asyncSendDeviceDataToRedisWithFuture(context.getDeviceImei(), mainLightMode, laserLightMode, + batteryPercentage, chargeState, batteryRemainingTime); + } catch (Exception e) { + log.error("处理定位数据命令时出错", e); + } + } + + /** + * 异步发送设备状态信息和位置信息到Redis(使用CompletableFuture) + * + * @param deviceImei 设备IMEI + * @param mainLightMode 主灯档位 + * @param laserLightMode 激光灯档位 + * @param batteryPercentage 电量百分比 + * @param chargeState 充电状态 + * @param batteryRemainingTime 电池剩余续航时间 + */ + public void asyncSendDeviceDataToRedisWithFuture(String deviceImei, String mainLightMode, String laserLightMode, + String batteryPercentage, String chargeState, String batteryRemainingTime) { + CompletableFuture.runAsync(() -> { + try { + // 构造设备状态信息对象 + Map deviceInfo = new LinkedHashMap<>(); + deviceInfo.put("deviceImei", deviceImei); + deviceInfo.put("mainLightMode", mainLightMode); + deviceInfo.put("laserLightMode", laserLightMode); + deviceInfo.put("batteryPercentage", batteryPercentage); + deviceInfo.put("chargeState", chargeState); + deviceInfo.put("batteryRemainingTime", batteryRemainingTime); + deviceInfo.put("timestamp", System.currentTimeMillis()); + + // 将设备状态信息存储到Redis中 + String deviceRedisKey = "device:status:" + deviceImei; + String deviceInfoJson = JsonUtils.toJsonString(deviceInfo); + + // 存储到Redis,设置过期时间(例如24小时) + RedisUtils.setCacheObject(deviceRedisKey, deviceInfoJson, Duration.ofSeconds(24 * 60 * 60)); + + log.info("设备状态信息已异步发送到Redis: device={}, mainLightMode={}, laserLightMode={}, batteryPercentage={}", + deviceImei, mainLightMode, laserLightMode, batteryPercentage); + } catch (Exception e) { + log.error("异步发送设备信息到Redis时出错: device={}, error={}", deviceImei, e.getMessage(), e); + } + }); + } + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java new file mode 100644 index 0000000..feae373 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/LocationDataRule.java @@ -0,0 +1,149 @@ +package com.fuyuanshen.global.mqtt.rule; + +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.LightingCommandTypeConstants; +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 String getCommandType() { + return LightingCommandTypeConstants.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 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 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 { + if(StringUtils.isNotBlank(latitude) || StringUtils.isNotBlank(longitude)){ + return; + } + // 构造位置信息对象 + Map locationInfo = new LinkedHashMap<>(); + double[] doubles = LngLonUtil.gps84_To_Gcj02(Double.parseDouble(latitude), Double.parseDouble(longitude)); + locationInfo.put("deviceImei", deviceImei); + locationInfo.put("latitude", doubles[0]); + locationInfo.put("longitude", doubles[1]); + String address = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); + 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 buildLocationDataMap(String latitude, String longitude) { + String[] latArr = latitude.split("\\."); + String[] lonArr = longitude.split("\\."); + + ArrayList intData = new ArrayList<>(); + intData.add(11); + 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 map = new HashMap<>(); + map.put("instruct", intData); + return map; + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java new file mode 100644 index 0000000..eed9bde --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/global/mqtt/rule/PersonnelInfoRule.java @@ -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.LightingCommandTypeConstants; +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 String getCommandType() { + return LightingCommandTypeConstants.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 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 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); + } + } +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java new file mode 100644 index 0000000..eadb157 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/controller/device/WEBDeviceController.java @@ -0,0 +1,46 @@ +package com.fuyuanshen.web.controller.device; + + +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.web.service.WEBDeviceService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @Description: + * @Author: WY + * @Date: 2025/5/16 + **/ +@Slf4j +@Tag(name = "web:设备管理", description = "web:设备管理") +@RestController +@RequiredArgsConstructor +@RequestMapping("/api/device") +public class WEBDeviceController extends BaseController { + + private final WEBDeviceService deviceService; + + + /** + * @param id + * @return + * @ModelAttribute 主要用于将请求参数绑定到 Java 对象上,它会从 HTTP 请求的查询参数(Query Parameters) + * 或表单数据(Form Data)中提取值,并自动填充到指定的对象属性中。 + */ + // @Log("解绑设备") + @Operation(summary = "WEB端解绑设备") + @DeleteMapping(value = "/unbind") + public R unbindDevice(Long id, Long userId) { + return toAjax(deviceService.webUnBindDevice(id, userId)); + } + + +} + + diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java new file mode 100644 index 0000000..0274717 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/WEBDeviceService.java @@ -0,0 +1,32 @@ +package com.fuyuanshen.web.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.IService; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.dto.AppDeviceBo; +import com.fuyuanshen.equipment.domain.form.DeviceForm; +import com.fuyuanshen.equipment.domain.query.DeviceQueryCriteria; +import com.fuyuanshen.equipment.domain.vo.AppDeviceVo; +import com.fuyuanshen.equipment.domain.vo.CustomerVo; + +import java.io.IOException; +import java.util.List; + +/** + * @Description: + * @Author: WY + * @Date: 2025/5/16 + **/ +public interface WEBDeviceService extends IService { + + /** + * WEB端解绑设备 + * + * @param id + * @return + */ + int webUnBindDevice(Long id, Long userId); + +} diff --git a/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java b/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java new file mode 100644 index 0000000..9f8e041 --- /dev/null +++ b/fys-admin/src/main/java/com/fuyuanshen/web/service/impl/WEBDeviceServiceImpl.java @@ -0,0 +1,51 @@ +package com.fuyuanshen.web.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.fuyuanshen.app.service.AppDeviceBizService; +import com.fuyuanshen.equipment.domain.Device; +import com.fuyuanshen.equipment.domain.DeviceAssignments; +import com.fuyuanshen.equipment.mapper.DeviceAssignmentsMapper; +import com.fuyuanshen.equipment.mapper.DeviceMapper; +import com.fuyuanshen.web.service.WEBDeviceService; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +/** + * @Description: + * @Author: WY + * @Date: 2025/5/16 + **/ +@Slf4j +@Service +@RequiredArgsConstructor +public class WEBDeviceServiceImpl extends ServiceImpl implements WEBDeviceService { + + private final AppDeviceBizService appDeviceService; + + private final DeviceAssignmentsMapper deviceAssignmentsMapper; + + + /** + * WEB端解绑设备 + * + * @param id + * @return + */ + @Override + public int webUnBindDevice(Long id, Long userId) { + // 设备端解绑 0:设备端解绑 1:web端解绑 + int type = 1; + if (userId == null) { + DeviceAssignments deviceAssignments = deviceAssignmentsMapper.selectById(id); + if (deviceAssignments == null) { + throw new RuntimeException("请先将设备入库!!!"); + } + id = deviceAssignments.getDeviceId(); + type = 0; + } + return appDeviceService.unBindDevice(id, userId, type); + } + + +} diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java new file mode 100644 index 0000000..5c6996e --- /dev/null +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/Bitmap80x12Generator.java @@ -0,0 +1,362 @@ +package com.fuyuanshen.common.core.utils; + +import javax.imageio.ImageIO; +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * 80*12像素点阵生成工具 + */ +public class Bitmap80x12Generator { + + public static void main(String[] args) throws IOException { + // 测试生成中文文本的点阵数据 + String text = "张三"; + byte[] bitmapData = generateFixedBitmapData(text, 120); +// System.out.println(Arrays.toString(bitmapData)); + int[] ints = convertHexToDecimal(bitmapData); + System.out.println(Arrays.toString(ints)); + // 生成预览图片 + byte[] bytes = convertDecimalToByteArray(ints); + BufferedImage image = convertByteArrayToImage(bytes, 12, 80); + ImageIO.write(image, "PNG", new File("D:\\bitmap_preview.png")); + System.out.println("成功生成预览图片: D:\\bitmap_preview.png"); + + // 打印十六进制数据 +// System.out.println("生成的点阵数据2:"); +// printHexData(bitmapData); +// int[] ints = convertHexToDecimal(bitmapData); + System.out.println("打印十进制无符号:"+Arrays.toString(ints)); +// printDecimalData(bitmapData); + + // 生成C文件 + generateCFile(bitmapData, "bitmap_data.c", "chinese_text"); + } + + /** + * 将十进制整数数组转换为字节数组 + * + * @param decimalArray 十进制整数数组(假设每个值都在0-255范围内) + * @return 字节数组 + */ + public static byte[] convertDecimalToByteArray(int[] decimalArray) { + if (decimalArray == null) { + return new byte[0]; + } + + byte[] byteArray = new byte[decimalArray.length]; + for (int i = 0; i < decimalArray.length; i++) { + // 确保值在0-255范围内,这是byte的无符号表示范围 + int value = decimalArray[i] & 0xFF; + byteArray[i] = (byte) value; + } + + return byteArray; + } + + /** + * 打印字节数组(以十进制形式显示) + * + * @param data 字节数组 + */ + public static void printByteArrayAsDecimal(byte[] data) { + System.out.println("字节数组(十进制显示):"); + for (int i = 0; i < data.length; i++) { + // 将字节转换为无符号十进制数显示 + int value = data[i] & 0xFF; + System.out.print(value); + + if (i < data.length - 1) { + System.out.print(", "); + if ((i + 1) % 12 == 0) { + System.out.println(); + } + } + } + System.out.println(); + } + + + /** + * 将十六进制字节数组转换为十进制整数数组 + * + * @param data 字节数组 + * @return 十进制整数数组 + */ + public static int[] convertHexToDecimal(byte[] data) { + if (data == null) { + return new int[0]; + } + + int[] decimalArray = new int[data.length]; + for (int i = 0; i < data.length; i++) { + // 将字节转换为无符号整数(十进制) + decimalArray[i] = data[i] & 0xFF; + } + + return decimalArray; + } + + /** + * 打印十进制数据 + * + * @param data 字节数组 + */ + public static void printDecimalData(byte[] data) { + int[] decimalArray = convertHexToDecimal(data); + + System.out.println("生成的十进制数据:"); + for (int i = 0; i < decimalArray.length; i++) { + System.out.print(decimalArray[i]); + + if (i < decimalArray.length - 1) { + System.out.print(", "); + if ((i + 1) % 12 == 0) { + System.out.println(); + } + } + } + System.out.println(); + } + + public static void buildArr(int[] data,List intData){ + for (int datum : data) { + intData.add(datum); + } + } + + /** + * 生成固定长度的点阵数据 + * + * @param text 要转换的文本 + * @param fixedLength 固定长度(字节) + * @return 固定长度的点阵数据 + */ + public static byte[] generateFixedBitmapData(String text, int fixedLength) { + if (text == null || text.isEmpty()) { + return new byte[fixedLength]; + } + + // 创建80*12像素的图像 + Font font = new Font("宋体", Font.PLAIN, 12); + BufferedImage image = createTextImage(text, font, 80, 12); + + // 提取点阵数据 + byte[] rawData = extractBitmapData(image); +// System.out.println("生成的点阵数据1:"); +// System.out.println(Arrays.toString(rawData)); + + // 调整到固定长度 + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + // 剩余部分自动初始化为0 + + return result; + } + + /** + * 创建文本图像 + */ + private static BufferedImage createTextImage(String text, Font font, int width, int height) { + // 创建图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + Graphics2D g = image.createGraphics(); + + // 设置白色背景 + g.setColor(Color.WHITE); + g.fillRect(0, 0, width, height); + + // 设置黑色文本 + g.setColor(Color.BLACK); + g.setFont(font); + + // 关闭抗锯齿 + g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, + RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); + g.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + // 获取字体度量 + FontMetrics metrics = g.getFontMetrics(); + + // 计算文本绘制位置(居中) + int textWidth = metrics.stringWidth(text); +// int x = Math.max(0, (width - textWidth) / 2); // 水平居中 + // 左对齐 + int x = 0; + int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); // 垂直居中 + + // 绘制文本 + g.drawString(text, x, y); + + g.dispose(); + return image; + } + + /** + * 提取点阵数据 - 从左到右,从上到下扫描 + */ + private static byte[] extractBitmapData(BufferedImage image) { + int width = image.getWidth(); + int height = image.getHeight(); + + List byteList = new ArrayList<>(); + int currentByte = 0; + int bitCount = 0; + + // 从上到下,从左到右扫描 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + // 获取像素颜色 + Color color = new Color(image.getRGB(x, y)); + + // 判断是否为黑色(阈值处理) + int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3; + boolean isBlack = gray < 128; + + // 高位优先打包 + currentByte = (currentByte << 1) | (isBlack ? 1 : 0); + bitCount++; + + if (bitCount == 8) { + byteList.add((byte) currentByte); + currentByte = 0; + bitCount = 0; + } + } + } + + // 处理最后不满8位的部分 + if (bitCount > 0) { + currentByte <<= (8 - bitCount); + byteList.add((byte) currentByte); + } + + return byteListToArray(byteList); + } + + private static byte[] byteListToArray(List byteList) { + byte[] result = new byte[byteList.size()]; + for (int i = 0; i < byteList.size(); i++) { + result[i] = byteList.get(i); + } + return result; + } + + /** + * 字节数组转图像 + */ + public static BufferedImage convertByteArrayToImage(byte[] data, int height, int width) { + if (data == null || data.length == 0) { + return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); + } + + // 创建RGB图像 + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + + // 设置白色背景 + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + image.setRGB(x, y, Color.WHITE.getRGB()); + } + } + + // 从左到右,从上到下设置像素点 + int bitIndex = 0; + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + for (int bit = 7; bit >= 0; bit--) { // 高位在前 + boolean isBlack = ((value >> bit) & 1) == 1; + if (isBlack) { + int x = bitIndex % width; + int y = bitIndex / width; + if (x < width && y < height) { // 确保不越界 + image.setRGB(x, y, Color.BLACK.getRGB()); + } + } + bitIndex++; + + // 如果已经处理完所有像素,则退出 + if (bitIndex >= width * height) { + return image; + } + } + } + + return image; + } + + public static String convertToCArrayString(byte[] data, String arrayName) { + StringBuilder sb = new StringBuilder(); + sb.append(String.format("// %s: %d 字节\n", arrayName, data.length)); + sb.append(String.format("const uint8_t %s[] = {\n ", arrayName)); + + for (int i = 0; i < data.length; i++) { + sb.append(String.format("0x%02X", data[i] & 0xFF)); + + if (i < data.length - 1) { + sb.append(", "); + // 每12个元素换行 + if ((i + 1) % 12 == 0) { + sb.append("\n "); + } + } + } + + sb.append("\n};"); + return sb.toString(); + } + /** + * 打印十六进制数据 + */ + private static void printHexData(byte[] data) { + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + System.out.printf("0x%02X", value); + + if (i < data.length - 1) { + System.out.print(", "); + if ((i + 1) % 12 == 0) System.out.println(); + } + } + System.out.println(); + } + + /** + * 生成C文件 + */ + public static void generateCFile(byte[] data, String filename, String arrayName) throws IOException { + try (FileWriter writer = new FileWriter(filename)) { + writer.write("/**\n"); + writer.write(" * 80*12点阵显示数据\n"); + writer.write(" * 数据大小: " + data.length + " 字节\n"); + writer.write(" * 分辨率: 80*12 像素\n"); + writer.write(" */\n\n"); + writer.write("#include \n\n"); + + writer.write(String.format("// %s: %d 字节, 80*12 像素\n", arrayName, data.length)); + writer.write(String.format("const uint8_t %s[] = {\n ", arrayName)); + writeByteArray(writer, data); + writer.write("\n};\n"); + } + } + + private static void writeByteArray(FileWriter writer, byte[] data) throws IOException { + for (int i = 0; i < data.length; i++) { + int value = data[i] & 0xFF; + writer.write(String.format("0x%02X", value)); + + if (i < data.length - 1) { + writer.write(", "); + if ((i + 1) % 12 == 0) writer.write("\n "); + } + } + } +} diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java new file mode 100644 index 0000000..45fea74 --- /dev/null +++ b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverter.java @@ -0,0 +1,373 @@ +package com.fuyuanshen.common.core.utils; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.*; +import java.util.ArrayList; +import java.util.List; + +public class ImageToCArrayConverter { + +/* public static void main(String[] args) { + try { + byte[] imageData = convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", 160, 80,25600); + System.out.println("长度:"+imageData.length); +// int[] ints =convertHexToDecimal(imageData); +// System.out.println("Image data: " + Arrays.toString(ints)); +// writeFile("E:\\workspace\\output.c", imageData,160,80); +// System.out.println("转换成功!"); + ArrayList intData = new ArrayList<>(); + intData.add(2); + buildArr(convertHexToDecimal(imageData),intData); + intData.add(0); + intData.add(0); + intData.add(0); + intData.add(0); + Map map = new HashMap<>(); + map.put("instruct", intData); + System.out.println(JSON.toJSONString( map)); + } catch (IOException e) { + System.err.println("转换失败: " + e.getMessage()); + } + }*/ + + public static void main(String[] args) throws IOException { + + byte[] largeData = convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", 160, 80,25600); + System.out.println("长度:"+largeData.length); + + System.out.println("原始数据大小: " + largeData.length + " 字节"); + + // 将25600字节的数据分割成512字节的块 +// List chunks = splitByteArrayIntoChunks(largeData, 512); +// printChunkInfo(chunks); +// +// // 打印前几块的数据示例 +// System.out.println("\n前3块数据示例(十进制显示):"); +// for (int i = 0; i < Math.min(50, chunks.size()); i++) { +// System.out.println("块 " + i + ":"); +// int[] ints = convertHexToDecimal(chunks.get(i)); +// System.out.println(Arrays.toString(ints)); +// } + + // 示例:获取特定块的数据 + byte[] specificChunk = getChunk(largeData, 5, 512); // 获取第6块(索引5) + System.out.println("第6块数据大小: " + specificChunk.length + " 字节"); + + // 生成预览图片 +// BufferedImage image = convertByteArrayToImage(bitmapData, 12, 80); +// ImageIO.write(image, "PNG", new File("D:\\bitmap_preview.png")); +// System.out.println("成功生成预览图片: D:\\bitmap_preview.png"); +// +// // 生成C文件 +// generateCFile(bitmapData, "bitmap_data.c", "chinese_text"); + } + /** + * 获取指定块的数据 + * + * @param data 原始字节数组 + * @param chunkIndex 块索引(从0开始) + * @param chunkSize 每块大小 + * @return 指定块的字节数组,如果索引无效则返回空数组 + */ + public static byte[] getChunk(byte[] data, int chunkIndex, int chunkSize) { + if (data == null || chunkSize <= 0 || chunkIndex < 0) { + return new byte[0]; + } + + int start = chunkIndex * chunkSize; + if (start >= data.length) { + return new byte[0]; // 索引超出范围 + } + + int end = Math.min(start + chunkSize, data.length); + int length = end - start; + + byte[] chunk = new byte[length]; + System.arraycopy(data, start, chunk, 0, length); + return chunk; + } + + public static void buildArr(int[] data,List intData){ + for (int datum : data) { + intData.add(datum); + } + } + + /** + * 打印分块信息 + * + * @param chunks 分块后的字节数组列表 + */ + public static void printChunkInfo(List chunks) { + System.out.println("总共分割成 " + chunks.size() + " 块"); + for (int i = 0; i < chunks.size(); i++) { + System.out.println("块 " + i + ": " + chunks.get(i).length + " 字节"); + } + } + /** + * 将大字节数组分割成固定大小的块 + * + * @param data 原始字节数组 + * @param chunkSize 每块大小(字节数) + * @return 分割后的字节数组列表 + */ + public static List splitByteArrayIntoChunks(byte[] data, int chunkSize) { + if (data == null || data.length == 0 || chunkSize <= 0) { + return new ArrayList<>(); + } + + List chunks = new ArrayList<>(); + int totalChunks = (int) Math.ceil((double) data.length / chunkSize); + + for (int i = 0; i < totalChunks; i++) { + int start = i * chunkSize; + int end = Math.min(start + chunkSize, data.length); + int length = end - start; + + byte[] chunk = new byte[length]; + System.arraycopy(data, start, chunk, 0, length); + chunks.add(chunk); + } + + return chunks; + } + + public static int[] convertHexToDecimal(byte[] data) { + if (data == null) { + return new int[0]; + } + + int[] decimalArray = new int[data.length]; + for (int i = 0; i < data.length; i++) { + // 将字节转换为无符号整数(十进制) + decimalArray[i] = data[i] & 0xFF; + } + + return decimalArray; + } + + public static byte[] convertImageToCArray(InputStream inputStream, + int width, int height, int fixedLength) throws IOException { + // 读取原始图片 + BufferedImage originalImage = ImageIO.read(inputStream); + + // 调整图片尺寸 + BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + resizedImage.getGraphics().drawImage( + originalImage, 0, 0, width, height, null); + + // 转换像素数据为RGB565格式(高位在前) + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int rgb = resizedImage.getRGB(x, y); + + // 提取RGB分量 + int r = (rgb >> 16) & 0xFF; + int g = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + // 转换为RGB565(5位红,6位绿,5位蓝) + int r5 = (r >> 3) & 0x1F; + int g6 = (g >> 2) & 0x3F; + int b5 = (b >> 3) & 0x1F; + + // 组合为16位值 + int rgb565 = (r5 << 11) | (g6 << 5) | b5; + + // 高位在前(大端序)写入字节 + byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 + byteStream.write(rgb565 & 0xFF); // 低字节 + } + } + // 调整到固定长度 + byte[] rawData = byteStream.toByteArray(); + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + return result; + } + + public static byte[] convertImageToCArray(String inputPath, + int width, int height, int fixedLength) throws IOException { + // 读取原始图片 + BufferedImage originalImage = ImageIO.read(new File(inputPath)); + + // 调整图片尺寸 + BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); + resizedImage.getGraphics().drawImage( + originalImage, 0, 0, width, height, null); + + // 转换像素数据为RGB565格式(高位在前) + ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + int rgb = resizedImage.getRGB(x, y); + + // 提取RGB分量 + int r = (rgb >> 16) & 0xFF; + int g = (rgb >> 8) & 0xFF; + int b = rgb & 0xFF; + + // 转换为RGB565(5位红,6位绿,5位蓝) + int r5 = (r >> 3) & 0x1F; + int g6 = (g >> 2) & 0x3F; + int b5 = (b >> 3) & 0x1F; + + // 组合为16位值 + int rgb565 = (r5 << 11) | (g6 << 5) | b5; + + // 高位在前(大端序)写入字节 + byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 + byteStream.write(rgb565 & 0xFF); // 低字节 + } + } + // 调整到固定长度 + byte[] rawData = byteStream.toByteArray(); + byte[] result = new byte[fixedLength]; + int copyLength = Math.min(rawData.length, fixedLength); + System.arraycopy(rawData, 0, result, 0, copyLength); + return result; + } + + private static void writeFile(String outputPath, byte[] imageData,int width, int height) throws IOException { + // 生成C语言数组文件 + try (FileOutputStream fos = new FileOutputStream(outputPath)) { + // 写入注释行(包含尺寸信息) + String header = String.format("/* 0X10,0X10,0X00,0X%02X,0X00,0X%02X,0X01,0X1B, */\n", + width, height); + fos.write(header.getBytes()); + + // 写入数组声明 + fos.write("const unsigned char gImage_data[] = {\n".getBytes()); + + // 写入数据(每行16个字节) + for (int i = 0; i < imageData.length; i++) { + // 写入0X前缀 + fos.write(("0X" + String.format("%02X", imageData[i] & 0xFF)).getBytes()); + + // 添加逗号(最后一个除外) + if (i < imageData.length - 1) { + fos.write(','); + } + + // 换行和缩进 + if ((i + 1) % 16 == 0) { + fos.write('\n'); + } else { + fos.write(' '); + } + } + + // 写入数组结尾 + fos.write("\n};\n".getBytes()); + } + } + + /** + * 将字节字符串转换为字节数组 + * + * @param byteString 字节字符串,格式如 "[12, 45, 67, ...]" + * @return 字节数组 + */ + public static byte[] convertStringToByteArray(String byteString) { + if (byteString == null || byteString.isEmpty()) { + return new byte[0]; + } + + try { + // 移除方括号 + String content = byteString.trim(); + if (content.startsWith("[")) { + content = content.substring(1); + } + if (content.endsWith("]")) { + content = content.substring(0, content.length() - 1); + } + + // 按逗号分割 + String[] byteValues = content.split(","); + byte[] result = new byte[byteValues.length]; + + // 转换每个值 + for (int i = 0; i < byteValues.length; i++) { + String value = byteValues[i].trim(); + // 处理可能的进制前缀 + if (value.startsWith("0x") || value.startsWith("0X")) { + // 十六进制 + result[i] = (byte) Integer.parseInt(value.substring(2), 16); + } else { + // 十进制 + int intValue = Integer.parseInt(value); + result[i] = (byte) intValue; + } + } + + return result; + } catch (NumberFormatException e) { + System.err.println("解析字节字符串时出错: " + e.getMessage()); + return new byte[0]; + } + } + + /** + * 将字节字符串转换为混合类型的Object数组 + * + * @param byteString 字节字符串 + * @return Object数组,包含不同类型的对象 + */ + public static Object[] convertByteStringToMixedObjectArray(String byteString) { + if (byteString == null || byteString.isEmpty()) { + return new Object[0]; + } + + try { + // 移除方括号(如果存在) + String content = byteString.trim(); + if (content.startsWith("[")) { + content = content.substring(1); + } + if (content.endsWith("]")) { + content = content.substring(0, content.length() - 1); + } + + // 按逗号分割 + String[] byteValues = content.split(","); + Object[] result = new Object[byteValues.length]; + + // 转换每个值为适当类型的对象 + for (int i = 0; i < byteValues.length; i++) { + String value = byteValues[i].trim(); + + // 处理可能的进制前缀 + if (value.startsWith("0x") || value.startsWith("0X")) { + // 十六进制 + int intValue = Integer.parseInt(value.substring(2), 16); + result[i] = intValue; + } else { + // 尝试解析为整数 + try { + int intValue = Integer.parseInt(value); + // 根据值的范围选择合适的类型 + if (intValue >= Byte.MIN_VALUE && intValue <= Byte.MAX_VALUE) { + result[i] = (byte) intValue; + } else if (intValue >= Short.MIN_VALUE && intValue <= Short.MAX_VALUE) { + result[i] = (short) intValue; + } else { + result[i] = intValue; + } + } catch (NumberFormatException e) { + // 如果不是数字,保持为字符串 + result[i] = value; + } + } + } + + return result; + } catch (Exception e) { + System.err.println("解析字节字符串时出错: " + e.getMessage()); + return new Object[0]; + } + } +} \ No newline at end of file diff --git a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverterUtils.java b/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverterUtils.java deleted file mode 100644 index 598db1e..0000000 --- a/fys-common/fys-common-core/src/main/java/com/fuyuanshen/common/core/utils/ImageToCArrayConverterUtils.java +++ /dev/null @@ -1,90 +0,0 @@ -package com.fuyuanshen.common.core.utils; - -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.ByteArrayOutputStream; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; - -public class ImageToCArrayConverterUtils { - - public static void main(String[] args) { - try { - convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", "E:\\workspace\\output.c", 160, 80); - System.out.println("转换成功!"); - } catch (IOException e) { - System.err.println("转换失败: " + e.getMessage()); - } - } - - public static void convertImageToCArray(String inputPath, String outputPath, - int width, int height) throws IOException { - // 读取原始图片 - BufferedImage originalImage = ImageIO.read(new File(inputPath)); - - // 调整图片尺寸 - BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); - resizedImage.getGraphics().drawImage( - originalImage, 0, 0, width, height, null); - - // 转换像素数据为RGB565格式(高位在前) - ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - int rgb = resizedImage.getRGB(x, y); - - // 提取RGB分量 - int r = (rgb >> 16) & 0xFF; - int g = (rgb >> 8) & 0xFF; - int b = rgb & 0xFF; - - // 转换为RGB565(5位红,6位绿,5位蓝) - int r5 = (r >> 3) & 0x1F; - int g6 = (g >> 2) & 0x3F; - int b5 = (b >> 3) & 0x1F; - - // 组合为16位值 - int rgb565 = (r5 << 11) | (g6 << 5) | b5; - - // 高位在前(大端序)写入字节 - byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 - byteStream.write(rgb565 & 0xFF); // 低字节 - } - } - - byte[] imageData = byteStream.toByteArray(); - - // 生成C语言数组文件 - try (FileOutputStream fos = new FileOutputStream(outputPath)) { - // 写入注释行(包含尺寸信息) - String header = String.format("/* 0X10,0X10,0X00,0X%02X,0X00,0X%02X,0X01,0X1B, */\n", - width, height); - fos.write(header.getBytes()); - - // 写入数组声明 - fos.write("const unsigned char gImage_data[] = {\n".getBytes()); - - // 写入数据(每行16个字节) - for (int i = 0; i < imageData.length; i++) { - // 写入0X前缀 - fos.write(("0X" + String.format("%02X", imageData[i] & 0xFF)).getBytes()); - - // 添加逗号(最后一个除外) - if (i < imageData.length - 1) { - fos.write(','); - } - - // 换行和缩进 - if ((i + 1) % 16 == 0) { - fos.write('\n'); - } else { - fos.write(' '); - } - } - - // 写入数组结尾 - fos.write("\n};\n".getBytes()); - } - } -} \ No newline at end of file diff --git a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/AppDeviceBindRecord.java b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/AppDeviceBindRecord.java index 40698ce..5abebed 100644 --- a/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/AppDeviceBindRecord.java +++ b/fys-modules/fys-app/src/main/java/com/fuyuanshen/app/domain/AppDeviceBindRecord.java @@ -1,7 +1,5 @@ package com.fuyuanshen.app.domain; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; import com.fuyuanshen.common.tenant.core.TenantEntity; import lombok.Data; import lombok.EqualsAndHashCode; diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java index 0e9f3de..229c2da 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceController.java @@ -147,19 +147,19 @@ public class DeviceController extends BaseController { return R.ok(); } - - /** - * @param id - * @return - * @ModelAttribute 主要用于将请求参数绑定到 Java 对象上,它会从 HTTP 请求的查询参数(Query Parameters) - * 或表单数据(Form Data)中提取值,并自动填充到指定的对象属性中。 - */ - // @Log("解绑设备") - @Operation(summary = "WEB端解绑设备") - @GetMapping(value = "/unbind") - public R unbindDevice(@Validated Long id) { - return toAjax(deviceService.webUnBindDevice(id)); - } + // + // /** + // * @param id + // * @return + // * @ModelAttribute 主要用于将请求参数绑定到 Java 对象上,它会从 HTTP 请求的查询参数(Query Parameters) + // * 或表单数据(Form Data)中提取值,并自动填充到指定的对象属性中。 + // */ + // // @Log("解绑设备") + // @Operation(summary = "WEB端解绑设备") + // @GetMapping(value = "/unbind") + // public R unbindDevice(@Validated Long id) { + // return toAjax(deviceService.webUnBindDevice(id)); + // } @Operation(summary = "导出数据设备") diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceLogController.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceLogController.java new file mode 100644 index 0000000..61b3c8a --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/controller/DeviceLogController.java @@ -0,0 +1,106 @@ +package com.fuyuanshen.equipment.controller; + +import java.util.List; + +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import com.fuyuanshen.common.idempotent.annotation.RepeatSubmit; +import com.fuyuanshen.common.log.annotation.Log; +import com.fuyuanshen.common.web.core.BaseController; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.fuyuanshen.common.core.domain.R; +import com.fuyuanshen.common.core.validate.AddGroup; +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.common.log.enums.BusinessType; +import com.fuyuanshen.common.excel.utils.ExcelUtil; +import com.fuyuanshen.equipment.domain.vo.DeviceLogVo; +import com.fuyuanshen.equipment.domain.bo.DeviceLogBo; +import com.fuyuanshen.equipment.service.IDeviceLogService; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; + +/** + * 设备日志 + * + * @author Lion Li + * @date 2025-07-29 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/equipment/log") +public class DeviceLogController extends BaseController { + + private final IDeviceLogService deviceLogService; + + /** + * 查询设备日志列表 + */ + @SaCheckPermission("equipment:log:list") + @GetMapping("/list") + public TableDataInfo list(DeviceLogBo bo, PageQuery pageQuery) { + return deviceLogService.queryPageList(bo, pageQuery); + } + + /** + * 导出设备日志列表 + */ + @SaCheckPermission("equipment:log:export") + @Log(title = "设备日志", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(DeviceLogBo bo, HttpServletResponse response) { + List list = deviceLogService.queryList(bo); + ExcelUtil.exportExcel(list, "设备日志", DeviceLogVo.class, response); + } + + /** + * 获取设备日志详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("equipment:log:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(deviceLogService.queryById(id)); + } + + /** + * 新增设备日志 + */ + @SaCheckPermission("equipment:log:add") + @Log(title = "设备日志", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody DeviceLogBo bo) { + return toAjax(deviceLogService.insertByBo(bo)); + } + + /** + * 修改设备日志 + */ + @SaCheckPermission("equipment:log:edit") + @Log(title = "设备日志", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody DeviceLogBo bo) { + return toAjax(deviceLogService.updateByBo(bo)); + } + + /** + * 删除设备日志 + * + * @param ids 主键串 + */ + @SaCheckPermission("equipment:log:remove") + @Log(title = "设备日志", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(deviceLogService.deleteWithValidByIds(List.of(ids), true)); + } + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java index 2ccd0a3..0aaddb0 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/DeviceLog.java @@ -1,40 +1,51 @@ package com.fuyuanshen.equipment.domain; -import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.bean.copier.CopyOptions; -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import com.fuyuanshen.common.tenant.core.TenantEntity; +import com.baomidou.mybatisplus.annotation.*; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; /** - * @Description: - * @Author: WY - * @Date: 2025/5/24 - **/ + * 设备日志对象 device_log + * + * @author Lion Li + * @date 2025-07-29 + */ @Data +@EqualsAndHashCode(callSuper = true) @TableName("device_log") -public class DeviceLog extends TenantEntity { +public class DeviceLog extends BaseEntity { - @TableId(value = "id", type = IdType.AUTO) - // @Schema(value = "ID") + @Serial + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id") private Long id; - // @Schema(value = "设备行为") + /** + * 设备行为 + */ private String deviceAction; - // @Schema(value = "设备名称") + /** + * 设备名称 + */ private String deviceName; - // @Schema(value = "数据来源") + /** + * 数据来源 + */ private String dataSource; - // @Schema(value = "内容") + /** + * 内容 + */ private String content; - public void copy(DeviceLog source){ - BeanUtil.copyProperties(source,this, CopyOptions.create().setIgnoreNullValue(true)); - } } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java new file mode 100644 index 0000000..71900d5 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/bo/DeviceLogBo.java @@ -0,0 +1,49 @@ +package com.fuyuanshen.equipment.domain.bo; + +import com.fuyuanshen.common.core.validate.EditGroup; +import com.fuyuanshen.equipment.domain.DeviceLog; +import com.fuyuanshen.common.mybatis.core.domain.BaseEntity; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +/** + * 设备日志业务对象 device_log + * + * @author Lion Li + * @date 2025-07-29 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = DeviceLog.class, reverseConvertGenerate = false) +public class DeviceLogBo extends BaseEntity { + + /** + * ID + */ + @NotNull(message = "ID不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 设备行为 + */ + private String deviceAction; + + /** + * 设备名称 + */ + private String deviceName; + + /** + * 数据来源 + */ + private String dataSource; + + /** + * 内容 + */ + private String content; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java new file mode 100644 index 0000000..cbfbc6a --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/domain/vo/DeviceLogVo.java @@ -0,0 +1,62 @@ +package com.fuyuanshen.equipment.domain.vo; + +import com.fuyuanshen.equipment.domain.DeviceLog; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; +import com.fuyuanshen.common.excel.annotation.ExcelDictFormat; +import com.fuyuanshen.common.excel.convert.ExcelDictConvert; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + + + +/** + * 设备日志视图对象 device_log + * + * @author Lion Li + * @date 2025-07-29 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = DeviceLog.class) +public class DeviceLogVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ExcelProperty(value = "ID") + private Long id; + + /** + * 设备行为 + */ + @ExcelProperty(value = "设备行为") + private String deviceAction; + + /** + * 设备名称 + */ + @ExcelProperty(value = "设备名称") + private String deviceName; + + /** + * 数据来源 + */ + @ExcelProperty(value = "数据来源") + private String dataSource; + + /** + * 内容 + */ + @ExcelProperty(value = "内容") + private String content; + + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceLogMapper.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceLogMapper.java new file mode 100644 index 0000000..adff5de --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/mapper/DeviceLogMapper.java @@ -0,0 +1,15 @@ +package com.fuyuanshen.equipment.mapper; + +import com.fuyuanshen.equipment.domain.DeviceLog; +import com.fuyuanshen.equipment.domain.vo.DeviceLogVo; +import com.fuyuanshen.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 设备日志Mapper接口 + * + * @author Lion Li + * @date 2025-07-29 + */ +public interface DeviceLogMapper extends BaseMapperPlus { + +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java index 7d18d1e..22d738d 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/DeviceService.java @@ -114,4 +114,5 @@ public interface DeviceService extends IService { * @return */ int webUnBindDevice(Long id); + } diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceLogService.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceLogService.java new file mode 100644 index 0000000..5605d20 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/IDeviceLogService.java @@ -0,0 +1,68 @@ +package com.fuyuanshen.equipment.service; + +import com.fuyuanshen.equipment.domain.vo.DeviceLogVo; +import com.fuyuanshen.equipment.domain.bo.DeviceLogBo; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 设备日志Service接口 + * + * @author Lion Li + * @date 2025-07-29 + */ +public interface IDeviceLogService { + + /** + * 查询设备日志 + * + * @param id 主键 + * @return 设备日志 + */ + DeviceLogVo queryById(Long id); + + /** + * 分页查询设备日志列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 设备日志分页列表 + */ + TableDataInfo queryPageList(DeviceLogBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的设备日志列表 + * + * @param bo 查询条件 + * @return 设备日志列表 + */ + List queryList(DeviceLogBo bo); + + /** + * 新增设备日志 + * + * @param bo 设备日志 + * @return 是否新增成功 + */ + Boolean insertByBo(DeviceLogBo bo); + + /** + * 修改设备日志 + * + * @param bo 设备日志 + * @return 是否修改成功 + */ + Boolean updateByBo(DeviceLogBo bo); + + /** + * 校验并批量删除设备日志信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java new file mode 100644 index 0000000..60d46df --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/service/impl/DeviceLogServiceImpl.java @@ -0,0 +1,135 @@ +package com.fuyuanshen.equipment.service.impl; + +import com.fuyuanshen.common.core.utils.MapstructUtils; +import com.fuyuanshen.common.mybatis.core.page.TableDataInfo; +import com.fuyuanshen.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import com.fuyuanshen.equipment.domain.bo.DeviceLogBo; +import com.fuyuanshen.equipment.domain.vo.DeviceLogVo; +import com.fuyuanshen.equipment.domain.DeviceLog; +import com.fuyuanshen.equipment.mapper.DeviceLogMapper; +import com.fuyuanshen.equipment.service.IDeviceLogService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 设备日志Service业务层处理 + * + * @author Lion Li + * @date 2025-07-29 + */ +@Slf4j +@RequiredArgsConstructor +@Service +public class DeviceLogServiceImpl implements IDeviceLogService { + + private final DeviceLogMapper baseMapper; + + /** + * 查询设备日志 + * + * @param id 主键 + * @return 设备日志 + */ + @Override + public DeviceLogVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 分页查询设备日志列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 设备日志分页列表 + */ + @Override + public TableDataInfo queryPageList(DeviceLogBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的设备日志列表 + * + * @param bo 查询条件 + * @return 设备日志列表 + */ + @Override + public List queryList(DeviceLogBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(DeviceLogBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.orderByAsc(DeviceLog::getId); + lqw.eq(StringUtils.isNotBlank(bo.getDeviceAction()), DeviceLog::getDeviceAction, bo.getDeviceAction()); + lqw.like(StringUtils.isNotBlank(bo.getDeviceName()), DeviceLog::getDeviceName, bo.getDeviceName()); + lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), DeviceLog::getDataSource, bo.getDataSource()); + lqw.eq(StringUtils.isNotBlank(bo.getContent()), DeviceLog::getContent, bo.getContent()); + return lqw; + } + + /** + * 新增设备日志 + * + * @param bo 设备日志 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(DeviceLogBo bo) { + DeviceLog add = MapstructUtils.convert(bo, DeviceLog.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改设备日志 + * + * @param bo 设备日志 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(DeviceLogBo bo) { + DeviceLog update = MapstructUtils.convert(bo, DeviceLog.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(DeviceLog entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除设备日志信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/Bitmap80x12Generator.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/Bitmap80x12Generator.java new file mode 100644 index 0000000..2262e10 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/Bitmap80x12Generator.java @@ -0,0 +1,362 @@ +//package com.fuyuanshen.equipment.utils.c; +// +//import javax.imageio.ImageIO; +//import java.awt.*; +//import java.awt.image.BufferedImage; +//import java.io.File; +//import java.io.FileWriter; +//import java.io.IOException; +//import java.util.ArrayList; +//import java.util.Arrays; +//import java.util.List; +// +///** +// * 80*12像素点阵生成工具 +// */ +//public class Bitmap80x12Generator { +// +// public static void main(String[] args) throws IOException { +// // 测试生成中文文本的点阵数据 +// String text = "张三"; +// byte[] bitmapData = generateFixedBitmapData(text, 120); +//// System.out.println(Arrays.toString(bitmapData)); +// int[] ints = convertHexToDecimal(bitmapData); +// System.out.println(Arrays.toString(ints)); +// // 生成预览图片 +// byte[] bytes = convertDecimalToByteArray(ints); +// BufferedImage image = convertByteArrayToImage(bytes, 12, 80); +// ImageIO.write(image, "PNG", new File("D:\\bitmap_preview.png")); +// System.out.println("成功生成预览图片: D:\\bitmap_preview.png"); +// +// // 打印十六进制数据 +//// System.out.println("生成的点阵数据2:"); +//// printHexData(bitmapData); +//// int[] ints = convertHexToDecimal(bitmapData); +// System.out.println("打印十进制无符号:"+Arrays.toString(ints)); +//// printDecimalData(bitmapData); +// +// // 生成C文件 +// generateCFile(bitmapData, "bitmap_data.c", "chinese_text"); +// } +// +// /** +// * 将十进制整数数组转换为字节数组 +// * +// * @param decimalArray 十进制整数数组(假设每个值都在0-255范围内) +// * @return 字节数组 +// */ +// public static byte[] convertDecimalToByteArray(int[] decimalArray) { +// if (decimalArray == null) { +// return new byte[0]; +// } +// +// byte[] byteArray = new byte[decimalArray.length]; +// for (int i = 0; i < decimalArray.length; i++) { +// // 确保值在0-255范围内,这是byte的无符号表示范围 +// int value = decimalArray[i] & 0xFF; +// byteArray[i] = (byte) value; +// } +// +// return byteArray; +// } +// +// /** +// * 打印字节数组(以十进制形式显示) +// * +// * @param data 字节数组 +// */ +// public static void printByteArrayAsDecimal(byte[] data) { +// System.out.println("字节数组(十进制显示):"); +// for (int i = 0; i < data.length; i++) { +// // 将字节转换为无符号十进制数显示 +// int value = data[i] & 0xFF; +// System.out.print(value); +// +// if (i < data.length - 1) { +// System.out.print(", "); +// if ((i + 1) % 12 == 0) { +// System.out.println(); +// } +// } +// } +// System.out.println(); +// } +// +// +// /** +// * 将十六进制字节数组转换为十进制整数数组 +// * +// * @param data 字节数组 +// * @return 十进制整数数组 +// */ +// public static int[] convertHexToDecimal(byte[] data) { +// if (data == null) { +// return new int[0]; +// } +// +// int[] decimalArray = new int[data.length]; +// for (int i = 0; i < data.length; i++) { +// // 将字节转换为无符号整数(十进制) +// decimalArray[i] = data[i] & 0xFF; +// } +// +// return decimalArray; +// } +// +// /** +// * 打印十进制数据 +// * +// * @param data 字节数组 +// */ +// public static void printDecimalData(byte[] data) { +// int[] decimalArray = convertHexToDecimal(data); +// +// System.out.println("生成的十进制数据:"); +// for (int i = 0; i < decimalArray.length; i++) { +// System.out.print(decimalArray[i]); +// +// if (i < decimalArray.length - 1) { +// System.out.print(", "); +// if ((i + 1) % 12 == 0) { +// System.out.println(); +// } +// } +// } +// System.out.println(); +// } +// +// public static void buildArr(int[] data,List intData){ +// for (int datum : data) { +// intData.add(datum); +// } +// } +// +// /** +// * 生成固定长度的点阵数据 +// * +// * @param text 要转换的文本 +// * @param fixedLength 固定长度(字节) +// * @return 固定长度的点阵数据 +// */ +// public static byte[] generateFixedBitmapData(String text, int fixedLength) { +// if (text == null || text.isEmpty()) { +// return new byte[fixedLength]; +// } +// +// // 创建80*12像素的图像 +// Font font = new Font("宋体", Font.PLAIN, 12); +// BufferedImage image = createTextImage(text, font, 80, 12); +// +// // 提取点阵数据 +// byte[] rawData = extractBitmapData(image); +//// System.out.println("生成的点阵数据1:"); +//// System.out.println(Arrays.toString(rawData)); +// +// // 调整到固定长度 +// byte[] result = new byte[fixedLength]; +// int copyLength = Math.min(rawData.length, fixedLength); +// System.arraycopy(rawData, 0, result, 0, copyLength); +// // 剩余部分自动初始化为0 +// +// return result; +// } +// +// /** +// * 创建文本图像 +// */ +// private static BufferedImage createTextImage(String text, Font font, int width, int height) { +// // 创建图像 +// BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// Graphics2D g = image.createGraphics(); +// +// // 设置白色背景 +// g.setColor(Color.WHITE); +// g.fillRect(0, 0, width, height); +// +// // 设置黑色文本 +// g.setColor(Color.BLACK); +// g.setFont(font); +// +// // 关闭抗锯齿 +// g.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, +// RenderingHints.VALUE_TEXT_ANTIALIAS_OFF); +// g.setRenderingHint(RenderingHints.KEY_RENDERING, +// RenderingHints.VALUE_RENDER_QUALITY); +// +// // 获取字体度量 +// FontMetrics metrics = g.getFontMetrics(); +// +// // 计算文本绘制位置(居中) +// int textWidth = metrics.stringWidth(text); +//// int x = Math.max(0, (width - textWidth) / 2); // 水平居中 +// // 左对齐 +// int x = 0; +// int y = (height - metrics.getHeight()) / 2 + metrics.getAscent(); // 垂直居中 +// +// // 绘制文本 +// g.drawString(text, x, y); +// +// g.dispose(); +// return image; +// } +// +// /** +// * 提取点阵数据 - 从左到右,从上到下扫描 +// */ +// private static byte[] extractBitmapData(BufferedImage image) { +// int width = image.getWidth(); +// int height = image.getHeight(); +// +// List byteList = new ArrayList<>(); +// int currentByte = 0; +// int bitCount = 0; +// +// // 从上到下,从左到右扫描 +// for (int y = 0; y < height; y++) { +// for (int x = 0; x < width; x++) { +// // 获取像素颜色 +// Color color = new Color(image.getRGB(x, y)); +// +// // 判断是否为黑色(阈值处理) +// int gray = (color.getRed() + color.getGreen() + color.getBlue()) / 3; +// boolean isBlack = gray < 128; +// +// // 高位优先打包 +// currentByte = (currentByte << 1) | (isBlack ? 1 : 0); +// bitCount++; +// +// if (bitCount == 8) { +// byteList.add((byte) currentByte); +// currentByte = 0; +// bitCount = 0; +// } +// } +// } +// +// // 处理最后不满8位的部分 +// if (bitCount > 0) { +// currentByte <<= (8 - bitCount); +// byteList.add((byte) currentByte); +// } +// +// return byteListToArray(byteList); +// } +// +// private static byte[] byteListToArray(List byteList) { +// byte[] result = new byte[byteList.size()]; +// for (int i = 0; i < byteList.size(); i++) { +// result[i] = byteList.get(i); +// } +// return result; +// } +// +// /** +// * 字节数组转图像 +// */ +// public static BufferedImage convertByteArrayToImage(byte[] data, int height, int width) { +// if (data == null || data.length == 0) { +// return new BufferedImage(1, 1, BufferedImage.TYPE_INT_RGB); +// } +// +// // 创建RGB图像 +// BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// +// // 设置白色背景 +// for (int y = 0; y < height; y++) { +// for (int x = 0; x < width; x++) { +// image.setRGB(x, y, Color.WHITE.getRGB()); +// } +// } +// +// // 从左到右,从上到下设置像素点 +// int bitIndex = 0; +// for (int i = 0; i < data.length; i++) { +// int value = data[i] & 0xFF; +// for (int bit = 7; bit >= 0; bit--) { // 高位在前 +// boolean isBlack = ((value >> bit) & 1) == 1; +// if (isBlack) { +// int x = bitIndex % width; +// int y = bitIndex / width; +// if (x < width && y < height) { // 确保不越界 +// image.setRGB(x, y, Color.BLACK.getRGB()); +// } +// } +// bitIndex++; +// +// // 如果已经处理完所有像素,则退出 +// if (bitIndex >= width * height) { +// return image; +// } +// } +// } +// +// return image; +// } +// +// public static String convertToCArrayString(byte[] data, String arrayName) { +// StringBuilder sb = new StringBuilder(); +// sb.append(String.format("// %s: %d 字节\n", arrayName, data.length)); +// sb.append(String.format("const uint8_t %s[] = {\n ", arrayName)); +// +// for (int i = 0; i < data.length; i++) { +// sb.append(String.format("0x%02X", data[i] & 0xFF)); +// +// if (i < data.length - 1) { +// sb.append(", "); +// // 每12个元素换行 +// if ((i + 1) % 12 == 0) { +// sb.append("\n "); +// } +// } +// } +// +// sb.append("\n};"); +// return sb.toString(); +// } +// /** +// * 打印十六进制数据 +// */ +// private static void printHexData(byte[] data) { +// for (int i = 0; i < data.length; i++) { +// int value = data[i] & 0xFF; +// System.out.printf("0x%02X", value); +// +// if (i < data.length - 1) { +// System.out.print(", "); +// if ((i + 1) % 12 == 0) System.out.println(); +// } +// } +// System.out.println(); +// } +// +// /** +// * 生成C文件 +// */ +// public static void generateCFile(byte[] data, String filename, String arrayName) throws IOException { +// try (FileWriter writer = new FileWriter(filename)) { +// writer.write("/**\n"); +// writer.write(" * 80*12点阵显示数据\n"); +// writer.write(" * 数据大小: " + data.length + " 字节\n"); +// writer.write(" * 分辨率: 80*12 像素\n"); +// writer.write(" */\n\n"); +// writer.write("#include \n\n"); +// +// writer.write(String.format("// %s: %d 字节, 80*12 像素\n", arrayName, data.length)); +// writer.write(String.format("const uint8_t %s[] = {\n ", arrayName)); +// writeByteArray(writer, data); +// writer.write("\n};\n"); +// } +// } +// +// private static void writeByteArray(FileWriter writer, byte[] data) throws IOException { +// for (int i = 0; i < data.length; i++) { +// int value = data[i] & 0xFF; +// writer.write(String.format("0x%02X", value)); +// +// if (i < data.length - 1) { +// writer.write(", "); +// if ((i + 1) % 12 == 0) writer.write("\n "); +// } +// } +// } +//} diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImageToCArrayConverter.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImageToCArrayConverter.java new file mode 100644 index 0000000..3e007e5 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ImageToCArrayConverter.java @@ -0,0 +1,310 @@ +//package com.fuyuanshen.equipment.utils.c; +// +//import com.fuyuanshen.common.redis.utils.RedisUtils; +// +//import javax.imageio.ImageIO; +//import java.awt.image.BufferedImage; +//import java.io.*; +//import java.util.ArrayList; +//import java.util.List; +// +//public class ImageToCArrayConverter { +// +///* public static void main(String[] args) { +// try { +// byte[] imageData = convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", 160, 80,25600); +// System.out.println("长度:"+imageData.length); +//// int[] ints =convertHexToDecimal(imageData); +//// System.out.println("Image data: " + Arrays.toString(ints)); +//// writeFile("E:\\workspace\\output.c", imageData,160,80); +//// System.out.println("转换成功!"); +// ArrayList intData = new ArrayList<>(); +// intData.add(2); +// buildArr(convertHexToDecimal(imageData),intData); +// intData.add(0); +// intData.add(0); +// intData.add(0); +// intData.add(0); +// Map map = new HashMap<>(); +// map.put("instruct", intData); +// System.out.println(JSON.toJSONString( map)); +// } catch (IOException e) { +// System.err.println("转换失败: " + e.getMessage()); +// } +// }*/ +// +// public static void main(String[] args) throws IOException { +// +// byte[] largeData = convertImageToCArray("E:\\workspace\\6170_强光_160_80_2.jpg", 160, 80,25600); +// System.out.println("长度:"+largeData.length); +// +// System.out.println("原始数据大小: " + largeData.length + " 字节"); +// +// // 将25600字节的数据分割成512字节的块 +//// List chunks = splitByteArrayIntoChunks(largeData, 512); +//// printChunkInfo(chunks); +//// +//// // 打印前几块的数据示例 +//// System.out.println("\n前3块数据示例(十进制显示):"); +//// for (int i = 0; i < Math.min(50, chunks.size()); i++) { +//// System.out.println("块 " + i + ":"); +//// int[] ints = convertHexToDecimal(chunks.get(i)); +//// System.out.println(Arrays.toString(ints)); +//// } +// +// RedisUtils.setCacheObject("app_logo_data", largeData); +// +// // 示例:获取特定块的数据 +// byte[] specificChunk = getChunk(largeData, 5, 512); // 获取第6块(索引5) +// System.out.println("第6块数据大小: " + specificChunk.length + " 字节"); +// +// // 生成预览图片 +//// BufferedImage image = convertByteArrayToImage(bitmapData, 12, 80); +//// ImageIO.write(image, "PNG", new File("D:\\bitmap_preview.png")); +//// System.out.println("成功生成预览图片: D:\\bitmap_preview.png"); +//// +//// // 生成C文件 +//// generateCFile(bitmapData, "bitmap_data.c", "chinese_text"); +// } +// /** +// * 获取指定块的数据 +// * +// * @param data 原始字节数组 +// * @param chunkIndex 块索引(从0开始) +// * @param chunkSize 每块大小 +// * @return 指定块的字节数组,如果索引无效则返回空数组 +// */ +// public static byte[] getChunk(byte[] data, int chunkIndex, int chunkSize) { +// if (data == null || chunkSize <= 0 || chunkIndex < 0) { +// return new byte[0]; +// } +// +// int start = chunkIndex * chunkSize; +// if (start >= data.length) { +// return new byte[0]; // 索引超出范围 +// } +// +// int end = Math.min(start + chunkSize, data.length); +// int length = end - start; +// +// byte[] chunk = new byte[length]; +// System.arraycopy(data, start, chunk, 0, length); +// return chunk; +// } +// /** +// * 打印分块信息 +// * +// * @param chunks 分块后的字节数组列表 +// */ +// public static void printChunkInfo(List chunks) { +// System.out.println("总共分割成 " + chunks.size() + " 块"); +// for (int i = 0; i < chunks.size(); i++) { +// System.out.println("块 " + i + ": " + chunks.get(i).length + " 字节"); +// } +// } +// /** +// * 将大字节数组分割成固定大小的块 +// * +// * @param data 原始字节数组 +// * @param chunkSize 每块大小(字节数) +// * @return 分割后的字节数组列表 +// */ +// public static List splitByteArrayIntoChunks(byte[] data, int chunkSize) { +// if (data == null || data.length == 0 || chunkSize <= 0) { +// return new ArrayList<>(); +// } +// +// List chunks = new ArrayList<>(); +// int totalChunks = (int) Math.ceil((double) data.length / chunkSize); +// +// for (int i = 0; i < totalChunks; i++) { +// int start = i * chunkSize; +// int end = Math.min(start + chunkSize, data.length); +// int length = end - start; +// +// byte[] chunk = new byte[length]; +// System.arraycopy(data, start, chunk, 0, length); +// chunks.add(chunk); +// } +// +// return chunks; +// } +// +// public static int[] convertHexToDecimal(byte[] data) { +// if (data == null) { +// return new int[0]; +// } +// +// int[] decimalArray = new int[data.length]; +// for (int i = 0; i < data.length; i++) { +// // 将字节转换为无符号整数(十进制) +// decimalArray[i] = data[i] & 0xFF; +// } +// +// return decimalArray; +// } +// +// public static byte[] convertImageToCArray(InputStream inputStream, +// int width, int height, int fixedLength) throws IOException { +// // 读取原始图片 +// BufferedImage originalImage = ImageIO.read(inputStream); +// +// // 调整图片尺寸 +// BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// resizedImage.getGraphics().drawImage( +// originalImage, 0, 0, width, height, null); +// +// // 转换像素数据为RGB565格式(高位在前) +// ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); +// for (int y = 0; y < height; y++) { +// for (int x = 0; x < width; x++) { +// int rgb = resizedImage.getRGB(x, y); +// +// // 提取RGB分量 +// int r = (rgb >> 16) & 0xFF; +// int g = (rgb >> 8) & 0xFF; +// int b = rgb & 0xFF; +// +// // 转换为RGB565(5位红,6位绿,5位蓝) +// int r5 = (r >> 3) & 0x1F; +// int g6 = (g >> 2) & 0x3F; +// int b5 = (b >> 3) & 0x1F; +// +// // 组合为16位值 +// int rgb565 = (r5 << 11) | (g6 << 5) | b5; +// +// // 高位在前(大端序)写入字节 +// byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 +// byteStream.write(rgb565 & 0xFF); // 低字节 +// } +// } +// // 调整到固定长度 +// byte[] rawData = byteStream.toByteArray(); +// byte[] result = new byte[fixedLength]; +// int copyLength = Math.min(rawData.length, fixedLength); +// System.arraycopy(rawData, 0, result, 0, copyLength); +// return result; +// } +// +// public static byte[] convertImageToCArray(String inputPath, +// int width, int height, int fixedLength) throws IOException { +// // 读取原始图片 +// BufferedImage originalImage = ImageIO.read(new File(inputPath)); +// +// // 调整图片尺寸 +// BufferedImage resizedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// resizedImage.getGraphics().drawImage( +// originalImage, 0, 0, width, height, null); +// +// // 转换像素数据为RGB565格式(高位在前) +// ByteArrayOutputStream byteStream = new ByteArrayOutputStream(); +// for (int y = 0; y < height; y++) { +// for (int x = 0; x < width; x++) { +// int rgb = resizedImage.getRGB(x, y); +// +// // 提取RGB分量 +// int r = (rgb >> 16) & 0xFF; +// int g = (rgb >> 8) & 0xFF; +// int b = rgb & 0xFF; +// +// // 转换为RGB565(5位红,6位绿,5位蓝) +// int r5 = (r >> 3) & 0x1F; +// int g6 = (g >> 2) & 0x3F; +// int b5 = (b >> 3) & 0x1F; +// +// // 组合为16位值 +// int rgb565 = (r5 << 11) | (g6 << 5) | b5; +// +// // 高位在前(大端序)写入字节 +// byteStream.write((rgb565 >> 8) & 0xFF); // 高字节 +// byteStream.write(rgb565 & 0xFF); // 低字节 +// } +// } +// // 调整到固定长度 +// byte[] rawData = byteStream.toByteArray(); +// byte[] result = new byte[fixedLength]; +// int copyLength = Math.min(rawData.length, fixedLength); +// System.arraycopy(rawData, 0, result, 0, copyLength); +// return result; +// } +// +// private static void writeFile(String outputPath, byte[] imageData,int width, int height) throws IOException { +// // 生成C语言数组文件 +// try (FileOutputStream fos = new FileOutputStream(outputPath)) { +// // 写入注释行(包含尺寸信息) +// String header = String.format("/* 0X10,0X10,0X00,0X%02X,0X00,0X%02X,0X01,0X1B, */\n", +// width, height); +// fos.write(header.getBytes()); +// +// // 写入数组声明 +// fos.write("const unsigned char gImage_data[] = {\n".getBytes()); +// +// // 写入数据(每行16个字节) +// for (int i = 0; i < imageData.length; i++) { +// // 写入0X前缀 +// fos.write(("0X" + String.format("%02X", imageData[i] & 0xFF)).getBytes()); +// +// // 添加逗号(最后一个除外) +// if (i < imageData.length - 1) { +// fos.write(','); +// } +// +// // 换行和缩进 +// if ((i + 1) % 16 == 0) { +// fos.write('\n'); +// } else { +// fos.write(' '); +// } +// } +// +// // 写入数组结尾 +// fos.write("\n};\n".getBytes()); +// } +// } +// +// /** +// * 将字节字符串转换为字节数组 +// * +// * @param byteString 字节字符串,格式如 "[12, 45, 67, ...]" +// * @return 字节数组 +// */ +// public static byte[] convertStringToByteArray(String byteString) { +// if (byteString == null || byteString.isEmpty()) { +// return new byte[0]; +// } +// +// try { +// // 移除方括号 +// String content = byteString.trim(); +// if (content.startsWith("[")) { +// content = content.substring(1); +// } +// if (content.endsWith("]")) { +// content = content.substring(0, content.length() - 1); +// } +// +// // 按逗号分割 +// String[] byteValues = content.split(","); +// byte[] result = new byte[byteValues.length]; +// +// // 转换每个值 +// for (int i = 0; i < byteValues.length; i++) { +// String value = byteValues[i].trim(); +// // 处理可能的进制前缀 +// if (value.startsWith("0x") || value.startsWith("0X")) { +// // 十六进制 +// result[i] = (byte) Integer.parseInt(value.substring(2), 16); +// } else { +// // 十进制 +// int intValue = Integer.parseInt(value); +// result[i] = (byte) intValue; +// } +// } +// +// return result; +// } catch (NumberFormatException e) { +// System.err.println("解析字节字符串时出错: " + e.getMessage()); +// return new byte[0]; +// } +// } +//} \ No newline at end of file diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java index bde75c7..bd28dc9 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/c/ReliableTextToBitmap.java @@ -7,6 +7,7 @@ import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; /** @@ -23,6 +24,11 @@ public class ReliableTextToBitmap { String name = "12李34四56"; byte[] unitBytes = textToBitmapBytes(unit); + for (int i = 0; i < unitBytes.length; i++) { + //打印byte转十进制 + System.out.printf("0x%02X", unitBytes[i]); + } +// System.out.println("单元数据: "+Arrays.toString(unitBytes)); byte[] deptBytes = textToBitmapBytes(department); byte[] nameBytes = textToBitmapBytes(name); diff --git a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GetAddressFromLatUtil.java b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GetAddressFromLatUtil.java index 9b07c6a..2744977 100644 --- a/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GetAddressFromLatUtil.java +++ b/fys-modules/fys-equipment/src/main/java/com/fuyuanshen/equipment/utils/map/GetAddressFromLatUtil.java @@ -17,13 +17,13 @@ public class GetAddressFromLatUtil { public static void main(String[] args) { - double[] doubles = LngLonUtil.gps84_To_Gcj02(22.557395054991183, 113.98008942433216); + double[] doubles = LngLonUtil.gps84_To_Gcj02(22.6826096, 113.986969); System.out.println(doubles[0]); System.out.println(doubles[1]); // lat 31.2990170 纬度 39.909 116.40,39.92 113.39039,23.131798 113.97556991,22.67075292 // log 121.3466440 经度 116.39742 113.9751543,22.5603342 - String add = GetAddressFromLatUtil.getAdd("113.98008942433216", "22.557395054991183"); + String add = GetAddressFromLatUtil.getAdd(String.valueOf(doubles[1]), String.valueOf(doubles[0])); logger.info(add); // System.out.println(System.currentTimeMillis()); diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceLogMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceLogMapper.xml new file mode 100644 index 0000000..d4c99d6 --- /dev/null +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceLogMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml index e54ae78..8af7215 100644 --- a/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml +++ b/fys-modules/fys-equipment/src/main/resources/mapper/equipment/DeviceMapper.xml @@ -148,7 +148,7 @@ dt.type_name, dt.communication_mode, d.bluetooth_name, - d.binding_time + c.binding_time from device d inner join device_type dt on d.device_type = dt.id inner join app_device_bind_record c on d.id = c.device_id diff --git a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/receiver/ReceiverMessageHandler.java b/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/receiver/ReceiverMessageHandler.java deleted file mode 100644 index c9df7ce..0000000 --- a/fys-modules/fys-system/src/main/java/com/fuyuanshen/system/mqtt/receiver/ReceiverMessageHandler.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.fuyuanshen.system.mqtt.receiver; - -import lombok.extern.slf4j.Slf4j; -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; - -/** - * @Author: HarryLin - * @Date: 2025/3/20 15:24 - * @Company: 北京红山信息科技研究院有限公司 - * @Email: linyun@***.com.cn - **/ -@Service -@Slf4j -public class ReceiverMessageHandler implements MessageHandler { - @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); - - } -} \ No newline at end of file