Commit 55ee6f5f0d363faacdb04e7ff01ef9f23e0b9d7f

Authored by gaofw189
1 parent 25fca14e

修复WVP作为下级平台接受devicecontrol命令处理-调试修改逻辑

src/main/java/com/genersoft/iot/vmp/common/enums/DeviceControlType.java
1 1 package com.genersoft.iot.vmp.common.enums;
2 2  
  3 +import com.alibaba.fastjson2.JSONObject;
  4 +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
3 5 import lombok.AllArgsConstructor;
4 6 import lombok.Getter;
5 7 import org.dom4j.Element;
... ... @@ -60,7 +62,7 @@ public enum DeviceControlType {
60 62  
61 63 public static DeviceControlType typeOf(Element rootElement) {
62 64 for (DeviceControlType item : DeviceControlType.values()) {
63   - if (!ObjectUtils.isEmpty(getText(rootElement,item.val))) {
  65 + if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
64 66 return item;
65 67 }
66 68 }
... ...
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 +import lombok.Data;
  5 +
  6 +import javax.validation.constraints.NotNull;
  7 +import java.util.List;
  8 +
  9 +/**
  10 + * 设备信息查询响应
  11 + *
  12 + * @author Y.G
  13 + * @version 1.0
  14 + * @date 2022/6/28 14:55
  15 + */
  16 +@Data
  17 +public class DragZoomRequest {
  18 + /**
  19 + * 序列号
  20 + */
  21 + @MessageElement("SN")
  22 + private String sn;
  23 +
  24 + @MessageElement("DeviceID")
  25 + private String deviceId;
  26 +
  27 + @MessageElement(value = "DragZoomIn")
  28 + private DragZoom dragZoomIn;
  29 +
  30 + @MessageElement(value = "DragZoomOut")
  31 + private DragZoom dragZoomOut;
  32 +
  33 + /**
  34 + * 基本参数
  35 + */
  36 + @Data
  37 + public static class DragZoom {
  38 + /**
  39 + * 播放窗口长度像素值
  40 + */
  41 + @MessageElement("Length")
  42 + protected Integer length;
  43 + /**
  44 + * 播放窗口宽度像素值
  45 + */
  46 + @MessageElement("Width")
  47 + protected Integer width;
  48 + /**
  49 + * 拉框中心的横轴坐标像素值
  50 + */
  51 + @MessageElement("MidPointX")
  52 + protected Integer midPointX;
  53 + /**
  54 + * 拉框中心的纵轴坐标像素值
  55 + */
  56 + @MessageElement("MidPointY")
  57 + protected Integer midPointY;
  58 + /**
  59 + * 拉框长度像素值
  60 + */
  61 + @MessageElement("LengthX")
  62 + protected Integer lengthX;
  63 + /**
  64 + * 拉框宽度像素值
  65 + */
  66 + @MessageElement("LengthY")
  67 + protected Integer lengthY;
  68 +
  69 + }
  70 +}
... ...
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 +import lombok.Data;
  5 +
  6 +/**
  7 + * 设备信息查询响应
  8 + *
  9 + * @author Y.G
  10 + * @version 1.0
  11 + * @date 2022/6/28 14:55
  12 + */
  13 +@Data
  14 +public class HomePositionRequest {
  15 + /**
  16 + * 序列号
  17 + */
  18 + @MessageElement("SN")
  19 + private String sn;
  20 +
  21 + @MessageElement("DeviceID")
  22 + private String deviceId;
  23 +
  24 + @MessageElement(value = "HomePosition")
  25 + private HomePosition homePosition;
  26 +
  27 +
  28 + /**
  29 + * 基本参数
  30 + */
  31 + @Data
  32 + public static class HomePosition {
  33 + /**
  34 + * 播放窗口长度像素值
  35 + */
  36 + @MessageElement("Enabled")
  37 + protected String enabled;
  38 + /**
  39 + * 播放窗口宽度像素值
  40 + */
  41 + @MessageElement("ResetTime")
  42 + protected String resetTime;
  43 + /**
  44 + * 拉框中心的横轴坐标像素值
  45 + */
  46 + @MessageElement("PresetIndex")
  47 + protected String presetIndex;
  48 +
  49 + }
  50 +}
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -226,7 +226,7 @@ public interface ISIPCommander {
226 226 * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
227 227 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
228 228 */
229   - void homePositionCmd(Device device, String channelId,String frontCmd, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
  229 + void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
230 230  
231 231 /**
232 232 * 设备配置命令
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -808,7 +808,7 @@ public class SIPCommander implements ISIPCommander {
808 808 * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
809 809 */
810 810 @Override
811   - public void homePositionCmd(Device device, String channelId,String frontCmd, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) 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 {
812 812  
813 813 StringBuffer cmdXml = new StringBuffer(200);
814 814 String charset = device.getCharset();
... ... @@ -822,26 +822,21 @@ public class SIPCommander implements ISIPCommander {
822 822 cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
823 823 }
824 824 cmdXml.append("<HomePosition>\r\n");
825   - if (StringUtils.hasText(frontCmd)){
826   - cmdXml.append(frontCmd);
827   - }else{
828   - if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
829   - cmdXml.append("<Enabled>1</Enabled>\r\n");
830   - if (NumericUtil.isInteger(resetTime)) {
831   - cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
832   - } else {
833   - cmdXml.append("<ResetTime>0</ResetTime>\r\n");
834   - }
835   - if (NumericUtil.isInteger(presetIndex)) {
836   - cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
837   - } else {
838   - cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
839   - }
  825 + if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
  826 + cmdXml.append("<Enabled>1</Enabled>\r\n");
  827 + if (NumericUtil.isInteger(resetTime)) {
  828 + cmdXml.append("<ResetTime>" + resetTime + "</ResetTime>\r\n");
840 829 } else {
841   - cmdXml.append("<Enabled>0</Enabled>\r\n");
  830 + cmdXml.append("<ResetTime>0</ResetTime>\r\n");
842 831 }
  832 + if (NumericUtil.isInteger(presetIndex)) {
  833 + cmdXml.append("<PresetIndex>" + presetIndex + "</PresetIndex>\r\n");
  834 + } else {
  835 + cmdXml.append("<PresetIndex>0</PresetIndex>\r\n");
  836 + }
  837 + } else {
  838 + cmdXml.append("<Enabled>0</Enabled>\r\n");
843 839 }
844   -
845 840 cmdXml.append("</HomePosition>\r\n");
846 841 cmdXml.append("</Control>\r\n");
847 842  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java
... ... @@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.contro
2 2  
3 3 import com.genersoft.iot.vmp.common.enums.DeviceControlType;
4 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 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
6 8 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
7 9 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
... ... @@ -20,18 +22,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
20 22 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
21 23 import org.springframework.stereotype.Component;
22 24 import org.springframework.util.ObjectUtils;
23   -import org.springframework.util.StringUtils;
24 25  
25 26 import javax.sip.*;
26 27 import javax.sip.address.SipURI;
27   -import javax.sip.header.HeaderAddress;
28   -import javax.sip.header.ToHeader;
29 28 import javax.sip.message.Response;
30 29 import java.text.ParseException;
31   -import java.util.Iterator;
32   -import java.util.Objects;
  30 +import java.util.List;
33 31  
34   -import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
  32 +import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
35 33  
36 34 @Component
37 35 public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
... ... @@ -83,7 +81,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
83 81 } catch (InvalidArgumentException | ParseException | SipException e) {
84 82 logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage());
85 83 }
86   - taskExecutor.execute(()->{
  84 + taskExecutor.execute(() -> {
87 85 // 远程启动
88 86 // try {
89 87 // Thread.sleep(3000);
... ... @@ -106,7 +104,8 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
106 104 }
107 105 }
108 106 DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement);
109   - if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)){
  107 + logger.info("[接受deviceControl命令] 命令: {}", deviceControlType);
  108 + if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)) {
110 109 //判断是否存在该通道
111 110 Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
112 111 if (deviceForPlatform == null) {
... ... @@ -117,33 +116,33 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
117 116 }
118 117 return;
119 118 }
120   - switch (deviceControlType){
  119 + switch (deviceControlType) {
121 120 case PTZ:
122   - handlePtzCmd(deviceForPlatform,channelId,rootElement,request,DeviceControlType.PTZ);
  121 + handlePtzCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.PTZ);
123 122 break;
124 123 case ALARM:
125   - handleAlarmCmd(deviceForPlatform,rootElement,request);
  124 + handleAlarmCmd(deviceForPlatform, rootElement, request);
126 125 break;
127 126 case GUARD:
128   - handleGuardCmd(deviceForPlatform,rootElement,request,DeviceControlType.GUARD);
  127 + handleGuardCmd(deviceForPlatform, rootElement, request, DeviceControlType.GUARD);
129 128 break;
130 129 case RECORD:
131   - handleRecordCmd(deviceForPlatform,channelId,rootElement,request,DeviceControlType.RECORD);
  130 + handleRecordCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.RECORD);
132 131 break;
133 132 case I_FRAME:
134   - handleIFameCmd(deviceForPlatform,request,channelId);
  133 + handleIFameCmd(deviceForPlatform, request, channelId);
135 134 break;
136 135 case TELE_BOOT:
137   - handleTeleBootCmd(deviceForPlatform,request);
  136 + handleTeleBootCmd(deviceForPlatform, request);
138 137 break;
139 138 case DRAG_ZOOM_IN:
140   - handleDragZoom(deviceForPlatform,channelId,rootElement,request,DeviceControlType.DRAG_ZOOM_IN);
  139 + handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_IN);
