diff --git a/doc/_content/introduction/config.md b/doc/_content/introduction/config.md index ad88140e9..29f00a4b8 100644 --- a/doc/_content/introduction/config.md +++ b/doc/_content/introduction/config.md @@ -153,7 +153,7 @@ user-settings: # 国标是否录制 record-sip: true # 是否将日志存储进数据库 - logInDatebase: true + logInDatabase: true # 第三方匹配,用于从stream钟获取有效信息 thirdPartyGBIdReg: [\s\S]* ``` diff --git a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java index 886d6fa17..be573166b 100644 --- a/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java +++ b/src/main/java/com/genersoft/iot/vmp/VManageBootstrap.java @@ -1,63 +1,63 @@ -package com.genersoft.iot.vmp; - -import com.genersoft.iot.vmp.utils.GitUtil; -import com.genersoft.iot.vmp.utils.SpringBeanFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.boot.builder.SpringApplicationBuilder; -import org.springframework.boot.web.servlet.ServletComponentScan; -import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; -import org.springframework.context.ConfigurableApplicationContext; -import org.springframework.scheduling.annotation.EnableScheduling; - -import javax.servlet.ServletContext; -import javax.servlet.ServletException; -import javax.servlet.SessionCookieConfig; -import javax.servlet.SessionTrackingMode; -import java.util.Collections; - -/** - * 启动类 - */ -@ServletComponentScan("com.genersoft.iot.vmp.conf") -@SpringBootApplication -@EnableScheduling -public class VManageBootstrap extends SpringBootServletInitializer { - - private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class); - - private static String[] args; - private static ConfigurableApplicationContext context; - public static void main(String[] args) { - VManageBootstrap.args = args; - VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); - GitUtil gitUtil1 = SpringBeanFactory.getBean("gitUtil"); - logger.info("构建版本: {}", gitUtil1.getBuildVersion()); - logger.info("构建时间: {}", gitUtil1.getBuildDate()); - logger.info("GIT最后提交时间: {}", gitUtil1.getCommitTime()); - } - // 项目重启 - public static void restart() { - context.close(); - VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); - } - - @Override - protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { - return application.sources(VManageBootstrap.class); - } - - @Override - public void onStartup(ServletContext servletContext) throws ServletException { - super.onStartup(servletContext); - - servletContext.setSessionTrackingModes( - Collections.singleton(SessionTrackingMode.COOKIE) - ); - SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); - sessionCookieConfig.setHttpOnly(true); - - } -} +package com.genersoft.iot.vmp; + +import com.genersoft.iot.vmp.utils.GitUtil; +import com.genersoft.iot.vmp.utils.SpringBeanFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.servlet.ServletComponentScan; +import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; +import org.springframework.context.ConfigurableApplicationContext; +import org.springframework.scheduling.annotation.EnableScheduling; + +import javax.servlet.ServletContext; +import javax.servlet.ServletException; +import javax.servlet.SessionCookieConfig; +import javax.servlet.SessionTrackingMode; +import java.util.Collections; + +/** + * 启动类 + */ +@ServletComponentScan("com.genersoft.iot.vmp.conf") +@SpringBootApplication +@EnableScheduling +public class VManageBootstrap extends SpringBootServletInitializer { + + private final static Logger logger = LoggerFactory.getLogger(VManageBootstrap.class); + + private static String[] args; + private static ConfigurableApplicationContext context; + public static void main(String[] args) { + VManageBootstrap.args = args; + VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); + GitUtil gitUtil1 = SpringBeanFactory.getBean("gitUtil"); + logger.info("构建版本: {}", gitUtil1.getBuildVersion()); + logger.info("构建时间: {}", gitUtil1.getBuildDate()); + logger.info("GIT最后提交时间: {}", gitUtil1.getCommitTime()); + } + // 项目重启 + public static void restart() { + context.close(); + VManageBootstrap.context = SpringApplication.run(VManageBootstrap.class, args); + } + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(VManageBootstrap.class); + } + + @Override + public void onStartup(ServletContext servletContext) throws ServletException { + super.onStartup(servletContext); + + servletContext.setSessionTrackingModes( + Collections.singleton(SessionTrackingMode.COOKIE) + ); + SessionCookieConfig sessionCookieConfig = servletContext.getSessionCookieConfig(); + sessionCookieConfig.setHttpOnly(true); + + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index 274f7a8af..0b8100b64 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -1,175 +1,177 @@ -package com.genersoft.iot.vmp.common; - -/** - * @description: 定义常量 - * @author: swwheihei - * @date: 2019年5月30日 下午3:04:04 - * - */ -public class VideoManagerConstants { - - public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_"; - - public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_"; - - public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; - - public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; - - public static final String DEVICE_PREFIX = "VMP_DEVICE_"; - - // 设备同步完成 - public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_"; - - public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_"; - - public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_"; - - // TODO 此处多了一个_,暂不修改 - public static final String INVITE_PREFIX = "VMP_INVITE"; - public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_"; - public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_"; - public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_"; - - public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_"; - - public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_"; - - public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_"; - - public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_"; - - public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_"; - - public static final String EVENT_ONLINE_REGISTER = "1"; - - public static final String EVENT_ONLINE_MESSAGE = "3"; - - public static final String EVENT_OUTLINE_UNREGISTER = "1"; - - public static final String EVENT_OUTLINE_TIMEOUT = "2"; - - public static final String MEDIA_SSRC_USED_PREFIX = "VMP_MEDIA_USED_SSRC_"; - - public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_"; - - public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_"; - - public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_"; - - public static final String SIP_SN_PREFIX = "VMP_SIP_SN_"; - - public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_"; - - public static final String SYSTEM_INFO_CPU_PREFIX = "VMP_SYSTEM_INFO_CPU_"; - - public static final String SYSTEM_INFO_MEM_PREFIX = "VMP_SYSTEM_INFO_MEM_"; - - public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_"; - - public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_"; - public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_"; - - public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_"; - - - - - //************************** redis 消息********************************* - - /** - * 流变化的通知 - */ - public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_"; - - /** - * 接收推流设备的GPS变化通知 - */ - public static final String VM_MSG_GPS = "VM_MSG_GPS"; - - /** - * 接收推流设备的GPS变化通知 - */ - public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE"; - /** - * 接收推流设备列表更新变化通知 - */ - public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE"; - - /** - * redis 消息通知设备推流到平台 - */ - public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED"; - - /** - * redis 消息通知上级平台开始观看流 - */ - public static final String VM_MSG_STREAM_START_PLAY_NOTIFY = "VM_MSG_STREAM_START_PLAY_NOTIFY"; - - /** - * redis 消息通知上级平台停止观看流 - */ - public static final String VM_MSG_STREAM_STOP_PLAY_NOTIFY = "VM_MSG_STREAM_STOP_PLAY_NOTIFY"; - - /** - * redis 消息接收关闭一个推流 - */ - public static final String VM_MSG_STREAM_PUSH_CLOSE_REQUESTED = "VM_MSG_STREAM_PUSH_CLOSE_REQUESTED"; - - - /** - * redis 消息通知平台通知设备推流结果 - */ - public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE"; - - /** - * redis 通知平台关闭推流 - */ - public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE"; - - /** - * redis 消息请求所有的在线通道 - */ - public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED"; - - /** - * 移动位置订阅通知 - */ - public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition"; - - /** - * 报警订阅的通知(收到报警向redis发出通知) - */ - public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm"; - - - /** - * 报警通知的发送 (收到redis发出的通知,转发给其他平台) - */ - public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive"; - - /** - * 设备状态订阅的通知 - */ - public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device"; - - - //************************** 第三方 **************************************** - - public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; - public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_"; - public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_"; - public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_"; - - /** - * Redis Const - * 设备录像信息结果前缀 - */ - public static final String REDIS_RECORD_INFO_RES_PRE = "GB_RECORD_INFO_RES_"; - /** - * Redis Const - * 设备录像信息结果前缀 - */ - public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:"; - -} +package com.genersoft.iot.vmp.common; + +/** + * @description: 定义常量 + * @author: swwheihei + * @date: 2019年5月30日 下午3:04:04 + * + */ +public class VideoManagerConstants { + + public static final String WVP_SERVER_PREFIX = "VMP_SIGNALLING_SERVER_INFO_"; + + public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_"; + + public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; + + public static final String MEDIA_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; + + public static final String DEVICE_PREFIX = "VMP_DEVICE_"; + + // 设备同步完成 + public static final String DEVICE_SYNC_PREFIX = "VMP_DEVICE_SYNC_"; + + public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_"; + + public static final String KEEPLIVEKEY_PREFIX = "VMP_KEEPALIVE_"; + + // TODO 此处多了一个_,暂不修改 + public static final String INVITE_PREFIX = "VMP_INVITE"; + public static final String PLAYER_PREFIX = "VMP_INVITE_PLAY_"; + public static final String PLAY_BLACK_PREFIX = "VMP_INVITE_PLAYBACK_"; + public static final String DOWNLOAD_PREFIX = "VMP_INVITE_DOWNLOAD_"; + + public static final String PLATFORM_KEEPALIVE_PREFIX = "VMP_PLATFORM_KEEPALIVE_"; + + public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_"; + + public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_"; + + public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_"; + + public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_"; + + public static final String EVENT_ONLINE_REGISTER = "1"; + + public static final String EVENT_ONLINE_MESSAGE = "3"; + + public static final String EVENT_OUTLINE_UNREGISTER = "1"; + + public static final String EVENT_OUTLINE_TIMEOUT = "2"; + + public static final String MEDIA_SSRC_USED_PREFIX = "VMP_MEDIA_USED_SSRC_"; + + public static final String MEDIA_TRANSACTION_USED_PREFIX = "VMP_MEDIA_TRANSACTION_"; + + public static final String MEDIA_STREAM_AUTHORITY = "MEDIA_STREAM_AUTHORITY_"; + + public static final String SIP_CSEQ_PREFIX = "VMP_SIP_CSEQ_"; + + public static final String SIP_SN_PREFIX = "VMP_SIP_SN_"; + + public static final String SIP_SUBSCRIBE_PREFIX = "VMP_SIP_SUBSCRIBE_"; + + public static final String SYSTEM_INFO_CPU_PREFIX = "VMP_SYSTEM_INFO_CPU_"; + + public static final String SYSTEM_INFO_MEM_PREFIX = "VMP_SYSTEM_INFO_MEM_"; + + public static final String SYSTEM_INFO_NET_PREFIX = "VMP_SYSTEM_INFO_NET_"; + + public static final String SYSTEM_INFO_DISK_PREFIX = "VMP_SYSTEM_INFO_DISK_"; + public static final String BROADCAST_WAITE_INVITE = "task_broadcast_waite_invite_"; + + public static final String REGISTER_EXPIRE_TASK_KEY_PREFIX = "VMP_device_register_expire_"; + + + + + //************************** redis 消息********************************* + + /** + * 流变化的通知 + */ + public static final String WVP_MSG_STREAM_CHANGE_PREFIX = "WVP_MSG_STREAM_CHANGE_"; + + /** + * 接收推流设备的GPS变化通知 + */ + public static final String VM_MSG_GPS = "VM_MSG_GPS"; + + /** + * 接收推流设备的GPS变化通知 + */ + public static final String VM_MSG_PUSH_STREAM_STATUS_CHANGE = "VM_MSG_PUSH_STREAM_STATUS_CHANGE"; + /** + * 接收推流设备列表更新变化通知 + */ + public static final String VM_MSG_PUSH_STREAM_LIST_CHANGE = "VM_MSG_PUSH_STREAM_LIST_CHANGE"; + + /** + * redis 消息通知设备推流到平台 + */ + public static final String VM_MSG_STREAM_PUSH_REQUESTED = "VM_MSG_STREAM_PUSH_REQUESTED"; + + /** + * redis 消息通知上级平台开始观看流 + */ + public static final String VM_MSG_STREAM_START_PLAY_NOTIFY = "VM_MSG_STREAM_START_PLAY_NOTIFY"; + + /** + * redis 消息通知上级平台停止观看流 + */ + public static final String VM_MSG_STREAM_STOP_PLAY_NOTIFY = "VM_MSG_STREAM_STOP_PLAY_NOTIFY"; + + /** + * redis 消息接收关闭一个推流 + */ + public static final String VM_MSG_STREAM_PUSH_CLOSE_REQUESTED = "VM_MSG_STREAM_PUSH_CLOSE_REQUESTED"; + + + /** + * redis 消息通知平台通知设备推流结果 + */ + public static final String VM_MSG_STREAM_PUSH_RESPONSE = "VM_MSG_STREAM_PUSH_RESPONSE"; + + /** + * redis 通知平台关闭推流 + */ + public static final String VM_MSG_STREAM_PUSH_CLOSE = "VM_MSG_STREAM_PUSH_CLOSE"; + + /** + * redis 消息请求所有的在线通道 + */ + public static final String VM_MSG_GET_ALL_ONLINE_REQUESTED = "VM_MSG_GET_ALL_ONLINE_REQUESTED"; + + /** + * 移动位置订阅通知 + */ + public static final String VM_MSG_SUBSCRIBE_MOBILE_POSITION = "mobileposition"; + + /** + * 报警订阅的通知(收到报警向redis发出通知) + */ + public static final String VM_MSG_SUBSCRIBE_ALARM = "alarm"; + + + /** + * 报警通知的发送 (收到redis发出的通知,转发给其他平台) + */ + public static final String VM_MSG_SUBSCRIBE_ALARM_RECEIVE= "alarm_receive"; + + /** + * 设备状态订阅的通知 + */ + public static final String VM_MSG_SUBSCRIBE_DEVICE_STATUS = "device"; + + + //************************** 第三方 **************************************** + + public static final String WVP_STREAM_GB_ID_PREFIX = "memberNo_"; + public static final String WVP_STREAM_GPS_MSG_PREFIX = "WVP_STREAM_GPS_MSG_"; + public static final String WVP_OTHER_SEND_RTP_INFO = "VMP_OTHER_SEND_RTP_INFO_"; + public static final String WVP_OTHER_SEND_PS_INFO = "VMP_OTHER_SEND_PS_INFO_"; + public static final String WVP_OTHER_RECEIVE_RTP_INFO = "VMP_OTHER_RECEIVE_RTP_INFO_"; + public static final String WVP_OTHER_RECEIVE_PS_INFO = "VMP_OTHER_RECEIVE_PS_INFO_"; + + /** + * Redis Const + * 设备录像信息结果前缀 + */ + public static final String REDIS_RECORD_INFO_RES_PRE = "GB_RECORD_INFO_RES_"; + /** + * Redis Const + * 设备录像信息结果前缀 + */ + public static final String REDIS_RECORD_INFO_RES_COUNT_PRE = "GB_RECORD_INFO_RES_COUNT:"; + +} diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java index 4d885e86c..b449b1b7e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java @@ -51,7 +51,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { filterChain.doFilter(servletRequest, servletResponse); - if (uriName != null && userSetting != null && userSetting.getLogInDatebase() != null && userSetting.getLogInDatebase()) { + if (uriName != null && userSetting != null && userSetting.getLogInDatabase() != null && userSetting.getLogInDatabase()) { LogDto logDto = new LogDto(); logDto.setName(uriName); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/CivilCodeFileConf.java b/src/main/java/com/genersoft/iot/vmp/conf/CivilCodeFileConf.java index 39e0a70a4..20b6eef77 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/CivilCodeFileConf.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/CivilCodeFileConf.java @@ -12,7 +12,10 @@ import org.springframework.core.annotation.Order; import org.springframework.core.io.ClassPathResource; import org.springframework.util.ObjectUtils; -import java.io.*; +import java.io.BufferedReader; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; import java.nio.file.Files; import java.util.Map; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java index 873feab58..5a451e35f 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -111,7 +111,7 @@ public class DynamicTask { } boolean result = false; if (!ObjectUtils.isEmpty(futureMap.get(key)) && !futureMap.get(key).isCancelled() && !futureMap.get(key).isDone()) { - result = futureMap.get(key).cancel(true); + result = futureMap.get(key).cancel(false); futureMap.remove(key); runnableMap.remove(key); } @@ -143,7 +143,8 @@ public class DynamicTask { public void execute(){ if (futureMap.size() > 0) { for (String key : futureMap.keySet()) { - if (futureMap.get(key).isDone() || futureMap.get(key).isCancelled()) { + ScheduledFuture future = futureMap.get(key); + if (future.isDone() || future.isCancelled()) { futureMap.remove(key); runnableMap.remove(key); } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java index f3fd1d80a..a7416a8e7 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java @@ -18,6 +18,7 @@ import org.springframework.util.ObjectUtils; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.ConnectException; @@ -64,6 +65,18 @@ public class ProxyServletConfig { return queryStr; } + + @Override + protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse, + HttpRequest proxyRequest) throws IOException { + HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest); + response.removeHeaders("Access-Control-Allow-Origin"); + response.setHeader("Access-Control-Allow-Credentials","true"); + response.removeHeaders("Access-Control-Allow-Credentials"); + + return response; + } + /** * 异常处理 */ @@ -181,6 +194,18 @@ public class ProxyServletConfig { return queryStr; } + + @Override + protected HttpResponse doExecute(HttpServletRequest servletRequest, HttpServletResponse servletResponse, + HttpRequest proxyRequest) throws IOException { + HttpResponse response = super.doExecute(servletRequest, servletResponse, proxyRequest); + String origin = servletRequest.getHeader("origin"); + response.setHeader("Access-Control-Allow-Origin",origin); + response.setHeader("Access-Control-Allow-Credentials","true"); + + return response; + } + /** * 异常处理 */ diff --git a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java index eb1b157a3..7760bddfa 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/SipPlatformRunner.java @@ -4,8 +4,11 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.service.IPlatformService; +import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; @@ -33,6 +36,7 @@ public class SipPlatformRunner implements CommandLineRunner { @Autowired private ISIPCommanderForPlatform sipCommanderForPlatform; + private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class); @Override public void run(String... args) throws Exception { @@ -50,9 +54,15 @@ public class SipPlatformRunner implements CommandLineRunner { redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); if (parentPlatformCatchOld != null) { // 取消订阅 - sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{ - platformService.login(parentPlatform); - }); + try { + sipCommanderForPlatform.unregister(parentPlatform, parentPlatformCatchOld.getSipTransactionInfo(), null, (eventResult)->{ + platformService.login(parentPlatform); + }); + } catch (Exception e) { + logger.error("[命令发送失败] 国标级联 注销: {}", e.getMessage()); + platformService.offline(parentPlatform, true); + continue; + } } // 设置所有平台离线 diff --git a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java index 0993d74a7..aadbf479a 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java @@ -31,7 +31,7 @@ public class UserSetting { private Boolean recordSip = Boolean.TRUE; - private Boolean logInDatebase = Boolean.TRUE; + private Boolean logInDatabase = Boolean.TRUE; private Boolean usePushingAsStatus = Boolean.FALSE; @@ -134,12 +134,12 @@ public class UserSetting { this.interfaceAuthenticationExcludes = interfaceAuthenticationExcludes; } - public Boolean getLogInDatebase() { - return logInDatebase; + public Boolean getLogInDatabase() { + return logInDatabase; } - public void setLogInDatebase(Boolean logInDatebase) { - this.logInDatebase = logInDatebase; + public void setLogInDatabase(Boolean logInDatabase) { + this.logInDatabase = logInDatabase; } public String getServerId() { diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java index c9c7b680f..65e9de37f 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/JwtUtils.java @@ -1,8 +1,10 @@ package com.genersoft.iot.vmp.conf.security; import com.genersoft.iot.vmp.conf.security.dto.JwtUser; -import org.jose4j.json.JsonUtil; +import com.genersoft.iot.vmp.service.IUserService; +import com.genersoft.iot.vmp.storager.dao.dto.User; import org.jose4j.jwk.RsaJsonWebKey; +import org.jose4j.jwk.RsaJwkGenerator; import org.jose4j.jws.AlgorithmIdentifiers; import org.jose4j.jws.JsonWebSignature; import org.jose4j.jwt.JwtClaims; @@ -14,45 +16,69 @@ import org.jose4j.jwt.consumer.JwtConsumerBuilder; import org.jose4j.lang.JoseException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.stereotype.Component; -import java.security.PrivateKey; +import javax.annotation.Resource; import java.time.LocalDateTime; import java.time.ZoneOffset; -public class JwtUtils { +@Component +public class JwtUtils implements InitializingBean { private static final Logger logger = LoggerFactory.getLogger(JwtUtils.class); private static final String HEADER = "access-token"; + private static final String AUDIENCE = "Audience"; - private static final long EXPIRED_THRESHOLD = 10 * 60; - private static final String keyId = "3e79646c4dbc408383a9eed09f2b85ae"; - private static final String privateKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\",\"d\":\"ed7U_k3rJ4yTk70JtRSIfjKGiEb67BO1TabcymnljKO7RU8nage84zZYuSu_XpQsHk6P1f0Gzxkicghm_Er-FrfVn2pp70Xu52z3yRd6BJUgWLDFk97ngScIyw5OiULKU9SrZk2frDpftNCSUcIgb50F8m0QAnBa_CdPsQKbuuhLv8V8tBAV7F_lAwvSBgu56wRo3hPz5dWH8YeXM7XBfQ9viFMNEKd21sP_j5C7ueUnXT66nBxe3ZJEU3iuMYM6D6dB_KW2GfZC6WmTgvGhhxJD0h7aYmfjkD99MDleB7SkpbvoODOqiQ5Epb7Nyh6kv5u4KUv2CJYtATLZkUeMkQ\",\"p\":\"uBUjWPWtlGksmOqsqCNWksfqJvMcnP_8TDYN7e4-WnHL4N-9HjRuPDnp6kHvCIEi9SEfxm7gNxlRcWegvNQr3IZCz7TnCTexXc5NOklB9OavWFla6u-s3Thn6Tz45-EUjpJr0VJMxhO-KxGmuTwUXBBp4vN6K2qV6rQNFmgkWzk\",\"q\":\"tW_i7cCec56bHkhITL_79dXHz_PLC_f7xlynmlZJGU_d6mqOKmLBNBbTMLnYW8uAFiFzWxDeDHh1o5uF0mSQR-Z1Fg35OftnpbWpy0Cbc2la5WgXQjOwtG1eLYIY2BD3-wQ1VYDBCvowr4FDi-sngxwLqvwmrJ0xjhi99O-Gzcs\",\"dp\":\"q1d5jE85Hz_6M-eTh_lEluEf0NtPEc-vvhw-QO4V-cecNpbrCBdTWBmr4dE3NdpFeJc5ZVFEv-SACyei1MBEh0ItI_pFZi4BmMfy2ELh8ptaMMkTOESYyVy8U7veDq9RnBcr5i1Nqr0rsBkA77-9T6gzdvycBZdzLYAkAmwzEvk\",\"dq\":\"q29A2K08Crs-jmp2Bi8Q_8QzvIX6wSBbwZ4ir24AO-5_HNP56IrPS0yV2GCB0pqCOGb6_Hz_koDvhtuYoqdqvMVAtMoXR3YJBUaVXPt65p4RyNmFwIPe31zHs_BNUTsXVRMw4c16mci03-Af1sEm4HdLfxAp6sfM3xr5wcnhcek\",\"qi\":\"rHPgVTyHUHuYzcxfouyBfb1XAY8nshwn0ddo81o1BccD4Z7zo5It6SefDHjxCAbcmbiCcXBSooLcY-NF5FMv3fg19UE21VyLQltHcVjRRp2tRs4OHcM8yaXIU2x6N6Z6BP2tOksHb9MOBY1wAQzFOAKg_G4Sxev6-_6ud6RISuc\"}"; - private static final String publicKeyStr = "{\"kty\":\"RSA\",\"kid\":\"3e79646c4dbc408383a9eed09f2b85ae\",\"alg\":\"RS256\",\"n\":\"gndmVdiOTSJ5et2HIeTM5f1m61x5ojLUi5HDfvr-jRrESQ5kbKuySGHVwR4QhwinpY1wQqBnwc80tx7cb_6SSqsTOoGln6T_l3k2Pb54ClVnGWiW_u1kmX78V2TZOsVmZmwtdZCMi-2zWIyAdIEXE-gncIehoAgEoq2VAhaCURbJWro_EwzzQwNmCTkDodLAx4npXRd_qSu0Ayp0txym9OFovBXBULRvk4DPiy3i_bPUmCDxzC46pTtFOe9p82uybTehZfULZtXXqRm85FL9n5zkrsTllPNAyEGhgb0RK9sE5nK1m_wNNysDyfLC4EFf1VXTrKm14XNVjc2vqLb7Mw\",\"e\":\"AQAB\"}"; /** * token过期时间(分钟) */ - public static final long expirationTime = 30; + public static final long expirationTime = 30 * 24 * 60; - public static String createToken(String username, String password, Integer roleId) { + private static RsaJsonWebKey rsaJsonWebKey; + + private static IUserService userService; + + @Resource + public void setUserService(IUserService userService) { + JwtUtils.userService = userService; + } + + @Override + public void afterPropertiesSet() { try { - /** + rsaJsonWebKey = generateRsaJsonWebKey(); + } catch (JoseException e) { + logger.error("生成RsaJsonWebKey报错。", e); + } + } + + /** + * 创建密钥对 + * @throws JoseException JoseException + */ + private RsaJsonWebKey generateRsaJsonWebKey() throws JoseException { + // 生成一个RSA密钥对,该密钥对将用于JWT的签名和验证,包装在JWK中 + RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048); + // 给JWK一个密钥ID + rsaJsonWebKey.setKeyId(keyId); + return rsaJsonWebKey; + } + + public static String createToken(String username) { + try { + /* * “iss” (issuer) 发行人 - * * “sub” (subject) 主题 - * * “aud” (audience) 接收方 用户 - * * “exp” (expiration time) 到期时间 - * * “nbf” (not before) 在此之前不可用 - * * “iat” (issued at) jwt的签发时间 */ - //Payload JwtClaims claims = new JwtClaims(); claims.setGeneratedJwtId(); claims.setIssuedAtToNow(); @@ -62,9 +88,7 @@ public class JwtUtils { claims.setSubject("login"); claims.setAudience(AUDIENCE); //添加自定义参数,必须是字符串类型 - claims.setClaim("username", username); - claims.setClaim("password", password); - claims.setClaim("roleId", roleId); + claims.setClaim("userName", username); //jws JsonWebSignature jws = new JsonWebSignature(); @@ -73,12 +97,10 @@ public class JwtUtils { jws.setKeyIdHeaderValue(keyId); jws.setPayload(claims.toJson()); - PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyStr)).getPrivateKey(); - jws.setKey(privateKey); + jws.setKey(rsaJsonWebKey.getPrivateKey()); //get token - String idToken = jws.getCompactSerialization(); - return idToken; + return jws.getCompactSerialization(); } catch (JoseException e) { logger.error("[Token生成失败]: {}", e.getMessage()); } @@ -90,7 +112,6 @@ public class JwtUtils { return HEADER; } - public static JwtUser verifyToken(String token) { JwtUser jwtUser = new JwtUser(); @@ -103,7 +124,7 @@ public class JwtUtils { .setRequireSubject() //.setExpectedIssuer("") .setExpectedAudience(AUDIENCE) - .setVerificationKey(new RsaJsonWebKey(JsonUtil.parseJson(publicKeyStr)).getPublicKey()) + .setVerificationKey(rsaJsonWebKey.getPublicKey()) .build(); JwtClaims claims = consumer.processToClaims(token); @@ -113,26 +134,26 @@ public class JwtUtils { long timeRemaining = LocalDateTime.now().toEpochSecond(ZoneOffset.ofHours(8)) - expirationTime.getValue(); if (timeRemaining < 5 * 60) { jwtUser.setStatus(JwtUser.TokenStatus.EXPIRING_SOON); - }else { + } else { jwtUser.setStatus(JwtUser.TokenStatus.NORMAL); } - String username = (String) claims.getClaimValue("username"); - String password = (String) claims.getClaimValue("password"); - Long roleId = (Long) claims.getClaimValue("roleId"); + String username = (String) claims.getClaimValue("userName"); + User user = userService.getUserByUsername(username); + jwtUser.setUserName(username); - jwtUser.setPassword(password); - jwtUser.setRoleId(roleId.intValue()); + jwtUser.setPassword(user.getPassword()); + jwtUser.setRoleId(user.getRole().getId()); return jwtUser; } catch (InvalidJwtException e) { if (e.hasErrorCode(ErrorCodes.EXPIRED)) { jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED); - }else { + } else { jwtUser.setStatus(JwtUser.TokenStatus.EXCEPTION); } return jwtUser; - }catch (Exception e) { + } catch (Exception e) { logger.error("[Token解析失败]: {}", e.getMessage()); jwtUser.setStatus(JwtUser.TokenStatus.EXPIRED); return jwtUser; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 0c77fc183..56663f18d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -1,141 +1,141 @@ -package com.genersoft.iot.vmp.gb28181; - -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory; -import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; -import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; -import gov.nist.javax.sip.SipProviderImpl; -import gov.nist.javax.sip.SipStackImpl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.core.annotation.Order; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; - -import javax.sip.*; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -@Component -@Order(value=10) -public class SipLayer implements CommandLineRunner { - - private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); - - @Autowired - private SipConfig sipConfig; - - @Autowired - private ISIPProcessorObserver sipProcessorObserver; - - @Autowired - private UserSetting userSetting; - - private final Map tcpSipProviderMap = new ConcurrentHashMap<>(); - private final Map udpSipProviderMap = new ConcurrentHashMap<>(); - - @Override - public void run(String... args) { - List monitorIps = new ArrayList<>(); - // 使用逗号分割多个ip - String separator = ","; - if (sipConfig.getIp().indexOf(separator) > 0) { - String[] split = sipConfig.getIp().split(separator); - monitorIps.addAll(Arrays.asList(split)); - }else { - monitorIps.add(sipConfig.getIp()); - } - - SipFactory.getInstance().setPathName("gov.nist"); - if (monitorIps.size() > 0) { - for (String monitorIp : monitorIps) { - addListeningPoint(monitorIp, sipConfig.getPort()); - } - if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) { - System.exit(1); - } - } - } - - private void addListeningPoint(String monitorIp, int port){ - SipStackImpl sipStack; - try { - sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog())); - sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); - } catch (PeerUnavailableException e) { - logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); - return; - } - - try { - ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP"); - SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint); - - tcpSipProvider.setDialogErrorsAutomaticallyHandled(); - tcpSipProvider.addSipListener(sipProcessorObserver); - tcpSipProviderMap.put(monitorIp, tcpSipProvider); - logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port); - } catch (TransportNotSupportedException - | TooManyListenersException - | ObjectInUseException - | InvalidArgumentException e) { - logger.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确" - , monitorIp, port); - } - - try { - ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP"); - - SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint); - udpSipProvider.addSipListener(sipProcessorObserver); - - udpSipProviderMap.put(monitorIp, udpSipProvider); - - logger.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port); - } catch (TransportNotSupportedException - | TooManyListenersException - | ObjectInUseException - | InvalidArgumentException e) { - logger.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确" - , monitorIp, port); - } - } - - public SipProviderImpl getUdpSipProvider(String ip) { - if (ObjectUtils.isEmpty(ip)) { - return null; - } - return udpSipProviderMap.get(ip); - } - - public SipProviderImpl getUdpSipProvider() { - if (udpSipProviderMap.size() != 1) { - return null; - } - return udpSipProviderMap.values().stream().findFirst().get(); - } - - public SipProviderImpl getTcpSipProvider() { - if (tcpSipProviderMap.size() != 1) { - return null; - } - return tcpSipProviderMap.values().stream().findFirst().get(); - } - - public SipProviderImpl getTcpSipProvider(String ip) { - if (ObjectUtils.isEmpty(ip)) { - return null; - } - return tcpSipProviderMap.get(ip); - } - - public String getLocalIp(String deviceLocalIp) { - if (!ObjectUtils.isEmpty(deviceLocalIp)) { - return deviceLocalIp; - } - return getUdpSipProvider().getListeningPoint().getIPAddress(); - } -} +package com.genersoft.iot.vmp.gb28181; + +import com.genersoft.iot.vmp.conf.SipConfig; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.GbStringMsgParserFactory; +import com.genersoft.iot.vmp.gb28181.conf.DefaultProperties; +import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; +import gov.nist.javax.sip.SipProviderImpl; +import gov.nist.javax.sip.SipStackImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import javax.sip.*; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Component +@Order(value=10) +public class SipLayer implements CommandLineRunner { + + private final static Logger logger = LoggerFactory.getLogger(SipLayer.class); + + @Autowired + private SipConfig sipConfig; + + @Autowired + private ISIPProcessorObserver sipProcessorObserver; + + @Autowired + private UserSetting userSetting; + + private final Map tcpSipProviderMap = new ConcurrentHashMap<>(); + private final Map udpSipProviderMap = new ConcurrentHashMap<>(); + + @Override + public void run(String... args) { + List monitorIps = new ArrayList<>(); + // 使用逗号分割多个ip + String separator = ","; + if (sipConfig.getIp().indexOf(separator) > 0) { + String[] split = sipConfig.getIp().split(separator); + monitorIps.addAll(Arrays.asList(split)); + }else { + monitorIps.add(sipConfig.getIp()); + } + + SipFactory.getInstance().setPathName("gov.nist"); + if (monitorIps.size() > 0) { + for (String monitorIp : monitorIps) { + addListeningPoint(monitorIp, sipConfig.getPort()); + } + if (udpSipProviderMap.size() + tcpSipProviderMap.size() == 0) { + System.exit(1); + } + } + } + + private void addListeningPoint(String monitorIp, int port){ + SipStackImpl sipStack; + try { + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog())); + sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); + } catch (PeerUnavailableException e) { + logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); + return; + } + + try { + ListeningPoint tcpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "TCP"); + SipProviderImpl tcpSipProvider = (SipProviderImpl)sipStack.createSipProvider(tcpListeningPoint); + + tcpSipProvider.setDialogErrorsAutomaticallyHandled(); + tcpSipProvider.addSipListener(sipProcessorObserver); + tcpSipProviderMap.put(monitorIp, tcpSipProvider); + logger.info("[SIP SERVER] tcp://{}:{} 启动成功", monitorIp, port); + } catch (TransportNotSupportedException + | TooManyListenersException + | ObjectInUseException + | InvalidArgumentException e) { + logger.error("[SIP SERVER] tcp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确" + , monitorIp, port); + } + + try { + ListeningPoint udpListeningPoint = sipStack.createListeningPoint(monitorIp, port, "UDP"); + + SipProviderImpl udpSipProvider = (SipProviderImpl)sipStack.createSipProvider(udpListeningPoint); + udpSipProvider.addSipListener(sipProcessorObserver); + + udpSipProviderMap.put(monitorIp, udpSipProvider); + + logger.info("[SIP SERVER] udp://{}:{} 启动成功", monitorIp, port); + } catch (TransportNotSupportedException + | TooManyListenersException + | ObjectInUseException + | InvalidArgumentException e) { + logger.error("[SIP SERVER] udp://{}:{} SIP服务启动失败,请检查端口是否被占用或者ip是否正确" + , monitorIp, port); + } + } + + public SipProviderImpl getUdpSipProvider(String ip) { + if (ObjectUtils.isEmpty(ip)) { + return null; + } + return udpSipProviderMap.get(ip); + } + + public SipProviderImpl getUdpSipProvider() { + if (udpSipProviderMap.size() != 1) { + return null; + } + return udpSipProviderMap.values().stream().findFirst().get(); + } + + public SipProviderImpl getTcpSipProvider() { + if (tcpSipProviderMap.size() != 1) { + return null; + } + return tcpSipProviderMap.values().stream().findFirst().get(); + } + + public SipProviderImpl getTcpSipProvider(String ip) { + if (ObjectUtils.isEmpty(ip)) { + return null; + } + return tcpSipProviderMap.get(ip); + } + + public String getLocalIp(String deviceLocalIp) { + if (!ObjectUtils.isEmpty(deviceLocalIp)) { + return deviceLocalIp; + } + return getUdpSipProvider().getListeningPoint().getIPAddress(); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java index bfc97b555..371134160 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/DeviceAlarm.java @@ -1,187 +1,187 @@ -package com.genersoft.iot.vmp.gb28181.bean; - -import io.swagger.v3.oas.annotations.media.Schema; - -/** - * @author lin - */ -@Schema(description = "报警信息") -public class DeviceAlarm { - - /** - * 数据库id - */ - @Schema(description = "数据库id") - private String id; - - /** - * 设备Id - */ - @Schema(description = "设备的国标编号") - private String deviceId; - - /** - * 通道Id - */ - @Schema(description = "通道的国标编号") - private String channelId; - - /** - * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情 - */ - @Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情") - private String alarmPriority; - - /** - * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警, - * 7其他报警;可以为直接组合如12为电话报警或 设备报警- - */ - @Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" + - "\t * 7其他报警;可以为直接组合如12为电话报警或设备报警") - private String alarmMethod; - - /** - * 报警时间 - */ - @Schema(description = "报警时间") - private String alarmTime; - - /** - * 报警内容描述 - */ - @Schema(description = "报警内容描述") - private String alarmDescription; - - /** - * 经度 - */ - @Schema(description = "经度") - private double longitude; - - /** - * 纬度 - */ - @Schema(description = "纬度") - private double latitude; - - /** - * 报警类型, - * 报警方式为2时,不携带 AlarmType为默认的报警设备报警, - * 携带 AlarmType取值及对应报警类型如下: - * 1-视频丢失报警; - * 2-设备防拆报警; - * 3-存储设备磁盘满报警; - * 4-设备高温报警; - * 5-设备低温报警。 - * 报警方式为5时,取值如下: - * 1-人工视频报警; - * 2-运动目标检测报警; - * 3-遗留物检测报警; - * 4-物体移除检测报警; - * 5-绊线检测报警; - * 6-入侵检测报警; - * 7-逆行检测报警; - * 8-徘徊检测报警; - * 9-流量统计报警; - * 10-密度检测报警; - * 11-视频异常检测报警; - * 12-快速移动报警。 - * 报警方式为6时,取值下: - * 1-存储设备磁盘故障报警; - * 2-存储设备风扇故障报警。 - */ - @Schema(description = "报警类型") - private String alarmType; - - @Schema(description = "创建时间") - private String createTime; - - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getAlarmPriority() { - return alarmPriority; - } - - public void setAlarmPriority(String alarmPriority) { - this.alarmPriority = alarmPriority; - } - - public String getAlarmMethod() { - return alarmMethod; - } - - public void setAlarmMethod(String alarmMethod) { - this.alarmMethod = alarmMethod; - } - - public String getAlarmTime() { - return alarmTime; - } - - public void setAlarmTime(String alarmTime) { - this.alarmTime = alarmTime; - } - - public String getAlarmDescription() { - return alarmDescription; - } - - public void setAlarmDescription(String alarmDescription) { - this.alarmDescription = alarmDescription; - } - - public double getLongitude() { - return longitude; - } - - public void setLongitude(double longitude) { - this.longitude = longitude; - } - - public double getLatitude() { - return latitude; - } - - public void setLatitude(double latitude) { - this.latitude = latitude; - } - - public String getAlarmType() { - return alarmType; - } - - public void setAlarmType(String alarmType) { - this.alarmType = alarmType; - } - - public String getChannelId() { - return channelId; - } - - public void setChannelId(String channelId) { - this.channelId = channelId; - } - - public String getCreateTime() { - return createTime; - } - - public void setCreateTime(String createTime) { - this.createTime = createTime; - } -} +package com.genersoft.iot.vmp.gb28181.bean; + +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * @author lin + */ +@Schema(description = "报警信息") +public class DeviceAlarm { + + /** + * 数据库id + */ + @Schema(description = "数据库id") + private String id; + + /** + * 设备Id + */ + @Schema(description = "设备的国标编号") + private String deviceId; + + /** + * 通道Id + */ + @Schema(description = "通道的国标编号") + private String channelId; + + /** + * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情 + */ + @Schema(description = "报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级警情") + private String alarmPriority; + + /** + * 报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警, + * 7其他报警;可以为直接组合如12为电话报警或 设备报警- + */ + @Schema(description = "报警方式 , 1为电话报警, 2为设备报警, 3为短信报警, 4为 GPS报警, 5为视频报警, 6为设备故障报警,\n" + + "\t * 7其他报警;可以为直接组合如12为电话报警或设备报警") + private String alarmMethod; + + /** + * 报警时间 + */ + @Schema(description = "报警时间") + private String alarmTime; + + /** + * 报警内容描述 + */ + @Schema(description = "报警内容描述") + private String alarmDescription; + + /** + * 经度 + */ + @Schema(description = "经度") + private double longitude; + + /** + * 纬度 + */ + @Schema(description = "纬度") + private double latitude; + + /** + * 报警类型, + * 报警方式为2时,不携带 AlarmType为默认的报警设备报警, + * 携带 AlarmType取值及对应报警类型如下: + * 1-视频丢失报警; + * 2-设备防拆报警; + * 3-存储设备磁盘满报警; + * 4-设备高温报警; + * 5-设备低温报警。 + * 报警方式为5时,取值如下: + * 1-人工视频报警; + * 2-运动目标检测报警; + * 3-遗留物检测报警; + * 4-物体移除检测报警; + * 5-绊线检测报警; + * 6-入侵检测报警; + * 7-逆行检测报警; + * 8-徘徊检测报警; + * 9-流量统计报警; + * 10-密度检测报警; + * 11-视频异常检测报警; + * 12-快速移动报警。 + * 报警方式为6时,取值下: + * 1-存储设备磁盘故障报警; + * 2-存储设备风扇故障报警。 + */ + @Schema(description = "报警类型") + private String alarmType; + + @Schema(description = "创建时间") + private String createTime; + + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getAlarmPriority() { + return alarmPriority; + } + + public void setAlarmPriority(String alarmPriority) { + this.alarmPriority = alarmPriority; + } + + public String getAlarmMethod() { + return alarmMethod; + } + + public void setAlarmMethod(String alarmMethod) { + this.alarmMethod = alarmMethod; + } + + public String getAlarmTime() { + return alarmTime; + } + + public void setAlarmTime(String alarmTime) { + this.alarmTime = alarmTime; + } + + public String getAlarmDescription() { + return alarmDescription; + } + + public void setAlarmDescription(String alarmDescription) { + this.alarmDescription = alarmDescription; + } + + public double getLongitude() { + return longitude; + } + + public void setLongitude(double longitude) { + this.longitude = longitude; + } + + public double getLatitude() { + return latitude; + } + + public void setLatitude(double latitude) { + this.latitude = latitude; + } + + public String getAlarmType() { + return alarmType; + } + + public void setAlarmType(String alarmType) { + this.alarmType = alarmType; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GBStringMsgParser.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStringMsgParserFactory.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HandlerCatchData.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HomePositionRequest.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/HomePositionRequest.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Host.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamCallback.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamCallback.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamType.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/MobilePosition.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/MobilePosition.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatform.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/ParentPlatformCatch.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformCatalog.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformGbStream.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PlatformRegister.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/PresetQuerySipReq.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java old mode 100644 new mode 100755 index 7ff528306..5b524cf67 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java @@ -1,102 +1,102 @@ -package com.genersoft.iot.vmp.gb28181.bean; - - -import io.swagger.v3.oas.annotations.media.Schema; - -import java.time.Instant; -import java.util.List; - -/** - * @description:设备录像信息bean - * @author: swwheihei - * @date: 2020年5月8日 下午2:05:56 - */ -@Schema(description = "设备录像查询结果信息") -public class RecordInfo { - - @Schema(description = "设备编号") - private String deviceId; - - @Schema(description = "通道编号") - private String channelId; - - @Schema(description = "命令序列号") - private String sn; - - @Schema(description = "设备名称") - private String name; - - @Schema(description = "列表总数") - private int sumNum; - - private int count; - - private Instant lastTime; - - @Schema(description = "") - private List recordList; - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public int getSumNum() { - return sumNum; - } - - public void setSumNum(int sumNum) { - this.sumNum = sumNum; - } - - public List getRecordList() { - return recordList; - } - - public void setRecordList(List recordList) { - this.recordList = recordList; - } - - public String getChannelId() { - return channelId; - } - - public void setChannelId(String channelId) { - this.channelId = channelId; - } - - public String getSn() { - return sn; - } - - public void setSn(String sn) { - this.sn = sn; - } - - public Instant getLastTime() { - return lastTime; - } - - public void setLastTime(Instant lastTime) { - this.lastTime = lastTime; - } - - public int getCount() { - return count; - } - - public void setCount(int count) { - this.count = count; - } -} +package com.genersoft.iot.vmp.gb28181.bean; + + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.Instant; +import java.util.List; + +/** + * @description:设备录像信息bean + * @author: swwheihei + * @date: 2020年5月8日 下午2:05:56 + */ +@Schema(description = "设备录像查询结果信息") +public class RecordInfo { + + @Schema(description = "设备编号") + private String deviceId; + + @Schema(description = "通道编号") + private String channelId; + + @Schema(description = "命令序列号") + private String sn; + + @Schema(description = "设备名称") + private String name; + + @Schema(description = "列表总数") + private int sumNum; + + private int count; + + private Instant lastTime; + + @Schema(description = "") + private List recordList; + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getSumNum() { + return sumNum; + } + + public void setSumNum(int sumNum) { + this.sumNum = sumNum; + } + + public List getRecordList() { + return recordList; + } + + public void setRecordList(List recordList) { + this.recordList = recordList; + } + + public String getChannelId() { + return channelId; + } + + public void setChannelId(String channelId) { + this.channelId = channelId; + } + + public String getSn() { + return sn; + } + + public void setSn(String sn) { + this.sn = sn; + } + + public Instant getLastTime() { + return lastTime; + } + + public void setLastTime(Instant lastTime) { + this.lastTime = lastTime; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java old mode 100644 new mode 100755 index 07e559c81..452e13886 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java @@ -1,144 +1,144 @@ -package com.genersoft.iot.vmp.gb28181.bean; - - -import com.genersoft.iot.vmp.utils.DateUtil; -import io.swagger.v3.oas.annotations.media.Schema; -import org.jetbrains.annotations.NotNull; - -import java.time.Instant; -import java.time.temporal.TemporalAccessor; - -/** - * @description:设备录像bean - * @author: swwheihei - * @date: 2020年5月8日 下午2:06:54 - */ -@Schema(description = "设备录像详情") -public class RecordItem implements Comparable{ - - @Schema(description = "设备编号") - private String deviceId; - - @Schema(description = "名称") - private String name; - - @Schema(description = "文件路径名 (可选)") - private String filePath; - - @Schema(description = "录像文件大小,单位:Byte(可选)") - private String fileSize; - - @Schema(description = "录像地址(可选)") - private String address; - - @Schema(description = "录像开始时间(可选)") - private String startTime; - - @Schema(description = "录像结束时间(可选)") - private String endTime; - - @Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密") - private int secrecy; - - @Schema(description = "录像产生类型(可选)time或alarm 或 manua") - private String type; - - @Schema(description = "录像触发者ID(可选)") - private String recorderId; - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getFilePath() { - return filePath; - } - - public void setFilePath(String filePath) { - this.filePath = filePath; - } - - public String getAddress() { - return address; - } - - public void setAddress(String address) { - this.address = address; - } - - public String getStartTime() { - return startTime; - } - - public void setStartTime(String startTime) { - this.startTime = startTime; - } - - public String getEndTime() { - return endTime; - } - - public void setEndTime(String endTime) { - this.endTime = endTime; - } - - public int getSecrecy() { - return secrecy; - } - - public void setSecrecy(int secrecy) { - this.secrecy = secrecy; - } - - public String getType() { - return type; - } - - public void setType(String type) { - this.type = type; - } - - public String getRecorderId() { - return recorderId; - } - - public void setRecorderId(String recorderId) { - this.recorderId = recorderId; - } - - public String getFileSize() { - return fileSize; - } - - public void setFileSize(String fileSize) { - this.fileSize = fileSize; - } - - @Override - public int compareTo(@NotNull RecordItem recordItem) { - TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime); - TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime()); - Instant startTimeParamInstant = Instant.from(startTimeParam); - Instant startTimeNowInstant = Instant.from(startTimeNow); - if (startTimeNowInstant.equals(startTimeParamInstant)) { - return 0; - }else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) { - return -1; - }else { - return 1; - } - - } -} +package com.genersoft.iot.vmp.gb28181.bean; + + +import com.genersoft.iot.vmp.utils.DateUtil; +import io.swagger.v3.oas.annotations.media.Schema; +import org.jetbrains.annotations.NotNull; + +import java.time.Instant; +import java.time.temporal.TemporalAccessor; + +/** + * @description:设备录像bean + * @author: swwheihei + * @date: 2020年5月8日 下午2:06:54 + */ +@Schema(description = "设备录像详情") +public class RecordItem implements Comparable{ + + @Schema(description = "设备编号") + private String deviceId; + + @Schema(description = "名称") + private String name; + + @Schema(description = "文件路径名 (可选)") + private String filePath; + + @Schema(description = "录像文件大小,单位:Byte(可选)") + private String fileSize; + + @Schema(description = "录像地址(可选)") + private String address; + + @Schema(description = "录像开始时间(可选)") + private String startTime; + + @Schema(description = "录像结束时间(可选)") + private String endTime; + + @Schema(description = "保密属性(必选)缺省为0;0:不涉密,1:涉密") + private int secrecy; + + @Schema(description = "录像产生类型(可选)time或alarm 或 manua") + private String type; + + @Schema(description = "录像触发者ID(可选)") + private String recorderId; + + public String getDeviceId() { + return deviceId; + } + + public void setDeviceId(String deviceId) { + this.deviceId = deviceId; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public String getStartTime() { + return startTime; + } + + public void setStartTime(String startTime) { + this.startTime = startTime; + } + + public String getEndTime() { + return endTime; + } + + public void setEndTime(String endTime) { + this.endTime = endTime; + } + + public int getSecrecy() { + return secrecy; + } + + public void setSecrecy(int secrecy) { + this.secrecy = secrecy; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getRecorderId() { + return recorderId; + } + + public void setRecorderId(String recorderId) { + this.recorderId = recorderId; + } + + public String getFileSize() { + return fileSize; + } + + public void setFileSize(String fileSize) { + this.fileSize = fileSize; + } + + @Override + public int compareTo(@NotNull RecordItem recordItem) { + TemporalAccessor startTimeNow = DateUtil.formatter.parse(startTime); + TemporalAccessor startTimeParam = DateUtil.formatter.parse(recordItem.getStartTime()); + Instant startTimeParamInstant = Instant.from(startTimeParam); + Instant startTimeNowInstant = Instant.from(startTimeNow); + if (startTimeNowInstant.equals(startTimeParamInstant)) { + return 0; + }else if (Instant.from(startTimeParam).isAfter(Instant.from(startTimeNow)) ) { + return -1; + }else { + return 1; + } + + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RemoteAddressInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SDPInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SDPInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipTransactionInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java old mode 100644 new mode 100755 index ba905b50b..d385d9af2 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java @@ -2,12 +2,9 @@ package com.genersoft.iot.vmp.gb28181.bean; import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeHandlerTask; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.service.IPlatformService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -24,6 +21,9 @@ public class SubscribeHolder { @Autowired private DynamicTask dynamicTask; + @Autowired + private UserSetting userSetting; + private final String taskOverduePrefix = "subscribe_overdue_"; private static ConcurrentHashMap catalogMap = new ConcurrentHashMap<>(); @@ -58,7 +58,7 @@ public class SubscribeHolder { public void putMobilePositionSubscribe(String platformId, SubscribeInfo subscribeInfo) { mobilePositionMap.put(platformId, subscribeInfo); - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId; + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId; // 添加任务处理GPS定时推送 dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(platformId), subscribeInfo.getGpsInterval() * 1000); @@ -76,7 +76,7 @@ public class SubscribeHolder { public void removeMobilePositionSubscribe(String platformId) { mobilePositionMap.remove(platformId); - String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + "MobilePosition_" + platformId; + String key = VideoManagerConstants.SIP_SUBSCRIBE_PREFIX + userSetting.getServerId() + "MobilePosition_" + platformId; // 结束任务处理GPS定时推送 dynamicTask.stop(key); String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SyncStatus.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/ServerLoggerImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/StackLoggerImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/StackLoggerImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java old mode 100644 new mode 100755 index 26ababd4c..d56e744da --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -1,118 +1,118 @@ -package com.genersoft.iot.vmp.gb28181.event; - -import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; -import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; -import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationEventPublisher; -import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; - -import javax.sip.TimeoutEvent; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -/** - * @description:Event事件通知推送器,支持推送在线事件、离线事件 - * @author: swwheihei - * @date: 2020年5月6日 上午11:30:50 - */ -@Component -public class EventPublisher { - - @Autowired - private ApplicationEventPublisher applicationEventPublisher; - - /** - * 设备报警事件 - * @param deviceAlarm - */ - public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) { - AlarmEvent alarmEvent = new AlarmEvent(this); - alarmEvent.setAlarmInfo(deviceAlarm); - applicationEventPublisher.publishEvent(alarmEvent); - } - - public void zlmOfflineEventPublish(String mediaServerId){ - ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this); - outEvent.setMediaServerId(mediaServerId); - applicationEventPublisher.publishEvent(outEvent); - } - - public void zlmOnlineEventPublish(String mediaServerId) { - ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this); - outEvent.setMediaServerId(mediaServerId); - applicationEventPublisher.publishEvent(outEvent); - } - - - public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) { - List deviceChannelList = new ArrayList<>(); - deviceChannelList.add(deviceChannel); - catalogEventPublish(platformId, deviceChannelList, type); - } - - - public void requestTimeOut(TimeoutEvent timeoutEvent) { - RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this); - requestTimeoutEvent.setTimeoutEvent(timeoutEvent); - applicationEventPublisher.publishEvent(requestTimeoutEvent); - } - - - /** - * - * @param platformId - * @param deviceChannels - * @param type - */ - public void catalogEventPublish(String platformId, List deviceChannels, String type) { - CatalogEvent outEvent = new CatalogEvent(this); - List channels = new ArrayList<>(); - if (deviceChannels.size() > 1) { - // 数据去重 - Set gbIdSet = new HashSet<>(); - for (DeviceChannel deviceChannel : deviceChannels) { - if (!gbIdSet.contains(deviceChannel.getChannelId())) { - gbIdSet.add(deviceChannel.getChannelId()); - channels.add(deviceChannel); - } - } - }else { - channels = deviceChannels; - } - outEvent.setDeviceChannels(channels); - outEvent.setType(type); - outEvent.setPlatformId(platformId); - applicationEventPublisher.publishEvent(outEvent); - } - - - public void catalogEventPublishForStream(String platformId, List gbStreams, String type) { - CatalogEvent outEvent = new CatalogEvent(this); - outEvent.setGbStreams(gbStreams); - outEvent.setType(type); - outEvent.setPlatformId(platformId); - applicationEventPublisher.publishEvent(outEvent); - } - - - public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) { - List gbStreamList = new ArrayList<>(); - gbStreamList.add(gbStream); - catalogEventPublishForStream(platformId, gbStreamList, type); - } - - public void recordEndEventPush(RecordInfo recordInfo) { - RecordEndEvent outEvent = new RecordEndEvent(this); - outEvent.setRecordInfo(recordInfo); - applicationEventPublisher.publishEvent(outEvent); - } - -} +package com.genersoft.iot.vmp.gb28181.event; + +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; +import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; +import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; +import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.stereotype.Component; + +import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; + +import javax.sip.TimeoutEvent; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * @description:Event事件通知推送器,支持推送在线事件、离线事件 + * @author: swwheihei + * @date: 2020年5月6日 上午11:30:50 + */ +@Component +public class EventPublisher { + + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + + /** + * 设备报警事件 + * @param deviceAlarm + */ + public void deviceAlarmEventPublish(DeviceAlarm deviceAlarm) { + AlarmEvent alarmEvent = new AlarmEvent(this); + alarmEvent.setAlarmInfo(deviceAlarm); + applicationEventPublisher.publishEvent(alarmEvent); + } + + public void zlmOfflineEventPublish(String mediaServerId){ + ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this); + outEvent.setMediaServerId(mediaServerId); + applicationEventPublisher.publishEvent(outEvent); + } + + public void zlmOnlineEventPublish(String mediaServerId) { + ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this); + outEvent.setMediaServerId(mediaServerId); + applicationEventPublisher.publishEvent(outEvent); + } + + + public void catalogEventPublish(String platformId, DeviceChannel deviceChannel, String type) { + List deviceChannelList = new ArrayList<>(); + deviceChannelList.add(deviceChannel); + catalogEventPublish(platformId, deviceChannelList, type); + } + + + public void requestTimeOut(TimeoutEvent timeoutEvent) { + RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this); + requestTimeoutEvent.setTimeoutEvent(timeoutEvent); + applicationEventPublisher.publishEvent(requestTimeoutEvent); + } + + + /** + * + * @param platformId + * @param deviceChannels + * @param type + */ + public void catalogEventPublish(String platformId, List deviceChannels, String type) { + CatalogEvent outEvent = new CatalogEvent(this); + List channels = new ArrayList<>(); + if (deviceChannels.size() > 1) { + // 数据去重 + Set gbIdSet = new HashSet<>(); + for (DeviceChannel deviceChannel : deviceChannels) { + if (!gbIdSet.contains(deviceChannel.getChannelId())) { + gbIdSet.add(deviceChannel.getChannelId()); + channels.add(deviceChannel); + } + } + }else { + channels = deviceChannels; + } + outEvent.setDeviceChannels(channels); + outEvent.setType(type); + outEvent.setPlatformId(platformId); + applicationEventPublisher.publishEvent(outEvent); + } + + + public void catalogEventPublishForStream(String platformId, List gbStreams, String type) { + CatalogEvent outEvent = new CatalogEvent(this); + outEvent.setGbStreams(gbStreams); + outEvent.setType(type); + outEvent.setPlatformId(platformId); + applicationEventPublisher.publishEvent(outEvent); + } + + + public void catalogEventPublishForStream(String platformId, GbStream gbStream, String type) { + List gbStreamList = new ArrayList<>(); + gbStreamList.add(gbStream); + catalogEventPublishForStream(platformId, gbStreamList, type); + } + + public void recordEndEventPush(RecordInfo recordInfo) { + RecordEndEvent outEvent = new RecordEndEvent(this); + outEvent.setRecordInfo(recordInfo); + applicationEventPublisher.publishEvent(outEvent); + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/alarm/AlarmEventListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/record/RecordEndEventListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/SSRCFactory.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java old mode 100644 new mode 100755 index a5da0186b..c46e38a99 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -1,139 +1,139 @@ -package com.genersoft.iot.vmp.gb28181.session; - -import com.genersoft.iot.vmp.common.InviteSessionType; -import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; -import com.genersoft.iot.vmp.utils.JsonUtil; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; -import gov.nist.javax.sip.message.SIPResponse; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; - -import java.util.ArrayList; -import java.util.List; - -/** - * 视频流session管理器,管理视频预览、预览回放的通信句柄 - */ -@Component -public class VideoStreamSessionManager { - - @Autowired - private UserSetting userSetting; - - @Autowired - private RedisTemplate redisTemplate; - - /** - * 添加一个点播/回放的事务信息 - * 后续可以通过流Id/callID - * @param deviceId 设备ID - * @param channelId 通道ID - * @param callId 一次请求的CallID - * @param stream 流名称 - * @param mediaServerId 所使用的流媒体ID - * @param response 回复 - */ - public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){ - SsrcTransaction ssrcTransaction = new SsrcTransaction(); - ssrcTransaction.setDeviceId(deviceId); - ssrcTransaction.setChannelId(channelId); - ssrcTransaction.setStream(stream); - ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response)); - ssrcTransaction.setCallId(callId); - ssrcTransaction.setSsrc(ssrc); - ssrcTransaction.setMediaServerId(mediaServerId); - ssrcTransaction.setType(type); - - redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() - + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); - } - - public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ - - if (ObjectUtils.isEmpty(deviceId)) { - deviceId ="*"; - } - if (ObjectUtils.isEmpty(channelId)) { - channelId ="*"; - } - if (ObjectUtils.isEmpty(callId)) { - callId ="*"; - } - if (ObjectUtils.isEmpty(stream)) { - stream ="*"; - } - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; - List scanResult = RedisUtil.scan(redisTemplate, key); - if (scanResult.size() == 0) { - return null; - } - return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0)); - } - - public List getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){ - if (ObjectUtils.isEmpty(deviceId)) { - deviceId ="*"; - } - if (ObjectUtils.isEmpty(channelId)) { - channelId ="*"; - } - if (ObjectUtils.isEmpty(callId)) { - callId ="*"; - } - if (ObjectUtils.isEmpty(stream)) { - stream ="*"; - } - String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; - List scanResult = RedisUtil.scan(redisTemplate, key); - if (scanResult.size() == 0) { - return null; - } - List result = new ArrayList<>(); - for (Object keyObj : scanResult) { - result.add((SsrcTransaction)redisTemplate.opsForValue().get(keyObj)); - } - return result; - } - - public String getMediaServerId(String deviceId, String channelId, String stream){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); - if (ssrcTransaction == null) { - return null; - } - return ssrcTransaction.getMediaServerId(); - } - - public String getSSRC(String deviceId, String channelId, String stream){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); - if (ssrcTransaction == null) { - return null; - } - return ssrcTransaction.getSsrc(); - } - - public void remove(String deviceId, String channelId, String stream) { - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); - if (ssrcTransaction == null) { - return; - } - redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" - + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream()); - } - - - public List getAllSsrc() { - List ssrcTransactionKeys = RedisUtil.scan(redisTemplate, String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId())); - List result= new ArrayList<>(); - for (Object ssrcTransactionKey : ssrcTransactionKeys) { - String key = (String) ssrcTransactionKey; - SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(redisTemplate, key, SsrcTransaction.class); - result.add(ssrcTransaction); - } - return result; - } -} +package com.genersoft.iot.vmp.gb28181.session; + +import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; +import com.genersoft.iot.vmp.utils.JsonUtil; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import gov.nist.javax.sip.message.SIPResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 视频流session管理器,管理视频预览、预览回放的通信句柄 + */ +@Component +public class VideoStreamSessionManager { + + @Autowired + private UserSetting userSetting; + + @Autowired + private RedisTemplate redisTemplate; + + /** + * 添加一个点播/回放的事务信息 + * 后续可以通过流Id/callID + * @param deviceId 设备ID + * @param channelId 通道ID + * @param callId 一次请求的CallID + * @param stream 流名称 + * @param mediaServerId 所使用的流媒体ID + * @param response 回复 + */ + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, SIPResponse response, InviteSessionType type){ + SsrcTransaction ssrcTransaction = new SsrcTransaction(); + ssrcTransaction.setDeviceId(deviceId); + ssrcTransaction.setChannelId(channelId); + ssrcTransaction.setStream(stream); + ssrcTransaction.setSipTransactionInfo(new SipTransactionInfo(response)); + ssrcTransaction.setCallId(callId); + ssrcTransaction.setSsrc(ssrc); + ssrcTransaction.setMediaServerId(mediaServerId); + ssrcTransaction.setType(type); + + redisTemplate.opsForValue().set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction); + } + + public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){ + + if (ObjectUtils.isEmpty(deviceId)) { + deviceId ="*"; + } + if (ObjectUtils.isEmpty(channelId)) { + channelId ="*"; + } + if (ObjectUtils.isEmpty(callId)) { + callId ="*"; + } + if (ObjectUtils.isEmpty(stream)) { + stream ="*"; + } + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; + List scanResult = RedisUtil.scan(redisTemplate, key); + if (scanResult.size() == 0) { + return null; + } + return (SsrcTransaction)redisTemplate.opsForValue().get(scanResult.get(0)); + } + + public List getSsrcTransactionForAll(String deviceId, String channelId, String callId, String stream){ + if (ObjectUtils.isEmpty(deviceId)) { + deviceId ="*"; + } + if (ObjectUtils.isEmpty(channelId)) { + channelId ="*"; + } + if (ObjectUtils.isEmpty(callId)) { + callId ="*"; + } + if (ObjectUtils.isEmpty(stream)) { + stream ="*"; + } + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream; + List scanResult = RedisUtil.scan(redisTemplate, key); + if (scanResult.size() == 0) { + return null; + } + List result = new ArrayList<>(); + for (Object keyObj : scanResult) { + result.add((SsrcTransaction)redisTemplate.opsForValue().get(keyObj)); + } + return result; + } + + public String getMediaServerId(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); + if (ssrcTransaction == null) { + return null; + } + return ssrcTransaction.getMediaServerId(); + } + + public String getSSRC(String deviceId, String channelId, String stream){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); + if (ssrcTransaction == null) { + return null; + } + return ssrcTransaction.getSsrc(); + } + + public void remove(String deviceId, String channelId, String stream) { + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); + if (ssrcTransaction == null) { + return; + } + redisTemplate.delete(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetting.getServerId() + "_" + + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream()); + } + + + public List getAllSsrc() { + List ssrcTransactionKeys = RedisUtil.scan(redisTemplate, String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetting.getServerId())); + List result= new ArrayList<>(); + for (Object ssrcTransactionKey : ssrcTransactionKeys) { + String key = (String) ssrcTransactionKey; + SsrcTransaction ssrcTransaction = JsonUtil.redisJsonToObject(redisTemplate, key, SsrcTransaction.class); + result.add(ssrcTransaction); + } + return result; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/ISubscribeTask.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java old mode 100644 new mode 100755 index 4b9244368..199979e97 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java @@ -12,13 +12,19 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlatformService; +import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -59,6 +65,8 @@ public class SipRunner implements CommandLineRunner { @Autowired private ISIPCommanderForPlatform commanderForPlatform; + private final static Logger logger = LoggerFactory.getLogger(PlatformServiceImpl.class); + @Override public void run(String... args) throws Exception { List deviceList = deviceService.getAllOnlineDevice(); @@ -110,7 +118,11 @@ public class SipRunner implements CommandLineRunner { if (jsonObject != null && jsonObject.getInteger("code") == 0) { ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); if (platform != null) { - commanderForPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); + try { + commanderForPlatform.streamByeCmd(platform, sendRtpItem.getCallId()); + } catch (InvalidArgumentException | ParseException | SipException e) { + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage()); + } } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/CatalogSubscribeTask.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeHandlerTask.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/impl/MobilePositionSubscribeTask.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java old mode 100644 new mode 100755 index 8a6218281..8d0ed7fb4 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java @@ -1,160 +1,160 @@ -package com.genersoft.iot.vmp.gb28181.transmit.callback; - -import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; -import org.springframework.stereotype.Component; -import org.springframework.util.ObjectUtils; -import org.springframework.web.context.request.async.DeferredResult; - -import java.util.Collection; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -/** - * @description: 异步请求处理 - * @author: swwheihei - * @date: 2020年5月8日 下午7:59:05 - */ -@SuppressWarnings(value = {"rawtypes", "unchecked"}) -@Component -public class DeferredResultHolder { - - public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS"; - - public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO"; - - public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL"; - - public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG"; - - public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD"; - - public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG"; - - public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO"; - - public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY"; - - public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK"; - - public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD"; - - public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY"; - - public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP"; - - public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL"; - - public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION"; - - public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; - - public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM"; - - public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST"; - - public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP"; - - private Map> map = new ConcurrentHashMap<>(); - - - public void put(String key, String id, DeferredResultEx result) { - Map deferredResultMap = map.get(key); - if (deferredResultMap == null) { - deferredResultMap = new ConcurrentHashMap<>(); - map.put(key, deferredResultMap); - } - deferredResultMap.put(id, result); - } - - public void put(String key, String id, DeferredResult result) { - Map deferredResultMap = map.get(key); - if (deferredResultMap == null) { - deferredResultMap = new ConcurrentHashMap<>(); - map.put(key, deferredResultMap); - } - deferredResultMap.put(id, new DeferredResultEx(result)); - } - - public DeferredResultEx get(String key, String id) { - Map deferredResultMap = map.get(key); - if (deferredResultMap == null || ObjectUtils.isEmpty(id)) { - return null; - } - return deferredResultMap.get(id); - } - - public Collection getAllByKey(String key) { - Map deferredResultMap = map.get(key); - if (deferredResultMap == null) { - return null; - } - return deferredResultMap.values(); - } - - public boolean exist(String key, String id){ - if (key == null) { - return false; - } - Map deferredResultMap = map.get(key); - if (id == null) { - return deferredResultMap != null; - }else { - return deferredResultMap != null && deferredResultMap.get(id) != null; - } - } - - /** - * 释放单个请求 - * @param msg - */ - public void invokeResult(RequestMessage msg) { - Map deferredResultMap = map.get(msg.getKey()); - if (deferredResultMap == null) { - return; - } - DeferredResultEx result = deferredResultMap.get(msg.getId()); - if (result == null) { - return; - } - result.getDeferredResult().setResult(msg.getData()); - deferredResultMap.remove(msg.getId()); - if (deferredResultMap.size() == 0) { - map.remove(msg.getKey()); - } - } - - /** - * 释放所有的请求 - * @param msg - */ - public void invokeAllResult(RequestMessage msg) { - Map deferredResultMap = map.get(msg.getKey()); - if (deferredResultMap == null) { - return; - } - synchronized (this) { - deferredResultMap = map.get(msg.getKey()); - if (deferredResultMap == null) { - return; - } - Set ids = deferredResultMap.keySet(); - for (String id : ids) { - DeferredResultEx result = deferredResultMap.get(id); - if (result == null) { - return; - } - if (result.getFilter() != null) { - Object handler = result.getFilter().handler(msg.getData()); - result.getDeferredResult().setResult(handler); - }else { - result.getDeferredResult().setResult(msg.getData()); - } - - } - map.remove(msg.getKey()); - } - } - - -} +package com.genersoft.iot.vmp.gb28181.transmit.callback; + +import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; +import org.springframework.web.context.request.async.DeferredResult; + +import java.util.Collection; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @description: 异步请求处理 + * @author: swwheihei + * @date: 2020年5月8日 下午7:59:05 + */ +@SuppressWarnings(value = {"rawtypes", "unchecked"}) +@Component +public class DeferredResultHolder { + + public static final String CALLBACK_CMD_DEVICESTATUS = "CALLBACK_DEVICESTATUS"; + + public static final String CALLBACK_CMD_DEVICEINFO = "CALLBACK_DEVICEINFO"; + + public static final String CALLBACK_CMD_DEVICECONTROL = "CALLBACK_DEVICECONTROL"; + + public static final String CALLBACK_CMD_DEVICECONFIG = "CALLBACK_DEVICECONFIG"; + + public static final String CALLBACK_CMD_CONFIGDOWNLOAD = "CALLBACK_CONFIGDOWNLOAD"; + + public static final String CALLBACK_CMD_CATALOG = "CALLBACK_CATALOG"; + + public static final String CALLBACK_CMD_RECORDINFO = "CALLBACK_RECORDINFO"; + + public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY"; + + public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAYBACK"; + + public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD"; + + public static final String CALLBACK_CMD_PROXY = "CALLBACK_PROXY"; + + public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP"; + + public static final String UPLOAD_FILE_CHANNEL = "UPLOAD_FILE_CHANNEL"; + + public static final String CALLBACK_CMD_MOBILE_POSITION = "CALLBACK_CMD_MOBILE_POSITION"; + + public static final String CALLBACK_CMD_PRESETQUERY = "CALLBACK_PRESETQUERY"; + + public static final String CALLBACK_CMD_ALARM = "CALLBACK_ALARM"; + + public static final String CALLBACK_CMD_BROADCAST = "CALLBACK_BROADCAST"; + + public static final String CALLBACK_CMD_SNAP= "CALLBACK_SNAP"; + + private Map> map = new ConcurrentHashMap<>(); + + + public void put(String key, String id, DeferredResultEx result) { + Map deferredResultMap = map.get(key); + if (deferredResultMap == null) { + deferredResultMap = new ConcurrentHashMap<>(); + map.put(key, deferredResultMap); + } + deferredResultMap.put(id, result); + } + + public void put(String key, String id, DeferredResult result) { + Map deferredResultMap = map.get(key); + if (deferredResultMap == null) { + deferredResultMap = new ConcurrentHashMap<>(); + map.put(key, deferredResultMap); + } + deferredResultMap.put(id, new DeferredResultEx(result)); + } + + public DeferredResultEx get(String key, String id) { + Map deferredResultMap = map.get(key); + if (deferredResultMap == null || ObjectUtils.isEmpty(id)) { + return null; + } + return deferredResultMap.get(id); + } + + public Collection getAllByKey(String key) { + Map deferredResultMap = map.get(key); + if (deferredResultMap == null) { + return null; + } + return deferredResultMap.values(); + } + + public boolean exist(String key, String id){ + if (key == null) { + return false; + } + Map deferredResultMap = map.get(key); + if (id == null) { + return deferredResultMap != null; + }else { + return deferredResultMap != null && deferredResultMap.get(id) != null; + } + } + + /** + * 释放单个请求 + * @param msg + */ + public void invokeResult(RequestMessage msg) { + Map deferredResultMap = map.get(msg.getKey()); + if (deferredResultMap == null) { + return; + } + DeferredResultEx result = deferredResultMap.get(msg.getId()); + if (result == null) { + return; + } + result.getDeferredResult().setResult(msg.getData()); + deferredResultMap.remove(msg.getId()); + if (deferredResultMap.size() == 0) { + map.remove(msg.getKey()); + } + } + + /** + * 释放所有的请求 + * @param msg + */ + public void invokeAllResult(RequestMessage msg) { + Map deferredResultMap = map.get(msg.getKey()); + if (deferredResultMap == null) { + return; + } + synchronized (this) { + deferredResultMap = map.get(msg.getKey()); + if (deferredResultMap == null) { + return; + } + Set ids = deferredResultMap.keySet(); + for (String id : ids) { + DeferredResultEx result = deferredResultMap.get(id); + if (result == null) { + return; + } + if (result.getFilter() != null) { + Object handler = result.getFilter().handler(msg.getData()); + result.getDeferredResult().setResult(handler); + }else { + result.getDeferredResult().setResult(msg.getData()); + } + + } + map.remove(msg.getKey()); + } + } + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java old mode 100644 new mode 100755 index 42ae577ad..f4e2d2013 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/RequestMessage.java @@ -1,39 +1,39 @@ -package com.genersoft.iot.vmp.gb28181.transmit.callback; - -/** - * @description: 请求信息定义 - * @author: swwheihei - * @date: 2020年5月8日 下午1:09:18 - */ -public class RequestMessage { - - private String id; - - private String key; - - private Object data; - - public String getId() { - return id; - } - - public void setId(String id) { - this.id = id; - } - - public void setKey(String key) { - this.key = key; - } - - public String getKey() { - return key; - } - - public Object getData() { - return data; - } - - public void setData(Object data) { - this.data = data; - } -} +package com.genersoft.iot.vmp.gb28181.transmit.callback; + +/** + * @description: 请求信息定义 + * @author: swwheihei + * @date: 2020年5月8日 下午1:09:18 + */ +public class RequestMessage { + + private String id; + + private String key; + + private Object data; + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public void setKey(String key) { + this.key = key; + } + + public String getKey() { + return key; + } + + public Object getData() { + return data; + } + + public void setData(Object data) { + this.data = data; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java old mode 100644 new mode 100755 index 80ea8909a..9c683369e --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -1,364 +1,364 @@ -package com.genersoft.iot.vmp.gb28181.transmit.cmd; - -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; -import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import gov.nist.javax.sip.message.SIPRequest; - -import javax.sip.InvalidArgumentException; -import javax.sip.SipException; -import java.text.ParseException; - -/** - * @description:设备能力接口,用于定义设备的控制、查询能力 - * @author: swwheihei - * @date: 2020年5月3日 下午9:16:34 - */ -public interface ISIPCommander { - - /** - * 云台方向放控制,使用配置文件中的默认镜头移动速度 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - */ - void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException; - - /** - * 云台方向放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param moveSpeed 镜头移动速度 - */ - void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; - - /** - * 云台缩放控制,使用配置文件中的默认镜头缩放速度 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - */ - void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException; - - /** - * 云台缩放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - */ - void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; - - /** - * 云台控制,支持方向与缩放控制 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 - * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 - * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 - * @param moveSpeed 镜头移动速度 - * @param zoomSpeed 镜头缩放速度 - */ - void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException; - - /** - * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 - * - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdCode 指令码 - * @param parameter1 数据1 - * @param parameter2 数据2 - * @param combineCode2 组合码2 - */ - void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException; - - /** - * 前端控制指令(用于转发上级指令) - * @param device 控制设备 - * @param channelId 预览通道 - * @param cmdString 前端控制指令串 - */ - void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 请求预览视频流 - * @param device 视频设备 - * @param channelId 预览通道 - */ - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 请求回放视频流 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - */ - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 请求历史媒体下载 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param downloadSpeed 下载倍速参数 - */ - void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, - String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent, - SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - - /** - * 视频流停止 - */ - void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; - - void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - - void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; - - void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; - - /** - * 回放暂停 - */ - void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException; - - /** - * 回放恢复 - */ - void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException; - - /** - * 回放拖动播放 - */ - void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException; - - /** - * 回放倍速播放 - */ - void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException; - - /** - * 回放控制 - * @param device - * @param streamInfo - * @param content - */ - void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException; - - - /** - * /** - * 语音广播 - * - * @param device 视频设备 - */ - void audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 音视频录像控制 - * - * @param device 视频设备 - * @param channelId 预览通道 - * @param recordCmdStr 录像命令:Record / StopRecord - */ - void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 远程启动控制命令 - * - * @param device 视频设备 - */ - void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException; - - /** - * 报警布防/撤防命令 - * - * @param device 视频设备 - */ - void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 报警复位命令 - * - * @param device 视频设备 - * @param alarmMethod 报警方式(可选) - * @param alarmType 报警类型(可选) - */ - void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 - * - * @param device 视频设备 - * @param channelId 预览通道 - */ - void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException; - - /** - * 看守位控制命令 - * - * @param device 视频设备 - * @param channelId 通道id,非通道则是设备本身 - * @param enabled 看守位使能:1 = 开启,0 = 关闭 - * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) - * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 - */ - void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 设备配置命令 - * - * @param device 视频设备 - */ - void deviceConfigCmd(Device device); - - /** - * 设备配置命令:basicParam - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param name 设备/通道名称(可选) - * @param expiration 注册过期时间(可选) - * @param heartBeatInterval 心跳间隔时间(可选) - * @param heartBeatCount 心跳超时次数(可选) - */ - void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询设备状态 - * - * @param device 视频设备 - */ - void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询设备信息 - * - * @param device 视频设备 - * @return - */ - void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询目录列表 - * - * @param device 视频设备 - */ - void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException; - - /** - * 查询录像信息 - * - * @param device 视频设备 - * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss - * @param sn - */ - void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询报警信息 - * - * @param device 视频设备 - * @param startPriority 报警起始级别(可选) - * @param endPriority 报警终止级别(可选) - * @param alarmMethod 报警方式条件(可选) - * @param alarmType 报警类型 - * @param startTime 报警发生起始时间(可选) - * @param endTime 报警发生终止时间(可选) - * @return true = 命令发送成功 - */ - void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, - String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询设备配置 - * - * @param device 视频设备 - * @param channelId 通道编码(可选) - * @param configType 配置类型: - */ - void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询设备预置位置 - * - * @param device 视频设备 - */ - void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 查询移动设备位置数据 - * - * @param device 视频设备 - */ - void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 订阅、取消订阅移动位置 - * - * @param device 视频设备 - * @return true = 命令发送成功 - */ - SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 订阅、取消订阅报警信息 - * @param device 视频设备 - * @param expires 订阅过期时间(0 = 取消订阅) - * @param startPriority 报警起始级别(可选) - * @param endPriority 报警终止级别(可选) - * @param alarmType 报警类型 - * @param startTime 报警发生起始时间(可选) - * @param endTime 报警发生终止时间(可选) - * @return true = 命令发送成功 - */ - void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException; - - /** - * 订阅、取消订阅目录信息 - * @param device 视频设备 - * @return true = 命令发送成功 - */ - SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; - - /** - * 拉框控制命令 - * - * @param device 控制设备 - * @param channelId 通道id - * @param cmdString 前端控制指令串 - */ - void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException; - - - /** - * 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待 - * @param device 设备 - * @param deviceAlarm 报警信息信息 - * @return - */ - void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException; - - -} +package com.genersoft.iot.vmp.gb28181.transmit.cmd; + +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import gov.nist.javax.sip.message.SIPRequest; + +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; + +/** + * @description:设备能力接口,用于定义设备的控制、查询能力 + * @author: swwheihei + * @date: 2020年5月3日 下午9:16:34 + */ +public interface ISIPCommander { + + /** + * 云台方向放控制,使用配置文件中的默认镜头移动速度 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + */ + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException; + + /** + * 云台方向放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + * @param moveSpeed 镜头移动速度 + */ + void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; + + /** + * 云台缩放控制,使用配置文件中的默认镜头缩放速度 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + */ + void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException; + + /** + * 云台缩放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + */ + void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; + + /** + * 云台控制,支持方向与缩放控制 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 + * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 + * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 + * @param moveSpeed 镜头移动速度 + * @param zoomSpeed 镜头缩放速度 + */ + void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException; + + /** + * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 + * + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdCode 指令码 + * @param parameter1 数据1 + * @param parameter2 数据2 + * @param combineCode2 组合码2 + */ + void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException; + + /** + * 前端控制指令(用于转发上级指令) + * @param device 控制设备 + * @param channelId 预览通道 + * @param cmdString 前端控制指令串 + */ + void fronEndCmd(Device device, String channelId, String cmdString, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 请求预览视频流 + * @param device 视频设备 + * @param channelId 预览通道 + */ + void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 请求回放视频流 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + */ + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 请求历史媒体下载 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param downloadSpeed 下载倍速参数 + */ + void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent, + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + + /** + * 视频流停止 + */ + void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; + + void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + + void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; + + void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; + + /** + * 回放暂停 + */ + void playPauseCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException; + + /** + * 回放恢复 + */ + void playResumeCmd(Device device, StreamInfo streamInfo) throws InvalidArgumentException, ParseException, SipException; + + /** + * 回放拖动播放 + */ + void playSeekCmd(Device device, StreamInfo streamInfo, long seekTime) throws InvalidArgumentException, ParseException, SipException; + + /** + * 回放倍速播放 + */ + void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException; + + /** + * 回放控制 + * @param device + * @param streamInfo + * @param content + */ + void playbackControlCmd(Device device, StreamInfo streamInfo, String content,SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws SipException, InvalidArgumentException, ParseException; + + + /** + * /** + * 语音广播 + * + * @param device 视频设备 + */ + void audioBroadcastCmd(Device device, String channelId, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 音视频录像控制 + * + * @param device 视频设备 + * @param channelId 预览通道 + * @param recordCmdStr 录像命令:Record / StopRecord + */ + void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 远程启动控制命令 + * + * @param device 视频设备 + */ + void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException; + + /** + * 报警布防/撤防命令 + * + * @param device 视频设备 + */ + void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 报警复位命令 + * + * @param device 视频设备 + * @param alarmMethod 报警方式(可选) + * @param alarmType 报警类型(可选) + */ + void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 + * + * @param device 视频设备 + * @param channelId 预览通道 + */ + void iFrameCmd(Device device, String channelId) throws InvalidArgumentException, SipException, ParseException; + + /** + * 看守位控制命令 + * + * @param device 视频设备 + * @param channelId 通道id,非通道则是设备本身 + * @param enabled 看守位使能:1 = 开启,0 = 关闭 + * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) + * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 + */ + void homePositionCmd(Device device, String channelId, String enabled, String resetTime, String presetIndex, SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 设备配置命令 + * + * @param device 视频设备 + */ + void deviceConfigCmd(Device device); + + /** + * 设备配置命令:basicParam + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param name 设备/通道名称(可选) + * @param expiration 注册过期时间(可选) + * @param heartBeatInterval 心跳间隔时间(可选) + * @param heartBeatCount 心跳超时次数(可选) + */ + void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询设备状态 + * + * @param device 视频设备 + */ + void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询设备信息 + * + * @param device 视频设备 + * @return + */ + void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询目录列表 + * + * @param device 视频设备 + */ + void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException; + + /** + * 查询录像信息 + * + * @param device 视频设备 + * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss + * @param sn + */ + void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询报警信息 + * + * @param device 视频设备 + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmMethod 报警方式条件(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, + String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询设备配置 + * + * @param device 视频设备 + * @param channelId 通道编码(可选) + * @param configType 配置类型: + */ + void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询设备预置位置 + * + * @param device 视频设备 + */ + void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 查询移动设备位置数据 + * + * @param device 视频设备 + */ + void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 订阅、取消订阅移动位置 + * + * @param device 视频设备 + * @return true = 命令发送成功 + */ + SIPRequest mobilePositionSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent , SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 订阅、取消订阅报警信息 + * @param device 视频设备 + * @param expires 订阅过期时间(0 = 取消订阅) + * @param startPriority 报警起始级别(可选) + * @param endPriority 报警终止级别(可选) + * @param alarmType 报警类型 + * @param startTime 报警发生起始时间(可选) + * @param endTime 报警发生终止时间(可选) + * @return true = 命令发送成功 + */ + void alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String startTime, String endTime) throws InvalidArgumentException, SipException, ParseException; + + /** + * 订阅、取消订阅目录信息 + * @param device 视频设备 + * @return true = 命令发送成功 + */ + SIPRequest catalogSubscribe(Device device, SIPRequest request, SipSubscribe.Event okEvent ,SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + + /** + * 拉框控制命令 + * + * @param device 控制设备 + * @param channelId 通道id + * @param cmdString 前端控制指令串 + */ + void dragZoomCmd(Device device, String channelId, String cmdString) throws InvalidArgumentException, SipException, ParseException; + + + /** + * 向设备发送报警NOTIFY消息, 用于互联结构下,此时将设备当成一个平级平台看待 + * @param device 设备 + * @param deviceAlarm 报警信息信息 + * @return + */ + void sendAlarmMessage(Device device, DeviceAlarm deviceAlarm) throws InvalidArgumentException, SipException, ParseException; + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java old mode 100644 new mode 100755 index 407ccc592..a412a6c74 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java @@ -25,6 +25,8 @@ public interface ISIPCommanderForPlatform { void register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException; void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) throws InvalidArgumentException, ParseException, SipException; + + void register(ParentPlatform parentPlatform, SipTransactionInfo sipTransactionInfo, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean isRegister) throws SipException, InvalidArgumentException, ParseException; /** diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/ISIPRequestProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/SIPRequestProcessorParent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/CancelRequestProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java old mode 100644 new mode 100755 index 08eb71ac9..30a27bed9 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -21,10 +21,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IPlayService; -import com.genersoft.iot.vmp.service.IStreamProxyService; -import com.genersoft.iot.vmp.service.IStreamPushService; +import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -83,6 +80,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private IInviteStreamService inviteStreamService; + @Autowired private SSRCFactory ssrcFactory; @@ -518,10 +518,10 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements errorEvent.run(code, msg, data); } }); - }else { + } else { SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { - if (code == InviteErrorCode.SUCCESS.getCode()){ + if (code == InviteErrorCode.SUCCESS.getCode()) { hookEvent.run(code, msg, data); } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java old mode 100644 new mode 100755 index d44ff5a85..dbe49d5d8 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java @@ -132,7 +132,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements if (CmdType.CATALOG.equals(cmd)) { logger.info("接收到Catalog通知"); -// processNotifyCatalogList(take.getEvt()); + processNotifyCatalogList(take.getEvt()); notifyRequestForCatalogProcessor.process(take.getEvt()); } else if (CmdType.ALARM.equals(cmd)) { logger.info("接收到Alarm通知"); @@ -319,6 +319,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements logger.info("[收到Notify-Alarm]:{}/{}", device.getDeviceId(), deviceAlarm.getChannelId()); if ("4".equals(deviceAlarm.getAlarmMethod())) { MobilePosition mobilePosition = new MobilePosition(); + mobilePosition.setChannelId(channelId); mobilePosition.setCreateTime(DateUtil.getNow()); mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); mobilePosition.setTime(deviceAlarm.getAlarmTime()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java old mode 100644 new mode 100755 index 70a9f770f..76e9d2c7d --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java @@ -88,7 +88,11 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen Response response = null; boolean passwordCorrect = false; // 注册标志 - boolean registerFlag; + boolean registerFlag = true; + if (request.getExpires().getExpires() == 0) { + // 注销成功 + registerFlag = false; + } FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); AddressImpl address = (AddressImpl) fromHeader.getAddress(); SipUri uri = (SipUri) address.getURI(); @@ -99,11 +103,12 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, userSetting.getSipUseSourceIpAsRemoteAddress()); String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort(); - logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress); + String title = registerFlag ? "[注册请求]": "[注销请求]"; + logger.info(title + "设备:{}, 开始处理: {}", deviceId, requestAddress); if (device != null && device.getSipTransactionInfo() != null && request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) { - logger.info("[注册请求] 设备:{}, 注册续订: {}",device.getDeviceId(), device.getDeviceId()); + logger.info(title + "设备:{}, 注册续订: {}",device.getDeviceId(), device.getDeviceId()); device.setExpires(request.getExpires().getExpires()); device.setIp(remoteAddressInfo.getIp()); device.setPort(remoteAddressInfo.getPort()); @@ -123,7 +128,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen String password = (device != null && !ObjectUtils.isEmpty(device.getPassword()))? device.getPassword() : sipConfig.getPassword(); AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); if (authHead == null && !ObjectUtils.isEmpty(password)) { - logger.info("[注册请求] 设备:{}, 回复401: {}",deviceId, requestAddress); + logger.info(title + " 设备:{}, 回复401: {}",deviceId, requestAddress); response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); @@ -138,7 +143,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 注册失败 response = getMessageFactory().createResponse(Response.FORBIDDEN, request); response.setReasonPhrase("wrong password"); - logger.info("[注册请求] 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress); + logger.info(title + " 设备:{}, 密码/SIP服务器ID错误, 回复403: {}", deviceId, requestAddress); sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); return; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/SubscribeRequestProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java old mode 100644 new mode 100755 index 62290c519..92175ac29 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java @@ -1,149 +1,149 @@ -package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; - -import com.genersoft.iot.vmp.common.InviteInfo; -import com.genersoft.iot.vmp.common.InviteSessionType; -import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; -import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; -import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; -import com.genersoft.iot.vmp.gb28181.utils.SipUtils; -import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import gov.nist.javax.sip.message.SIPRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; - -import javax.sip.InvalidArgumentException; -import javax.sip.RequestEvent; -import javax.sip.SipException; -import javax.sip.header.CallIdHeader; -import javax.sip.header.ContentTypeHeader; -import javax.sip.message.Response; -import java.text.ParseException; - -@Component -public class InfoRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { - - private final static Logger logger = LoggerFactory.getLogger(InfoRequestProcessor.class); - - private final String method = "INFO"; - - @Autowired - private SIPProcessorObserver sipProcessorObserver; - - @Autowired - private IVideoManagerStorage storage; - - @Autowired - private SipSubscribe sipSubscribe; - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired - private IInviteStreamService inviteStreamService; - - @Autowired - private IVideoManagerStorage storager; - - @Autowired - private SIPCommander cmder; - - @Autowired - private VideoStreamSessionManager sessionManager; - - @Override - public void afterPropertiesSet() throws Exception { - // 添加消息处理的订阅 - sipProcessorObserver.addRequestProcessor(method, this); - } - - @Override - public void process(RequestEvent evt) { - logger.debug("接收到消息:" + evt.getRequest()); - SIPRequest request = (SIPRequest) evt.getRequest(); - String deviceId = SipUtils.getUserIdFromFromHeader(request); - CallIdHeader callIdHeader = request.getCallIdHeader(); - // 先从会话内查找 - SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); - - // 兼容海康 媒体通知 消息from字段不是设备ID的问题 - if (ssrcTransaction != null) { - deviceId = ssrcTransaction.getDeviceId(); - } - // 查询设备是否存在 - Device device = redisCatchStorage.getDevice(deviceId); - // 查询上级平台是否存在 - ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); - try { - if (device != null && parentPlatform != null) { - logger.warn("[重复]平台与设备编号重复:{}", deviceId); - String hostAddress = request.getRemoteAddress().getHostAddress(); - int remotePort = request.getRemotePort(); - if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) { - parentPlatform = null; - }else { - device = null; - } - } - if (device == null && parentPlatform == null) { - // 不存在则回复404 - responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found"); - logger.warn("[设备未找到 ]: {}", deviceId); - if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ - DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog()); - deviceNotFoundEvent.setCallId(callIdHeader.getCallId()); - SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent); - sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); - }; - }else { - ContentTypeHeader header = (ContentTypeHeader)evt.getRequest().getHeader(ContentTypeHeader.NAME); - String contentType = header.getContentType(); - String contentSubType = header.getContentSubType(); - if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); - String streamId = sendRtpItem.getStream(); - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); - if (null == inviteInfo) { - responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); - return; - } - Device device1 = storager.queryVideoDevice(inviteInfo.getDeviceId()); - if (inviteInfo.getStreamInfo() != null) { - cmder.playbackControlCmd(device1,inviteInfo.getStreamInfo(),new String(evt.getRequest().getRawContent()),eventResult -> { - // 失败的回复 - try { - responseAck(request, eventResult.statusCode, eventResult.msg); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); - } - }, eventResult -> { - // 成功的回复 - try { - responseAck(request, eventResult.statusCode); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); - } - }); - } - - } - } - } catch (SipException e) { - logger.warn("SIP 回复错误", e); - } catch (InvalidArgumentException e) { - logger.warn("参数无效", e); - } catch (ParseException e) { - logger.warn("SIP回复时解析异常", e); - } - } - - -} +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; + +import com.genersoft.iot.vmp.common.InviteInfo; +import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.service.IInviteStreamService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import gov.nist.javax.sip.message.SIPRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.sip.InvalidArgumentException; +import javax.sip.RequestEvent; +import javax.sip.SipException; +import javax.sip.header.CallIdHeader; +import javax.sip.header.ContentTypeHeader; +import javax.sip.message.Response; +import java.text.ParseException; + +@Component +public class InfoRequestProcessor extends SIPRequestProcessorParent implements InitializingBean, ISIPRequestProcessor { + + private final static Logger logger = LoggerFactory.getLogger(InfoRequestProcessor.class); + + private final String method = "INFO"; + + @Autowired + private SIPProcessorObserver sipProcessorObserver; + + @Autowired + private IVideoManagerStorage storage; + + @Autowired + private SipSubscribe sipSubscribe; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IInviteStreamService inviteStreamService; + + @Autowired + private IVideoManagerStorage storager; + + @Autowired + private SIPCommander cmder; + + @Autowired + private VideoStreamSessionManager sessionManager; + + @Override + public void afterPropertiesSet() throws Exception { + // 添加消息处理的订阅 + sipProcessorObserver.addRequestProcessor(method, this); + } + + @Override + public void process(RequestEvent evt) { + logger.debug("接收到消息:" + evt.getRequest()); + SIPRequest request = (SIPRequest) evt.getRequest(); + String deviceId = SipUtils.getUserIdFromFromHeader(request); + CallIdHeader callIdHeader = request.getCallIdHeader(); + // 先从会话内查找 + SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null); + + // 兼容海康 媒体通知 消息from字段不是设备ID的问题 + if (ssrcTransaction != null) { + deviceId = ssrcTransaction.getDeviceId(); + } + // 查询设备是否存在 + Device device = redisCatchStorage.getDevice(deviceId); + // 查询上级平台是否存在 + ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(deviceId); + try { + if (device != null && parentPlatform != null) { + logger.warn("[重复]平台与设备编号重复:{}", deviceId); + String hostAddress = request.getRemoteAddress().getHostAddress(); + int remotePort = request.getRemotePort(); + if (device.getHostAddress().equals(hostAddress + ":" + remotePort)) { + parentPlatform = null; + }else { + device = null; + } + } + if (device == null && parentPlatform == null) { + // 不存在则回复404 + responseAck(request, Response.NOT_FOUND, "device "+ deviceId +" not found"); + logger.warn("[设备未找到 ]: {}", deviceId); + if (sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()) != null){ + DeviceNotFoundEvent deviceNotFoundEvent = new DeviceNotFoundEvent(evt.getDialog()); + deviceNotFoundEvent.setCallId(callIdHeader.getCallId()); + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent); + sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); + }; + }else { + ContentTypeHeader header = (ContentTypeHeader)evt.getRequest().getHeader(ContentTypeHeader.NAME); + String contentType = header.getContentType(); + String contentSubType = header.getContentSubType(); + if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); + String streamId = sendRtpItem.getStream(); + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId); + if (null == inviteInfo) { + responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); + return; + } + Device device1 = storager.queryVideoDevice(inviteInfo.getDeviceId()); + if (inviteInfo.getStreamInfo() != null) { + cmder.playbackControlCmd(device1,inviteInfo.getStreamInfo(),new String(evt.getRequest().getRawContent()),eventResult -> { + // 失败的回复 + try { + responseAck(request, eventResult.statusCode, eventResult.msg); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); + } + }, eventResult -> { + // 成功的回复 + try { + responseAck(request, eventResult.statusCode); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage()); + } + }); + } + + } + } + } catch (SipException e) { + logger.warn("SIP 回复错误", e); + } catch (InvalidArgumentException e) { + logger.warn("参数无效", e); + } catch (ParseException e) { + logger.warn("SIP回复时解析异常", e); + } + } + + +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/IMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/IMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java old mode 100644 new mode 100755 index b5db5b37f..69b4b2531 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageHandlerAbstract.java @@ -3,7 +3,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; -import gov.nist.javax.sip.message.SIPRequest; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,6 +23,9 @@ public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent i public Map messageHandlerMap = new ConcurrentHashMap<>(); + @Autowired + private IVideoManagerStorage storage; + public void addHandler(String cmdType, IMessageHandler messageHandler) { messageHandlerMap.put(cmdType, messageHandler); } @@ -40,7 +42,15 @@ public abstract class MessageHandlerAbstract extends SIPRequestProcessorParent i return; } IMessageHandler messageHandler = messageHandlerMap.get(cmd); + if (messageHandler != null) { + //两个国标平台互相级联时由于上一步判断导致本该在平台处理的消息 放到了设备的处理逻辑 + //所以对目录查询单独做了校验 + if(messageHandler instanceof CatalogQueryMessageHandler){ + ParentPlatform parentPlatform = storage.queryParentPlatByServerGBId(device.getDeviceId()); + messageHandler.handForPlatform(evt, parentPlatform, element); + return; + } messageHandler.handForDevice(evt, device, element); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/ControlMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/ControlMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/control/cmd/DeviceControlQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/NotifyMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java old mode 100644 new mode 100755 index 6928def26..2fc7ae0e0 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java @@ -137,6 +137,7 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme MobilePosition mobilePosition = new MobilePosition(); mobilePosition.setCreateTime(DateUtil.getNow()); mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); + mobilePosition.setChannelId(channelId); mobilePosition.setTime(deviceAlarm.getAlarmTime()); mobilePosition.setLongitude(deviceAlarm.getLongitude()); mobilePosition.setLatitude(deviceAlarm.getLatitude()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java old mode 100644 new mode 100755 index 5526e15d9..7d94787e7 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.gb28181.utils.SipUtils; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.message.SIPRequest; +import org.apache.commons.lang3.ObjectUtils; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -68,7 +69,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[命令发送失败] 心跳回复: {}", e.getMessage()); } - if (device.getKeepaliveTime() != null && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L){ + if (!ObjectUtils.isEmpty(device.getKeepaliveTime()) && DateUtil.getDifferenceForNow(device.getKeepaliveTime()) <= 3000L) { logger.info("[收到心跳] 心跳发送过于频繁,已忽略 device: {}, callId: {}", device.getDeviceId(), request.getCallIdHeader().getCallId()); return; } @@ -109,7 +110,11 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @Override public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { - // 不会收到上级平台的心跳信息 - + // 个别平台保活不回复200OK会判定离线 + try { + responseAck((SIPRequest) evt.getRequest(), Response.OK); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[命令发送失败] 心跳回复: {}", e.getMessage()); + } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/QueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/QueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/AlarmQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/CatalogQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceInfoQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/DeviceStatusQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/query/cmd/RecordInfoQueryMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/ResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/AlarmResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/BroadcastResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java old mode 100644 new mode 100755 index 2283fa2e8..19dde718d --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java @@ -30,6 +30,7 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.atomic.AtomicBoolean; /** * 目录查询的回复 @@ -61,6 +62,7 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @Autowired private SipConfig sipConfig; + private AtomicBoolean processing = new AtomicBoolean(false); @Override public void afterPropertiesSet() throws Exception { @@ -69,7 +71,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp @Override public void handForDevice(RequestEvent evt, Device device, Element element) { - boolean isEmpty = taskQueue.isEmpty(); taskQueue.offer(new HandlerCatchData(evt, device, element)); // 回复200 OK try { @@ -77,8 +78,8 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[命令发送失败] 目录查询回复: {}", e.getMessage()); } - // 如果不为空则说明已经开启消息处理 - if (isEmpty) { + // 已经开启消息处理则跳过 + if (processing.compareAndSet(false, true)) { taskExecutor.execute(() -> { while (!taskQueue.isEmpty()) { // 全局异常捕获,保证下一条可以得到处理 @@ -147,11 +148,12 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp } } - }catch (Exception e) { + } catch (Exception e) { logger.warn("[收到通道] 发现未处理的异常, \r\n{}", evt.getRequest()); logger.error("[收到通道] 异常内容: ", e); } } + processing.set(false); }); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/ConfigDownloadResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceConfigResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceConfigResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceControlResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceInfoResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/DeviceStatusResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/MobilePositionResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/PresetQueryResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/ISIPResponseProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/SIPResponseProcessorAbstract.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/SIPResponseProcessorAbstract.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/ByeResponseProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/CancelResponseProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/ITimeoutProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/ITimeoutProcessor.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/impl/TimeoutProcessorImpl.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/timeout/impl/TimeoutProcessorImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index 8c96a8e85..e614b9fd8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -1,647 +1,647 @@ -package com.genersoft.iot.vmp.gb28181.utils; - -import com.alibaba.fastjson2.JSONArray; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.CivilCodePo; -import com.genersoft.iot.vmp.conf.CivilCodeFileConf; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.utils.DateUtil; -import org.apache.commons.lang3.math.NumberUtils; -import org.dom4j.Attribute; -import org.dom4j.Document; -import org.dom4j.DocumentException; -import org.dom4j.Element; -import org.dom4j.io.SAXReader; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.util.ObjectUtils; -import org.springframework.util.ReflectionUtils; - -import javax.sip.RequestEvent; -import javax.sip.message.Request; -import java.io.ByteArrayInputStream; -import java.io.StringReader; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.ParameterizedType; -import java.lang.reflect.Type; -import java.util.*; - -/** - * 基于dom4j的工具包 - * - * - */ -public class XmlUtil { - /** - * 日志服务 - */ - private static Logger logger = LoggerFactory.getLogger(XmlUtil.class); - - /** - * 解析XML为Document对象 - * - * @param xml 被解析的XMl - * - * @return Document - */ - public static Element parseXml(String xml) { - Document document = null; - // - StringReader sr = new StringReader(xml); - SAXReader saxReader = new SAXReader(); - try { - document = saxReader.read(sr); - } catch (DocumentException e) { - logger.error("解析失败", e); - } - return null == document ? null : document.getRootElement(); - } - - /** - * 获取element对象的text的值 - * - * @param em 节点的对象 - * @param tag 节点的tag - * @return 节点 - */ - public static String getText(Element em, String tag) { - if (null == em) { - return null; - } - Element e = em.element(tag); - // - return null == e ? null : e.getText().trim(); - } - - /** - * 递归解析xml节点,适用于 多节点数据 - * - * @param node node - * @param nodeName nodeName - * @return List> - */ - public static List> listNodes(Element node, String nodeName) { - if (null == node) { - return null; - } - // 初始化返回 - List> listMap = new ArrayList>(); - // 首先获取当前节点的所有属性节点 - List list = node.attributes(); - - Map map = null; - // 遍历属性节点 - for (Attribute attribute : list) { - if (nodeName.equals(node.getName())) { - if (null == map) { - map = new HashMap(); - listMap.add(map); - } - // 取到的节点属性放到map中 - map.put(attribute.getName(), attribute.getValue()); - } - - } - // 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称 - // 使用递归 - Iterator iterator = node.elementIterator(); - while (iterator.hasNext()) { - Element e = iterator.next(); - listMap.addAll(listNodes(e, nodeName)); - } - return listMap; - } - - /** - * xml转json - * - * @param element - * @param json - */ - public static void node2Json(Element element, JSONObject json) { - // 如果是属性 - for (Object o : element.attributes()) { - Attribute attr = (Attribute) o; - if (!ObjectUtils.isEmpty(attr.getValue())) { - json.put("@" + attr.getName(), attr.getValue()); - } - } - List chdEl = element.elements(); - if (chdEl.isEmpty() && !ObjectUtils.isEmpty(element.getText())) {// 如果没有子元素,只有一个值 - json.put(element.getName(), element.getText()); - } - - for (Element e : chdEl) { // 有子元素 - if (!e.elements().isEmpty()) { // 子元素也有子元素 - JSONObject chdjson = new JSONObject(); - node2Json(e, chdjson); - Object o = json.get(e.getName()); - if (o != null) { - JSONArray jsona = null; - if (o instanceof JSONObject) { // 如果此元素已存在,则转为jsonArray - JSONObject jsono = (JSONObject) o; - json.remove(e.getName()); - jsona = new JSONArray(); - jsona.add(jsono); - jsona.add(chdjson); - } - if (o instanceof JSONArray) { - jsona = (JSONArray) o; - jsona.add(chdjson); - } - json.put(e.getName(), jsona); - } else { - if (!chdjson.isEmpty()) { - json.put(e.getName(), chdjson); - } - } - } else { // 子元素没有子元素 - for (Object o : element.attributes()) { - Attribute attr = (Attribute) o; - if (!ObjectUtils.isEmpty(attr.getValue())) { - json.put("@" + attr.getName(), attr.getValue()); - } - } - if (!e.getText().isEmpty()) { - json.put(e.getName(), e.getText()); - } - } - } - } - public static Element getRootElement(RequestEvent evt) throws DocumentException { - - return getRootElement(evt, "gb2312"); - } - - public static Element getRootElement(RequestEvent evt, String charset) throws DocumentException { - Request request = evt.getRequest(); - return getRootElement(request.getRawContent(), charset); - } - - public static Element getRootElement(byte[] content, String charset) throws DocumentException { - if (charset == null) { - charset = "gb2312"; - } - SAXReader reader = new SAXReader(); - reader.setEncoding(charset); - Document xml = reader.read(new ByteArrayInputStream(content)); - return xml.getRootElement(); - } - - private enum ChannelType{ - CivilCode, BusinessGroup,VirtualOrganization,Other - } - - public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event, CivilCodeFileConf civilCodeFileConf){ - DeviceChannel deviceChannel = new DeviceChannel(); - deviceChannel.setDeviceId(device.getDeviceId()); - Element channdelIdElement = itemDevice.element("DeviceID"); - if (channdelIdElement == null) { - logger.warn("解析Catalog消息时发现缺少 DeviceID"); - return null; - } - String channelId = channdelIdElement.getTextTrim(); - if (ObjectUtils.isEmpty(channelId)) { - logger.warn("解析Catalog消息时发现缺少 DeviceID"); - return null; - } - deviceChannel.setChannelId(channelId); - if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) { - // 除了ADD和update情况下需要识别全部内容, - return deviceChannel; - } - Element nameElement = itemDevice.element("Name"); - if (nameElement != null) { - deviceChannel.setName(nameElement.getText()); - } - if(channelId.length() <= 8) { - deviceChannel.setHasAudio(false); - CivilCodePo parentCode = civilCodeFileConf.getParentCode(channelId); - if (parentCode != null) { - deviceChannel.setParentId(parentCode.getCode()); - deviceChannel.setCivilCode(parentCode.getCode()); - }else { - logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId); - } - deviceChannel.setStatus(true); - return deviceChannel; - }else { - if(channelId.length() != 20) { - logger.warn("[xml解析] 失败,编号不符合国标28181定义: {}", channelId); - return null; - } - - int code = Integer.parseInt(channelId.substring(10, 13)); - if (code == 136 || code == 137 || code == 138) { - deviceChannel.setHasAudio(true); - }else { - deviceChannel.setHasAudio(false); - } - // 设备厂商 - String manufacturer = getText(itemDevice, "Manufacturer"); - // 设备型号 - String model = getText(itemDevice, "Model"); - // 设备归属 - String owner = getText(itemDevice, "Owner"); - // 行政区域 - String civilCode = getText(itemDevice, "CivilCode"); - // 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织 - String businessGroupID = getText(itemDevice, "BusinessGroupID"); - // 父设备/区域/系统ID - String parentID = getText(itemDevice, "ParentID"); - if (parentID != null && parentID.equalsIgnoreCase("null")) { - parentID = null; - } - // 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式 - String registerWay = getText(itemDevice, "RegisterWay"); - // 保密属性(必选)缺省为0;0:不涉密,1:涉密 - String secrecy = getText(itemDevice, "Secrecy"); - // 安装地址 - String address = getText(itemDevice, "Address"); - - switch (code){ - case 200: - // 系统目录 - if (!ObjectUtils.isEmpty(manufacturer)) { - deviceChannel.setManufacture(manufacturer); - } - if (!ObjectUtils.isEmpty(model)) { - deviceChannel.setModel(model); - } - if (!ObjectUtils.isEmpty(owner)) { - deviceChannel.setOwner(owner); - } - if (!ObjectUtils.isEmpty(civilCode)) { - deviceChannel.setCivilCode(civilCode); - deviceChannel.setParentId(civilCode); - }else { - if (!ObjectUtils.isEmpty(parentID)) { - deviceChannel.setParentId(parentID); - } - } - if (!ObjectUtils.isEmpty(address)) { - deviceChannel.setAddress(address); - } - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(registerWay)) { - try { - deviceChannel.setRegisterWay(Integer.parseInt(registerWay)); - }catch (NumberFormatException exception) { - logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); - } - } - if (!ObjectUtils.isEmpty(secrecy)) { - deviceChannel.setSecrecy(secrecy); - } - return deviceChannel; - case 215: - // 业务分组 - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(parentID)) { - if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) { - deviceChannel.setParentId(parentID); - } - }else { - logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId"); - if (!ObjectUtils.isEmpty(civilCode)) { - deviceChannel.setCivilCode(civilCode); - } - } - break; - case 216: - // 虚拟组织 - deviceChannel.setStatus(true); - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setBusinessGroupId(businessGroupID); - } - - if (!ObjectUtils.isEmpty(parentID)) { - if (parentID.contains("/")) { - String[] parentIdArray = parentID.split("/"); - parentID = parentIdArray[parentIdArray.length - 1]; - } - deviceChannel.setParentId(parentID); - }else { - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setParentId(businessGroupID); - } - } - break; - default: - // 设备目录 - if (!ObjectUtils.isEmpty(manufacturer)) { - deviceChannel.setManufacture(manufacturer); - } - if (!ObjectUtils.isEmpty(model)) { - deviceChannel.setModel(model); - } - if (!ObjectUtils.isEmpty(owner)) { - deviceChannel.setOwner(owner); - } - if (!ObjectUtils.isEmpty(civilCode) - && civilCode.length() <= 8 - && NumberUtils.isParsable(civilCode) - && civilCode.length()%2 == 0 - ) { - deviceChannel.setCivilCode(civilCode); - } - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setBusinessGroupId(businessGroupID); - } - - // 警区 - String block = getText(itemDevice, "Block"); - if (!ObjectUtils.isEmpty(block)) { - deviceChannel.setBlock(block); - } - if (!ObjectUtils.isEmpty(address)) { - deviceChannel.setAddress(address); - } - - if (!ObjectUtils.isEmpty(secrecy)) { - deviceChannel.setSecrecy(secrecy); - } - - // 当为设备时,是否有子设备(必选)1有,0没有 - String parental = getText(itemDevice, "Parental"); - if (!ObjectUtils.isEmpty(parental)) { - try { - // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1 - if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) { - deviceChannel.setParental(0); - }else { - deviceChannel.setParental(1); - } - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 parental失败: {}", parental); - } - } - // 父设备/区域/系统ID - - if (!ObjectUtils.isEmpty(parentID) ) { - if (parentID.contains("/")) { - String[] parentIdArray = parentID.split("/"); - deviceChannel.setParentId(parentIdArray[parentIdArray.length - 1]); - }else { - if (parentID.length()%2 == 0) { - deviceChannel.setParentId(parentID); - }else { - logger.warn("[xml解析] 不规范的parentID:{}, 已舍弃", parentID); - } - } - }else { - if (!ObjectUtils.isEmpty(businessGroupID)) { - deviceChannel.setParentId(businessGroupID); - }else { - if (!ObjectUtils.isEmpty(deviceChannel.getCivilCode())) { - deviceChannel.setParentId(deviceChannel.getCivilCode()); - } - } - } - // 注册方式 - if (!ObjectUtils.isEmpty(registerWay)) { - try { - int registerWayInt = Integer.parseInt(registerWay); - deviceChannel.setRegisterWay(registerWayInt); - }catch (NumberFormatException exception) { - logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); - deviceChannel.setRegisterWay(1); - } - }else { - deviceChannel.setRegisterWay(1); - } - - // 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式 - String safetyWay = getText(itemDevice, "SafetyWay"); - if (!ObjectUtils.isEmpty(safetyWay)) { - try { - deviceChannel.setSafetyWay(Integer.parseInt(safetyWay)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 safetyWay失败: {}", safetyWay); - } - } - - // 证书序列号(有证书的设备必选) - String certNum = getText(itemDevice, "CertNum"); - if (!ObjectUtils.isEmpty(certNum)) { - deviceChannel.setCertNum(certNum); - } - - // 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效 - String certifiable = getText(itemDevice, "Certifiable"); - if (!ObjectUtils.isEmpty(certifiable)) { - try { - deviceChannel.setCertifiable(Integer.parseInt(certifiable)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 Certifiable失败: {}", certifiable); - } - } - - // 无效原因码(有证书且证书无效的设备必选) - String errCode = getText(itemDevice, "ErrCode"); - if (!ObjectUtils.isEmpty(errCode)) { - try { - deviceChannel.setErrCode(Integer.parseInt(errCode)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 ErrCode失败: {}", errCode); - } - } - - // 证书终止有效期(有证书的设备必选) - String endTime = getText(itemDevice, "EndTime"); - if (!ObjectUtils.isEmpty(endTime)) { - deviceChannel.setEndTime(endTime); - } - - - // 设备/区域/系统IP地址 - String ipAddress = getText(itemDevice, "IPAddress"); - if (!ObjectUtils.isEmpty(ipAddress)) { - deviceChannel.setIpAddress(ipAddress); - } - - // 设备/区域/系统端口 - String port = getText(itemDevice, "Port"); - if (!ObjectUtils.isEmpty(port)) { - try { - deviceChannel.setPort(Integer.parseInt(port)); - }catch (NumberFormatException e) { - logger.warn("[xml解析] 从通道数据获取 Port失败: {}", port); - } - } - - // 设备口令 - String password = getText(itemDevice, "Password"); - if (!ObjectUtils.isEmpty(password)) { - deviceChannel.setPassword(password); - } - - - // 设备状态 - String status = getText(itemDevice, "Status"); - if (status != null) { - // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 - if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) { - deviceChannel.setStatus(true); - } - if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { - deviceChannel.setStatus(false); - } - }else { - deviceChannel.setStatus(true); - } - - // 经度 - String longitude = getText(itemDevice, "Longitude"); - if (NumericUtil.isDouble(longitude)) { - deviceChannel.setLongitude(Double.parseDouble(longitude)); - } else { - deviceChannel.setLongitude(0.00); - } - - // 纬度 - String latitude = getText(itemDevice, "Latitude"); - if (NumericUtil.isDouble(latitude)) { - deviceChannel.setLatitude(Double.parseDouble(latitude)); - } else { - deviceChannel.setLatitude(0.00); - } - - deviceChannel.setGpsTime(DateUtil.getNow()); - - // -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机。当目录项为摄像机时可选 - String ptzType = getText(itemDevice, "PTZType"); - if (ObjectUtils.isEmpty(ptzType)) { - //兼容INFO中的信息 - Element info = itemDevice.element("Info"); - String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType"); - if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){ - try { - deviceChannel.setPTZType(Integer.parseInt(ptzTypeFromInfo)); - }catch (NumberFormatException e){ - logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo); - } - } - } else { - try { - deviceChannel.setPTZType(Integer.parseInt(ptzType)); - }catch (NumberFormatException e){ - logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType); - } - } - - // TODO 摄像机位置类型扩展。 - // 1-省际检查站、 - // 2-党政机关、 - // 3-车站码头、 - // 4-中心广场、 - // 5-体育场馆、 - // 6-商业中心、 - // 7-宗教场所、 - // 8-校园周边、 - // 9-治安复杂区域、 - // 10-交通干线。 - // String positionType = getText(itemDevice, "PositionType"); - - // TODO 摄像机安装位置室外、室内属性。1-室外、2-室内。 - // String roomType = getText(itemDevice, "RoomType"); - // TODO 摄像机用途属性 - // String useType = getText(itemDevice, "UseType"); - // TODO 摄像机补光属性。1-无补光、2-红外补光、3-白光补光 - // String supplyLightType = getText(itemDevice, "SupplyLightType"); - // TODO 摄像机监视方位属性。1-东、2-西、3-南、4-北、5-东南、6-东北、7-西南、8-西北。 - // String directionType = getText(itemDevice, "DirectionType"); - // TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以“/”分隔。分辨率取值参见附录 F中SDPf字段规定 - // String resolution = getText(itemDevice, "Resolution"); - - // TODO 下载倍速范围(可选),各可选参数以“/”分隔,如设备支持1,2,4倍速下载则应写为“1/2/4 - // String downloadSpeed = getText(itemDevice, "DownloadSpeed"); - // TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层) - // String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode"); - // TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强 - // String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode"); - - - deviceChannel.setSecrecy(secrecy); - break; - } - } - - return deviceChannel; - } - - /** - * 新增方法支持内部嵌套 - * - * @param element xmlElement - * @param clazz 结果类 - * @param 泛型 - * @return 结果对象 - * @throws NoSuchMethodException - * @throws InvocationTargetException - * @throws InstantiationException - * @throws IllegalAccessException - */ - public static T loadElement(Element element, Class clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { - Field[] fields = clazz.getDeclaredFields(); - T t = clazz.getDeclaredConstructor().newInstance(); - for (Field field : fields) { - ReflectionUtils.makeAccessible(field); - MessageElement annotation = field.getAnnotation(MessageElement.class); - if (annotation == null) { - continue; - } - String value = annotation.value(); - String subVal = annotation.subVal(); - Element element1 = element.element(value); - if (element1 == null) { - continue; - } - if ("".equals(subVal)) { - // 无下级数据 - Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType()); - Object o = simpleTypeDeal(field.getType(), fieldVal); - ReflectionUtils.setField(field, t, o); - } else { - // 存在下级数据 - ArrayList list = new ArrayList<>(); - Type genericType = field.getGenericType(); - if (!(genericType instanceof ParameterizedType)) { - continue; - } - Class aClass = (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0]; - for (Element element2 : element1.elements(subVal)) { - list.add(loadElement(element2, aClass)); - } - ReflectionUtils.setField(field, t, list); - } - } - return t; - } - - /** - * 简单类型处理 - * - * @param tClass - * @param val - * @return - */ - private static Object simpleTypeDeal(Class tClass, Object val) { - if (tClass.equals(String.class)) { - return val.toString(); - } - if (tClass.equals(Integer.class)) { - return Integer.valueOf(val.toString()); - } - if (tClass.equals(Double.class)) { - return Double.valueOf(val.toString()); - } - if (tClass.equals(Long.class)) { - return Long.valueOf(val.toString()); - } - return val; - } +package com.genersoft.iot.vmp.gb28181.utils; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.CivilCodePo; +import com.genersoft.iot.vmp.conf.CivilCodeFileConf; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; +import com.genersoft.iot.vmp.utils.DateUtil; +import org.apache.commons.lang3.math.NumberUtils; +import org.dom4j.Attribute; +import org.dom4j.Document; +import org.dom4j.DocumentException; +import org.dom4j.Element; +import org.dom4j.io.SAXReader; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.util.ObjectUtils; +import org.springframework.util.ReflectionUtils; + +import javax.sip.RequestEvent; +import javax.sip.message.Request; +import java.io.ByteArrayInputStream; +import java.io.StringReader; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.*; + +/** + * 基于dom4j的工具包 + * + * + */ +public class XmlUtil { + /** + * 日志服务 + */ + private static Logger logger = LoggerFactory.getLogger(XmlUtil.class); + + /** + * 解析XML为Document对象 + * + * @param xml 被解析的XMl + * + * @return Document + */ + public static Element parseXml(String xml) { + Document document = null; + // + StringReader sr = new StringReader(xml); + SAXReader saxReader = new SAXReader(); + try { + document = saxReader.read(sr); + } catch (DocumentException e) { + logger.error("解析失败", e); + } + return null == document ? null : document.getRootElement(); + } + + /** + * 获取element对象的text的值 + * + * @param em 节点的对象 + * @param tag 节点的tag + * @return 节点 + */ + public static String getText(Element em, String tag) { + if (null == em) { + return null; + } + Element e = em.element(tag); + // + return null == e ? null : e.getText().trim(); + } + + /** + * 递归解析xml节点,适用于 多节点数据 + * + * @param node node + * @param nodeName nodeName + * @return List> + */ + public static List> listNodes(Element node, String nodeName) { + if (null == node) { + return null; + } + // 初始化返回 + List> listMap = new ArrayList>(); + // 首先获取当前节点的所有属性节点 + List list = node.attributes(); + + Map map = null; + // 遍历属性节点 + for (Attribute attribute : list) { + if (nodeName.equals(node.getName())) { + if (null == map) { + map = new HashMap(); + listMap.add(map); + } + // 取到的节点属性放到map中 + map.put(attribute.getName(), attribute.getValue()); + } + + } + // 遍历当前节点下的所有节点 ,nodeName 要解析的节点名称 + // 使用递归 + Iterator iterator = node.elementIterator(); + while (iterator.hasNext()) { + Element e = iterator.next(); + listMap.addAll(listNodes(e, nodeName)); + } + return listMap; + } + + /** + * xml转json + * + * @param element + * @param json + */ + public static void node2Json(Element element, JSONObject json) { + // 如果是属性 + for (Object o : element.attributes()) { + Attribute attr = (Attribute) o; + if (!ObjectUtils.isEmpty(attr.getValue())) { + json.put("@" + attr.getName(), attr.getValue()); + } + } + List chdEl = element.elements(); + if (chdEl.isEmpty() && !ObjectUtils.isEmpty(element.getText())) {// 如果没有子元素,只有一个值 + json.put(element.getName(), element.getText()); + } + + for (Element e : chdEl) { // 有子元素 + if (!e.elements().isEmpty()) { // 子元素也有子元素 + JSONObject chdjson = new JSONObject(); + node2Json(e, chdjson); + Object o = json.get(e.getName()); + if (o != null) { + JSONArray jsona = null; + if (o instanceof JSONObject) { // 如果此元素已存在,则转为jsonArray + JSONObject jsono = (JSONObject) o; + json.remove(e.getName()); + jsona = new JSONArray(); + jsona.add(jsono); + jsona.add(chdjson); + } + if (o instanceof JSONArray) { + jsona = (JSONArray) o; + jsona.add(chdjson); + } + json.put(e.getName(), jsona); + } else { + if (!chdjson.isEmpty()) { + json.put(e.getName(), chdjson); + } + } + } else { // 子元素没有子元素 + for (Object o : element.attributes()) { + Attribute attr = (Attribute) o; + if (!ObjectUtils.isEmpty(attr.getValue())) { + json.put("@" + attr.getName(), attr.getValue()); + } + } + if (!e.getText().isEmpty()) { + json.put(e.getName(), e.getText()); + } + } + } + } + public static Element getRootElement(RequestEvent evt) throws DocumentException { + + return getRootElement(evt, "gb2312"); + } + + public static Element getRootElement(RequestEvent evt, String charset) throws DocumentException { + Request request = evt.getRequest(); + return getRootElement(request.getRawContent(), charset); + } + + public static Element getRootElement(byte[] content, String charset) throws DocumentException { + if (charset == null) { + charset = "gb2312"; + } + SAXReader reader = new SAXReader(); + reader.setEncoding(charset); + Document xml = reader.read(new ByteArrayInputStream(content)); + return xml.getRootElement(); + } + + private enum ChannelType{ + CivilCode, BusinessGroup,VirtualOrganization,Other + } + + public static DeviceChannel channelContentHandler(Element itemDevice, Device device, String event, CivilCodeFileConf civilCodeFileConf){ + DeviceChannel deviceChannel = new DeviceChannel(); + deviceChannel.setDeviceId(device.getDeviceId()); + Element channdelIdElement = itemDevice.element("DeviceID"); + if (channdelIdElement == null) { + logger.warn("解析Catalog消息时发现缺少 DeviceID"); + return null; + } + String channelId = channdelIdElement.getTextTrim(); + if (ObjectUtils.isEmpty(channelId)) { + logger.warn("解析Catalog消息时发现缺少 DeviceID"); + return null; + } + deviceChannel.setChannelId(channelId); + if (event != null && !event.equals(CatalogEvent.ADD) && !event.equals(CatalogEvent.UPDATE)) { + // 除了ADD和update情况下需要识别全部内容, + return deviceChannel; + } + Element nameElement = itemDevice.element("Name"); + if (nameElement != null) { + deviceChannel.setName(nameElement.getText()); + } + if(channelId.length() <= 8) { + deviceChannel.setHasAudio(false); + CivilCodePo parentCode = civilCodeFileConf.getParentCode(channelId); + if (parentCode != null) { + deviceChannel.setParentId(parentCode.getCode()); + deviceChannel.setCivilCode(parentCode.getCode()); + }else { + logger.warn("[xml解析] 无法确定行政区划{}的上级行政区划", channelId); + } + deviceChannel.setStatus(true); + return deviceChannel; + }else { + if(channelId.length() != 20) { + logger.warn("[xml解析] 失败,编号不符合国标28181定义: {}", channelId); + return null; + } + + int code = Integer.parseInt(channelId.substring(10, 13)); + if (code == 136 || code == 137 || code == 138) { + deviceChannel.setHasAudio(true); + }else { + deviceChannel.setHasAudio(false); + } + // 设备厂商 + String manufacturer = getText(itemDevice, "Manufacturer"); + // 设备型号 + String model = getText(itemDevice, "Model"); + // 设备归属 + String owner = getText(itemDevice, "Owner"); + // 行政区域 + String civilCode = getText(itemDevice, "CivilCode"); + // 虚拟组织所属的业务分组ID,业务分组根据特定的业务需求制定,一个业务分组包含一组特定的虚拟组织 + String businessGroupID = getText(itemDevice, "BusinessGroupID"); + // 父设备/区域/系统ID + String parentID = getText(itemDevice, "ParentID"); + if (parentID != null && parentID.equalsIgnoreCase("null")) { + parentID = null; + } + // 注册方式(必选)缺省为1;1:符合IETFRFC3261标准的认证注册模式;2:基于口令的双向认证注册模式;3:基于数字证书的双向认证注册模式 + String registerWay = getText(itemDevice, "RegisterWay"); + // 保密属性(必选)缺省为0;0:不涉密,1:涉密 + String secrecy = getText(itemDevice, "Secrecy"); + // 安装地址 + String address = getText(itemDevice, "Address"); + + switch (code){ + case 200: + // 系统目录 + if (!ObjectUtils.isEmpty(manufacturer)) { + deviceChannel.setManufacture(manufacturer); + } + if (!ObjectUtils.isEmpty(model)) { + deviceChannel.setModel(model); + } + if (!ObjectUtils.isEmpty(owner)) { + deviceChannel.setOwner(owner); + } + if (!ObjectUtils.isEmpty(civilCode)) { + deviceChannel.setCivilCode(civilCode); + deviceChannel.setParentId(civilCode); + }else { + if (!ObjectUtils.isEmpty(parentID)) { + deviceChannel.setParentId(parentID); + } + } + if (!ObjectUtils.isEmpty(address)) { + deviceChannel.setAddress(address); + } + deviceChannel.setStatus(true); + if (!ObjectUtils.isEmpty(registerWay)) { + try { + deviceChannel.setRegisterWay(Integer.parseInt(registerWay)); + }catch (NumberFormatException exception) { + logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); + } + } + if (!ObjectUtils.isEmpty(secrecy)) { + deviceChannel.setSecrecy(secrecy); + } + return deviceChannel; + case 215: + // 业务分组 + deviceChannel.setStatus(true); + if (!ObjectUtils.isEmpty(parentID)) { + if (!parentID.trim().equalsIgnoreCase(device.getDeviceId())) { + deviceChannel.setParentId(parentID); + } + }else { + logger.warn("[xml解析] 业务分组数据中缺少关键信息->ParentId"); + if (!ObjectUtils.isEmpty(civilCode)) { + deviceChannel.setCivilCode(civilCode); + } + } + break; + case 216: + // 虚拟组织 + deviceChannel.setStatus(true); + if (!ObjectUtils.isEmpty(businessGroupID)) { + deviceChannel.setBusinessGroupId(businessGroupID); + } + + if (!ObjectUtils.isEmpty(parentID)) { + if (parentID.contains("/")) { + String[] parentIdArray = parentID.split("/"); + parentID = parentIdArray[parentIdArray.length - 1]; + } + deviceChannel.setParentId(parentID); + }else { + if (!ObjectUtils.isEmpty(businessGroupID)) { + deviceChannel.setParentId(businessGroupID); + } + } + break; + default: + // 设备目录 + if (!ObjectUtils.isEmpty(manufacturer)) { + deviceChannel.setManufacture(manufacturer); + } + if (!ObjectUtils.isEmpty(model)) { + deviceChannel.setModel(model); + } + if (!ObjectUtils.isEmpty(owner)) { + deviceChannel.setOwner(owner); + } + if (!ObjectUtils.isEmpty(civilCode) + && civilCode.length() <= 8 + && NumberUtils.isParsable(civilCode) + && civilCode.length()%2 == 0 + ) { + deviceChannel.setCivilCode(civilCode); + } + if (!ObjectUtils.isEmpty(businessGroupID)) { + deviceChannel.setBusinessGroupId(businessGroupID); + } + + // 警区 + String block = getText(itemDevice, "Block"); + if (!ObjectUtils.isEmpty(block)) { + deviceChannel.setBlock(block); + } + if (!ObjectUtils.isEmpty(address)) { + deviceChannel.setAddress(address); + } + + if (!ObjectUtils.isEmpty(secrecy)) { + deviceChannel.setSecrecy(secrecy); + } + + // 当为设备时,是否有子设备(必选)1有,0没有 + String parental = getText(itemDevice, "Parental"); + if (!ObjectUtils.isEmpty(parental)) { + try { + // 由于海康会错误的发送65535作为这里的取值,所以这里除非是0否则认为是1 + if (!ObjectUtils.isEmpty(parental) && parental.length() == 1 && Integer.parseInt(parental) == 0) { + deviceChannel.setParental(0); + }else { + deviceChannel.setParental(1); + } + }catch (NumberFormatException e) { + logger.warn("[xml解析] 从通道数据获取 parental失败: {}", parental); + } + } + // 父设备/区域/系统ID + + if (!ObjectUtils.isEmpty(parentID) ) { + if (parentID.contains("/")) { + String[] parentIdArray = parentID.split("/"); + deviceChannel.setParentId(parentIdArray[parentIdArray.length - 1]); + }else { + if (parentID.length()%2 == 0) { + deviceChannel.setParentId(parentID); + }else { + logger.warn("[xml解析] 不规范的parentID:{}, 已舍弃", parentID); + } + } + }else { + if (!ObjectUtils.isEmpty(businessGroupID)) { + deviceChannel.setParentId(businessGroupID); + }else { + if (!ObjectUtils.isEmpty(deviceChannel.getCivilCode())) { + deviceChannel.setParentId(deviceChannel.getCivilCode()); + } + } + } + // 注册方式 + if (!ObjectUtils.isEmpty(registerWay)) { + try { + int registerWayInt = Integer.parseInt(registerWay); + deviceChannel.setRegisterWay(registerWayInt); + }catch (NumberFormatException exception) { + logger.warn("[xml解析] 从通道数据获取registerWay失败: {}", registerWay); + deviceChannel.setRegisterWay(1); + } + }else { + deviceChannel.setRegisterWay(1); + } + + // 信令安全模式(可选)缺省为0; 0:不采用;2:S/MIME 签名方式;3:S/MIME加密签名同时采用方式;4:数字摘要方式 + String safetyWay = getText(itemDevice, "SafetyWay"); + if (!ObjectUtils.isEmpty(safetyWay)) { + try { + deviceChannel.setSafetyWay(Integer.parseInt(safetyWay)); + }catch (NumberFormatException e) { + logger.warn("[xml解析] 从通道数据获取 safetyWay失败: {}", safetyWay); + } + } + + // 证书序列号(有证书的设备必选) + String certNum = getText(itemDevice, "CertNum"); + if (!ObjectUtils.isEmpty(certNum)) { + deviceChannel.setCertNum(certNum); + } + + // 证书有效标识(有证书的设备必选)缺省为0;证书有效标识:0:无效 1:有效 + String certifiable = getText(itemDevice, "Certifiable"); + if (!ObjectUtils.isEmpty(certifiable)) { + try { + deviceChannel.setCertifiable(Integer.parseInt(certifiable)); + }catch (NumberFormatException e) { + logger.warn("[xml解析] 从通道数据获取 Certifiable失败: {}", certifiable); + } + } + + // 无效原因码(有证书且证书无效的设备必选) + String errCode = getText(itemDevice, "ErrCode"); + if (!ObjectUtils.isEmpty(errCode)) { + try { + deviceChannel.setErrCode(Integer.parseInt(errCode)); + }catch (NumberFormatException e) { + logger.warn("[xml解析] 从通道数据获取 ErrCode失败: {}", errCode); + } + } + + // 证书终止有效期(有证书的设备必选) + String endTime = getText(itemDevice, "EndTime"); + if (!ObjectUtils.isEmpty(endTime)) { + deviceChannel.setEndTime(endTime); + } + + + // 设备/区域/系统IP地址 + String ipAddress = getText(itemDevice, "IPAddress"); + if (!ObjectUtils.isEmpty(ipAddress)) { + deviceChannel.setIpAddress(ipAddress); + } + + // 设备/区域/系统端口 + String port = getText(itemDevice, "Port"); + if (!ObjectUtils.isEmpty(port)) { + try { + deviceChannel.setPort(Integer.parseInt(port)); + }catch (NumberFormatException e) { + logger.warn("[xml解析] 从通道数据获取 Port失败: {}", port); + } + } + + // 设备口令 + String password = getText(itemDevice, "Password"); + if (!ObjectUtils.isEmpty(password)) { + deviceChannel.setPassword(password); + } + + + // 设备状态 + String status = getText(itemDevice, "Status"); + if (status != null) { + // ONLINE OFFLINE HIKVISION DS-7716N-E4 NVR的兼容性处理 + if (status.equals("ON") || status.equals("On") || status.equals("ONLINE") || status.equals("OK")) { + deviceChannel.setStatus(true); + } + if (status.equals("OFF") || status.equals("Off") || status.equals("OFFLINE")) { + deviceChannel.setStatus(false); + } + }else { + deviceChannel.setStatus(true); + } + + // 经度 + String longitude = getText(itemDevice, "Longitude"); + if (NumericUtil.isDouble(longitude)) { + deviceChannel.setLongitude(Double.parseDouble(longitude)); + } else { + deviceChannel.setLongitude(0.00); + } + + // 纬度 + String latitude = getText(itemDevice, "Latitude"); + if (NumericUtil.isDouble(latitude)) { + deviceChannel.setLatitude(Double.parseDouble(latitude)); + } else { + deviceChannel.setLatitude(0.00); + } + + deviceChannel.setGpsTime(DateUtil.getNow()); + + // -摄像机类型扩展,标识摄像机类型:1-球机;2-半球;3-固定枪机;4-遥控枪机。当目录项为摄像机时可选 + String ptzType = getText(itemDevice, "PTZType"); + if (ObjectUtils.isEmpty(ptzType)) { + //兼容INFO中的信息 + Element info = itemDevice.element("Info"); + String ptzTypeFromInfo = XmlUtil.getText(info, "PTZType"); + if(!ObjectUtils.isEmpty(ptzTypeFromInfo)){ + try { + deviceChannel.setPTZType(Integer.parseInt(ptzTypeFromInfo)); + }catch (NumberFormatException e){ + logger.warn("[xml解析] 从通道数据info中获取PTZType失败: {}", ptzTypeFromInfo); + } + } + } else { + try { + deviceChannel.setPTZType(Integer.parseInt(ptzType)); + }catch (NumberFormatException e){ + logger.warn("[xml解析] 从通道数据中获取PTZType失败: {}", ptzType); + } + } + + // TODO 摄像机位置类型扩展。 + // 1-省际检查站、 + // 2-党政机关、 + // 3-车站码头、 + // 4-中心广场、 + // 5-体育场馆、 + // 6-商业中心、 + // 7-宗教场所、 + // 8-校园周边、 + // 9-治安复杂区域、 + // 10-交通干线。 + // String positionType = getText(itemDevice, "PositionType"); + + // TODO 摄像机安装位置室外、室内属性。1-室外、2-室内。 + // String roomType = getText(itemDevice, "RoomType"); + // TODO 摄像机用途属性 + // String useType = getText(itemDevice, "UseType"); + // TODO 摄像机补光属性。1-无补光、2-红外补光、3-白光补光 + // String supplyLightType = getText(itemDevice, "SupplyLightType"); + // TODO 摄像机监视方位属性。1-东、2-西、3-南、4-北、5-东南、6-东北、7-西南、8-西北。 + // String directionType = getText(itemDevice, "DirectionType"); + // TODO 摄像机支持的分辨率,可有多个分辨率值,各个取值间以“/”分隔。分辨率取值参见附录 F中SDPf字段规定 + // String resolution = getText(itemDevice, "Resolution"); + + // TODO 下载倍速范围(可选),各可选参数以“/”分隔,如设备支持1,2,4倍速下载则应写为“1/2/4 + // String downloadSpeed = getText(itemDevice, "DownloadSpeed"); + // TODO 空域编码能力,取值0:不支持;1:1级增强(1个增强层);2:2级增强(2个增强层);3:3级增强(3个增强层) + // String svcSpaceSupportMode = getText(itemDevice, "SVCSpaceSupportMode"); + // TODO 时域编码能力,取值0:不支持;1:1级增强;2:2级增强;3:3级增强 + // String svcTimeSupportMode = getText(itemDevice, "SVCTimeSupportMode"); + + + deviceChannel.setSecrecy(secrecy); + break; + } + } + + return deviceChannel; + } + + /** + * 新增方法支持内部嵌套 + * + * @param element xmlElement + * @param clazz 结果类 + * @param 泛型 + * @return 结果对象 + * @throws NoSuchMethodException + * @throws InvocationTargetException + * @throws InstantiationException + * @throws IllegalAccessException + */ + public static T loadElement(Element element, Class clazz) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException { + Field[] fields = clazz.getDeclaredFields(); + T t = clazz.getDeclaredConstructor().newInstance(); + for (Field field : fields) { + ReflectionUtils.makeAccessible(field); + MessageElement annotation = field.getAnnotation(MessageElement.class); + if (annotation == null) { + continue; + } + String value = annotation.value(); + String subVal = annotation.subVal(); + Element element1 = element.element(value); + if (element1 == null) { + continue; + } + if ("".equals(subVal)) { + // 无下级数据 + Object fieldVal = element1.isTextOnly() ? element1.getText() : loadElement(element1, field.getType()); + Object o = simpleTypeDeal(field.getType(), fieldVal); + ReflectionUtils.setField(field, t, o); + } else { + // 存在下级数据 + ArrayList list = new ArrayList<>(); + Type genericType = field.getGenericType(); + if (!(genericType instanceof ParameterizedType)) { + continue; + } + Class aClass = (Class) ((ParameterizedType) genericType).getActualTypeArguments()[0]; + for (Element element2 : element1.elements(subVal)) { + list.add(loadElement(element2, aClass)); + } + ReflectionUtils.setField(field, t, list); + } + } + return t; + } + + /** + * 简单类型处理 + * + * @param tClass + * @param val + * @return + */ + private static Object simpleTypeDeal(Class tClass, Object val) { + if (tClass.equals(String.class)) { + return val.toString(); + } + if (tClass.equals(Integer.class)) { + return Integer.valueOf(val.toString()); + } + if (tClass.equals(Double.class)) { + return Double.valueOf(val.toString()); + } + if (tClass.equals(Long.class)) { + return Long.valueOf(val.toString()); + } + return val; + } } \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java index 863ff32cb..cf71bf1d7 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java @@ -21,6 +21,7 @@ public class AssistRESTfulUtils { private final static Logger logger = LoggerFactory.getLogger(AssistRESTfulUtils.class); + public interface RequestCallback{ void run(JSONObject response); } @@ -145,4 +146,25 @@ public class AssistRESTfulUtils { return sendGet(mediaServerItem, "api/record/addStreamCallInfo",param, callback); } + public JSONObject getDateList(MediaServerItem mediaServerItem, String app, String stream, int year, int month) { + Map param = new HashMap<>(); + param.put("app", app); + param.put("stream", stream); + param.put("year", year); + param.put("month", month); + return sendGet(mediaServerItem, "api/record/date/list", param, null); + } + + public JSONObject getFileList(MediaServerItem mediaServerItem, int page, int count, String app, String stream, + String startTime, String endTime) { + Map param = new HashMap<>(); + param.put("app", app); + param.put("stream", stream); + param.put("page", page); + param.put("count", count); + param.put("startTime", startTime); + param.put("endTime", endTime); + return sendGet(mediaServerItem, "api/record/file/listWithDate", param, null); + } + } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java old mode 100644 new mode 100755 index f960c7dc8..3f28d02ad --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java @@ -30,7 +30,7 @@ public class SendRtpPortManager { private final String KEY = "VM_MEDIA_SEND_RTP_PORT_"; - public int getNextPort(MediaServerItem mediaServer) { + public synchronized int getNextPort(MediaServerItem mediaServer) { if (mediaServer == null) { logger.warn("[发送端口管理] 参数错误,mediaServer为NULL"); return -1; @@ -50,17 +50,15 @@ public class SendRtpPortManager { String sendRtpPortRange = mediaServer.getSendRtpPortRange(); int startPort; int endPort; - if (sendRtpPortRange == null) { - logger.warn("{}未设置发送端口默认值,自动使用40000-50000作为端口范围", mediaServer.getId()); + if (sendRtpPortRange != null) { String[] portArray = sendRtpPortRange.split(","); if (portArray.length != 2 || !NumberUtils.isParsable(portArray[0]) || !NumberUtils.isParsable(portArray[1])) { - logger.warn("{}发送端口配置格式错误,自动使用40000-50000作为端口范围", mediaServer.getId()); + logger.warn("{}发送端口配置格式错误,自动使用50000-60000作为端口范围", mediaServer.getId()); startPort = 50000; endPort = 60000; }else { - if ( Integer.parseInt(portArray[1]) - Integer.parseInt(portArray[0]) < 1) { - logger.warn("{}发送端口配置错误,结束端口至少比开始端口大一,自动使用40000-50000作为端口范围", mediaServer.getId()); + logger.warn("{}发送端口配置错误,结束端口至少比开始端口大一,自动使用50000-60000作为端口范围", mediaServer.getId()); startPort = 50000; endPort = 60000; }else { @@ -69,6 +67,7 @@ public class SendRtpPortManager { } } }else { + logger.warn("{}未设置发送端口默认值,自动使用50000-60000作为端口范围", mediaServer.getId()); startPort = 50000; endPort = 60000; } @@ -76,10 +75,35 @@ public class SendRtpPortManager { logger.warn("{}获取redis连接信息失败", mediaServer.getId()); return -1; } +// RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory()); +// return redisAtomicInteger.getAndUpdate((current)->{ +// return getPort(current, startPort, endPort, checkPort-> !sendRtpItemMap.containsKey(checkPort)); +// }); + return getSendPort(startPort, endPort, sendIndexKey, sendRtpItemMap); + } + + private synchronized int getSendPort(int startPort, int endPort, String sendIndexKey, Map sendRtpItemMap){ RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory()); - return redisAtomicInteger.getAndUpdate((current)->{ - return getPort(current, startPort, endPort, checkPort-> !sendRtpItemMap.containsKey(checkPort)); - }); + if (redisAtomicInteger.get() < startPort) { + redisAtomicInteger.set(startPort); + return startPort; + }else { + int port = redisAtomicInteger.getAndIncrement(); + if (port > endPort) { + redisAtomicInteger.set(startPort); + if (sendRtpItemMap.containsKey(startPort)) { + return getSendPort(startPort, endPort, sendIndexKey, sendRtpItemMap); + }else { + return startPort; + } + } + if (sendRtpItemMap.containsKey(port)) { + return getSendPort(startPort, endPort, sendIndexKey, sendRtpItemMap); + }else { + return port; + } + } + } interface CheckPortCallback{ diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java old mode 100644 new mode 100755 index 0cd16028c..87a3fc5fa --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -30,6 +30,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import org.slf4j.Logger; @@ -311,7 +312,10 @@ public class ZLMHttpHookListener { if (param.getApp().equalsIgnoreCase("rtp")) { String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(receiveKey); - if (otherRtpSendInfo != null) { + + String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + param.getStream(); + OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo)redisTemplate.opsForValue().get(receiveKeyForPS); + if (otherRtpSendInfo != null || otherPsSendInfo != null) { result.setEnable_mp4(true); } } @@ -696,7 +700,9 @@ public class ZLMHttpHookListener { result.onTimeout(() -> { logger.info("[ZLM HOOK] 预览流自动点播, 等待超时"); msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "点播超时")); - resultHolder.invokeResult(msg); + resultHolder.invokeAllResult(msg); + inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); + storager.stopPlay(deviceId, channelId); }); resultHolder.put(key, uuid, result); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java old mode 100644 new mode 100755 index 72fed0798..24222069d --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java @@ -42,7 +42,7 @@ public class ZLMServerFactory { * @param tcpMode 0/null udp 模式,1 tcp 被动模式, 2 tcp 主动模式。 * @return */ - public int createRTPServer(MediaServerItem mediaServerItem, String streamId, int ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { + public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { int result = -1; // 查询此rtp server 是否已经存在 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ChannelOnlineEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRtpServerTimeout.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRtpServerTimeout.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ServerKeepaliveData.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ServerKeepaliveData.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnPlayHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnPlayHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnPublishHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnPublishHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRtpServerTimeoutHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnRtpServerTimeoutHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnSendRtpStoppedHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnSendRtpStoppedHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnServerKeepaliveHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnServerKeepaliveHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamNoneReaderHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamNoneReaderHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamNotFoundHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamNotFoundHookParam.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OriginType.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OriginType.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMEventAbstract.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMEventAbstract.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceAlarmService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceAlarmService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java b/src/main/java/com/genersoft/iot/vmp/service/IGbStreamService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IInviteStreamService.java b/src/main/java/com/genersoft/iot/vmp/service/IInviteStreamService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/ILogService.java b/src/main/java/com/genersoft/iot/vmp/service/ILogService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java old mode 100644 new mode 100755 index 657f294d6..bf7df28d2 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; import com.genersoft.iot.vmp.service.bean.MediaServerLoad; import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import com.genersoft.iot.vmp.vmanager.bean.RecordFile; import java.util.List; @@ -95,4 +96,14 @@ public interface IMediaServerService { * @return */ MediaServerLoad getLoad(MediaServerItem mediaServerItem); + + /** + * 按时间查找录像文件 + */ + List getRecords(String app, String stream, String startTime, String endTime, List mediaServerItems); + + /** + * 查找存在录像文件的时间 + */ + List getRecordDates(String app, String stream, int year, int month, List mediaServerItems); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlatformChannelService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IRoleService.java b/src/main/java/com/genersoft/iot/vmp/service/IRoleService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/IUserService.java b/src/main/java/com/genersoft/iot/vmp/service/IUserService.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/ErrorCallback.java b/src/main/java/com/genersoft/iot/vmp/service/bean/ErrorCallback.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java b/src/main/java/com/genersoft/iot/vmp/service/bean/GPSMsgInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCode.java b/src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCode.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/InviteTimeOutCallback.java b/src/main/java/com/genersoft/iot/vmp/service/bean/InviteTimeOutCallback.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/MediaServerLoad.java b/src/main/java/com/genersoft/iot/vmp/service/bean/MediaServerLoad.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java b/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannelResponse.java b/src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannelResponse.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PushStreamStatusChangeFromRedisDto.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PushStreamStatusChangeFromRedisDto.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestPushStreamMsg.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/RequestSendItemMsg.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java b/src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java b/src/main/java/com/genersoft/iot/vmp/service/bean/StreamPushItemFromRedis.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/ThirdPartyGB.java b/src/main/java/com/genersoft/iot/vmp/service/bean/ThirdPartyGB.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsg.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java b/src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java old mode 100644 new mode 100755 index 5192d1d0d..68e12f002 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -115,6 +115,7 @@ public class DeviceServiceImpl implements IDeviceService { inviteStreamService.clearInviteInfo(device.getDeviceId()); } device.setUpdateTime(now); + device.setKeepaliveTime(now); if (device.getKeepaliveIntervalTime() == 0) { // 默认心跳间隔60 device.setKeepaliveIntervalTime(60); @@ -535,6 +536,13 @@ public class DeviceServiceImpl implements IDeviceService { if (!ObjectUtils.isEmpty(device.getSdpIp())) { deviceInStore.setSdpIp(device.getSdpIp()); } + if (!ObjectUtils.isEmpty(device.getPassword())) { + deviceInStore.setPassword(device.getPassword()); + } + if (!ObjectUtils.isEmpty(device.getStreamMode())) { + deviceInStore.setStreamMode(device.getStreamMode()); + } + // 目录订阅相关的信息 if (device.getSubscribeCycleForCatalog() > 0) { @@ -568,18 +576,23 @@ public class DeviceServiceImpl implements IDeviceService { if (deviceInStore.getGeoCoordSys() != null) { // 坐标系变化,需要重新计算GCJ02坐标和WGS84坐标 if (!deviceInStore.getGeoCoordSys().equals(device.getGeoCoordSys())) { - updateDeviceChannelGeoCoordSys(device); + deviceInStore.setGeoCoordSys(device.getGeoCoordSys()); + updateDeviceChannelGeoCoordSys(deviceInStore); } }else { - device.setGeoCoordSys("WGS84"); + deviceInStore.setGeoCoordSys("WGS84"); } if (device.getCharset() == null) { - device.setCharset("GB2312"); + deviceInStore.setCharset("GB2312"); } - + //SSRC校验 + deviceInStore.setSsrcCheck(device.isSsrcCheck()); + //作为消息通道 + deviceInStore.setAsMessageChannel(device.isAsMessageChannel()); + // 更新redis - redisCatchStorage.updateDevice(device); - deviceMapper.updateCustom(device); + deviceMapper.updateCustom(deviceInStore); + redisCatchStorage.removeDevice(deviceInStore.getDeviceId()); } @Override diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/GbStreamServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/LogServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/LogServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java old mode 100644 new mode 100755 index b5faf1bf2..0556a8456 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -24,23 +24,30 @@ import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.JsonUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.RecordFile; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; +import org.springframework.util.Assert; import org.springframework.util.ObjectUtils; import java.io.File; import java.time.LocalDateTime; import java.util.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; /** * 媒体服务器节点管理 @@ -104,6 +111,11 @@ public class MediaServerServiceImpl implements IMediaServerService { @Autowired private RedisTemplate redisTemplate; + @Qualifier("taskExecutor") + @Autowired + private ThreadPoolTaskExecutor taskExecutor; + + @@ -118,7 +130,7 @@ public class MediaServerServiceImpl implements IMediaServerService { continue; } // 更新 - if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { + if (!ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); } // 查询redis是否存在此mediaServer @@ -151,7 +163,7 @@ public class MediaServerServiceImpl implements IMediaServerService { } if (streamId == null) { - streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); + streamId = String.format("%08x", Long.parseLong(ssrc)).toUpperCase(); } int ssrcCheckParam = 0; if (ssrcCheck && tcpMode > 1) { @@ -160,7 +172,7 @@ public class MediaServerServiceImpl implements IMediaServerService { } int rtpServerPort; if (mediaServerItem.isRtpEnable()) { - rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, (ssrcCheck && tcpMode == 0)?Integer.parseInt(ssrc):0, port, onlyAuto, reUsePort, tcpMode); + rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, (ssrcCheck && tcpMode == 0) ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode); } else { rtpServerPort = mediaServerItem.getRtpProxyPort(); } @@ -225,7 +237,7 @@ public class MediaServerServiceImpl implements IMediaServerService { mediaServerMapper.update(mediaSerItem); MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); - if (mediaServerItemInRedis == null || ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { + if (mediaServerItemInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null); } String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); @@ -408,7 +420,7 @@ public class MediaServerServiceImpl implements IMediaServerService { } mediaServerMapper.update(serverItem); String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); - if (ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { + if (!ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); } redisTemplate.opsForValue().set(key, serverItem); @@ -758,4 +770,89 @@ public class MediaServerServiceImpl implements IMediaServerService { return result; } + @Override + public List getRecords(String app, String stream, String startTime, String endTime, List mediaServerItems) { + Assert.notNull(app, "app不存在"); + Assert.notNull(stream, "stream不存在"); + Assert.notNull(startTime, "startTime不存在"); + Assert.notNull(endTime, "endTime不存在"); + Assert.notEmpty(mediaServerItems, "流媒体列表为空"); + + CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()]; + for (int i = 0; i < mediaServerItems.size(); i++) { + completableFutures[i] = getRecordFilesForOne(app, stream, startTime, endTime, mediaServerItems.get(i)); + } + List result = new ArrayList<>(); + for (int i = 0; i < completableFutures.length; i++) { + try { + List list = (List) completableFutures[i].get(); + if (!list.isEmpty()) { + for (int g = 0; g < list.size(); g++) { + list.get(g).setMediaServerId(mediaServerItems.get(i).getId()); + } + result.addAll(list); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + Comparator comparator = Comparator.comparing(RecordFile::getFileName); + result.sort(comparator); + return result; + } + + @Override + public List getRecordDates(String app, String stream, int year, int month, List mediaServerItems) { + Assert.notNull(app, "app不存在"); + Assert.notNull(stream, "stream不存在"); + Assert.notEmpty(mediaServerItems, "流媒体列表为空"); + CompletableFuture[] completableFutures = new CompletableFuture[mediaServerItems.size()]; + + for (int i = 0; i < mediaServerItems.size(); i++) { + completableFutures[i] = getRecordDatesForOne(app, stream, year, month, mediaServerItems.get(i)); + } + List result = new ArrayList<>(); + CompletableFuture.allOf(completableFutures).join(); + for (CompletableFuture completableFuture : completableFutures) { + try { + List list = (List) completableFuture.get(); + result.addAll(list); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } catch (ExecutionException e) { + throw new RuntimeException(e); + } + } + Collections.sort(result); + return result; + } + + @Async + public CompletableFuture> getRecordDatesForOne(String app, String stream, int year, int month, MediaServerItem mediaServerItem) { + JSONObject fileListJson = assistRESTfulUtils.getDateList(mediaServerItem, app, stream, year, month); + if (fileListJson != null && !fileListJson.isEmpty()) { + if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) { + JSONArray data = fileListJson.getJSONArray("data"); + return CompletableFuture.completedFuture(data.toJavaList(String.class)); + } + } + return CompletableFuture.completedFuture(new ArrayList<>()); + } + + @Async + public CompletableFuture> getRecordFilesForOne(String app, String stream, String startTime, String endTime, MediaServerItem mediaServerItem) { + JSONObject fileListJson = assistRESTfulUtils.getFileList(mediaServerItem, 1, 100000000, app, stream, startTime, endTime); + if (fileListJson != null && !fileListJson.isEmpty()) { + if (fileListJson.getString("code") != null && fileListJson.getInteger("code") == 0) { + JSONObject data = fileListJson.getJSONObject("data"); + JSONArray list = data.getJSONArray("list"); + if (list != null) { + return CompletableFuture.completedFuture(list.toJavaList(RecordFile.class)); + } + } + } + return CompletableFuture.completedFuture(new ArrayList<>()); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformChannelServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java old mode 100644 new mode 100755 index dbde37390..067329d5d --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -251,7 +251,6 @@ public class PlatformServiceImpl implements IPlatformService { // 设置平台离线,并重新注册 logger.info("[国标级联] 三次心跳超时, 平台{}({})离线", parentPlatform.getName(), parentPlatform.getServerGBId()); offline(parentPlatform, false); - } }else { @@ -266,6 +265,7 @@ public class PlatformServiceImpl implements IPlatformService { platformCatch.setKeepAliveReply(0); redisCatchStorage.updatePlatformCatchInfo(platformCatch); } + logger.info("[发送心跳] 国标级联 发送心跳, code: {}, msg: {}", eventResult.statusCode, eventResult.msg); }); } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[命令发送失败] 国标级联 发送心跳: {}", e.getMessage()); @@ -293,7 +293,7 @@ public class PlatformServiceImpl implements IPlatformService { eventResult.statusCode, eventResult.msg); offline(parentPlatform, false); }, null); - } catch (InvalidArgumentException | ParseException | SipException e) { + } catch (Exception e) { logger.error("[命令发送失败] 国标级联定时注册: {}", e.getMessage()); } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RoleServerImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushUploadFileHandler.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/UserServiceImpl.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisCloseStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisCloseStreamMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceAlarmMapper.java old mode 100644 new mode 100755 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java old mode 100644 new mode 100755 index bdc45bf20..d48b802dd --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -193,7 +193,7 @@ public interface DeviceChannelMapper { @Update(value = {"UPDATE wvp_device_channel SET status=false WHERE device_id=#{deviceId} AND channel_id=#{channelId}"}) void offline(String deviceId, String channelId); - @Update(value = {"UPDATE wvp_device_channel SET status=fasle WHERE device_id=#{deviceId}"}) + @Update(value = {"UPDATE wvp_device_channel SET status=false WHERE device_id=#{deviceId}"}) void offlineByDeviceId(String deviceId); @Insert("