package com.ard.work.sdk.service;
|
|
import com.ard.common.core.constant.CacheConstants;
|
import com.ard.common.core.exception.ServiceException;
|
import com.ard.common.core.exception.device.CameraSDKException;
|
import com.ard.common.core.web.domain.AjaxResult;
|
import com.ard.common.redis.service.RedisService;
|
import com.ard.common.security.utils.SecurityUtils;
|
import com.ard.work.api.domian.*;
|
import com.ard.work.device.camera.domain.PtzParamDTO;
|
import com.ard.work.device.noview.domain.ArdNoViewingZone;
|
import com.ard.work.device.noview.service.IArdNoViewingZoneService;
|
import com.ard.work.sdk.annotation.SdkOperate;
|
import com.ard.work.sdk.common.RecordManager;
|
import com.ard.work.sdk.factory.CameraSDKFactory;
|
import com.ard.work.sdk.model.DeviceCFG;
|
import com.ard.work.sdk.model.PtzScope;
|
import com.ard.work.utils.gis.GisUtil;
|
import jakarta.annotation.Resource;
|
import lombok.extern.slf4j.Slf4j;
|
import org.springframework.scheduling.annotation.Async;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Service;
|
|
import java.util.ArrayList;
|
import java.util.Date;
|
import java.util.List;
|
import java.util.Map;
|
|
@Service
|
@Slf4j
|
public class CameraSDKService {
|
|
@Resource
|
private RedisService redisService;
|
@Resource
|
private CameraSDKFactory cameraSDKFactory;
|
@Resource
|
private IArdNoViewingZoneService ardNoViewingZoneService;
|
|
// ========== 基础操作 ==========
|
|
@Async("cameraSdkExecutor")
|
public void login(ArdCamera ardCamera) {
|
if (ardCamera == null) {
|
throw CameraSDKException.cameraNotExist(null);
|
}
|
CameraSDK sdk = cameraSDKFactory.createCameraSDK(ardCamera.getFactory());
|
sdk.login(ardCamera);
|
}
|
|
public void logout(String cameraId) {
|
ArdCamera ardCamera = redisService.getCacheMapValue(CacheConstants.CAMERA_LIST, cameraId);
|
if (ardCamera == null || ardCamera.getFactory() == null) {
|
return;
|
}
|
CameraSDK sdk = cameraSDKFactory.createCameraSDK(ardCamera.getFactory());
|
sdk.logout(cameraId);
|
}
|
|
// ========== 简单操作(一行搞定) ==========
|
|
@SdkOperate
|
public Boolean pTZControl(CameraCmd cmd) {
|
return getSdk(cmd).pTZControl(cmd);
|
}
|
|
public Boolean setFocusPos(CameraCmd cmd) {
|
return getSdk(cmd).setFocusPos(cmd);
|
}
|
|
public Integer getFocusPos(CameraCmd cmd) {
|
return getSdk(cmd).getFocusPos(cmd);
|
}
|
|
public Boolean setPreset(CameraCmd cmd) {
|
return getSdk(cmd).setPreset(cmd);
|
}
|
|
public Boolean gotoPreset(CameraCmd cmd) {
|
return getSdk(cmd).gotoPreset(cmd);
|
}
|
|
public VideoCompressionCfg getVideoCompressionCfg(CameraCmd cmd) {
|
return getSdk(cmd).getVideoCompressionCfg(cmd);
|
}
|
|
public Boolean controlDefog(CameraCmd cmd) {
|
return getSdk(cmd).controlDefog(cmd);
|
}
|
|
public Boolean isEnableDefog(CameraCmd cmd) {
|
return getSdk(cmd).isEnableDefog(cmd);
|
}
|
|
public Boolean controlInfrared(CameraCmd cmd) {
|
return getSdk(cmd).controlInfrared(cmd);
|
}
|
|
public Boolean isEnableInfrared(CameraCmd cmd) {
|
return getSdk(cmd).isEnableInfrared(cmd);
|
}
|
|
public Boolean controlFocusMode(CameraCmd cmd) {
|
return getSdk(cmd).controlFocusMode(cmd);
|
}
|
|
public Boolean getFocusMode(CameraCmd cmd) {
|
return getSdk(cmd).getFocusMode(cmd);
|
}
|
|
public Boolean controlPTHeater(CameraCmd cmd) {
|
return getSdk(cmd).controlPTHeater(cmd);
|
}
|
|
public Boolean controlCameraDeicing(CameraCmd cmd) {
|
return getSdk(cmd).controlCameraDeicing(cmd);
|
}
|
|
public Boolean getPTZLockInfo(CameraCmd cmd) {
|
return getSdk(cmd).getPTZLockInfo(cmd);
|
}
|
|
public Boolean setPTZLockInfo(CameraCmd cmd) {
|
return getSdk(cmd).setPTZLockInfo(cmd);
|
}
|
|
public byte[] localCapture(CameraCmd cmd) {
|
return getSdk(cmd).localCapture(cmd);
|
}
|
|
public PtzScope getPtzScope(CameraCmd cmd) {
|
return getSdk(cmd).getPtzScope(cmd);
|
}
|
|
public Boolean setZeroPtz(CameraCmd cmd) {
|
return getSdk(cmd).setZeroPtz(cmd);
|
}
|
|
public Boolean set3DPosition(CameraCmd cmd) {
|
return getSdk(cmd).set3DPosition(cmd);
|
}
|
|
public PtzParamDTO getGisInfo(CameraCmd cmd) {
|
return getSdk(cmd).getGisInfo(cmd);
|
}
|
|
public Double correctPitch(CameraCmd cmd) {
|
return getSdk(cmd).correctPitch(cmd);
|
}
|
|
// ========== 需要判断类型的操作 ==========
|
|
public PtzDto getPtz(CameraCmd cmd) {
|
return getSdk(cmd).getPtz(cmd);
|
}
|
|
@SdkOperate
|
public Boolean setPtz(CameraCmd cmd) {
|
return getSdk(cmd).setPtz(cmd);
|
}
|
|
// ========== 抓图(重载方法) ==========
|
|
@SdkOperate
|
public String picCutCate(CameraCmd cmd) {
|
return getSdk(cmd).picCutCate(cmd);
|
}
|
|
@SdkOperate
|
public String picCutCate(CameraCmd cmd, String bucketName, String objectName) {
|
return getSdk(cmd).picCutCate(cmd, bucketName, objectName);
|
}
|
|
// ========== 录像 ==========
|
public String record(CameraCmd cmd) {
|
return getSdk(cmd).record(cmd);
|
}
|
|
public Boolean recordStart(CameraCmd cmd) {
|
CameraSDK sdk = getSdk(cmd);
|
Boolean result = sdk.recordStart(cmd);
|
if (result != null && result) {
|
RecordManager.addRecord(cmd.getCameraId() + "_" + cmd.getChanNo());
|
}
|
return result;
|
}
|
|
public String recordStop(CameraCmd cmd) {
|
CameraSDK sdk = getSdk(cmd);
|
String url = sdk.recordStop(cmd);
|
String key = cmd.getCameraId() + "_" + cmd.getChanNo();
|
RecordManager.stopRecord(key);
|
return url;
|
}
|
|
// ========== 智能引导 ==========
|
|
@SdkOperate
|
public Boolean guideTargetPosition(CameraCmd cmd) {
|
CameraSDK sdk = getSdk(cmd);
|
ArdCamera camera = getCamera(cmd.getCameraId());
|
String cameraId = camera.getId();
|
|
// 判断是否超出引导距离
|
if (isOutMaxDistance(cameraId, cmd.getTargetPosition())) {
|
throw new CameraSDKException(CameraSDKException.ErrorCode.OVER_GUIDANCE_RANGE.getCode(),
|
cameraId, "目标超出最大引导距离");
|
}
|
|
// 判断是否在不可视域
|
if (isInNoViewingZone(cameraId, cmd.getTargetPosition())) {
|
throw new CameraSDKException(CameraSDKException.ErrorCode.BEYOND_VISIBILITY_RANGE.getCode(),
|
cameraId, "目标在不可视区域内");
|
}
|
|
cmd.setBaseYaw(camera.getBaseYaw());
|
return sdk.guideTargetPosition(cmd);
|
}
|
|
// ========== 在线检测 ==========
|
|
public boolean isOnLine(CameraCmd cmd) {
|
Long loginId = redisService.getCacheMapValue(CacheConstants.CAMERA_ONLINE, cmd.getCameraId());
|
if (loginId == null) {
|
return false;
|
}
|
cmd.setLoginId(loginId);
|
CameraSDK sdk = getSdk(cmd);
|
return sdk.isOnLine(cmd);
|
}
|
|
// ========== 通道信息 ==========
|
|
public List<ArdChannel> getChannels(ArdCamera camera) {
|
Long loginId = redisService.getCacheMapValue(CacheConstants.CAMERA_ONLINE, camera.getId());
|
if (loginId == null) {
|
return new ArrayList<>();
|
}
|
CameraSDK sdk = cameraSDKFactory.createCameraSDK(camera.getFactory());
|
return sdk.getChannels(camera);
|
}
|
|
// ========== 视频标签 ==========
|
|
public AjaxResult getCameraVideoLable(CameraCmd cmd) {
|
CameraSDK sdk = cameraSDKFactory.createCameraSDK("1"); // 硬编码问题建议修复
|
try {
|
List<Map<String, Object>> result = sdk.getCameraVideoLable(SecurityUtils.getUserId(), cmd);
|
return AjaxResult.success(result);
|
} catch (ServiceException e) {
|
return AjaxResult.error(e.getMessage());
|
}
|
}
|
|
// ========== 定时任务 ==========
|
|
@Scheduled(fixedRate = 30 * 1000)
|
public void checkVideoTimeout() {
|
Date now = new Date();
|
RecordManager.getActiveRecords().forEach((name, date) -> {
|
long duration = now.getTime() - date.getTime();
|
if (duration > 15 * 60 * 1000) {
|
CameraCmd cmd = new CameraCmd();
|
String cameraId = name.split("_")[0];
|
Integer chanNo = Integer.parseInt(name.split("_")[1]);
|
cmd.setCameraId(cameraId);
|
cmd.setChanNo(chanNo);
|
recordStop(cmd);
|
log.info("录像超时检测:停止{}_{}的录像,已录像时间超过15分钟", cameraId, chanNo);
|
}
|
});
|
}
|
|
// ========== 私有辅助方法 ==========
|
|
/**
|
* 获取SDK实例(会校验参数、相机存在性、在线状态)
|
*/
|
private CameraSDK getSdk(CameraCmd cmd) {
|
if (cmd == null || cmd.getCameraId() == null || cmd.getCameraId().isBlank()) {
|
throw CameraSDKException.cameraNotExist(null);
|
}
|
|
Long loginId = redisService.getCacheMapValue(CacheConstants.CAMERA_ONLINE, cmd.getCameraId());
|
if (loginId == null) {
|
throw CameraSDKException.cameraOffline(cmd.getCameraId());
|
}
|
cmd.setLoginId(loginId);
|
|
ArdCamera camera = getCamera(cmd.getCameraId());
|
return cameraSDKFactory.createCameraSDK(camera.getFactory());
|
}
|
|
/**
|
* 获取相机信息(会校验存在性)
|
*/
|
private ArdCamera getCamera(String cameraId) {
|
ArdCamera camera = redisService.getCacheMapValue(CacheConstants.CAMERA_LIST, cameraId);
|
if (camera == null) {
|
throw CameraSDKException.cameraNotExist(cameraId);
|
}
|
return camera;
|
}
|
|
// 判断坐标是否超出引导范围
|
private Boolean isOutMaxDistance(String cameraId, Point targetPoint) {
|
ArdCamera camera = getCamera(cameraId);
|
Point cameraCoordinate = new Point(camera.getLongitude(), camera.getLatitude(), camera.getAltitude());
|
double distance = GisUtil.getDistance(cameraCoordinate, targetPoint);
|
|
if (camera.getCamMaxVisibleDistance() == null) {
|
throw new CameraSDKException(CameraSDKException.ErrorCode.CAMERA_MAX_VISIBLE_DISTANCE_NULL.getCode(),
|
cameraId, CameraSDKException.ErrorCode.CAMERA_MAX_VISIBLE_DISTANCE_NULL.getMsg());
|
}
|
return distance > camera.getCamMaxVisibleDistance();
|
}
|
|
// 判断坐标是否在不可视域
|
private Boolean isInNoViewingZone(String cameraId, Point targetPoint) {
|
ArdNoViewingZone query = new ArdNoViewingZone();
|
query.setCameraId(cameraId);
|
List<ArdNoViewingZone> zones = ardNoViewingZoneService.selectArdNoViewingZoneList(query);
|
if (zones.isEmpty()) {
|
return false;
|
}
|
|
List<Point> points = new ArrayList<>();
|
for (ArdNoViewingZone zone : zones) {
|
String[] parts = zone.getPoi().split(",");
|
for (int i = 0; i < parts.length; i += 3) {
|
Point point = new Point();
|
point.setLongitude(Double.valueOf(parts[i]));
|
point.setLatitude(Double.valueOf(parts[i + 1]));
|
points.add(point);
|
}
|
}
|
return GisUtil.isInPolygon(targetPoint, points);
|
}
|
}
|