Commit 48fad3582d81dd79423db1db5402d9f47fd5f30f

Authored by 648540858
2 parents 6484f52e 03ee15ec

Merge remote-tracking branch 'origin/wvp-28181-2.0' into wvp-28181-2.0

Showing 21 changed files with 831 additions and 121 deletions
src/main/java/com/genersoft/iot/vmp/common/enums/DeviceControlType.java 0 → 100644
  1 +package com.genersoft.iot.vmp.common.enums;
  2 +
  3 +import org.dom4j.Element;
  4 +import org.springframework.util.ObjectUtils;
  5 +
  6 +
  7 +/**
  8 + * @author gaofuwang
  9 + * @date 2023/01/18/ 10:09:00
  10 + * @since 1.0
  11 + */
  12 +public enum DeviceControlType {
  13 +
  14 + /**
  15 + * 云台控制
  16 + * 上下左右,预置位,扫描,辅助功能,巡航
  17 + */
  18 + PTZ("PTZCmd","云台控制"),
  19 + /**
  20 + * 远程启动
  21 + */
  22 + TELE_BOOT("TeleBoot","远程启动"),
  23 + /**
  24 + * 录像控制
  25 + */
  26 + RECORD("RecordCmd","录像控制"),
  27 + /**
  28 + * 布防撤防
  29 + */
  30 + GUARD("GuardCmd","布防撤防"),
  31 + /**
  32 + * 告警控制
  33 + */
  34 + ALARM("AlarmCmd","告警控制"),
  35 + /**
  36 + * 强制关键帧
  37 + */
  38 + I_FRAME("IFameCmd","强制关键帧"),
  39 + /**
  40 + * 拉框放大
  41 + */
  42 + DRAG_ZOOM_IN("DragZoomIn","拉框放大"),
  43 + /**
  44 + * 拉框缩小
  45 + */
  46 + DRAG_ZOOM_OUT("DragZoomOut","拉框缩小"),
  47 + /**
  48 + * 看守位
  49 + */
  50 + HOME_POSITION("HomePosition","看守位");
  51 +
  52 + private final String val;
  53 +
  54 + private final String desc;
  55 +
  56 + DeviceControlType(String val, String desc) {
  57 + this.val = val;
  58 + this.desc = desc;
  59 + }
  60 +
  61 + public String getVal() {
  62 + return val;
  63 + }
  64 +
  65 + public String getDesc() {
  66 + return desc;
  67 + }
  68 +
  69 + public static DeviceControlType typeOf(Element rootElement) {
  70 + for (DeviceControlType item : DeviceControlType.values()) {
  71 + if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
  72 + return item;
  73 + }
  74 + }
  75 + return null;
  76 + }
  77 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/AlarmChannelMessage.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
  3 +
