Commit 29191373aa1e8940d3ca6ce5a052182f99b37ba9
Merge branch 'wvp-28181-2.0' into wvp-pro-record
# Conflicts: # src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java # web_src/src/components/control.vue
Showing
39 changed files
with
569 additions
and
247 deletions
.gitignore
pom.xml
| ... | ... | @@ -90,8 +90,8 @@ |
| 90 | 90 | <!-- druid数据库连接池 --> |
| 91 | 91 | <dependency> |
| 92 | 92 | <groupId>com.alibaba</groupId> |
| 93 | - <artifactId>druid</artifactId> | |
| 94 | - <version>1.2.3</version> | |
| 93 | + <artifactId>druid-spring-boot-starter</artifactId> | |
| 94 | + <version>1.1.22</version> | |
| 95 | 95 | </dependency> |
| 96 | 96 | |
| 97 | 97 | <!-- mysql数据库 --> | ... | ... |
src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java
| ... | ... | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp; |
| 2 | 2 | |
| 3 | 3 | import java.util.logging.LogManager; |
| 4 | 4 | |
| 5 | +import com.genersoft.iot.vmp.conf.druid.EnableDruidSupport; | |
| 5 | 6 | import org.springframework.boot.SpringApplication; |
| 6 | 7 | import org.springframework.boot.autoconfigure.SpringBootApplication; |
| 7 | 8 | import org.springframework.boot.web.servlet.ServletComponentScan; |
| ... | ... | @@ -17,6 +18,7 @@ import springfox.documentation.oas.annotations.EnableOpenApi; |
| 17 | 18 | @SpringBootApplication |
| 18 | 19 | @EnableScheduling |
| 19 | 20 | @EnableOpenApi |
| 21 | +@EnableDruidSupport | |
| 20 | 22 | public class VManageBootstrap extends LogManager { |
| 21 | 23 | private static String[] args; |
| 22 | 24 | private static ConfigurableApplicationContext context; | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java
| ... | ... | @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.conf; |
| 3 | 3 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 6 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 6 | 7 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 7 | 8 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 8 | 9 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| ... | ... | @@ -30,7 +31,7 @@ public class SipPlatformRunner implements CommandLineRunner { |
| 30 | 31 | private EventPublisher publisher; |
| 31 | 32 | |
| 32 | 33 | @Autowired |
| 33 | - private ZLMRTPServerFactory zlmrtpServerFactory; | |
| 34 | + private ISIPCommanderForPlatform sipCommanderForPlatform; | |
| 34 | 35 | |
| 35 | 36 | |
| 36 | 37 | @Override |
| ... | ... | @@ -57,6 +58,9 @@ public class SipPlatformRunner implements CommandLineRunner { |
| 57 | 58 | parentPlatformCatch.setId(parentPlatform.getServerGBId()); |
| 58 | 59 | redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); |
| 59 | 60 | |
| 61 | + // 取消订阅 | |
| 62 | + sipCommanderForPlatform.unregister(parentPlatform, null, null); | |
| 63 | + Thread.sleep(500); | |
| 60 | 64 | // 发送平台未注册消息 |
| 61 | 65 | publisher.platformNotRegisterEventPublish(parentPlatform.getServerGBId()); |
| 62 | 66 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/druid/DruidConfiguration.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.druid; | |
| 2 | + | |
| 3 | +import com.alibaba.druid.support.http.StatViewServlet; | |
| 4 | +import com.alibaba.druid.support.http.WebStatFilter; | |
| 5 | +import org.springframework.beans.factory.annotation.Value; | |
| 6 | +import org.springframework.boot.web.servlet.FilterRegistrationBean; | |
| 7 | +import org.springframework.boot.web.servlet.ServletRegistrationBean; | |
| 8 | +import org.springframework.context.annotation.Bean; | |
| 9 | + | |
| 10 | +import javax.servlet.Filter; | |
| 11 | +import javax.servlet.Servlet; | |
| 12 | + | |
| 13 | +/** | |
| 14 | + * druid监控配置 | |
| 15 | + * @author | |
| 16 | + */ | |
| 17 | +public class DruidConfiguration { | |
| 18 | + | |
| 19 | + @Value("${rj-druid-manage.allow:127.0.0.1}") | |
| 20 | + private String allow; | |
| 21 | + | |
| 22 | + @Value("${rj-druid-manage.deny:}") | |
| 23 | + private String deny; | |
| 24 | + | |
| 25 | + @Value("${rj-druid-manage.loginUsername:admin}") | |
| 26 | + private String loginUsername; | |
| 27 | + | |
| 28 | + @Value("${rj-druid-manage.loginPassword:admin}") | |
| 29 | + private String loginPassword; | |
| 30 | + | |
| 31 | + @Value("${rj-druid-manage.resetEnable:false}") | |
| 32 | + private String resetEnable; | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * druid监控页面开启 | |
| 36 | + */ | |
| 37 | + @Bean | |
| 38 | + public ServletRegistrationBean druidServlet() { | |
| 39 | + ServletRegistrationBean<Servlet> servletRegistrationBean = new ServletRegistrationBean<>(new StatViewServlet(), "/druid/*"); | |
| 40 | + // IP白名单 | |
| 41 | + servletRegistrationBean.addInitParameter("allow", allow); | |
| 42 | + // IP黑名单(共同存在时,deny优先于allow) | |
| 43 | + servletRegistrationBean.addInitParameter("deny", deny); | |
| 44 | + //控制台管理用户 | |
| 45 | + servletRegistrationBean.addInitParameter("loginUsername", loginUsername); | |
| 46 | + servletRegistrationBean.addInitParameter("loginPassword", loginPassword); | |
| 47 | + //是否能够重置数据 禁用HTML页面上的“Reset All”功能 | |
| 48 | + servletRegistrationBean.addInitParameter("resetEnable", resetEnable); | |
| 49 | + return servletRegistrationBean; | |
| 50 | + } | |
| 51 | + | |
| 52 | + /** | |
| 53 | + * druid url监控配置 | |
| 54 | + */ | |
| 55 | + @Bean | |
| 56 | + public FilterRegistrationBean filterRegistrationBean() { | |
| 57 | + FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>(new WebStatFilter()); | |
| 58 | + filterRegistrationBean.addUrlPatterns("/*"); | |
| 59 | + filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*"); | |
| 60 | + return filterRegistrationBean; | |
| 61 | + } | |
| 62 | + | |
| 63 | + | |
| 64 | +} | |
| 0 | 65 | \ No newline at end of file | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/druid/EnableDruidSupport.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.conf.druid; | |
| 2 | + | |
| 3 | +import org.springframework.boot.web.servlet.ServletComponentScan; | |
| 4 | +import org.springframework.context.annotation.Import; | |
| 5 | + | |
| 6 | +import java.lang.annotation.*; | |
| 7 | + | |
| 8 | +/** | |
| 9 | + * druid监控支持注解 | |
| 10 | + * | |
| 11 | + * @author | |
| 12 | + * {@link DruidConfiguration} druid监控页面安全配置支持 | |
| 13 | + * {@link ServletComponentScan} druid监控页面需要扫描servlet | |
| 14 | + */ | |
| 15 | +@Target(ElementType.TYPE) | |
| 16 | +@Retention(RetentionPolicy.RUNTIME) | |
| 17 | +@Documented | |
| 18 | +@Inherited | |
| 19 | +@Import({ | |
| 20 | + DruidConfiguration.class, | |
| 21 | +}) | |
| 22 | +@ServletComponentScan | |
| 23 | +public @interface EnableDruidSupport { | |
| 24 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java
| ... | ... | @@ -18,13 +18,16 @@ public class SubscribeInfo { |
| 18 | 18 | this.fromTag = fromHeader.getTag(); |
| 19 | 19 | ExpiresHeader expiresHeader = (ExpiresHeader)request.getHeader(ExpiresHeader.NAME); |
| 20 | 20 | this.expires = expiresHeader.getExpires(); |
| 21 | - this.event = ((EventHeader)request.getHeader(EventHeader.NAME)).getName(); | |
| 21 | + EventHeader eventHeader = (EventHeader)request.getHeader(EventHeader.NAME); | |
| 22 | + this.eventId = eventHeader.getEventId(); | |
| 23 | + this.eventType = eventHeader.getEventType(); | |
| 22 | 24 | } |
| 23 | 25 | |
| 24 | 26 | private String id; |
| 25 | 27 | private int expires; |
| 26 | 28 | private String callId; |
| 27 | - private String event; | |
| 29 | + private String eventId; | |
| 30 | + private String eventType; | |
| 28 | 31 | private String fromTag; |
| 29 | 32 | private String toTag; |
| 30 | 33 | |
| ... | ... | @@ -68,11 +71,19 @@ public class SubscribeInfo { |
| 68 | 71 | this.fromTag = fromTag; |
| 69 | 72 | } |
| 70 | 73 | |
| 71 | - public String getEvent() { | |
| 72 | - return event; | |
| 74 | + public String getEventId() { | |
| 75 | + return eventId; | |
| 73 | 76 | } |
| 74 | 77 | |
| 75 | - public void setEvent(String event) { | |
| 76 | - this.event = event; | |
| 78 | + public void setEventId(String eventId) { | |
| 79 | + this.eventId = eventId; | |
| 80 | + } | |
| 81 | + | |
| 82 | + public String getEventType() { | |
| 83 | + return eventType; | |
| 84 | + } | |
| 85 | + | |
| 86 | + public void setEventType(String eventType) { | |
| 87 | + this.eventType = eventType; | |
| 77 | 88 | } |
| 78 | 89 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
| ... | ... | @@ -99,14 +99,14 @@ public class EventPublisher { |
| 99 | 99 | applicationEventPublisher.publishEvent(outEvent); |
| 100 | 100 | } |
| 101 | 101 | |
| 102 | - @Async | |
| 102 | + | |
| 103 | 103 | public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) { |
| 104 | 104 | List<DeviceChannel> deviceChannelList = new ArrayList<>(); |
| 105 | 105 | deviceChannelList.add(deviceChannel); |
| 106 | 106 | catalogEventPublish(platformId, deviceChannelList, type); |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | - @Async | |
| 109 | + | |
| 110 | 110 | public void catalogEventPublish(String platformId, List<DeviceChannel> deviceChannels, String type) { |
| 111 | 111 | CatalogEvent outEvent = new CatalogEvent(this); |
| 112 | 112 | List<DeviceChannel> channels = new ArrayList<>(); |
| ... | ... | @@ -128,8 +128,8 @@ public class EventPublisher { |
| 128 | 128 | applicationEventPublisher.publishEvent(outEvent); |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | - @Async | |
| 132 | - public void catalogEventPublishForStream(String platformId, GbStream[] gbStreams, String type) { | |
| 131 | + | |
| 132 | + public void catalogEventPublishForStream(String platformId, List<GbStream> gbStreams, String type) { | |
| 133 | 133 | CatalogEvent outEvent = new CatalogEvent(this); |
| 134 | 134 | outEvent.setGbStreams(gbStreams); |
| 135 | 135 | outEvent.setType(type); |
| ... | ... | @@ -137,10 +137,11 @@ public class EventPublisher { |
| 137 | 137 | applicationEventPublisher.publishEvent(outEvent); |
| 138 | 138 | } |
| 139 | 139 | |
| 140 | - @Async | |
| 140 | + | |
| 141 | 141 | public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) { |
| 142 | - GbStream[] gbStreams = {gbStream}; | |
| 143 | - catalogEventPublishForStream(platformId, gbStreams, type); | |
| 142 | + List<GbStream> gbStreamList = new ArrayList<>(); | |
| 143 | + gbStreamList.add(gbStream); | |
| 144 | + catalogEventPublishForStream(platformId, gbStreamList, type); | |
| 144 | 145 | } |
| 145 | 146 | |
| 146 | 147 | public void recordEndEventPush(RecordInfo recordInfo) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java
| ... | ... | @@ -20,7 +20,7 @@ public class CatalogEvent extends ApplicationEvent { |
| 20 | 20 | public static final String UPDATE = "UPDATE"; // 更新 |
| 21 | 21 | |
| 22 | 22 | private List<DeviceChannel> deviceChannels; |
| 23 | - private GbStream[] gbStreams; | |
| 23 | + private List<GbStream> gbStreams; | |
| 24 | 24 | private String type; |
| 25 | 25 | private String platformId; |
| 26 | 26 | |
| ... | ... | @@ -48,11 +48,11 @@ public class CatalogEvent extends ApplicationEvent { |
| 48 | 48 | this.platformId = platformId; |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | - public GbStream[] getGbStreams() { | |
| 51 | + public List<GbStream> getGbStreams() { | |
| 52 | 52 | return gbStreams; |
| 53 | 53 | } |
| 54 | 54 | |
| 55 | - public void setGbStreams(GbStream[] gbStreams) { | |
| 55 | + public void setGbStreams(List<GbStream> gbStreams) { | |
| 56 | 56 | this.gbStreams = gbStreams; |
| 57 | 57 | } |
| 58 | 58 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
| ... | ... | @@ -63,7 +63,11 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { |
| 63 | 63 | if (parentPlatform != null && !parentPlatform.isStatus())return; |
| 64 | 64 | String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetup.getServerId() + "_Catalog_" + event.getPlatformId(); |
| 65 | 65 | subscribe = redisCatchStorage.getSubscribe(key); |
| 66 | - if (subscribe == null) return; | |
| 66 | + | |
| 67 | + if (subscribe == null) { | |
| 68 | + logger.debug("发送订阅消息时发现订阅信息已经不存在"); | |
| 69 | + return; | |
| 70 | + } | |
| 67 | 71 | }else { |
| 68 | 72 | // 获取所用订阅 |
| 69 | 73 | List<String> platforms = redisCatchStorage.getAllSubscribePlatform(); |
| ... | ... | @@ -94,7 +98,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { |
| 94 | 98 | if (event.getDeviceChannels() != null) { |
| 95 | 99 | deviceChannelList.addAll(event.getDeviceChannels()); |
| 96 | 100 | } |
| 97 | - if (event.getGbStreams() != null && event.getGbStreams().length > 0){ | |
| 101 | + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ | |
| 98 | 102 | for (GbStream gbStream : event.getGbStreams()) { |
| 99 | 103 | DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); |
| 100 | 104 | deviceChannelList.add(deviceChannelByStream); |
| ... | ... | @@ -134,7 +138,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { |
| 134 | 138 | if (event.getDeviceChannels() != null) { |
| 135 | 139 | deviceChannelList.addAll(event.getDeviceChannels()); |
| 136 | 140 | } |
| 137 | - if (event.getGbStreams() != null && event.getGbStreams().length > 0){ | |
| 141 | + if (event.getGbStreams() != null && event.getGbStreams().size() > 0){ | |
| 138 | 142 | for (GbStream gbStream : event.getGbStreams()) { |
| 139 | 143 | DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform.getDeviceGBId()); |
| 140 | 144 | deviceChannelList.add(deviceChannelByStream); |
| ... | ... | @@ -142,7 +146,7 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> { |
| 142 | 146 | } |
| 143 | 147 | if (deviceChannelList.size() > 0) { |
| 144 | 148 | logger.info("[Catalog事件: {}]平台:{},影响通道{}个", event.getType(), event.getPlatformId(), deviceChannelList.size()); |
| 145 | - sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe); | |
| 149 | + sipCommanderFroPlatform.sendNotifyForCatalogAddOrUpdate(event.getType(), parentPlatform, deviceChannelList, subscribe, null); | |
| 146 | 150 | } |
| 147 | 151 | }else if (parentPlatformMap.keySet().size() > 0) { |
| 148 | 152 | for (String gbId : parentPlatformMap.keySet()) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
| ... | ... | @@ -73,6 +73,7 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { |
| 73 | 73 | @Override |
| 74 | 74 | @Async |
| 75 | 75 | public void processRequest(RequestEvent requestEvent) { |
| 76 | + logger.debug("\n收到请求:\n{}", requestEvent.getRequest()); | |
| 76 | 77 | String method = requestEvent.getRequest().getMethod(); |
| 77 | 78 | ISIPRequestProcessor sipRequestProcessor = requestProcessorMap.get(method); |
| 78 | 79 | if (sipRequestProcessor == null) { |
| ... | ... | @@ -90,9 +91,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { |
| 90 | 91 | @Override |
| 91 | 92 | @Async |
| 92 | 93 | public void processResponse(ResponseEvent responseEvent) { |
| 93 | - logger.debug(responseEvent.getResponse().toString()); | |
| 94 | 94 | Response response = responseEvent.getResponse(); |
| 95 | - logger.debug(responseEvent.getResponse().toString()); | |
| 95 | + logger.debug("\n收到响应:\n{}", responseEvent.getResponse()); | |
| 96 | 96 | int status = response.getStatusCode(); |
| 97 | 97 | if (((status >= 200) && (status < 300)) || status == 401) { // Success! |
| 98 | 98 | CSeqHeader cseqHeader = (CSeqHeader) responseEvent.getResponse().getHeader(CSeqHeader.NAME); |
| ... | ... | @@ -107,8 +107,8 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { |
| 107 | 107 | SipSubscribe.Event subscribe = sipSubscribe.getOkSubscribe(callIdHeader.getCallId()); |
| 108 | 108 | if (subscribe != null) { |
| 109 | 109 | SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(responseEvent); |
| 110 | - subscribe.response(eventResult); | |
| 111 | 110 | sipSubscribe.removeOkSubscribe(callIdHeader.getCallId()); |
| 111 | + subscribe.response(eventResult); | |
| 112 | 112 | } |
| 113 | 113 | } |
| 114 | 114 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
| ... | ... | @@ -79,7 +79,7 @@ public interface ISIPCommanderForPlatform { |
| 79 | 79 | * @param parentPlatform |
| 80 | 80 | * @param deviceChannels |
| 81 | 81 | */ |
| 82 | - boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo); | |
| 82 | + boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index); | |
| 83 | 83 | |
| 84 | 84 | /** |
| 85 | 85 | * 回复catalog事件-删除 | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
| ... | ... | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.gb28181.transmit.cmd; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; | |
| 5 | 6 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 6 | 7 | import gov.nist.javax.sip.message.MessageFactoryImpl; |
| 7 | 8 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -223,30 +224,31 @@ public class SIPRequestHeaderPlarformProvider { |
| 223 | 224 | UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); |
| 224 | 225 | request.addHeader(userAgentHeader); |
| 225 | 226 | |
| 226 | - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 227 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 227 | 228 | request.setContent(content, contentTypeHeader); |
| 228 | 229 | return request; |
| 229 | 230 | } |
| 230 | 231 | |
| 231 | - public Request createNotifyRequest(ParentPlatform parentPlatform, String content, String fromTag, String toTag, CallIdHeader callIdHeader) throws PeerUnavailableException, ParseException, InvalidArgumentException { | |
| 232 | + public Request createNotifyRequest(ParentPlatform parentPlatform, String content, CallIdHeader callIdHeader, String viaTag, SubscribeInfo subscribeInfo) throws PeerUnavailableException, ParseException, InvalidArgumentException { | |
| 232 | 233 | Request request = null; |
| 233 | 234 | // sipuri |
| 234 | 235 | SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP()+ ":" + parentPlatform.getServerPort()); |
| 235 | 236 | // via |
| 236 | 237 | ArrayList<ViaHeader> viaHeaders = new ArrayList<ViaHeader>(); |
| 237 | 238 | ViaHeader viaHeader = sipFactory.createHeaderFactory().createViaHeader(parentPlatform.getDeviceIp(), Integer.parseInt(parentPlatform.getDevicePort()), |
| 238 | - parentPlatform.getTransport(), null); | |
| 239 | + parentPlatform.getTransport(), viaTag); | |
| 239 | 240 | viaHeader.setRPort(); |
| 240 | 241 | viaHeaders.add(viaHeader); |
| 241 | 242 | // from |
| 242 | 243 | SipURI fromSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getDeviceGBId(), |
| 243 | 244 | parentPlatform.getDeviceIp() + ":" + parentPlatform.getDevicePort()); |
| 244 | 245 | Address fromAddress = sipFactory.createAddressFactory().createAddress(fromSipURI); |
| 245 | - FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, fromTag); | |
| 246 | + String tm = Long.toString(System.currentTimeMillis()); | |
| 247 | + FromHeader fromHeader = sipFactory.createHeaderFactory().createFromHeader(fromAddress, "fromtag" + tm); | |
| 246 | 248 | // to |
| 247 | 249 | SipURI toSipURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerGBDomain()); |
| 248 | 250 | Address toAddress = sipFactory.createAddressFactory().createAddress(toSipURI); |
| 249 | - ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, toTag); | |
| 251 | + ToHeader toHeader = sipFactory.createHeaderFactory().createToHeader(toAddress, subscribeInfo.getToTag()); | |
| 250 | 252 | |
| 251 | 253 | // Forwards |
| 252 | 254 | MaxForwardsHeader maxForwards = sipFactory.createHeaderFactory().createMaxForwardsHeader(70); |
| ... | ... | @@ -262,7 +264,19 @@ public class SIPRequestHeaderPlarformProvider { |
| 262 | 264 | UserAgentHeader userAgentHeader = sipFactory.createHeaderFactory().createUserAgentHeader(agentParam); |
| 263 | 265 | request.addHeader(userAgentHeader); |
| 264 | 266 | |
| 265 | - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 267 | + EventHeader event = sipFactory.createHeaderFactory().createEventHeader(subscribeInfo.getEventType()); | |
| 268 | + event.setEventId(subscribeInfo.getEventId()); | |
| 269 | + request.addHeader(event); | |
| 270 | + | |
| 271 | + SubscriptionStateHeader active = sipFactory.createHeaderFactory().createSubscriptionStateHeader("active"); | |
| 272 | + request.setHeader(active); | |
| 273 | + | |
| 274 | + String sipAddress = sipConfig.getIp() + ":" + sipConfig.getPort(); | |
| 275 | + Address concatAddress = sipFactory.createAddressFactory().createAddress(sipFactory.createAddressFactory() | |
| 276 | + .createSipURI(parentPlatform.getDeviceGBId(), sipAddress)); | |
| 277 | + request.addHeader(sipFactory.createHeaderFactory().createContactHeader(concatAddress)); | |
| 278 | + | |
| 279 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 266 | 280 | request.setContent(content, contentTypeHeader); |
| 267 | 281 | return request; |
| 268 | 282 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
| ... | ... | @@ -67,7 +67,7 @@ public class SIPRequestHeaderProvider { |
| 67 | 67 | |
| 68 | 68 | request = sipFactory.createMessageFactory().createRequest(requestURI, Request.MESSAGE, callIdHeader, cSeqHeader, fromHeader, |
| 69 | 69 | toHeader, viaHeaders, maxForwards); |
| 70 | - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 70 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 71 | 71 | request.setContent(content, contentTypeHeader); |
| 72 | 72 | return request; |
| 73 | 73 | } |
| ... | ... | @@ -217,7 +217,7 @@ public class SIPRequestHeaderProvider { |
| 217 | 217 | EventHeader eventHeader = sipFactory.createHeaderFactory().createEventHeader(event); |
| 218 | 218 | request.addHeader(eventHeader); |
| 219 | 219 | |
| 220 | - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 220 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 221 | 221 | request.setContent(content, contentTypeHeader); |
| 222 | 222 | return request; |
| 223 | 223 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| ... | ... | @@ -31,21 +31,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 31 | 31 | |
| 32 | 32 | private final Logger logger = LoggerFactory.getLogger(SIPCommanderFroPlatform.class); |
| 33 | 33 | |
| 34 | - // @Autowired | |
| 35 | - // private SipConfig sipConfig; | |
| 36 | - | |
| 37 | - // @Autowired | |
| 38 | - // private SIPRequestHeaderProvider headerProvider; | |
| 39 | - | |
| 40 | 34 | @Autowired |
| 41 | 35 | private SIPRequestHeaderPlarformProvider headerProviderPlarformProvider; |
| 42 | 36 | |
| 43 | - // @Autowired | |
| 44 | - // private VideoStreamSessionManager streamSession; | |
| 45 | - | |
| 46 | - // @Autowired | |
| 47 | - // private IVideoManagerStorager storager; | |
| 48 | - | |
| 49 | 37 | @Autowired |
| 50 | 38 | private IRedisCatchStorage redisCatchStorage; |
| 51 | 39 | |
| ... | ... | @@ -172,6 +160,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 172 | 160 | } |
| 173 | 161 | |
| 174 | 162 | private void transmitRequest(ParentPlatform parentPlatform, Request request, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws SipException { |
| 163 | + logger.debug("\n发送消息:\n{}", request); | |
| 175 | 164 | if("TCP".equals(parentPlatform.getTransport())) { |
| 176 | 165 | tcpSipProvider.sendRequest(request); |
| 177 | 166 | |
| ... | ... | @@ -222,7 +211,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 222 | 211 | catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); |
| 223 | 212 | catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); |
| 224 | 213 | catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); |
| 225 | - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); | |
| 214 | + if (channel.getParentId() != null) { | |
| 215 | + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); | |
| 216 | + } | |
| 226 | 217 | catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); |
| 227 | 218 | catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); |
| 228 | 219 | catalogXml.append("<Status>" + (channel.getStatus() == 0?"OFF":"ON") + "</Status>\r\n"); |
| ... | ... | @@ -357,7 +348,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 357 | 348 | |
| 358 | 349 | String tm = Long.toString(System.currentTimeMillis()); |
| 359 | 350 | |
| 360 | - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, deviceStatusXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); | |
| 351 | + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, | |
| 352 | + deviceStatusXml.toString(),callIdHeader, | |
| 353 | + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); | |
| 361 | 354 | transmitRequest(parentPlatform, request); |
| 362 | 355 | |
| 363 | 356 | } catch (SipException | ParseException | InvalidArgumentException e) { |
| ... | ... | @@ -368,63 +361,73 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 368 | 361 | } |
| 369 | 362 | |
| 370 | 363 | @Override |
| 371 | - public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) { | |
| 364 | + public boolean sendNotifyForCatalogAddOrUpdate(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo, Integer index) { | |
| 372 | 365 | if (parentPlatform == null || deviceChannels == null || deviceChannels.size() == 0 || subscribeInfo == null) { |
| 373 | 366 | return false; |
| 374 | 367 | } |
| 375 | - for (DeviceChannel channel : deviceChannels) { | |
| 376 | - try { | |
| 377 | - StringBuffer catalogXml = new StringBuffer(600); | |
| 378 | - catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 379 | - catalogXml.append("<Notify>\r\n"); | |
| 380 | - catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); | |
| 381 | - catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 382 | - catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n"); | |
| 383 | - catalogXml.append("<DeviceList Num=\"1\">\r\n"); | |
| 384 | - catalogXml.append("<Item>\r\n"); | |
| 385 | - catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); | |
| 386 | - catalogXml.append("<Event>" + type + "</Event>\r\n"); | |
| 387 | - catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); | |
| 388 | - catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n"); | |
| 389 | - catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n"); | |
| 390 | - catalogXml.append("<Owner>" + channel.getOwner() + "</Owner>\r\n"); | |
| 391 | - catalogXml.append("<CivilCode>" + channel.getCivilCode() + "</CivilCode>\r\n"); | |
| 392 | - catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); | |
| 393 | - catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); | |
| 394 | - catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); | |
| 395 | - catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); | |
| 396 | - catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); | |
| 397 | - catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n"); | |
| 398 | - catalogXml.append("<Longitude>" + channel.getLongitude() + "</Longitude>\r\n"); | |
| 399 | - catalogXml.append("<Latitude>" + channel.getLatitude() + "</Latitude>\r\n"); | |
| 400 | - catalogXml.append("<IPAddress>" + channel.getIpAddress() + "</IPAddress>\r\n"); | |
| 401 | - catalogXml.append("<Port>" + channel.getPort() + "</Port>\r\n"); | |
| 402 | - catalogXml.append("<Info>\r\n"); | |
| 403 | - catalogXml.append("<PTZType>" + channel.getPTZType() + "</PTZType>\r\n"); | |
| 404 | - catalogXml.append("</Info>\r\n"); | |
| 405 | - catalogXml.append("</Item>\r\n"); | |
| 406 | - catalogXml.append("</DeviceList>\r\n"); | |
| 407 | - catalogXml.append("</Notify>\r\n"); | |
| 408 | - | |
| 409 | - CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | |
| 410 | - : udpSipProvider.getNewCallId(); | |
| 411 | - callIdHeader.setCallId(subscribeInfo.getCallId()); | |
| 412 | - | |
| 413 | - String tm = Long.toString(System.currentTimeMillis()); | |
| 368 | + if (index == null) { | |
| 369 | + index = 0; | |
| 370 | + } | |
| 414 | 371 | |
| 415 | - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); | |
| 416 | - transmitRequest(parentPlatform, request); | |
| 417 | - Thread.sleep(10); | |
| 418 | - } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 419 | - e.printStackTrace(); | |
| 420 | - return false; | |
| 421 | - } catch (InterruptedException e) { | |
| 422 | - e.printStackTrace(); | |
| 372 | + try { | |
| 373 | + if (index == deviceChannels.size() - 1) { | |
| 374 | + return true; | |
| 423 | 375 | } |
| 376 | + Request request = getCatalogNotifyRequest(parentPlatform, deviceChannels.get(index), deviceChannels.size(), type, subscribeInfo); | |
| 377 | + index += 1; | |
| 378 | + Integer finalIndex = index; | |
| 379 | + transmitRequest(parentPlatform, request, null, (eventResult -> { | |
| 380 | + sendNotifyForCatalogAddOrUpdate(type, parentPlatform, deviceChannels, subscribeInfo, finalIndex); | |
| 381 | + })); | |
| 382 | + } catch (SipException | ParseException | InvalidArgumentException e) { | |
| 383 | + e.printStackTrace(); | |
| 384 | + return false; | |
| 424 | 385 | } |
| 425 | 386 | return true; |
| 426 | 387 | } |
| 427 | 388 | |
| 389 | + private Request getCatalogNotifyRequest(ParentPlatform parentPlatform, DeviceChannel channel, int size, String type, | |
| 390 | + SubscribeInfo subscribeInfo) throws ParseException, InvalidArgumentException, | |
| 391 | + PeerUnavailableException { | |
| 392 | + String catalogXmlContent = getCatalogXmlContent(parentPlatform, channel, size, type); | |
| 393 | + | |
| 394 | + CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | |
| 395 | + : udpSipProvider.getNewCallId(); | |
| 396 | + callIdHeader.setCallId(subscribeInfo.getCallId()); | |
| 397 | + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXmlContent, | |
| 398 | + callIdHeader, "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); | |
| 399 | + return request; | |
| 400 | + } | |
| 401 | + | |
| 402 | + private String getCatalogXmlContent(ParentPlatform parentPlatform, DeviceChannel channel, int sumNum, String type) { | |
| 403 | + StringBuffer catalogXml = new StringBuffer(600); | |
| 404 | + catalogXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | |
| 405 | + catalogXml.append("<Notify>\r\n"); | |
| 406 | + catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); | |
| 407 | + catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); | |
| 408 | + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); | |
| 409 | + catalogXml.append("<SumNum>" + sumNum + "</SumNum>\r\n"); | |
| 410 | + catalogXml.append("<DeviceList Num=\"1\">\r\n"); | |
| 411 | + catalogXml.append("<Item>\r\n"); | |
| 412 | + catalogXml.append("<DeviceID>" + channel.getChannelId() + "</DeviceID>\r\n"); | |
| 413 | + catalogXml.append("<Name>" + channel.getName() + "</Name>\r\n"); | |
| 414 | + catalogXml.append("<Manufacturer>" + channel.getManufacture() + "</Manufacturer>\r\n"); | |
| 415 | + catalogXml.append("<Model>" + channel.getModel() + "</Model>\r\n"); | |
| 416 | + catalogXml.append("<Owner>0</Owner>\r\n"); | |
| 417 | + catalogXml.append("<CivilCode>CivilCode</CivilCode>\r\n"); | |
| 418 | + catalogXml.append("<Address>" + channel.getAddress() + "</Address>\r\n"); | |
| 419 | + catalogXml.append("<Parental>" + channel.getParental() + "</Parental>\r\n"); | |
| 420 | + catalogXml.append("<ParentID>" + channel.getParentId() + "</ParentID>\r\n"); | |
| 421 | + catalogXml.append("<Secrecy>" + channel.getSecrecy() + "</Secrecy>\r\n"); | |
| 422 | + catalogXml.append("<RegisterWay>" + channel.getRegisterWay() + "</RegisterWay>\r\n"); | |
| 423 | + catalogXml.append("<Status>" + (channel.getStatus() == 0 ? "OFF" : "ON") + "</Status>\r\n"); | |
| 424 | + catalogXml.append("<Event>" + type + "</Event>\r\n"); | |
| 425 | + catalogXml.append("</Item>\r\n"); | |
| 426 | + catalogXml.append("</DeviceList>\r\n"); | |
| 427 | + catalogXml.append("</Notify>\r\n"); | |
| 428 | + return catalogXml.toString(); | |
| 429 | + } | |
| 430 | + | |
| 428 | 431 | @Override |
| 429 | 432 | public boolean sendNotifyForCatalogOther(String type, ParentPlatform parentPlatform, List<DeviceChannel> deviceChannels, SubscribeInfo subscribeInfo) { |
| 430 | 433 | if (parentPlatform == null |
| ... | ... | @@ -441,6 +444,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 441 | 444 | catalogXml.append("<Notify>\r\n"); |
| 442 | 445 | catalogXml.append("<CmdType>Catalog</CmdType>\r\n"); |
| 443 | 446 | catalogXml.append("<SN>" + (int) ((Math.random() * 9 + 1) * 100000) + "</SN>\r\n"); |
| 447 | + catalogXml.append("<DeviceID>" + parentPlatform.getDeviceGBId() + "</DeviceID>\r\n"); | |
| 444 | 448 | catalogXml.append("<SumNum>" + deviceChannels.size() + "</SumNum>\r\n"); |
| 445 | 449 | catalogXml.append("<DeviceList Num=\"1\">\r\n"); |
| 446 | 450 | catalogXml.append("<Item>\r\n"); |
| ... | ... | @@ -456,7 +460,9 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { |
| 456 | 460 | |
| 457 | 461 | String tm = Long.toString(System.currentTimeMillis()); |
| 458 | 462 | |
| 459 | - Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), subscribeInfo.getToTag(), subscribeInfo.getFromTag(), callIdHeader); | |
| 463 | + Request request = headerProviderPlarformProvider.createNotifyRequest(parentPlatform, catalogXml.toString(), | |
| 464 | + callIdHeader, | |
| 465 | + "z9hG4bK-" + UUID.randomUUID().toString().replace("-", ""), subscribeInfo); | |
| 460 | 466 | transmitRequest(parentPlatform, request); |
| 461 | 467 | Thread.sleep(200); |
| 462 | 468 | } catch (SipException | ParseException | InvalidArgumentException e) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 3 | 4 | import gov.nist.javax.sip.SipProviderImpl; |
| 4 | 5 | import gov.nist.javax.sip.SipStackImpl; |
| 5 | 6 | import gov.nist.javax.sip.message.SIPRequest; |
| ... | ... | @@ -160,13 +161,18 @@ public abstract class SIPRequestProcessorParent { |
| 160 | 161 | * @throws InvalidArgumentException |
| 161 | 162 | * @throws ParseException |
| 162 | 163 | */ |
| 163 | - public void responseSdpAck(RequestEvent evt, String sdp) throws SipException, InvalidArgumentException, ParseException { | |
| 164 | + public void responseSdpAck(RequestEvent evt, String sdp, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { | |
| 164 | 165 | Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); |
| 165 | 166 | SipFactory sipFactory = SipFactory.getInstance(); |
| 166 | 167 | ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "SDP"); |
| 167 | 168 | response.setContent(sdp, contentTypeHeader); |
| 168 | 169 | |
| 170 | + // 兼容国标中的使用编码@域名作为RequestURI的情况 | |
| 169 | 171 | SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); |
| 172 | + if (sipURI.getPort() == -1) { | |
| 173 | + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); | |
| 174 | + } | |
| 175 | + logger.debug("responseSdpAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); | |
| 170 | 176 | |
| 171 | 177 | Address concatAddress = sipFactory.createAddressFactory().createAddress( |
| 172 | 178 | sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() |
| ... | ... | @@ -183,13 +189,18 @@ public abstract class SIPRequestProcessorParent { |
| 183 | 189 | * @throws InvalidArgumentException |
| 184 | 190 | * @throws ParseException |
| 185 | 191 | */ |
| 186 | - public Response responseXmlAck(RequestEvent evt, String xml) throws SipException, InvalidArgumentException, ParseException { | |
| 192 | + public Response responseXmlAck(RequestEvent evt, String xml, ParentPlatform platform) throws SipException, InvalidArgumentException, ParseException { | |
| 187 | 193 | Response response = getMessageFactory().createResponse(Response.OK, evt.getRequest()); |
| 188 | 194 | SipFactory sipFactory = SipFactory.getInstance(); |
| 189 | - ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("APPLICATION", "MANSCDP+xml"); | |
| 195 | + ContentTypeHeader contentTypeHeader = sipFactory.createHeaderFactory().createContentTypeHeader("Application", "MANSCDP+xml"); | |
| 190 | 196 | response.setContent(xml, contentTypeHeader); |
| 191 | 197 | |
| 198 | + // 兼容国标中的使用编码@域名作为RequestURI的情况 | |
| 192 | 199 | SipURI sipURI = (SipURI)evt.getRequest().getRequestURI(); |
| 200 | + if (sipURI.getPort() == -1) { | |
| 201 | + sipURI = sipFactory.createAddressFactory().createSipURI(platform.getServerGBId(), platform.getServerIP()+":"+platform.getServerPort()); | |
| 202 | + } | |
| 203 | + logger.debug("responseXmlAck SipURI: {}:{}", sipURI.getHost(), sipURI.getPort()); | |
| 193 | 204 | |
| 194 | 205 | Address concatAddress = sipFactory.createAddressFactory().createAddress( |
| 195 | 206 | sipFactory.createAddressFactory().createSipURI(sipURI.getUser(), sipURI.getHost()+":"+sipURI.getPort() | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -293,7 +293,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 293 | 293 | content.append("f=\r\n"); |
| 294 | 294 | |
| 295 | 295 | try { |
| 296 | - responseSdpAck(evt, content.toString()); | |
| 296 | + responseSdpAck(evt, content.toString(), platform); | |
| 297 | 297 | } catch (SipException e) { |
| 298 | 298 | e.printStackTrace(); |
| 299 | 299 | } catch (InvalidArgumentException e) { |
| ... | ... | @@ -369,7 +369,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements |
| 369 | 369 | content.append("f=\r\n"); |
| 370 | 370 | |
| 371 | 371 | try { |
| 372 | - responseSdpAck(evt, content.toString()); | |
| 372 | + responseSdpAck(evt, content.toString(), platform); | |
| 373 | 373 | } catch (SipException e) { |
| 374 | 374 | e.printStackTrace(); |
| 375 | 375 | } catch (InvalidArgumentException e) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java
| ... | ... | @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 4 | 4 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 5 | 5 | import com.genersoft.iot.vmp.conf.UserSetup; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.bean.CmdType; |
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | |
| 7 | 8 | import com.genersoft.iot.vmp.gb28181.bean.SubscribeInfo; |
| 8 | 9 | import com.genersoft.iot.vmp.gb28181.task.GPSSubscribeTask; |
| 9 | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| ... | ... | @@ -105,9 +106,6 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme |
| 105 | 106 | logger.info("processRequest serverTransactionId is null."); |
| 106 | 107 | } |
| 107 | 108 | } |
| 108 | - | |
| 109 | - | |
| 110 | - | |
| 111 | 109 | } catch (ParseException e) { |
| 112 | 110 | e.printStackTrace(); |
| 113 | 111 | } catch (SipException e) { |
| ... | ... | @@ -155,7 +153,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme |
| 155 | 153 | |
| 156 | 154 | |
| 157 | 155 | try { |
| 158 | - Response response = responseXmlAck(evt, resultXml.toString()); | |
| 156 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); | |
| 157 | + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform); | |
| 159 | 158 | ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); |
| 160 | 159 | subscribeInfo.setToTag(toHeader.getTag()); |
| 161 | 160 | redisCatchStorage.updateSubscribe(key, subscribeInfo); |
| ... | ... | @@ -196,7 +195,8 @@ public class SubscribeRequestProcessor extends SIPRequestProcessorParent impleme |
| 196 | 195 | } |
| 197 | 196 | |
| 198 | 197 | try { |
| 199 | - Response response = responseXmlAck(evt, resultXml.toString()); | |
| 198 | + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); | |
| 199 | + Response response = responseXmlAck(evt, resultXml.toString(), parentPlatform); | |
| 200 | 200 | ToHeader toHeader = (ToHeader)response.getHeader(ToHeader.NAME); |
| 201 | 201 | subscribeInfo.setToTag(toHeader.getTag()); |
| 202 | 202 | redisCatchStorage.updateSubscribe(key, subscribeInfo); | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/CatalogNotifyMessageHandler.java
| ... | ... | @@ -72,6 +72,9 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple |
| 72 | 72 | List<PlatformCatalog> catalogs = storager.queryCatalogInPlatform(parentPlatform.getServerGBId()); |
| 73 | 73 | if (catalogs.size() > 0) { |
| 74 | 74 | for (PlatformCatalog catalog : catalogs) { |
| 75 | + if (catalog.getParentId().equals(catalog.getPlatformId())) { | |
| 76 | + catalog.setParentId(parentPlatform.getDeviceGBId()); | |
| 77 | + } | |
| 75 | 78 | DeviceChannel deviceChannel = new DeviceChannel(); |
| 76 | 79 | deviceChannel.setChannelId(catalog.getId()); |
| 77 | 80 | deviceChannel.setName(catalog.getName()); |
| ... | ... | @@ -83,29 +86,35 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple |
| 83 | 86 | deviceChannel.setParental(1); |
| 84 | 87 | deviceChannel.setParentId(catalog.getParentId()); |
| 85 | 88 | deviceChannel.setRegisterWay(1); |
| 86 | - deviceChannel.setCivilCode(config.getDomain()); | |
| 89 | + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); | |
| 87 | 90 | deviceChannel.setModel("live"); |
| 88 | 91 | deviceChannel.setOwner("wvp-pro"); |
| 89 | 92 | deviceChannel.setSecrecy("0"); |
| 90 | 93 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 91 | 94 | // 防止发送过快 |
| 92 | - Thread.sleep(50); | |
| 95 | + Thread.sleep(100); | |
| 93 | 96 | } |
| 94 | 97 | } |
| 95 | 98 | // 回复级联的通道 |
| 96 | 99 | if (channelReduces.size() > 0) { |
| 97 | 100 | for (ChannelReduce channelReduce : channelReduces) { |
| 101 | + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) { | |
| 102 | + channelReduce.setCatalogId(parentPlatform.getDeviceGBId()); | |
| 103 | + } | |
| 98 | 104 | DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); |
| 99 | 105 | deviceChannel.setParental(0); |
| 100 | 106 | deviceChannel.setParentId(channelReduce.getCatalogId()); |
| 101 | 107 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 102 | 108 | // 防止发送过快 |
| 103 | - Thread.sleep(50); | |
| 109 | + Thread.sleep(100); | |
| 104 | 110 | } |
| 105 | 111 | } |
| 106 | 112 | // 回复直播的通道 |
| 107 | 113 | if (gbStreams.size() > 0) { |
| 108 | 114 | for (GbStream gbStream : gbStreams) { |
| 115 | + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) { | |
| 116 | + gbStream.setCatalogId(null); | |
| 117 | + } | |
| 109 | 118 | DeviceChannel deviceChannel = new DeviceChannel(); |
| 110 | 119 | deviceChannel.setChannelId(gbStream.getGbId()); |
| 111 | 120 | deviceChannel.setName(gbStream.getName()); |
| ... | ... | @@ -116,14 +125,14 @@ public class CatalogNotifyMessageHandler extends SIPRequestProcessorParent imple |
| 116 | 125 | deviceChannel.setStatus(gbStream.isStatus()?1:0); |
| 117 | 126 | deviceChannel.setParentId(gbStream.getCatalogId()); |
| 118 | 127 | deviceChannel.setRegisterWay(1); |
| 119 | - deviceChannel.setCivilCode(config.getDomain()); | |
| 128 | + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); | |
| 120 | 129 | deviceChannel.setModel("live"); |
| 121 | 130 | deviceChannel.setOwner("wvp-pro"); |
| 122 | 131 | deviceChannel.setParental(0); |
| 123 | 132 | deviceChannel.setSecrecy("0"); |
| 124 | 133 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 125 | 134 | // 防止发送过快 |
| 126 | - Thread.sleep(50); | |
| 135 | + Thread.sleep(100); | |
| 127 | 136 | } |
| 128 | 137 | } |
| 129 | 138 | if (size == 0) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java
| ... | ... | @@ -75,6 +75,9 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem |
| 75 | 75 | int size = catalogs.size() + channelReduces.size() + gbStreams.size(); |
| 76 | 76 | if (catalogs.size() > 0) { |
| 77 | 77 | for (PlatformCatalog catalog : catalogs) { |
| 78 | + if (catalog.getParentId().equals(parentPlatform.getServerGBId())) { | |
| 79 | + catalog.setParentId(parentPlatform.getDeviceGBId()); | |
| 80 | + } | |
| 78 | 81 | DeviceChannel deviceChannel = new DeviceChannel(); |
| 79 | 82 | deviceChannel.setChannelId(catalog.getId()); |
| 80 | 83 | deviceChannel.setName(catalog.getName()); |
| ... | ... | @@ -86,30 +89,35 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem |
| 86 | 89 | deviceChannel.setParental(1); |
| 87 | 90 | deviceChannel.setParentId(catalog.getParentId()); |
| 88 | 91 | deviceChannel.setRegisterWay(1); |
| 89 | - deviceChannel.setCivilCode(config.getDomain()); | |
| 92 | + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); | |
| 90 | 93 | deviceChannel.setModel("live"); |
| 91 | 94 | deviceChannel.setOwner("wvp-pro"); |
| 92 | 95 | deviceChannel.setSecrecy("0"); |
| 93 | 96 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 94 | 97 | // 防止发送过快 |
| 95 | - Thread.sleep(50); | |
| 98 | + Thread.sleep(100); | |
| 96 | 99 | } |
| 97 | 100 | } |
| 98 | 101 | // 回复级联的通道 |
| 99 | 102 | if (channelReduces.size() > 0) { |
| 100 | 103 | for (ChannelReduce channelReduce : channelReduces) { |
| 104 | + if (channelReduce.getCatalogId().equals(parentPlatform.getServerGBId())) { | |
| 105 | + channelReduce.setCatalogId(parentPlatform.getDeviceGBId()); | |
| 106 | + } | |
| 101 | 107 | DeviceChannel deviceChannel = storager.queryChannel(channelReduce.getDeviceId(), channelReduce.getChannelId()); |
| 102 | - // TODO 目前暂时认为这里只用通道没有目录 | |
| 103 | 108 | deviceChannel.setParental(0); |
| 104 | 109 | deviceChannel.setParentId(channelReduce.getCatalogId()); |
| 105 | 110 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 106 | 111 | // 防止发送过快 |
| 107 | - Thread.sleep(50); | |
| 112 | + Thread.sleep(100); | |
| 108 | 113 | } |
| 109 | 114 | } |
| 110 | 115 | // 回复直播的通道 |
| 111 | 116 | if (gbStreams.size() > 0) { |
| 112 | 117 | for (GbStream gbStream : gbStreams) { |
| 118 | + if (gbStream.getCatalogId().equals(parentPlatform.getServerGBId())) { | |
| 119 | + gbStream.setCatalogId(parentPlatform.getDeviceGBId()); | |
| 120 | + } | |
| 113 | 121 | DeviceChannel deviceChannel = new DeviceChannel(); |
| 114 | 122 | deviceChannel.setChannelId(gbStream.getGbId()); |
| 115 | 123 | deviceChannel.setName(gbStream.getName()); |
| ... | ... | @@ -120,7 +128,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem |
| 120 | 128 | deviceChannel.setStatus(gbStream.isStatus()?1:0); |
| 121 | 129 | deviceChannel.setParentId(gbStream.getCatalogId()); |
| 122 | 130 | deviceChannel.setRegisterWay(1); |
| 123 | - deviceChannel.setCivilCode(config.getDomain()); | |
| 131 | + deviceChannel.setCivilCode(config.getDomain().substring(0, config.getDomain().length() - 2)); | |
| 124 | 132 | deviceChannel.setModel("live"); |
| 125 | 133 | deviceChannel.setOwner("wvp-pro"); |
| 126 | 134 | deviceChannel.setParental(0); |
| ... | ... | @@ -128,7 +136,7 @@ public class CatalogQueryMessageHandler extends SIPRequestProcessorParent implem |
| 128 | 136 | |
| 129 | 137 | cmderFroPlatform.catalogQuery(deviceChannel, parentPlatform, sn, fromHeader.getTag(), size); |
| 130 | 138 | // 防止发送过快 |
| 131 | - Thread.sleep(50); | |
| 139 | + Thread.sleep(100); | |
| 132 | 140 | } |
| 133 | 141 | } |
| 134 | 142 | if (size == 0) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| ... | ... | @@ -358,6 +358,8 @@ public class ZLMHttpHookListener { |
| 358 | 358 | if (mediaServerItem != null){ |
| 359 | 359 | if (regist) { |
| 360 | 360 | StreamPushItem streamPushItem = null; |
| 361 | + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); | |
| 362 | + item.setStreamInfo(streamInfoByAppAndStream); | |
| 361 | 363 | redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item); |
| 362 | 364 | if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() |
| 363 | 365 | || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() |
| ... | ... | @@ -375,7 +377,7 @@ public class ZLMHttpHookListener { |
| 375 | 377 | } |
| 376 | 378 | } |
| 377 | 379 | if (gbStreams.size() > 0) { |
| 378 | - eventPublisher.catalogEventPublishForStream(null, gbStreams.toArray(new GbStream[0]), CatalogEvent.ON); | |
| 380 | + eventPublisher.catalogEventPublishForStream(null, gbStreams, CatalogEvent.ON); | |
| 379 | 381 | } |
| 380 | 382 | |
| 381 | 383 | }else { | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java
| 1 | 1 | package com.genersoft.iot.vmp.media.zlm.dto; |
| 2 | 2 | |
| 3 | +import com.genersoft.iot.vmp.common.StreamInfo; | |
| 4 | + | |
| 3 | 5 | import java.util.List; |
| 4 | 6 | |
| 5 | 7 | public class MediaItem { |
| ... | ... | @@ -281,6 +283,8 @@ public class MediaItem { |
| 281 | 283 | } |
| 282 | 284 | } |
| 283 | 285 | |
| 286 | + private StreamInfo streamInfo; | |
| 287 | + | |
| 284 | 288 | public String getApp() { |
| 285 | 289 | return app; |
| 286 | 290 | } |
| ... | ... | @@ -402,4 +406,12 @@ public class MediaItem { |
| 402 | 406 | public void setMediaServerId(String mediaServerId) { |
| 403 | 407 | this.mediaServerId = mediaServerId; |
| 404 | 408 | } |
| 409 | + | |
| 410 | + public StreamInfo getStreamInfo() { | |
| 411 | + return streamInfo; | |
| 412 | + } | |
| 413 | + | |
| 414 | + public void setStreamInfo(StreamInfo streamInfo) { | |
| 415 | + this.streamInfo = streamInfo; | |
| 416 | + } | |
| 405 | 417 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java
| ... | ... | @@ -103,7 +103,7 @@ public class GbStreamServiceImpl implements IGbStreamService { |
| 103 | 103 | deviceChannel.setStatus(gbStream.isStatus()?1:0); |
| 104 | 104 | deviceChannel.setParentId(catalogId ==null?gbStream.getCatalogId():catalogId); |
| 105 | 105 | deviceChannel.setRegisterWay(1); |
| 106 | - deviceChannel.setCivilCode(sipConfig.getDomain()); | |
| 106 | + deviceChannel.setCivilCode(sipConfig.getDomain().substring(0, sipConfig.getDomain().length() - 2)); | |
| 107 | 107 | deviceChannel.setModel("live"); |
| 108 | 108 | deviceChannel.setOwner("wvp-pro"); |
| 109 | 109 | deviceChannel.setParental(0); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 7 | +import com.genersoft.iot.vmp.conf.MediaConfig; | |
| 7 | 8 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 8 | 9 | import com.genersoft.iot.vmp.conf.UserSetup; |
| 9 | 10 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| ... | ... | @@ -278,6 +279,7 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 278 | 279 | |
| 279 | 280 | @Override |
| 280 | 281 | public MediaServerItem getDefaultMediaServer() { |
| 282 | + | |
| 281 | 283 | return mediaServerMapper.queryDefault(); |
| 282 | 284 | } |
| 283 | 285 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
| ... | ... | @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 7 | +import com.genersoft.iot.vmp.conf.MediaConfig; | |
| 7 | 8 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 8 | 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| 9 | 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| ... | ... | @@ -26,6 +27,10 @@ public class MediaServiceImpl implements IMediaService { |
| 26 | 27 | @Autowired |
| 27 | 28 | private IMediaServerService mediaServerService; |
| 28 | 29 | |
| 30 | + | |
| 31 | + @Autowired | |
| 32 | + private MediaConfig mediaConfig; | |
| 33 | + | |
| 29 | 34 | @Autowired |
| 30 | 35 | private ZLMRESTfulUtils zlmresTfulUtils; |
| 31 | 36 | |
| ... | ... | @@ -39,15 +44,12 @@ public class MediaServiceImpl implements IMediaService { |
| 39 | 44 | @Override |
| 40 | 45 | public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) { |
| 41 | 46 | StreamInfo streamInfo = null; |
| 42 | - | |
| 43 | - MediaServerItem mediaInfo; | |
| 44 | 47 | if (mediaServerId == null) { |
| 45 | - mediaInfo = mediaServerService.getDefaultMediaServer(); | |
| 46 | - }else { | |
| 47 | - mediaInfo = mediaServerService.getOne(mediaServerId); | |
| 48 | + mediaServerId = mediaConfig.getId(); | |
| 48 | 49 | } |
| 50 | + MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId);; | |
| 49 | 51 | if (mediaInfo == null) { |
| 50 | - return streamInfo; | |
| 52 | + return null; | |
| 51 | 53 | } |
| 52 | 54 | JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream); |
| 53 | 55 | if (mediaList != null) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGPSMsgListener.java
| ... | ... | @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.service.impl; |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 5 | 5 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 6 | +import org.slf4j.Logger; | |
| 7 | +import org.slf4j.LoggerFactory; | |
| 6 | 8 | import org.springframework.beans.factory.annotation.Autowired; |
| 7 | 9 | import org.springframework.data.redis.connection.Message; |
| 8 | 10 | import org.springframework.data.redis.connection.MessageListener; |
| ... | ... | @@ -11,11 +13,14 @@ import org.springframework.stereotype.Component; |
| 11 | 13 | @Component |
| 12 | 14 | public class RedisGPSMsgListener implements MessageListener { |
| 13 | 15 | |
| 16 | + private final static Logger logger = LoggerFactory.getLogger(RedisGPSMsgListener.class); | |
| 17 | + | |
| 14 | 18 | @Autowired |
| 15 | 19 | private IRedisCatchStorage redisCatchStorage; |
| 16 | 20 | |
| 17 | 21 | @Override |
| 18 | 22 | public void onMessage(Message message, byte[] bytes) { |
| 23 | + logger.debug("收到来自REDIS的GPS通知: {}", new String(message.getBody())); | |
| 19 | 24 | GPSMsgInfo gpsMsgInfo = JSON.parseObject(message.getBody(), GPSMsgInfo.class); |
| 20 | 25 | redisCatchStorage.updateGpsMsgInfo(gpsMsgInfo); |
| 21 | 26 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
| ... | ... | @@ -377,7 +377,7 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 377 | 377 | |
| 378 | 378 | if (streamPushItemsForPlatform.size() > 0) { |
| 379 | 379 | List<StreamPushItem> streamPushItemListFroPlatform = new ArrayList<>(); |
| 380 | - Map<String, List<StreamPushItem>> platformForEvent = new HashMap<>(); | |
| 380 | + Map<String, List<GbStream>> platformForEvent = new HashMap<>(); | |
| 381 | 381 | // 遍历存储结果,查找app+Stream->platformId+catalogId的对应关系,然后执行批量写入 |
| 382 | 382 | for (StreamPushItem streamPushItem : streamPushItemsForPlatform) { |
| 383 | 383 | List<String[]> platFormInfoList = streamPushItemsForAll.get(streamPushItem.getApp() + streamPushItem.getStream()); |
| ... | ... | @@ -390,16 +390,17 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 390 | 390 | // 数组 platFormInfoArray 0 为平台ID。 1为目录ID |
| 391 | 391 | streamPushItemForPlatform.setPlatformId(platFormInfoArray[0]); |
| 392 | 392 | |
| 393 | - List<StreamPushItem> streamPushItemsInPlatform = platformForEvent.get(streamPushItem.getPlatformId()); | |
| 394 | - if (streamPushItemsInPlatform == null) { | |
| 395 | - streamPushItemsInPlatform = new ArrayList<>(); | |
| 396 | - platformForEvent.put(platFormInfoArray[0], streamPushItemsInPlatform); | |
| 393 | + List<GbStream> gbStreamList = platformForEvent.get(streamPushItem.getPlatformId()); | |
| 394 | + if (gbStreamList == null) { | |
| 395 | + gbStreamList = new ArrayList<>(); | |
| 396 | + platformForEvent.put(platFormInfoArray[0], gbStreamList); | |
| 397 | 397 | } |
| 398 | 398 | // 为发送通知整理数据 |
| 399 | + streamPushItemForPlatform.setName(streamPushItem.getName()); | |
| 399 | 400 | streamPushItemForPlatform.setApp(streamPushItem.getApp()); |
| 400 | 401 | streamPushItemForPlatform.setStream(streamPushItem.getStream()); |
| 401 | 402 | streamPushItemForPlatform.setGbId(streamPushItem.getGbId()); |
| 402 | - streamPushItemsInPlatform.add(streamPushItemForPlatform); | |
| 403 | + gbStreamList.add(streamPushItemForPlatform); | |
| 403 | 404 | } |
| 404 | 405 | if (platFormInfoArray.length > 1) { |
| 405 | 406 | streamPushItemForPlatform.setCatalogId(platFormInfoArray[1]); |
| ... | ... | @@ -416,7 +417,7 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 416 | 417 | // 发送通知 |
| 417 | 418 | for (String platformId : platformForEvent.keySet()) { |
| 418 | 419 | eventPublisher.catalogEventPublishForStream( |
| 419 | - platformId, platformForEvent.get(platformId).toArray(new GbStream[0]), CatalogEvent.ADD); | |
| 420 | + platformId, platformForEvent.get(platformId), CatalogEvent.ADD); | |
| 420 | 421 | } |
| 421 | 422 | } |
| 422 | 423 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
| ... | ... | @@ -74,7 +74,7 @@ public interface DeviceMapper { |
| 74 | 74 | "<if test=\"keepaliveTime != null\">, keepaliveTime='${keepaliveTime}'</if>" + |
| 75 | 75 | "<if test=\"expires != null\">, expires=${expires}</if>" + |
| 76 | 76 | "<if test=\"charset != null\">, charset='${charset}'</if>" + |
| 77 | - "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=#{subscribeCycleForCatalog}</if>" + | |
| 77 | + "<if test=\"subscribeCycleForCatalog != null\">, subscribeCycleForCatalog=${subscribeCycleForCatalog}</if>" + | |
| 78 | 78 | "WHERE deviceId='${deviceId}'"+ |
| 79 | 79 | " </script>"}) |
| 80 | 80 | int update(Device device); | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
| ... | ... | @@ -34,7 +34,6 @@ public interface PlatformChannelMapper { |
| 34 | 34 | "</script>") |
| 35 | 35 | int addChannels(String platformId, List<ChannelReduce> channelReducesToAdd); |
| 36 | 36 | |
| 37 | - | |
| 38 | 37 | @Delete("<script> "+ |
| 39 | 38 | "DELETE FROM platform_gb_channel WHERE platformId='${platformId}' AND deviceChannelId in" + |
| 40 | 39 | "<foreach collection='channelReducesToDel' item='item' open='(' separator=',' close=')' > '${item.id}'</foreach>" + |
| ... | ... | @@ -42,7 +41,11 @@ public interface PlatformChannelMapper { |
| 42 | 41 | int delChannelForGB(String platformId, List<ChannelReduce> channelReducesToDel); |
| 43 | 42 | |
| 44 | 43 | @Delete("<script> "+ |
| 45 | - "DELETE FROM platform_gb_channel WHERE deviceId='${deviceId}' " + | |
| 44 | + "DELETE FROM platform_gb_channel WHERE deviceChannelId in " + | |
| 45 | + "( select temp.deviceChannelId from " + | |
| 46 | + "(select pgc.deviceChannelId from platform_gb_channel pgc " + | |
| 47 | + "left join device_channel dc on dc.id = pgc.deviceChannelId where dc.deviceId =#{deviceId} " + | |
| 48 | + ") temp)" + | |
| 46 | 49 | "</script>") |
| 47 | 50 | int delChannelForDeviceId(String deviceId); |
| 48 | 51 | |
| ... | ... | @@ -51,18 +54,19 @@ public interface PlatformChannelMapper { |
| 51 | 54 | "</script>") |
| 52 | 55 | int cleanChannelForGB(String platformId); |
| 53 | 56 | |
| 54 | - | |
| 55 | - @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE " + | |
| 56 | - "pgc.platformId=#{platformId} AND dc.channelId=#{channelId}") | |
| 57 | + @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}'") | |
| 57 | 58 | DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); |
| 58 | 59 | |
| 59 | - | |
| 60 | 60 | @Select("select dc.channelId as id, dc.name as name, pgc.platformId as platformId, pgc.catalogId as parentId, 0 as childrenCount, 1 as type " + |
| 61 | - "from device_channel dc left join platform_gb_channel pgc on dc.deviceId = pgc.deviceId and dc.channelId = pgc.channelId " + | |
| 61 | + "from device_channel dc left join platform_gb_channel pgc on dc.id = pgc.deviceChannelId" + | |
| 62 | 62 | "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") |
| 63 | 63 | List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); |
| 64 | 64 | |
| 65 | - @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE pgc.platformId='${platformId}' AND dc.channelId='${channelId}')") | |
| 65 | + @Select("select d.*\n" + | |
| 66 | + "from platform_gb_channel pgc\n" + | |
| 67 | + " left join device_channel dc on dc.id = pgc.deviceChannelId\n" + | |
| 68 | + " left join device d on dc.deviceId = d.deviceId\n" + | |
| 69 | + "where dc.channelId = #{channelId} and pgc.platformId=#{platformId}") | |
| 66 | 70 | Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); |
| 67 | 71 | |
| 68 | 72 | @Delete("<script> "+ | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
| ... | ... | @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.storager.dao; |
| 3 | 3 | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| 4 | 4 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 5 | 5 | import org.apache.ibatis.annotations.*; |
| 6 | -import org.omg.PortableInterceptor.INACTIVE; | |
| 6 | +// import org.omg.PortableInterceptor.INACTIVE; | |
| 7 | 7 | import org.springframework.stereotype.Repository; |
| 8 | 8 | |
| 9 | 9 | import java.util.Collection; | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
| ... | ... | @@ -204,10 +204,7 @@ public class DeviceQuery { |
| 204 | 204 | if (logger.isDebugEnabled()) { |
| 205 | 205 | logger.debug("设备信息删除API调用,deviceId:" + deviceId); |
| 206 | 206 | } |
| 207 | - | |
| 208 | - if (offLineDetector.isOnline(deviceId)) { | |
| 209 | - return new ResponseEntity<String>("不允许删除在线设备!", HttpStatus.NOT_ACCEPTABLE); | |
| 210 | - } | |
| 207 | + | |
| 211 | 208 | // 清除redis记录 |
| 212 | 209 | boolean isSuccess = storager.delete(deviceId); |
| 213 | 210 | if (isSuccess) { |
| ... | ... | @@ -319,20 +316,20 @@ public class DeviceQuery { |
| 319 | 316 | if (!StringUtils.isEmpty(device.getCharset())) deviceInStore.setCharset(device.getCharset()); |
| 320 | 317 | if (!StringUtils.isEmpty(device.getMediaServerId())) deviceInStore.setMediaServerId(device.getMediaServerId()); |
| 321 | 318 | |
| 322 | - if ((deviceInStore.getSubscribeCycleForCatalog() <=0 && device.getSubscribeCycleForCatalog() > 0) | |
| 323 | - || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { | |
| 324 | - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); | |
| 325 | - // 开启订阅 | |
| 326 | - deviceService.addCatalogSubscribe(deviceInStore); | |
| 327 | - } | |
| 328 | - if (deviceInStore.getSubscribeCycleForCatalog() > 0 && device.getSubscribeCycleForCatalog() <= 0) { | |
| 329 | - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); | |
| 330 | - // 取消订阅 | |
| 331 | - deviceService.removeCatalogSubscribe(deviceInStore); | |
| 319 | + if (device.getSubscribeCycleForCatalog() > 0) { | |
| 320 | + if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { | |
| 321 | + // 开启订阅 | |
| 322 | + deviceService.addCatalogSubscribe(deviceInStore); | |
| 323 | + } | |
| 324 | + }else if (device.getSubscribeCycleForCatalog() == 0) { | |
| 325 | + if (deviceInStore.getSubscribeCycleForCatalog() != 0) { | |
| 326 | + // 取消订阅 | |
| 327 | + deviceService.removeCatalogSubscribe(deviceInStore); | |
| 328 | + } | |
| 332 | 329 | } |
| 333 | 330 | |
| 334 | - storager.updateDevice(deviceInStore); | |
| 335 | - cmder.deviceInfoQuery(deviceInStore); | |
| 331 | + storager.updateDevice(device); | |
| 332 | + cmder.deviceInfoQuery(device); | |
| 336 | 333 | } |
| 337 | 334 | WVPResult<String> result = new WVPResult<>(); |
| 338 | 335 | result.setCode(0); | ... | ... |
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/platform/PlatformController.java
| ... | ... | @@ -154,8 +154,16 @@ public class PlatformController { |
| 154 | 154 | if (updateResult) { |
| 155 | 155 | // 保存时启用就发送注册 |
| 156 | 156 | if (parentPlatform.isEnable()) { |
| 157 | - // 只要保存就发送注册 | |
| 158 | - commanderForPlatform.register(parentPlatform, null, null); | |
| 157 | + if (parentPlatformOld.isStatus()) { | |
| 158 | + commanderForPlatform.unregister(parentPlatformOld, null, eventResult -> { | |
| 159 | + // 只要保存就发送注册 | |
| 160 | + commanderForPlatform.register(parentPlatform, null, null); | |
| 161 | + }); | |
| 162 | + }else { | |
| 163 | + // 只要保存就发送注册 | |
| 164 | + commanderForPlatform.register(parentPlatform, null, null); | |
| 165 | + } | |
| 166 | + | |
| 159 | 167 | } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 |
| 160 | 168 | commanderForPlatform.unregister(parentPlatform, null, null); |
| 161 | 169 | } |
| ... | ... | @@ -208,8 +216,24 @@ public class PlatformController { |
| 208 | 216 | if (updateResult) { |
| 209 | 217 | // 保存时启用就发送注册 |
| 210 | 218 | if (parentPlatform.isEnable()) { |
| 211 | - // 只要保存就发送注册 | |
| 212 | - commanderForPlatform.register(parentPlatform, null, null); | |
| 219 | + // 保存时启用就发送注册 | |
| 220 | + if (parentPlatform.isEnable()) { | |
| 221 | + if (parentPlatformOld.isStatus()) { | |
| 222 | + commanderForPlatform.unregister(parentPlatformOld, null, null); | |
| 223 | + try { | |
| 224 | + Thread.sleep(500); | |
| 225 | + } catch (InterruptedException e) { | |
| 226 | + e.printStackTrace(); | |
| 227 | + } | |
| 228 | + // 只要保存就发送注册 | |
| 229 | + commanderForPlatform.register(parentPlatform, null, null); | |
| 230 | + }else { | |
| 231 | + // 只要保存就发送注册 | |
| 232 | + commanderForPlatform.register(parentPlatform, null, null); | |
| 233 | + } | |
| 234 | + } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 | |
| 235 | + commanderForPlatform.unregister(parentPlatformOld, null, null); | |
| 236 | + } | |
| 213 | 237 | } else if (parentPlatformOld != null && parentPlatformOld.isEnable() && !parentPlatform.isEnable()){ // 关闭启用时注销 |
| 214 | 238 | commanderForPlatform.unregister(parentPlatform, null, null); |
| 215 | 239 | } | ... | ... |
src/main/resources/all-application.yml
| ... | ... | @@ -30,24 +30,44 @@ spring: |
| 30 | 30 | poolMaxWait: 5 |
| 31 | 31 | # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 |
| 32 | 32 | datasource: |
| 33 | - # 使用mysql 打开23-28行注释, 删除29-36行 | |
| 34 | - # name: wvp | |
| 35 | - # url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true | |
| 36 | - # username: | |
| 37 | - # password: | |
| 38 | - # type: com.alibaba.druid.pool.DruidDataSource | |
| 39 | - # driver-class-name: com.mysql.cj.jdbc.Driver | |
| 40 | - name: eiot | |
| 41 | - url: jdbc:sqlite::resource:wvp.sqlite | |
| 42 | - username: | |
| 43 | - password: | |
| 44 | 33 | type: com.alibaba.druid.pool.DruidDataSource |
| 45 | - driver-class-name: org.sqlite.JDBC | |
| 46 | - journal_mode: WAL | |
| 47 | - synchronous: NORMAL | |
| 48 | - transaction_mode: IMMEDIATE | |
| 49 | - max-active: 1 | |
| 50 | - min-idle: 1 | |
| 34 | + driver-class-name: com.mysql.cj.jdbc.Driver | |
| 35 | + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false | |
| 36 | + username: root | |
| 37 | + password: root123 | |
| 38 | + druid: | |
| 39 | + initialSize: 10 # 连接池初始化连接数 | |
| 40 | + maxActive: 200 # 连接池最大连接数 | |
| 41 | + minIdle: 5 # 连接池最小空闲连接数 | |
| 42 | + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 | |
| 43 | + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 | |
| 44 | + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 | |
| 45 | + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 | |
| 46 | + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | |
| 47 | + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | |
| 48 | + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小 | |
| 49 | + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 | |
| 50 | + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒 | |
| 51 | + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall | |
| 52 | + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 | |
| 53 | + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 | |
| 54 | + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000 | |
| 55 | + #stat-view-servlet.url-pattern: /admin/druid/* | |
| 56 | + | |
| 57 | +# druid管理监控页面的一些配置 | |
| 58 | +rj-druid-manage: | |
| 59 | + allow: # 访问druid监控页面的IP白名单 | |
| 60 | + deny: 192.168.1.100 # 访问druid监控页面IP黑名单 | |
| 61 | + loginUsername: rjAdmin # 访问druid监控页面账号 | |
| 62 | + loginPassword: rj@2022 # 访问druid监控页面密码 | |
| 63 | + | |
| 64 | +#mybatis: | |
| 65 | +# configuration: | |
| 66 | +# # 这个配置会将执行的sql打印出来,在开发或测试的时候可以用 | |
| 67 | +# log-impl: org.apache.ibatis.logging.stdout.StdOutImpl | |
| 68 | +# # 返回类型为Map,显示null对应的字段 | |
| 69 | +# call-setters-on-nulls: true | |
| 70 | +## [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 51 | 71 | |
| 52 | 72 | # [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 |
| 53 | 73 | server: |
| ... | ... | @@ -136,15 +156,8 @@ media: |
| 136 | 156 | |
| 137 | 157 | # [可选] 日志配置, 一般不需要改 |
| 138 | 158 | logging: |
| 139 | - file: | |
| 140 | - name: logs/wvp.log | |
| 141 | - max-history: 30 | |
| 142 | - max-size: 10MB | |
| 143 | - total-size-cap: 300MB | |
| 144 | - level: | |
| 145 | - com.genersoft.iot: debug | |
| 146 | - com.genersoft.iot.vmp.storager.dao: info | |
| 147 | - com.genersoft.iot.vmp.gb28181: debug | |
| 159 | + config: classpath:logback-spring-local.xml | |
| 160 | + | |
| 148 | 161 | # [根据业务需求配置] |
| 149 | 162 | user-settings: |
| 150 | 163 | # [可选] 服务ID,不写则为000000 | ... | ... |
src/main/resources/application-dev.yml
| ... | ... | @@ -16,24 +16,41 @@ spring: |
| 16 | 16 | password: |
| 17 | 17 | # [可选] 超时时间 |
| 18 | 18 | timeout: 10000 |
| 19 | - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 | |
| 19 | + # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 | |
| 20 | + # mysql数据源 | |
| 20 | 21 | datasource: |
| 21 | - # 使用mysql 打开23-28行注释, 删除29-36行 | |
| 22 | - name: wvp | |
| 23 | - url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&allowMultiQueries=true&useSSL=false | |
| 24 | - username: | |
| 25 | - password: | |
| 26 | 22 | type: com.alibaba.druid.pool.DruidDataSource |
| 27 | 23 | driver-class-name: com.mysql.cj.jdbc.Driver |
| 24 | + url: jdbc:mysql://127.0.0.1:3306/wvp?useUnicode=true&characterEncoding=UTF8&rewriteBatchedStatements=true&serverTimezone=PRC&useSSL=false | |
| 25 | + username: root | |
| 26 | + password: root123 | |
| 27 | + druid: | |
| 28 | + initialSize: 10 # 连接池初始化连接数 | |
| 29 | + maxActive: 200 # 连接池最大连接数 | |
| 30 | + minIdle: 5 # 连接池最小空闲连接数 | |
| 31 | + maxWait: 60000 # 获取连接时最大等待时间,单位毫秒。配置了maxWait之后,缺省启用公平锁,并发效率会有所下降,如果需要可以通过配置useUnfairLock属性为true使用非公平锁。 | |
| 32 | + keepAlive: true # 连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行keepAlive操作。 | |
| 33 | + validationQuery: select 1 # 检测连接是否有效sql,要求是查询语句,常用select 'x'。如果validationQuery为null,testOnBorrow、testOnReturn、testWhileIdle都不会起作用。 | |
| 34 | + testWhileIdle: true # 建议配置为true,不影响性能,并且保证安全性。申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。 | |
| 35 | + testOnBorrow: false # 申请连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | |
| 36 | + testOnReturn: false # 归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。 | |
| 37 | + poolPreparedStatements: false # 是否開啟PSCache,並且指定每個連線上PSCache的大小 | |
| 38 | + timeBetweenEvictionRunsMillis: 60000 # 配置間隔多久才進行一次檢測,檢測需要關閉的空閒連線,單位是毫秒 | |
| 39 | + minEvictableIdleTimeMillis: 300000 # 配置一個連線在池中最小生存的時間,單位是毫秒 | |
| 40 | + filters: stat,wall,slf4j # 配置监控统计拦截的filters,监控统计用的filter:sta, 日志用的filter:log4j, 防御sql注入的filter:wall | |
| 41 | + useGlobalDataSourceStat: true # 合并多个DruidDataSource的监控数据 | |
| 42 | + # 通过connectProperties属性来打开mergeSql功能;慢SQL记录 | |
| 43 | + connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=1000 | |
| 44 | + #stat-view-servlet.url-pattern: /admin/druid/* | |
| 28 | 45 | |
| 29 | -# [可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 46 | +#[可选] WVP监听的HTTP端口, 网页和接口调用都是这个端口 | |
| 30 | 47 | server: |
| 31 | 48 | port: 18080 |
| 32 | 49 | |
| 33 | 50 | # 作为28181服务器的配置 |
| 34 | 51 | sip: |
| 35 | 52 | # [必须修改] 本机的IP |
| 36 | - ip: | |
| 53 | + ip: 192.168.118.70 | |
| 37 | 54 | # [可选] 28181服务监听的端口 |
| 38 | 55 | port: 5060 |
| 39 | 56 | # 根据国标6.1.2中规定,domain宜采用ID统一编码的前十位编码。国标附录D中定义前8位为中心编码(由省级、市级、区级、基层编号组成,参照GB/T 2260-2007) |
| ... | ... | @@ -48,10 +65,9 @@ sip: |
| 48 | 65 | |
| 49 | 66 | #zlm 默认服务器配置 |
| 50 | 67 | media: |
| 51 | - # [必须修改] zlm服务器唯一id,用于触发hook时区别是哪台服务器,general.mediaServerId | |
| 52 | - id: | |
| 68 | + id: FQ3TF8yT83wh5Wvz | |
| 53 | 69 | # [必须修改] zlm服务器的内网IP |
| 54 | - ip: | |
| 70 | + ip: 192.168.118.70 | |
| 55 | 71 | # [必须修改] zlm服务器的http.port |
| 56 | 72 | http-port: 80 |
| 57 | 73 | # [可选] zlm服务器的hook.admin_params=secret |
| ... | ... | @@ -68,25 +84,7 @@ media: |
| 68 | 84 | record-assist-port: 18081 |
| 69 | 85 | # [可选] 日志配置, 一般不需要改 |
| 70 | 86 | logging: |
| 71 | - file: | |
| 72 | - name: logs/wvp.log | |
| 73 | - max-history: 30 | |
| 74 | - max-size: 10MB | |
| 75 | - total-size-cap: 300MB | |
| 76 | - level: | |
| 77 | - com.genersoft.iot: debug | |
| 78 | - com.genersoft.iot.vmp.storager.dao: info | |
| 79 | - com.genersoft.iot.vmp.gb28181: info | |
| 80 | - | |
| 81 | -# [根据业务需求配置] | |
| 82 | -user-settings: | |
| 83 | - # 推流直播是否录制 | |
| 84 | - record-push-live: true | |
| 85 | - auto-apply-play: false | |
| 86 | - | |
| 87 | -# 在线文档: swagger-ui(生产环境建议关闭) | |
| 88 | -swagger-ui: | |
| 89 | - enabled: true | |
| 87 | + config: classpath:logback-spring-local.xml | |
| 90 | 88 | |
| 91 | 89 | # 版本信息, 不需修改 |
| 92 | 90 | version: | ... | ... |
src/main/resources/application-docker.yml
| ... | ... | @@ -69,16 +69,9 @@ media: |
| 69 | 69 | sdp-ip: ${sip.ip} |
| 70 | 70 | stream-ip: ${sip.ip} |
| 71 | 71 | # [可选] 日志配置, 一般不需要改 |
| 72 | +# [可选] 日志配置, 一般不需要改 | |
| 72 | 73 | logging: |
| 73 | - file: | |
| 74 | - name: logs/wvp.log | |
| 75 | - max-history: 30 | |
| 76 | - max-size: 10MB | |
| 77 | - total-size-cap: 300MB | |
| 78 | - level: | |
| 79 | - com.genersoft.iot: debug | |
| 80 | - com.genersoft.iot.vmp.storager.dao: info | |
| 81 | - com.genersoft.iot.vmp.gb28181: info | |
| 74 | + config: classpath:logback-spring-local.xml | |
| 82 | 75 | |
| 83 | 76 | # [根据业务需求配置] |
| 84 | 77 | user-settings: | ... | ... |
src/main/resources/application.yml
src/main/resources/logback-spring-local.xml
0 → 100644
| 1 | +<?xml version="1.0" encoding="UTF-8"?> | |
| 2 | +<configuration debug="false"> | |
| 3 | + <!--定义日志文件的存储地址 --> | |
| 4 | + <springProperty scop="context" name="spring.application.name" source="spring.application.name" defaultValue=""/> | |
| 5 | + <property name="LOG_HOME" value="logs/${spring.application.name}" /> | |
| 6 | + | |
| 7 | + <!--<property name="COLOR_PATTERN" value="%black(%contextName-) %red(%d{yyyy-MM-dd HH:mm:ss}) %green([%thread]) %highlight(%-5level) %boldMagenta( %replace(%caller{1}){'\t|Caller.{1}0|\r\n', ''})- %gray(%msg%xEx%n)" />--> | |
| 8 | + <!-- 控制台输出 --> | |
| 9 | + <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> | |
| 10 | + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |
| 11 | + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> | |
| 12 | + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern> | |
| 13 | + </encoder> | |
| 14 | + </appender> | |
| 15 | + | |
| 16 | + <!-- 按照每天生成日志文件 DEBUG以上级别的日志,仅用于测试环境,正式环境为info级别以上的日志--> | |
| 17 | + <appender name="RollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |
| 18 | + | |
| 19 | + <!-- 文件路径 --> | |
| 20 | + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | |
| 21 | + <!--历史日志文件输出的文件名 --> | |
| 22 | + <FileNamePattern>${LOG_HOME}/wvp-%d{yyyy-MM-dd}.%i.log</FileNamePattern> | |
| 23 | + <!--日志文件保留天数 --> | |
| 24 | + <MaxHistory>30</MaxHistory> | |
| 25 | + <maxFileSize>20MB</maxFileSize> | |
| 26 | + </rollingPolicy> | |
| 27 | + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |
| 28 | + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> | |
| 29 | + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern> | |
| 30 | + </encoder> | |
| 31 | + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> | |
| 32 | + <!--与ThresholdFilter的区别,允许onmatch--> | |
| 33 | + <!--设置日志级别 接收info级别的日志--> | |
| 34 | + <level>DEBUG</level> | |
| 35 | + </filter> | |
| 36 | + </appender> | |
| 37 | + | |
| 38 | + <!-- 生成 error格式日志开始 --> | |
| 39 | + <appender name="RollingFileError" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |
| 40 | + | |
| 41 | + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | |
| 42 | + <!--历史日志文件输出的文件名 --> | |
| 43 | + <FileNamePattern>${LOG_HOME}/error-%d{yyyy-MM-dd}.%i.log</FileNamePattern> | |
| 44 | + <!--日志文件保留天数 --> | |
| 45 | + <MaxHistory>30</MaxHistory> | |
| 46 | + <maxFileSize>20MB</maxFileSize> | |
| 47 | + </rollingPolicy> | |
| 48 | + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |
| 49 | + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> | |
| 50 | + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern> | |
| 51 | + </encoder> | |
| 52 | + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> | |
| 53 | + <!--设置日志级别,过滤掉info日志,只输入error日志--> | |
| 54 | + <level>WARN</level> | |
| 55 | + <!-- <onMatch>ACCEPT</onMatch> <!– 用过滤器,只接受ERROR级别的日志信息,其余全部过滤掉 –>--> | |
| 56 | + <!-- <onMismatch>DENY</onMismatch>--> | |
| 57 | + </filter> | |
| 58 | + </appender> | |
| 59 | + | |
| 60 | + <!-- 生成 druid日志追加 --> | |
| 61 | + <appender name="druidSqlRollingFile" class="ch.qos.logback.core.rolling.RollingFileAppender"> | |
| 62 | + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> | |
| 63 | + <!--历史日志文件输出的文件名 --> | |
| 64 | + <FileNamePattern>${LOG_HOME}/druid-%d{yyyy-MM-dd}.%i.log</FileNamePattern> | |
| 65 | + <!--日志文件保留天数 --> | |
| 66 | + <MaxHistory>30</MaxHistory> | |
| 67 | + <maxFileSize>50MB</maxFileSize> | |
| 68 | + </rollingPolicy> | |
| 69 | + <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"> | |
| 70 | + <!--格式化输出:%d表示日期,%thread表示线程名,%-5level:级别从左显示5个字符宽度%msg:日志消息,%n是换行符 --> | |
| 71 | + <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50}:%L - %msg%n</pattern> | |
| 72 | + </encoder> | |
| 73 | + </appender> | |
| 74 | + | |
| 75 | + | |
| 76 | + <!-- 日志输出级别 --> | |
| 77 | + <root level="INFO"> | |
| 78 | + <appender-ref ref="STDOUT" /> | |
| 79 | + <appender-ref ref="RollingFile" /> | |
| 80 | + <appender-ref ref="RollingFileError" /> | |
| 81 | + </root> | |
| 82 | + | |
| 83 | + <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO"> | |
| 84 | + <appender-ref ref="STDOUT"/> | |
| 85 | + </logger> | |
| 86 | + <logger name="com.genersoft.iot.vmp.gb28181" level="DEBUG"> | |
| 87 | + <appender-ref ref="STDOUT"/> | |
| 88 | + </logger> | |
| 89 | + | |
| 90 | + <!--记录druid-sql的记录--> | |
| 91 | + <logger name="druid.sql.Statement" level="debug" additivity="true"> | |
| 92 | + <!--AppenderRef ref="Console"/--> | |
| 93 | + <!-- <appender-ref ref="RollingFile"/>--> | |
| 94 | + <appender-ref ref="RollingFileError"/> | |
| 95 | + <appender-ref ref="druidSqlRollingFile"/> | |
| 96 | + </logger> | |
| 97 | +</configuration> | |
| 0 | 98 | \ No newline at end of file | ... | ... |
web_src/src/components/DeviceList.vue
| ... | ... | @@ -55,14 +55,14 @@ |
| 55 | 55 | <el-table-column prop="createTime" label="创建时间" align="center" width="140"> |
| 56 | 56 | </el-table-column> |
| 57 | 57 | |
| 58 | - <el-table-column label="操作" width="360" align="center" fixed="right"> | |
| 58 | + <el-table-column label="操作" width="450" align="center" fixed="right"> | |
| 59 | 59 | <template slot-scope="scope"> |
| 60 | 60 | <el-button size="mini" :ref="scope.row.deviceId + 'refbtn' " v-if="scope.row.online!=0" icon="el-icon-refresh" @click="refDevice(scope.row)">刷新</el-button> |
| 61 | 61 | <el-button-group> |
| 62 | 62 | <el-button size="mini" icon="el-icon-video-camera-solid" v-bind:disabled="scope.row.online==0" type="primary" @click="showChannelList(scope.row)">通道</el-button> |
| 63 | 63 | <el-button size="mini" icon="el-icon-location" v-bind:disabled="scope.row.online==0" type="primary" @click="showDevicePosition(scope.row)">定位</el-button> |
| 64 | 64 | <el-button size="mini" icon="el-icon-edit" type="primary" @click="edit(scope.row)">编辑</el-button> |
| 65 | - <el-button size="mini" icon="el-icon-delete" type="danger" v-if="scope.row.online==0" @click="deleteDevice(scope.row)">删除</el-button> | |
| 65 | + <el-button size="mini" icon="el-icon-delete" type="danger" @click="deleteDevice(scope.row)">删除</el-button> | |
| 66 | 66 | </el-button-group> |
| 67 | 67 | </template> |
| 68 | 68 | </el-table-column> |
| ... | ... | @@ -165,15 +165,29 @@ |
| 165 | 165 | |
| 166 | 166 | }, |
| 167 | 167 | deleteDevice: function(row) { |
| 168 | - let that = this; | |
| 169 | - this.$axios({ | |
| 170 | - method: 'delete', | |
| 171 | - url:`/api/device/query/devices/${row.deviceId}/delete` | |
| 172 | - }).then((res)=>{ | |
| 173 | - this.getDeviceList(); | |
| 174 | - }).catch((error) =>{ | |
| 175 | - console.log(error); | |
| 176 | - }); | |
| 168 | + let msg = "确定删除此设备?" | |
| 169 | + if (row.online !== 0) { | |
| 170 | + msg = "在线设备删除后仍可通过注册再次上线。<br/>如需彻底删除请先将设备离线。<br/><strong>确定删除此设备?</strong>" | |
| 171 | + } | |
| 172 | + this.$confirm(msg, '提示', { | |
| 173 | + dangerouslyUseHTMLString : true, | |
| 174 | + confirmButtonText: '确定', | |
| 175 | + cancelButtonText: '取消', | |
| 176 | + center: true, | |
| 177 | + type: 'warning' | |
| 178 | + }).then(() => { | |
| 179 | + this.$axios({ | |
| 180 | + method: 'delete', | |
| 181 | + url:`/api/device/query/devices/${row.deviceId}/delete` | |
| 182 | + }).then((res)=>{ | |
| 183 | + this.getDeviceList(); | |
| 184 | + }).catch((error) =>{ | |
| 185 | + console.log(error); | |
| 186 | + }); | |
| 187 | + }).catch(() => { | |
| 188 | + | |
| 189 | + }); | |
| 190 | + | |
| 177 | 191 | |
| 178 | 192 | }, |
| 179 | 193 | showChannelList: function(row) { | ... | ... |
web_src/src/components/control.vue
| ... | ... | @@ -21,11 +21,11 @@ |
| 21 | 21 | <div style="position: absolute; right: 1rem; top: 0.3rem;"> |
| 22 | 22 | <el-popover placement="bottom" width="900" height="300" trigger="click"> |
| 23 | 23 | <div style="height: 600px; overflow:auto; padding: 20px"> |
| 24 | - <el-descriptions v-for="(value, key, index) in serverConfig" border column="1" style="margin-bottom: 1rem"> | |
| 24 | + <el-descriptions v-for="(value, key, index) in serverConfig" :key="key" border column="1" style="margin-bottom: 1rem"> | |
| 25 | 25 | <template slot="title"> |
| 26 | 26 | {{key}} |
| 27 | 27 | </template> |
| 28 | - <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]"> | |
| 28 | + <el-descriptions-item v-for="(value1, key1, index1) in serverConfig[key]" :key="key1"> | |
| 29 | 29 | <template slot="label" > |
| 30 | 30 | {{ getMediaKeyNameFromKey(key1) }} |
| 31 | 31 | </template> |
| ... | ... | @@ -54,7 +54,7 @@ |
| 54 | 54 | <template slot="extra"> |
| 55 | 55 | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerConfig.base)" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| 56 | 56 | </template> |
| 57 | - <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" > | |
| 57 | + <el-descriptions-item v-for="(value, key, index) in wvpServerConfig.base" :key="key"> | |
| 58 | 58 | <template slot="label" > |
| 59 | 59 | {{ getNameFromKey(key) }} |
| 60 | 60 | </template> |
| ... | ... | @@ -64,7 +64,7 @@ |
| 64 | 64 | 查看<i class="el-icon-arrow-down el-icon--right"></i> |
| 65 | 65 | </span> |
| 66 | 66 | <el-dropdown-menu slot="dropdown"> |
| 67 | - <el-dropdown-item v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes">{{value}}</el-dropdown-item> | |
| 67 | + <el-dropdown-item v-for="(value, key, index) in wvpServerConfig.base.interfaceAuthenticationExcludes" :key="key">{{value}}</el-dropdown-item> | |
| 68 | 68 | </el-dropdown-menu> |
| 69 | 69 | </el-dropdown> |
| 70 | 70 | </div> |
| ... | ... | @@ -88,7 +88,7 @@ |
| 88 | 88 | <template slot="extra"> |
| 89 | 89 | <el-button style="float: right;" type="primary" size="mini" icon="el-icon-document-copy" title="点击拷贝" v-clipboard="JSON.stringify(wvpServerVersion)" @success="$message({type:'success', message:'成功拷贝到粘贴板'})"></el-button> |
| 90 | 90 | </template> |
| 91 | - <el-descriptions-item v-for="(value, key, index) in wvpServerVersion"> | |
| 91 | + <el-descriptions-item v-for="(value, key, index) in wvpServerVersion" :key="key"> | |
| 92 | 92 | <template slot="label"> |
| 93 | 93 | {{ getNameFromKey(key) }} |
| 94 | 94 | </template> | ... | ... |