修复WVP作为下级平台接受devicecontrol命令处理-调试修改逻辑
parent
25fca14e62
commit
55ee6f5f0d
|
@ -1,5 +1,7 @@
|
|||
package com.genersoft.iot.vmp.common.enums;
|
||||
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.utils.XmlUtil;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import org.dom4j.Element;
|
||||
|
@ -60,7 +62,7 @@ public enum DeviceControlType {
|
|||
|
||||
public static DeviceControlType typeOf(Element rootElement) {
|
||||
for (DeviceControlType item : DeviceControlType.values()) {
|
||||
if (!ObjectUtils.isEmpty(getText(rootElement,item.val))) {
|
||||
if (!ObjectUtils.isEmpty(rootElement.element(item.val)) || !ObjectUtils.isEmpty(rootElement.elements(item.val))) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
|
||||
import lombok.Data;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 设备信息查询响应
|
||||
*
|
||||
* @author Y.G
|
||||
* @version 1.0
|
||||
* @date 2022/6/28 14:55
|
||||
*/
|
||||
@Data
|
||||
public class DragZoomRequest {
|
||||
/**
|
||||
* 序列号
|
||||
*/
|
||||
@MessageElement("SN")
|
||||
private String sn;
|
||||
|
||||
@MessageElement("DeviceID")
|
||||
private String deviceId;
|
||||
|
||||
@MessageElement(value = "DragZoomIn")
|
||||
private DragZoom dragZoomIn;
|
||||
|
||||
@MessageElement(value = "DragZoomOut")
|
||||
private DragZoom dragZoomOut;
|
||||
|
||||
/**
|
||||
* 基本参数
|
||||
*/
|
||||
@Data
|
||||
public static class DragZoom {
|
||||
/**
|
||||
* 播放窗口长度像素值
|
||||
*/
|
||||
@MessageElement("Length")
|
||||
protected Integer length;
|
||||
/**
|
||||
* 播放窗口宽度像素值
|
||||
*/
|
||||
@MessageElement("Width")
|
||||
protected Integer width;
|
||||
/**
|
||||
* 拉框中心的横轴坐标像素值
|
||||
*/
|
||||
@MessageElement("MidPointX")
|
||||
protected Integer midPointX;
|
||||
/**
|
||||
* 拉框中心的纵轴坐标像素值
|
||||
*/
|
||||
@MessageElement("MidPointY")
|
||||
protected Integer midPointY;
|
||||
/**
|
||||
* 拉框长度像素值
|
||||
*/
|
||||
@MessageElement("LengthX")
|
||||
protected Integer lengthX;
|
||||
/**
|
||||
* 拉框宽度像素值
|
||||
*/
|
||||
@MessageElement("LengthY")
|
||||
protected Integer lengthY;
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.genersoft.iot.vmp.gb28181.bean;
|
||||
|
||||
import com.genersoft.iot.vmp.gb28181.utils.MessageElement;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* 设备信息查询响应
|
||||
*
|
||||
* @author Y.G
|
||||
* @version 1.0
|
||||
* @date 2022/6/28 14:55
|
||||
*/
|
||||
@Data
|
||||
public class HomePositionRequest {
|
||||
/**
|
||||
* 序列号
|
||||
*/
|
||||
@MessageElement("SN")
|
||||
private String sn;
|
||||
|
||||
@MessageElement("DeviceID")
|
||||
private String deviceId;
|
||||
|
||||
@MessageElement(value = "HomePosition")
|
||||
private HomePosition homePosition;
|
||||
|
||||
|
||||
/**
|
||||
* 基本参数
|
||||
*/
|
||||
@Data
|
||||
public static class HomePosition {
|
||||
/**
|
||||
* 播放窗口长度像素值
|
||||
*/
|
||||
@MessageElement("Enabled")
|
||||
protected String enabled;
|
||||
/**
|
||||
* 播放窗口宽度像素值
|
||||
*/
|
||||
@MessageElement("ResetTime")
|
||||
protected String resetTime;
|
||||
/**
|
||||
* 拉框中心的横轴坐标像素值
|
||||
*/
|
||||
@MessageElement("PresetIndex")
|
||||
protected String presetIndex;
|
||||
|
||||
}
|
||||
}
|
|
@ -226,7 +226,7 @@ public interface ISIPCommander {
|
|||
* @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s)
|
||||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
void homePositionCmd(Device device, String channelId,String frontCmd, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
|
||||
|
||||
/**
|
||||
* 设备配置命令
|
||||
|
|
|
@ -808,7 +808,7 @@ public class SIPCommander implements ISIPCommander {
|
|||
* @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255
|
||||
*/
|
||||
@Override
|
||||
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 {
|
||||
public void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
|
||||
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
String charset = device.getCharset();
|
||||
|
@ -822,9 +822,6 @@ public class SIPCommander implements ISIPCommander {
|
|||
cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
|
||||
}
|
||||
cmdXml.append("<HomePosition>\r\n");
|
||||
if (StringUtils.hasText(frontCmd)){
|
||||
cmdXml.append(frontCmd);
|
||||
}else{
|
||||
if (NumericUtil.isInteger(enabled) && (!enabled.equals("0"))) {
|
||||
cmdXml.append("<Enabled>1</Enabled>\r\n");
|
||||
if (NumericUtil.isInteger(resetTime)) {
|
||||
|
@ -840,8 +837,6 @@ public class SIPCommander implements ISIPCommander {
|
|||
} else {
|
||||
cmdXml.append("<Enabled>0</Enabled>\r\n");
|
||||
}
|
||||
}
|
||||
|
||||
cmdXml.append("</HomePosition>\r\n");
|
||||
cmdXml.append("</Control>\r\n");
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.contro
|
|||
|
||||
import com.genersoft.iot.vmp.common.enums.DeviceControlType;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.DragZoomRequest;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.HomePositionRequest;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
|
||||
import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
|
||||
import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
|
||||
|
@ -20,18 +22,14 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
|||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import javax.sip.*;
|
||||
import javax.sip.address.SipURI;
|
||||
import javax.sip.header.HeaderAddress;
|
||||
import javax.sip.header.ToHeader;
|
||||
import javax.sip.message.Response;
|
||||
import java.text.ParseException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Objects;
|
||||
import java.util.List;
|
||||
|
||||
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText;
|
||||
import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*;
|
||||
|
||||
@Component
|
||||
public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler {
|
||||
|
@ -106,6 +104,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
}
|
||||
}
|
||||
DeviceControlType deviceControlType = DeviceControlType.typeOf(rootElement);
|
||||
logger.info("[接受deviceControl命令] 命令: {}", deviceControlType);
|
||||
if (!ObjectUtils.isEmpty(deviceControlType) && !parentPlatform.getServerGBId().equals(targetGBId)) {
|
||||
//判断是否存在该通道
|
||||
Device deviceForPlatform = storager.queryVideoDeviceByPlatformIdAndChannelId(parentPlatform.getServerGBId(), channelId);
|
||||
|
@ -153,6 +152,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 处理云台指令
|
||||
*
|
||||
* @param device 设备
|
||||
* @param channelId 通道id
|
||||
* @param rootElement
|
||||
|
@ -171,6 +171,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 处理强制关键帧
|
||||
*
|
||||
* @param device 设备
|
||||
* @param channelId 通道id
|
||||
*/
|
||||
|
@ -185,6 +186,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 处理重启命令
|
||||
*
|
||||
* @param device 设备信息
|
||||
*/
|
||||
private void handleTeleBootCmd(Device device, SIPRequest request) {
|
||||
|
@ -198,29 +200,40 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
}
|
||||
|
||||
/**
|
||||
* 处理拉框控制
|
||||
* 处理拉框控制***
|
||||
*
|
||||
* @param device 设备信息
|
||||
* @param channelId 通道id
|
||||
* @param rootElement 根节点
|
||||
* @param type 消息类型
|
||||
*/
|
||||
private void handleDragZoom(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
|
||||
String cmdString = getText(rootElement,type.getVal());
|
||||
try {
|
||||
DragZoomRequest dragZoomRequest = loadElement(rootElement, DragZoomRequest.class);
|
||||
DragZoomRequest.DragZoom dragZoom = dragZoomRequest.getDragZoomIn();
|
||||
if (dragZoom == null) {
|
||||
dragZoom = dragZoomRequest.getDragZoomOut();
|
||||
}
|
||||
StringBuffer cmdXml = new StringBuffer(200);
|
||||
cmdXml.append("<" + type.getVal() + ">\r\n");
|
||||
cmdXml.append(cmdString);
|
||||
cmdXml.append("<Length>" + dragZoom.getLength() + "</Length>\r\n");
|
||||
cmdXml.append("<Width>" + dragZoom.getWidth() + "</Width>\r\n");
|
||||
cmdXml.append("<MidPointX>" + dragZoom.getMidPointX() + "</MidPointX>\r\n");
|
||||
cmdXml.append("<MidPointY>" + dragZoom.getMidPointY() + "</MidPointY>\r\n");
|
||||
cmdXml.append("<LengthX>" + dragZoom.getLengthX() + "</LengthX>\r\n");
|
||||
cmdXml.append("<LengthY>" + dragZoom.getLengthY() + "</LengthY>\r\n");
|
||||
cmdXml.append("</" + type.getVal() + ">\r\n");
|
||||
try {
|
||||
cmder.dragZoomCmd(device, channelId, cmdXml.toString());
|
||||
responseAck(request, Response.OK);
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
} catch (Exception e) {
|
||||
logger.error("[命令发送失败] 拉框控制: {}", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理看守位命令
|
||||
* 处理看守位命令***
|
||||
*
|
||||
* @param device 设备信息
|
||||
* @param channelId 通道id
|
||||
* @param rootElement 根节点
|
||||
|
@ -228,19 +241,21 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
* @param type 消息类型
|
||||
*/
|
||||
private void handleHomePositionCmd(Device device, String channelId, Element rootElement, SIPRequest request, DeviceControlType type) {
|
||||
//获取整个消息主体,我们只需要修改请求头即可
|
||||
String cmdString = getText(rootElement,type.getVal());
|
||||
try {
|
||||
cmder.homePositionCmd(device, channelId, cmdString,null,null,null,
|
||||
HomePositionRequest homePosition = loadElement(rootElement, HomePositionRequest.class);
|
||||
//获取整个消息主体,我们只需要修改请求头即可
|
||||
HomePositionRequest.HomePosition info = homePosition.getHomePosition();
|
||||
cmder.homePositionCmd(device, channelId, info.getEnabled(), info.getResetTime(), info.getPresetIndex(),
|
||||
errorResult -> onError(request, errorResult),
|
||||
okResult -> onOk(request, okResult));
|
||||
} catch (InvalidArgumentException | SipException | ParseException e) {
|
||||
} catch (Exception e) {
|
||||
logger.error("[命令发送失败] 看守位设置: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理告警消息
|
||||
* 处理告警消息***
|
||||
*
|
||||
* @param device 设备信息
|
||||
* @param rootElement 根节点
|
||||
* @param request 请求信息
|
||||
|
@ -250,10 +265,12 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
String alarmMethod = "";
|
||||
//告警类型
|
||||
String alarmType = "";
|
||||
Element info = rootElement.element("Info");
|
||||
List<Element> info = rootElement.elements("Info");
|
||||
if (info != null) {
|
||||
alarmMethod = getText(rootElement,"AlarmMethod");
|
||||
alarmType = getText(rootElement,"AlarmType");
|
||||
for (Element element : info) {
|
||||
alarmMethod = getText(element, "AlarmMethod");
|
||||
alarmType = getText(element, "AlarmType");
|
||||
}
|
||||
}
|
||||
try {
|
||||
cmder.alarmCmd(device, alarmMethod, alarmType,
|
||||
|
@ -266,6 +283,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 处理录像控制
|
||||
*
|
||||
* @param device 设备信息
|
||||
* @param channelId 通道id
|
||||
* @param rootElement 根节点
|
||||
|
@ -286,6 +304,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 处理报警布防/撤防命令
|
||||
*
|
||||
* @param device 设备信息
|
||||
* @param rootElement 根节点
|
||||
* @param request 请求信息
|
||||
|
@ -306,6 +325,7 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
|
||||
/**
|
||||
* 错误响应处理
|
||||
*
|
||||
* @param request 请求
|
||||
* @param eventResult 响应结构
|
||||
*/
|
||||
|
@ -317,8 +337,10 @@ public class DeviceControlQueryMessageHandler extends SIPRequestProcessorParent
|
|||
logger.error("[命令发送失败] 回复: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功响应处理
|
||||
*
|
||||
* @param request 请求
|
||||
* @param eventResult 响应结构
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package com.genersoft.iot.vmp.gb28181.utils;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* @author gaofuwang
|
||||
* @version 1.0
|
||||
* @date 2022/6/28 14:58
|
||||
*/
|
||||
@Target({ElementType.FIELD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface MessageElement {
|
||||
String value();
|
||||
|
||||
String subVal() default "";
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
package com.genersoft.iot.vmp.gb28181.utils;
|
||||
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import com.alibaba.fastjson2.JSONArray;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.genersoft.iot.vmp.gb28181.bean.Device;
|
||||
|
@ -15,12 +16,16 @@ import org.dom4j.io.SAXReader;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import javax.sip.RequestEvent;
|
||||
import javax.sip.message.Request;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.StringReader;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -411,4 +416,76 @@ public class XmlUtil {
|
|||
}
|
||||
return deviceChannel;
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增方法支持内部嵌套
|
||||
*
|
||||
* @param element xmlElement
|
||||
* @param clazz 结果类
|
||||
* @param <T> 泛型
|
||||
* @return 结果对象
|
||||
* @throws NoSuchMethodException
|
||||
* @throws InvocationTargetException
|
||||
* @throws InstantiationException
|
||||
* @throws IllegalAccessException
|
||||
*/
|
||||
public static <T> T loadElement(Element element, Class<T> clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
|
||||
Field[] fields = clazz.getDeclaredFields();
|
||||
T t = clazz.getDeclaredConstructor().newInstance();
|
||||
for (Field field : fields) {
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
MessageElement annotation = field.getAnnotation(MessageElement.class);
|
||||
if (annotation == null) {
|
||||
continue;
|
||||
}
|
||||
String value = annotation.value();
|
||||
String subVal = annotation.subVal();
|
||||
Element element1 = element.element(value);
|
||||
if (element1 == null) {
|
||||
continue;
|
||||
}
|
||||
if ("".equals(subVal)) {
|
||||
// 无下级数据
|
||||
Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType());
|
||||
Object o = simpleTypeDeal(field.getType(), fieldVal);
|
||||
ReflectionUtils.setField(field, t, o);
|
||||
} else {
|
||||
// 存在下级数据
|
||||
ArrayList<Object> list = new ArrayList<>();
|
||||
Type genericType = field.getGenericType();
|
||||
if (!(genericType instanceof ParameterizedType)) {
|
||||
continue;
|
||||
}
|
||||
Class<?> aClass = (Class<?>) ((ParameterizedType) genericType).getActualTypeArguments()[0];
|
||||
for (Element element2 : element1.elements(subVal)) {
|
||||
list.add(loadElement(element2, aClass));
|
||||
}
|
||||
ReflectionUtils.setField(field, t, list);
|
||||
}
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 简单类型处理
|
||||
*
|
||||
* @param tClass
|
||||
* @param val
|
||||
* @return
|
||||
*/
|
||||
private static Object simpleTypeDeal(Class<?> tClass, Object val) {
|
||||
if (tClass.equals(String.class)) {
|
||||
return val.toString();
|
||||
}
|
||||
if (tClass.equals(Integer.class)) {
|
||||
return Integer.valueOf(val.toString());
|
||||
}
|
||||
if (tClass.equals(Double.class)) {
|
||||
return Double.valueOf(val.toString());
|
||||
}
|
||||
if (tClass.equals(Long.class)) {
|
||||
return Long.valueOf(val.toString());
|
||||
}
|
||||
return val;
|
||||
}
|
||||
}
|
|
@ -114,4 +114,7 @@ public interface PlatformChannelMapper {
|
|||
" left join device d on dc.deviceId = d.deviceId\n" +
|
||||
"where dc.channelId = #{channelId} and pgc.platformId=#{platformId}")
|
||||
List<Device> queryDeviceInfoByPlatformIdAndChannelId(String platformId, String channelId);
|
||||
|
||||
@Select("SELECT pgc.platformId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}'")
|
||||
List<String> queryParentPlatformByChannelId(String channelId);
|
||||
}
|
||||
|
|
|
@ -133,6 +133,15 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage {
|
|||
if (allChannelMap.containsKey(deviceChannel.getChannelId())) {
|
||||
deviceChannel.setStreamId(allChannelMap.get(deviceChannel.getChannelId()).getStreamId());
|
||||
deviceChannel.setHasAudio(allChannelMap.get(deviceChannel.getChannelId()).isHasAudio());
|
||||
if (allChannelMap.get(deviceChannel.getChannelId()).getStatus() !=deviceChannel.getStatus()){
|
||||
List<String> strings = platformChannelMapper.queryParentPlatformByChannelId(deviceChannel.getChannelId());
|
||||
if (!CollectionUtils.isEmpty(strings)){
|
||||
strings.forEach(platformId->{
|
||||
eventPublisher.catalogEventPublish(platformId, deviceChannel, deviceChannel.getStatus()==1?CatalogEvent.ON:CatalogEvent.OFF);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
channels.add(deviceChannel);
|
||||
if (!ObjectUtils.isEmpty(deviceChannel.getParentId())) {
|
||||
|
|
|
@ -268,7 +268,7 @@ public class DeviceControl {
|
|||
String uuid = UUID.randomUUID().toString();
|
||||
Device device = storager.queryVideoDevice(deviceId);
|
||||
try {
|
||||
cmder.homePositionCmd(device, channelId,null, enabled, resetTime, presetIndex, event -> {
|
||||
cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> {
|
||||
RequestMessage msg = new RequestMessage();
|
||||
msg.setId(uuid);
|
||||
msg.setKey(key);
|
||||
|
|
Loading…
Reference in New Issue