aijinhui
2023-10-17 49207386ea4a3d663628347eef443af9c7cc7f39
ard-work/src/main/java/com/ruoyi/device/dhsdk/service/impl/DhClientServiceImpl.java
@@ -1,255 +1,662 @@
package com.ruoyi.device.dhsdk.service.impl;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.device.camera.domain.ArdCameras;
import com.ruoyi.device.camera.domain.CameraCmd;
import com.ruoyi.device.camera.service.IArdCamerasService;
import com.ruoyi.device.channel.domain.ArdChannel;
import com.ruoyi.device.channel.service.IArdChannelService;
import com.ruoyi.device.dhsdk.common.Res;
import com.ruoyi.device.dhsdk.lib.NetSDKLib;
import com.ruoyi.device.dhsdk.lib.NetSDKLib.LLong;
import com.ruoyi.device.dhsdk.lib.ToolKits;
import com.ruoyi.device.dhsdk.lib.enumeration.EM_NEW_QUERY_SYSTEM_INFO;
import com.ruoyi.device.dhsdk.module.ConfigModule;
import com.ruoyi.device.dhsdk.module.LoginModule;
import com.ruoyi.device.dhsdk.module.PtzControlModule;
import com.ruoyi.device.dhsdk.service.IDhClientService;
import com.ruoyi.device.hiksdk.common.GlobalVariable;
import com.ruoyi.device.hiksdk.sdk.HCNetSDK;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;
import static com.ruoyi.device.dhsdk.lib.NetSDKLib.NET_DEVSTATE_PTZ_LOCATION;
import static com.ruoyi.device.dhsdk.lib.ToolKits.getErrorCodePrint;
import static com.ruoyi.device.hiksdk.sdk.HCNetSDK.NET_DVR_CHECK_USER_STATUS;
/**
 * @ClassName DhSdkServiceImpl
 * @Description:
 * @Author 刘苏义
 * @Date 2023/10/13 21:19
 * @Version 1.0
 */