3 /** 4 /**
4 * 通过redis分发报警消息 5 * 通过redis分发报警消息
5 */ 6 */
@@ -8,12 +9,14 @@ public class AlarmChannelMessage { @@ -8,12 +9,14 @@ public class AlarmChannelMessage {
8 * 国标编号 9 * 国标编号
9 */ 10 */
10 private String gbId; 11 private String gbId;
11 -  
12 /** 12 /**
13 * 报警编号 13 * 报警编号
14 */ 14 */
15 private int alarmSn; 15 private int alarmSn;
16 - 16 + /**
  17 + * 告警类型
  18 + */
  19 + private int alarmType;
17 20
18 /** 21 /**
19 * 报警描述 22 * 报警描述
@@ -36,6 +39,14 @@ public class AlarmChannelMessage { @@ -36,6 +39,14 @@ public class AlarmChannelMessage {
36 this.alarmSn = alarmSn; 39 this.alarmSn = alarmSn;
37 } 40 }
38 41
  42 + public int getAlarmType() {
  43 + return alarmType;
  44 + }
  45 +
  46 + public void setAlarmType(int alarmType) {
  47 + this.alarmType = alarmType;
  48 + }
  49 +
39 public String getAlarmDescription() { 50 public String getAlarmDescription() {
40 return alarmDescription; 51 return alarmDescription;
41 } 52 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarmMethod.java
@@ -37,4 +37,18 @@ public enum DeviceAlarmMethod { @@ -37,4 +37,18 @@ public enum DeviceAlarmMethod {
37 public int getVal() { 37 public int getVal() {
38 return val; 38 return val;
39 } 39 }
  40 +
  41 + /**
  42 + * 查询是否匹配类型
  43 + * @param code
  44 + * @return
  45 + */
  46 + public static DeviceAlarmMethod typeOf(int code) {
  47 + for (DeviceAlarmMethod item : DeviceAlarmMethod.values()) {
  48 + if (code==item.getVal()) {
  49 + return item;
  50 + }
  51 + }
  52 + return null;
  53 + }
40 } 54 }
src/main/java/com/genersoft/iot/vmp/gb28181/bean/DragZoomRequest.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
  4 +
  5 +/**
  6 + * 设备信息查询响应
  7 + *
  8 + * @author Y.G
  9 + * @version 1.0
  10 + * @date 2022/6/28 14:55
  11 + */
  12 +public class DragZoomRequest {
  13 + /**
  14 + * 序列号
  15 + */
  16 + @MessageElement("SN")
  17 + private String sn;
  18 +
  19 + @MessageElement("DeviceID")
  20 + private String deviceId;
  21 +
  22 + @MessageElement(value = "DragZoomIn")
  23 + private DragZoom dragZoomIn;
  24 +
  25 + @MessageElement(value = "DragZoomOut")
  26 + private DragZoom dragZoomOut;
  27 +
  28 + /**
  29 + * 基本参数
  30 + */
  31 + public static class DragZoom {
  32 + /**
  33 + * 播放窗口长度像素值
  34 + */
  35 + @MessageElement("Length")
  36 + protected Integer length;
  37 + /**
  38 + * 播放窗口宽度像素值
  39 + */
  40 + @MessageElement("Width")
  41 + protected Integer width;
  42 + /**
  43 + * 拉框中心的横轴坐标像素值
  44 + */
  45 + @MessageElement("MidPointX")
  46 + protected Integer midPointX;
  47 + /**
  48 + * 拉框中心的纵轴坐标像素值
  49 + */
  50 + @MessageElement("MidPointY")
  51 + protected Integer midPointY;
  52 + /**
  53 + * 拉框长度像素值
  54 + */
  55 + @MessageElement("LengthX")
  56 + protected Integer lengthX;
  57 + /**
  58 + * 拉框宽度像素值
  59 + */
  60 + @MessageElement("LengthY")
  61 + protected Integer lengthY;
  62 +
  63 + public Integer getLength() {
  64 + return length;
  65 + }
  66 +
  67 + public void setLength(Integer length) {
  68 + this.length = length;
  69 + }
  70 +
  71 + public Integer getWidth() {
  72 + return width;
  73 + }
  74 +
  75 + public void setWidth(Integer width) {
  76 + this.width = width;
  77 + }
  78 +
  79 + public Integer getMidPointX() {
  80 + return midPointX;
  81 + }
  82 +
  83 + public void setMidPointX(Integer midPointX) {
  84 + this.midPointX = midPointX;
  85 + }
  86 +
  87 + public Integer getMidPointY() {
  88 + return midPointY;
  89 + }
  90 +
  91 + public void setMidPointY(Integer midPointY) {
  92 + this.midPointY = midPointY;
  93 + }
  94 +
  95 + public Integer getLengthX() {
  96 + return lengthX;
  97 + }
  98 +
  99 + public void setLengthX(Integer lengthX) {
  100 + this.lengthX = lengthX;
  101 + }
  102 +
  103 + public Integer getLengthY() {
  104 + return lengthY;
  105 + }
  106 +
  107 + public void setLengthY(Integer lengthY) {
  108 + this.lengthY = lengthY;
  109 + }
  110 + }
  111 +
  112 + public String getSn() {
  113 + return sn;
  114 + }
  115 +
  116 + public void setSn(String sn) {
  117 + this.sn = sn;
  118 + }
  119 +
  120 + public String getDeviceId() {
  121 + return deviceId;
  122 + }
  123 +
  124 + public void setDeviceId(String deviceId) {
  125 + this.deviceId = deviceId;
  126 + }
  127 +
  128 + public DragZoom getDragZoomIn() {
  129 + return dragZoomIn;
  130 + }
  131 +
  132 + public void setDragZoomIn(DragZoom dragZoomIn) {
  133 + this.dragZoomIn = dragZoomIn;
  134 + }
  135 +
  136 + public DragZoom getDragZoomOut() {
  137 + return dragZoomOut;
  138 + }
  139 +
  140 + public void setDragZoomOut(DragZoom dragZoomOut) {
  141 + this.dragZoomOut = dragZoomOut;
  142 + }
  143 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/HomePositionRequest.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
  4 +
  5 +/**
  6 + * 设备信息查询响应
  7 + *
  8 + * @author Y.G
  9 + * @version 1.0
  10 + * @date 2022/6/28 14:55
  11 + */
  12 +public class HomePositionRequest {
  13 + /**
  14 + * 序列号
  15 + */
  16 + @MessageElement("SN")
  17 + private String sn;
  18 +
  19 + @MessageElement("DeviceID")
  20 + private String deviceId;
  21 +
  22 + @MessageElement(value = "HomePosition")
  23 + private HomePosition homePosition;
  24 +
  25 +
  26 + /**
  27 + * 基本参数
  28 + */
  29 + public static class HomePosition {
  30 + /**
  31 + * 播放窗口长度像素值
  32 + */
  33 + @MessageElement("Enabled")
  34 + protected String enabled;
  35 + /**
  36 + * 播放窗口宽度像素值
  37 + */
  38 + @MessageElement("ResetTime")
  39 + protected String resetTime;
  40 + /**
  41 + * 拉框中心的横轴坐标像素值
  42 + */
  43 + @MessageElement("PresetIndex")
  44 + protected String presetIndex;
  45 +
  46 + public String getEnabled() {
  47 + return enabled;
  48 + }
  49 +
  50 + public void setEnabled(String enabled) {
  51 + this.enabled = enabled;
  52 + }
  53 +
  54 + public String getResetTime() {
  55 + return resetTime;
  56 + }
  57 +
  58 + public void setResetTime(String resetTime) {
  59 + this.resetTime = resetTime;
  60 + }
  61 +
  62 + public String getPresetIndex() {
  63 + return presetIndex;
  64 + }
  65 +
  66 + public void setPresetIndex(String presetIndex) {
  67 + this.presetIndex = presetIndex;
  68 + }
  69 + }
  70 +
  71 + public String getSn() {
  72 + return sn;
  73 + }
  74 +
  75 + public void setSn(String sn) {
  76 + this.sn = sn;
  77 + }
  78 +
  79 + public String getDeviceId() {
  80 + return deviceId;
  81 + }
  82 +
  83 + public void setDeviceId(String deviceId) {
  84 + this.deviceId = deviceId;
  85 + }
  86 +
  87 + public HomePosition getHomePosition() {
  88 + return homePosition;
  89 + }
  90 +
  91 + public void setHomePosition(HomePosition homePosition) {
  92 + this.homePosition = homePosition;
  93 + }
  94 +}
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
1 package com.genersoft.iot.vmp.gb28181.bean; 1 package com.genersoft.iot.vmp.gb28181.bean;
2 2
  3 +
3 import java.time.Instant; 4 import java.time.Instant;
4 import java.util.List; 5 import java.util.List;
5 6
@@ -20,6 +21,8 @@ public class RecordInfo { @@ -20,6 +21,8 @@ public class RecordInfo {
20 21
21 private int sumNum; 22 private int sumNum;
22 23
  24 + private int count;
  25 +
23 private Instant lastTime; 26 private Instant lastTime;
24 27
25 private List<RecordItem> recordList; 28 private List<RecordItem> recordList;
@@ -79,4 +82,12 @@ public class RecordInfo { @@ -79,4 +82,12 @@ public class RecordInfo {
79 public void setLastTime(Instant lastTime) { 82 public void setLastTime(Instant lastTime) {
80 this.lastTime = lastTime; 83 this.lastTime = lastTime;
81 } 84 }
  85 +
  86 + public int getCount() {
  87 + return count;
  88 + }
  89 +
  90 + public void setCount(int count) {
  91 + this.count = count;
  92 + }
82 } 93 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java
1 package com.genersoft.iot.vmp.gb28181.event.record; 1 package com.genersoft.iot.vmp.gb28181.event.record;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; 3 import com.genersoft.iot.vmp.gb28181.bean.RecordInfo;
  4 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
4 import org.slf4j.Logger; 5 import org.slf4j.Logger;
5 import org.slf4j.LoggerFactory; 6 import org.slf4j.LoggerFactory;
  7 +import org.springframework.beans.factory.annotation.Autowired;
6 import org.springframework.context.ApplicationListener; 8 import org.springframework.context.ApplicationListener;
7 import org.springframework.stereotype.Component; 9 import org.springframework.stereotype.Component;
8 10
@@ -20,25 +22,46 @@ public class RecordEndEventListener implements ApplicationListener&lt;RecordEndEven @@ -20,25 +22,46 @@ public class RecordEndEventListener implements ApplicationListener&lt;RecordEndEven
20 22
21 private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class); 23 private final static Logger logger = LoggerFactory.getLogger(RecordEndEventListener.class);
22 24
  25 + private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();
23 public interface RecordEndEventHandler{ 26 public interface RecordEndEventHandler{
24 void handler(RecordInfo recordInfo); 27 void handler(RecordInfo recordInfo);
25 } 28 }
26 29
27 - private Map<String, RecordEndEventHandler> handlerMap = new ConcurrentHashMap<>();  
28 -  
29 @Override 30 @Override
30 public void onApplicationEvent(RecordEndEvent event) { 31 public void onApplicationEvent(RecordEndEvent event) {
31 - logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}条", event.getRecordInfo().getDeviceId(),  
32 - event.getRecordInfo().getChannelId(), event.getRecordInfo().getSumNum() ); 32 + String deviceId = event.getRecordInfo().getDeviceId();
  33 + String channelId = event.getRecordInfo().getChannelId();
  34 + int count = event.getRecordInfo().getCount();
  35 + int sumNum = event.getRecordInfo().getSumNum();
  36 + logger.info("录像查询完成事件触发,deviceId:{}, channelId: {}, 录像数量{}/{}条", event.getRecordInfo().getDeviceId(),
  37 + event.getRecordInfo().getChannelId(), count,sumNum);
33 if (handlerMap.size() > 0) { 38 if (handlerMap.size() > 0) {
34 - for (RecordEndEventHandler recordEndEventHandler : handlerMap.values()) {  
35 - recordEndEventHandler.handler(event.getRecordInfo()); 39 + RecordEndEventHandler handler = handlerMap.get(deviceId + channelId);
  40 + if (handler !=null){
  41 + handler.handler(event.getRecordInfo());
  42 + if (count ==sumNum){
  43 + handlerMap.remove(deviceId + channelId);
  44 + }
36 } 45 }
37 } 46 }
38 - handlerMap.clear();  
39 } 47 }
40 48
  49 + /**
  50 + * 添加
  51 + * @param device
  52 + * @param channelId
  53 + * @param recordEndEventHandler
  54 + */
41 public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) { 55 public void addEndEventHandler(String device, String channelId, RecordEndEventHandler recordEndEventHandler) {
42 handlerMap.put(device + channelId, recordEndEventHandler); 56 handlerMap.put(device + channelId, recordEndEventHandler);
43 } 57 }
  58 + /**
  59 + * 添加
  60 + * @param device
  61 + * @param channelId
  62 + */
  63 + public void delEndEventHandler(String device, String channelId) {
  64 + handlerMap.remove(device + channelId);
  65 + }
  66 +
