对需要向设备发起请求的http请求,使用缓存,等待设备请求返回的时候一次性释放所有请求
17个文件已修改
646 ■■■■■ 已修改文件
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java 66 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java 26 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java 189 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java 11 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java 24 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java 74 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java 52 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java 50 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
web_src/src/components/MediaServerManger.vue 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
@@ -13,7 +13,9 @@
public class RecordInfo {
    private String deviceId;
    private String channelId;
    private String name;
    
    private int sumNum;
@@ -52,4 +54,11 @@
        this.recordList = recordList;
    }
    public String getChannelId() {
        return channelId;
    }
    public void setChannelId(String channelId) {
        this.channelId = channelId;
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
@@ -54,11 +54,9 @@
        // 自然顺序排序, 元素进行升序排列
        this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
        RequestMessage msg = new RequestMessage();
        String deviceId = recordInfo.getDeviceId();
        msg.setDeviceId(deviceId);
        msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getChannelId());
        msg.setData(recordInfo);
        deferredResultHolder.invokeResult(msg);
        deferredResultHolder.invokeAllResult(msg);
        logger.info("处理完成,返回结果");
        MessageRequestProcessor.threadNameList.remove(cacheKey);
    }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
@@ -1,6 +1,8 @@
package com.genersoft.iot.vmp.gb28181.transmit.callback;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.http.HttpStatus;
@@ -45,22 +47,72 @@
    public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST";
    private Map<String, DeferredResult> map = new ConcurrentHashMap<String, DeferredResult>();
    private Map<String, Map<String, DeferredResult>> map = new ConcurrentHashMap<>();
    public void put(String key, DeferredResult result) {
        map.put(key, result);
    public void put(String key, String id, DeferredResult result) {
        Map<String, DeferredResult> deferredResultMap = map.get(key);
        if (deferredResultMap == null) {
            deferredResultMap = new ConcurrentHashMap<>();
            map.put(key, deferredResultMap);
        }
        deferredResultMap.put(id, result);
    }
    
    public DeferredResult get(String key) {
        return map.get(key);
    public DeferredResult get(String key, String id) {
        Map<String, DeferredResult> deferredResultMap = map.get(key);
        if (deferredResultMap == null) return null;
        return deferredResultMap.get(id);
    }
    public boolean exist(String key, String id){
        if (key == null) return false;
        Map<String, DeferredResult> deferredResultMap = map.get(key);
        if (id == null) {
            return deferredResultMap != null;
        }else {
            return deferredResultMap != null && deferredResultMap.get(id) != null;
        }
    }
    /**
     * 释放单个请求
     * @param msg
     */
    public void invokeResult(RequestMessage msg) {
        DeferredResult result = map.get(msg.getId());
        Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
        if (deferredResultMap == null) {
            return;
        }
        DeferredResult result = deferredResultMap.get(msg.getId());
        if (result == null) {
            return;
        }
        result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
        deferredResultMap.remove(msg.getId());
        if (deferredResultMap.size() == 0) {
            map.remove(msg.getKey());
        }
    }
    /**
     * 释放所有的请求
     * @param msg
     */
    public void invokeAllResult(RequestMessage msg) {
        Map<String, DeferredResult> deferredResultMap = map.get(msg.getKey());
        if (deferredResultMap == null) {
            return;
        }
        Set<String> ids = deferredResultMap.keySet();
        for (String id : ids) {
            DeferredResult result = deferredResultMap.get(id);
            if (result == null) {
                return;
            }
            result.setResult(new ResponseEntity<>(msg.getData(),HttpStatus.OK));
        }
        map.remove(msg.getKey());
    }
}
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java
@@ -9,12 +9,10 @@
    
    private String id;
    private String deviceId;
    private String type;
    private String key;
    private Object data;
    public String getId() {
        return id;
    }
@@ -23,22 +21,12 @@
        this.id = id;
    }
    public String getDeviceId() {
        return deviceId;
    public void setKey(String key) {
        this.key = key;
    }
    public void setDeviceId(String deviceId) {
        this.deviceId = deviceId;
        this.id = type + deviceId;
    }
    public String getType() {
        return type;
    }
    public void setType(String type) {
        this.type = type;
        this.id = type + deviceId;
    public String getKey() {
        return key;
    }
    public Object getData() {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -173,12 +173,12 @@
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理MobilePosition移动位置消息时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt, device.getCharset());
            MobilePosition mobilePosition = new MobilePosition();
            Element deviceIdElement = rootElement.element("DeviceID");
            if (!StringUtils.isEmpty(device.getName())) {
                mobilePosition.setDeviceName(device.getName());
            }
@@ -227,11 +227,17 @@
     */
    private void processMessageDeviceStatus(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceStatus设备状态Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String name = rootElement.getName();
            Element deviceIdElement = rootElement.element("DeviceID");
            String deviceId = deviceIdElement.getText();
            Device device = storager.queryVideoDevice(deviceId);
            String channelId = deviceIdElement.getText();
            if (name.equalsIgnoreCase("Query")) { // 区分是Response——查询响应,还是Query——查询请求
                logger.info("接收到DeviceStatus查询消息");
                FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
@@ -258,10 +264,9 @@
                        logger.debug(json.toJSONString());
                    }
                    RequestMessage msg = new RequestMessage();
                    msg.setDeviceId(deviceId);
                    msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS);
                    msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId + channelId);
                    msg.setData(json);
                    deferredResultHolder.invokeResult(msg);
                    deferredResultHolder.invokeAllResult(msg);
                    if (offLineDetector.isOnline(deviceId)) {
                        publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE);
@@ -282,8 +287,15 @@
     */
    private void processMessageDeviceControl(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceControl设备状态Message未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            //String result = XmlUtil.getText(rootElement, "Result");
            // 回复200 OK
            responseAck(evt);
@@ -295,10 +307,10 @@
                    logger.debug(json.toJSONString());
                }
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL);
                String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL +  deviceId + channelId;
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                // 此处是上级发出的DeviceControl指令
                String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();