@Service
@Slf4j(topic = "dhSdk")
public class DhClientServiceImpl implements IDhClientService {
    @Resource
    private IArdCamerasService ardCamerasService;
    @Resource
    private IArdChannelService ardChannelService;
    private Vector<String> chnlist = new Vector<String>();
    // 设备断线通知回调
    private static DisConnect disConnect = new DisConnect();
    // 网络连接恢复
    private static HaveReConnect haveReConnect = new HaveReConnect();
    @Override
    public void loginAll() {
        try {
            ArdCameras ardCamera = new ArdCameras();
            ardCamera.setFactory("2");//获取大华相机
            List<ArdCameras> ardCameras = ardCamerasService.selectArdCamerasListNoDataScope(ardCamera);
            for (ArdCameras camera : ardCameras) {
                Thread.sleep(500);
                //异步登录
                login(camera);
            }
        } catch (Exception ex) {
            log.error("初始化登录相机异常:" + ex.getMessage());
        }
    }
    @Override
    public Boolean init() {
        return LoginModule.init(disConnect, haveReConnect);   // 打开工程,初始化
    }
    @Override
    @Async
    public Boolean login(ArdCameras camera) {
        LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword());
        if (loginId.longValue() > 0) {
            //log.debug(camera.getIp() + ":" + camera.getPort() + "登录成功");
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            camera.setState("1");
            camera.setChanNum(LoginModule.m_stDeviceInfo.byChanNum);
            camera.setStartDChan(1);
            camera.setLoginId((int) loginId.longValue());
            ardCamerasService.updateArdCameras(camera);
            GlobalVariable.loginMap.put(camera.getId(), loginId);
            //获取最新通道
            for (int i = 1; i < LoginModule.m_stDeviceInfo.byChanNum + 1; i++) {
                chnlist.add(Res.string().getChannel() + " " + String.valueOf(i));
                ArdChannel channel = new ArdChannel();
                channel.setDeviceId(camera.getId());
                channel.setName("通道" + i);
                channel.setId(IdUtils.simpleUUID());
                channel.setChanNo(i);
                ardChannelService.insertArdChannel(channel);
            }
        } else {
            //log.debug(camera.getIp() + ":" + camera.getPort() + "登录失败");
            camera.setChanNum(0);
            camera.setLoginId(-1);
            camera.setState("0");
            ardCamerasService.updateArdCameras(camera);
            return false;
        }
        return true;
    }
    @Override
    public Boolean logout(String cameraId) {
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        return LoginModule.logout(loginId);
    }
    @Override
    public boolean isOnLine(CameraCmd cmd) {
        try {
            String cameraId = cmd.getCameraId();
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return false;
            }
            LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        } catch (Exception ex) {
            log.error("检测在线异常:" + ex.getMessage());
            return false;
        }
        return false;
    }
    @Override
    public boolean pTZControl(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        boolean enable = cmd.isEnable();
        Integer chanNo = cmd.getChanNo();
        Integer speed = cmd.getSpeed();
        Integer code = cmd.getCode();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        int dwStop;
        if (enable) {
            dwStop = 0;//开启
        } else {
            dwStop = 1;//关闭
        }
        int dwPTZCommand = -1;
        switch (code) {
            /*方向*/
            case 1:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTTOP;
                break;
            case 2:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_UP_CONTROL;
                break;
            case 3:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTTOP;
                break;
            case 4:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_LEFT_CONTROL;
                break;
            case 5:
                dwPTZCommand = HCNetSDK.RUN_SEQ;
                break;
            case 6:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_RIGHT_CONTROL;
                break;
            case 7:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTDOWN;
                break;
            case 8:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_DOWN_CONTROL;
                break;
            case 9:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTDOWN;
                break;
            /*焦距*/
            case 10:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_ADD_CONTROL;
                break;
            case 11:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_DEC_CONTROL;
                break;
            /*焦点*/
            case 12:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_ADD_CONTROL;
                break;
            case 13:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_DEC_CONTROL;
                break;
            /*光圈*/
            case 14:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_APERTURE_ADD_CONTROL;
                break;
            case 15:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_APERTURE_DEC_CONTROL;
                break;
        }
        boolean bool = LoginModule.netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, dwPTZCommand, speed, speed, 0, dwStop);
        if (!bool) {
            log.error("控制失败,请稍后重试" + getErrorCodePrint());
        }
        return bool;
    }
    @Override
    public Map<String, Object> getPtz(CameraCmd cmd) {
        Map<String, Object> ptzMap = new HashMap<>();
        String cameraId = cmd.getCameraId();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return null;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        NetSDKLib.NET_PTZ_LOCATION_INFO dh_ptz_location_info = new NetSDKLib.NET_PTZ_LOCATION_INFO();
        boolean b = ConfigModule.queryDevState(loginId, NET_DEVSTATE_PTZ_LOCATION, dh_ptz_location_info);
        if (b) {
            DecimalFormat df = new DecimalFormat("0.0");//设置保留位数
            String nPTZPan = df.format((float)dh_ptz_location_info.nPTZPan / 10);
            String nPTZTilt = df.format((float)dh_ptz_location_info.nPTZTilt/10);
            String nPTZZoom = df.format((float)dh_ptz_location_info.nPTZZoom);
            ptzMap.put("p", nPTZPan);
            ptzMap.put("t", nPTZTilt);
            ptzMap.put("z", nPTZZoom);
        }
        return ptzMap;
    }
    // 设备断线回调: 通过 CLIENT_Init 设置该回调函数,当设备出现断线时,SDK会调用该函数
    private static class DisConnect implements NetSDKLib.fDisConnect {
        public void invoke(LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
        }
    }
    // 网络连接恢复,设备重连成功回调
    // 通过 CLIENT_SetAutoReconnect 设置该回调函数,当已断线的设备重连成功时,SDK会调用该函数
    private static class HaveReConnect implements NetSDKLib.fHaveReConnect {
        @Override
        public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);
        }
    }