44 } 67 }
src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java
1 package com.genersoft.iot.vmp.gb28181.session; 1 package com.genersoft.iot.vmp.gb28181.session;
2 2
3 import com.genersoft.iot.vmp.gb28181.bean.*; 3 import com.genersoft.iot.vmp.gb28181.bean.*;
  4 +import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEventListener;
4 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 5 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
5 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 6 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
6 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 7 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
@@ -23,14 +24,17 @@ public class RecordDataCatch { @@ -23,14 +24,17 @@ public class RecordDataCatch {
23 24
24 @Autowired 25 @Autowired
25 private DeferredResultHolder deferredResultHolder; 26 private DeferredResultHolder deferredResultHolder;
  27 + @Autowired
  28 + private RecordEndEventListener recordEndEventListener;
26 29
27 30
28 - public int put(String deviceId, String sn, int sumNum, List<RecordItem> recordItems) { 31 + public int put(String deviceId,String channelId, String sn, int sumNum, List<RecordItem> recordItems) {
29 String key = deviceId + sn; 32 String key = deviceId + sn;
30 RecordInfo recordInfo = data.get(key); 33 RecordInfo recordInfo = data.get(key);
31 if (recordInfo == null) { 34 if (recordInfo == null) {
32 recordInfo = new RecordInfo(); 35 recordInfo = new RecordInfo();
33 recordInfo.setDeviceId(deviceId); 36 recordInfo.setDeviceId(deviceId);
  37 + recordInfo.setChannelId(channelId);
34 recordInfo.setSn(sn.trim()); 38 recordInfo.setSn(sn.trim());
35 recordInfo.setSumNum(sumNum); 39 recordInfo.setSumNum(sumNum);
36 recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>())); 40 recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>()));
@@ -67,6 +71,7 @@ public class RecordDataCatch { @@ -67,6 +71,7 @@ public class RecordDataCatch {
67 msg.setKey(msgKey); 71 msg.setKey(msgKey);
68 msg.setData(recordInfo); 72 msg.setData(recordInfo);
69 deferredResultHolder.invokeAllResult(msg); 73 deferredResultHolder.invokeAllResult(msg);
  74 + recordEndEventListener.delEndEventHandler(recordInfo.getDeviceId(),recordInfo.getChannelId());
70 data.remove(key); 75 data.remove(key);
71 } 76 }
72 } 77 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPSender.java
@@ -47,61 +47,65 @@ public class SIPSender { @@ -47,61 +47,65 @@ public class SIPSender {
47 } 47 }
48 48
49 public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException { 49 public void transmitRequest(String ip, Message message, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, ParseException {
50 - ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);  
51 - String transport = "UDP";  
52 - if (viaHeader == null) {  
53 - logger.warn("[消息头缺失]: ViaHeader, 使用默认的UDP方式处理数据");  
54 - }else {  
55 - transport = viaHeader.getTransport();  
56 - }  
57 - if (message.getHeader(UserAgentHeader.NAME) == null) {  
58 - try {  
59 - message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));  
60 - } catch (ParseException e) {  
61 - logger.error("添加UserAgentHeader失败", e); 50 + try {
  51 + ViaHeader viaHeader = (ViaHeader)message.getHeader(ViaHeader.NAME);
  52 + String transport = "UDP";
  53 + if (viaHeader == null) {
  54 + logger.warn("[消息头缺失]: ViaHeader, 使用默认的UDP方式处理数据");
  55 + }else {
  56 + transport = viaHeader.getTransport();
  57 + }
  58 + if (message.getHeader(UserAgentHeader.NAME) == null) {
  59 + try {
  60 + message.addHeader(SipUtils.createUserAgentHeader(sipLayer.getSipFactory(), gitUtil));
  61 + } catch (ParseException e) {
  62 + logger.error("添加UserAgentHeader失败", e);
  63 + }
62 } 64 }
63 - }  
64 65
65 - CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);  
66 - // 添加错误订阅  
67 - if (errorEvent != null) {  
68 - sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {  
69 - errorEvent.response(eventResult);  
70 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
71 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
72 - }));  
73 - }  
74 - // 添加订阅  
75 - if (okEvent != null) {  
76 - sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {  
77 - okEvent.response(eventResult);  
78 - sipSubscribe.removeOkSubscribe(eventResult.callId);  
79 - sipSubscribe.removeErrorSubscribe(eventResult.callId);  
80 - });  
81 - }  
82 - if ("TCP".equals(transport)) {  
83 - SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip);  
84 - if (tcpSipProvider == null) {  
85 - logger.error("[发送信息失败] 未找到tcp://{}的监听信息", ip);  
86 - return; 66 + CallIdHeader callIdHeader = (CallIdHeader) message.getHeader(CallIdHeader.NAME);
  67 + // 添加错误订阅
  68 + if (errorEvent != null) {
  69 + sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> {
  70 + errorEvent.response(eventResult);
  71 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  72 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  73 + }));
