wvp passive

This commit is contained in:
Jerry Yan 2025-01-16 18:27:40 +08:00
parent f2f7fa22c9
commit 0bba613001
6 changed files with 180 additions and 2 deletions

View File

@ -2,21 +2,58 @@ package com.ycwl.basic.controller.wvp;
import com.ycwl.basic.annotation.IgnoreLogReq; import com.ycwl.basic.annotation.IgnoreLogReq;
import com.ycwl.basic.annotation.IgnoreToken; 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 com.ycwl.basic.utils.ApiResponse;
import io.swagger.annotations.Api; 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.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@Slf4j
@IgnoreToken @IgnoreToken
@RestController @RestController
@Api(tags = "WVP对接接口") @Api(tags = "WVP对接接口")
@RequestMapping("/wvp/v1/") @RequestMapping("/wvp/v1/")
public class WvpController { public class WvpController {
private final DeviceService deviceService;
public WvpController(DeviceService deviceService) {
this.deviceService = deviceService;
}
@IgnoreLogReq @IgnoreLogReq
@PostMapping("/sync") @PostMapping("/scenic/{scenicId}/sync")
public ApiResponse sync() { public ApiResponse<List<WvpPassiveStorageOperator.Task>> 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<String> 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<String> fail(@PathVariable("scenicId") Long scenicId, @PathVariable("taskId") Long taskId) {
WvpPassiveStorageOperator.onReceiveResult(taskId, null);
return ApiResponse.success("success"); return ApiResponse.success("success");
} }
} }

View File

@ -8,6 +8,7 @@ import com.ycwl.basic.device.operator.AliOssStorageOperator;
import com.ycwl.basic.device.operator.IDeviceStorageOperator; import com.ycwl.basic.device.operator.IDeviceStorageOperator;
import com.ycwl.basic.device.operator.LocalStorageOperator; import com.ycwl.basic.device.operator.LocalStorageOperator;
import com.ycwl.basic.device.operator.WvpActiveStorageOperator; 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.DeviceConfigEntity;
import com.ycwl.basic.model.pc.device.entity.DeviceEntity; import com.ycwl.basic.model.pc.device.entity.DeviceEntity;
@ -18,6 +19,8 @@ public class DeviceFactory {
operator = new AliOssStorageOperator(config.getStoreConfigJson()); operator = new AliOssStorageOperator(config.getStoreConfigJson());
} else if (config.getStoreType() == DeviceStoreTypeEnum.WVP_ACTIVE.getType()) { } else if (config.getStoreType() == DeviceStoreTypeEnum.WVP_ACTIVE.getType()) {
operator = new WvpActiveStorageOperator(config.getStoreConfigJson()); 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()) { } else if (config.getStoreType() == DeviceStoreTypeEnum.LOCAL.getType()) {
operator = new LocalStorageOperator(config.getStoreConfigJson()); operator = new LocalStorageOperator(config.getStoreConfigJson());
} }

View File

@ -0,0 +1,8 @@
package com.ycwl.basic.device.entity.wvp_passive;
import lombok.Data;
@Data
public class WvpPassiveStorageConfig {
private String deviceNo;
}

View File

@ -8,6 +8,7 @@ import lombok.Getter;
public enum DeviceStoreTypeEnum { public enum DeviceStoreTypeEnum {
ALI_OSS(1, "阿里云OSS"), ALI_OSS(1, "阿里云OSS"),
WVP_ACTIVE(3, "WVP主动模式"), WVP_ACTIVE(3, "WVP主动模式"),
WVP_PASSIVE(4, "WVP被动模式"),
LOCAL(2, "本地文件"); LOCAL(2, "本地文件");
private final int type; private final int type;

View File

@ -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<Task> taskList = Collections.synchronizedList(new ArrayList<>());
private static ConcurrentHashMap<Long, FileObject> 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<Task> getTaskListByScenicId(Long scenicId) {
List<Task> 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<FileObject> 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;
}
}

View File

@ -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<DeviceItem> devices;
}