| | |
| | | <version>2.0.9</version> |
| | | <scope>compile</scope> |
| | | </dependency> |
| | | <!--张建提供引导依赖--> |
| | | <dependency> |
| | | <groupId>org.gavaghan</groupId> |
| | | <artifactId>geodesy</artifactId> |
| | | <version>1.1.3</version> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | </project> |
| 对比新文件 |
| | |
| | | package com.ruoyi.constant; |
| | | |
| | | /** |
| | | * @Description: sdk控制优先级 |
| | | * @ClassName: sdkPriority |
| | | * @Author: 刘苏义 |
| | | * @Date: 2023年05月23日11:25 |
| | | * @Version: 1.0 |
| | | **/ |
| | | public class sdkPriority { |
| | | static Integer radar_fire = 999; |
| | | } |
| | |
| | | Map<String,Double>ptzMap; |
| | | /*过期间隔(分钟)*/ |
| | | Integer expired; |
| | | /*相机经纬度*/ |
| | | String camPosition; |
| | | /*目标经纬度*/ |
| | | String targetPosition; |
| | | } |
| | |
| | | return toAjax(sdk.setPtz(cmd)); |
| | | } |
| | | |
| | | @ApiOperation("指向目标") |
| | | @PostMapping("/setTargetPosition") |
| | | @Log(title = "指向目标", businessType = BusinessType.CONTROL) |
| | | @ApiOperationSupport(includeParameters = {"cmd.cameraId", "cmd.channelNum", "cmd.targetPosition"}) |
| | | public @ResponseBody |
| | | AjaxResult setTargetPosition(@RequestBody CameraCmd cmd) { |
| | | return toAjax(sdk.setTargetPosition(cmd)); |
| | | } |
| | | |
| | | |
| | | @ApiOperation("设置零方位角") |
| | | @PostMapping("/setZeroPTZ") |
| | | @Log(title = "设置零方位角", businessType = BusinessType.CONTROL) |
| | |
| | | **/ |
| | | public interface hikClientService { |
| | | void loadHCNetSDKLib(); |
| | | |
| | | boolean setTargetPosition(CameraCmd cmd); |
| | | //登录 |
| | | ArdCameras login(ArdCameras cameras); |
| | | |
| | |
| | | import com.ruoyi.device.camera.mapper.ArdCamerasMapper; |
| | | import com.ruoyi.device.hiksdk.common.global.globalVariable; |
| | | import com.ruoyi.device.camera.domain.ArdCameras; |
| | | import com.ruoyi.device.camera.service.IArdCamerasService; |
| | | import com.ruoyi.device.cameracalibration.domain.ArdCamerasCalibration; |
| | | import com.ruoyi.device.hiksdk.domain.recordInfo; |
| | | import com.ruoyi.device.cameracalibration.service.IArdCamerasCalibrationService; |
| | | import com.ruoyi.device.hiksdk.util.hikSdkUtil.GisUtil; |
| | | import com.ruoyi.device.hiksdk.util.hikSdkUtil.HCNetSDK; |
| | | import com.ruoyi.device.hiksdk.service.hikClientService; |
| | | import com.ruoyi.device.hiksdk.util.imageUtil.waterMarkUtil; |
| | | import com.ruoyi.device.hiksdk.util.minioUtil.MinioUtil; |
| | | import com.ruoyi.system.mapper.SysUserMapper; |
| | | import com.ruoyi.system.service.ISysUserService; |
| | | import com.sun.jna.Native; |
| | | import com.sun.jna.Platform; |
| | | import com.sun.jna.Pointer; |
| | |
| | | import sun.misc.BASE64Encoder; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.imageio.ImageIO; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.*; |
| | | import java.math.BigDecimal; |
| | | import java.net.URLEncoder; |
| | | import java.nio.ByteBuffer; |
| | | import java.text.DecimalFormat; |
| | | import java.text.SimpleDateFormat; |
| | |
| | | * @修改人和其它信息 |
| | | */ |
| | | @Override |
| | | @SdkOperate |
| | | // @SdkOperate |
| | | public boolean PTZControlWithSpeed(CameraCmd cmd) { |
| | | String cameraId = cmd.getCameraId(); |
| | | boolean enable = cmd.isEnable(); |
| | |
| | | } |
| | | return bool; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 设置聚焦值 |
| | |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public boolean setTargetPosition(CameraCmd cmd) { |
| | | String cameraId = cmd.getCameraId(); |
| | | Integer channelNum = cmd.getChannelNum(); |
| | | if (!globalVariable.loginMap.containsKey(cameraId)) { |
| | | return false; |
| | | } |
| | | Integer userId = globalVariable.loginMap.get(cameraId); |
| | | HCNetSDK.NET_DVR_PTZPOS m_ptzPosCurrent = new HCNetSDK.NET_DVR_PTZPOS(); |
| | | m_ptzPosCurrent.wAction = 1; |
| | | try { |
| | | double[] cameraPositon = Arrays.stream(cmd.getCamPosition().split(",")).mapToDouble(Double::parseDouble).toArray(); |
| | | double[] targetPositions = Arrays.stream(cmd.getTargetPosition().split(",")).mapToDouble(Double::parseDouble).toArray(); |
| | | double[] cameraPTZ = GisUtil.getCameraPTZ(cameraPositon, targetPositions, 20, 150); |
| | | String p = String.valueOf((int) ( cameraPTZ[0] * 10)); |
| | | String t = String.valueOf((int) ( cameraPTZ[1] * 10)); |
| | | String z = String.valueOf((int) (cameraPTZ[2]* 10)); |
| | | m_ptzPosCurrent.wPanPos = (short) (Integer.parseInt(p, 16)); |
| | | m_ptzPosCurrent.wTiltPos = (short) (Integer.parseInt(t, 16)); |
| | | m_ptzPosCurrent.wZoomPos = (short) (Integer.parseInt(z, 16)); |
| | | Pointer point = m_ptzPosCurrent.getPointer(); |
| | | m_ptzPosCurrent.write(); |
| | | boolean bool = hCNetSDK.NET_DVR_SetDVRConfig(userId, NET_DVR_SET_PTZPOS, channelNum, point, m_ptzPosCurrent.size()); |
| | | if (!bool) { |
| | | int code = hCNetSDK.NET_DVR_GetLastError(); |
| | | log.info("设置ptz失败,请稍后重试" + code); |
| | | } |
| | | return bool; |
| | | } catch (Exception ex) { |
| | | log.error(ex.getMessage()); |
| | | return false; |
| | | } |
| | | } |
| | | /** |
| | | * @描述 操控锁定 |
| | | * @参数 [userId, channelNum] |
| 对比新文件 |
| | |
| | | package com.ruoyi.device.hiksdk.util.hikSdkUtil; |
| | | |
| | | import org.gavaghan.geodesy.*; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.util.Arrays; |
| | | |
| | | public class GisUtil { |
| | | |
| | | public static GeodeticCalculator geodeticCalculator = new GeodeticCalculator(); |
| | | |
| | | /** |
| | | * 根据经纬度,计算两点间的距离 |
| | | * |
| | | * @param longitudeFrom 第一个点的经度 |
| | | * @param latitudeFrom 第一个点的纬度 |
| | | * @param longitudeTo 第二个点的经度 |
| | | * @param latitudeTo 第二个点的纬度 |
| | | * @return 返回距离 单位米 |
| | | */ |
| | | public static double getDistance(double longitudeFrom, double latitudeFrom, double longitudeTo, double latitudeTo) { |
| | | GlobalCoordinates source = new GlobalCoordinates(latitudeFrom, longitudeFrom); |
| | | GlobalCoordinates target = new GlobalCoordinates(latitudeTo, longitudeTo); |
| | | return geodeticCalculator.calculateGeodeticCurve(Ellipsoid.WGS84, source, target).getEllipsoidalDistance(); |
| | | } |
| | | |
| | | /** |
| | | * 计算从from到to方向的直线与正北方向夹角 |
| | | * |
| | | * @param longitudeFrom 第一个点的经度 |
| | | * @param latitudeFrom 第一个点的纬度 |
| | | * @param longitudeTo 第二个点的经度 |
| | | * @param latitudeTo 第二个点的纬度 |
| | | * @return 返回角度 |
| | | */ |
| | | public static double getNorthAngle(double longitudeFrom, double latitudeFrom, double longitudeTo, double latitudeTo) { |
| | | GlobalPosition source = new GlobalPosition(latitudeFrom, longitudeFrom, 0); |
| | | GlobalPosition target = new GlobalPosition(latitudeTo, longitudeTo, 0); |
| | | return geodeticCalculator.calculateGeodeticMeasurement(Ellipsoid.WGS84, source, target).getAzimuth(); |
| | | } |
| | | |
| | | /** |
| | | * @param camera 经度,纬度,高度 如:{125.097531, 46.60029, 120}; |
| | | * @param lookAt 经度,纬度,高度 如:{125.124731, 46.584808, 0}; |
| | | * @param viewAngle 相机可视角度 如:20 |
| | | * @param viewWidth 视域宽度 如:150 |
| | | * @return ptz 数组 如:[129.5355798969157, -2.5419097807416655, 23.3676043024458] |
| | | */ |
| | | public static double[] getCameraPTZ(double[] camera, double[] lookAt, double viewAngle, double viewWidth) { |
| | | double p = 0, t = 0, z = 0; |
| | | double distance = GisUtil.getDistance(camera[0], camera[1], lookAt[0], lookAt[1]); |
| | | double northAngle = GisUtil.getNorthAngle(camera[0], camera[1], lookAt[0], lookAt[1]); |
| | | double height = camera[2] - lookAt[2]; |
| | | p = northAngle; |
| | | t = Angle.toDegrees(Math.atan(height / distance)) * -1+360; |
| | | z = distance * Math.tan(viewAngle / 2) * 2 / viewWidth; |
| | | /* p = new BigDecimal(p).setScale(1,BigDecimal.ROUND_HALF_UP).doubleValue(); |
| | | t = new BigDecimal(t).setScale(1,BigDecimal.ROUND_HALF_UP).doubleValue(); |
| | | z = new BigDecimal(z).setScale(1,BigDecimal.ROUND_HALF_UP).doubleValue();*/ |
| | | return new double[]{p, t, z}; |
| | | } |
| | | |
| | | public static void main(String[] args) { |
| | | // 125.097531,46.60029, 125.124731,46.584808 |
| | | //相机位置 |
| | | double[] camera = {125.146964331147,46.5580925811216,102};//经度,纬度,高度 |
| | | //看向的位置 |
| | | double[] lookAt = {125.155449,46.555108,0};//经度,纬度,高度 |
| | | |
| | | double viewAngle = 20;//相机可视角度 |
| | | double viewWidth = 150;//相机视域宽度 |
| | | |
| | | double[] ptz = GisUtil.getCameraPTZ(camera, lookAt, viewAngle, viewWidth); |
| | | System.out.println("ptz:" + Arrays.toString(ptz)); |
| | | |
| | | } |
| | | } |
| | |
| | | <link rel="stylesheet" th:href="@{/css/bootstrap.css}"/> |
| | | <script th:src="@{/js/bootstrap.js}"></script> |
| | | <style> |
| | | .top-buffer { margin-top:10px; } |
| | | .top-buffer { |
| | | margin-top: 10px; |
| | | } |
| | | </style> |
| | | <body> |
| | | <div class="container"> |
| | | <div class="row "> |
| | | <div class="dropdown"> |
| | | 相机id: |
| | | <select id="select"> |
| | | 相机id:<select id="select"> |
| | | </select> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | | <div class="col-md-6"> |
| | | <div class="row top-buffer"> |
| | | <div class="input-group"> |
| | | <span class="input-group-addon">目的坐标值:</span> |
| | | <input id="targetPostion" class="form-control" placeholder="目的坐标"/> |
| | | <button id="setTargetPostion" type="button" class="btn btn-default">指向坐标</button> |
| | | </div> |
| | | <div class="input-group"> |
| | | <span class="input-group-addon">P值:</span> |
| | | <input id="p" class="form-control" placeholder="请输入P值"/> |
| | |
| | | </div> |
| | | <div class="row top-buffer"> |
| | | <div class="col-md-6"> |
| | | <img class="thumbnail" id="imgContainer" style="width: 500px; height: 400px;padding: 5px 5px;"/> |
| | | </div> |
| | | <div class="col-md-6"> |
| | | <video id="video" muted autoplay loop controls style="width: 800px; height: 100%; object-fit: fill" /> |
| | | <img class="thumbnail" id="imgContainer" style="width: 500px; height: 300px;"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </body> |
| | | <div class="col-md-1"/> |
| | | <div class="col-md-5"> |
| | | <div class="row top-buffer"> |
| | | <video id="video" muted autoplay loop controls style="width: 800px; height: 100%; object-fit: fill;"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <script th:inline="javascript"> |
| | | var cameraId, opt, token; |
| | | window.onload = function () { |
| | |
| | | ipaddr: arr[i].ip, |
| | | username: arr[i].username, |
| | | password: arr[i].password, |
| | | port: arr[i].rtspPort |
| | | port: arr[i].rtspPort, |
| | | longitude: arr[i].longitude, |
| | | latitude: arr[i].latitude, |
| | | altitude: arr[i].altitude |
| | | }; |
| | | cameraMap.set(arr[i].id, camera); |
| | | //先创建好select里面的option元素 |
| | |
| | | 'Authorization': token |
| | | }, |
| | | url: "../hik/setPTZ", |
| | | type: "post", |
| | | dataType: "json", |
| | | data: JSON.stringify(myEntity), |
| | | success: function (data) { |
| | | console.log(data); |
| | | } |
| | | }) |
| | | }) |
| | | $("#setTargetPostion").click(function () { |
| | | cameraId = $('#select option:selected').val(); |
| | | var camera = cameraMap.get(cameraId); |
| | | var camP = camera.longitude + ',' + camera.latitude + ',' + camera.altitude; |
| | | var targetP = $('#targetPostion').val(); |
| | | //定义一个带有Map字段的实体对象 |
| | | var myEntity = { |
| | | channelNum: 1, |
| | | cameraId: cameraId, |
| | | targetPosition: targetP, |
| | | camPosition: camP, |
| | | }; |
| | | console.log(myEntity) |
| | | $.ajax({ |
| | | headers: { |
| | | 'Accept': 'application/json', |
| | | 'Content-Type': 'application/json', |
| | | 'Authorization': token |
| | | }, |
| | | url: "../hik/setTargetPosition", |
| | | type: "post", |
| | | dataType: "json", |
| | | data: JSON.stringify(myEntity), |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | let webRtcServer = null; |
| | | let videoMap = new Map(); |
| | | $('video').click(function (e) { |
| | |
| | | webRtcServer.disconnect(); |
| | | } |
| | | </script> |
| | | </body> |
| | | </html> |
| | |
| | | <link rel="stylesheet" th:href="@{/css/bootstrap.css}"/> |
| | | <script th:src="@{/js/bootstrap.js}"></script> |
| | | <style> |
| | | .top-buffer { margin-top:10px; } |
| | | .top-buffer { |
| | | margin-top: 10px; |
| | | } |
| | | </style> |
| | | <body> |
| | | <div class="container"> |
| | | <div class="row "> |
| | | <div class="dropdown"> |
| | | 相机id: |
| | | <select id="select"> |
| | | 相机id:<select id="select"> |
| | | </select> |
| | | </div> |
| | | </div> |
| | |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="row"> |
| | | <div class="col-md-6"> |
| | | <div class="row top-buffer"> |
| | | <div class="input-group"> |
| | | <span class="input-group-addon">目的坐标值:</span> |
| | | <input id="targetPostion" class="form-control" placeholder="目的坐标"/> |
| | | <button id="setTargetPostion" type="button" class="btn btn-default">指向坐标</button> |
| | | </div> |
| | | <div class="input-group"> |
| | | <span class="input-group-addon">P值:</span> |
| | | <input id="p" class="form-control" placeholder="请输入P值"/> |
| | |
| | | </div> |
| | | <div class="row top-buffer"> |
| | | <div class="col-md-6"> |
| | | <img class="thumbnail" id="imgContainer" style="width: 500px; height: 400px;padding: 5px 5px;"/> |
| | | </div> |
| | | <div class="col-md-6"> |
| | | <video id="video" muted autoplay loop controls style="width: 800px; height: 100%; object-fit: fill" /> |
| | | <img class="thumbnail" id="imgContainer" style="width: 500px; height: 300px;"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </body> |
| | | <div class="col-md-1"/> |
| | | <div class="col-md-5"> |
| | | <div class="row top-buffer"> |
| | | <video id="video" muted autoplay loop controls style="width: 800px; height: 100%; object-fit: fill;"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <script th:inline="javascript"> |
| | | var cameraId, opt, token; |
| | | window.onload = function () { |
| | |
| | | ipaddr: arr[i].ip, |
| | | username: arr[i].username, |
| | | password: arr[i].password, |
| | | port: arr[i].rtspPort |
| | | port: arr[i].rtspPort, |
| | | longitude: arr[i].longitude, |
| | | latitude: arr[i].latitude, |
| | | altitude: arr[i].altitude |
| | | }; |
| | | cameraMap.set(arr[i].id, camera); |
| | | //先创建好select里面的option元素 |
| | |
| | | 'Authorization': token |
| | | }, |
| | | url: "../hik/setPTZ", |
| | | type: "post", |
| | | dataType: "json", |
| | | data: JSON.stringify(myEntity), |
| | | success: function (data) { |
| | | console.log(data); |
| | | } |
| | | }) |
| | | }) |
| | | $("#setTargetPostion").click(function () { |
| | | cameraId = $('#select option:selected').val(); |
| | | var camera = cameraMap.get(cameraId); |
| | | var camP = camera.longitude + ',' + camera.latitude + ',' + camera.altitude; |
| | | var targetP = $('#targetPostion').val(); |
| | | //定义一个带有Map字段的实体对象 |
| | | var myEntity = { |
| | | channelNum: 1, |
| | | cameraId: cameraId, |
| | | targetPosition: targetP, |
| | | camPosition: camP, |
| | | }; |
| | | console.log(myEntity) |
| | | $.ajax({ |
| | | headers: { |
| | | 'Accept': 'application/json', |
| | | 'Content-Type': 'application/json', |
| | | 'Authorization': token |
| | | }, |
| | | url: "../hik/setTargetPosition", |
| | | type: "post", |
| | | dataType: "json", |
| | | data: JSON.stringify(myEntity), |
| | |
| | | } |
| | | }) |
| | | } |
| | | |
| | | let webRtcServer = null; |
| | | let videoMap = new Map(); |
| | | $('video').click(function (e) { |
| | |
| | | webRtcServer.disconnect(); |
| | | } |
| | | </script> |
| | | </body> |
| | | </html> |
| | |
| | | package com.ruoyi.framework.aspectj; |
| | | |
| | | import com.ruoyi.common.annotation.SdkOperate; |
| | | import com.ruoyi.common.core.domain.AjaxResult; |
| | | import com.ruoyi.common.core.domain.entity.SysUser; |
| | | import com.ruoyi.common.core.domain.model.LoginUser; |
| | | import com.ruoyi.common.utils.SecurityUtils; |
| | |
| | | import com.ruoyi.device.camera.domain.ArdCameras; |
| | | import com.ruoyi.device.camera.domain.CameraCmd; |
| | | import com.ruoyi.device.camera.service.IArdCamerasService; |
| | | import com.ruoyi.system.service.ISysUserService; |
| | | import org.aspectj.lang.JoinPoint; |
| | | import org.aspectj.lang.ProceedingJoinPoint; |
| | | import org.aspectj.lang.annotation.Around; |
| | | import org.aspectj.lang.annotation.Aspect; |
| | | import org.aspectj.lang.annotation.Before; |
| | | import org.aspectj.lang.annotation.Pointcut; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.annotation.Resource; |
| | | import java.util.Date; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * SDK控制处理 |
| | |
| | | |
| | | @Around("dsPointCut()") |
| | | public Object around(ProceedingJoinPoint point) throws Throwable { |
| | | |
| | | Boolean resultMap = dataScopeFilter(point); |
| | | if (resultMap) { |
| | | return point.proceed(); |
| | |
| | | * @param joinPoint 切点 |
| | | */ |
| | | public Boolean dataScopeFilter(ProceedingJoinPoint joinPoint) { |
| | | |
| | | //获取请求控制相机的信息 |
| | | CameraCmd cmd = (CameraCmd) joinPoint.getArgs()[0]; |
| | | ArdCameras ardCameras = ardCamerasService.selectArdCamerasById(cmd.getCameraId()); |
| | | if (StringUtils.isNull(ardCameras)) { |
| | | return false; |
| | | } |
| | | //优先级比对 |
| | | Date operatorExpired = ardCameras.getOperatorExpired(); |
| | | Date now = new Date(); |
| | | if (now.before(operatorExpired)) { |
| | | //未过期 |
| | | |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | if (StringUtils.isNull(loginUser)) { |
| | | return false;//当前登录用户为空不可以控制 |