87 } 74 }
88 - if (message instanceof Request) {  
89 - tcpSipProvider.sendRequest((Request)message);  
90 - }else if (message instanceof Response) {  
91 - tcpSipProvider.sendResponse((Response)message); 75 + // 添加订阅
  76 + if (okEvent != null) {
  77 + sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult -> {
  78 + okEvent.response(eventResult);
  79 + sipSubscribe.removeOkSubscribe(eventResult.callId);
  80 + sipSubscribe.removeErrorSubscribe(eventResult.callId);
  81 + });
92 } 82 }
  83 + if ("TCP".equals(transport)) {
  84 + SipProviderImpl tcpSipProvider = sipLayer.getTcpSipProvider(ip);
  85 + if (tcpSipProvider == null) {
  86 + logger.error("[发送信息失败] 未找到tcp://{}的监听信息", ip);
  87 + return;
  88 + }
  89 + if (message instanceof Request) {
  90 + tcpSipProvider.sendRequest((Request)message);
  91 + }else if (message instanceof Response) {
  92 + tcpSipProvider.sendResponse((Response)message);
  93 + }
93 94
94 - } else if ("UDP".equals(transport)) {  
95 - SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip);  
96 - if (sipProvider == null) {  
97 - logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip);  
98 - return;  
99 - }  
100 - if (message instanceof Request) {  
101 - sipProvider.sendRequest((Request)message);  
102 - }else if (message instanceof Response) {  
103 - sipProvider.sendResponse((Response)message); 95 + } else if ("UDP".equals(transport)) {
  96 + SipProviderImpl sipProvider = sipLayer.getUdpSipProvider(ip);
  97 + if (sipProvider == null) {
  98 + logger.error("[发送信息失败] 未找到udp://{}的监听信息", ip);
  99 + return;
  100 + }
  101 + if (message instanceof Request) {
  102 + sipProvider.sendRequest((Request)message);
  103 + }else if (message instanceof Response) {
  104 + sipProvider.sendResponse((Response)message);
  105 + }
104 } 106 }
  107 + } finally {
  108 + logger.info("[SEND]:SUCCESS:{}", message);
105 } 109 }
106 } 110 }
107 111
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -183,7 +183,7 @@ public interface ISIPCommander { @@ -183,7 +183,7 @@ public interface ISIPCommander {
183 * @param channelId 预览通道 183 * @param channelId 预览通道
184 * @param recordCmdStr 录像命令:Record / StopRecord 184 * @param recordCmdStr 录像命令:Record / StopRecord
185 */ 185 */
186 - void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 186 + void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
187 187
188 /** 188 /**
189 * 远程启动控制命令 189 * 远程启动控制命令
@@ -197,7 +197,7 @@ public interface ISIPCommander { @@ -197,7 +197,7 @@ public interface ISIPCommander {
197 * 197 *
198 * @param device 视频设备 198 * @param device 视频设备
199 */ 199 */
200 - void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 200 + void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
201 201
202 /** 202 /**
203 * 报警复位命令 203 * 报警复位命令
@@ -206,7 +206,7 @@ public interface ISIPCommander { @@ -206,7 +206,7 @@ public interface ISIPCommander {
206 * @param alarmMethod 报警方式(可选) 206 * @param alarmMethod 报警方式(可选)
207 * @param alarmType 报警类型(可选) 207 * @param alarmType 报警类型(可选)
208 */ 208 */
209 - void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 209 + void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
210 210
211 /** 211 /**
212 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 212 * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧
@@ -215,17 +215,19 @@ public interface ISIPCommander { @@ -215,17 +215,19 @@ public interface ISIPCommander {
215 * @param channelId 预览通道 215 * @param channelId 预览通道
216 */ 216 */
217 void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException; 217 void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException;
218 - 218 +
219 /** 219 /**
220 * 看守位控制命令 220 * 看守位控制命令
221 - *  
222 - * @param device 视频设备  
223 - * @param enabled 看守位使能:1 = 开启,0 = 关闭  
224 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)  
225 - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255  
226 - */  
227 - void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;  
228 - 221 + *
  222 + * @param device 视频设备
  223 + * @param channelId 通道id,非通道则是设备本身
  224 + * @param frontCmd 上级平台的指令,如果存在则直接下发
  225 + * @param enabled 看守位使能:1 = 开启,0 = 关闭
  226 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
  227 + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
  228 + */
  229 + void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
  230 +
229 /** 231 /**
230 * 设备配置命令 232 * 设备配置命令
231 * 233 *
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -29,6 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired;
29 import org.springframework.context.annotation.DependsOn; 29 import org.springframework.context.annotation.DependsOn;
30 import org.springframework.stereotype.Component; 30 import org.springframework.stereotype.Component;
31 import org.springframework.util.ObjectUtils; 31 import org.springframework.util.ObjectUtils;
  32 +import org.springframework.util.StringUtils;
32 33
33 import javax.sip.InvalidArgumentException; 34 import javax.sip.InvalidArgumentException;
34 import javax.sip.ResponseEvent; 35 import javax.sip.ResponseEvent;
@@ -663,7 +664,7 @@ public class SIPCommander implements ISIPCommander { @@ -663,7 +664,7 @@ public class SIPCommander implements ISIPCommander {
663 * @param recordCmdStr 录像命令:Record / StopRecord 664 * @param recordCmdStr 录像命令:Record / StopRecord
664 */ 665 */
665 @Override 666 @Override
666 - public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 667 + public void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
667 StringBuffer cmdXml = new StringBuffer(200); 668 StringBuffer cmdXml = new StringBuffer(200);
668 String charset = device.getCharset(); 669 String charset = device.getCharset();
669 cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n"); 670 cmdXml.append("<?xml version=\"1.0\" encoding=\"" + charset + "\"?>\r\n");
@@ -681,7 +682,7 @@ public class SIPCommander implements ISIPCommander { @@ -681,7 +682,7 @@ public class SIPCommander implements ISIPCommander {
681 682
682 683
683 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 684 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
684 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); 685 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
685 } 686 }
686 687
687 /** 688 /**
@@ -715,7 +716,7 @@ public class SIPCommander implements ISIPCommander { @@ -715,7 +716,7 @@ public class SIPCommander implements ISIPCommander {
715 * @param guardCmdStr "SetGuard"/"ResetGuard" 716 * @param guardCmdStr "SetGuard"/"ResetGuard"
716 */ 717 */
717 @Override 718 @Override
718 - public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 719 + public void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
719 720
720 StringBuffer cmdXml = new StringBuffer(200); 721 StringBuffer cmdXml = new StringBuffer(200);
721 String charset = device.getCharset(); 722 String charset = device.getCharset();
@@ -728,7 +729,7 @@ public class SIPCommander implements ISIPCommander { @@ -728,7 +729,7 @@ public class SIPCommander implements ISIPCommander {
728 cmdXml.append("</Control>\r\n"); 729 cmdXml.append("</Control>\r\n");
729 730
730 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 731 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
731 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); 732 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
732 } 733 }
733 734
734 /** 735 /**
@@ -737,7 +738,7 @@ public class SIPCommander implements ISIPCommander { @@ -737,7 +738,7 @@ public class SIPCommander implements ISIPCommander {
737 * @param device 视频设备 738 * @param device 视频设备
738 */ 739 */
739 @Override 740 @Override
740 - public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 741 + public void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
741 742
742 StringBuffer cmdXml = new StringBuffer(200); 743 StringBuffer cmdXml = new StringBuffer(200);
743 String charset = device.getCharset(); 744 String charset = device.getCharset();
@@ -764,7 +765,7 @@ public class SIPCommander implements ISIPCommander { @@ -764,7 +765,7 @@ public class SIPCommander implements ISIPCommander {
764 765
765 766
766 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 767 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
767 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); 768 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
768 } 769 }
769 770
770 /** 771 /**
@@ -800,12 +801,14 @@ public class SIPCommander implements ISIPCommander { @@ -800,12 +801,14 @@ public class SIPCommander implements ISIPCommander {
800 * 看守位控制命令 801 * 看守位控制命令
801 * 802 *
802 * @param device 视频设备 803 * @param device 视频设备
  804 + * @param channelId 通道id,非通道则是设备本身
  805 + * @param frontCmd 上级平台的指令,如果存在则直接下发
803 * @param enabled 看守位使能:1 = 开启,0 = 关闭 806 * @param enabled 看守位使能:1 = 开启,0 = 关闭
804 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) 807 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
805 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 808 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
806 */ 809 */
807 @Override 810 @Override
808 - public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 811 + public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
809 812
810 StringBuffer cmdXml = new StringBuffer(200); 813 StringBuffer cmdXml = new StringBuffer(200);
811 String charset = device.getCharset(); 814 String charset = device.getCharset();
@@ -840,7 +843,7 @@ public class SIPCommander implements ISIPCommander { @@ -840,7 +843,7 @@ public class SIPCommander implements ISIPCommander {
840 843
841 844
842 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); 845 Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()));
843 - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); 846 + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent);
844 } 847 }
845 848
846 /** 849 /**
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.control.cmd;
2 2
3 -import com.genersoft.iot.vmp.VManageBootstrap; 3 +import com.genersoft.iot.vmp.common.enums.DeviceControlType;
4 import com.genersoft.iot.vmp.gb28181.bean.Device; 4 import com.genersoft.iot.vmp.gb28181.bean.Device;
  5 +import com.genersoft.iot.vmp.gb28181.bean.DragZoomRequest;
  6 +import com.genersoft.iot.vmp.gb28181.bean.HomePositionRequest;
5 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  8 +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
7 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
8 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
@@ -19,17 +22,14 @@ import org.springframework.beans.factory.annotation.Qualifier; @@ -19,17 +22,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
19 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 22 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
20 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
21 import org.springframework.util.ObjectUtils; 24 import org.springframework.util.ObjectUtils;
22 -import org.springframework.util.StringUtils;  
23 25
24 import javax.sip.*; 26 import javax.sip.*;
25 import javax.sip.address.SipURI; 27 import javax.sip.address.SipURI;
26 -import javax.sip.header.HeaderAddress;  
27 -import javax.sip.header.ToHeader;  
28 import javax.sip.message.Response; 28 import javax.sip.message.Response;
29 import java.text.ParseException; 29 import java.text.ParseException;
30 -import java.util.Iterator; 30 +import java.util.List;
31 31
32 -import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; 32 +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
33 33
34 @Component 34 @Component
35 public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 35 public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
@@ -81,7 +81,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -81,7 +81,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
81 } catch (InvalidArgumentException | ParseException | SipException e) { 81 } catch (InvalidArgumentException | ParseException | SipException e) {
82 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); 82 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
83 } 83 }
84 - taskExecutor.execute(()->{ 84 + taskExecutor.execute(() -> {
85 // 远程启动 85 // 远程启动
86 // try { 86 // try {
87 // Thread.sleep(3000); 87 // Thread.sleep(3000);
@@ -101,13 +101,12 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -101,13 +101,12 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
101 // logger.error("[任务执行失败] 服务重启: {}", e.getMessage()); 101 // logger.error("[任务执行失败] 服务重启: {}", e.getMessage());
102 // } 102 // }
103 }); 103 });
104 - } else {  
105 - // 远程启动指定设备  
106 } 104 }
107 } 105 }
108 - // 云台/前端控制命令  
109 - if (!ObjectUtils.isEmpty(getText(rootElement,"PTZCmd")) && !parentPlatform.getServerGBId().equals(targetGBId)) {  
110 - String cmdString = getText(rootElement,"PTZCmd"); 106 + DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement);
  107 + logger.info("[接受deviceControl命令] 命令: {}", deviceControlType);
  108 + if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)) {
  109 + //判断是否存在该通道
111 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId); 110 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
112 if (deviceForPlatform == null) { 111 if (deviceForPlatform == null) {
113 try { 112 try {
@@ -117,25 +116,240 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent @@ -117,25 +116,240 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
117 } 116 }
118 return; 117 return;
119 } 118 }
120 - try {  
121 - cmder.fronEndCmd(deviceForPlatform, channelId, cmdString, eventResult -> {  
122 - // 失败的回复  
123 - try {  
124 - responseAck(request, eventResult.statusCode, eventResult.msg);  
125 - } catch (SipException | InvalidArgumentException | ParseException e) {  
126 - logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());  
127 - }  
128 - }, eventResult -> {  
129 - // 成功的回复  
130 - try {  
131 - responseAck(request, eventResult.statusCode);  
132 - } catch (SipException | InvalidArgumentException | ParseException e) {  
133 - logger.error("[命令发送失败] 云台/前端回复: {}", e.getMessage());  
134 - }  
135 - });  
136 - } catch (InvalidArgumentException | SipException | ParseException e) {  
137 - logger.error("[命令发送失败] 云台/前端: {}", e.getMessage()); 119 + switch (deviceControlType) {
  120 + case PTZ:
  121 + handlePtzCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.PTZ);
  122 + break;
  123 + case ALARM:
  124 + handleAlarmCmd(deviceForPlatform, rootElement, request);
  125 + break;
  126 + case GUARD:
  127 + handleGuardCmd(deviceForPlatform, rootElement, request, DeviceControlType.GUARD);
  128 + break;
  129 + case RECORD:
  130 + handleRecordCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.RECORD);
  131 + break;
  132 + case I_FRAME:
  133 + handleIFameCmd(deviceForPlatform, request, channelId);
  134 + break;
  135 + case TELE_BOOT:
  136 + handleTeleBootCmd(deviceForPlatform, request);
  137 + break;
  138 + case DRAG_ZOOM_IN:
  139 + handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_IN);
  140 + break;
  141 + case DRAG_ZOOM_OUT:
  142 + handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_OUT);
  143 + break;
  144 + case HOME_POSITION:
  145 + handleHomePositionCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.HOME_POSITION);
  146 + break;
  147 + default:
  148 + break;
138 } 149 }
139 } 150 }
140 } 151 }
  152 +
  153 + /**
  154 + * 处理云台指令
  155 + *
  156 + * @param device 设备
  157 + * @param channelId 通道id
  158 + * @param rootElement
  159 + * @param request
  160 + */
  161 + private void handlePtzCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
  162 + String cmdString = getText(rootElement, type.getVal());
  163 + try {
  164 + cmder.fronEndCmd(device, channelId, cmdString,
  165 + errorResult -> onError(request, errorResult),
  166 + okResult -> onOk(request, okResult));
  167 + } catch (InvalidArgumentException | SipException | ParseException e) {
  168 + logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
  169 + }
  170 + }
  171 +
  172 + /**
  173 + * 处理强制关键帧
  174 + *
  175 + * @param device 设备
  176 + * @param channelId 通道id
  177 + */
  178 + private void handleIFameCmd(Device device, SIPRequest request, String channelId) {
  179 + try {
  180 + cmder.iFrameCmd(device, channelId);
  181 + responseAck(request, Response.OK);
  182 + } catch (InvalidArgumentException | SipException | ParseException e) {
  183 + logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
  184 + }
  185 + }
  186 +
  187 + /**
  188 + * 处理重启命令
  189 + *
  190 + * @param device 设备信息
  191 + */
  192 + private void handleTeleBootCmd(Device device, SIPRequest request) {
  193 + try {
  194 + cmder.teleBootCmd(device);
  195 + responseAck(request, Response.OK);
  196 + } catch (InvalidArgumentException | SipException | ParseException e) {
  197 + logger.error("[命令发送失败] 重启: {}", e.getMessage());
  198 + }
  199 +
  200 + }
  201 +
  202 + /**
  203 + * 处理拉框控制***
  204 + *
  205 + * @param device 设备信息
  206 + * @param channelId 通道id
  207 + * @param rootElement 根节点
  208 + * @param type 消息类型
  209 + */
  210 + private void handleDragZoom(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
  211 + try {
  212 + DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class);
  213 + DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn();
  214 + if (dragZoom == null) {
  215 + dragZoom = dragZoomRequest.getDragZoomOut();
  216 + }
  217 + StringBuffer cmdXml = new StringBuffer(200);
  218 + cmdXml.append("<" + type.getVal() + ">\r\n");
  219 + cmdXml.append("<Length>" + dragZoom.getLength() + "</Length>\r\n");
  220 + cmdXml.append("<Width>" + dragZoom.getWidth() + "</Width>\r\n");
  221 + cmdXml.append("<MidPointX>" + dragZoom.getMidPointX() + "</MidPointX>\r\n");
  222 + cmdXml.append("<MidPointY>" + dragZoom.getMidPointY() + "</MidPointY>\r\n");
  223 + cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n");
  224 + cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n");
  225 + cmdXml.append("</" + type.getVal() + ">\r\n");
  226 + cmder.dragZoomCmd(device, channelId, cmdXml.toString());
  227 + responseAck(request, Response.OK);
  228 + } catch (Exception e) {
  229 + logger.error("[命令发送失败] 拉框控制: {}", e.getMessage());
  230 + }
  231 +
  232 + }
  233 +
  234 + /**
  235 + * 处理看守位命令***
  236 + *
  237 + * @param device 设备信息
  238 + * @param channelId 通道id
  239 + * @param rootElement 根节点
  240 + * @param request 请求信息
  241 + * @param type 消息类型
  242 + */
  243 + private void handleHomePositionCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
  244 + try {
  245 + HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class);
  246 + //获取整个消息主体,我们只需要修改请求头即可
  247 + HomePositionRequest.HomePosition info = homePosition.getHomePosition();
  248 + cmder.homePositionCmd(device, channelId, info.getEnabled(), info.getResetTime(), info.getPresetIndex(),
  249 + errorResult -> onError(request, errorResult),
  250 + okResult -> onOk(request, okResult));
  251 + } catch (Exception e) {
  252 + logger.error("[命令发送失败] 看守位设置: {}", e.getMessage());
  253 + }
  254 + }
  255 +
  256 + /**
  257 + * 处理告警消息***
  258 + *
  259 + * @param device 设备信息
  260 + * @param rootElement 根节点
  261 + * @param request 请求信息
  262 + */
  263 + private void handleAlarmCmd(Device device, Element rootElement, SIPRequest request) {
  264 + //告警方法
  265 + String alarmMethod = "";
  266 + //告警类型
  267 + String alarmType = "";
  268 + List<Element> info = rootElement.elements("Info");
  269 + if (info != null) {
  270 + for (Element element : info) {
  271 + alarmMethod = getText(element, "AlarmMethod");
  272 + alarmType = getText(element, "AlarmType");
  273 + }
  274 + }
  275 + try {
  276 + cmder.alarmCmd(device, alarmMethod, alarmType,
  277 + errorResult -> onError(request, errorResult),
  278 + okResult -> onOk(request, okResult));
  279 + } catch (InvalidArgumentException | SipException | ParseException e) {
  280 + logger.error("[命令发送失败] 告警消息: {}", e.getMessage());
  281 + }
  282 + }
  283 +
  284 + /**
  285 + * 处理录像控制
  286 + *
  287 + * @param device 设备信息
  288 + * @param channelId 通道id
  289 + * @param rootElement 根节点
  290 + * @param request 请求信息
  291 + * @param type 消息类型
  292 + */
  293 + private void handleRecordCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
  294 + //获取整个消息主体,我们只需要修改请求头即可
  295 + String cmdString = getText(rootElement, type.getVal());
  296 + try {
  297 + cmder.recordCmd(device, channelId, cmdString,
  298 + errorResult -> onError(request, errorResult),
  299 + okResult -> onOk(request, okResult));
  300 + } catch (InvalidArgumentException | SipException | ParseException e) {
  301 + logger.error("[命令发送失败] 录像控制: {}", e.getMessage());
  302 + }
  303 + }
  304 +
  305 + /**
  306 + * 处理报警布防/撤防命令
  307 + *
  308 + * @param device 设备信息
  309 + * @param rootElement 根节点
  310 + * @param request 请求信息
  311 + * @param type 消息类型
  312 + */
  313 + private void handleGuardCmd(Device device, Element rootElement, SIPRequest request, DeviceControlType type) {
  314 + //获取整个消息主体,我们只需要修改请求头即可
  315 + String cmdString = getText(rootElement, type.getVal());
  316 + try {
  317 + cmder.guardCmd(device, cmdString,
  318 + errorResult -> onError(request, errorResult),
  319 + okResult -> onOk(request, okResult));
  320 + } catch (InvalidArgumentException | SipException | ParseException e) {
  321 + logger.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage());
  322 + }
  323 + }
  324 +
  325 +
  326 + /**
  327 + * 错误响应处理
  328 + *
  329 + * @param request 请求
  330 + * @param eventResult 响应结构
  331 + */
  332 + private void onError(SIPRequest request, SipSubscribe.EventResult eventResult) {
  333 + // 失败的回复
  334 + try {
  335 + responseAck(request, eventResult.statusCode, eventResult.msg);
  336 + } catch (SipException | InvalidArgumentException | ParseException e) {
  337 + logger.error("[命令发送失败] 回复: {}", e.getMessage());
  338 + }
  339 + }
  340 +
  341 + /**
  342 + * 成功响应处理
  343 + *
  344 + * @param request 请求
  345 + * @param eventResult 响应结构
  346 + */
  347 + private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) {
  348 + // 成功的回复
  349 + try {
  350 + responseAck(request, eventResult.statusCode);
  351 + } catch (SipException | InvalidArgumentException | ParseException e) {
  352 + logger.error("[命令发送失败] 回复: {}", e.getMessage());
  353 + }
  354 + }