141 140 break;
142 141 case DRAG_ZOOM_OUT:
143   - handleDragZoom(deviceForPlatform,channelId,rootElement,request,DeviceControlType.DRAG_ZOOM_OUT);
  142 + handleDragZoom(deviceForPlatform, channelId, rootElement, request, DeviceControlType.DRAG_ZOOM_OUT);
144 143 break;
145 144 case HOME_POSITION:
146   - handleHomePositionCmd(deviceForPlatform,channelId,rootElement,request,DeviceControlType.HOME_POSITION);
  145 + handleHomePositionCmd(deviceForPlatform, channelId, rootElement, request, DeviceControlType.HOME_POSITION);
147 146 break;
148 147 default:
149 148 break;
... ... @@ -153,17 +152,18 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
153 152  
154 153 /**
155 154 * 处理云台指令
156   - * @param device 设备
157   - * @param channelId 通道id
  155 + *
  156 + * @param device 设备
  157 + * @param channelId 通道id
158 158 * @param rootElement
159 159 * @param request
160 160 */
161   - private void handlePtzCmd(Device device,String channelId,Element rootElement,SIPRequest request,DeviceControlType type){
162   - String cmdString = getText(rootElement,type.getVal());
  161 + private void handlePtzCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
  162 + String cmdString = getText(rootElement, type.getVal());
163 163 try {
164 164 cmder.fronEndCmd(device, channelId, cmdString,
165   - errorResult -> onError(request,errorResult),
166   - okResult -> onOk(request,okResult));
  165 + errorResult -> onError(request, errorResult),
  166 + okResult -> onOk(request, okResult));
167 167 } catch (InvalidArgumentException | SipException | ParseException e) {
168 168 logger.error("[命令发送失败] 云台/前端: {}", e.getMessage());
169 169 }
... ... @@ -171,12 +171,13 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
171 171  
172 172 /**
173 173 * 处理强制关键帧
174   - * @param device 设备
  174 + *
  175 + * @param device 设备
175 176 * @param channelId 通道id
176 177 */
177   - private void handleIFameCmd(Device device,SIPRequest request,String channelId){
  178 + private void handleIFameCmd(Device device, SIPRequest request, String channelId) {
178 179 try {
179   - cmder.iFrameCmd(device,channelId);
  180 + cmder.iFrameCmd(device, channelId);
180 181 responseAck(request, Response.OK);
181 182 } catch (InvalidArgumentException | SipException | ParseException e) {
182 183 logger.error("[命令发送失败] 强制关键帧: {}", e.getMessage());
... ... @@ -185,9 +186,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
185 186  
186 187 /**
187 188 * 处理重启命令
  189 + *
188 190 * @param device 设备信息
189 191 */
190   - private void handleTeleBootCmd(Device device,SIPRequest request){
  192 + private void handleTeleBootCmd(Device device, SIPRequest request) {
191 193 try {
192 194 cmder.teleBootCmd(device);
193 195 responseAck(request, Response.OK);
... ... @@ -198,67 +200,82 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
198 200 }
199 201  
200 202 /**
201   - * 处理拉框控制
202   - * @param device 设备信息
203   - * @param channelId 通道id
  203 + * 处理拉框控制***
  204 + *
  205 + * @param device 设备信息
  206 + * @param channelId 通道id
204 207 * @param rootElement 根节点
205   - * @param type 消息类型
  208 + * @param type 消息类型
206 209 */
207   - private void handleDragZoom(Device device,String channelId,Element rootElement,SIPRequest request,DeviceControlType type){
208   - String cmdString = getText(rootElement,type.getVal());
209   - StringBuffer cmdXml = new StringBuffer(200);
210   - cmdXml.append("<" + type.getVal() + ">\r\n");
211   - cmdXml.append(cmdString);
212   - cmdXml.append("</" + type.getVal() + ">\r\n");
  210 + private void handleDragZoom(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
213 211 try {
214   - cmder.dragZoomCmd(device,channelId,cmdXml.toString());
  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());
215 227 responseAck(request, Response.OK);
216   - } catch (InvalidArgumentException | SipException | ParseException e) {
  228 + } catch (Exception e) {
217 229 logger.error("[命令发送失败] 拉框控制: {}", e.getMessage());
218 230 }
219 231  
220 232 }
221 233  
222 234 /**
223   - * 处理看守位命令
224   - * @param device 设备信息
225   - * @param channelId 通道id
  235 + * 处理看守位命令***
  236 + *
  237 + * @param device 设备信息
  238 + * @param channelId 通道id
226 239 * @param rootElement 根节点
227   - * @param request 请求信息
228   - * @param type 消息类型
  240 + * @param request 请求信息
  241 + * @param type 消息类型
229 242 */
230   - private void handleHomePositionCmd(Device device,String channelId,Element rootElement,SIPRequest request,DeviceControlType type){
231   - //获取整个消息主体,我们只需要修改请求头即可
232   - String cmdString = getText(rootElement,type.getVal());
  243 + private void handleHomePositionCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
233 244 try {
234   - cmder.homePositionCmd(device, channelId, cmdString,null,null,null,
235   - errorResult -> onError(request,errorResult),
236   - okResult -> onOk(request,okResult));
237   - } catch (InvalidArgumentException | SipException | ParseException e) {
  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) {
238 252 logger.error("[命令发送失败] 看守位设置: {}", e.getMessage());
239 253 }
240 254 }
241 255  
242 256 /**
243   - * 处理告警消息
244   - * @param device 设备信息
  257 + * 处理告警消息***
  258 + *
  259 + * @param device 设备信息
245 260 * @param rootElement 根节点
246   - * @param request 请求信息
  261 + * @param request 请求信息
247 262 */
248   - private void handleAlarmCmd(Device device,Element rootElement,SIPRequest request){
  263 + private void handleAlarmCmd(Device device, Element rootElement, SIPRequest request) {
249 264 //告警方法
250 265 String alarmMethod = "";
251 266 //告警类型
252 267 String alarmType = "";
253   - Element info = rootElement.element("Info");
254   - if (info !=null){
255   - alarmMethod = getText(rootElement,"AlarmMethod");
256   - alarmType = getText(rootElement,"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 + }
257 274 }
258 275 try {
259   - cmder.alarmCmd(device, alarmMethod,alarmType,
260   - errorResult -> onError(request,errorResult),
261   - okResult -> onOk(request,okResult));
  276 + cmder.alarmCmd(device, alarmMethod, alarmType,
  277 + errorResult -> onError(request, errorResult),
  278 + okResult -> onOk(request, okResult));
262 279 } catch (InvalidArgumentException | SipException | ParseException e) {
263 280 logger.error("[命令发送失败] 告警消息: {}", e.getMessage());
264 281 }
... ... @@ -266,19 +283,20 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
266 283  
267 284 /**
268 285 * 处理录像控制
269   - * @param device 设备信息
270   - * @param channelId 通道id
  286 + *
  287 + * @param device 设备信息
  288 + * @param channelId 通道id
271 289 * @param rootElement 根节点
272   - * @param request 请求信息
273   - * @param type 消息类型
  290 + * @param request 请求信息
  291 + * @param type 消息类型
274 292 */
275   - private void handleRecordCmd(Device device,String channelId,Element rootElement,SIPRequest request,DeviceControlType type){
  293 + private void handleRecordCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
276 294 //获取整个消息主体,我们只需要修改请求头即可
277   - String cmdString = getText(rootElement,type.getVal());
  295 + String cmdString = getText(rootElement, type.getVal());
278 296 try {
279   - cmder.recordCmd(device, channelId,cmdString,
280   - errorResult -> onError(request,errorResult),
281   - okResult -> onOk(request,okResult));
  297 + cmder.recordCmd(device, channelId, cmdString,
  298 + errorResult -> onError(request, errorResult),
  299 + okResult -> onOk(request, okResult));
282 300 } catch (InvalidArgumentException | SipException | ParseException e) {
283 301 logger.error("[命令发送失败] 录像控制: {}", e.getMessage());
284 302 }
... ... @@ -286,18 +304,19 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
286 304  
287 305 /**
288 306 * 处理报警布防/撤防命令
289   - * @param device 设备信息
  307 + *
  308 + * @param device 设备信息
290 309 * @param rootElement 根节点
291   - * @param request 请求信息
292   - * @param type 消息类型
  310 + * @param request 请求信息
  311 + * @param type 消息类型
293 312 */
294   - private void handleGuardCmd(Device device,Element rootElement,SIPRequest request,DeviceControlType type){
  313 + private void handleGuardCmd(Device device, Element rootElement, SIPRequest request, DeviceControlType type) {
295 314 //获取整个消息主体,我们只需要修改请求头即可
296   - String cmdString = getText(rootElement,type.getVal());
  315 + String cmdString = getText(rootElement, type.getVal());
297 316 try {
298 317 cmder.guardCmd(device, cmdString,
299   - errorResult -> onError(request,errorResult),
300   - okResult -> onOk(request,okResult));
  318 + errorResult -> onError(request, errorResult),
  319 + okResult -> onOk(request, okResult));
301 320 } catch (InvalidArgumentException | SipException | ParseException e) {
302 321 logger.error("[命令发送失败] 布防/撤防命令: {}", e.getMessage());
303 322 }
... ... @@ -306,10 +325,11 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
306 325  
307 326 /**
308 327 * 错误响应处理
309   - * @param request 请求
  328 + *
  329 + * @param request 请求
310 330 * @param eventResult 响应结构
311 331 */
312   - private void onError(SIPRequest request, SipSubscribe.EventResult eventResult){
  332 + private void onError(SIPRequest request, SipSubscribe.EventResult eventResult) {
313 333 // 失败的回复
314 334 try {
315 335 responseAck(request, eventResult.statusCode, eventResult.msg);
... ... @@ -317,12 +337,14 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
317 337 logger.error("[命令发送失败] 回复: {}", e.getMessage());
318 338 }
319 339 }
  340 +
320 341 /**
321 342 * 成功响应处理
322   - * @param request 请求
  343 + *
  344 + * @param request 请求
323 345 * @param eventResult 响应结构
324 346 */
325   - private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult){
  347 + private void onOk(SIPRequest request, SipSubscribe.EventResult eventResult) {
326 348 // 成功的回复
327 349 try {
328 350 responseAck(request, eventResult.statusCode);
... ...
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 1 package com.genersoft.iot.vmp.gb28181.utils;
2 2  
  3 +import com.alibaba.fastjson2.JSON;
3 4 import com.alibaba.fastjson2.JSONArray;
4 5 import com.alibaba.fastjson2.JSONObject;
5 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
... ... @@ -15,12 +16,16 @@ import org.dom4j.io.SAXReader;
15 16 import org.slf4j.Logger;
16 17 import org.slf4j.LoggerFactory;
17 18 import org.springframework.util.ObjectUtils;
18   -import org.springframework.util.StringUtils;
  19 +import org.springframework.util.ReflectionUtils;
19 20  
20 21 import javax.sip.RequestEvent;
21 22 import javax.sip.message.Request;
22 23 import java.io.ByteArrayInputStream;
23 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 29 import java.util.*;
25 30  
26 31 /**
... ... @@ -411,4 +416,76 @@ public class XmlUtil {
411 416 }
412 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 492 \ No newline at end of file
... ...
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
... ... @@ -114,4 +114,7 @@ public interface PlatformChannelMapper {
114 114 " left join device d on dc.deviceId = d.deviceId\n" +
115 115 "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}")
116 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/VideoManagerStorageImpl.java
... ... @@ -133,6 +133,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
133 133 if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
134 134 deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
135 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 146 channels.add(deviceChannel);
138 147 if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java
... ... @@ -268,7 +268,7 @@ public class DeviceControl {
268 268 String uuid = UUID.randomUUID().toString();
269 269 Device device = storager.queryVideoDevice(deviceId);
270 270 try {
271   - cmder.homePositionCmd(device, channelId,null, enabled, resetTime, presetIndex, event -> {
  271 + cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
272 272 RequestMessage msg = new RequestMessage();
273 273 msg.setId(uuid);
274 274 msg.setKey(key);
... ...