@@ -344,8 +356,8 @@
                // 云台/前端控制命令
                if (!StringUtils.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) {
                    String cmdString = XmlUtil.getText(rootElement,"PTZCmd");
                    Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
                    cmder.fronEndCmd(device, deviceId, cmdString);
                    Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId);
                    cmder.fronEndCmd(deviceForPlatform, deviceId, cmdString);
                }
            }
        } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
@@ -360,8 +372,16 @@
     */
    private void processMessageDeviceConfig(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceConfig设备状态Message消息时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            // 回复200 OK
            responseAck(evt);
            if (rootElement.getName().equals("Response")) {
@@ -371,11 +391,11 @@
                if (logger.isDebugEnabled()) {
                    logger.debug(json.toJSONString());
                }
                String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG);
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                // 此处是上级发出的DeviceConfig指令
            }
@@ -391,8 +411,17 @@
     */
    private void processMessageConfigDownload(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理ConfigDownload设备状态Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + deviceId + channelId;
            // 回复200 OK
            responseAck(evt);
            if (rootElement.getName().equals("Response")) {
@@ -403,10 +432,9 @@
                    logger.debug(json.toJSONString());
                }
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD);
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                // 此处是上级发出的DeviceConfig指令
            }
@@ -422,8 +450,17 @@
     */
    private void processMessagePresetQuery(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理PresetQuery预置位列表Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            String key = DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + deviceId + channelId;
            // 回复200 OK
            responseAck(evt);
            if (rootElement.getName().equals("Response")) {//   !StringUtils.isEmpty(result)) {
@@ -434,10 +471,9 @@
                    logger.debug(json.toJSONString());
                }
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY);
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                // 此处是上级发出的DeviceControl指令
            }