141 } 355 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -181,11 +181,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -181,11 +181,13 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
181 } 181 }
182 } 182 }
183 logger.info("[收到报警通知]内容:{}", JSON.toJSONString(deviceAlarm)); 183 logger.info("[收到报警通知]内容:{}", JSON.toJSONString(deviceAlarm));
184 - if ("7".equals(deviceAlarm.getAlarmMethod()) ) { 184 + if (DeviceAlarmMethod.typeOf(Integer.parseInt(deviceAlarm.getAlarmMethod())) !=null) {
185 // 发送给平台的报警信息。 发送redis通知 185 // 发送给平台的报警信息。 发送redis通知
  186 + logger.info("[发送给平台的报警信息]内容:{}", JSONObject.toJSONString(deviceAlarm));
186 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); 187 AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage();
187 alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); 188 alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
188 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); 189 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
  190 + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
189 alarmChannelMessage.setGbId(channelId); 191 alarmChannelMessage.setGbId(channelId);
190 redisCatchStorage.sendAlarmMsg(alarmChannelMessage); 192 redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
191 continue; 193 continue;
@@ -264,6 +266,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme @@ -264,6 +266,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme
264 alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); 266 alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod()));
265 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); 267 alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription());
266 alarmChannelMessage.setGbId(channelId); 268 alarmChannelMessage.setGbId(channelId);
  269 + alarmChannelMessage.setAlarmType(Integer.parseInt(deviceAlarm.getAlarmType()));
