‘liusuyi’
2024-04-02 6a26b1d539576a556d0f8682af7ae4317de78c7a
修复相机密码脱敏导致的bug
已修改10个文件
652 ■■■■ 文件已修改
ard-work/src/main/java/com/ruoyi/device/camera/controller/ArdCamerasController.java 49 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/factory/CameraSDK.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/ICameraSdkService.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/CameraSdkServiceImpl.java 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/utils/sdk/dhsdk/module/LoginModule.java 16 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/utils/sdk/dhsdk/service/impl/DahuaSDK.java 251 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/utils/sdk/hiksdk/service/impl/HikvisionSDK.java 246 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/utils/tools/ArdTool.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/resources/mapper/device/ArdCamerasMapper.xml 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/SyncTask.java 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ard-work/src/main/java/com/ruoyi/device/camera/controller/ArdCamerasController.java
@@ -2,6 +2,7 @@
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.ruoyi.alarmpoints.well.domain.ArdAlarmpointsWell;
import com.ruoyi.common.constant.CameraConstants;
@@ -14,10 +15,12 @@
import com.ruoyi.device.camera.service.ICameraSdkService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.inspect.service.IArdVideoInspectTaskService;
import com.ruoyi.utils.tools.ArdTool;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
@@ -64,6 +67,7 @@
        List<ArdCameras> list = ardCamerasService.selectArdCamerasList(ardCamera);
        return getDataTable(list);
    }
    /**
     * 查询相机设备列表(不校验权限)
     */
@@ -74,6 +78,7 @@
        List<ArdCameras> list = ardCamerasService.selectArdCamerasList(ardCamera);
        return getDataTable(list);
    }
    /**
     * 导出相机设备列表
     */
