Commit 55ee6f5f0d363faacdb04e7ff01ef9f23e0b9d7f
1 parent
25fca14e
修复WVP作为下级平台接受devicecontrol命令处理-调试修改逻辑
Showing
11 changed files
with
350 additions
and
105 deletions
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); | ... | ... |