267 redisCatchStorage.sendAlarmMsg(alarmChannelMessage); 270 redisCatchStorage.sendAlarmMsg(alarmChannelMessage);
268 return; 271 return;
269 } 272 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
@@ -102,8 +102,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -102,8 +102,9 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
102 Element recordListElement = rootElementForCharset.element("RecordList"); 102 Element recordListElement = rootElementForCharset.element("RecordList");
103 if (recordListElement == null || sumNum == 0) { 103 if (recordListElement == null || sumNum == 0) {
104 logger.info("无录像数据"); 104 logger.info("无录像数据");
  105 + int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, new ArrayList<>());
  106 + recordInfo.setCount(count);
105 eventPublisher.recordEndEventPush(recordInfo); 107 eventPublisher.recordEndEventPush(recordInfo);
106 - recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, new ArrayList<>());  
107 releaseRequest(take.getDevice().getDeviceId(), sn); 108 releaseRequest(take.getDevice().getDeviceId(), sn);
108 } else { 109 } else {
109 Iterator<Element> recordListIterator = recordListElement.elementIterator(); 110 Iterator<Element> recordListIterator = recordListElement.elementIterator();
@@ -137,12 +138,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent @@ -137,12 +138,11 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
137 recordList.add(record); 138 recordList.add(record);
138 } 139 }
139 recordInfo.setRecordList(recordList); 140 recordInfo.setRecordList(recordList);
  141 + int count = recordDataCatch.put(take.getDevice().getDeviceId(),channelId, sn, sumNum, recordList);recordInfo.setCount(count);
  142 + logger.info("[国标录像], {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum);
140 // 发送消息,如果是上级查询此录像,则会通过这里通知给上级 143 // 发送消息,如果是上级查询此录像,则会通过这里通知给上级
141 eventPublisher.recordEndEventPush(recordInfo); 144 eventPublisher.recordEndEventPush(recordInfo);
142 - int count = recordDataCatch.put(take.getDevice().getDeviceId(), sn, sumNum, recordList);  
143 - logger.info("[国标录像], {}->{}: {}/{}", take.getDevice().getDeviceId(), sn, count, sumNum);  
144 } 145 }
145 -  
146 if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){ 146 if (recordDataCatch.isComplete(take.getDevice().getDeviceId(), sn)){
147 releaseRequest(take.getDevice().getDeviceId(), sn); 147 releaseRequest(take.getDevice().getDeviceId(), sn);
148 } 148 }
src/main/java/com/genersoft/iot/vmp/gb28181/utils/MessageElement.java 0 → 100644
  1 +package com.genersoft.iot.vmp.gb28181.utils;
  2 +
  3 +import java.lang.annotation.*;
  4 +
  5 +/**
  6 + * @author gaofuwang
  7 + * @version 1.0
  8 + * @date 2022/6/28 14:58
  9 + */
  10 +@Target({ElementType.FIELD})
  11 +@Retention(RetentionPolicy.RUNTIME)
  12 +@Documented
  13 +public @interface MessageElement {
  14 + String value();
  15 +
  16 + String subVal() default "";
  17 +}
