diff --git a/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java b/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java index 5a15a45..fc4e313 100644 --- a/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java +++ b/src/main/java/com/ycwl/basic/controller/wvp/WvpController.java @@ -2,21 +2,58 @@ package com.ycwl.basic.controller.wvp; import com.ycwl.basic.annotation.IgnoreLogReq; import com.ycwl.basic.annotation.IgnoreToken; +import com.ycwl.basic.device.entity.common.FileObject; +import com.ycwl.basic.device.operator.WvpPassiveStorageOperator; +import com.ycwl.basic.model.wvp.WvpSyncReqVo; +import com.ycwl.basic.service.pc.DeviceService; +import com.ycwl.basic.storage.StorageFactory; +import com.ycwl.basic.storage.adapters.IStorageAdapter; import com.ycwl.basic.utils.ApiResponse; import io.swagger.annotations.Api; +import lombok.extern.slf4j.Slf4j; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import java.util.List; + +@Slf4j @IgnoreToken @RestController @Api(tags = "WVP对接接口") @RequestMapping("/wvp/v1/") public class WvpController { + private final DeviceService deviceService; + + public WvpController(DeviceService deviceService) { + this.deviceService = deviceService; + } + @IgnoreLogReq - @PostMapping("/sync") - public ApiResponse sync() { + @PostMapping("/scenic/{scenicId}/sync") + public ApiResponse> sync(@PathVariable("scenicId") Long scenicId, @RequestBody WvpSyncReqVo reqVo) { + deviceService.updateDevices(scenicId, reqVo); + return ApiResponse.success(WvpPassiveStorageOperator.getTaskListByScenicId(scenicId)); + } + + @PostMapping("/scenic/{scenicId}/{taskId}/uploadUrl") + public String uploadUrl(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) { + IStorageAdapter adapter = StorageFactory.use("assets-ext"); + return adapter.getUrlForUpload(WvpPassiveStorageOperator.getUrlForTask(taskId)); + } + @PostMapping("/scenic/{scenicId}/{taskId}/success") + public ApiResponse success(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId, @RequestBody FileObject fileObject) { + IStorageAdapter adapter = StorageFactory.use("assets-ext"); + fileObject.setUrl(adapter.getUrl(WvpPassiveStorageOperator.getUrlForTask(taskId))); + WvpPassiveStorageOperator.onReceiveResult(taskId, fileObject); + return ApiResponse.success("success"); + } + @PostMapping("/scenic/{scenicId}/{taskId}/fail") + public ApiResponse fail(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) { + WvpPassiveStorageOperator.onReceiveResult(taskId, null); return ApiResponse.success("success"); } } diff --git a/src/main/java/com/ycwl/basic/device/DeviceFactory.java b/src/main/java/com/ycwl/basic/device/DeviceFactory.java index f30aa1f..6f62865 100644 --- a/src/main/java/com/ycwl/basic/device/DeviceFactory.java +++ b/src/main/java/com/ycwl/basic/device/DeviceFactory.java @@ -8,6 +8,7 @@ import com.ycwl.basic.device.operator.AliOssStorageOperator; import com.ycwl.basic.device.operator.IDeviceStorageOperator; import com.ycwl.basic.device.operator.LocalStorageOperator; import com.ycwl.basic.device.operator.WvpActiveStorageOperator; +import com.ycwl.basic.device.operator.WvpPassiveStorageOperator; import com.ycwl.basic.model.pc.device.entity.DeviceConfigEntity; import com.ycwl.basic.model.pc.device.entity.DeviceEntity; @@ -18,6 +19,8 @@ public class DeviceFactory { operator = new AliOssStorageOperator(config.getStoreConfigJson()); } else if (config.getStoreType() == DeviceStoreTypeEnum.WVP_ACTIVE.getType()) { operator = new WvpActiveStorageOperator(config.getStoreConfigJson()); + } else if (config.getStoreType() == DeviceStoreTypeEnum.WVP_PASSIVE.getType()) { + operator = new WvpPassiveStorageOperator(config.getStoreConfigJson()); } else if (config.getStoreType() == DeviceStoreTypeEnum.LOCAL.getType()) { operator = new LocalStorageOperator(config.getStoreConfigJson()); } diff --git a/src/main/java/com/ycwl/basic/device/entity/wvp_passive/WvpPassiveStorageConfig.java b/src/main/java/com/ycwl/basic/device/entity/wvp_passive/WvpPassiveStorageConfig.java new file mode 100644 index 0000000..48f9db6 --- /dev/null +++ b/src/main/java/com/ycwl/basic/device/entity/wvp_passive/WvpPassiveStorageConfig.java @@ -0,0 +1,8 @@ +package com.ycwl.basic.device.entity.wvp_passive; + +import lombok.Data; + +@Data +public class WvpPassiveStorageConfig { + private String deviceNo; +} diff --git a/src/main/java/com/ycwl/basic/device/enums/DeviceStoreTypeEnum.java b/src/main/java/com/ycwl/basic/device/enums/DeviceStoreTypeEnum.java index 369d3ba..59f96bd 100644 --- a/src/main/java/com/ycwl/basic/device/enums/DeviceStoreTypeEnum.java +++ b/src/main/java/com/ycwl/basic/device/enums/DeviceStoreTypeEnum.java @@ -8,6 +8,7 @@ import lombok.Getter; public enum DeviceStoreTypeEnum { ALI_OSS(1, "阿里云OSS"), WVP_ACTIVE(3, "WVP主动模式"), + WVP_PASSIVE(4, "WVP被动模式"), LOCAL(2, "本地文件"); private final int type; diff --git a/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java b/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java new file mode 100644 index 0000000..8be6995 --- /dev/null +++ b/src/main/java/com/ycwl/basic/device/operator/WvpPassiveStorageOperator.java @@ -0,0 +1,110 @@ +package com.ycwl.basic.device.operator; + +import com.alibaba.fastjson.JSON; +import com.ycwl.basic.device.entity.common.FileObject; +import com.ycwl.basic.device.entity.wvp_passive.WvpPassiveStorageConfig; +import com.ycwl.basic.storage.utils.StorageUtil; +import com.ycwl.basic.utils.SnowFlakeUtil; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; + +@Slf4j +public class WvpPassiveStorageOperator extends ADeviceStorageOperator { + public static class Task { + public Long taskId; + public Long scenicId; + public Long deviceId; + public String deviceNo; + public Date startTime; + public Date endTime; + } + + private static List taskList = Collections.synchronizedList(new ArrayList<>()); + private static ConcurrentHashMap fileListMap = new ConcurrentHashMap<>(); + + private WvpPassiveStorageConfig config; + + public WvpPassiveStorageOperator(String configJson) { + loadConfig(configJson); + } + + public static String getUrlForTask(Long taskId) { + return StorageUtil.joinPath("video-source", taskId.toString() + ".mp4"); + } + + public static void onReceiveResult(Long taskId, FileObject fileObject) { + if (fileObject == null) { + log.info("任务{}获取视频失败!", taskId); + fileListMap.put(taskId, new FileObject()); + } else { + fileListMap.put(taskId, fileObject); + } + } + + public static List getTaskListByScenicId(Long scenicId) { + List scenicTask = taskList.stream().filter(task -> task.scenicId.equals(scenicId)).collect(Collectors.toList()); + if (scenicTask.isEmpty()) { + return Collections.emptyList(); + } + taskList.removeAll(scenicTask); + return scenicTask; + } + + @Override + public void loadConfig(String configJson) { + this.config = JSON.parseObject(configJson, WvpPassiveStorageConfig.class); + } + + @Override + public List getFileListByDtRange(Date startDate, Date endDate) { + Task task = new Task(); + task.taskId = SnowFlakeUtil.getLongId(); + task.scenicId = device.getScenicId(); + task.deviceId = device.getId(); + if (StringUtils.isNotBlank(config.getDeviceNo())) { + task.deviceNo = config.getDeviceNo(); + } else { + task.deviceNo = device.getNo2(); + } + task.startTime = startDate; + task.endTime = endDate; + taskList.add(task); + Date taskStartTime = new Date(); + while (true) { + if (new Date().getTime() - taskStartTime.getTime() > 120000L) { + log.info("任务{}获取视频超时!", task.taskId); + return Collections.emptyList(); + } + if (fileListMap.containsKey(task.taskId)) { + FileObject fileObject = fileListMap.get(task.taskId); + if (StringUtils.isNotBlank(fileObject.getUrl())) { + log.info("任务{}获取视频成功!{}", task.taskId, fileObject); + fileListMap.remove(task.taskId); + return Collections.singletonList(fileObject); + } else { + log.info("任务{}获取视频失败!", task.taskId); + return Collections.emptyList(); + } + } else { + try { + Thread.sleep(1000L); + } catch (InterruptedException e) { + return Collections.emptyList(); + } + } + } + } + + @Override + public boolean removeFilesBeforeDate(Date date) { + // 不做删除 + return false; + } +} diff --git a/src/main/java/com/ycwl/basic/model/wvp/WvpSyncReqVo.java b/src/main/java/com/ycwl/basic/model/wvp/WvpSyncReqVo.java new file mode 100644 index 0000000..8a1ef58 --- /dev/null +++ b/src/main/java/com/ycwl/basic/model/wvp/WvpSyncReqVo.java @@ -0,0 +1,19 @@ +package com.ycwl.basic.model.wvp; + +import lombok.Data; + +import java.util.Date; +import java.util.List; + +@Data +public class WvpSyncReqVo { + @Data + public static class DeviceItem { + String deviceNo; + String channelNo; + Integer online; + Date keepaliveAt; + } + private String version; + private List devices; +}