@@ -453,11 +489,19 @@
     */
    private void processMessageDeviceInfo(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String requestName = rootElement.getName();
            Element deviceIdElement = rootElement.element("DeviceID");
            String deviceId = deviceIdElement.getTextTrim();
            Device device = storager.queryVideoDevice(deviceId);
            String channelId = deviceIdElement.getTextTrim();
            String key = DeferredResultHolder.CALLBACK_CMD_DEVICEINFO + deviceId + channelId;
            if (device != null ) {
                rootElement = getRootElement(evt, device.getCharset());
            }
@@ -492,10 +536,9 @@
                storager.updateDevice(device);
    
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_DEVICEINFO);
                msg.setKey(key);
                msg.setData(device);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
                // 回复200 OK
                responseAck(evt);
                if (offLineDetector.isOnline(deviceId)) {
@@ -514,12 +557,22 @@
     */
    private void processMessageCatalogList(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String name = rootElement.getName();
            Element deviceIdElement = rootElement.element("DeviceID");
            String deviceId = deviceIdElement.getText();
            String channelId = deviceIdElement.getText();
            Element deviceListElement = rootElement.element("DeviceList");
            String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
            FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME);
            AddressImpl address = (AddressImpl) fromHeader.getAddress();
            SipUri uri = (SipUri) address.getURI();
@@ -581,10 +634,6 @@
            } else {
                Device device = storager.queryVideoDevice(deviceId);
                if (device == null) {
                    return;
                }
                deviceListElement = getRootElement(evt, device.getCharset()).element("DeviceList");
                Iterator<Element> deviceListIterator = deviceListElement.elementIterator();
                if (deviceListIterator != null) {
@@ -674,10 +723,9 @@
                    }
                    RequestMessage msg = new RequestMessage();
                    msg.setDeviceId(deviceId);
                    msg.setType(DeferredResultHolder.CALLBACK_CMD_CATALOG);
                    msg.setKey(key);
                    msg.setData(device);
                    deferredResultHolder.invokeResult(msg);
                    deferredResultHolder.invokeAllResult(msg);
                    // 回复200 OK
                    responseAck(evt);
                    if (offLineDetector.isOnline(deviceId)) {
@@ -701,11 +749,13 @@
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理alarm设备报警信息未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt, device.getCharset());
            Element deviceIdElement = rootElement.element("DeviceID");
            String channelId = deviceIdElement.getText().toString();
            String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId + channelId;
            // 回复200 OK
            responseAck(evt);
@@ -770,10 +820,9 @@
                    logger.debug(json.toJSONString());
                }
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_ALARM);
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            }
        } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) {
            e.printStackTrace();
@@ -787,9 +836,13 @@
     */
    private void processMessageKeepAlive(RequestEvent evt) {
        try {
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            Element rootElement = getRootElement(evt);
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            // 检查设备是否存在并在线, 不在线则设置为在线
            if (device != null ) {
@@ -831,18 +884,29 @@
     */
    private void processMessageRecordInfo(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            // 回复200 OK
            responseAck(evt);
            String uuid = UUID.randomUUID().toString().replace("-", "");
            RecordInfo recordInfo = new RecordInfo();
            Element rootElement = getRootElement(evt);
            Element deviceIdElement = rootElement.element("DeviceID");
            String deviceId = deviceIdElement.getText().toString();
            Device device = storager.queryVideoDevice(deviceId);
            String channelId = deviceIdElement.getText().toString();
            String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
            if (device != null ) {
                rootElement = getRootElement(evt, device.getCharset());
            }
            recordInfo.setDeviceId(deviceId);
            recordInfo.setChannelId(channelId);
            recordInfo.setName(XmlUtil.getText(rootElement, "Name"));
            if (XmlUtil.getText(rootElement, "SumNum")== null || XmlUtil.getText(rootElement, "SumNum") =="") {
                recordInfo.setSumNum(0);
@@ -854,10 +918,9 @@
            if (recordListElement == null || recordInfo.getSumNum() == 0) {
                logger.info("无录像数据");
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
                msg.setKey(key);
                msg.setData(recordInfo);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                Iterator<Element> recordListIterator = recordListElement.elementIterator();
                List<RecordItem> recordList = new ArrayList<RecordItem>();
@@ -956,10 +1019,20 @@
      */
    private void processMessageMediaStatus(RequestEvent evt){
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            // 回复200 OK
            responseAck(evt);
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            String NotifyType =XmlUtil.getText(rootElement, "NotifyType");
            if (NotifyType.equals("121")){
                logger.info("媒体播放完毕,通知关流");
@@ -981,8 +1054,19 @@
     */
    private void processMessageBroadcast(RequestEvent evt) {
        try {
            String deviceId = SipUtils.getUserIdFromFromHeader(evt.getRequest());
            // 查询设备是否存在
            Device device = storager.queryVideoDevice(deviceId);
            if (device == null) {
                logger.warn("处理DeviceInfo设备信息Message时未找到设备信息");
                response404Ack(evt);
                return;
            }
            Element rootElement = getRootElement(evt);
            String deviceId = XmlUtil.getText(rootElement, "DeviceID");
            String channelId = XmlUtil.getText(rootElement, "DeviceID");
            String key = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId + channelId;
            // 回复200 OK
            responseAck(evt);
            if (rootElement.getName().equals("Response")) {
@@ -993,10 +1077,9 @@
                    logger.debug(json.toJSONString());
                }
                RequestMessage msg = new RequestMessage();
                msg.setDeviceId(deviceId);
                msg.setType(DeferredResultHolder.CALLBACK_CMD_BROADCAST);
                msg.setKey(key);
                msg.setData(json);
                deferredResultHolder.invokeResult(msg);
                deferredResultHolder.invokeAllResult(msg);
            } else {
                // 此处是上级发出的Broadcast指令
            }
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -78,9 +78,11 @@
    @Override
    public PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) {
        PlayResult playResult = new PlayResult();
        RequestMessage msg = new RequestMessage();
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
        msg.setKey(key);
        msg.setId(playResult.getUuid());
        if (mediaServerItem == null) {
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + playResult.getUuid());
            WVPResult wvpResult = new WVPResult();
            wvpResult.setCode(-1);
            wvpResult.setMsg("未找到可用的zlm");
@@ -88,20 +90,19 @@
            resultHolder.invokeResult(msg);
            return playResult;
        }
        Device device = storager.queryVideoDevice(deviceId);
        StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
        playResult.setDevice(device);
        UUID uuid = UUID.randomUUID();
        playResult.setUuid(uuid.toString());
        String uuid = UUID.randomUUID().toString();
        playResult.setUuid(uuid);
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(userSetup.getPlayTimeout());
        playResult.setResult(result);
        // 录像查询以channelId作为deviceId查询
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
        resultHolder.put(key, uuid, result);
        // 超时处理
        result.onTimeout(()->{
            logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + playResult.getUuid());
            WVPResult wvpResult = new WVPResult();
            wvpResult.setCode(-1);
            SIPDialog dialog = streamSession.getDialog(deviceId, channelId);
@@ -115,7 +116,8 @@
            cmder.streamByeCmd(device.getDeviceId(), channelId);
            // 释放rtpserver
            mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
            resultHolder.invokeResult(msg);
            // 回复之前所有的点播请求
            resultHolder.invokeAllResult(msg);
        });
        result.onCompletion(()->{
            // 点播结束时调用截图接口
@@ -169,15 +171,13 @@
                }
            }, (event) -> {
                // 点播返回sip错误
                RequestMessage msg = new RequestMessage();
                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                Response response = event.getResponse();
                mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
                WVPResult wvpResult = new WVPResult();
                wvpResult.setCode(-1);
                wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
                msg.setData(wvpResult);
                resultHolder.invokeResult(msg);
                resultHolder.invokeAllResult(msg);
                if (errorEvent != null) {
                    errorEvent.response(event);
                }
@@ -186,13 +186,11 @@
        } else {
            String streamId = streamInfo.getStreamId();
            if (streamId == null) {
                RequestMessage msg = new RequestMessage();
                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                WVPResult wvpResult = new WVPResult();
                wvpResult.setCode(-1);
                wvpResult.setMsg(String.format("点播失败, redis缓存streamId等于null"));
                msg.setData(wvpResult);
                resultHolder.invokeResult(msg);
                resultHolder.invokeAllResult(msg);
                return playResult;
            }
            String mediaServerId = streamInfo.getMediaServerId();
@@ -200,8 +198,6 @@
            JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId);
            if (rtpInfo != null && rtpInfo.getBoolean("exist")) {
                RequestMessage msg = new RequestMessage();
                msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                WVPResult wvpResult = new WVPResult();
                wvpResult.setCode(0);
@@ -209,7 +205,7 @@
                wvpResult.setData(streamInfo);
                msg.setData(wvpResult);
                resultHolder.invokeResult(msg);
                resultHolder.invokeAllResult(msg);
                if (hookEvent != null) {
                    hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo)));
                }
@@ -229,15 +225,13 @@
                    onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString());
                }, (event) -> {
                    mediaServerService.closeRTPServer(playResult.getDevice(), channelId);
                    RequestMessage msg = new RequestMessage();
                    msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
                    Response response = event.getResponse();
                    WVPResult wvpResult = new WVPResult();
                    wvpResult.setCode(-1);
                    wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
                    msg.setData(wvpResult);
                    resultHolder.invokeResult(msg);
                    resultHolder.invokeAllResult(msg);
                });
            }
        }
@@ -248,7 +242,8 @@
    @Override
    public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
        RequestMessage msg = new RequestMessage();
        msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
        msg.setId(uuid);
        msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
        StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
        if (streamInfo != null) {
            DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
@@ -265,11 +260,11 @@
            wvpResult.setData(streamInfo);
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        } else {
            logger.warn("设备预览API调用失败!");
            msg.setData("设备预览API调用失败!");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        }
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java
@@ -1,6 +1,7 @@
package com.genersoft.iot.vmp.vmanager.gb28181.MobilePosition;
import java.util.List;
import java.util.UUID;
import javax.sip.message.Response;
@@ -111,10 +112,13 @@
    @GetMapping("/realtime/{deviceId}")
    public DeferredResult<ResponseEntity<MobilePosition>> realTimePosition(@PathVariable String deviceId) {
        Device device = storager.queryVideoDevice(deviceId);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId;
        cmder.mobilePostitionQuery(device, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_MOBILEPOSITION + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("获取移动位置信息失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -123,11 +127,12 @@
            logger.warn(String.format("获取移动位置信息超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
        resultHolder.put(key, uuid, result);
        return result;
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java
@@ -28,6 +28,8 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.UUID;
@Api(tags = "国标设备配置")
@CrossOrigin
@RestController
@@ -66,7 +68,7 @@
            @ApiImplicitParam(name = "heartBeatCount", value ="心跳计数" ,dataTypeClass = String.class),
    })
    public DeferredResult<ResponseEntity<String>> homePositionApi(@PathVariable String deviceId,
                                                                @RequestParam(required = false) String channelId,
                                                                   String channelId,
                                                                @RequestParam(required = false) String name,
                                                                @RequestParam(required = false) String expiration,
                                                                @RequestParam(required = false) String heartBeatInterval,
@@ -75,10 +77,13 @@
            logger.debug("报警复位API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + deviceId + channelId;
        cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("设备配置操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -87,7 +92,8 @@
            logger.warn(String.format("设备配置操作超时, 设备未返回应答指令"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("Status", "Timeout");
@@ -95,7 +101,7 @@
            msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
        resultHolder.put(key, uuid, result);
        return result;
    }
@@ -119,11 +125,14 @@
        if (logger.isDebugEnabled()) {
            logger.debug("设备状态查询API调用");
        }
        String key = DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
        String uuid = UUID.randomUUID().toString();
        Device device = storager.queryVideoDevice(deviceId);
        cmder.deviceConfigQuery(device, channelId, configType, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("获取设备配置失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -132,11 +141,12 @@
            logger.warn(String.format("获取设备配置超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout. Device did not response to this command.");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
        resultHolder.put(key, uuid, result);
        return result;
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -29,6 +29,8 @@
import org.springframework.web.bind.annotation.*;
import org.springframework.web.context.request.async.DeferredResult;
import java.util.UUID;
@Api(tags = "国标设备控制")
@CrossOrigin
@RestController
@@ -89,28 +91,36 @@
    })
    @GetMapping("/record/{deviceId}/{recordCmdStr}")
    public DeferredResult<ResponseEntity<String>> recordApi(@PathVariable String deviceId,
            @PathVariable String recordCmdStr, @RequestParam(required = false) String channelId) {
            @PathVariable String recordCmdStr, String channelId) {
        if (logger.isDebugEnabled()) {
            logger.debug("开始/停止录像API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        cmder.recordCmd(device, channelId, recordCmdStr, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL +  deviceId + channelId;
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
        result.onTimeout(() -> {
            logger.warn(String.format("开始/停止录像操作超时, 设备未返回应答指令"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setKey(key);
            msg.setId(uuid);
            msg.setData("Timeout. Device did not response to this command.");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
        resultHolder.put(key, uuid, result);
        if (resultHolder.exist(key, null)){
            return result;
        }
        cmder.recordCmd(device, channelId, recordCmdStr, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeAllResult(msg);
        });
        return result;
    }
@@ -123,32 +133,38 @@
    @ApiOperation("布防/撤防命令")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
            @ApiImplicitParam(name = "guardCmdStr", value ="命令, 可选值:SetGuard(布防),ResetGuard(撤防)", required = true,
                    dataTypeClass = String.class)
    })
    @GetMapping("/guard/{deviceId}/{guardCmdStr}")
    public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, @PathVariable String guardCmdStr) {
    public DeferredResult<ResponseEntity<String>> guardApi(@PathVariable String deviceId, String channelId, @PathVariable String guardCmdStr) {
        if (logger.isDebugEnabled()) {
            logger.debug("布防/撤防API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
        String uuid =UUID.randomUUID().toString();
        cmder.guardCmd(device, guardCmdStr, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
        resultHolder.put(key, uuid, result);
        result.onTimeout(() -> {
            logger.warn(String.format("布防/撤防操作超时, 设备未返回应答指令"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
            msg.setKey(key);
            msg.setId(uuid);
            msg.setData("Timeout. Device did not response to this command.");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
        return result;
    }
@@ -162,21 +178,25 @@
    @ApiOperation("报警复位")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
            @ApiImplicitParam(name = "alarmMethod", value ="报警方式", dataTypeClass = String.class),
            @ApiImplicitParam(name = "alarmType", value ="报警类型", dataTypeClass = String.class),
    })
    @GetMapping("/reset_alarm/{deviceId}")
    public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId,
    public DeferredResult<ResponseEntity<String>> resetAlarmApi(@PathVariable String deviceId, String channelId,
                                                                @RequestParam(required = false) String alarmMethod,
                                                                @RequestParam(required = false) String alarmType) {
        if (logger.isDebugEnabled()) {
            logger.debug("报警复位API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId + channelId;
        cmder.alarmCmd(device, alarmMethod, alarmType, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("报警复位操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -185,11 +205,12 @@
            logger.warn(String.format("报警复位操作超时, 设备未返回应答指令"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout. Device did not response to this command.");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + deviceId, result);
        resultHolder.put(key, uuid, result);
        return result;
    }
@@ -236,6 +257,7 @@
    @ApiOperation("看守位控制")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "deviceId", value = "设备ID", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "channelId", value ="通道编码" ,dataTypeClass = String.class),
            @ApiImplicitParam(name = "enabled", value = "是否开启看守位 1:开启,0:关闭", required = true, dataTypeClass = String.class),
            @ApiImplicitParam(name = "resetTime", value = "自动归位时间间隔", dataTypeClass = String.class),
            @ApiImplicitParam(name = "presetIndex", value = "调用预置位编号", dataTypeClass = String.class),
@@ -246,15 +268,18 @@
                                                                @PathVariable String enabled,
                                                                @RequestParam(required = false) String resetTime,
                                                                @RequestParam(required = false) String presetIndex,
                                                                @RequestParam(required = false) String channelId) {
                                                                String channelId) {
        if (logger.isDebugEnabled()) {
            logger.debug("报警复位API调用");
        }
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
        String uuid = UUID.randomUUID().toString();
        Device device = storager.queryVideoDevice(deviceId);
        cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -263,7 +288,8 @@
            logger.warn(String.format("看守位控制操作超时, 设备未返回应答指令"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("Status", "Timeout");
@@ -271,7 +297,7 @@
            msg.setData(json); //("看守位控制操作超时, 设备未返回应答指令");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
        resultHolder.put(key, uuid, result);
        return result;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -24,6 +24,7 @@
import javax.sip.message.Response;
import java.io.UnsupportedEncodingException;
import java.util.UUID;
@Api(tags = "国标设备查询", value = "国标设备查询")
@SuppressWarnings("rawtypes")
@@ -143,23 +144,32 @@
            logger.debug("设备通道信息同步API调用,deviceId:" + deviceId);
        }
        Device device = storager.queryVideoDevice(deviceId);
        cmder.catalogQuery(device, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
            msg.setData(String.format("同步通道失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
        DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(15*1000L);
        String key = DeferredResultHolder.CALLBACK_CMD_CATALOG + deviceId;
        String uuid = UUID.randomUUID().toString();
        DeferredResult<ResponseEntity<Device>> result = new DeferredResult<ResponseEntity<Device>>(15*1000L);
        result.onTimeout(()->{
            logger.warn(String.format("设备通道信息同步超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId);
            msg.setKey(key);
            msg.setId(uuid);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CATALOG+deviceId, result);
        // 等待其他相同请求返回时一起返回
        if (resultHolder.exist(key, null)) {
            return result;
        }
        cmder.catalogQuery(device, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setKey(key);
            msg.setId(uuid);
            msg.setData(String.format("同步通道失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeAllResult(msg);
        });
        resultHolder.put(key, uuid, result);
        return result;
    }
@@ -316,10 +326,13 @@
            logger.debug("设备状态查询API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId;
        cmder.deviceStatusQuery(device, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("获取设备状态失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -328,11 +341,12 @@
            logger.warn(String.format("获取设备状态超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout. Device did not response to this command.");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, result);
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + deviceId, uuid, result);
        return result;
    }
@@ -369,10 +383,13 @@
            logger.debug("设备报警查询API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        String key = DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId;
        String uuid = UUID.randomUUID().toString();
        cmder.alarmInfoQuery(device, startPriority, endPriority, alarmMethod, alarmType, startTime, endTime, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("设备报警查询失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
@@ -381,11 +398,12 @@
            logger.warn(String.format("设备报警查询超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("设备报警查询超时");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, result);
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_ALARM + deviceId, uuid, result);
        return result;
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -103,28 +103,31 @@
        logger.debug(String.format("设备预览/回放停止API调用,streamId:%s_%s", deviceId, channelId ));
        UUID uuid = UUID.randomUUID();
        String uuid = UUID.randomUUID().toString();
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
        // 录像查询以channelId作为deviceId查询
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result);
        String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
        resultHolder.put(key, uuid, result);
        Device device = storager.queryVideoDevice(deviceId);
        cmder.streamByeCmd(deviceId, channelId, (event) -> {
            StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
            if (streamInfo == null) {
                RequestMessage msg = new RequestMessage();
                msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
                msg.setId(uuid);
                msg.setKey(key);
                msg.setData("点播未找到");
                resultHolder.invokeResult(msg);
                resultHolder.invokeAllResult(msg);
                storager.stopPlay(deviceId, channelId);
            }else {
                redisCatchStorage.stopPlay(streamInfo);
                storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
                RequestMessage msg = new RequestMessage();
                msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
                msg.setId(uuid);
                msg.setKey(key);
                //Response response = event.getResponse();
                msg.setData(String.format("success"));
                resultHolder.invokeResult(msg);
                resultHolder.invokeAllResult(msg);
            }
            mediaServerService.closeRTPServer(device, channelId);
        });
@@ -134,24 +137,27 @@
            json.put("deviceId", deviceId);
            json.put("channelId", channelId);
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(json.toString());
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        } else {
            logger.warn("设备预览/回放停止API调用失败!");
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("streamId null");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        }
        // 超时处理
        result.onTimeout(()->{
            logger.warn(String.format("设备预览/回放停止超时,deviceId/channelId:%s_%s ", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        });
        return result;
    }
@@ -259,10 +265,18 @@
        }
        Device device = storager.queryVideoDevice(deviceId);
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(3 * 1000L);
        String key  = DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId;
        if (resultHolder.exist(key, null)) {
            result.setResult(new ResponseEntity<>("设备使用中",HttpStatus.OK));
            return result;
        }
        String uuid  = UUID.randomUUID().toString();
        if (device == null) {
            resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result);
            resultHolder.put(key, key,  result);
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
            msg.setKey(key);
            msg.setId(uuid);
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("CmdType", "Broadcast");
@@ -275,7 +289,8 @@
        cmder.audioBroadcastCmd(device, (event) -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
            msg.setKey(key);
            msg.setId(uuid);
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("CmdType", "Broadcast");
@@ -288,7 +303,8 @@
        result.onTimeout(() -> {
            logger.warn(String.format("语音广播操作超时, 设备未返回应答指令"));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId);
            msg.setKey(key);
            msg.setId(uuid);
            JSONObject json = new JSONObject();
            json.put("DeviceID", deviceId);
            json.put("CmdType", "Broadcast");
@@ -297,7 +313,7 @@
            msg.setData(json);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId, result);
        resultHolder.put(key, uuid, result);
        return result;
    }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
@@ -76,30 +76,37 @@
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed));
        }
        UUID uuid = UUID.randomUUID();
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime;
        String uuid = UUID.randomUUID().toString();
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
        // 超时处理
        result.onTimeout(()->{
            logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        });
        resultHolder.put(key, uuid, result);
        if(resultHolder.exist(key, null)) {
            return result;
        }
        Device device = storager.queryVideoDevice(deviceId);
        StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
        if (streamInfo != null) {
            // 停止之前的下载
            cmder.streamByeCmd(deviceId, channelId);
        }
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
        MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
        if (newMediaServerItem == null) {
            logger.warn(String.format("设备下载响应超时,deviceId:%s ,channelId:%s", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
            return result;
        }
@@ -111,9 +118,10 @@
        }, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("回放失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
            resultHolder.invokeAllResult(msg);
        });
        return result;
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -76,9 +76,9 @@
        if (logger.isDebugEnabled()) {
            logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
        }
        UUID uuid = UUID.randomUUID();
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime;
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
        Device device = storager.queryVideoDevice(deviceId);
        if (device == null) {
            result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
@@ -91,7 +91,8 @@
        result.onTimeout(()->{
            logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
        });
@@ -101,12 +102,13 @@
            // 停止之前的回放
            cmder.streamByeCmd(deviceId, channelId);
        }
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid, result);
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId + startTime + endTime, uuid, result);
        if (newMediaServerItem == null) {
            logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("Timeout");
            resultHolder.invokeResult(msg);
            return result;
@@ -118,7 +120,8 @@
        }, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PLAY + uuid);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("回放失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java
@@ -21,6 +21,8 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import java.util.UUID;
@Api(tags = "云台控制")
@CrossOrigin
@RestController
@@ -101,23 +103,31 @@
            logger.debug("设备预置位查询API调用");
        }
        Device device = storager.queryVideoDevice(deviceId);
        cmder.presetQuery(device, channelId, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
        String uuid =  UUID.randomUUID().toString();
        String key =  DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId);
        DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String >> (3 * 1000L);
        result.onTimeout(()->{
            logger.warn(String.format("获取设备预置位超时"));
            // 释放rtpserver
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId));
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("获取设备预置位超时");
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result);
        resultHolder.put(key, uuid, result);
        if (resultHolder.exist(key, null)) {
            return result;
        }
        cmder.presetQuery(device, channelId, event -> {
            Response response = event.getResponse();
            RequestMessage msg = new RequestMessage();
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData(String.format("获取设备预置位失败,错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
            resultHolder.invokeResult(msg);
        });
        return result;
    }
}
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
@@ -22,6 +22,8 @@
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
import java.util.UUID;
@Api(tags = "国标录像")
@CrossOrigin
@RestController
@@ -56,13 +58,15 @@
        Device device = storager.queryVideoDevice(deviceId);
        cmder.recordInfoQuery(device, channelId, startTime, endTime);
        // 指定超时时间 1分钟30秒
        DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<ResponseEntity<RecordInfo>>(90*1000L);
        DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<>(90*1000L);
        String uuid = UUID.randomUUID().toString();
        String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
        // 录像查询以channelId作为deviceId查询
        resultHolder.put(DeferredResultHolder.CALLBACK_CMD_RECORDINFO+channelId, result);
        resultHolder.put(key, uuid, result);
        result.onTimeout(()->{
            RequestMessage msg = new RequestMessage();
            msg.setDeviceId(deviceId);
            msg.setType(DeferredResultHolder.CALLBACK_CMD_RECORDINFO);
            msg.setId(uuid);
            msg.setKey(key);
            msg.setData("timeout");
            resultHolder.invokeResult(msg);
        });
src/main/java/com/genersoft/iot/vmp/vmanager/onvif/ONVIFController.java
@@ -40,17 +40,18 @@
    @ResponseBody
    public DeferredResult<ResponseEntity<WVPResult>> search(@RequestParam(required = false)Integer timeout){
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
        UUID uuid = UUID.randomUUID();
        String uuid = UUID.randomUUID().toString();
        result.onTimeout(()->{
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            msg.setKey(DeferredResultHolder.CALLBACK_ONVIF );
            msg.setId(uuid);
            WVPResult<String> wvpResult = new WVPResult();
            wvpResult.setCode(0);
            wvpResult.setMsg("搜索超时");
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF, uuid, result);
        onvifServer.search(timeout, (errorCode, onvifDevices) ->{
            RequestMessage msg = new RequestMessage();
@@ -87,17 +88,18 @@
                                                                ){
        DeferredResult<ResponseEntity<WVPResult>> result = new DeferredResult<>(timeout + 10L);
        UUID uuid = UUID.randomUUID();
        String uuid = UUID.randomUUID().toString();
        result.onTimeout(()->{
            RequestMessage msg = new RequestMessage();
            msg.setId(DeferredResultHolder.CALLBACK_ONVIF + uuid);
            msg.setId(uuid);
            msg.setKey(DeferredResultHolder.CALLBACK_ONVIF);
            WVPResult<String> wvpResult = new WVPResult();
            wvpResult.setCode(0);
            wvpResult.setMsg("获取onvif的rtsp地址超时");
            msg.setData(wvpResult);
            resultHolder.invokeResult(msg);
        });
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF + uuid, result);
        resultHolder.put(DeferredResultHolder.CALLBACK_ONVIF, uuid, result);
        OnvifDevice onvifDevice = new OnvifDevice(hostname, username, password);
        onvifServer.getRTSPUrl(timeout, onvifDevice,  (errorCode, url) ->{
            RequestMessage msg = new RequestMessage();
web_src/src/components/MediaServerManger.vue
@@ -127,7 +127,6 @@
          }
        }
        console.log("aadada:    "+ resultVal)
        return resultVal;
      },
            dateFormat: function(/** timestamp=0 **/) {