src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
1 package com.genersoft.iot.vmp.gb28181.utils; 1 package com.genersoft.iot.vmp.gb28181.utils;
2 2
  3 +import com.alibaba.fastjson2.JSON;
3 import com.alibaba.fastjson2.JSONArray; 4 import com.alibaba.fastjson2.JSONArray;
4 import com.alibaba.fastjson2.JSONObject; 5 import com.alibaba.fastjson2.JSONObject;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -15,12 +16,16 @@ import org.dom4j.io.SAXReader; @@ -15,12 +16,16 @@ import org.dom4j.io.SAXReader;
15 import org.slf4j.Logger; 16 import org.slf4j.Logger;
16 import org.slf4j.LoggerFactory; 17 import org.slf4j.LoggerFactory;
17 import org.springframework.util.ObjectUtils; 18 import org.springframework.util.ObjectUtils;
18 -import org.springframework.util.StringUtils; 19 +import org.springframework.util.ReflectionUtils;
19 20
20 import javax.sip.RequestEvent; 21 import javax.sip.RequestEvent;
21 import javax.sip.message.Request; 22 import javax.sip.message.Request;
22 import java.io.ByteArrayInputStream; 23 import java.io.ByteArrayInputStream;
23 import java.io.StringReader; 24 import java.io.StringReader;
  25 +import java.lang.reflect.Field;
  26 +import java.lang.reflect.InvocationTargetException;
  27 +import java.lang.reflect.ParameterizedType;
  28 +import java.lang.reflect.Type;
24 import java.util.*; 29 import java.util.*;
25 30
26 /** 31 /**
@@ -411,4 +416,76 @@ public class XmlUtil { @@ -411,4 +416,76 @@ public class XmlUtil {
411 } 416 }
412 return deviceChannel; 417 return deviceChannel;
413 } 418 }
  419 +
  420 + /**
  421 + * 新增方法支持内部嵌套
  422 + *
  423 + * @param element xmlElement
  424 + * @param clazz 结果类
  425 + * @param <T> 泛型
  426 + * @return 结果对象
  427 + * @throws NoSuchMethodException
  428 + * @throws InvocationTargetException
  429 + * @throws InstantiationException
  430 + * @throws IllegalAccessException
  431 + */
  432 + public static <T> T loadElement(Element element, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
  433 + Field[] fields = clazz.getDeclaredFields();
  434 + T t = clazz.getDeclaredConstructor().newInstance();
  435 + for (Field field : fields) {
  436 + ReflectionUtils.makeAccessible(field);
  437 + MessageElement annotation = field.getAnnotation(MessageElement.class);
  438 + if (annotation == null) {
  439 + continue;
  440 + }
  441 + String value = annotation.value();
  442 + String subVal = annotation.subVal();
  443 + Element element1 = element.element(value);
  444 + if (element1 == null) {
  445 + continue;
  446 + }
  447 + if ("".equals(subVal)) {
  448 + // 无下级数据
  449 + Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType());
  450 + Object o = simpleTypeDeal(field.getType(), fieldVal);
  451 + ReflectionUtils.setField(field, t, o);
  452 + } else {
  453 + // 存在下级数据
  454 + ArrayList<Object> list = new ArrayList<>();
  455 + Type genericType = field.getGenericType();
  456 + if (!(genericType instanceof ParameterizedType)) {
  457 + continue;
  458 + }
  459 + Class<?> aClass = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
  460 + for (Element element2 : element1.elements(subVal)) {
  461 + list.add(loadElement(element2, aClass));
  462 + }
  463 + ReflectionUtils.setField(field, t, list);
  464 + }
  465 + }
  466 + return t;
  467 + }
  468 +
  469 + /**
  470 + * 简单类型处理
  471 + *
  472 + * @param tClass
  473 + * @param val
  474 + * @return
  475 + */
  476 + private static Object simpleTypeDeal(Class<?> tClass, Object val) {
  477 + if (tClass.equals(String.class)) {
  478 + return val.toString();
  479 + }
  480 + if (tClass.equals(Integer.class)) {
  481 + return Integer.valueOf(val.toString());
  482 + }
  483 + if (tClass.equals(Double.class)) {
  484 + return Double.valueOf(val.toString());
  485 + }
  486 + if (tClass.equals(Long.class)) {
  487 + return Long.valueOf(val.toString());
  488 + }
  489 + return val;
  490 + }