@@ -105,16 +110,17 @@
    @Log(title = "相机设备", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody ArdCameras camera) {
        if (CameraConstants.NOT_UNIQUE.equals(ardCamerasService.checkCameraIpAndPortUnique(camera)))
        {
            return error("新增相机'" + camera.getIp()+":"+camera.getPort() + "'失败,相机已存在");
        if (CameraConstants.NOT_UNIQUE.equals(ardCamerasService.checkCameraIpAndPortUnique(camera))) {
            return error("新增相机'" + camera.getIp() + ":" + camera.getPort() + "'失败,相机已存在");
        }
        camera.setState("0");
        int i = ardCamerasService.insertArdCameras(camera);
        if (i > 0) {
            cameraSdkService.logout(camera.getId());
            cameraSdkService.login(camera);
            AjaxResult result = cameraSdkService.login(camera);
            return success(result.get("msg"));
        } else {
            return error("新增相机设备失败");
        }
        return toAjax(i);
    }
    /**
@@ -125,18 +131,20 @@
    @Log(title = "相机设备", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody ArdCameras camera) {
        if (CameraConstants.NOT_UNIQUE.equals(ardCamerasService.checkCameraIpAndPortUnique(camera)))
        {
            return error("修改相机'" + camera.getIp()+":"+camera.getPort() + "'失败,相机已存在");
        if (CameraConstants.NOT_UNIQUE.equals(ardCamerasService.checkCameraIpAndPortUnique(camera))) {
            return error("修改相机'" + camera.getIp() + ":" + camera.getPort() + "'失败,相机已存在");
        }
        ArdCameras cameraOld = ardCamerasService.selectArdCamerasById(camera.getId());
        ArdTool.fillNullFields(cameraOld, camera);
        camera.setState("0");
        int i = ardCamerasService.updateArdCameras(camera);
        if (i > 0) {
            if(StringUtils.isNotNull(camera.getPassword())) {
                cameraSdkService.logout(camera.getId());
                cameraSdkService.login(camera);
            }
            AjaxResult result = cameraSdkService.login(camera);
            return success(result.get("msg"));
        } else {
            return error("修改相机设备失败");
        }
        return toAjax(i);
    }
    /**
@@ -173,7 +181,6 @@
    }
    @GetMapping("/options")
    @ApiOperation("选择相机数据")
    public List options(ArdCameras ardCameras) {
@@ -198,12 +205,14 @@
        Map deptAndCamera = ardCamerasService.getChildDeptAndCamera(true);
        return AjaxResult.success(deptAndCamera);
    }
    @GetMapping("/getDeptAndCameraByRole")
    @ApiOperation("获取部门和相机按角色")
    public AjaxResult getDeptAndCameraByRole() {
        List<DeptAndCamerasDto> deptAndCamera = ardCamerasService.getChildDeptAndCamera();
        return AjaxResult.success(deptAndCamera);
    }
    @GetMapping("/getDeptAndCameraWithCheckBox")
    @ApiOperation("获取部门和相机(开启复选框)")
    public AjaxResult getDeptAndCameraWithCheckBox() {
@@ -224,22 +233,22 @@
    public AjaxResult getCamerasByDeptId() {
        Long deptId = SecurityUtils.getDeptId();
        String userId = SecurityUtils.getUserId();
        List<Map<String,Object>> camerasList = ardCamerasService.getCamerasByDeptId(deptId,userId);
        List<Map<String, Object>> camerasList = ardCamerasService.getCamerasByDeptId(deptId, userId);
        return AjaxResult.success(camerasList);
    }
    @PostMapping("/getCameraOperationByCameraId")
    @ApiOperation("查看相机可否操控")
    public AjaxResult getCameraOperationByCameraId(@RequestBody Map<String,String> map) {
    public AjaxResult getCameraOperationByCameraId(@RequestBody Map<String, String> map) {
        String userId = SecurityUtils.getUserId();
        Boolean flag = ardCamerasService.getCameraOperationByCameraId(map.get("id"),userId);
        Boolean flag = ardCamerasService.getCameraOperationByCameraId(map.get("id"), userId);
        return AjaxResult.success(flag);
    }
    @PostMapping("/getChannelByCameraId")
    @ApiOperation("获取相机通道")
    public AjaxResult getChannelByCameraId(@RequestBody Map<String,String> map) {
        Map<String,Object> result = ardCamerasService.getChannelByCameraId(map.get("id"));
    public AjaxResult getChannelByCameraId(@RequestBody Map<String, String> map) {
        Map<String, Object> result = ardCamerasService.getChannelByCameraId(map.get("id"));
        return AjaxResult.success(result);
    }
}
ard-work/src/main/java/com/ruoyi/device/camera/factory/CameraSDK.java
@@ -15,10 +15,10 @@
public interface CameraSDK {
    //同步登录
    boolean login(ArdCameras cameras);
    AjaxResult login(ArdCameras cameras);
    //异步登录
    void asyncLogin(ArdCameras cameras);
    AjaxResult asyncLogin(ArdCameras cameras);
    //注销
    boolean logout(String cameraId);
ard-work/src/main/java/com/ruoyi/device/camera/service/ICameraSdkService.java
@@ -9,8 +9,11 @@
public interface ICameraSdkService {
    //登录
    Boolean login(ArdCameras ardCamera);
    //同步登录
    AjaxResult login(ArdCameras ardCamera);
    //异步登录
    AjaxResult asyncLogin(ArdCameras ardCamera);
    //注销
    boolean logout(String cameraId);
ard-work/src/main/java/com/ruoyi/device/camera/service/impl/CameraSdkServiceImpl.java
@@ -59,12 +59,11 @@
     */
    @Override
    public void run(ApplicationArguments args) {
        try {
            // 从ardCamerasService中获取ArdCameras列表
            List<ArdCameras> ardCameras = ardCamerasService.selectArdCamerasListNoDataScope(new ArdCameras());
            for (ArdCameras camera : ardCameras) {
                login(camera);
                asyncLogin(camera);
            }
        } catch (Exception ex) {
            // 初始化登录相机异常,记录错误日志
@@ -73,23 +72,35 @@
    }
    //登录
    //同步登录
    @Override
    public Boolean login(ArdCameras ardCamera) {
        boolean result = false;
    public AjaxResult login(ArdCameras ardCamera) {
        try {
            if (ardCamera != null) {
                String factory = ardCamera.getFactory();
                CameraSDK cameraSDK = cameraSDKFactory.createCameraSDK(factory);
                //sdkStrategy.login(ardCamera);//同步登录
                cameraSDK.asyncLogin(ardCamera);//异步登录
                result = true;
            if (ardCamera == null) {
                return AjaxResult.error("登录相机失败,相机不存在");
            }
            String factory = ardCamera.getFactory();
            CameraSDK cameraSDK = cameraSDKFactory.createCameraSDK(factory);
            return cameraSDK.login(ardCamera);//同步登录
        } catch (Exception ex) {
            log.error("登录异常:" + ex.getMessage());
            return false;
            return AjaxResult.error("登录异常:" + ex.getMessage());
        }
        return result;
    }
    @Override
    public AjaxResult asyncLogin(ArdCameras ardCamera) {
        try {
            if (ardCamera == null) {
                return AjaxResult.error("登录相机失败,相机不存在");
            }
            String factory = ardCamera.getFactory();
            CameraSDK cameraSDK = cameraSDKFactory.createCameraSDK(factory);
            return cameraSDK.asyncLogin(ardCamera);//异步登录
        } catch (Exception ex) {
            log.error("登录异常:" + ex.getMessage());
            return AjaxResult.error("登录异常:" + ex.getMessage());
        }
    }
    //注销
@@ -463,7 +474,7 @@
        } catch (Exception ex) {
            log.error("设置ptz异常:" + ex.getMessage());
           return AjaxResult.error("设置ptz异常:" + ex.getMessage());
            return AjaxResult.error("设置ptz异常:" + ex.getMessage());
        }
    }
@@ -689,8 +700,7 @@
    public AjaxResult controlLock(CameraCmd cmd) {
        String cameraId = cmd.getCameraId();//申请锁的相机
        ArdCameras ardCameras = ardCamerasService.selectArdCamerasById(cameraId);
        if(ardCameras==null)
        {
        if (ardCameras == null) {
            return AjaxResult.error("设备未登录");
        }
        Date now = new Date();
@@ -713,8 +723,7 @@
        String cameraId = cmd.getCameraId();//申请解锁的相机
        String operator = cmd.getOperator();//申请者
        ArdCameras ardCameras = ardCamerasService.selectArdCamerasById(cameraId);
        if(ardCameras==null)
        {
        if (ardCameras == null) {
            return AjaxResult.error("设备未登录");
        }
        if (ardCameras.getOperatorId().equals(operator)) {
ard-work/src/main/java/com/ruoyi/utils/sdk/dhsdk/module/LoginModule.java
@@ -63,14 +63,14 @@
        netsdk.CLIENT_SetAutoReconnect(haveReConnect, null);
        //设置登录超时时间和尝试次数,可选
        int waitTime = 5000; //登录请求响应超时时间设置为5S
        int waitTime = 2000; //登录请求响应超时时间设置为5S
        int tryTimes = 1;    //登录时尝试建立链接1次
        netsdk.CLIENT_SetConnectTime(waitTime, tryTimes);
        // 设置更多网络参数,NET_PARAM的nWaittime,nConnectTryNum成员与CLIENT_SetConnectTime
        // 接口设置的登录设备超时时间和尝试次数意义相同,可选
        NetSDKLib.NET_PARAM netParam = new NetSDKLib.NET_PARAM();
        netParam.nConnectTime = 10000;      // 登录时尝试建立链接的超时时间
        netParam.nConnectTime = 2000;      // 登录时尝试建立链接的超时时间
        netParam.nGetConnInfoTime = 3000;   // 设置子连接的超时时间
        netParam.nGetDevInfoTime = 3000;//获取设备信息超时时间,为0默认1000ms
        netsdk.CLIENT_SetNetworkParam(netParam);
@@ -114,11 +114,11 @@
        //NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY pstOutParam = new NET_OUT_LOGIN_WITH_HIGHLEVEL_SECURITY();
        LLong m_hLoginHandle = netsdk.CLIENT_LoginEx2(m_strIp, m_nPort, m_strUser, m_strPassword, 0, null, lpDeviceInfo, nError);
        //m_hLoginHandle=netsdk.CLIENT_LoginWithHighLevelSecurity(pstInParam, pstOutParam);
        if (m_hLoginHandle.longValue() == 0) {
            log.debug("Login Failed [" + m_strIp + ":" + m_nPort + "],错误码:" + getErrorCodePrint());
        } else {
            log.debug("Login Success [ " + m_strIp + ":" + m_nPort + " ]");
        }
        //if (m_hLoginHandle.longValue() == 0) {
        //    log.debug("Login Failed [" + m_strIp + ":" + m_nPort + "],错误码:" + getErrorCodePrint());
        //} else {
        //    log.debug("Login Success [ " + m_strIp + ":" + m_nPort + " ]");
        //}
        return m_hLoginHandle;
    }
@@ -141,4 +141,4 @@
    }
}
}
ard-work/src/main/java/com/ruoyi/utils/sdk/dhsdk/service/impl/DahuaSDK.java
@@ -86,145 +86,156 @@
     * @return
     */
    @Override
    public boolean login(ArdCameras camera) {
        LoginModule.init(disConnect, haveReConnect);
        NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
        NetSDKLib.LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword(), m_stDeviceInfo);
        if (loginId.longValue() <= 0) {
            camera.setChanNum(0);
            camera.setLoginId(-1);
            camera.setState("0");
            ardCamerasService.updateArdCameras(camera);
    public AjaxResult login(ArdCameras camera) {
        try {
            LoginModule.init(disConnect, haveReConnect);
            NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
            NetSDKLib.LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword(), m_stDeviceInfo);
            if (loginId.longValue() <= 0) {
                camera.setChanNum(0);
                camera.setLoginId(-1);
                camera.setState("0");
                ardCamerasService.updateArdCameras(camera);
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                log.error("设备[" + camera.getIp() + ":" + camera.getPort() + "]登录失败:" + getErrorCodePrint());
                return AjaxResult.error(ErrorCode.getErrorCode(LoginModule.netsdk.CLIENT_GetLastError()));
            }
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            return false;
        }
        if (GlobalVariable.loginMap.containsKey(camera.getId())) {
            GlobalVariable.loginMap.remove(camera.getId());
        }
        //删除管理通道
        ardChannelService.deleteArdChannelByDeviceId(camera.getId());
        camera.setState("1");
        camera.setChanNum(m_stDeviceInfo.byChanNum);
        camera.setStartDChan(1);
        camera.setLoginId((int) loginId.longValue());
        ardCamerasService.updateArdCameras(camera);
        GlobalVariable.loginMap.put(camera.getId(), loginId);
            camera.setState("1");
            camera.setChanNum(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 < m_stDeviceInfo.byChanNum + 1; i++) {
            ArdChannel channel = new ArdChannel();
            NetSDKLib.AV_CFG_ChannelName av_cfg_channelName = new NetSDKLib.AV_CFG_ChannelName();
            boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
            if (b) {
                String chanName = null;
                try {
                    chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                channel.setName(chanName);
            } else {
                channel.setName("通道" + i);
            }
            channel.setDeviceId(camera.getId());
            channel.setChanNo(i);
            ardChannelService.insertArdChannel(channel);
        }
        //配置到流媒体
        for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
            String name = camera.getId() + "_" + i;
            String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/cam/realmonitor?channel=" + i + "&subtype=0";
            Vtdu vtdu = vtduService.selectVtduByName(name);
            if (vtdu != null) {
                vtduService.deleteVtduByName(name);
            }
            //添加到流媒体
            CameraCmd cmd = new CameraCmd(camera.getId(), i);
            Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
            vtdu = new Vtdu();
            if (videoCompressionCfg.get("videoEncType") != null) {
                if (videoCompressionCfg.get("videoEncType").equals("标准h264")) {
                    vtdu.setIsCode("0");//默认不转码
            //获取最新通道
            for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
                ArdChannel channel = new ArdChannel();
                NetSDKLib.AV_CFG_ChannelName av_cfg_channelName = new NetSDKLib.AV_CFG_ChannelName();
                boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
                if (b) {
                    String chanName = null;
                    try {
                        chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    channel.setName(chanName);
                } else {
                    vtdu.setIsCode("1");//默认转码
                    channel.setName("通道" + i);
                }
            } else {
                vtdu.setIsCode("0");//默认不转码
                channel.setDeviceId(camera.getId());
                channel.setChanNo(i);
                ardChannelService.insertArdChannel(channel);
            }
            vtdu.setRtspSource(rtspSource);
            vtdu.setName(camera.getId() + "_" + i);
            vtdu.setMode("1");//默认CPU软解码
            vtdu.setCameraId(camera.getId());
            vtduService.insertVtdu(vtdu);
        }
            //配置到流媒体
            for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
                String name = camera.getId() + "_" + i;
                String rtspSource = "rtsp://" + camera.getUsername() + ":" + camera.getPassword() + "@" + camera.getIp() + ":" + camera.getRtspPort() + "/cam/realmonitor?channel=" + i + "&subtype=0";
                Vtdu vtdu = vtduService.selectVtduByName(name);
                if (vtdu != null) {
                    vtduService.deleteVtduByName(name);
                }
                //添加到流媒体
                CameraCmd cmd = new CameraCmd(camera.getId(), i);
                Map<String, Object> videoCompressionCfg = getVideoCompressionCfg(cmd);
                vtdu = new Vtdu();
                if (videoCompressionCfg.get("videoEncType") != null) {
                    if (videoCompressionCfg.get("videoEncType").equals("标准h264")) {
                        vtdu.setIsCode("0");//默认不转码
                    } else {
                        vtdu.setIsCode("1");//默认转码
                    }
                } else {
                    vtdu.setIsCode("0");//默认不转码
                }
                vtdu.setRtspSource(rtspSource);
                vtdu.setName(camera.getId() + "_" + i);
                vtdu.setMode("1");//默认CPU软解码
                vtdu.setCameraId(camera.getId());
                vtduService.insertVtdu(vtdu);
            }
        //创建引导队列
        //创建引导队列
        if (camera.getCamAlarmGuideEnable() == 1) {
            if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
            //创建引导队列
            if (camera.getCamAlarmGuideEnable() != null && camera.getCamAlarmGuideEnable() == 1) {
                if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                    Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                    PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                    GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
                }
                //启动队列处理器
                queueHandler.process(camera.getId());
            }
            //启动队列处理器
            queueHandler.process(camera.getId());
            return AjaxResult.success("登录成功");
        } catch (Exception ex) {
            log.error("登录异常:" + ex.getMessage());
            return AjaxResult.error("登录异常:" + ex.getMessage());
        }
        return true;
    }
    @Override
    @Async("loginExecutor")
    public void asyncLogin(ArdCameras camera) {
        LoginModule.init(disConnect, haveReConnect);
        NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
        NetSDKLib.LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword(), m_stDeviceInfo);
        if (loginId.longValue() <= 0) {
            camera.setChanNum(0);
            camera.setLoginId(-1);
            camera.setState("0");
            ardCamerasService.updateArdCameras(camera);
    public AjaxResult asyncLogin(ArdCameras camera) {
        try {
            LoginModule.init(disConnect, haveReConnect);
            NetSDKLib.NET_DEVICEINFO_Ex m_stDeviceInfo = new NetSDKLib.NET_DEVICEINFO_Ex();
            NetSDKLib.LLong loginId = LoginModule.login(camera.getIp(), camera.getPort(), camera.getUsername(), camera.getPassword(), m_stDeviceInfo);
            if (loginId.longValue() <= 0) {
                camera.setChanNum(0);
                camera.setLoginId(-1);
                camera.setState("0");
                ardCamerasService.updateArdCameras(camera);
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                log.error("设备[" + camera.getIp() + ":" + camera.getPort() + "]登录失败:" + getErrorCodePrint());
                return AjaxResult.error(ErrorCode.getErrorCode(LoginModule.netsdk.CLIENT_GetLastError()));
            }
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            return;
        }
        if (GlobalVariable.loginMap.containsKey(camera.getId())) {
            GlobalVariable.loginMap.remove(camera.getId());
        }
        //删除管理通道
        ardChannelService.deleteArdChannelByDeviceId(camera.getId());
        camera.setState("1");
        camera.setChanNum(m_stDeviceInfo.byChanNum);
        camera.setStartDChan(1);
        camera.setLoginId((int) loginId.longValue());
        ardCamerasService.updateArdCameras(camera);
        GlobalVariable.loginMap.put(camera.getId(), loginId);
            camera.setState("1");
            camera.setChanNum(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 < m_stDeviceInfo.byChanNum + 1; i++) {
            ArdChannel channel = new ArdChannel();
            NetSDKLib.AV_CFG_ChannelName av_cfg_channelName = new NetSDKLib.AV_CFG_ChannelName();
            boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
            if (b) {
                String chanName = null;
                try {
                    chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
            //获取最新通道
            for (int i = 1; i < m_stDeviceInfo.byChanNum + 1; i++) {
                ArdChannel channel = new ArdChannel();
                NetSDKLib.AV_CFG_ChannelName av_cfg_channelName = new NetSDKLib.AV_CFG_ChannelName();
                boolean b = ConfigModule.GetNewDevConfig(loginId, i - 1, CFG_CMD_CHANNELTITLE, av_cfg_channelName);
                if (b) {
                    String chanName = null;
                    try {
                        chanName = new String(av_cfg_channelName.szName, "GBK").trim();
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                    channel.setName(chanName);
                } else {
                    channel.setName("通道" + i);
                }
                channel.setName(chanName);
            } else {
                channel.setName("通道" + i);
                channel.setDeviceId(camera.getId());
                channel.setChanNo(i);
                ardChannelService.insertArdChannel(channel);
            }
            channel.setDeviceId(camera.getId());
            channel.setChanNo(i);
            ardChannelService.insertArdChannel(channel);
            //配置到流媒体
            addVtdu(camera);
            //创建引导队列
            createGuideQueue(camera);
            return AjaxResult.success("登录成功");
        } catch (Exception ex) {
            log.error("登录异常:" + ex.getMessage());
            return AjaxResult.error("登录异常:" + ex.getMessage());
        }
        //配置到流媒体
        addVtdu(camera);
        //创建引导队列
        createGuideQueue(camera);
    }
    //添加到流媒体
ard-work/src/main/java/com/ruoyi/utils/sdk/hiksdk/service/impl/HikvisionSDK.java
@@ -73,116 +73,7 @@
     * @修改人和其它信息
     */
    @Override
    public boolean login(ArdCameras camera) {
        try {
            // 初始化
            if (!hCNetSDK.NET_DVR_Init()) {
                log.error("SDK初始化失败");
            }
            //打印海康sdk日志
            if (Platform.isWindows()) {
                String WIN_PATH = System.getProperty("user.dir") + File.separator + "ardLog" + File.separator + "logs" + File.separator;
                hCNetSDK.NET_DVR_SetLogToFile(3, WIN_PATH, true);
            } else {
                hCNetSDK.NET_DVR_SetLogToFile(3, "/home/ardLog/hiklog", true);
            }
            String m_sDeviceIP = camera.getIp();
            String m_sUsername = camera.getUsername();
            String m_sPassword = camera.getPassword();
            short m_sPort = camera.getPort().shortValue();
            //设置连接时间与重连时间
            hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
            hCNetSDK.NET_DVR_SetReconnect(5000, true);
            //设备信息, 输出参数
            HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
            HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
            // 注册设备-登录参数,包括设备地址、登录用户、密码等
            m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
            System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
            m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
            System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
            m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
            System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
            m_strLoginInfo.wPort = m_sPort;
            m_strLoginInfo.byVerifyMode = 0;
            m_strLoginInfo.byLoginMode = 0;
            //是否异步登录:0- 否,1- 是  windowsSDK里是true和false
            m_strLoginInfo.bUseAsynLogin = false;
            m_strLoginInfo.write();
            //同步登录
            int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
            if (lUserID < 0) {
                log.debug("Login Failed [ " + camera.getIp() + ":" + camera.getPort() + " ],错误码:" + hCNetSDK.NET_DVR_GetLastError());
                camera.setChanNum(0);
                camera.setLoginId(-1);
                camera.setState("0");
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                ardCamerasService.updateArdCameras(camera);
                return false;
            }
            log.debug("Login Success [ " + camera.getIp() + ":" + camera.getPort() + " ]");
            if (fExceptionCallBack == null) {
                fExceptionCallBack = new ExceptionCallBack();//异常回调
                //设置异常回调函数(可在回调函数中获取设备上下线状态等)
                if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, null)) {
                    log.debug("Set fExceptionCallBack function fail");
                    return false;
                } else {
                    log.debug("Set fExceptionCallBack function successfully!");
                }
            }
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            GlobalVariable.loginMap.put(camera.getId(), lUserID);
            GlobalVariable.loginCameraMap.put(lUserID, camera);
            camera.setLoginId(lUserID);
            camera.setState("1");
            camera.setChanNum((int) m_strDeviceInfo.struDeviceV30.byChanNum);
            camera.setStartDChan((int) m_strDeviceInfo.struDeviceV30.byStartDChan);
            //获取最新通道
            List<ArdChannel> cameraChannelList = getIPChannelInfo(camera);
            if (cameraChannelList.size() > 0) {
                camera.setChannelList(cameraChannelList);
                for (ArdChannel channel : cameraChannelList) {
                    channel.setId(IdUtils.simpleUUID());
                    ardChannelService.insertArdChannel(channel);
                }
                //添加到流媒体
                addVtdu(camera);
            }
            //创建引导队列
            if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
            }
            ardCamerasService.updateArdCameras(camera);
        } catch (Exception ex) {
            log.error("注册设备异常", ex);
        }
        return true;
    }
    /**
     * @描述 注册登录 集成于NET_DVR_Login_V30,支持同步和异步登录
     * @参数 [dvrLogin]
     * @返回值 java.lang.Integer
     * @创建人 刘苏义
     * @创建时间 2023/1/17 16:12
     * @修改人和其它信息
     */
    @Override
    @Async("loginExecutor")
    public void asyncLogin(ArdCameras camera) {
    public AjaxResult login(ArdCameras camera) {
        try {
            // 初始化
            if (!hCNetSDK.NET_DVR_Init()) {
@@ -223,18 +114,126 @@
            int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
            if (lUserID < 0) {
                int errorCode = hCNetSDK.NET_DVR_GetLastError();
                log.debug("Login Failed 【 " + camera.getIp() + ":" + camera.getPort() + " 】," +
                        "Error Code:" + errorCode + " " +
                        "Error Info:" + SdkErrorCodeEnum.getDescByCode(errorCode));
                camera.setChanNum(0);
                camera.setLoginId(-1);
                camera.setState("0");
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                ardCamerasService.updateArdCameras(camera);
                return;
                log.error("设备[" + camera.getIp() + ":" + camera.getPort() + "]登录失败: errorCode:" + errorCode + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(errorCode));
                return AjaxResult.error("登录失败: errorCode:" + errorCode + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(errorCode));
            }
            log.debug("Login Success [ " + camera.getIp() + ":" + camera.getPort() + " ]");
            if (fExceptionCallBack == null) {
                fExceptionCallBack = new ExceptionCallBack();//异常回调
                //设置异常回调函数(可在回调函数中获取设备上下线状态等)
                if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, null)) {
                    log.debug("Set fExceptionCallBack function fail");
                } else {
                    log.debug("Set fExceptionCallBack function successfully!");
                }
            }
            if (GlobalVariable.loginMap.containsKey(camera.getId())) {
                GlobalVariable.loginMap.remove(camera.getId());
            }
            //删除管理通道
            ardChannelService.deleteArdChannelByDeviceId(camera.getId());
            GlobalVariable.loginMap.put(camera.getId(), lUserID);
            GlobalVariable.loginCameraMap.put(lUserID, camera);
            camera.setLoginId(lUserID);
            camera.setState("1");
            camera.setChanNum((int) m_strDeviceInfo.struDeviceV30.byChanNum);
            camera.setStartDChan((int) m_strDeviceInfo.struDeviceV30.byStartDChan);
            //获取最新通道
            List<ArdChannel> cameraChannelList = getIPChannelInfo(camera);
            if (cameraChannelList.size() > 0) {
                camera.setChannelList(cameraChannelList);
                for (ArdChannel channel : cameraChannelList) {
                    channel.setId(IdUtils.simpleUUID());
                    ardChannelService.insertArdChannel(channel);
                }
                //添加到流媒体
                addVtdu(camera);
            }
            //创建引导队列
            if (!GuidePriorityQueue.cameraQueueMap.containsKey(camera.getId())) {
                Comparator<GuideTask> comparator = GuidePriorityQueue.getComparator();
                PriorityBlockingQueue<GuideTask> priorityQueue = new PriorityBlockingQueue<>(1000, comparator);
                GuidePriorityQueue.cameraQueueMap.put(camera.getId(), priorityQueue);
            }
            ardCamerasService.updateArdCameras(camera);
            return AjaxResult.success("设备登录成功");
        } catch (Exception ex) {
            log.error("注册设备异常", ex);
            return AjaxResult.error("注册设备异常" + ex.getMessage());
        }
    }
    /**
     * @描述 注册登录 集成于NET_DVR_Login_V30,支持同步和异步登录
     * @参数 [dvrLogin]
     * @返回值 java.lang.Integer
     * @创建人 刘苏义
     * @创建时间 2023/1/17 16:12
     * @修改人和其它信息
     */
    @Override
    @Async("loginExecutor")
    public AjaxResult asyncLogin(ArdCameras camera) {
        try {
            // 初始化
            if (!hCNetSDK.NET_DVR_Init()) {
                log.error("SDK初始化失败");
                return AjaxResult.error("SDK初始化失败");
            }
            //打印海康sdk日志
            if (Platform.isWindows()) {
                String WIN_PATH = System.getProperty("user.dir") + File.separator + "ardLog" + File.separator + "logs" + File.separator;
                hCNetSDK.NET_DVR_SetLogToFile(3, WIN_PATH, true);
            } else {
                hCNetSDK.NET_DVR_SetLogToFile(3, "/home/ardLog/hiklog", true);
            }
            String m_sDeviceIP = camera.getIp();
            String m_sUsername = camera.getUsername();
            String m_sPassword = camera.getPassword();
            short m_sPort = camera.getPort().shortValue();
            //设置连接时间与重连时间
            hCNetSDK.NET_DVR_SetConnectTime(2000, 1);
            hCNetSDK.NET_DVR_SetReconnect(5000, true);
            //设备信息, 输出参数
            HCNetSDK.NET_DVR_DEVICEINFO_V40 m_strDeviceInfo = new HCNetSDK.NET_DVR_DEVICEINFO_V40();
            HCNetSDK.NET_DVR_USER_LOGIN_INFO m_strLoginInfo = new HCNetSDK.NET_DVR_USER_LOGIN_INFO();
            // 注册设备-登录参数,包括设备地址、登录用户、密码等
            m_strLoginInfo.sDeviceAddress = new byte[HCNetSDK.NET_DVR_DEV_ADDRESS_MAX_LEN];
            System.arraycopy(m_sDeviceIP.getBytes(), 0, m_strLoginInfo.sDeviceAddress, 0, m_sDeviceIP.length());
            m_strLoginInfo.sUserName = new byte[HCNetSDK.NET_DVR_LOGIN_USERNAME_MAX_LEN];
            System.arraycopy(m_sUsername.getBytes(), 0, m_strLoginInfo.sUserName, 0, m_sUsername.length());
            m_strLoginInfo.sPassword = new byte[HCNetSDK.NET_DVR_LOGIN_PASSWD_MAX_LEN];
            System.arraycopy(m_sPassword.getBytes(), 0, m_strLoginInfo.sPassword, 0, m_sPassword.length());
            m_strLoginInfo.wPort = m_sPort;
            m_strLoginInfo.byVerifyMode = 0;
            m_strLoginInfo.byLoginMode = 0;
            //是否异步登录:0- 否,1- 是  windowsSDK里是true和false
            m_strLoginInfo.bUseAsynLogin = false;
            m_strLoginInfo.write();
            //同步登录
            int lUserID = hCNetSDK.NET_DVR_Login_V40(m_strLoginInfo, m_strDeviceInfo);
            if (lUserID < 0) {
                int errorCode = hCNetSDK.NET_DVR_GetLastError();
                camera.setChanNum(0);
                camera.setLoginId(-1);
                camera.setState("0");
                //删除管理通道
                ardChannelService.deleteArdChannelByDeviceId(camera.getId());
                ardCamerasService.updateArdCameras(camera);
                log.error("设备[" + camera.getIp() + ":" + camera.getPort() + "]登录失败: errorCode:" + errorCode + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(errorCode));
                return AjaxResult.error("设备登录失败: errorCode:" + errorCode + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(errorCode));
            }
            log.debug("Login Success 【 " + camera.getIp() + ":" + camera.getPort() + " 】");
            synchronized (_lock) {
                if (fExceptionCallBack == null) {
@@ -242,7 +241,6 @@
                    //设置异常回调函数(可在回调函数中获取设备上下线状态等)
                    if (!hCNetSDK.NET_DVR_SetExceptionCallBack_V30(0, 0, fExceptionCallBack, null)) {
                        log.debug("Set fExceptionCallBack function fail");
                        return;
                    } else {
                        log.debug("Set fExceptionCallBack function successfully!");
                    }
@@ -277,8 +275,10 @@
            addVtdu(camera);
            //创建引导队列
            createGuideQueue(camera);
            return AjaxResult.success("设备登录成功");
        } catch (Exception ex) {
            log.error("注册设备异常", ex);
            return AjaxResult.error("注册设备异常" + ex.getMessage());
        }
    }
@@ -1917,14 +1917,14 @@
            log.error("获取GIS信息数据失败: errorCode:" + code + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(code));
            return AjaxResult.error("获取GIS信息数据失败: errorCode:" + code + " errorInfo:" + SdkErrorCodeEnum.getDescByCode(code));
        }
            struGisInfo.read();
            Map<String, Object> map = new HashMap<>();
            map.put("p", struGisInfo.struPtzPos.fPanPos);
            map.put("t", struGisInfo.struPtzPos.fTiltPos < 0 ? struGisInfo.struPtzPos.fTiltPos + 360 : struGisInfo.struPtzPos.fTiltPos);
            map.put("z", struGisInfo.struPtzPos.fZoomPos);
            map.put("fHorFieldAngle", struGisInfo.fHorizontalValue);// 水平视场角
            map.put("fVerFieldAngle", struGisInfo.fVerticalValue);// 垂直视场角
            return AjaxResult.success(map);
        struGisInfo.read();
        Map<String, Object> map = new HashMap<>();
        map.put("p", struGisInfo.struPtzPos.fPanPos);
        map.put("t", struGisInfo.struPtzPos.fTiltPos < 0 ? struGisInfo.struPtzPos.fTiltPos + 360 : struGisInfo.struPtzPos.fTiltPos);
        map.put("z", struGisInfo.struPtzPos.fZoomPos);
        map.put("fHorFieldAngle", struGisInfo.fHorizontalValue);// 水平视场角
        map.put("fVerFieldAngle", struGisInfo.fVerticalValue);// 垂直视场角
        return AjaxResult.success(map);
    }
}
ard-work/src/main/java/com/ruoyi/utils/tools/ArdTool.java
@@ -186,4 +186,27 @@
        }
    }
    /**
     *  通过反射对象填充
     * 刘苏义
     * 2024/4/2 11:50:57
     */
    public static void fillNullFields(Object source, Object target) {
        if (source == null || target == null) {
            return;
        }
        Field[] fields = source.getClass().getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);
            try {
                Object sourceValue = field.get(source);
                Object targetValue = field.get(target);
                if (targetValue == null && sourceValue != null) {
                    field.set(target, sourceValue);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}
ard-work/src/main/resources/mapper/device/ArdCamerasMapper.xml
@@ -104,6 +104,7 @@
                WHERE cast(#{deptId} as varchar) = any(string_to_array(ancestors,',')) ))
            </if>
            <if test="towerId != null ">and c.tower_id = #{towerId}</if>
            <if test="state != null ">and c.state = #{state}</if>
            <!-- 数据范围过滤 -->
            ${params.dataScope}
        </where>
@@ -140,6 +141,7 @@
            <if test="camMaxVisibleDistance != null ">and c.cam_max_visible_distance = #{camMaxVisibleDistance}</if>
            <if test="camAlarmGuideEnable != null ">and c.cam_alarm_guide_enable = #{camAlarmGuideEnable}</if>
            <if test="loginId != null ">and c.login_id = #{loginId}</if>
            <if test="state != null ">and c.state = #{state}</if>
        </where>
    </select>
    <select id="selectArdCamerasById" parameterType="String" resultMap="ArdCamerasResult">
@@ -181,6 +183,7 @@
            <if test="createTime != null">create_time,</if>
            <if test="updateBy != null">update_by,</if>
            <if test="updateTime != null">update_time,</if>
            <if test="state != null">state,</if>
        </trim>
        <trim prefix="values (" suffix=")" suffixOverrides=",">
            <if test="id != null">#{id},</if>
@@ -214,6 +217,7 @@
            <if test="createTime != null">#{createTime},</if>
            <if test="updateBy != null">#{updateBy},</if>
            <if test="updateTime != null">#{updateTime},</if>
            <if test="state != null">#{state},</if>
        </trim>
    </insert>
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/SyncTask.java
@@ -8,6 +8,7 @@
import com.ruoyi.device.camera.factory.CameraSDK;
import com.ruoyi.device.camera.factory.CameraSDKFactory;
import com.ruoyi.device.camera.service.IArdCamerasService;
import com.ruoyi.device.camera.service.ICameraSdkService;
import com.ruoyi.media.domain.Vtdu;
import com.ruoyi.media.service.IMediaService;
import com.ruoyi.media.service.IVtduService;
@@ -41,7 +42,7 @@
    @Resource
    IMediaService mediaService;
    @Resource
    private CameraSDKFactory cameraSDKFactory;
    private ICameraSdkService cameraSdkService;
    /**
     * 同步相机在线状态
     * 刘苏义
@@ -55,9 +56,7 @@
            for (ArdCameras camera : ardCameras) {
                CameraCmd cmd = new CameraCmd();
                cmd.setCameraId(camera.getId());
                String factory = camera.getFactory();
                CameraSDK cameraSDK = cameraSDKFactory.createCameraSDK(factory);
                boolean onLineNew = cameraSDK.isOnLine(cmd);
                boolean onLineNew = cameraSdkService.isOnLine(cmd);
                boolean onLineOld = "1".equals(camera.getState());
                if (onLineNew != onLineOld) {
                    if (onLineNew) {