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 ec4c8e420c75498ff1bf0ba7c3a50dd54d9b188a..8d0f2c88d6bc94055d2aaf4141f64256fe471b7c 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 19c716ef60767d4ec93d3c2094f93ee5b8282245..b8bb7194f483bec6a23910d15efb595a25b6b406 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 75f6a242e9b7b9616f6fb8da3ca0a5b7d8761467..5af1156d7ccae3bb04fe6be0df963a1cf7110da3 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 ee88a3a8e4181de811783f768e13d7d80dc761a2..6218893e7a9e127259e5201ba8f0c514b7baa7a7 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 91b577b7aa490834f938ca8a015ecce57456c58d..867e40d1f9e1df3e4e54b14d4ae373d48f411992 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 775de4e3aa61206564ba75d1b1c37fd073595b91..76e72923de83e32967e167328da783140144eb9e 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 7be647acee97c9c05d91b600f0fc342dc6041a63..d2f24050fd68e22458b8f8c1ac799928ba296aec 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 cceed278405971197bc1cd4ac390c254c22ea999..0000000000000000000000000000000000000000 --- 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 c5df151ce07d5a9f3cabfd3baa07d094176acad7..c2e79f34f192ce847f2c17d0100c7a299a897894 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 8a02bfadea678ac679f9c92a008229c36b7e0605..69f6672112484d67d42d8e4d7d6eb01fb14e360c 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 ade9205bf00660d6bc399d018cd2c3b264c7f3e6..0000000000000000000000000000000000000000 --- 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 51c08aeec22f6c722e416b1ca2499468719c16b2..0000000000000000000000000000000000000000 --- 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 1c7bd6a31117548a0695cc4317ee32c8b17e9f7d..0000000000000000000000000000000000000000 --- 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 3407409a3d8c73bbe35c345728cc498ee19e0d8a..6b47a451f9c4b9806cc28b6044c016bd9f7a9b0a 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 d39f90bafb94bb43d83561e0d8e728a767afaf9d..0fb157eb01346d46a950d3071d080a63d582dcec 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 ac325ead627be53d5416f2b46289201860e76e1b..0000000000000000000000000000000000000000 --- 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 3c2b70407c3c473169f573a493590154e59550cd..9acb9b3ab14d28b67db980339daa4697be4157cb 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 0862f8b716ddf367d84c80eaa8731e4e12a4d03f..181a3cfa9b04e55031eb7924f0d7274d3afa7e11 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 4e2694bb70f90cc4d6096e183c0257e8a9adb15b..02ff1d38f00b6ea34a6b3c3359ec72beec8c1a57 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 2d4fe614e0d8742d040d27e1217e22f70ddc6c78..fcf13dbd63c8d733c6e034e09cc5c6d799db8da7 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 4204471ed9dd6f4ed917f5e1da5d6d59f4ee7f7a..f92791d79b4b498692d7754479205ae23dd8645f 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 278f57197f9aae6d8ff18b9c36df35539e96254b..ad17848fb2302b3ff44b8cbd445bb2f18cb5638c 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