From ce3d4f50bb18f8226710e4046ba4f0f7b8d2ecad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A5=88=E7=A7=91=E6=96=AF=EF=BC=88NexIoT=EF=BC=89?= <16120872+nexiot@user.noreply.gitee.com> Date: Tue, 23 Sep 2025 11:04:19 +0800 Subject: [PATCH] =?UTF-8?q?news=EF=BC=9A=E5=90=88=E5=B9=B62.0=E5=95=86?= =?UTF-8?q?=E4=B8=9A=E7=89=88=E4=BB=A3=E7=A0=81=EF=BC=9Aframework=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=20=E7=89=88=E6=9C=AC=E6=9B=B4=E6=96=B0=E6=B1=87?= =?UTF-8?q?=E6=80=BB=20(2025-08-10=20=E8=87=B3=202025-09-23)=20=E6=A0=B8?= =?UTF-8?q?=E5=BF=83=E5=8A=9F=E8=83=BD=E4=BC=98=E5=8C=96:=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9EUDP=E6=A8=A1=E5=9D=97=E5=B9=B6=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E5=BC=80=E5=90=AF=EF=BC=8CTCP=E5=9F=BA=E7=A1=80=E4=B8=8A?= =?UTF-8?q?=E5=A2=9E=E5=8A=A0UDP=E9=80=82=E9=85=8D=20-=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E7=BD=91=E5=85=B3=E7=BB=91=E5=AE=9A=E5=A4=9A=E4=BA=A7?= =?UTF-8?q?=E5=93=81=E5=AD=90=E8=AE=BE=E5=A4=87=EF=BC=8C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E8=AE=BE=E5=A4=87=E9=87=8D=E8=BF=9E=E6=9C=BA=E5=88=B6=20-=20?= =?UTF-8?q?=E6=96=B0=E5=A2=9EEzviz=EF=BC=88=E8=90=A4=E7=9F=B3=EF=BC=89?= =?UTF-8?q?=E6=8E=A5=E5=85=A5=E6=A8=A1=E5=9D=97=EF=BC=8C=E8=B0=83=E6=95=B4?= =?UTF-8?q?imoulife=E6=94=AF=E6=8C=81=E8=87=AA=E6=9C=89=E5=B9=B3=E5=8F=B0?= =?UTF-8?q?=E8=B4=A6=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 性能与稳定性: - 优化设备影子热数据存储,增加强制刷盘功能 - 产品列表及MQTT查询增加多级缓存策略 - 强化TCP安全机制,新增异常攻击封禁策略 功能完善: - 集成rulego可视化规则引擎基础框架 - Web-IDE新增20+ modbus/hex封装方法 - 优化乐城播放器界面及TCP连接信息展示 问题修复: - 解决系统间强依赖及注入相关问题 - 修复时间格式化、设备创建时间显示问题 - 完善日志处理及应用推送相关异常 其他改进: - 重构TCP粘包处理,删除冗余代码 - 增加Docker部署配置 - 细化权限控制策略 --- .../common/constant/IoTConstant.java | 129 +++++++- .../common/event/EventProcessorFactory.java | 41 +-- .../universal/common/event/EventTopics.java | 15 + .../common/event/RedisEventPublisher.java | 2 +- .../common/event/RedisEventSubscriber.java | 5 +- .../common/exception/IoTErrorCode.java | 2 +- .../cn-universal-core/pom.xml | 12 - .../core/engine/functions/IotRedisUtil.java | 303 ------------------ .../protocol/magic/ProtocolCodecMagic.java | 49 ++- .../core/service/AbstractCodecService.java | 10 +- .../java/cn/universal/core/service/Codec.java | 48 --- .../core/service/CodecServiceFactory.java | 61 ---- .../cn/universal/core/service/ICodec.java | 38 --- .../universal/core/service/ICodecService.java | 9 + .../core/service/IoTDownlFactory.java | 3 +- .../core/service/UniversalCodec.java | 32 -- .../cn-universal-oss/pom.xml | 5 + .../java/cn/universal/ossm/entity/SysOss.java | 2 +- .../ossm/oss/enumd/CloudServiceEnumd.java | 3 +- .../ossm/oss/factory/OssFactory.java | 17 +- .../ossm/service/impl/SysOssServiceImpl.java | 15 +- cn-universal-framework/pom.xml | 1 + 22 files changed, 250 insertions(+), 552 deletions(-) delete mode 100644 cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/engine/functions/IotRedisUtil.java delete mode 100644 cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/Codec.java delete mode 100644 cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/CodecServiceFactory.java delete mode 100644 cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodec.java delete mode 100644 cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/UniversalCodec.java diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/constant/IoTConstant.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/constant/IoTConstant.java index ec4c8e4..8d0f2c8 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/constant/IoTConstant.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/constant/IoTConstant.java @@ -23,7 +23,8 @@ import java.util.stream.Stream; /** IoT常量 */ public interface IoTConstant { - + /*发送直通第三方平台*/ + String DOWN_TO_THIRD_PLATFORM = "downToThirdPlatform"; String CURRENT_INSTANCE_ID = "instanceId"; public final String CERT_DEFAULT_KEY = "default-tcp"; public final String HTTP_UP_BLACK_LIST = "httpUpBlackList"; @@ -126,6 +127,7 @@ public interface IoTConstant { public static final String TRACE_ID = "traceId"; + static final String defaultMetadata = """ {"tags":[],"events":[{"id":"online","name":"上线","valueType":{"type":"string"}},{"id":"offline","name":"下线","valueType":{"type":"string"}}],"functions":[],"properties":[]}"""; @@ -134,9 +136,11 @@ public interface IoTConstant { ctaiot, ezviz, onenet, - lechen, + imoulife, tcp, - sniTcp + udp, + mqtt, + http } /** 非设备真实上报事件 */ @@ -203,8 +207,109 @@ public interface IoTConstant { } } - /** 下行指令 */ + /** 下行指令 - 重新设计为更通俗易懂的指令 */ enum DownCmd { + // 设备管理指令 + DEVICE_ADD("设备添加"), + DEVICE_DELETE("设备删除"), + DEVICE_UPDATE("设备更新"), + DEVICE_INFO("设备信息查询"), + DEVICE_STATUS("设备状态查询"), + DEVICE_ONLINE_CHECK("设备在线检查"), + + // 摄像头控制指令 + CAMERA_TURN("摄像头转动"), + CAMERA_PTZ_CONTROL("云台控制"), + CAMERA_SNAPSHOT("摄像头截图"), + CAMERA_LIVE_STREAM("摄像头直播"), + CAMERA_PLAYBACK("摄像头回放"), + CAMERA_RECORD_START("开始录像"), + CAMERA_RECORD_STOP("停止录像"), + CAMERA_FLIP_SET("画面翻转设置"), + + // 存储相关物模型函数 + STORAGE_LOCAL_STREAM_SET_FUNC("storageLocalStreamSet"), + STORAGE_LOCAL_STREAM_QUERY_FUNC("storageLocalStreamQuery"), + STORAGE_LOCAL_PLAN_SET_FUNC("storageLocalPlanSet"), + STORAGE_LOCAL_PLAN_QUERY_FUNC("storageLocalPlanQuery"), + STORAGE_CLOUD_RECORDS_QUERY_FUNC("storageCloudRecordsQuery"), + STORAGE_CLOUD_UNUSED_LIST_FUNC("storageCloudUnusedList"), + STORAGE_CLOUD_CALL_COUNT_QUERY_FUNC("storageCloudCallCountQuery"), + STORAGE_CLOUD_SERVICE_SET_FUNC("storageCloudServiceSet"), + STORAGE_CLOUD_LIST_QUERY_FUNC("storageCloudListQuery"), + STORAGE_CLOUD_UNBIND_FUNC("storageCloudUnbind"), + STORAGE_CLOUD_OPEN_FUNC("storageCloudOpen"), + STORAGE_FREE_CLOUD_SET_FUNC("storageFreeCloudSet"), + STORAGE_SDCARD_FORMAT_FUNC("storageSdcardFormat"), + STORAGE_SDCARD_INFO_GET_FUNC("storageSdcardInfoGet"), + STORAGE_SDCARD_STATUS_GET_FUNC("storageSdcardStatusGet"), + STORAGE_CLOUD_VIDEO_COUNT_QUERY_FUNC("storageCloudVideoCountQuery"), + STORAGE_LOCAL_VIDEO_COUNT_QUERY_FUNC("storageLocalVideoCountQuery"), + VIDEO_DOWNLOAD_FUNC("videoDownload"), + + // 设备相关物模型函数 + DEVICE_SOUND_VOLUME_GET_FUNC("deviceSoundVolumeGet"), + DEVICE_SOUND_VOLUME_SET_FUNC("deviceSoundVolumeSet"), + DEVICE_CAMERA_STATUS_GET_FUNC("deviceCameraStatusGet"), + DEVICE_WIFI_SET_FUNC("deviceWifiSet"), + DEVICE_WIFI_SCAN_FUNC("deviceWifiScan"), + DEVICE_UPGRADE_FUNC("deviceUpgrade"), + DEVICE_VERSION_QUERY_FUNC("deviceVersionQuery"), + DEVICE_CLOUD_INFO_GET_FUNC("deviceCloudInfoGet"), + DEVICE_ENABLE_SET_FUNC("deviceEnableSet"), + DEVICE_RESTART_FUNC("deviceRestart"), + + // 报警相关物模型函数 + ALARM_MESSAGE_QUERY_FUNC("alarmMessageQuery"), + + // 存储管理指令 + STORAGE_INFO("存储信息查询"), + STORAGE_FORMAT("存储格式化"), + STORAGE_CLOUD_ENABLE("云存储开启"), + STORAGE_CLOUD_DISABLE("云存储关闭"), + STORAGE_LOCAL_ENABLE("本地存储开启"), + STORAGE_LOCAL_DISABLE("本地存储关闭"), + STORAGE_LOCAL_STREAM_SET("设置本地录像视频流"), + STORAGE_LOCAL_STREAM_QUERY("查询本地录像视频流"), + STORAGE_LOCAL_PLAN_SET("设置本地录像计划"), + STORAGE_LOCAL_PLAN_QUERY("查询本地录像计划"), + STORAGE_CLOUD_RECORDS_QUERY("查询云录像片段"), + STORAGE_CLOUD_UNUSED_LIST("获取未启用的云存储服务"), + STORAGE_CLOUD_CALL_COUNT_QUERY("查询云存储开通接口剩余调用次数"), + STORAGE_CLOUD_SERVICE_SET("设置云存储服务开关"), + STORAGE_CLOUD_LIST_QUERY("查询设备云存储服务"), + STORAGE_CLOUD_UNBIND("解绑设备云存储"), + STORAGE_CLOUD_OPEN("开通设备云存储"), + STORAGE_FREE_CLOUD_SET("设置免费云存储服务"), + STORAGE_SDCARD_FORMAT("格式化SD卡"), + STORAGE_SDCARD_INFO_GET("获取SD卡信息"), + STORAGE_SDCARD_STATUS_GET("获取SD卡状态"), + STORAGE_CLOUD_VIDEO_COUNT_QUERY("查询云录像数量"), + STORAGE_LOCAL_VIDEO_COUNT_QUERY("查询本地录像数量"), + VIDEO_DOWNLOAD("下载录像"), + + // 设备设置指令 + DEVICE_RESTART("设备重启"), + DEVICE_UPGRADE("设备升级"), + DEVICE_WIFI_SET("WiFi设置"), + DEVICE_WIFI_SCAN("WiFi扫描"), + DEVICE_SOUND_VOLUME_GET("获取设备音量"), + DEVICE_SOUND_VOLUME_SET("设置设备音量"), + DEVICE_CAMERA_STATUS_GET("获取摄像头状态"), + DEVICE_VERSION_QUERY("查询设备版本信息"), + DEVICE_CLOUD_INFO_GET("获取设备云存储信息"), + DEVICE_ENABLE_SET("设置设备使能开关"), + + // 报警管理指令 + ALARM_MESSAGE_QUERY("查询报警消息"), + + // 产品管理指令 + PRODUCT_ADD("产品添加"), + PRODUCT_UPDATE("产品更新"), + PRODUCT_DELETE("产品删除"), + PRODUCT_PUBLISH("产品发布"), + + // 兼容旧版本指令(保留) DEV_ADD, DEV_ADDS, DEV_FUNCTION, @@ -214,7 +319,6 @@ public interface IoTConstant { MANUAL_CAPTURE, DEV_CONTROLLING, DEV_MONITOR_PLAY, - DEV_ELECTRIC_QUANTITY, DEV_DOOR_KEYS, DEV_OPENDOOR_RECORD, @@ -264,7 +368,6 @@ public interface IoTConstant { FRAME_REVERSE_STATUS, SOUND_VOLUME_SIZE_GET, CAMERA_STATUS, - CAMERA_SNAPSHOT, CONTROL_DEVICE_WIFI, WIFI_AROUND, UPGRADE_DEVICE, @@ -277,7 +380,15 @@ public interface IoTConstant { ALARM_MESSAGE, DEV_MONITOR_CHECK_ONLINE; - private DownCmd() {} + private String description; + + DownCmd() { + this.description = super.toString().toLowerCase(); + } + + DownCmd(String description) { + this.description = description; + } @JsonCreator public static DownCmd find(String value) { @@ -291,6 +402,10 @@ public interface IoTConstant { public String getValue() { return super.toString().toLowerCase(); } + + public String getDescription() { + return description; + } } /** 设备订阅 */ diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventProcessorFactory.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventProcessorFactory.java index 19c716e..b8bb719 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventProcessorFactory.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventProcessorFactory.java @@ -1,8 +1,11 @@ package cn.universal.common.event; +import cn.hutool.core.map.MapUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.universal.common.event.processer.FenceEventProcessor; import cn.universal.common.event.processer.ProductConfigProcessor; import cn.universal.common.event.processer.TcpDownProcessor; +import java.util.Map; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -26,10 +29,6 @@ public class EventProcessorFactory { @Autowired(required = false) private TcpDownProcessor tcpDownProcessor; - // 产品配置处理器 - @Autowired(required = false) - private ProductConfigProcessor productConfigProcessor; - /** 处理电子围栏事件 */ public void handleFenceEvent(EventMessage message) { if (fenceEventProcessor != null) { @@ -58,27 +57,33 @@ public class EventProcessorFactory { /** 处理产品配置更新事件 */ public void handleProductConfigUpdated(EventMessage message) { - if (productConfigProcessor != null) { - try { - productConfigProcessor.handleProductConfigUpdated(message); - } catch (Exception e) { - log.error("[事件处理器] 产品配置更新处理失败", e); + try { + Map beans = + SpringUtil.getBeansOfType(ProductConfigProcessor.class); + if (MapUtil.isNotEmpty(beans)) { + beans.forEach( + (k, v) -> { + v.handleProductConfigUpdated(message); + }); } - } else { - log.warn("[事件处理器] ProductConfigProcessor未找到,跳过产品配置更新处理"); + } catch (Exception e) { + log.error("[事件处理器] 产品配置更新处理失败", e); } } /** 处理产品配置更新事件 */ public void handleProtocolUpdated(EventMessage message) { - if (productConfigProcessor != null) { - try { - productConfigProcessor.handleProtocolUpdated(message); - } catch (Exception e) { - log.error("[事件处理器] 产品协议更新处理失败", e); + try { + Map beans = + SpringUtil.getBeansOfType(ProductConfigProcessor.class); + if (MapUtil.isNotEmpty(beans)) { + beans.forEach( + (k, v) -> { + v.handleProductConfigUpdated(message); + }); } - } else { - log.warn("[事件处理器] ProductConfigProcessor未找到,产品协议更新处理失败"); + } catch (Exception e) { + log.error("[事件处理器] 产品协议更新处理失败", e); } } } diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventTopics.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventTopics.java index 75f6a24..5af1156 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventTopics.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/EventTopics.java @@ -35,6 +35,11 @@ public class EventTopics { /** TCP下行指令事件(模式匹配) 用于处理TCP下行指令 */ public static final String TCP_DOWN = "tcp:down:*"; + // ==================== UDP相关事件 ==================== + + /** UDP下行指令事件(模式匹配) 用于处理UDP下行指令 */ + public static final String UDP_DOWN = "udp:down:*"; + // ==================== 产品配置相关事件 ==================== /** 产品配置更新事件 用于通知产品配置变更 */ @@ -56,4 +61,14 @@ public class EventTopics { public static String getTcpDownTopic(String instanceId) { return "tcp:down:" + instanceId; } + + /** + * 获取UDP下行指令主题(带实例ID) + * + * @param instanceId 实例ID + * @return 完整的UDP下行指令主题 + */ + public static String getUdpDownTopic(String instanceId) { + return "udp:down:" + instanceId; + } } diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventPublisher.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventPublisher.java index ee88a3a..6218893 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventPublisher.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventPublisher.java @@ -42,7 +42,7 @@ public class RedisEventPublisher implements EventPublisher { String message = JSONUtil.toJsonStr(eventMessage); redisTemplate.convertAndSend(topic, message); - log.debug("[Redis事件发布] 发布事件到主题: {}, 消息: {}", topic, message); + log.info("[Redis事件发布] 发布事件到主题: {}, 消息: {}", topic, message); } catch (Exception e) { log.error("[Redis事件发布] 发布事件失败: topic={}, event={}", topic, event, e); } diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventSubscriber.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventSubscriber.java index 91b577b..867e40d 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventSubscriber.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/event/RedisEventSubscriber.java @@ -154,7 +154,10 @@ public class RedisEventSubscriber { private boolean isOwnMessage(EventMessage message) { try { String nodeId = message.getNodeId(); - return instanceIdProvider.getInstanceId().equals(nodeId); + String instanceId = instanceIdProvider.getInstanceId(); + final boolean b = instanceId.equalsIgnoreCase(nodeId); + log.info("判断是否自己的消息={},nodeId={}, instanceId={}", b, nodeId, instanceId); + return b; } catch (Exception e) { return false; } diff --git a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/exception/IoTErrorCode.java b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/exception/IoTErrorCode.java index 775de4e..76e7292 100644 --- a/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/exception/IoTErrorCode.java +++ b/cn-universal-framework/cn-universal-common/src/main/java/cn/universal/common/exception/IoTErrorCode.java @@ -59,7 +59,7 @@ public enum IoTErrorCode { APPLICATION_NOT_FOR_YOU(801, "应用没有操作权限!"), /** 产品 */ - PRODUCT_NOT_FOR_YOU(901, "您没有权限操作此产品!"), + PRODUCT_NOT_FOR_YOU(901, "无产品权限"), PRODUCT_NOT_EXIST(902, "产品不存在"); private Integer code; diff --git a/cn-universal-framework/cn-universal-core/pom.xml b/cn-universal-framework/cn-universal-core/pom.xml index 7be647a..d2f2405 100644 --- a/cn-universal-framework/cn-universal-core/pom.xml +++ b/cn-universal-framework/cn-universal-core/pom.xml @@ -46,12 +46,6 @@ io.lettuce lettuce-core - - - - org.springframework.boot - spring-boot-starter-data-redis - org.graalvm.js @@ -70,12 +64,6 @@ spring-security-crypto - - - - - - org.projectlombok lombok diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/engine/functions/IotRedisUtil.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/engine/functions/IotRedisUtil.java deleted file mode 100644 index cceed27..0000000 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/engine/functions/IotRedisUtil.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * - * Copyright (c) 2025, IoT-Universal. All Rights Reserved. - * - * @Description: 本文件由 Aleo 开发并拥有版权,未经授权严禁擅自商用、复制或传播。 - * @Author: Aleo - * @Email: wo8335224@gmail.com - * @Wechat: outlookFil - * - * - */ - -package cn.universal.core.engine.functions; - -import cn.universal.core.engine.annotation.Comment; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.concurrent.TimeUnit; -import lombok.extern.slf4j.Slf4j; -import org.springframework.data.geo.Point; -import org.springframework.data.redis.RedisConnectionFailureException; -import org.springframework.data.redis.RedisSystemException; -import org.springframework.data.redis.connection.RedisGeoCommands; -import org.springframework.data.redis.core.RedisCallback; -import org.springframework.data.redis.core.StringRedisTemplate; -import org.springframework.data.redis.core.script.DefaultRedisScript; -import org.springframework.data.redis.core.script.RedisScript; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class IotRedisUtil { - - private final StringRedisTemplate redisTemplate; - private static final String DEVICE_PREFIX = "univiot:device:"; - - public IotRedisUtil(StringRedisTemplate redisTemplate) { - this.redisTemplate = redisTemplate; - } - - // ==================== 基础数据结构操作(带过期时间)==================== - @Comment("设置字符串值(带过期时间)") - public void setString(String key, String value, long timeout, String unit) { - try { - redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.valueOf(unit)); - } catch (RedisConnectionFailureException e) { - log.error("Redis连接失败 - Key: {}, Error: {}", key, e.getMessage()); - } catch (RedisSystemException e) { - log.error("Redis系统异常 - Key: {}, Error: {}", key, e.getCause().getMessage()); - } catch (Exception e) { - log.error("设置字符串值异常 - Key: {}, Error: {}", key, e.getMessage()); - } - } - - @Comment("设置Hash字段值(带过期时间)") - public void setHashField(String key, String field, String value, long timeout, String unit) { - try { - redisTemplate.opsForHash().put(key, field, value); - redisTemplate.expire(key, timeout, TimeUnit.valueOf(unit)); - } catch (RedisConnectionFailureException e) { - log.error("Redis连接失败 - Key: {}, Field: {}", key, field); - } catch (Exception e) { - log.error("设置Hash字段异常 - Key: {}, Field: {}, Error: {}", key, field, e.getMessage()); - } - } - - @Comment("从左侧插入List(带过期时间)") - public Long leftPush(String key, String value, long timeout, String unit) { - try { - Long result = redisTemplate.opsForList().leftPush(key, value); - redisTemplate.expire(key, timeout, TimeUnit.valueOf(unit)); - return result; - } catch (RedisConnectionFailureException e) { - log.error("Redis连接失败 - Key: {}", key); - return 0L; - } catch (Exception e) { - log.error("List左插入异常 - Key: {}, Error: {}", key, e.getMessage()); - return 0L; - } - } - - @Comment("添加Set成员(带过期时间)") - public Long addToSet(String key, String value, long timeout, String unit) { - try { - Long result = redisTemplate.opsForSet().add(key, value); - redisTemplate.expire(key, timeout, TimeUnit.valueOf(unit)); - return result; - } catch (RedisConnectionFailureException e) { - log.error("Redis连接失败 - Key: {}", key); - return 0L; - } catch (Exception e) { - log.error("Set添加成员异常 - Key: {}, Error: {}", key, e.getMessage()); - return 0L; - } - } - - @Comment("添加ZSet成员(带过期时间)") - public Boolean addToZSet(String key, String value, double score, long timeout, String unit) { - try { - Boolean result = redisTemplate.opsForZSet().add(key, value, score); - redisTemplate.expire(key, timeout, TimeUnit.valueOf(unit)); - return result; - } catch (RedisConnectionFailureException e) { - log.error("Redis连接失败 - Key: {}", key); - return false; - } catch (Exception e) { - log.error("ZSet添加成员异常 - Key: {}, Error: {}", key, e.getMessage()); - return false; - } - } - - // ==================== 物联网场景专用方法 ==================== - @Comment("更新设备状态(自动续期)") - public void updateDeviceStatus( - String deviceId, String field, String value, long timeout, String unit) { - String key = DEVICE_PREFIX + "status:" + deviceId; - try { - redisTemplate.opsForHash().put(key, field, value); - redisTemplate.expire(key, timeout, TimeUnit.valueOf(unit)); - } catch (RedisConnectionFailureException e) { - log.error("设备状态更新失败 - Device: {}, Field: {}", deviceId, field); - } catch (Exception e) { - log.error("更新设备状态异常 - Device: {}, Field: {}, Error: {}", deviceId, field, e.getMessage()); - } - } - - @Comment("获取设备状态") - public Map getDeviceStatus(String deviceId) { - String key = DEVICE_PREFIX + "status:" + deviceId; - try { - Map rawMap = redisTemplate.opsForHash().entries(key); - return convertToStringMap(rawMap); - } catch (RedisConnectionFailureException e) { - log.error("获取设备状态失败 - Device: {}", deviceId); - return Collections.emptyMap(); - } catch (Exception e) { - log.error("获取设备状态异常 - Device: {}, Error: {}", deviceId, e.getMessage()); - return Collections.emptyMap(); - } - } - - @Comment("推送设备指令到队列(带过期时间)") - public void pushDeviceCommand( - String deviceId, String commandType, String params, long timeout, String unit) { - String key = DEVICE_PREFIX + "cmd:" + deviceId; - try { - String command = - String.format( - "{\"type\":\"%s\",\"params\":%s,\"timestamp\":%d}", - commandType, params, System.currentTimeMillis()); - - // 使用管道操作确保原子性 - redisTemplate.executePipelined( - (RedisCallback) - connection -> { - connection.rPush(key.getBytes(), command.getBytes()); - connection.expire(key.getBytes(), TimeUnit.valueOf(unit).toSeconds(timeout)); - return null; - }); - } catch (RedisConnectionFailureException e) { - log.error("指令推送失败 - Device: {}, Command: {}", deviceId, commandType); - } catch (Exception e) { - log.error( - "指令推送异常 - Device: {}, Command: {}, Error: {}", deviceId, commandType, e.getMessage()); - } - } - - @Comment("获取并移除下一个指令") - public String popNextCommand(String deviceId) { - String key = DEVICE_PREFIX + "cmd:" + deviceId; - try { - return redisTemplate.opsForList().leftPop(key); - } catch (RedisConnectionFailureException e) { - log.error("获取指令失败 - Device: {}", deviceId); - return null; - } catch (Exception e) { - log.error("获取指令异常 - Device: {}, Error: {}", deviceId, e.getMessage()); - return null; - } - } - - @Comment("记录设备位置") - public void recordDeviceLocation(String deviceId, double lng, double lat) { - try { - redisTemplate - .opsForGeo() - .add( - DEVICE_PREFIX + "geo:devices", - new RedisGeoCommands.GeoLocation<>(deviceId, new Point(lng, lat))); - } catch (RedisConnectionFailureException e) { - log.error("位置记录失败 - Device: {}", deviceId); - } catch (Exception e) { - log.error("位置记录异常 - Device: {}, Error: {}", deviceId, e.getMessage()); - } - } - - @Comment("记录设备事件") - public void recordDeviceEvent(String deviceId, String eventType, Map eventData) { - String key = DEVICE_PREFIX + "events:" + deviceId; - try { - Map fields = new HashMap<>(); - fields.put("eventType", eventType); - fields.put("timestamp", String.valueOf(System.currentTimeMillis())); - fields.putAll(eventData); - redisTemplate.opsForStream().add(key, fields); - } catch (RedisConnectionFailureException e) { - log.error("事件记录失败 - Device: {}, Event: {}", deviceId, eventType); - logToLocalStorage(eventData); // 降级到本地存储 - } catch (Exception e) { - log.error("事件记录异常 - Device: {}, Event: {}, Error: {}", deviceId, eventType, e.getMessage()); - logToLocalStorage(eventData); // 降级到本地存储 - } - } - - @Comment("缓存设备数据并记录历史") - public void cacheDeviceData( - String deviceId, String dataType, String value, long timeout, String unit) { - String currentKey = DEVICE_PREFIX + "data:current:" + deviceId + ":" + dataType; - try { - // 获取上一次值 - String lastValue = redisTemplate.opsForValue().get(currentKey); - - // 存储历史记录 - if (lastValue != null) { - String historyKey = DEVICE_PREFIX + "data:history:" + deviceId + ":" + dataType; - redisTemplate.executePipelined( - (RedisCallback) - connection -> { - connection.zAdd( - historyKey.getBytes(), System.currentTimeMillis(), lastValue.getBytes()); - connection.zRemRange(historyKey.getBytes(), 0, -101); // 保留最近100条 - return null; - }); - } - - // 更新当前值 - redisTemplate.opsForValue().set(currentKey, value, timeout, TimeUnit.valueOf(unit)); - } catch (RedisConnectionFailureException e) { - log.error("数据缓存失败 - Device: {}, Type: {}", deviceId, dataType); - } catch (Exception e) { - log.error("数据缓存异常 - Device: {}, Type: {}, Error: {}", deviceId, dataType, e.getMessage()); - } - } - - // ==================== 分布式锁(设备操作互斥)==================== - private static final String LOCK_SCRIPT = - "if redis.call('setnx', KEYS[1], ARGV[1]) == 1 then " - + " redis.call('pexpire', KEYS[1], ARGV[2]) " - + " return 1 " - + "else return 0 end"; - - private static final String UNLOCK_SCRIPT = - "if redis.call('get', KEYS[1]) == ARGV[1] then " - + " return redis.call('del', KEYS[1]) " - + "else return 0 end"; - - @Comment("获取设备操作锁") - public boolean acquireDeviceLock(String deviceId, String lockId, long expireMs) { - String lockKey = DEVICE_PREFIX + "lock:" + deviceId; - try { - RedisScript script = new DefaultRedisScript<>(LOCK_SCRIPT, Boolean.class); - return Boolean.TRUE.equals( - redisTemplate.execute( - script, Collections.singletonList(lockKey), lockId, String.valueOf(expireMs))); - } catch (RedisConnectionFailureException e) { - log.error("获取锁失败 - Device: {}, LockID: {}", deviceId, lockId); - return false; - } catch (Exception e) { - log.error("获取锁异常 - Device: {}, LockID: {}, Error: {}", deviceId, lockId, e.getMessage()); - return false; - } - } - - @Comment("释放设备锁") - public boolean releaseDeviceLock(String deviceId, String lockId) { - String lockKey = DEVICE_PREFIX + "lock:" + deviceId; - try { - RedisScript script = new DefaultRedisScript<>(UNLOCK_SCRIPT, Long.class); - Long result = redisTemplate.execute(script, Collections.singletonList(lockKey), lockId); - return result != null && result == 1; - } catch (RedisConnectionFailureException e) { - log.error("释放锁失败 - Device: {}, LockID: {}", deviceId, lockId); - return false; - } catch (Exception e) { - log.error("释放锁异常 - Device: {}, LockID: {}, Error: {}", deviceId, lockId, e.getMessage()); - return false; - } - } - - // ==================== 辅助方法 ==================== - private Map convertToStringMap(Map rawMap) { - Map result = new HashMap<>(); - rawMap.forEach((k, v) -> result.put(k.toString(), v.toString())); - return result; - } - - private void logToLocalStorage(Map eventData) { - // 实现本地临时存储逻辑 - log.warn("事件降级到本地存储: {}", eventData); - // 实际项目中可写入本地文件或数据库 - } -} diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/protocol/magic/ProtocolCodecMagic.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/protocol/magic/ProtocolCodecMagic.java index c5df151..c2e79f3 100644 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/protocol/magic/ProtocolCodecMagic.java +++ b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/protocol/magic/ProtocolCodecMagic.java @@ -142,7 +142,7 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper MagicScript script = MagicScript.create(location, null); MagicScriptRuntime compile = script.compile(); // 处理内部实现了哪些方法 - evalMethodCache(definition, compile); + evalMethodCache(provider, compile); log.info("编译耗时:{}", (System.currentTimeMillis() - t) + "ms"); t = System.currentTimeMillis(); if (codecMethod.equals(CodecMethod.decode)) { @@ -159,7 +159,7 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper } } - private void evalMethodCache(ProtocolSupportDefinition definition, MagicScriptRuntime compile) { + private void evalMethodCache(String provider, MagicScriptRuntime compile) { String[] varNames = compile.getVarNames(); if (varNames != null && varNames.length > 0) { Set methods = new HashSet<>(); @@ -170,7 +170,8 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper methods.add(method); } } - methodCache.put(definition.getId(), methods); + methodCache.put(provider, methods); + log.info("evalMethodCache provider={}, methods={}", provider, methods); } } @@ -180,6 +181,9 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper if (!magicDecoderProvider.containsKey(decodeRequest.getDefinition().getProvider())) { // 增加同步锁,防止异常 synchronized (magicDecoderProvider) { + log.info( + "magic decoder not exist,key={}, start reload ", + decodeRequest.getDefinition().getProvider()); load(decodeRequest.getDefinition(), CodecMethod.decode); } } @@ -212,7 +216,12 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper public String encode(ProtocolEncodeRequest encodeRequest) throws CodecException { try { if (!magicEncoderProvider.containsKey(encodeRequest.getDefinition().getProvider())) { - load(encodeRequest.getDefinition(), CodecMethod.encode); + log.info( + "magic encode not exist,key={}, start reload ", + encodeRequest.getDefinition().getProvider()); + synchronized (magicEncoderProvider) { + load(encodeRequest.getDefinition(), CodecMethod.encode); + } } // 如果编解码内部不包含 encode 方法,则直接返回原串 if (methodCache.get(encodeRequest.getDefinition().getId()) == null @@ -227,7 +236,6 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper context.set("payload", encodeRequest.getPayload()); context.set("context", encodeRequest.getContext()); Object execute = magicScript.execute(context); - log.debug("execute={}", execute.getClass()); return str(execute); } catch (Exception e) { String error = ExceptionUtil.getRootCauseMessage(e); @@ -242,10 +250,18 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper @Override public void remove(String provider) { + log.info("开始remove magic provider={}", provider); if (StrUtil.isNotBlank(provider)) { - magicEncoderProvider.remove(provider); - magicDecoderProvider.remove(provider); - magicPreDecoderProvider.remove(provider); + MagicScript encodeV = magicEncoderProvider.remove(provider); + MagicScript decodeV = magicDecoderProvider.remove(provider); + MagicScript preDecodeV = magicPreDecoderProvider.remove(provider); + Set methodV = methodCache.remove(provider); + log.info( + "remove encodeV={},decodeV={},preDecodeV={},methodV={}", + encodeV, + decodeV, + preDecodeV, + methodV); } } @@ -257,7 +273,12 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper try { if (!magicPreDecoderProvider.containsKey( protocolDecodeRequest.getDefinition().getProvider())) { - load(protocolDecodeRequest.getDefinition(), CodecMethod.preDecode); + log.info( + "magic preDecode not exist,key={}, start reload ", + protocolDecodeRequest.getDefinition().getProvider()); + synchronized (magicPreDecoderProvider) { + load(protocolDecodeRequest.getDefinition(), CodecMethod.preDecode); + } } // 如果编解码内部不包含 preDecode 方法,则直接返回原串 if (methodCache.get(protocolDecodeRequest.getDefinition().getId()) == null @@ -307,7 +328,10 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper public String iotToYour(ProtocolEncodeRequest encodeRequest) throws CodecException { try { if (!magicEncoderProvider.containsKey(encodeRequest.getDefinition().getProvider())) { - load(encodeRequest.getDefinition(), CodecMethod.iotToYour); + synchronized (magicEncoderProvider) { + log.info("magic encoder not exist,key={}", encodeRequest.getDefinition().getProvider()); + load(encodeRequest.getDefinition(), CodecMethod.iotToYour); + } } // 如果编解码内部不包含 iotToYour 方法,则使用encode方法 if (methodCache.get(encodeRequest.getDefinition().getId()) == null @@ -339,7 +363,10 @@ public class ProtocolCodecMagic extends ProtocolCodecSupportWrapper public String yourToIot(ProtocolDecodeRequest decodeRequest) throws CodecException { try { if (!magicDecoderProvider.containsKey(decodeRequest.getDefinition().getProvider())) { - load(decodeRequest.getDefinition(), CodecMethod.yourToIot); + log.info("magic decoder not exist,key={}", decodeRequest.getDefinition().getProvider()); + synchronized (magicDecoderProvider) { + load(decodeRequest.getDefinition(), CodecMethod.yourToIot); + } } // 如果编解码内部不包含 yourToIot 方法,则使用decode方法 if (methodCache.get(decodeRequest.getDefinition().getId()) == null diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/AbstractCodecService.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/AbstractCodecService.java index 8a02bfa..69f6672 100644 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/AbstractCodecService.java +++ b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/AbstractCodecService.java @@ -119,6 +119,11 @@ public abstract class AbstractCodecService implements ICodecService { /** 编码 */ @Override public String encode(String productKey, String payload) { + return encode(productKey, payload, null); + } + + @Override + public String encode(String productKey, String payload, Object context) { ProtocolSupportDefinition protocolDef = getProtocolDefinitionWithScriptIfNeeded(productKey, CodecMethod.encode); String result = null; @@ -127,14 +132,15 @@ public abstract class AbstractCodecService implements ICodecService { if (protocolDef != null && protocolDef.supportMethod(CodecMethod.encode)) { ProtocolCodecSupport protocolCodecSupport = getProtocolCodecProvider(protocolDef.getType()); try { - result = protocolCodecSupport.encode(new ProtocolEncodeRequest(protocolDef, payload)); + result = + protocolCodecSupport.encode(new ProtocolEncodeRequest(protocolDef, payload, context)); } catch (CodecException e) { log.error("产品编号={} 原始报文={} 编码报错", productKey, payload, e); } } long t2 = System.currentTimeMillis(); - log.info("产品编号={} 原始报文={} 编码={} 耗时={}ms", productKey, payload, result, (t2 - t1)); + log.info("产品编号={} 原始报文={} 编码={} 耗时={}ms", productKey, payload, result, (t2 - t1)); return result; } diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/Codec.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/Codec.java deleted file mode 100644 index ade9205..0000000 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/Codec.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * - * Copyright (c) 2025, cn-universal. All Rights Reserved. - * - * @Description: 本文件由 Aleo 开发并拥有版权,未经授权严禁擅自商用、复制或传播。 - * @Author: Aleo - * @Email: wo8335224@gmail.com - * @Wechat: outlookFil - * - * - */ -package cn.universal.core.service; - -import cn.universal.core.message.UPRequest; -import java.util.List; - -public interface Codec { - - /** - * 消息解码->物模型 - * - * @param productKey 产品ProductKey - * @param payload 实际入参字符串 - * @param elementType 格式化类型 - * @param 泛型 - * @return 返回解码后的结构化消息 - */ - List decode(String productKey, String payload, Class elementType); - - /** - * 消息解码->物模型 - * - * @param productKey 产品ProductKey - * @param payload 实际入参字符串 - * @return 返回解码后的结构化消息 - */ - default List decode(String productKey, String payload) { - return null; - } - - /** - * 结构化消息->设备识别(二进制、16进制、其他) - * - * @param productKey 产品key - * @param payload 消息的原串 - */ - String encode(String productKey, String payload); -} diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/CodecServiceFactory.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/CodecServiceFactory.java deleted file mode 100644 index 51c08ae..0000000 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/CodecServiceFactory.java +++ /dev/null @@ -1,61 +0,0 @@ -/* - * - * Copyright (c) 2025, IoT-Universal. All Rights Reserved. - * - * @Description: 本文件由 Aleo 开发并拥有版权,未经授权严禁擅自商用、复制或传播。 - * @Author: Aleo - * @Email: wo8335224@gmail.com - * @Wechat: outlookFil - * - * - */ - -package cn.universal.core.service; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -/** - * 编解码服务工厂 - * - *

用于获取不同协议的编解码服务 - * - * @version 1.0 @Author Aleo - * @since 2025/01/20 - */ -@Slf4j -@Component -public class CodecServiceFactory { - - @Autowired private ICodecService defaultCodecService; - - /** - * 获取默认编解码服务 - * - * @return 默认编解码服务 - */ - public ICodecService getDefaultCodecService() { - return defaultCodecService; - } - - /** - * 根据协议类型获取编解码服务 - * - * @param protocolType 协议类型 - * @return 对应的编解码服务 - */ - public ICodecService getCodecService(String protocolType) { - return defaultCodecService; - } - - /** - * 检查是否支持指定协议 - * - * @param protocolType 协议类型 - * @return 是否支持 - */ - public boolean isSupported(String protocolType) { - return true; // 默认服务支持所有协议 - } -} diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodec.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodec.java deleted file mode 100644 index 1c7bd6a..0000000 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodec.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * - * Copyright (c) 2025, IoT-Universal. All Rights Reserved. - * - * @Description: 本文件由 Aleo 开发并拥有版权,未经授权严禁擅自商用、复制或传播。 - * @Author: Aleo - * @Email: wo8335224@gmail.com - * @Wechat: outlookFil - * - * - */ - -package cn.universal.core.service; - -import cn.universal.core.message.UPRequest; - -/** 消息编解码 */ -public interface ICodec { - - default String version() { - return "1.0.0"; - } - - /** 上行消息消息,预编码 */ - default UPRequest preDecode(String productKey, String message) { - return null; - } - - /** 进编码前特殊处理 附加影子 */ - default String beforeEncode(String productKey, String deviceId, String config, String function) { - return function; - } - - /** 下行消息编码 */ - default String spliceDown(String productKey, String payload) { - return null; - } -} diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodecService.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodecService.java index 3407409..6b47a45 100644 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodecService.java +++ b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/ICodecService.java @@ -67,6 +67,15 @@ public interface ICodecService { */ String encode(String productKey, String payload); + /** + * 编码 + * + * @param productKey 产品Key + * @param payload 原始数据 + * @return 编码后的字符串 + */ + String encode(String productKey, String payload, Object context); + /** * 预解码 * diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/IoTDownlFactory.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/IoTDownlFactory.java index d39f90b..0fb157e 100644 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/IoTDownlFactory.java +++ b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/IoTDownlFactory.java @@ -12,6 +12,7 @@ package cn.universal.core.service; +import cn.universal.common.constant.IoTConstant; import cn.universal.common.domain.R; import cn.universal.common.exception.IoTException; import cn.universal.core.protocol.ProtocolModuleInfo; @@ -109,7 +110,7 @@ public class IoTDownlFactory implements ApplicationContextAware { switch (operation) { case "down": return service.doAction(msg); - case "downPro": + case IoTConstant.DOWN_TO_THIRD_PLATFORM: return service.downToThirdPlatform(msg); default: return R.error("不支持的操作: " + operation); diff --git a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/UniversalCodec.java b/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/UniversalCodec.java deleted file mode 100644 index ac325ea..0000000 --- a/cn-universal-framework/cn-universal-core/src/main/java/cn/universal/core/service/UniversalCodec.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.universal.core.service; - -import cn.universal.core.message.UPRequest; - -/** - * @version 1.0 @Author Aleo - * @since 2025/6/26 19:41 - */ -public interface UniversalCodec extends Codec { - - /** - * 预解码,用于TCP表示出哪个ProductKey - * - * @param productKey 产品Key - * @param message 消息原文 - * @return 解码内容 - */ - default UPRequest preDecode(String productKey, String message) { - return null; - } - - /** - * 上行消息转换->转换为阿里云、腾讯云、三方平台 - * - * @param productKey 产品Key - * @param message 消息原文 - * @return 消息原文 - */ - default String messageFormatUP(String productKey, String message) { - return null; - } -} diff --git a/cn-universal-framework/cn-universal-oss/pom.xml b/cn-universal-framework/cn-universal-oss/pom.xml index 3c2b704..9acb9b3 100644 --- a/cn-universal-framework/cn-universal-oss/pom.xml +++ b/cn-universal-framework/cn-universal-oss/pom.xml @@ -32,6 +32,11 @@ + + com.qiniu + qiniu-java-sdk + 7.18.0 + org.springframework spring-web diff --git a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/entity/SysOss.java b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/entity/SysOss.java index 0862f8b..181a3cf 100644 --- a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/entity/SysOss.java +++ b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/entity/SysOss.java @@ -75,6 +75,6 @@ public class SysOss implements Serializable { private String updateBy; /** 服务商 */ - @Column(name = "third") + @Column(name = "service") private String service; } diff --git a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/enumd/CloudServiceEnumd.java b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/enumd/CloudServiceEnumd.java index 4e2694b..02ff1d3 100644 --- a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/enumd/CloudServiceEnumd.java +++ b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/enumd/CloudServiceEnumd.java @@ -13,6 +13,7 @@ package cn.universal.ossm.oss.enumd; import cn.universal.ossm.oss.service.impl.AliyunCloudStorageServiceImpl; +import cn.universal.ossm.oss.service.impl.QiniuCloudStorageServiceImpl; import lombok.AllArgsConstructor; import lombok.Getter; @@ -22,7 +23,7 @@ import lombok.Getter; public enum CloudServiceEnumd { /** 七牛云 */ - // QINIU("qiniu", QiniuCloudStorageServiceImpl.class), + QINIU("qiniu", QiniuCloudStorageServiceImpl.class), /** 阿里云 */ ALIYUN("aliyun", AliyunCloudStorageServiceImpl.class); diff --git a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/factory/OssFactory.java b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/factory/OssFactory.java index 2d4fe61..fcf13db 100644 --- a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/factory/OssFactory.java +++ b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/oss/factory/OssFactory.java @@ -14,6 +14,7 @@ package cn.universal.ossm.oss.factory; import cn.hutool.core.lang.Assert; import cn.universal.common.utils.SpringUtils; +import cn.universal.ossm.oss.constant.CloudConstant; import cn.universal.ossm.oss.enumd.CloudServiceEnumd; import cn.universal.ossm.oss.service.ICloudStorageService; import java.util.Map; @@ -21,18 +22,18 @@ import java.util.concurrent.ConcurrentHashMap; /** 文件上传Factory @Author Lion Li */ public class OssFactory { - - // private static ISysConfigService sysConfigService; - // - // static { - // OssFactory.sysConfigService = SpringUtils.getBean(ISysConfigService.class); - // } +// +// private static ISysConfigService sysConfigService; +// +// static { +// OssFactory.sysConfigService = SpringUtils.getBean(ISysConfigService.class); +// } private static final Map SERVICES = new ConcurrentHashMap<>(); public static ICloudStorageService instance() { - // String type = sysConfigService.selectConfigByKey(CloudConstant.CLOUD_STORAGE_CONFIG_KEY); - return instance("aliyun"); +// String type = sysConfigService.selectConfigByKey(CloudConstant.CLOUD_STORAGE_CONFIG_KEY); + return instance("qiniu"); } public static ICloudStorageService instance(String type) { diff --git a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/service/impl/SysOssServiceImpl.java b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/service/impl/SysOssServiceImpl.java index 4204471..f92791d 100644 --- a/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/service/impl/SysOssServiceImpl.java +++ b/cn-universal-framework/cn-universal-oss/src/main/java/cn/universal/ossm/service/impl/SysOssServiceImpl.java @@ -13,7 +13,6 @@ package cn.universal.ossm.service.impl; import cn.hutool.core.bean.BeanUtil; -import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import cn.universal.common.exception.IoTException; import cn.universal.ossm.entity.SysOss; @@ -39,7 +38,7 @@ public class SysOssServiceImpl implements ISysOssService { @Resource private SysOssMapper sysOssMapper; - @Value("${codec.path:cn-universal}") + @Value("${codec.path:nexiot/}") private String prePath; @Override @@ -58,10 +57,14 @@ public class SysOssServiceImpl implements ISysOssService { if (file.getOriginalFilename() == null) { throw new IoTException("文件名为空!"); } - String originalfileName = - prePath + file.getOriginalFilename().replace(".", RandomUtil.randomString(8) + "."); - String suffix = - StrUtil.sub(originalfileName, originalfileName.lastIndexOf("."), originalfileName.length()); + // 获取文件扩展名 + String originalFilename = file.getOriginalFilename(); + String suffix = ""; + if (originalFilename != null && originalFilename.contains(".")) { + suffix = StrUtil.sub(originalFilename, originalFilename.lastIndexOf("."), originalFilename.length()); + } + // 生成基于 Unix 时间戳的文件名 + String originalfileName = prePath + System.currentTimeMillis() + suffix; ICloudStorageService storage = OssFactory.instance(); UploadResult uploadResult; try { diff --git a/cn-universal-framework/pom.xml b/cn-universal-framework/pom.xml index 278f571..ad17848 100644 --- a/cn-universal-framework/pom.xml +++ b/cn-universal-framework/pom.xml @@ -16,6 +16,7 @@ cn-universal-core cn-universal-exception cn-universal-config + cn-universal-notice cn-universal-oss cn-universal-dm -- Gitee