README.md
@@ -105,6 +105,10 @@ - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 # docker快速体验 目前作者的docker-compose因为时间有限维护不及时,这里提供第三方提供的供大家使用,维护不易,大家记得给这位小伙伴点个star。 https://github.com/SaltFish001/wvp_pro_compose [https://github.com/SaltFish001/wvp_pro_compose](https://github.com/SaltFish001/wvp_pro_compose) 这是作者维护的一个镜像,可能存在不及时的问题。 ```shell docker pull 648540858/wvp_pro src/main/java/com/genersoft/iot/vmp/conf/Swagger3Config.java
@@ -14,7 +14,7 @@ @Configuration public class Swagger3Config { @Value("${swagger-ui.enabled}") @Value("${swagger-ui.enabled: true}") private boolean enable; @Bean src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
@@ -21,6 +21,8 @@ EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); this.eventId = eventHeader.getEventId(); this.eventType = eventHeader.getEventType(); ViaHeader viaHeader = (ViaHeader)request.getHeader(ViaHeader.NAME); this.branch = viaHeader.getBranch(); } private String id; @@ -30,6 +32,7 @@ private String eventType; private String fromTag; private String toTag; private String branch; public String getId() { return id; @@ -86,4 +89,12 @@ public void setEventType(String eventType) { this.eventType = eventType; } public String getBranch() { return branch; } public void setBranch(String branch) { this.branch = branch; } } src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
@@ -106,7 +106,7 @@ } if (deviceChannelList.size() > 0) { logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), parentPlatform, deviceChannelList, subscribe, null); } }else if (parentPlatformMap.keySet().size() > 0) { for (String gbId : parentPlatformMap.keySet()) { @@ -121,7 +121,7 @@ DeviceChannel deviceChannel = new DeviceChannel(); deviceChannel.setChannelId(gbId); deviceChannelList.add(deviceChannel); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); } } } @@ -163,7 +163,7 @@ GbStream gbStream = storager.queryStreamInParentPlatform(platform.getServerGBId(), gbId); DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), platform.getDeviceGBId()); deviceChannelList.add(deviceChannelByStream); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo); sipCommanderFroPlatform.sendNotifyForCatalogOther(event.getType(), platform, deviceChannelList, subscribeInfo, null); } } } src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -86,7 +86,7 @@ * @param parentPlatform * @param deviceChannels */ boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo); boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index); /** * 回复recordInfo src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -236,19 +236,18 @@ // via ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), parentPlatform.getTransport(), viaTag); parentPlatform.getTransport(), subscribeInfo.getBranch()); viaHeader.setRPort(); viaHeaders.add(viaHeader); // from SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); String tm = Long.toString(System.currentTimeMillis()); FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, "fromtag" + tm); FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, subscribeInfo.getToTag()); // to SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getToTag()); ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getFromTag()); // Forwards MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); @@ -265,7 +264,10 @@ request.addHeader(userAgentHeader); EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); event.setEventId(subscribeInfo.getEventId()); if (subscribeInfo.getEventId() != null) { event.setEventId(subscribeInfo.getEventId()); } request.addHeader(event); SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active"); src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -89,7 +89,7 @@ sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (event)->{ if (event != null) { logger.info("向上级平台 [ {} ] 注册发上错误: {} ", logger.info("向上级平台 [ {} ] 注册发生错误: {} ", parentPlatform.getServerGBId(), event.msg); } @@ -370,10 +370,10 @@ } try { if (index == deviceChannels.size() - 1) { if (index > deviceChannels.size() - 1) { return true; } Request request = getCatalogNotifyRequest(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo); Request request = getCatalogNotifyRequestForCatalogAddOrUpdate(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo); index += 1; Integer finalIndex = index; transmitRequest(parentPlatform, request, null, (eventResult -> { @@ -386,10 +386,10 @@ return true; } private Request getCatalogNotifyRequest(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type, private Request getCatalogNotifyRequestForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type, SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException, PeerUnavailableException { String catalogXmlContent = getCatalogXmlContent(parentPlatform, channel, size, type); String catalogXmlContent = getCatalogXmlContentForCatalogAddOrUpdate(parentPlatform, channel, size, type, subscribeInfo); CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); @@ -399,14 +399,17 @@ return request; } private String getCatalogXmlContent(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type) { private String getCatalogXmlContentForCatalogAddOrUpdate(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type, SubscribeInfo subscribeInfo) { StringBuffer catalogXml = new StringBuffer(600); if (parentPlatform.getServerGBId().equals(channel.getParentId())) { channel.setParentId(parentPlatform.getDeviceGBId()); } catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); catalogXml.append("<Notify>\r\n"); catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); catalogXml.append("<SumNum>" + sumNum + "</SumNum>\r\n"); catalogXml.append("<SumNum>1</SumNum>\r\n"); catalogXml.append("<DeviceList Num=\"1\">\r\n"); catalogXml.append("<Item>\r\n"); catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); @@ -417,11 +420,15 @@ catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n"); catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); if (channel.getParentId() != null) { catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); } catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n"); catalogXml.append("<Event>" + type + "</Event>\r\n"); if (!"presence".equals(subscribeInfo.getEventType())) { catalogXml.append("<Event>" + type + "</Event>\r\n"); } catalogXml.append("</Item>\r\n"); catalogXml.append("</DeviceList>\r\n"); catalogXml.append("</Notify>\r\n"); @@ -429,7 +436,7 @@ } @Override public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) { public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) { if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 @@ -437,44 +444,56 @@ return false; } for (DeviceChannel channel : deviceChannels) { try { StringBuffer catalogXml = new StringBuffer(600); catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); catalogXml.append("<Notify>\r\n"); catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n"); catalogXml.append("<DeviceList Num=\"1\">\r\n"); catalogXml.append("<Item>\r\n"); catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); catalogXml.append("<Event>" + type + "</Event>\r\n"); catalogXml.append("</Item>\r\n"); catalogXml.append("</DeviceList>\r\n"); catalogXml.append("</Notify>\r\n"); if (index == null) { index = 0; } CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() if (index > deviceChannels.size() - 1) { return true; } try { String catalogXml = getCatalogXmlContentForCatalogOther(deviceChannels.get(index), type, parentPlatform); CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() : udpSipProvider.getNewCallId(); callIdHeader.setCallId(subscribeInfo.getCallId()); String tm = Long.toString(System.currentTimeMillis()); Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml, callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); transmitRequest(parentPlatform, request); Thread.sleep(200); } catch (SipException | ParseException | InvalidArgumentException e) { e.printStackTrace(); return false; } catch (InterruptedException e) { e.printStackTrace(); } index += 1; Integer finalIndex = index; transmitRequest(parentPlatform, request, null, eventResult -> { sendNotifyForCatalogOther(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex); }); } catch (SipException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { e.printStackTrace(); } catch (ParseException e) { e.printStackTrace(); } return true; } private String getCatalogXmlContentForCatalogOther(DeviceChannel channel, String type, ParentPlatform parentPlatform) { if (parentPlatform.getServerGBId().equals(channel.getParentId())) { channel.setParentId(parentPlatform.getDeviceGBId()); } StringBuffer catalogXml = new StringBuffer(600); catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); catalogXml.append("<Notify>\r\n"); catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); catalogXml.append("<SumNum>1</SumNum>\r\n"); catalogXml.append("<DeviceList Num=\"1\">\r\n"); catalogXml.append("<Item>\r\n"); catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); catalogXml.append("<Event>" + type + "</Event>\r\n"); catalogXml.append("</Item>\r\n"); catalogXml.append("</DeviceList>\r\n"); catalogXml.append("</Notify>\r\n"); return catalogXml.toString(); } @Override public boolean recordInfo(DeviceChannel deviceChannel, ParentPlatform parentPlatform, String fromTag, RecordInfo recordInfo) { if ( parentPlatform ==null) { src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
@@ -22,7 +22,7 @@ import javax.sip.RequestEvent; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; @Component public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -105,6 +105,11 @@ storager.insertMobilePosition(mobilePosition); } } if (!StringUtils.isEmpty(deviceAlarm.getDeviceId())) { if (deviceAlarm.getAlarmMethod().equals("5")) { deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType")); } } logger.debug("存储报警信息、报警分类"); // 存储报警信息、报警分类 deviceAlarmService.add(deviceAlarm); src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java
@@ -191,7 +191,7 @@ String channelId = channdelIdElement != null ? channdelIdElement.getTextTrim().toString() : ""; deviceChannel.setChannelId(channelId); // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 if (status.equals("ON") || status.equals("On") || status.equals("ONLINE")) { if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) { deviceChannel.setStatus(1); } if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { @@ -255,9 +255,14 @@ } else { deviceChannel.setLatitude(0.00); } if (XmlUtil.getText(itemDevice, "PTZType") == null || XmlUtil.getText(itemDevice, "PTZType") == "") { deviceChannel.setPTZType(0); if (XmlUtil.getText(itemDevice, "PTZType") == null || "".equals(XmlUtil.getText(itemDevice, "PTZType"))) { //兼容INFO中的信息 Element info = itemDevice.element("Info"); if(XmlUtil.getText(info, "PTZType") == null || "".equals(XmlUtil.getText(info, "PTZType"))){ deviceChannel.setPTZType(0); }else{ deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(info, "PTZType"))); } } else { deviceChannel.setPTZType(Integer.parseInt(XmlUtil.getText(itemDevice, "PTZType"))); } src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
@@ -61,7 +61,7 @@ List<GbStream> selectByGBId(String gbId); @Select("SELECT gs.*, pgs.platformId as platformId, pgs.catalogId as catalogId FROM gb_stream gs " + "LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.catalogId " + "LEFT JOIN platform_gb_stream pgs ON gs.gbStreamId = pgs.gbStreamId " + "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") GbStream queryStreamInPlatform(String platformId, String gbId); src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
@@ -57,9 +57,9 @@ @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE dc.channelId='${channelId}' and pgc.platformId='${platformId}'") DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); @Select("select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + "from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId" + "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") @Select(" select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + " from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId " + " where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); @Select("select d.*\n" + src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
@@ -216,26 +216,21 @@ if (updateResult) { // 保存时启用就发送注册 if (parentPlatform.isEnable()) { // 保存时启用就发送注册 if (parentPlatform.isEnable()) { if (parentPlatformOld.isStatus()) { commanderForPlatform.unregister(parentPlatformOld, null, null); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 只要保存就发送注册 commanderForPlatform.register(parentPlatform, null, null); }else { // 只要保存就发送注册 commanderForPlatform.register(parentPlatform, null, null); } } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 if (parentPlatformOld.isStatus()) { commanderForPlatform.unregister(parentPlatformOld, null, null); try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } // 只要保存就发送注册 commanderForPlatform.register(parentPlatform, null, null); }else { // 只要保存就发送注册 commanderForPlatform.register(parentPlatform, null, null); } } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 commanderForPlatform.unregister(parentPlatform, null, null); commanderForPlatform.unregister(parentPlatformOld, null, null); } wvpResult.setCode(0); wvpResult.setMsg("success");