diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogChannelEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogChannelEvent.java new file mode 100644 index 00000000..cf7c9cbd --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogChannelEvent.java @@ -0,0 +1,38 @@ +package com.genersoft.iot.vmp.gb28181.bean; + +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.dom4j.Element; + +import java.lang.reflect.InvocationTargetException; + +@Data +@Slf4j +@EqualsAndHashCode(callSuper = true) +public class CatalogChannelEvent extends DeviceChannel{ + + private String event; + + private DeviceChannel channel; + + public static CatalogChannelEvent decode(Element element) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + Element eventElement = element.element("Event"); + CatalogChannelEvent catalogChannelEvent = new CatalogChannelEvent(); + if (eventElement != null) { + catalogChannelEvent.setEvent(eventElement.getText()); + }else { + catalogChannelEvent.setEvent(CatalogEvent.ADD); + } + DeviceChannel deviceChannel; + if (CatalogEvent.ADD.equalsIgnoreCase(catalogChannelEvent.getEvent()) || + CatalogEvent.UPDATE.equalsIgnoreCase(catalogChannelEvent.getEvent()) ){ + deviceChannel = DeviceChannel.decode(element); + }else { + deviceChannel = DeviceChannel.decodeWithOnlyDeviceId(element); + } + catalogChannelEvent.setChannel(deviceChannel); + return catalogChannelEvent; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogEvent.java deleted file mode 100644 index a3fcdee8..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogEvent.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.bean; - -import com.genersoft.iot.vmp.gb28181.utils.MessageElement; - -public class CatalogEvent extends DeviceChannel{ - - @MessageElement("Event") - private String event; -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java index 5ddf1c46..09f28785 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceChannel.java @@ -1,257 +1,170 @@ package com.genersoft.iot.vmp.gb28181.bean; import com.genersoft.iot.vmp.gb28181.utils.MessageElement; +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import lombok.extern.slf4j.Slf4j; +import org.dom4j.Element; + +import java.lang.reflect.InvocationTargetException; @Data +@Slf4j @Schema(description = "通道信息") @EqualsAndHashCode(callSuper = true) public class DeviceChannel extends CommonGBChannel { + @Schema(description = "数据库自增ID") + private int id; + @MessageElement("DeviceID") @Schema(description = "编码") private String deviceId; - @MessageElement("DeviceID") + @MessageElement("Name") @Schema(description = "名称") private String name; - @MessageElement("DeviceID") + @MessageElement("Manufacturer") @Schema(description = "设备厂商") private String manufacturer; - @MessageElement("DeviceID") + @MessageElement("Model") @Schema(description = "设备型号") private String model; // 2016 - @MessageElement("DeviceID") + @MessageElement("Owner") @Schema(description = "设备归属") private String owner; - @MessageElement("DeviceID") + @MessageElement("CivilCode") @Schema(description = "行政区域") private String civilCode; - @MessageElement("DeviceID") + @MessageElement("Block") @Schema(description = "警区") private String block; - @MessageElement("DeviceID") + @MessageElement("Address") @Schema(description = "安装地址") private String address; - @MessageElement("DeviceID") - @Schema(description = "是否有子设备") - private Boolean parental; + @MessageElement("Parental") + @Schema(description = "是否有子设备(必选)1有,0没有") + private Integer parental; - @MessageElement("DeviceID") + @MessageElement("ParentID") @Schema(description = "父节点ID") private String parentId; // 2016 - @MessageElement("DeviceID") + @MessageElement("SafetyWay") @Schema(description = "信令安全模式") private Integer safetyWay; - @MessageElement("DeviceID") + @MessageElement("RegisterWay") @Schema(description = "注册方式") private Integer registerWay; // 2016 - @MessageElement("DeviceID") + @MessageElement("CertNum") @Schema(description = "证书序列号") - private Integer certNum; + private String certNum; // 2016 - @MessageElement("DeviceID") - @Schema(description = "证书有效标识") + @MessageElement("Certifiable") + @Schema(description = "证书有效标识, 缺省为0;证书有效标识:0:无效 1:有效") private Integer certifiable; // 2016 - @MessageElement("DeviceID") + @MessageElement("ErrCode") @Schema(description = "无效原因码(有证书且证书无效的设备必选)") private Integer errCode; // 2016 - @MessageElement("DeviceID") + @MessageElement("EndTime") @Schema(description = "证书终止有效期(有证书且证书无效的设备必选)") - private Integer endTime; + private String endTime; - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机安全能力等级代码") - private String securityLevelCode; - - @MessageElement("DeviceID") + @MessageElement("Secrecy") @Schema(description = "保密属性(必选)缺省为0;0-不涉密,1-涉密") private Integer secrecy; - @MessageElement("DeviceID") + @MessageElement("IPAddress") @Schema(description = "设备/系统IPv4/IPv6地址") private String ipAddress; - @MessageElement("DeviceID") + @MessageElement("Port") @Schema(description = "设备/系统端口") private Integer port; - @MessageElement("DeviceID") + @MessageElement("Password") @Schema(description = "设备口令") private String password; - @MessageElement("DeviceID") + @MessageElement("Status") @Schema(description = "设备状态") - private Boolean status; + private String status; - @MessageElement("DeviceID") + @MessageElement("Longitude") @Schema(description = "经度 WGS-84坐标系") private Double longitude; - @MessageElement("DeviceID") + @MessageElement("Latitude") @Schema(description = ",纬度 WGS-84坐标系") private Double latitude; - @MessageElement("DeviceID") - @Schema(description = "虚拟组织所属的业务分组ID") - private String businessGroupId; - - @MessageElement("DeviceID") + @MessageElement("Info.PTZType") @Schema(description = "摄像机结构类型,标识摄像机类型: 1-球机; 2-半球; 3-固定枪机; 4-遥控枪机;5-遥控半球;6-多目设备的全景/拼接通道;7-多目设备的分割通道") private Integer ptzType; - @MessageElement("DeviceID") - @Schema(description = "摄像机光电成像类型。1-可见光成像;2-热成像;3-雷达成像;4-X光成像;5-深度光场成像;9-其他。可多值,") - private String photoelectricImagingTyp; + @MessageElement("Info.PositionType") + @Schema(description = "摄像机位置类型扩展。1-省际检查站、2-党政机关、3-车站码头、4-中心广场、5-体育场馆、" + + "6-商业中心、7-宗教场所、8-校园周边、9-治安复杂区域、10-交通干线") + private Integer positionType; - @MessageElement("DeviceID") - @Schema(description = "摄像机采集部位类型") - private String capturePositionType; - - @MessageElement("DeviceID") + @MessageElement("Info.RoomType") @Schema(description = "摄像机安装位置室外、室内属性。1-室外、2-室内。") private Integer roomType; - // 2016 - @MessageElement("DeviceID") - @Schema(description = "用途属性") + @MessageElement("Info.UseType") + @Schema(description = "用途属性, 1-治安、2-交通、3-重点。") private Integer useType; - @MessageElement("DeviceID") + @MessageElement("Info.SupplyLightType") @Schema(description = "摄像机补光属性。1-无补光;2-红外补光;3-白光补光;4-激光补光;9-其他") private Integer supplyLightType; - @MessageElement("DeviceID") + @MessageElement("Info.DirectionType") @Schema(description = "摄像机监视方位(光轴方向)属性。1-东(西向东)、2-西(东向西)、3-南(北向南)、4-北(南向北)、" + "5-东南(西北到东南)、6-东北(西南到东北)、7-西南(东北到西南)、8-西北(东南到西北)") private Integer directionType; - @MessageElement("DeviceID") + @MessageElement("Info.Resolution") @Schema(description = "摄像机支持的分辨率,可多值") private String resolution; - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机支持的码流编号列表,用于实时点播时指定码流编号(可选)") - private String streamNumberList; + @MessageElement("Info.BusinessGroupID") + @Schema(description = "虚拟组织所属的业务分组ID") + private String businessGroupId; - @MessageElement("DeviceID") + @MessageElement("Info.DownloadSpeed") @Schema(description = "下载倍速(可选),可多值") private String downloadSpeed; - @MessageElement("DeviceID") + @MessageElement("Info.SVCSpaceSupportMode") @Schema(description = "空域编码能力,取值0-不支持;1-1级增强(1个增强层);2-2级增强(2个增强层);3-3级增强(3个增强层)") private Integer svcSpaceSupportMod; - @MessageElement("DeviceID") + @MessageElement("Info.SVCTimeSupportMode") @Schema(description = "时域编码能力,取值0-不支持;1-1级增强;2-2级增强;3-3级增强(可选)") private Integer svcTimeSupportMode; - // 2022 - @MessageElement("DeviceID") - @Schema(description = " SSVC增强层与基本层比例能力 ") - private String ssvcRatioSupportList; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "移动采集设备类型(仅移动采集设备适用,必选);1-移动机器人载摄像机;2-执法记录仪;3-移动单兵设备;" + - "4-车载视频记录设备;5-无人机载摄像机;9-其他") - private Integer mobileDeviceType; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机水平视场角(可选),取值范围大于0度小于等于360度") - private Double horizontalFieldAngle; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机竖直视场角(可选),取值范围大于0度小于等于360度 ") - private Double verticalFieldAngle; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机可视距离(可选),单位:米") - private Double maxViewDistance; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "基层组织编码(必选,非基层建设时为“000000”)") - private String grassrootsCode; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "监控点位类型(当为摄像机时必选),1-一类视频监控点;2-二类视频监控点;3-三类视频监控点;9-其他点位。") - private Integer poType; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "点位俗称") - private String poCommonName; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "设备MAC地址(可选),用“XX-XX-XX-XX-XX-XX”格式表达") - private String mac; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机卡口功能类型,01-人脸卡口;02-人员卡口;03-机动车卡口;04-非机动车卡口;05-物品卡口;99-其他") - private String functionType; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机视频编码格式") - private String encodeType; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机安装使用时间") - private String installTime; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机所属管理单位名称") - private String managementUnit; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "摄像机所属管理单位联系人的联系方式(电话号码,可多值,用英文半角“/”分割)") - private String contactInfo; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "录像保存天数(可选)") - private Integer recordSaveDays; - - // 2022 - @MessageElement("DeviceID") - @Schema(description = "国民经济行业分类代码(可选)") - private String industrialClassification; - - @Schema(description = "云台类型描述字符串") private String ptzTypeText; @@ -306,4 +219,15 @@ public class DeviceChannel extends CommonGBChannel { break; } } + + public static DeviceChannel decode(Element element) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { + return XmlUtil.elementDecode(element, DeviceChannel.class); + } + + public static DeviceChannel decodeWithOnlyDeviceId(Element element) { + Element deviceElement = element.element("DeviceID"); + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setDeviceId(deviceElement.getText()); + return deviceChannel; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java index 18ad2b01..9c65b873 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java @@ -5,8 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.service.IGbStreamService; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; @@ -23,11 +22,10 @@ import java.util.Map; /** * catalog事件 */ +@Slf4j @Component public class CatalogEventLister implements ApplicationListener { - private final static Logger logger = LoggerFactory.getLogger(CatalogEventLister.class); - @Autowired private IVideoManagerStorage storager; @@ -66,9 +64,9 @@ public class CatalogEventLister implements ApplicationListener { if (event.getDeviceChannels() != null) { if (platforms.size() > 0) { for (DeviceChannel deviceChannel : event.getDeviceChannels()) { - List parentPlatformsForGB = storager.queryPlatFormListForGBWithGBId(deviceChannel.getChannelId(), platforms); - parentPlatformMap.put(deviceChannel.getChannelId(), parentPlatformsForGB); - channelMap.put(deviceChannel.getChannelId(), deviceChannel); + List parentPlatformsForGB = storager.queryPlatFormListForGBWithGBId(deviceChannel.getDeviceId(), platforms); + parentPlatformMap.put(deviceChannel.getDeviceId(), parentPlatformsForGB); + channelMap.put(deviceChannel.getDeviceId(), deviceChannel); } } }else if (event.getGbStreams() != null) { @@ -106,12 +104,12 @@ public class CatalogEventLister implements ApplicationListener { } } if (deviceChannelList.size() > 0) { - logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); + log.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); try { sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException | IllegalAccessException e) { - logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); + log.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); } } }else if (parentPlatformMap.keySet().size() > 0) { @@ -123,16 +121,16 @@ public class CatalogEventLister implements ApplicationListener { if (subscribeInfo == null) { continue; } - logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); + log.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); List deviceChannelList = new ArrayList<>(); DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setChannelId(gbId); + deviceChannel.setDeviceId(gbId); deviceChannelList.add(deviceChannel); try { sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException | IllegalAccessException e) { - logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); + log.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); } } } @@ -157,12 +155,12 @@ public class CatalogEventLister implements ApplicationListener { } } if (!deviceChannelList.isEmpty()) { - logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); + log.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); try { sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException | IllegalAccessException e) { - logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); + log.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); } } }else if (!parentPlatformMap.keySet().isEmpty()) { @@ -174,7 +172,7 @@ public class CatalogEventLister implements ApplicationListener { if (subscribeInfo == null) { continue; } - logger.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); + log.info("[Catalog事件: {}]平台:{},影响通道{}", event.getType(), platform.getServerGBId(), gbId); List deviceChannelList = new ArrayList<>(); DeviceChannel deviceChannel = channelMap.get(gbId); deviceChannelList.add(deviceChannel); @@ -187,7 +185,7 @@ public class CatalogEventLister implements ApplicationListener { sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), platform, deviceChannelList, subscribeInfo, null); } catch (InvalidArgumentException | ParseException | NoSuchFieldException | SipException | IllegalAccessException e) { - logger.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); + log.error("[命令发送失败] 国标级联 Catalog通知: {}", e.getMessage()); } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java index c832161a..f90b93fc 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.CatalogChannelEvent; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData; @@ -10,14 +11,12 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.service.IDeviceChannelService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.DateUtil; +import lombok.extern.slf4j.Slf4j; import org.dom4j.DocumentException; import org.dom4j.Element; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; @@ -25,6 +24,8 @@ import org.springframework.transaction.annotation.Transactional; import javax.sip.RequestEvent; import javax.sip.header.FromHeader; +import java.lang.reflect.InvocationTargetException; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -36,12 +37,10 @@ import java.util.concurrent.CopyOnWriteArrayList; /** * SIP命令类型: NOTIFY请求中的目录请求处理 */ +@Slf4j @Component public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent { - - private final static Logger logger = LoggerFactory.getLogger(NotifyRequestForCatalogProcessor.class); - private final List updateChannelOnlineList = new CopyOnWriteArrayList<>(); private final List updateChannelOfflineList = new CopyOnWriteArrayList<>(); private final Map updateChannelMap = new ConcurrentHashMap<>(); @@ -72,7 +71,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @Transactional public void process(RequestEvent evt) { if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { - logger.error("[notify-目录订阅] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); + log.error("[notify-目录订阅] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); return; } taskQueue.offer(new HandlerCatchData(evt, null, null)); @@ -95,12 +94,12 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent Device device = redisCatchStorage.getDevice(deviceId); if (device == null || !device.isOnLine()) { - logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId() : "")); + log.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId() : "")); return; } Element rootElement = getRootElement(evt, device.getCharset()); if (rootElement == null) { - logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest()); + log.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest()); return; } Element deviceListElement = rootElement.element("DeviceList"); @@ -113,132 +112,134 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent // 遍历DeviceList while (deviceListIterator.hasNext()) { Element itemDevice = deviceListIterator.next(); - Element eventElement = itemDevice.element("Event"); - String event; - if (eventElement == null) { - logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId() : "")); - event = CatalogEvent.ADD; - } else { - event = eventElement.getText().toUpperCase(); - } - DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, event); - - - if (channel == null) { - logger.info("[收到目录订阅]:但是解析失败 {}", new String(evt.getRequest().getRawContent())); + CatalogChannelEvent catalogChannelEvent = null; + try { + catalogChannelEvent = CatalogChannelEvent.decode(itemDevice); + if (catalogChannelEvent.getChannel() == null) { + log.info("[解析CatalogChannelEvent]成功:但是解析通道信息失败, 原文如下: \n{}", new String(evt.getRequest().getRawContent())); + continue; + } + } catch (InvocationTargetException | NoSuchMethodException | InstantiationException | + IllegalAccessException e) { + log.error("[解析CatalogChannelEvent]失败,", e); + log.error("[解析CatalogChannelEvent]失败原文: \n{}", new String(evt.getRequest().getRawContent(), Charset.forName(device.getCharset()))); + continue; + } + if (catalogChannelEvent == null) { continue; } - if (channel.getParentId() != null && channel.getParentId().equals(sipConfig.getId())) { - channel.setParentId(null); - } - channel.setDeviceId(device.getDeviceId()); - logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getDeviceId()); - switch (event) { + + log.info("[收到目录订阅]:{}/{}-{}", device.getDeviceId(), + catalogChannelEvent.getChannel().getDeviceId(), catalogChannelEvent.getEvent()); + switch (catalogChannelEvent.getEvent()) { case CatalogEvent.ON: // 上线 - logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); - updateChannelOnlineList.add(channel); + log.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); + updateChannelOnlineList.add(catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), true); + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), true); } break; case CatalogEvent.OFF: // 离线 - logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); if (userSetting.getRefuseChannelStatusChannelFormNotify()) { - logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); } else { - updateChannelOfflineList.add(channel); + updateChannelOfflineList.add(catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), false); } } break; case CatalogEvent.VLOST: // 视频丢失 - logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); if (userSetting.getRefuseChannelStatusChannelFormNotify()) { - logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); } else { - updateChannelOfflineList.add(channel); + updateChannelOfflineList.add(catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), false); } } break; case CatalogEvent.DEFECT: // 故障 - logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); if (userSetting.getRefuseChannelStatusChannelFormNotify()) { - logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); } else { - updateChannelOfflineList.add(channel); + updateChannelOfflineList.add(catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false); + redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), false); } } break; case CatalogEvent.ADD: // 增加 - logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); // 判断此通道是否存在 - DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId()); + DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, catalogChannelEvent.getChannel().getDeviceId()); if (deviceChannel != null) { - logger.info("[增加通道] 已存在,不发送通知只更新,设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[增加通道] 已存在,不发送通知只更新,设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); + DeviceChannel channel = catalogChannelEvent.getChannel(); channel.setId(deviceChannel.getId()); - channel.setHasAudio(null); - updateChannelMap.put(channel.getChannelId(), channel); + channel.setHasAudio(deviceChannel.getHasAudio()); + channel.setUpdateTime(DateUtil.getNow()); + updateChannelMap.put(catalogChannelEvent.getChannel().getDeviceId(), channel); } else { - addChannelMap.put(channel.getChannelId(), channel); + addChannelMap.put(catalogChannelEvent.getChannel().getDeviceId(), catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), true); + redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), true); } } break; case CatalogEvent.DEL: // 删除 - logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); - deleteChannelList.add(channel); + log.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); + deleteChannelList.add(catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), false); + redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), false); } break; case CatalogEvent.UPDATE: // 更新 - logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); + log.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId()); // 判断此通道是否存在 - DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId()); + DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, catalogChannelEvent.getChannel().getDeviceId()); if (deviceChannelForUpdate != null) { + DeviceChannel channel = catalogChannelEvent.getChannel(); channel.setId(deviceChannelForUpdate.getId()); + channel.setHasAudio(deviceChannelForUpdate.getHasAudio()); channel.setUpdateTime(DateUtil.getNow()); - channel.setHasAudio(null); - updateChannelMap.put(channel.getChannelId(), channel); + updateChannelMap.put(catalogChannelEvent.getChannel().getDeviceId(), channel); } else { - addChannelMap.put(channel.getChannelId(), channel); + addChannelMap.put(catalogChannelEvent.getChannel().getDeviceId(), catalogChannelEvent.getChannel()); if (userSetting.getDeviceStatusNotify()) { // 发送redis消息 - redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), channel.getChannelId(), true); + redisCatchStorage.sendChannelAddOrDelete(device.getDeviceId(), catalogChannelEvent.getChannel().getDeviceId(), true); } } break; default: - logger.warn("[ NotifyCatalog ] event not found : {}", event); + log.warn("[ NotifyCatalog ] event not found : {}", catalogChannelEvent.getEvent()); } // 转发变化信息 - eventPublisher.catalogEventPublish(null, channel, event); + eventPublisher.catalogEventPublish(null, catalogChannelEvent.getChannel(), catalogChannelEvent.getEvent()); } } } catch (DocumentException e) { - logger.error("未处理的异常 ", e); + log.error("未处理的异常 ", e); } } taskQueue.clear(); @@ -255,33 +256,33 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent try { executeSaveForAdd(); } catch (Exception e) { - logger.error("[存储收到的增加通道] 异常: ", e ); + log.error("[存储收到的增加通道] 异常: ", e ); } try { executeSaveForOnline(); } catch (Exception e) { - logger.error("[存储收到的通道上线] 异常: ", e ); + log.error("[存储收到的通道上线] 异常: ", e ); } try { executeSaveForOffline(); } catch (Exception e) { - logger.error("[存储收到的通道离线] 异常: ", e ); + log.error("[存储收到的通道离线] 异常: ", e ); } try { executeSaveForUpdate(); } catch (Exception e) { - logger.error("[存储收到的更新通道] 异常: ", e ); + log.error("[存储收到的更新通道] 异常: ", e ); } try { executeSaveForDelete(); } catch (Exception e) { - logger.error("[存储收到的删除通道] 异常: ", e ); + log.error("[存储收到的删除通道] 异常: ", e ); } } private void executeSaveForUpdate(){ if (!updateChannelMap.values().isEmpty()) { - logger.info("[存储收到的更新通道], 数量: {}", updateChannelMap.size()); + log.info("[存储收到的更新通道], 数量: {}", updateChannelMap.size()); ArrayList deviceChannels = new ArrayList<>(updateChannelMap.values()); deviceChannelService.batchUpdateChannel(deviceChannels); updateChannelMap.clear(); @@ -319,6 +320,6 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent @Scheduled(fixedRate = 10000) //每1秒执行一次 public void execute(){ - logger.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size()); + log.info("[待处理Notify-目录订阅消息数量]: {}", taskQueue.size()); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java index c16d7f56..c2b0b2de 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java @@ -7,7 +7,6 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import gov.nist.javax.sip.message.SIPRequest; import org.dom4j.DocumentException; @@ -114,8 +113,9 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp if (channelDeviceElement == null) { continue; } - DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, null); - if (channel == null) { + DeviceChannel channel = DeviceChannel.decode(itemDevice); +// DeviceChannel channel = XmlUtil.channelContentHandler(itemDevice, device, null); + if (channel == null || channel.getDeviceId() == null) { logger.info("[收到目录订阅]:但是解析失败 {}", new String(evt.getRequest().getRawContent())); continue; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index cb874802..46e92480 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -2,13 +2,6 @@ package com.genersoft.iot.vmp.gb28181.utils; import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.CivilCodePo; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.utils.CivilCodeUtil; -import com.genersoft.iot.vmp.utils.DateUtil; -import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; import org.dom4j.Attribute; import org.dom4j.Document; @@ -240,388 +233,387 @@ public class XmlUtil { CivilCode, BusinessGroup,VirtualOrganization,Other } - public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event){ - loadElement(itemDevice, DeviceChannel.class) - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setDeviceId(device.getDeviceId()); - Element channdelIdElement = itemDevice.element("DeviceID"); - if (channdelIdElement == null) { - logger.warn("解析Catalog消息时发现缺少 DeviceID"); - return null; - } - String channelId = channdelIdElement.getTextTrim(); - if (ObjectUtils.isEmpty(channelId)) { - logger.warn("解析Catalog消息时发现缺少 DeviceID"); - return null; - } - deviceChannel.setChannelId(channelId); - if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) { - // 除了ADD和update情况下需要识别全部内容, - return deviceChannel; - } - Element nameElement = itemDevice.element("Name"); - // 当通道名称为空时,设置通道名称为通道编码,避免级联时因通道名称为空导致上级接收通道失败 - if (nameElement != null && StringUtils.isNotBlank(nameElement.getText())) { - deviceChannel.setName(nameElement.getText()); - } else { - deviceChannel.setName(channelId); - } - if(channelId.length() <= 8) { - deviceChannel.setHasAudio(false); - CivilCodePo parentCode = CivilCodeUtil.INSTANCE.getParentCode(channelId); - if (parentCode != null) { - deviceChannel.setParentId(parentCode.getCode()); - deviceChannel.setCivilCode(parentCode.getCode()); - }else { - logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId); - } - deviceChannel.setStatus(true); - return deviceChannel; - }else { - if(channelId.length() != 20) { - logger.warn("[xml解析] 失败,编号不符合国标28181定义: {}", channelId); - return null; - } - - int code = Integer.parseInt(channelId.substring(10, 13)); - if (code == 136 || code == 137 || code == 138) { - deviceChannel.setHasAudio(true); - }else { - deviceChannel.setHasAudio(false); - } - // 设备厂商 - String manufacturer = getText(itemDevice, "Manufacturer"); - // 设备型号 - String model = getText(itemDevice, "Model"); - // 设备归属 - String owner = getText(itemDevice, "Owner"); - // 行政区域 - String civilCode = getText(itemDevice, "CivilCode"); - // 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织 - String businessGroupID = getText(itemDevice, "BusinessGroupID"); - // 父设备/区域/系统ID - String parentID = getText(itemDevice, "ParentID"); - if (parentID != null && parentID.equalsIgnoreCase("null")) { - parentID = null; - } - // 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式 - String registerWay = getText(itemDevice, "RegisterWay"); - // 保密属性(必选)缺省为0;0:不涉密,1:涉密 - String secrecy = getText(itemDevice, "Secrecy"); - // 安装地址 - String address = getText(itemDevice, "Address"); - - switch (code){ - case 200: - // 系统目录 - if (!ObjectUtils.isEmpty(manufacturer)) { - deviceChannel.setManufacture(manufacturer); - } - if (!ObjectUtils.isEmpty(model)) { - deviceChannel.setModel(model); - } - if (!ObjectUtils.isEmpty(owner)) { - deviceChannel.setOwner(owner); - } - if (!ObjectUtils.isEmpty(civilCode)) { - deviceChannel.setCivilCode(civilCode); - deviceChannel.setParentId(civilCode); - }else { - if (!ObjectUtils.isEmpty(parentID)) { - deviceChannel.setParentId(parentID); - } - } - if (!ObjectUtils.isEmpty(address)) { - deviceChannel.setAddress(address); - } - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(registerWay)) { - try { - deviceChannel.setRegisterWay(Integer.parseInt(registerWay)); - }catch (NumberFormatException exception) { - logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); - } - } - if (!ObjectUtils.isEmpty(secrecy)) { - deviceChannel.setSecrecy(secrecy); - } - return deviceChannel; - case 215: - // 业务分组 - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(parentID)) { - if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) { - deviceChannel.setParentId(parentID); - } - }else { - logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId"); - if (!ObjectUtils.isEmpty(civilCode)) { - deviceChannel.setCivilCode(civilCode); - } - } - break; - case 216: - // 虚拟组织 - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setBusinessGroupId(businessGroupID); - } - - if (!ObjectUtils.isEmpty(parentID)) { - if (parentID.contains("/")) { - String[] parentIdArray = parentID.split("/"); - parentID = parentIdArray[parentIdArray.length - 1]; - } - deviceChannel.setParentId(parentID); - }else { - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setParentId(businessGroupID); - } - } - break; - default: - // 设备目录 - if (!ObjectUtils.isEmpty(manufacturer)) { - deviceChannel.setManufacture(manufacturer); - } - if (!ObjectUtils.isEmpty(model)) { - deviceChannel.setModel(model); - } - if (!ObjectUtils.isEmpty(owner)) { - deviceChannel.setOwner(owner); - } - if (!ObjectUtils.isEmpty(civilCode) - && civilCode.length() <= 8 - && NumberUtils.isParsable(civilCode) - && civilCode.length()%2 == 0 - ) { - deviceChannel.setCivilCode(civilCode); - } - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setBusinessGroupId(businessGroupID); - } - - // 警区 - String block = getText(itemDevice, "Block"); - if (!ObjectUtils.isEmpty(block)) { - deviceChannel.setBlock(block); - } - if (!ObjectUtils.isEmpty(address)) { - deviceChannel.setAddress(address); - } - - if (!ObjectUtils.isEmpty(secrecy)) { - deviceChannel.setSecrecy(secrecy); - } - - // 当为设备时,是否有子设备(必选)1有,0没有 - String parental = getText(itemDevice, "Parental"); - if (!ObjectUtils.isEmpty(parental)) { - try { - // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1 - if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) { - deviceChannel.setParental(0); - }else { - deviceChannel.setParental(1); - } - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 parental失败: {}", parental); - } - } - // 父设备/区域/系统ID - - if (!ObjectUtils.isEmpty(parentID) ) { - if (parentID.contains("/")) { - String[] parentIdArray = parentID.split("/"); - deviceChannel.setParentId(parentIdArray[parentIdArray.length - 1]); - }else { - if (parentID.length()%2 == 0) { - deviceChannel.setParentId(parentID); - }else { - logger.warn("[xml解析] 不规范的parentID:{}, 已舍弃", parentID); - } - } - }else { - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setParentId(businessGroupID); - }else { - if (!ObjectUtils.isEmpty(deviceChannel.getCivilCode())) { - deviceChannel.setParentId(deviceChannel.getCivilCode()); - } - } - } - // 注册方式 - if (!ObjectUtils.isEmpty(registerWay)) { - try { - int registerWayInt = Integer.parseInt(registerWay); - deviceChannel.setRegisterWay(registerWayInt); - }catch (NumberFormatException exception) { - logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); - deviceChannel.setRegisterWay(1); - } - }else { - deviceChannel.setRegisterWay(1); - } - - // 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式 - String safetyWay = getText(itemDevice, "SafetyWay"); - if (!ObjectUtils.isEmpty(safetyWay)) { - try { - deviceChannel.setSafetyWay(Integer.parseInt(safetyWay)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 safetyWay失败: {}", safetyWay); - } - } - - // 证书序列号(有证书的设备必选) - String certNum = getText(itemDevice, "CertNum"); - if (!ObjectUtils.isEmpty(certNum)) { - deviceChannel.setCertNum(certNum); - } - - // 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效 - String certifiable = getText(itemDevice, "Certifiable"); - if (!ObjectUtils.isEmpty(certifiable)) { - try { - deviceChannel.setCertifiable(Integer.parseInt(certifiable)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 Certifiable失败: {}", certifiable); - } - } - - // 无效原因码(有证书且证书无效的设备必选) - String errCode = getText(itemDevice, "ErrCode"); - if (!ObjectUtils.isEmpty(errCode)) { - try { - deviceChannel.setErrCode(Integer.parseInt(errCode)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 ErrCode失败: {}", errCode); - } - } - - // 证书终止有效期(有证书的设备必选) - String endTime = getText(itemDevice, "EndTime"); - if (!ObjectUtils.isEmpty(endTime)) { - deviceChannel.setEndTime(endTime); - } - - - // 设备/区域/系统IP地址 - String ipAddress = getText(itemDevice, "IPAddress"); - if (!ObjectUtils.isEmpty(ipAddress)) { - deviceChannel.setIpAddress(ipAddress); - } - - // 设备/区域/系统端口 - String port = getText(itemDevice, "Port"); - if (!ObjectUtils.isEmpty(port)) { - try { - deviceChannel.setPort(Integer.parseInt(port)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 Port失败: {}", port); - } - } - - // 设备口令 - String password = getText(itemDevice, "Password"); - if (!ObjectUtils.isEmpty(password)) { - deviceChannel.setPassword(password); - } - - - // 设备状态 - String status = getText(itemDevice, "Status"); - if (status != null) { - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 - if (status.equalsIgnoreCase("ON") || status.equalsIgnoreCase("On") || status.equalsIgnoreCase("ONLINE") || status.equalsIgnoreCase("OK")) { - deviceChannel.setStatus(true); - } - if (status.equalsIgnoreCase("OFF") || status.equalsIgnoreCase("Off") || status.equalsIgnoreCase("OFFLINE")) { - deviceChannel.setStatus(false); - } - }else { - deviceChannel.setStatus(true); - } -// logger.info("状态字符串: {}", status); -// logger.info("状态结果: {}", deviceChannel.isStatus()); - // 经度 - String longitude = getText(itemDevice, "Longitude"); - if (NumericUtil.isDouble(longitude)) { - deviceChannel.setLongitude(Double.parseDouble(longitude)); - } else { - deviceChannel.setLongitude(0.00); - } - - // 纬度 - String latitude = getText(itemDevice, "Latitude"); - if (NumericUtil.isDouble(latitude)) { - deviceChannel.setLatitude(Double.parseDouble(latitude)); - } else { - deviceChannel.setLatitude(0.00); - } - - deviceChannel.setGpsTime(DateUtil.getNow()); - - // -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机。当目录项为摄像机时可选 - String ptzType = getText(itemDevice, "PTZType"); - if (ObjectUtils.isEmpty(ptzType)) { - //兼容INFO中的信息 - Element info = itemDevice.element("Info"); - String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType"); - if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){ - try { - deviceChannel.setPtzType(Integer.parseInt(ptzTypeFromInfo)); - }catch (NumberFormatException e){ - logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo); - } - } - } else { - try { - deviceChannel.setPtzType(Integer.parseInt(ptzType)); - }catch (NumberFormatException e){ - logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType); - } - } - - // TODO 摄像机位置类型扩展。 - // 1-省际检查站、 - // 2-党政机关、 - // 3-车站码头、 - // 4-中心广场、 - // 5-体育场馆、 - // 6-商业中心、 - // 7-宗教场所、 - // 8-校园周边、 - // 9-治安复杂区域、 - // 10-交通干线。 - // String positionType = getText(itemDevice, "PositionType"); - - // TODO 摄像机安装位置室外、室内属性。1-室外、2-室内。 - // String roomType = getText(itemDevice, "RoomType"); - // TODO 摄像机用途属性 - // String useType = getText(itemDevice, "UseType"); - // TODO 摄像机补光属性。1-无补光、2-红外补光、3-白光补光 - // String supplyLightType = getText(itemDevice, "SupplyLightType"); - // TODO 摄像机监视方位属性。1-东、2-西、3-南、4-北、5-东南、6-东北、7-西南、8-西北。 - // String directionType = getText(itemDevice, "DirectionType"); - // TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以“/”分隔。分辨率取值参见附录 F中SDPf字段规定 - // String resolution = getText(itemDevice, "Resolution"); - - // TODO 下载倍速范围(可选),各可选参数以“/”分隔,如设备支持1,2,4倍速下载则应写为“1/2/4 - // String downloadSpeed = getText(itemDevice, "DownloadSpeed"); - // TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层) - // String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode"); - // TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强 - // String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode"); - - - deviceChannel.setSecrecy(secrecy); - break; - } - } - - return deviceChannel; - } +// public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event){ +// DeviceChannel deviceChannel = new DeviceChannel(); +// deviceChannel.setDeviceId(device.getDeviceId()); +// Element channdelIdElement = itemDevice.element("DeviceID"); +// if (channdelIdElement == null) { +// logger.warn("解析Catalog消息时发现缺少 DeviceID"); +// return null; +// } +// String channelId = channdelIdElement.getTextTrim(); +// if (ObjectUtils.isEmpty(channelId)) { +// logger.warn("解析Catalog消息时发现缺少 DeviceID"); +// return null; +// } +// deviceChannel.setDeviceId(channelId); +// if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) { +// // 除了ADD和update情况下需要识别全部内容, +// return deviceChannel; +// } +// Element nameElement = itemDevice.element("Name"); +// // 当通道名称为空时,设置通道名称为通道编码,避免级联时因通道名称为空导致上级接收通道失败 +// if (nameElement != null && StringUtils.isNotBlank(nameElement.getText())) { +// deviceChannel.setName(nameElement.getText()); +// } else { +// deviceChannel.setName(channelId); +// } +// if(channelId.length() <= 8) { +// deviceChannel.setHasAudio(false); +// CivilCodePo parentCode = CivilCodeUtil.INSTANCE.getParentCode(channelId); +// if (parentCode != null) { +// deviceChannel.setParentId(parentCode.getCode()); +// deviceChannel.setCivilCode(parentCode.getCode()); +// }else { +// logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId); +// } +// deviceChannel.setStatus("ON"); +// return deviceChannel; +// }else { +// if(channelId.length() != 20) { +// logger.warn("[xml解析] 失败,编号不符合国标28181定义: {}", channelId); +// return null; +// } +// +// int code = Integer.parseInt(channelId.substring(10, 13)); +// if (code == 136 || code == 137 || code == 138) { +// deviceChannel.setHasAudio(true); +// }else { +// deviceChannel.setHasAudio(false); +// } +// // 设备厂商 +// String manufacturer = getText(itemDevice, "Manufacturer"); +// // 设备型号 +// String model = getText(itemDevice, "Model"); +// // 设备归属 +// String owner = getText(itemDevice, "Owner"); +// // 行政区域 +// String civilCode = getText(itemDevice, "CivilCode"); +// // 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织 +// String businessGroupID = getText(itemDevice, "BusinessGroupID"); +// // 父设备/区域/系统ID +// String parentID = getText(itemDevice, "ParentID"); +// if (parentID != null && parentID.equalsIgnoreCase("null")) { +// parentID = null; +// } +// // 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式 +// String registerWay = getText(itemDevice, "RegisterWay"); +// // 保密属性(必选)缺省为0;0:不涉密,1:涉密 +// String secrecy = getText(itemDevice, "Secrecy"); +// // 安装地址 +// String address = getText(itemDevice, "Address"); +// +// switch (code){ +// case 200: +// // 系统目录 +// if (!ObjectUtils.isEmpty(manufacturer)) { +// deviceChannel.setManufacture(manufacturer); +// } +// if (!ObjectUtils.isEmpty(model)) { +// deviceChannel.setModel(model); +// } +// if (!ObjectUtils.isEmpty(owner)) { +// deviceChannel.setOwner(owner); +// } +// if (!ObjectUtils.isEmpty(civilCode)) { +// deviceChannel.setCivilCode(civilCode); +// deviceChannel.setParentId(civilCode); +// }else { +// if (!ObjectUtils.isEmpty(parentID)) { +// deviceChannel.setParentId(parentID); +// } +// } +// if (!ObjectUtils.isEmpty(address)) { +// deviceChannel.setAddress(address); +// } +// deviceChannel.setStatus(true); +// if (!ObjectUtils.isEmpty(registerWay)) { +// try { +// deviceChannel.setRegisterWay(Integer.parseInt(registerWay)); +// }catch (NumberFormatException exception) { +// logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); +// } +// } +// if (!ObjectUtils.isEmpty(secrecy)) { +// deviceChannel.setSecrecy(secrecy); +// } +// return deviceChannel; +// case 215: +// // 业务分组 +// deviceChannel.setStatus(true); +// if (!ObjectUtils.isEmpty(parentID)) { +// if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) { +// deviceChannel.setParentId(parentID); +// } +// }else { +// logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId"); +// if (!ObjectUtils.isEmpty(civilCode)) { +// deviceChannel.setCivilCode(civilCode); +// } +// } +// break; +// case 216: +// // 虚拟组织 +// deviceChannel.setStatus(true); +// if (!ObjectUtils.isEmpty(businessGroupID)) { +// deviceChannel.setBusinessGroupId(businessGroupID); +// } +// +// if (!ObjectUtils.isEmpty(parentID)) { +// if (parentID.contains("/")) { +// String[] parentIdArray = parentID.split("/"); +// parentID = parentIdArray[parentIdArray.length - 1]; +// } +// deviceChannel.setParentId(parentID); +// }else { +// if (!ObjectUtils.isEmpty(businessGroupID)) { +// deviceChannel.setParentId(businessGroupID); +// } +// } +// break; +// default: +// // 设备目录 +// if (!ObjectUtils.isEmpty(manufacturer)) { +// deviceChannel.setManufacture(manufacturer); +// } +// if (!ObjectUtils.isEmpty(model)) { +// deviceChannel.setModel(model); +// } +// if (!ObjectUtils.isEmpty(owner)) { +// deviceChannel.setOwner(owner); +// } +// if (!ObjectUtils.isEmpty(civilCode) +// && civilCode.length() <= 8 +// && NumberUtils.isParsable(civilCode) +// && civilCode.length()%2 == 0 +// ) { +// deviceChannel.setCivilCode(civilCode); +// } +// if (!ObjectUtils.isEmpty(businessGroupID)) { +// deviceChannel.setBusinessGroupId(businessGroupID); +// } +// +// // 警区 +// String block = getText(itemDevice, "Block"); +// if (!ObjectUtils.isEmpty(block)) { +// deviceChannel.setBlock(block); +// } +// if (!ObjectUtils.isEmpty(address)) { +// deviceChannel.setAddress(address); +// } +// +// if (!ObjectUtils.isEmpty(secrecy)) { +// deviceChannel.setSecrecy(secrecy); +// } +// +// // 当为设备时,是否有子设备(必选)1有,0没有 +// String parental = getText(itemDevice, "Parental"); +// if (!ObjectUtils.isEmpty(parental)) { +// try { +// // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1 +// if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) { +// deviceChannel.setParental(0); +// }else { +// deviceChannel.setParental(1); +// } +// }catch (NumberFormatException e) { +// logger.warn("[xml解析] 从通道数据获取 parental失败: {}", parental); +// } +// } +// // 父设备/区域/系统ID +// +// if (!ObjectUtils.isEmpty(parentID) ) { +// if (parentID.contains("/")) { +// String[] parentIdArray = parentID.split("/"); +// deviceChannel.setParentId(parentIdArray[parentIdArray.length - 1]); +// }else { +// if (parentID.length()%2 == 0) { +// deviceChannel.setParentId(parentID); +// }else { +// logger.warn("[xml解析] 不规范的parentID:{}, 已舍弃", parentID); +// } +// } +// }else { +// if (!ObjectUtils.isEmpty(businessGroupID)) { +// deviceChannel.setParentId(businessGroupID); +// }else { +// if (!ObjectUtils.isEmpty(deviceChannel.getCivilCode())) { +// deviceChannel.setParentId(deviceChannel.getCivilCode()); +// } +// } +// } +// // 注册方式 +// if (!ObjectUtils.isEmpty(registerWay)) { +// try { +// int registerWayInt = Integer.parseInt(registerWay); +// deviceChannel.setRegisterWay(registerWayInt); +// }catch (NumberFormatException exception) { +// logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); +// deviceChannel.setRegisterWay(1); +// } +// }else { +// deviceChannel.setRegisterWay(1); +// } +// +// // 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式 +// String safetyWay = getText(itemDevice, "SafetyWay"); +// if (!ObjectUtils.isEmpty(safetyWay)) { +// try { +// deviceChannel.setSafetyWay(Integer.parseInt(safetyWay)); +// }catch (NumberFormatException e) { +// logger.warn("[xml解析] 从通道数据获取 safetyWay失败: {}", safetyWay); +// } +// } +// +// // 证书序列号(有证书的设备必选) +// String certNum = getText(itemDevice, "CertNum"); +// if (!ObjectUtils.isEmpty(certNum)) { +// deviceChannel.setCertNum(certNum); +// } +// +// // 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效 +// String certifiable = getText(itemDevice, "Certifiable"); +// if (!ObjectUtils.isEmpty(certifiable)) { +// try { +// deviceChannel.setCertifiable(Integer.parseInt(certifiable)); +// }catch (NumberFormatException e) { +// logger.warn("[xml解析] 从通道数据获取 Certifiable失败: {}", certifiable); +// } +// } +// +// // 无效原因码(有证书且证书无效的设备必选) +// String errCode = getText(itemDevice, "ErrCode"); +// if (!ObjectUtils.isEmpty(errCode)) { +// try { +// deviceChannel.setErrCode(Integer.parseInt(errCode)); +// }catch (NumberFormatException e) { +// logger.warn("[xml解析] 从通道数据获取 ErrCode失败: {}", errCode); +// } +// } +// +// // 证书终止有效期(有证书的设备必选) +// String endTime = getText(itemDevice, "EndTime"); +// if (!ObjectUtils.isEmpty(endTime)) { +// deviceChannel.setEndTime(endTime); +// } +// +// +// // 设备/区域/系统IP地址 +// String ipAddress = getText(itemDevice, "IPAddress"); +// if (!ObjectUtils.isEmpty(ipAddress)) { +// deviceChannel.setIpAddress(ipAddress); +// } +// +// // 设备/区域/系统端口 +// String port = getText(itemDevice, "Port"); +// if (!ObjectUtils.isEmpty(port)) { +// try { +// deviceChannel.setPort(Integer.parseInt(port)); +// }catch (NumberFormatException e) { +// logger.warn("[xml解析] 从通道数据获取 Port失败: {}", port); +// } +// } +// +// // 设备口令 +// String password = getText(itemDevice, "Password"); +// if (!ObjectUtils.isEmpty(password)) { +// deviceChannel.setPassword(password); +// } +// +// +// // 设备状态 +// String status = getText(itemDevice, "Status"); +// if (status != null) { +// // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 +// if (status.equalsIgnoreCase("ON") || status.equalsIgnoreCase("On") || status.equalsIgnoreCase("ONLINE") || status.equalsIgnoreCase("OK")) { +// deviceChannel.setStatus(true); +// } +// if (status.equalsIgnoreCase("OFF") || status.equalsIgnoreCase("Off") || status.equalsIgnoreCase("OFFLINE")) { +// deviceChannel.setStatus(false); +// } +// }else { +// deviceChannel.setStatus(true); +// } +//// logger.info("状态字符串: {}", status); +//// logger.info("状态结果: {}", deviceChannel.isStatus()); +// // 经度 +// String longitude = getText(itemDevice, "Longitude"); +// if (NumericUtil.isDouble(longitude)) { +// deviceChannel.setLongitude(Double.parseDouble(longitude)); +// } else { +// deviceChannel.setLongitude(0.00); +// } +// +// // 纬度 +// String latitude = getText(itemDevice, "Latitude"); +// if (NumericUtil.isDouble(latitude)) { +// deviceChannel.setLatitude(Double.parseDouble(latitude)); +// } else { +// deviceChannel.setLatitude(0.00); +// } +// +// deviceChannel.setGpsTime(DateUtil.getNow()); +// +// // -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机。当目录项为摄像机时可选 +// String ptzType = getText(itemDevice, "PTZType"); +// if (ObjectUtils.isEmpty(ptzType)) { +// //兼容INFO中的信息 +// Element info = itemDevice.element("Info"); +// String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType"); +// if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){ +// try { +// deviceChannel.setPtzType(Integer.parseInt(ptzTypeFromInfo)); +// }catch (NumberFormatException e){ +// logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo); +// } +// } +// } else { +// try { +// deviceChannel.setPtzType(Integer.parseInt(ptzType)); +// }catch (NumberFormatException e){ +// logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType); +// } +// } +// +// // TODO 摄像机位置类型扩展。 +// // 1-省际检查站、 +// // 2-党政机关、 +// // 3-车站码头、 +// // 4-中心广场、 +// // 5-体育场馆、 +// // 6-商业中心、 +// // 7-宗教场所、 +// // 8-校园周边、 +// // 9-治安复杂区域、 +// // 10-交通干线。 +// // String positionType = getText(itemDevice, "PositionType"); +// +// // TODO 摄像机安装位置室外、室内属性。1-室外、2-室内。 +// // String roomType = getText(itemDevice, "RoomType"); +// // TODO 摄像机用途属性 +// // String useType = getText(itemDevice, "UseType"); +// // TODO 摄像机补光属性。1-无补光、2-红外补光、3-白光补光 +// // String supplyLightType = getText(itemDevice, "SupplyLightType"); +// // TODO 摄像机监视方位属性。1-东、2-西、3-南、4-北、5-东南、6-东北、7-西南、8-西北。 +// // String directionType = getText(itemDevice, "DirectionType"); +// // TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以“/”分隔。分辨率取值参见附录 F中SDPf字段规定 +// // String resolution = getText(itemDevice, "Resolution"); +// +// // TODO 下载倍速范围(可选),各可选参数以“/”分隔,如设备支持1,2,4倍速下载则应写为“1/2/4 +// // String downloadSpeed = getText(itemDevice, "DownloadSpeed"); +// // TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层) +// // String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode"); +// // TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强 +// // String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode"); +// +// +// deviceChannel.setSecrecy(secrecy); +// break; +// } +// } +// +// return deviceChannel; +// } /** * 新增方法支持内部嵌套 @@ -672,6 +664,46 @@ public class XmlUtil { return t; } + public static T elementDecode(Element element, Class 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(); + boolean subVal = value.contains("."); + Element element1 = element.element(value); + if (element1 == null) { + continue; + } + if (!subVal) { + // 无下级数据 + Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType()); + Object o = simpleTypeDeal(field.getType(), fieldVal); + ReflectionUtils.setField(field, t, o); + } else { + String[] pathArray = value.split("."); + Element subElement = element1; + for (String path : pathArray) { + subElement = subElement.element(path); + if (subElement == null) { + break; + } + } + if (subElement == null) { + continue; + } + Object fieldVal = subElement.isTextOnly() ? subElement.getText() : loadElement(subElement, field.getType()); + Object o = simpleTypeDeal(field.getType(), fieldVal); + ReflectionUtils.setField(field, t, o); + } + } + return t; + } + /** * 简单类型处理 * diff --git a/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java b/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java index f37539cd..f4477283 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.service; +import com.genersoft.iot.vmp.gb28181.bean.CommonGBChannel; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; @@ -45,8 +46,8 @@ public interface IGbStreamService { DeviceChannel getDeviceChannelListByStream(GbStream gbStream, String catalogId, ParentPlatform platform); - void sendCatalogMsg(GbStream gbStream, String type); - void sendCatalogMsgs(List gbStreams, String type); + void sendCatalogMsg(CommonGBChannel gbStream, String type); + void sendCatalogMsgs(List gbStreams, String type); /** * 修改gbId或name diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java index b99106e7..8936c642 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java @@ -116,4 +116,7 @@ public interface IStreamPushService { void updatePush(OnStreamChangedHookParam param); + + Map getAllGBId(); + } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java index 46b70f18..0f199378 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java @@ -157,16 +157,16 @@ public class GbStreamServiceImpl implements IGbStreamService { } @Override - public void sendCatalogMsg(GbStream gbStream, String type) { - if (gbStream == null || type == null) { + public void sendCatalogMsg(CommonGBChannel channel, String type) { + if (channel == null || type == null) { logger.warn("[发送目录订阅]类型:流信息或类型为NULL"); return; } - List gbStreams = new ArrayList<>(); - if (gbStream.getGbId() != null) { - gbStreams.add(gbStream); + List gbStreams = new ArrayList<>(); + if (channel.getGbDeviceId() != null) { + gbStreams.add(channel); }else { - GbStream gbStreamIndb = gbStreamMapper.selectOne(gbStream.getApp(), gbStream.getStream()); + GbStream gbStreamIndb = gbStreamMapper.selectOne(channel.getApp(), channel.getStream()); if (gbStreamIndb != null && gbStreamIndb.getGbId() != null){ gbStreams.add(gbStreamIndb); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java index 0d8a8ec6..c73b055c 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java @@ -48,9 +48,6 @@ public class StreamPushServiceImpl implements IStreamPushService { private final static Logger logger = LoggerFactory.getLogger(StreamPushServiceImpl.class); - @Autowired - private GbStreamMapper gbStreamMapper; - @Autowired private StreamPushMapper streamPushMapper; @@ -66,9 +63,6 @@ public class StreamPushServiceImpl implements IStreamPushService { @Autowired private PlatformGbStreamMapper platformGbStreamMapper; - @Autowired - private IGbStreamService gbStreamService; - @Autowired private EventPublisher eventPublisher; @@ -126,16 +120,7 @@ public class StreamPushServiceImpl implements IStreamPushService { streamPushMapper.update(transform); gbStreamMapper.updateMediaServer(event.getApp(), event.getStream(), event.getMediaServer().getId()); } - // TODO 相关的事件自行管理,不需要写入ZLMMediaListManager -// ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream()); -// if ( channelOnlineEventLister != null) { -// try { -// channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());; -// } catch (ParseException e) { -// logger.error("addPush: ", e); -// } -// removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); -// } + // 冗余数据,自己系统中自用 redisCatchStorage.addPushListItem(event.getApp(), event.getStream(), event); @@ -216,7 +201,6 @@ public class StreamPushServiceImpl implements IStreamPushService { streamPushItem.setMediaServerId(item.getMediaServerId()); streamPushItem.setStream(item.getStream()); streamPushItem.setCreateTime(DateUtil.getNow()); - streamPushItem.setVhost(item.getVhost()); streamPushItem.setServerId(item.getSeverId()); return streamPushItem; } @@ -625,6 +609,11 @@ public class StreamPushServiceImpl implements IStreamPushService { return streamPushMapper.getAllAppAndStreamMap(); } + @Override + public Map getAllGBId() { + return streamPushMapper.getAllGBId(); + } + @Override public void updatePush(OnStreamChangedHookParam param) { StreamPush transform = transform(param); diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java index 48b08eac..842277a8 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java @@ -2,10 +2,9 @@ package com.genersoft.iot.vmp.service.redisMsg; import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.gb28181.bean.GbStream; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.StreamPush; import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; @@ -60,43 +59,40 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { List streamPushItems = JSON.parseArray(new String(msg.getBody()), StreamPush.class); //查询全部的app+stream 用于判断是添加还是修改 Map allAppAndStream = streamPushService.getAllAppAndStreamMap(); - Map allGBId = gbStreamService.getAllGBId(); + Map allGBId = streamPushService.getAllGBId(); /** * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 */ List streamPushItemForSave = new ArrayList<>(); List streamPushItemForUpdate = new ArrayList<>(); - for (StreamPush streamPushItem : streamPushItems) { - String app = streamPushItem.getApp(); - String stream = streamPushItem.getStream(); + for (StreamPush streamPush : streamPushItems) { + String app = streamPush.getApp(); + String stream = streamPush.getStream(); boolean contains = allAppAndStream.containsKey(app + stream); //不存在就添加 if (!contains) { - if (allGBId.containsKey(streamPushItem.getGbId())) { - GbStream gbStream = allGBId.get(streamPushItem.getGbId()); + if (allGBId.containsKey(streamPush.getGbDeviceId())) { + StreamPush streamPushInDb = allGBId.get(streamPush.getGbDeviceId()); logger.warn("[REDIS消息-推流设备列表更新-INSERT] 国标编号重复: {}, 已分配给{}/{}", - streamPushItem.getGbId(), gbStream.getApp(), gbStream.getStream()); + streamPushInDb.getGbDeviceId(), streamPushInDb.getApp(), streamPushInDb.getStream()); continue; } - streamPushItem.setStreamType("push"); - streamPushItem.setCreateTime(DateUtil.getNow()); - streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); - streamPushItem.setOriginType(2); - streamPushItem.setOriginTypeStr("rtsp_push"); - streamPushItem.setTotalReaderCount(0); - streamPushItemForSave.add(streamPushItem); - allGBId.put(streamPushItem.getGbId(), streamPushItem); + streamPush.setCreateTime(DateUtil.getNow()); + streamPush.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); + streamPushItemForSave.add(streamPush); + allGBId.put(streamPush.getGbDeviceId(), streamPush); } else { - if (allGBId.containsKey(streamPushItem.getGbId()) - && (!allGBId.get(streamPushItem.getGbId()).getApp().equals(streamPushItem.getApp()) || !allGBId.get(streamPushItem.getGbId()).getStream().equals(streamPushItem.getStream()))) { - GbStream gbStream = allGBId.get(streamPushItem.getGbId()); + if (allGBId.containsKey(streamPush.getGbDeviceId()) + && (!allGBId.get(streamPush.getGbDeviceId()).getApp().equals(streamPush.getApp()) + || !allGBId.get(streamPush.getGbDeviceId()).getStream().equals(streamPush.getStream()))) { + StreamPush streamPushInDb = allGBId.get(streamPush.getGbDeviceId()); logger.warn("[REDIS消息-推流设备列表更新-UPDATE] 国标编号重复: {}, 已分配给{}/{}", - streamPushItem.getGbId(), gbStream.getApp(), gbStream.getStream()); + streamPush.getGbDeviceId(), streamPushInDb.getApp(), streamPushInDb.getStream()); continue; } //存在就只修改 name和gbId - streamPushItemForUpdate.add(streamPushItem); + streamPushItemForUpdate.add(streamPush); } } if (!streamPushItemForSave.isEmpty()) { diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java index a0746dc5..6c6f93d0 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java @@ -204,4 +204,10 @@ public interface StreamPushMapper { Map getAllAppAndStreamMap(); + @MapKey("gb_id") + @Select("SELECT wgs.gb_id, wsp.app, wsp.stream, wgs.gb_id, wgs.name " + + " from wvp_stream_push wsp " + + " left join wvp_gb_stream wgs on wgs.app = wsp.app and wgs.stream = wsp.stream") + Map getAllGBId(); + } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 3f478442..ddb05dee 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -2,4 +2,4 @@ spring: application: name: wvp profiles: - active: local \ No newline at end of file + active: local271 \ No newline at end of file