123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- package com.persagy.cameractl.service;
- import com.hikvision.artemis.sdk.ArtemisHttpUtil;
- import com.hikvision.artemis.sdk.config.ArtemisConfig;
- import com.persagy.cameractl.conf.CameraApiConfig;
- import com.persagy.cameractl.utils.Camera;
- import com.persagy.cameractl.utils.CmdStreamThread;
- import com.persagy.cameractl.utils.EnumTools;
- import com.persagy.cameractl.utils.ResultClass;
- import com.persagy.cameractl.utils.JsonTools;
- import com.persagy.cameractl.utils.OtherTools;
- import cn.hutool.core.date.DateUtil;
- import java.io.File;
- import java.util.Date;
- import java.util.HashMap;
- import java.util.Map;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import net.sf.json.JSONObject;
- @Component
- public class HkCameraExecuteApi {
- Logger logger = LoggerFactory.getLogger(HkCameraExecuteApi.class);
- @Autowired
- private CameraApiConfig cameraApiConfig;
- /**
- * STEP2:设置OpenAPI接口的上下文
- */
- final String ARTEMIS_PATH = "/artemis/api/";
- /*
- * 解析返回结果
- * */
- private ResultClass parseResult(String resultStr) {
- ResultClass resultClass = new ResultClass();
- resultClass.name = false;
- try {
- if (resultStr == null || resultStr.equals("")) {
- resultClass.reason = "结果为空";
- return resultClass;
- }
- // org.springframework.boot.configurationprocessor.json.JSONObject resultMap=new
- // org.springframework.boot.configurationprocessor.json.JSONObject(resultStr);
- Map<String, Object> mapResult = JsonTools.str2Map(resultStr);
- String msgStr = String.valueOf(mapResult.get("msg"));
- if (msgStr == null || !msgStr.equals("success")) {
- resultClass.reason = "错误码:" + String.valueOf(mapResult.get("code")) + ",错误原因:"
- + String.valueOf(mapResult.get("msg"));
- return resultClass;
- }
- resultClass.name = true;
- resultClass.resultData = mapResult.get("data");
- return resultClass;
- } catch (Exception e) {
- logger.error("海康中心平台返回结果非法:" + resultStr);
- resultClass.reason = "海康中心平台返回结果非法,请查看后台日志";
- return resultClass;
- }
- };
- /*
- * 发送请求并解析返回结果
- * */
- private ResultClass SendRequest(String url, String paramString) {
- /**
- * STEP1:设置平台参数,根据实际情况,设置host appkey appsecret 三个参数.
- */
- ArtemisConfig.host = cameraApiConfig.getHkApiHost(); // artemis网关服务器ip端口
- ArtemisConfig.appKey = cameraApiConfig.getHkApiKey(); // 秘钥appkey
- ArtemisConfig.appSecret = cameraApiConfig.getHkApiSecret();// 秘钥appSecret
- /**
- * STEP3:设置接口的URI地址
- */
- String previewURLsApi = ARTEMIS_PATH + url;
- Map<String, String> path = new HashMap<String, String>(2) {
- /**
- *
- */
- private static final long serialVersionUID = 1L;
- {
- put("https://", previewURLsApi);// 根据现场环境部署确认是http还是https
- }
- };
- /**
- * STEP4:设置参数提交方式
- */
- String contentType = "application/json";
- /**
- * STEP6:调用接口
- */
- String result = ArtemisHttpUtil.doPostStringArtemis(path, paramString, null, null, contentType, null);// post请求application/json类型参数
- return parseResult(result);
- };
- /*
- * 根据监控点获取预览流
- */
- public ResultClass GetCameraPreviewURL(Camera hkCamera) {
- try {
- String url = "video/v2/cameras/previewURLs";
- /**
- * STEP5:组装请求参数
- */
- JSONObject jsonBody = new JSONObject();
- jsonBody.put("cameraIndexCode", hkCamera.cameraIndexCode);
- jsonBody.put("streamType", hkCamera.streamType);
- jsonBody.put("protocol", hkCamera.protocol);
- // 传输协议(传输层协议),0:UDP 1:TCP 默认是TCP 注:GB28181 2011及以前版本只支持UDP传输
- // jsonBody.put("transmode", 1);
- String expandStr = "transcode=" + hkCamera.transcode + "&resolution=" + hkCamera.resolution + "&bitrate="
- + hkCamera.bitrate + "&videotype=" + hkCamera.videotype;
- jsonBody.put("expand", expandStr);
- String body = jsonBody.toString();
- return SendRequest(url, body);
- } catch (Exception e) {
- logger.error("海康调用实时预览API出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用实时预览API出错");
- return resultClass;
- }
- }
- /*
- * 根据监控点获取回放流
- */
- public ResultClass GetCameraPlayBackURL(Camera hkCamera) {
- try {
- String reqUrl = "video/v2/cameras/playbackURLs";
- /**
- * STEP5:组装请求参数
- * 因为香港置地返回的回放rtsp流总是在剩余大概15秒的时候卡顿,所以传过去的结束时间要加30秒,所以ffmpeg命令里要用-t控制实际读取时长
- */
- Date dateStart = DateUtil.parse(hkCamera.startDateStr);
- long startMillSeconds = dateStart.getTime();
- Date dateEnd = DateUtil.parse(hkCamera.endDateStr);
- long endMillSeconds = dateEnd.getTime();
- // 先求得真实的回放时长
- long temp = endMillSeconds - startMillSeconds;
- long hourCount = 0;
- long minuteCount = 0;
- long secondCount = temp / 1000;
- long millSecondCount = temp % 1000;
- // 到了分钟级
- if (secondCount >= 60) {
- minuteCount = secondCount / 60;
- secondCount = secondCount % 60;
- // 到了小时级
- if (minuteCount >= 60) {
- hourCount = minuteCount / 60;
- minuteCount = minuteCount % 60;
- }
- }
- long endMillSeconds2 = endMillSeconds + 30 * 1000;
- Date enDate2 = DateUtil.date(endMillSeconds2);
- String endString2 = DateUtil.format(enDate2, "yyyy-MM-dd HH:mm:ss");
- JSONObject jsonBody = new JSONObject();
- jsonBody.put("cameraIndexCode", hkCamera.cameraIndexCode);
- jsonBody.put("protocol", hkCamera.protocol);
- jsonBody.put("beginTime", hkCamera.startDateStr.replace(" ", "T") + ".000+08:00");
- jsonBody.put("endTime", endString2.replace(" ", "T") + ".000+08:00");
- // 传输协议(传输层协议),0:UDP 1:TCP 默认是TCP 注:GB28181 2011及以前版本只支持UDP传输
- // jsonBody.put("transmode", 1);
- String expandStr = "transcode=" + hkCamera.transcode + "&resolution=" + hkCamera.resolution + "&bitrate="
- + hkCamera.bitrate + "&videotype=" + hkCamera.videotype;
- jsonBody.put("expand", expandStr);
- String body = jsonBody.toString();
- ResultClass resultClass = SendRequest(reqUrl, body);
- // return resultClass;
- // hls格式回放时,直接返回
- // if (hkCamera.protocol.equals("hls"))
- // return resultClass;
- /*
- * 如果不是hls格式,那么即为rtsp格式,此时需抓取rtsp流并转成mp4
- * */
- // 调用失败直接返回
- if (!resultClass.name)
- return resultClass;
- String resultDataStr = JsonTools.obj2Str(resultClass.resultData);
- Map<String, Object> resultDataMap = JsonTools.str2Map(resultDataStr);
- String videoUrl = String.valueOf(resultDataMap.get("url"));
- if (videoUrl == null || videoUrl.equals(""))
- return new ResultClass(false, "未获取到视频源地址");
- String playFilePath = OtherTools.getVideoFilePath();
- if (playFilePath.equals("")) {
- return new ResultClass(false, "回放文件名称生成失败");
- }
- // 抓取视频流转为页面上可播放的MP4
- Runtime run = Runtime.getRuntime();
- /*
- * stimeout、rw_timeout的单位为微秒 1秒=1000000微秒
- * 因为香港置地返回的回放rtsp流总是在剩余大概15秒的时候卡顿,所以传过去的结束时间要加30秒,所以ffmpeg命令里要用-t控制实际读取时长
- * */
- String timeDuration = hourCount + ":" + minuteCount + ":" + secondCount
- + (millSecondCount > 0 ? "." + millSecondCount : "");
- String cmdStr = hkCamera.protocol.equals("hls")
- ? ("ffmpeg -i \"" + videoUrl + "\" -c copy -y \"" + playFilePath + "\"")
- : ("ffmpeg -t " + timeDuration + " -rtsp_transport tcp -i \"" + videoUrl + "\" -y \"" + playFilePath
- + "\"");
- Process p = run.exec(cmdStr);
- // 读取标准输入流、输出流,防止进程阻塞
- CmdStreamThread cmdStreamThread = new CmdStreamThread(p.getInputStream(), p.getErrorStream());
- int retCode = p.waitFor();
- p.destroy();
- if (retCode == 0) {
- // 正常转换结束
- File mp4File = new File(playFilePath);
- String playFileName = mp4File.getName();
- String token = OtherTools.getMp4NamePrefix(playFileName);
- String url = OtherTools.playMp4RootUrl + token;
- Map<String, String> dataMap = new HashMap<String, String>();
- dataMap.put("url", url);
- dataMap.put("videoUrl", videoUrl);
- return new ResultClass(true, dataMap);
- } else {
- // 转换出错
- String errStr = cmdStreamThread.errString != null ? cmdStreamThread.errString
- : cmdStreamThread.outString;
- logger.error("ffmpeg抓取rtsp转为mp4时失败,错误信息:" + errStr);
- return new ResultClass(false, "ffmpeg抓取rtsp转为mp4时失败");
- }
- } catch (Exception e) {
- logger.error("海康调用回调API出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用回调API出错");
- return resultClass;
- }
- }
- /*
- * 控制命令入口
- * */
- public ResultClass PtzControllingMain(Camera hkCamera) {
- // 开始控制命令
- ResultClass startResultClass = PtzControlling(hkCamera, 0);
- // 控制命令执行成功后要调用停止命令
- if (startResultClass.name) {
- // 停止控制
- ResultClass endResultClass = PtzControlling(hkCamera, 1);
- return endResultClass;
- }
- return startResultClass;
- }
- /*
- * 根据监控点进行云台控制
- */
- private ResultClass PtzControlling(Camera hkCamera, int action) {
- try {
- String url = "video/v1/ptzs/controlling";
- /**
- * STEP5:组装请求参数
- */
- JSONObject jsonBody = new JSONObject();
- jsonBody.put("cameraIndexCode", hkCamera.cameraIndexCode);
- // 0 开始 1 停止
- jsonBody.put("action", action);
- int sdkCommandIndex = EnumTools.listSdkCommand.indexOf(hkCamera.command);
- if (sdkCommandIndex == -1)
- return new ResultClass(false, "无效的控制命令");
- String commandStr = EnumTools.arrHkvisionCommand[sdkCommandIndex];
- jsonBody.put("command", commandStr);
- jsonBody.put("speed", hkCamera.speed);
- String body = jsonBody.toString();
- ResultClass resultClass = SendRequest(url, body);
- return resultClass;
- } catch (Exception e) {
- String str = action == 0 ? "开始时" : "停止时";
- logger.error("海康调用控制API," + str + "出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用控制API" + str + "出错");
- return resultClass;
- }
- }
- /* 分页获取监控点 */
- public ResultClass GetCameraPointsByPage(Camera hkCamera) {
- try {
- String url = "resource/v1/cameras";
- /**
- * STEP5:组装请求参数
- */
- JSONObject jsonBody = new JSONObject();
- jsonBody.put("pageNo", hkCamera.pageNo);
- jsonBody.put("pageSize", hkCamera.pageSize);
- String body = jsonBody.toString();
- return SendRequest(url, body);
- } catch (Exception e) {
- logger.error("海康调用分页获取监控点API出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用分页获取监控点API出错");
- return resultClass;
- }
- }
- /*
- * 获取access_token
- */
- public ResultClass GetAccessToken(Camera hkCamera) {
- try {
- String url = "v1/oauth/token";
- /**
- * STEP5:组装请求参数
- */
- JSONObject jsonBody = new JSONObject();
- String body = jsonBody.toString();
- return SendRequest(url, body);
- } catch (Exception e) {
- logger.error("海康调用access_token API出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用access_token API出错");
- return resultClass;
- }
- }
- /*
- * 获取电视墙大屏信息
- */
- public ResultClass GetDianshiQiang(Camera hkCamera) {
- try {
- String url = "tvms/v1/tvwall/allResources";
- /**
- * STEP5:组装请求参数
- */
- JSONObject jsonBody = new JSONObject();
- String body = jsonBody.toString();
- ResultClass resultClass = SendRequest(url, body);
- return resultClass;
- } catch (Exception e) {
- logger.error("海康调用电视墙大屏API出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用电视墙大屏API出错");
- return resultClass;
- }
- }
- /*
- * 传入接口名称和参数,方便客户端调用测试
- */
- public ResultClass GetOtherInfo(Camera hkCamera) {
- try {
- String paramStr = "";
- if (hkCamera.paramStr != null && !"".equals(hkCamera.paramStr)) {
- JSONObject jsonBody = new JSONObject();
- Map<String, Object> tempMap = JsonTools.str2Map(hkCamera.paramStr);
- for (Map.Entry<String, Object> entry : tempMap.entrySet()) {
- jsonBody.put(entry.getKey(), entry.getValue());
- }
- paramStr = jsonBody.toString();
- }
- ResultClass resultClass = SendRequest(hkCamera.url, paramStr);
- return resultClass;
- } catch (Exception e) {
- logger.error("海康" + hkCamera.url + "出错:", e);
- ResultClass resultClass = new ResultClass(false, "海康调用" + hkCamera.url + "出错");
- return resultClass;
- }
- }
- }
|