414 } 491 }
415 \ No newline at end of file 492 \ No newline at end of file
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
@@ -67,9 +67,9 @@ public class RedisAlarmMsgListener implements MessageListener { @@ -67,9 +67,9 @@ public class RedisAlarmMsgListener implements MessageListener {
67 deviceAlarm.setChannelId(gbId); 67 deviceAlarm.setChannelId(gbId);
68 deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); 68 deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription());
69 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); 69 deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn());
  70 + deviceAlarm.setAlarmType("" + alarmChannelMessage.getAlarmType());
70 deviceAlarm.setAlarmPriority("1"); 71 deviceAlarm.setAlarmPriority("1");
71 deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); 72 deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601());
72 - deviceAlarm.setAlarmType("1");  
73 deviceAlarm.setLongitude(0); 73 deviceAlarm.setLongitude(0);
74 deviceAlarm.setLatitude(0); 74 deviceAlarm.setLatitude(0);
75 75
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
@@ -114,4 +114,7 @@ public interface PlatformChannelMapper { @@ -114,4 +114,7 @@ public interface PlatformChannelMapper {
114 " left join device d on dc.deviceId = d.deviceId\n" + 114 " left join device d on dc.deviceId = d.deviceId\n" +
115 "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}") 115 "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}")
116 List<Device> queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId); 116 List<Device> queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId);
  117 +
  118 + @Select("SELECT pgc.platformId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}'")
  119 + List<String> queryParentPlatformByChannelId(String channelId);
117 } 120 }
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -830,7 +830,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -830,7 +830,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
830 830
831 @Override 831 @Override
832 public void sendAlarmMsg(AlarmChannelMessage msg) { 832 public void sendAlarmMsg(AlarmChannelMessage msg) {
833 - String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM; 833 + String key = VideoManagerConstants.VM_MSG_SUBSCRIBE_ALARM_RECEIVE;
834 logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg)); 834 logger.info("[redis发送通知] 报警{}: {}", key, JSON.toJSON(msg));
835 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg)); 835 RedisUtil.convertAndSend(key, (JSONObject)JSON.toJSON(msg));
836 } 836 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
@@ -133,6 +133,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @@ -133,6 +133,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
133 if (allChannelMap.containsKey(deviceChannel.getChannelId())) { 133 if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
134 deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId()); 134 deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
135 deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio()); 135 deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
  136 + if (allChannelMap.get(deviceChannel.getChannelId()).getStatus() !=deviceChannel.getStatus()){
  137 + List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId());
  138 + if (!CollectionUtils.isEmpty(strings)){
  139 + strings.forEach(platformId->{
  140 + eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.getStatus()==1?CatalogEvent.ON:CatalogEvent.OFF);
  141 + });
  142 + }
  143 +
  144 + }
136 } 145 }
137 channels.add(deviceChannel); 146 channels.add(deviceChannel);
138 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) { 147 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
@@ -110,7 +110,7 @@ public class DeviceControl { @@ -110,7 +110,7 @@ public class DeviceControl {
110 msg.setKey(key); 110 msg.setKey(key);
111 msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg)); 111 msg.setData(String.format("开始/停止录像操作失败,错误码: %s, %s", event.statusCode, event.msg));
112 resultHolder.invokeAllResult(msg); 112 resultHolder.invokeAllResult(msg);
113 - }); 113 + },null);
114 } catch (InvalidArgumentException | SipException | ParseException e) { 114 } catch (InvalidArgumentException | SipException | ParseException e) {
115 logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage()); 115 logger.error("[命令发送失败] 开始/停止录像: {}", e.getMessage());
116 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); 116 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
@@ -143,7 +143,7 @@ public class DeviceControl { @@ -143,7 +143,7 @@ public class DeviceControl {
143 msg.setKey(key); 143 msg.setKey(key);
144 msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg)); 144 msg.setData(String.format("布防/撤防操作失败,错误码: %s, %s", event.statusCode, event.msg));
145 resultHolder.invokeResult(msg); 145 resultHolder.invokeResult(msg);
146 - }); 146 + },null);
147 } catch (InvalidArgumentException | SipException | ParseException e) { 147 } catch (InvalidArgumentException | SipException | ParseException e) {
148 logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage()); 148 logger.error("[命令发送失败] 布防/撤防操作: {}", e.getMessage());
149 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage()); 149 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送: " + e.getMessage());
@@ -192,7 +192,7 @@ public class DeviceControl { @@ -192,7 +192,7 @@ public class DeviceControl {
192 msg.setKey(key); 192 msg.setKey(key);
193 msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg)); 193 msg.setData(String.format("报警复位操作失败,错误码: %s, %s", event.statusCode, event.msg));
194 resultHolder.invokeResult(msg); 194 resultHolder.invokeResult(msg);
195 - }); 195 + },null);
196 } catch (InvalidArgumentException | SipException | ParseException e) { 196 } catch (InvalidArgumentException | SipException | ParseException e) {
197 logger.error("[命令发送失败] 报警复位: {}", e.getMessage()); 197 logger.error("[命令发送失败] 报警复位: {}", e.getMessage());
198 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); 198 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());
@@ -274,7 +274,7 @@ public class DeviceControl { @@ -274,7 +274,7 @@ public class DeviceControl {
274 msg.setKey(key); 274 msg.setKey(key);
275 msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg)); 275 msg.setData(String.format("看守位控制操作失败,错误码: %s, %s", event.statusCode, event.msg));
276 resultHolder.invokeResult(msg); 276 resultHolder.invokeResult(msg);
277 - }); 277 + },null);
278 } catch (InvalidArgumentException | SipException | ParseException e) { 278 } catch (InvalidArgumentException | SipException | ParseException e) {
279 logger.error("[命令发送失败] 看守位控制: {}", e.getMessage()); 279 logger.error("[命令发送失败] 看守位控制: {}", e.getMessage());
280 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage()); 280 throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());