package com.ruoyi.device.dhsdk.service.impl;
import com.ruoyi.common.annotation.SdkOperate;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.device.camera.domain.ArdCameras;
import com.ruoyi.device.camera.domain.CameraCmd;
import com.ruoyi.device.camera.service.IArdCamerasService;
import com.ruoyi.device.channel.domain.ArdChannel;
import com.ruoyi.device.channel.service.IArdChannelService;
import com.ruoyi.device.dhsdk.common.Res;
import com.ruoyi.device.dhsdk.lib.NetSDKLib;
import com.ruoyi.device.dhsdk.lib.NetSDKLib.LLong;
import com.ruoyi.device.dhsdk.lib.structure.CFG_VIDEO_IN_FOCUS;
import com.ruoyi.device.dhsdk.lib.structure.CFG_VIDEO_IN_FOCUS_UNIT;
import com.ruoyi.device.dhsdk.module.CapturePictureModule;
import com.ruoyi.device.dhsdk.module.ConfigModule;
import com.ruoyi.device.dhsdk.module.LoginModule;
import com.ruoyi.device.dhsdk.module.RealPlayModule;
import com.ruoyi.device.dhsdk.service.IDhClientService;
import com.ruoyi.device.hiksdk.common.GlobalVariable;
import com.ruoyi.device.hiksdk.sdk.HCNetSDK;
import com.ruoyi.utils.gis.GisUtil;
import com.ruoyi.utils.minio.MinioUtil;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.text.DecimalFormat;
import java.util.*;
import static com.ruoyi.device.dhsdk.lib.NetSDKLib.NET_DEVSTATE_ONLINE;
import static com.ruoyi.device.dhsdk.lib.NetSDKLib.NET_DEVSTATE_PTZ_LOCATION;
import static com.ruoyi.device.dhsdk.lib.NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_MOVE_CONTROL;
import static com.ruoyi.device.dhsdk.lib.NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_SET_CONTROL;
import static com.ruoyi.device.dhsdk.lib.ToolKits.getErrorCodePrint;
import static com.ruoyi.device.dhsdk.module.LoginModule.netsdk;
import static com.ruoyi.device.hiksdk.sdk.HCNetSDK.NET_DVR_SET_PTZPOS;
/**
 * @ClassName DhSdkServiceImpl
 * @Description:
 * @Author 刘苏义
 * @Date 2023/10/13 21:19
 * @Version 1.0
 */
@Service
@Slf4j(topic = "dhSdk")
public class DhClientServiceImpl implements IDhClientService {
    @Resource
    private IArdCamerasService ardCamerasService;
    @Resource
    private IArdChannelService ardChannelService;
    @Value("${minio.endpoint}")
    private String minioEndPoint;
    private Vector<String> chnlist = new Vector<String>();
    // 设备断线通知回调
    private static DisConnect disConnect = new DisConnect();
    // 网络连接恢复
    private static HaveReConnect haveReConnect = new HaveReConnect();
    /**
     * 登录所有相机
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public void loginAll() {
        try {
            ArdCameras ardCamera = new ArdCameras();
            ardCamera.setFactory("2");//获取大华相机
            List<ArdCameras> ardCameras = ardCamerasService.selectArdCamerasListNoDataScope(ardCamera);
            for (ArdCameras camera : ardCameras) {
                Thread.sleep(500);
                //异步登录
                login(camera);
            }
        } catch (Exception ex) {
            log.error("初始化登录相机异常:" + ex.getMessage());
        }
    }
    /**
     * sdk初始化
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public Boolean init() {
        return LoginModule.init(disConnect, haveReConnect);   // 打开工程,初始化
    }
    /**
     * 登录
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    @Async
    public Boolean login(ArdCameras camera) {
        LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword());
        if (loginId.longValue() > 0) {
            //log.debug(camera.getIp() + ":" + camera.getPort() + "登录成功");
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            camera.setState("1");
            camera.setChanNum(LoginModule.m_stDeviceInfo.byChanNum);
            camera.setStartDChan(1);
            camera.setLoginId((int) loginId.longValue());
            ardCamerasService.updateArdCameras(camera);
            GlobalVariable.loginMap.put(camera.getId(), loginId);
            //获取最新通道
            for (int i = 1; i < LoginModule.m_stDeviceInfo.byChanNum + 1; i++) {
                chnlist.add(Res.string().getChannel() + " " + String.valueOf(i));
                ArdChannel channel = new ArdChannel();
                channel.setDeviceId(camera.getId());
                channel.setName("通道" + i);
                channel.setId(IdUtils.simpleUUID());
                channel.setChanNo(i);
                ardChannelService.insertArdChannel(channel);
            }
        } else {
            //log.debug(camera.getIp() + ":" + camera.getPort() + "登录失败");
            camera.setChanNum(0);
            camera.setLoginId(-1);
            camera.setState("0");
            ardCamerasService.updateArdCameras(camera);
            return false;
        }
        return true;
    }
    /**
     * 注销
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public Boolean logout(String cameraId) {
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        return LoginModule.logout(loginId);
    }
    /**
     * 是否在线检测
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public boolean isOnLine(CameraCmd cmd) {
        try {
            String cameraId = cmd.getCameraId();
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return false;
            }
            LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
            NetSDKLib.NET_WORKSTATE dh_ptz_location_info = new NetSDKLib.NET_WORKSTATE();
            boolean b = ConfigModule.queryDevState(loginId, NET_DEVSTATE_ONLINE, dh_ptz_location_info);
            if (!b) {
                return false;
            }
        } catch (Exception ex) {
            log.error("检测在线异常:" + ex.getMessage());
            return false;
        }
        return true;
    }
    /**
     * 云台控制
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public boolean pTZControl(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        boolean enable = cmd.isEnable();
        Integer chanNo = cmd.getChanNo();
        Integer speed = cmd.getSpeed();
        Integer code = cmd.getCode();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        int dwStop;
        if (enable) {
            dwStop = 0;//开启
        } else {
            dwStop = 1;//关闭
        }
        int dwPTZCommand = -1;
        switch (code) {
            /*方向*/
            case 1:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTTOP;
                break;
            case 2:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_UP_CONTROL;
                break;
            case 3:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTTOP;
                break;
            case 4:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_LEFT_CONTROL;
                break;
            case 5:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_POINT_LOOP_CONTROL;
                break;
            case 6:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_RIGHT_CONTROL;
                break;
            case 7:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_LEFTDOWN;
                break;
            case 8:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_DOWN_CONTROL;
                break;
            case 9:
                dwPTZCommand = NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RIGHTDOWN;
                break;
            /*焦距*/
            case 10:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_ADD_CONTROL;
                break;
            case 11:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_ZOOM_DEC_CONTROL;
                break;
            /*焦点*/
            case 12:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_ADD_CONTROL;
                break;
            case 13:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_FOCUS_DEC_CONTROL;
                break;
            /*光圈*/
            case 14:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_APERTURE_ADD_CONTROL;
                break;
            case 15:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_APERTURE_DEC_CONTROL;
                break;
            case 16:
                dwPTZCommand = NetSDKLib.NET_PTZ_ControlType.NET_PTZ_LAMP_CONTROL;
                break;
        }
        boolean bool = netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, dwPTZCommand, speed, speed, 0, dwStop);
        if (!bool) {
            log.error("控制失败,请稍后重试" + getErrorCodePrint());
        }
        return bool;
    }
    /**
     * 获取PTZ值
     * 刘苏义
     * 2023/10/17 8:28:13
     */
    @Override
    public Map<String, Object> getPtz(CameraCmd cmd) {
        Map<String, Object> ptzMap = new HashMap<>();
        String cameraId = cmd.getCameraId();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return null;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        NetSDKLib.NET_PTZ_LOCATION_INFO dh_ptz_location_info = new NetSDKLib.NET_PTZ_LOCATION_INFO();
        boolean b = ConfigModule.queryDevState(loginId, NET_DEVSTATE_PTZ_LOCATION, dh_ptz_location_info);
        if (b) {
            DecimalFormat df = new DecimalFormat("0.0");//设置保留位数
            String nPTZPan = df.format((float) dh_ptz_location_info.nPTZPan / 10);
            String nPTZTilt = df.format((float) dh_ptz_location_info.nPTZTilt / 10);
            String nPTZZoom = df.format((float) dh_ptz_location_info.nPTZZoom);
            ptzMap.put("p", nPTZPan);
            ptzMap.put("t", nPTZTilt);
            ptzMap.put("z", nPTZZoom);
        }
        return ptzMap;
    }
    /**
     * @描述 设置ptz信息
     * @参数 [userId, channelNum]
     * @返回值 boolean
     * @创建人 刘苏义
     * @创建时间 2023/1/17 16:36
     * @修改人和其它信息 注意俯仰角度负值需要加上360得到的正值进行设置
     */
    @Override
    @SdkOperate
    public boolean setPtz(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        Map<String, Double> ptz = cmd.getPtzMap();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        try {
            int p = (int) (ptz.get("p") * 10);
            int t = (int) (ptz.get("t") * 10);
            int z = ptz.get("z").intValue();
            if (z == 0) {
                z = 1;
            }
            boolean bool = netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_EXACTGOTO, p, t, z, 0);
            if (!bool) {
                log.error("控制失败,请稍后重试" + getErrorCodePrint());
            }
            return bool;
        } catch (Exception ex) {
            log.error(ex.getMessage());
            return false;
        }
    }
    /**
     * @描述 设置零方位角
     * @参数 [userId, channelNum]
     * @返回值 boolean
     * @创建人 刘苏义
     * @创建时间 2023/1/17 16:36
     * @修改人和其它信息 注意俯仰角度负值需要加上360得到的正值进行设置
     */
    @Override
    @SdkOperate
    public boolean setZeroPtz(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        boolean bool = NetSDKLib.NETSDK_INSTANCE.CLIENT_DHPTZControlEx(loginId, chanNo - 1, NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_RESETZERO, 0, 0, 0, 0);
        if (!bool) {
            log.error("控制失败,请稍后重试" + getErrorCodePrint());
        }
        return bool;
    }
    /**
     * @描述 截图 存服务器
     * @参数 [cameraId, channelNum]
     * @返回值 java.lang.String
     * @创建人 刘苏义
     * @创建时间 2023/2/2 14:59
     * @修改人和其它信息
     */
    @Override
    @SdkOperate
    public String picCutCate(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return "";
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        String bucketName = "pic";
        String picUrl = "";
        String bucketObject = "/capture/" + IdUtils.simpleUUID() + ".jpeg";
        fCaptureReceiveCB m_CaptureReceiveCB = new fCaptureReceiveCB(minioEndPoint, bucketName, bucketObject);
        CapturePictureModule.setSnapRevCallBack(m_CaptureReceiveCB);
        boolean b = CapturePictureModule.remoteCapturePicture(loginId, chanNo - 1);
        if (b) {
            picUrl = minioEndPoint + "/" + bucketName + bucketObject;
        }
        return picUrl;
    }
    /**
     * @描述 短时录像
     * @参数 [userId, channelNum, enable]
     * @返回值 void
     * @创建人 刘苏义
     * @创建时间 2023/1/20 11:18
     * @修改人和其它信息
     */
    @Override
    public String record(CameraCmd cmd) {
        try {
            String url = "";
            String cameraId = cmd.getCameraId();
            Integer chanNo = cmd.getChanNo();
            String path = FileUtils.createFile("D:/recordTemp/" + cameraId + ".mp4");
            boolean enable = cmd.isEnable();
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return "";
            }
            LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
            if (enable) {
                LLong lRealHandle = new LLong(0);
                if (!GlobalVariable.previewMap.containsKey(cameraId)) {
                    lRealHandle = RealPlayModule.startRealPlay(loginId, chanNo, 0);
                    if (lRealHandle.longValue() <= 0) {
                        log.error("取流失败" + getErrorCodePrint());
                        return "";
                    }
                    log.debug("取流成功");
                    GlobalVariable.previewMap.put(cameraId, lRealHandle.intValue());
                }
                if (!netsdk.CLIENT_SaveRealData(lRealHandle, path)) {
                    log.error("保存视频文件到临时文件夹失败 错误码为:  " + getErrorCodePrint());
                    return "";
                }
                log.debug("录像开始");
            } else {
                if (GlobalVariable.previewMap.containsKey(cameraId)) {
                    LLong lRealHandle = new LLong(GlobalVariable.previewMap.get(cameraId));
                    boolean b = netsdk.CLIENT_StopSaveRealData(lRealHandle);
                    GlobalVariable.previewMap.remove(cameraId);
                }
                log.debug("录像停止");
            }
            return url;
        } catch (Exception ex) {
            log.error("录像异常" + ex.getMessage());
            return "";
        }
    }
    @Override
    public boolean recordStart(CameraCmd cmd) {
        try {
            String cameraId = cmd.getCameraId();
            Integer chanNo = cmd.getChanNo();
            String path = FileUtils.createFile("D:/recordTemp/" + cameraId + ".mp4");
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return false;
            }
            LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
            LLong lRealHandle;
            if (GlobalVariable.previewMap.containsKey(cameraId)) {
                lRealHandle = new LLong(GlobalVariable.previewMap.get(cameraId));
                netsdk.CLIENT_StopRealPlayEx(lRealHandle);
                GlobalVariable.previewMap.remove(cameraId);
                log.debug("停止当前录像");
            }
            lRealHandle = RealPlayModule.startRealPlay1(loginId, chanNo - 1, path);
            if (lRealHandle.longValue() <= 0) {
                log.error("取流失败" + getErrorCodePrint());
            }
            log.debug("取流成功");
            GlobalVariable.previewMap.put(cameraId, lRealHandle.intValue());
            GlobalVariable.threadMap.put(cameraId, Thread.currentThread().getName());
            //if (!netsdk.CLIENT_SaveRealData(lRealHandle, path)) {
            //    log.error("保存视频文件到临时文件夹失败 错误码为:  " +getErrorCodePrint());
            //    return false;
            //}
            log.debug("录像开始");
            return true;
        } catch (Exception ex) {
            log.error("开始录像异常" + ex.getMessage());
            return false;
        }
    }
    @Override
    public String recordStopToMinio(CameraCmd cmd) {
        String url = "";
        try {
            String cameraId = cmd.getCameraId();
            String path = FileUtils.createFile("D:/recordTemp/" + cameraId + ".mp4");
            if (!GlobalVariable.loginMap.containsKey(cameraId)) {
                return "";
            }
            LLong lRealHandle;
            if (GlobalVariable.previewMap.containsKey(cameraId)) {
                lRealHandle = new LLong(GlobalVariable.previewMap.get(cameraId));
                netsdk.CLIENT_StopRealPlayEx(lRealHandle);
                GlobalVariable.previewMap.remove(cameraId);
                log.debug("停止当前录像");
            }
            //存入minio
            String BucketName = cmd.getRecordBucketName();
            String ObjectName = cmd.getRecordObjectName() + ".mp4";
            FileInputStream stream = new FileInputStream(path);
            boolean b = MinioUtil.uploadObject(BucketName, ObjectName, stream, stream.available(), "video/MP4");
            if (b) {
                url = MinioUtil.getBucketObjectUrl(BucketName, ObjectName);
                log.debug("上传文件成功!" + url);
            }
            return url;
        } catch (Exception ex) {
            log.error("录像异常" + ex.getMessage());
            return "";
        }
    }
    /**
     * 引导目标位置
     * 刘苏义
     * 2023/10/17 8:27:48
     */
    @Override
    public boolean guideTargetPosition(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        try {
            ArdCameras cameras = ardCamerasService.selectArdCamerasById(cameraId);
            double[] cameraPositon = new double[]{cameras.getLongitude(), cameras.getLatitude(), cameras.getAltitude()};
            double[] targetPositions = cmd.getTargetPosition();
            double[] cameraPTZ = GisUtil.getCameraPTZ(cameraPositon, targetPositions, 20, 150);
            int p = (int) (cameraPTZ[0] * 10);
            int t = (int) (cameraPTZ[1] * 10);
            int z = (int) (cameraPTZ[2]);
            boolean bool = netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, NetSDKLib.NET_EXTPTZ_ControlType.NET_EXTPTZ_EXACTGOTO, p, t, z, 0);
            if (!bool) {
                log.error("控制失败,请稍后重试" + getErrorCodePrint());
            }
            return bool;
        } catch (Exception ex) {
            log.error("引导异常:" + ex.getMessage());
            return false;
        }
    }
    //转至预置点
    @Override
    public boolean gotoPreset(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        Integer PresetIndex = cmd.getPresetIndex();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        try {
            boolean bool = netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, NET_PTZ_POINT_MOVE_CONTROL, 0, PresetIndex, 0, 0);
            if (!bool) {
                log.error("控制失败,请稍后重试" + getErrorCodePrint());
            }
            return bool;
        } catch (Exception ex) {
            log.error("转至预置点异常:" + ex.getMessage());
            return false;
        }
    }
    @Override
    //设置预置位
    public boolean setPreset(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        Integer PresetIndex = cmd.getPresetIndex();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        try {
            boolean bool = netsdk.CLIENT_DHPTZControlEx(loginId, chanNo - 1, NET_PTZ_POINT_SET_CONTROL, 0, PresetIndex, 0, 0);
            if (!bool) {
                log.error("控制失败,请稍后重试" + getErrorCodePrint());
            }
            return bool;
        } catch (Exception ex) {
            log.error("设置预置点异常:" + ex.getMessage());
            return false;
        }
    }
    //切换聚焦模式
    @Override
    public boolean controlFocusMode(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();
        Integer chanNo = cmd.getChanNo();
        boolean enable = cmd.isEnable();
        if (!GlobalVariable.loginMap.containsKey(cameraId)) {
            return false;
        }
        LLong loginId = (LLong) GlobalVariable.loginMap.get(cameraId);
        try {
            CFG_VIDEO_IN_FOCUS cfg_video_in_focus = new CFG_VIDEO_IN_FOCUS();
            CFG_VIDEO_IN_FOCUS_UNIT[] stVideoInFocusUnit = new CFG_VIDEO_IN_FOCUS_UNIT[32];
            if (enable) {
                stVideoInFocusUnit[0].nMode = 4;//手动聚焦
            } else {
                stVideoInFocusUnit[0].nMode = 2;//手动聚焦
            }
            cfg_video_in_focus.nChannelIndex = chanNo - 1;
            cfg_video_in_focus.stVideoInFocusUnit = stVideoInFocusUnit;
            boolean bool = ConfigModule.SetDevConfig(loginId, chanNo - 1, NetSDKLib.CFG_CMD_VIDEOIN_FOCUS, cfg_video_in_focus);
            if (!bool) {
                log.error("控制失败,请稍后重试" + getErrorCodePrint());
            }
            return bool;
        } catch (Exception ex) {
            log.error("切换聚焦模式异常:" + ex.getMessage());
            return false;
        }
    }
    // 设备断线回调: 当设备出现断线时,SDK会调用该函数
    private static class DisConnect implements NetSDKLib.fDisConnect {
        public void invoke(LLong m_hLoginHandle, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            System.out.printf("Device[%s] Port[%d] DisConnect!\n", pchDVRIP, nDVRPort);
        }
    }
    // 网络连接恢复回调:设备重连成功回调,当已断线的设备重连成功时,SDK会调用该函数
    private static class HaveReConnect implements NetSDKLib.fHaveReConnect {
        @Override
        public void invoke(LLong lLoginID, String pchDVRIP, int nDVRPort, Pointer dwUser) {
            System.out.printf("ReConnect Device[%s] Port[%d]\n", pchDVRIP, nDVRPort);
        }
    }
    // 抓图接收回调:当抓图成功,sdk会调用该函数
    public static class fCaptureReceiveCB implements NetSDKLib.fSnapRev {
        private String minioEndPoint;
        private String ObjectName;
        private String bucketName;
        public fCaptureReceiveCB(String minioEndPoint, String bucketName, String ObjectName) {
            this.minioEndPoint = minioEndPoint;
            this.bucketName = bucketName;
            this.ObjectName = ObjectName;
        }
        public void invoke(LLong lLoginID, Pointer pBuf, int RevLen, int EncodeType, int CmdSerial, Pointer dwUser) {
            if (pBuf != null && RevLen > 0) {
                byte[] buf = pBuf.getByteArray(0, RevLen);
                //存储到minio
                InputStream input = new ByteArrayInputStream(buf);
                try {
                    boolean b = MinioUtil.uploadObject(bucketName, ObjectName, input, input.available(), MimeTypeUtils.IMAGE_JPEG);
                    if (b) {
                        String url = minioEndPoint + "/" + bucketName + ObjectName;
                        log.debug("上传文件成功!" + url);
                    }
                } catch (IOException ex) {
                    log.error("上传文件异常:" + ex.getMessage());
                }
            }
        }
    }
}