From bd21d0e3910b50a8e6cd658364fe198c5a8e6015 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 10 May 2022 09:38:05 +0800 Subject: [PATCH 01/18] =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=E8=8E=B7=E5=8F=96=E5=B9=B6=E6=B3=95=E8=83=BD=E5=8A=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 index 62393d52..75b9f59a 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java @@ -30,7 +30,7 @@ public class CatalogDataCatch { CatalogData catalogData = data.get(device.getDeviceId()); if (catalogData == null || catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end)) { catalogData = new CatalogData(); - catalogData.setChannelList(new ArrayList<>()); + catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>())); catalogData.setDevice(device); catalogData.setSn(sn); catalogData.setStatus(CatalogData.CatalogDataStatus.ready); @@ -46,7 +46,7 @@ public class CatalogDataCatch { catalogData.setSn(sn); catalogData.setTotal(total); catalogData.setDevice(device); - catalogData.setChannelList(new ArrayList<>()); + catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>())); catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); catalogData.setLastTime(new Date(System.currentTimeMillis())); data.put(deviceId, catalogData); From 93e6347f188b87e8d946005aa24b9d7401bc818c Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 10 May 2022 09:45:09 +0800 Subject: [PATCH 02/18] =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E6=8E=A8=E6=B5=81?= =?UTF-8?q?=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/SendRtpItem.java | 37 +++++++++++++++++++ .../request/impl/AckRequestProcessor.java | 3 ++ 2 files changed, 40 insertions(+) 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 index 4b63ec53..c7f61820 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java @@ -76,6 +76,21 @@ public class SendRtpItem { */ private String CallId; + /** + * 发送时,rtp的pt(uint8_t),不传时默认为96 + */ + private int pt = 96; + + /** + * 发送时,rtp的负载类型。为true时,负载为ps;为false时,为es; + */ + private boolean usePs = true; + + /** + * 当usePs 为false时,有效。为1时,发送音频;为0时,发送视频;不传时默认为0 + */ + private boolean onlyAudio = false; + /** * 播放类型 */ @@ -221,5 +236,27 @@ public class SendRtpItem { this.dialog = dialog; } + public int getPt() { + return pt; + } + public void setPt(int pt) { + this.pt = pt; + } + + public boolean isUsePs() { + return usePs; + } + + public void setUsePs(boolean usePs) { + this.usePs = usePs; + } + + public boolean isOnlyAudio() { + return onlyAudio; + } + + public void setOnlyAudio(boolean onlyAudio) { + this.onlyAudio = onlyAudio; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 0f65bf52..873a0a3f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -94,6 +94,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In param.put("dst_port", sendRtpItem.getPort()); param.put("is_udp", is_Udp); param.put("src_port", sendRtpItem.getLocalPort()); + param.put("pt", sendRtpItem.getPt()); + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); + param.put("only_audio", sendRtpItem.isOnlyAudio()); zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); From a1321c29c568d02164a551e774d8bd39868aaf23 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 10 May 2022 10:58:26 +0800 Subject: [PATCH 03/18] =?UTF-8?q?=20=E4=BC=98=E5=8C=96=E7=BA=A7=E8=81=94?= =?UTF-8?q?=E7=82=B9=E6=92=AD=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/impl/AckRequestProcessor.java | 32 +++++++++++++++++-- .../PresetQueryResponseMessageHandler.java | 11 ------- .../vmp/media/zlm/ZLMRTPServerFactory.java | 12 +------ 3 files changed, 31 insertions(+), 24 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 873a0a3f..2e31b481 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -4,8 +4,12 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 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.media.zlm.ZLMHttpHookSubscribe; @@ -13,6 +17,8 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import org.ehcache.shadow.org.terracotta.offheapstore.storage.IntegerStorageEngine; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; @@ -50,6 +56,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private IVideoManagerStorage storager; + @Autowired private ZLMRTPServerFactory zlmrtpServerFactory; @@ -62,6 +71,12 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @Autowired private DynamicTask dynamicTask; + @Autowired + private ISIPCommander cmder; + + @Autowired + private ISIPCommanderForPlatform commanderForPlatform; + /** * 处理 ACK请求 @@ -78,6 +93,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In if (dialog.getState()== DialogState.CONFIRMED) { String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); logger.info("ACK请求: platformGbId->{}", platformGbId); + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformGbId); // 取消设置的超时任务 dynamicTask.stop(callIdHeader.getCallId()); String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); @@ -97,8 +113,20 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In param.put("pt", sendRtpItem.getPt()); param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); param.put("only_audio", sendRtpItem.isOnlyAudio()); - zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); - + JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); + if (jsonObject == null) { + logger.error("RTP推流失败: 请检查ZLM服务"); + } else if (jsonObject.getInteger("code") == 0) { + logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); + } else { + logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); + if (sendRtpItem.isOnlyAudio()) { + // TODO 可能是语音对讲 + }else { + // 向上级平台 + commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); + } + } // if (streamInfo == null) { // 流还没上来,对方就回复ack 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 index db7bb55b..1c9ec21b 100644 --- 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 @@ -1,21 +1,12 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd; -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.domain.req.PresetQuerySipReq; import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.session.CatalogDataCatch; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; -import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; -import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; -import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.dom4j.DocumentException; import org.dom4j.Element; import org.slf4j.Logger; @@ -23,7 +14,6 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; @@ -34,7 +24,6 @@ import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; -import java.util.UUID; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index a7e60167..bd3dcb14 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -246,17 +246,7 @@ public class ZLMRTPServerFactory { * 调用zlm RESTFUL API —— startSendRtp */ public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Mapparam) { - Boolean result = false; - JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param); - if (jsonObject == null) { - logger.error("RTP推流失败: 请检查ZLM服务"); - } else if (jsonObject.getInteger("code") == 0) { - result= true; - logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); - } else { - logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"),JSONObject.toJSON(param)); - } - return jsonObject; + return zlmresTfulUtils.startSendRtp(mediaServerItem, param); } /** From c395cf42d1fbe23c63dccdd87be4444715cf0bfe Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Tue, 10 May 2022 11:01:33 +0800 Subject: [PATCH 04/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E5=8F=91=E6=B5=81?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=E7=9A=84=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../transmit/event/request/impl/AckRequestProcessor.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 2e31b481..af61ed3f 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -112,7 +112,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In param.put("src_port", sendRtpItem.getLocalPort()); param.put("pt", sendRtpItem.getPt()); param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); - param.put("only_audio", sendRtpItem.isOnlyAudio()); + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); JSONObject jsonObject = zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); if (jsonObject == null) { logger.error("RTP推流失败: 请检查ZLM服务"); From f6893cf95b15531dfc45950fea7e780e045ba2ae Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 11 May 2022 18:37:24 +0800 Subject: [PATCH 05/18] =?UTF-8?q?=E4=BC=98=E5=8C=96=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E5=9C=A8=E7=BA=BF=E7=8A=B6=E6=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/common/VideoManagerConstants.java | 2 - .../iot/vmp/conf/ApiAccessFilter.java | 5 +- .../genersoft/iot/vmp/conf/DynamicTask.java | 20 +-- .../genersoft/iot/vmp/conf/MediaConfig.java | 8 +- .../iot/vmp/conf/ThreadPoolTaskConfig.java | 3 +- .../genersoft/iot/vmp/gb28181/SipLayer.java | 7 + .../iot/vmp/gb28181/bean/Device.java | 13 -- .../iot/vmp/gb28181/bean/RecordItem.java | 7 +- .../iot/vmp/gb28181/bean/SubscribeHolder.java | 2 +- .../iot/vmp/gb28181/event/EventPublisher.java | 34 ++--- .../event/device/RequestTimeoutEvent.java | 25 ++++ .../event/device/RequestTimeoutEventImpl.java | 41 ++++++ .../KeepaliveTimeoutListenerForPlatform.java | 25 ++-- .../offline/KeepliveTimeoutListener.java | 63 -------- .../gb28181/event/offline/OfflineEvent.java | 40 ------ .../event/offline/OfflineEventListener.java | 98 ------------- .../vmp/gb28181/event/online/OnlineEvent.java | 51 ------- .../event/online/OnlineEventListener.java | 110 -------------- .../task}/SipDeviceRunner.java | 28 ++-- .../transmit/SIPProcessorObserver.java | 44 +++++- .../transmit/cmd/impl/SIPCommander.java | 3 +- .../cmd/impl/SIPCommanderFroPlatform.java | 2 +- .../request/impl/InviteRequestProcessor.java | 7 +- .../request/impl/NotifyRequestProcessor.java | 33 ++--- .../impl/RegisterRequestProcessor.java | 29 ++-- .../cmd/KeepaliveNotifyMessageHandler.java | 61 ++++---- .../cmd/RecordInfoQueryMessageHandler.java | 2 +- .../cmd/CatalogResponseMessageHandler.java | 3 - .../cmd/DeviceInfoResponseMessageHandler.java | 11 +- .../DeviceStatusResponseMessageHandler.java | 19 ++- .../PresetQueryResponseMessageHandler.java | 3 - .../cmd/RecordInfoResponseMessageHandler.java | 2 +- .../iot/vmp/media/zlm/ZLMRunner.java | 84 ++++------- .../zlm/event/ZLMStatusEventListener.java | 6 +- .../iot/vmp/service/IDeviceService.java | 63 +++++++- .../vmp/service/impl/DeviceServiceImpl.java | 135 +++++++++++++++++- .../service/impl/MediaServerServiceImpl.java | 9 +- .../iot/vmp/service/impl/PlayServiceImpl.java | 2 +- .../service/impl/RedisAlarmMsgListener.java | 11 +- .../iot/vmp/storager/IRedisCatchStorage.java | 17 --- .../iot/vmp/storager/dao/DeviceMapper.java | 5 + .../storager/impl/RedisCatchStorageImpl.java | 33 +---- .../impl/VideoManagerStorageImpl.java | 17 +-- .../iot/vmp/{gb28181 => }/utils/DateUtil.java | 114 +++++++-------- .../gb28181/alarm/AlarmController.java | 14 +- .../iot/vmp/vmanager/log/LogController.java | 8 +- .../iot/vmp/vmanager/user/RoleController.java | 13 +- .../iot/vmp/vmanager/user/UserController.java | 8 +- .../impl/DeviceAlarmServiceImplTest.java | 10 +- .../vmp/service/impl/RoleServiceImplTest.java | 7 +- .../vmp/service/impl/UserServiceImplTest.java | 12 +- web_src/src/components/channelList.vue | 4 +- 52 files changed, 571 insertions(+), 802 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java rename src/main/java/com/genersoft/iot/vmp/{conf/runner => gb28181/task}/SipDeviceRunner.java (54%) rename src/main/java/com/genersoft/iot/vmp/{gb28181 => }/utils/DateUtil.java (52%) 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 ef4492f8..eb98f6f2 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -47,8 +47,6 @@ public class VideoManagerConstants { 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_KEEPLIVE = "2"; public static final String EVENT_ONLINE_MESSAGE = "3"; 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 61809743..5f4ac22e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ApiAccessFilter.java @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.common.ApiSaveConstant; import com.genersoft.iot.vmp.conf.security.SecurityUtils; import com.genersoft.iot.vmp.service.ILogService; import com.genersoft.iot.vmp.storager.dao.dto.LogDto; +import com.genersoft.iot.vmp.utils.DateUtil; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -16,7 +17,6 @@ import javax.servlet.annotation.WebFilter; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; -import java.text.SimpleDateFormat; /** * @author lin @@ -26,7 +26,6 @@ public class ApiAccessFilter extends OncePerRequestFilter { private final static Logger logger = LoggerFactory.getLogger(ApiAccessFilter.class); - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @Autowired private UserSetting userSetting; @@ -58,7 +57,7 @@ public class ApiAccessFilter extends OncePerRequestFilter { logDto.setTiming(System.currentTimeMillis() - start); logDto.setType(servletRequest.getMethod()); logDto.setUri(servletRequest.getRequestURI()); - logDto.setCreateTime(format.format(System.currentTimeMillis())); + logDto.setCreateTime(DateUtil.getNow()); logService.add(logDto); // logger.warn("[Api Access] [{}] [{}] [{}] [{}] [{}] {}ms", // uriName, servletRequest.getMethod(), servletRequest.getRequestURI(), servletRequest.getRemoteAddr(), HttpStatus.valueOf(servletResponse.getStatus()), 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 052f5336..2812f92c 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -43,27 +43,27 @@ public class DynamicTask { * 循环执行的任务 * @param key 任务ID * @param task 任务 - * @param cycleForCatalog 间隔 + * @param cycleForCatalog 间隔 毫秒 * @return */ public void startCron(String key, Runnable task, int cycleForCatalog) { ScheduledFuture future = futureMap.get(key); if (future != null) { if (future.isCancelled()) { - logger.info("任务【{}】已存在但是关闭状态!!!", key); + logger.debug("任务【{}】已存在但是关闭状态!!!", key); } else { - logger.info("任务【{}】已存在且已启动!!!", key); + logger.debug("任务【{}】已存在且已启动!!!", key); return; } } // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 - future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog * 1000L); + future = threadPoolTaskScheduler.scheduleAtFixedRate(task, cycleForCatalog); if (future != null){ futureMap.put(key, future); runnableMap.put(key, task); - logger.info("任务【{}】启动成功!!!", key); + logger.debug("任务【{}】启动成功!!!", key); }else { - logger.info("任务【{}】启动失败!!!", key); + logger.debug("任务【{}】启动失败!!!", key); } } @@ -81,9 +81,9 @@ public class DynamicTask { ScheduledFuture future = futureMap.get(key); if (future != null) { if (future.isCancelled()) { - logger.info("任务【{}】已存在但是关闭状态!!!", key); + logger.debug("任务【{}】已存在但是关闭状态!!!", key); } else { - logger.info("任务【{}】已存在且已启动!!!", key); + logger.debug("任务【{}】已存在且已启动!!!", key); return; } } @@ -92,9 +92,9 @@ public class DynamicTask { if (future != null){ futureMap.put(key, future); runnableMap.put(key, task); - logger.info("任务【{}】启动成功!!!", key); + logger.debug("任务【{}】启动成功!!!", key); }else { - logger.info("任务【{}】启动失败!!!", key); + logger.debug("任务【{}】启动失败!!!", key); } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index bdd15034..85f46849 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -1,12 +1,11 @@ package com.genersoft.iot.vmp.conf; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.utils.DateUtil; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; -import java.text.SimpleDateFormat; -import java.util.Date; @Configuration("mediaConfig") public class MediaConfig{ @@ -206,9 +205,8 @@ public class MediaConfig{ mediaServerItem.setRecordAssistPort(recordAssistPort); mediaServerItem.setHookAliveInterval(120); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - mediaServerItem.setCreateTime(format.format(System.currentTimeMillis())); - mediaServerItem.setUpdateTime(format.format(System.currentTimeMillis())); + mediaServerItem.setCreateTime(DateUtil.getNow()); + mediaServerItem.setUpdateTime(DateUtil.getNow()); return mediaServerItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java index 71aed27f..7377702f 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ThreadPoolTaskConfig.java @@ -35,10 +35,11 @@ public class ThreadPoolTaskConfig { * 允许线程空闲时间(单位:默认为秒) */ private static final int keepAliveTime = 30; + /** * 缓冲队列大小 */ - private static final int queueCapacity = 500; + private static final int queueCapacity = 10000; /** * 线程池名前缀 */ 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 58772d9c..2b93d702 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -48,8 +48,15 @@ public class SipLayer{ Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); properties.setProperty("javax.sip.IP_ADDRESS", sipConfig.getMonitorIp()); + /** + * 完整配置参考 gov.nist.javax.sip.SipStackImpl,需要下载源码 + * gov/nist/javax/sip/SipStackImpl.class + */ properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true"); properties.setProperty("gov.nist.javax.sip.DELIVER_UNSOLICITED_NOTIFY", "true"); // 接收所有notify请求,即使没有订阅 + properties.setProperty("gov.nist.javax.sip.DELIVER_TERMINATED_EVENT_FOR_NULL_DIALOG", "true"); // 为_NULL _对话框传递_终止的_事件 + properties.setProperty("gov.nist.javax.sip.RELEASE_REFERENCES_STRATEGY", "Normal"); // 会话清理策略 + properties.setProperty("gov.nist.javax.sip.RELIABLE_CONNECTION_KEEP_ALIVE_TIMEOUT", "10"); /** * sip_server_log.log 和 sip_debug_log.log public static final int TRACE_NONE = * 0; public static final int TRACE_MESSAGES = 16; public static final int diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 81b96662..e8eab8c2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -99,11 +99,6 @@ public class Device { */ private String mediaServerId; - /** - * 首次注册 - */ - private boolean firsRegister; - /** * 字符集, 支持 UTF-8 与 GB2312 */ @@ -279,14 +274,6 @@ public class Device { this.mediaServerId = mediaServerId; } - public boolean isFirsRegister() { - return firsRegister; - } - - public void setFirsRegister(boolean firsRegister) { - this.firsRegister = firsRegister; - } - public String getCharset() { return charset; } 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 index ca7fd54c..3349cdc5 100644 --- 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,10 +1,10 @@ package com.genersoft.iot.vmp.gb28181.bean; +import com.genersoft.iot.vmp.utils.DateUtil; import org.jetbrains.annotations.NotNull; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; /** @@ -116,10 +116,9 @@ public class RecordItem implements Comparable{ @Override public int compareTo(@NotNull RecordItem recordItem) { - SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); try { - Date startTime_now = sdf.parse(startTime); - Date startTime_param = sdf.parse(recordItem.getStartTime()); + Date startTime_now = DateUtil.format.parse(startTime); + Date startTime_param = DateUtil.format.parse(recordItem.getStartTime()); if (startTime_param.compareTo(startTime_now) > 0) { return -1; }else { 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 index e804be28..2736be2d 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java @@ -61,7 +61,7 @@ public class SubscribeHolder { // 添加任务处理GPS定时推送 dynamicTask.startCron(key, new MobilePositionSubscribeHandlerTask(redisCatchStorage, sipCommanderForPlatform, storager, platformId, subscribeInfo.getSn(), key, this, dynamicTask), - subscribeInfo.getGpsInterval()); + subscribeInfo.getGpsInterval() * 1000); String taskOverdueKey = taskOverduePrefix + "MobilePosition_" + platformId; dynamicTask.stop(taskOverdueKey); // 添加任务处理订阅过期 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 index ffe477f0..eaf674fa 100644 --- 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,7 +1,7 @@ package com.genersoft.iot.vmp.gb28181.event; import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent; +import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformCycleRegisterEvent; import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; @@ -11,12 +11,11 @@ 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.scheduling.annotation.Async; import org.springframework.stereotype.Component; import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; -import com.genersoft.iot.vmp.gb28181.event.online.OnlineEvent; +import javax.sip.TimeoutEvent; import java.util.ArrayList; import java.util.HashSet; import java.util.List; @@ -32,28 +31,6 @@ public class EventPublisher { @Autowired private ApplicationEventPublisher applicationEventPublisher; - - public void onlineEventPublish(Device device, String from, int expires) { - OnlineEvent onEvent = new OnlineEvent(this); - onEvent.setDevice(device); - onEvent.setFrom(from); - onEvent.setExpires(expires); - applicationEventPublisher.publishEvent(onEvent); - } - - public void onlineEventPublish(Device device, String from) { - OnlineEvent onEvent = new OnlineEvent(this); - onEvent.setDevice(device); - onEvent.setFrom(from); - applicationEventPublisher.publishEvent(onEvent); - } - - public void outlineEventPublish(String deviceId, String from){ - OfflineEvent outEvent = new OfflineEvent(this); - outEvent.setDeviceId(deviceId); - outEvent.setFrom(from); - applicationEventPublisher.publishEvent(outEvent); - } /** * 平台心跳到期事件 @@ -115,6 +92,13 @@ public class EventPublisher { } + public void requestTimeOut(TimeoutEvent timeoutEvent) { + RequestTimeoutEvent requestTimeoutEvent = new RequestTimeoutEvent(this); + requestTimeoutEvent.setTimeoutEvent(timeoutEvent); + applicationEventPublisher.publishEvent(requestTimeoutEvent); + } + + /** * * @param platformId 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 new file mode 100644 index 00000000..c4d3baba --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEvent.java @@ -0,0 +1,25 @@ +package com.genersoft.iot.vmp.gb28181.event.device; + +import org.springframework.context.ApplicationEvent; + +import javax.sip.TimeoutEvent; + +/** + * @author lin + */ +public class RequestTimeoutEvent extends ApplicationEvent { + public RequestTimeoutEvent(Object source) { + super(source); + } + + + private TimeoutEvent timeoutEvent; + + public TimeoutEvent getTimeoutEvent() { + return timeoutEvent; + } + + public void setTimeoutEvent(TimeoutEvent timeoutEvent) { + this.timeoutEvent = timeoutEvent; + } +} 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 new file mode 100644 index 00000000..9382c2f6 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/device/RequestTimeoutEventImpl.java @@ -0,0 +1,41 @@ +package com.genersoft.iot.vmp.gb28181.event.device; + +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; +import com.genersoft.iot.vmp.service.IDeviceService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import javax.sip.ClientTransaction; +import javax.sip.address.SipURI; +import javax.sip.header.CallIdHeader; +import javax.sip.header.ToHeader; +import javax.sip.message.Request; + +/** + * @author lin + */ +@Component +public class RequestTimeoutEventImpl implements ApplicationListener { + + @Autowired + private IDeviceService deviceService; + + @Override + public void onApplicationEvent(RequestTimeoutEvent event) { + ClientTransaction clientTransaction = event.getTimeoutEvent().getClientTransaction(); + if (clientTransaction != null) { + Request request = clientTransaction.getRequest(); + if (request != null) { + String host = ((SipURI) request.getRequestURI()).getHost(); + int port = ((SipURI) request.getRequestURI()).getPort(); + Device device = deviceService.getDeviceByHostAndPort(host, port); + if (device == null) { + return; + } + deviceService.offline(device.getDeviceId()); + } + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java index ef78d371..8516fc78 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepaliveTimeoutListenerForPlatform.java @@ -17,9 +17,8 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; /** - * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 - * @author: swwheihei - * @date: 2020年5月6日 上午11:35:46 + * 设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 + * @author swwheihei */ @Component public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEventMessageListener { @@ -55,25 +54,18 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent // 平台心跳到期,需要重发, 判断是否已经多次未收到心跳回复, 多次未收到,则重新发起注册, 注册尝试多次未得到回复,则认为平台离线 String PLATFORM_KEEPLIVEKEY_PREFIX = VideoManagerConstants.PLATFORM_KEEPALIVE_PREFIX + userSetting.getServerId() + "_"; String PLATFORM_REGISTER_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_PREFIX + userSetting.getServerId() + "_"; - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_"; String REGISTER_INFO_PREFIX = VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_"; if (expiredKey.startsWith(PLATFORM_KEEPLIVEKEY_PREFIX)) { - String platformGBId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGBId); + String platformGbId = expiredKey.substring(PLATFORM_KEEPLIVEKEY_PREFIX.length()); + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); if (platform != null) { - publisher.platformKeepaliveExpireEventPublish(platformGBId); + publisher.platformKeepaliveExpireEventPublish(platformGbId); } }else if (expiredKey.startsWith(PLATFORM_REGISTER_PREFIX)) { - String platformGBId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length()); - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGBId); + String platformGbId = expiredKey.substring(PLATFORM_REGISTER_PREFIX.length(),expiredKey.length()); + ParentPlatform platform = storager.queryParentPlatByServerGBId(platformGbId); if (platform != null) { - publisher.platformRegisterCycleEventPublish(platformGBId); - } - }else if (expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){ - String deviceId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); - Device device = storager.queryVideoDevice(deviceId); - if (device != null) { - publisher.outlineEventPublish(deviceId, KEEPLIVEKEY_PREFIX); + publisher.platformRegisterCycleEventPublish(platformGbId); } }else if (expiredKey.startsWith(REGISTER_INFO_PREFIX)) { String callId = expiredKey.substring(REGISTER_INFO_PREFIX.length()); @@ -85,6 +77,5 @@ public class KeepaliveTimeoutListenerForPlatform extends RedisKeyExpirationEvent sipSubscribe.getErrorSubscribe(callId).response(eventResult); } } - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java deleted file mode 100644 index 9e8c6471..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/KeepliveTimeoutListener.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.event.offline; - -import com.genersoft.iot.vmp.conf.RedisKeyExpirationEventMessageListener; -import com.genersoft.iot.vmp.conf.UserSetting; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.data.redis.connection.Message; -import org.springframework.data.redis.listener.RedisMessageListenerContainer; -import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; - -/** - * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 - * @author: swwheihei - * @date: 2020年5月6日 上午11:35:46 - */ -@Component -public class KeepliveTimeoutListener extends RedisKeyExpirationEventMessageListener { - - private Logger logger = LoggerFactory.getLogger(KeepliveTimeoutListener.class); - - @Autowired - private EventPublisher publisher; - - @Autowired - private UserSetting userSetting; - - public KeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer, UserSetting userSetting) { - super(listenerContainer, userSetting); - } - - @Override - public void init() { - if (!userSetting.getRedisConfig()) { - // 配置springboot默认Config为空,即不让应用去修改redis的默认配置,因为Redis服务出于安全会禁用CONFIG命令给远程用户使用 - setKeyspaceNotificationsConfigParameter(""); - } - super.init(); - } - - - /** - * 监听失效的key,key格式为keeplive_deviceId - * @param message - * @param pattern - */ - @Override - public void onMessage(Message message, byte[] pattern) { - // 获取失效的key - String expiredKey = message.toString(); - String KEEPLIVEKEY_PREFIX = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_"; - if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){ - logger.debug("收到redis过期监听,但开头不是"+KEEPLIVEKEY_PREFIX+",忽略"); - return; - } - - String deviceId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); - publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_TIMEOUT); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java deleted file mode 100644 index 9dfeffca..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEvent.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.event.offline; - -import org.springframework.context.ApplicationEvent; - -/** - * @description: 离线事件类 - * @author: swwheihei - * @date: 2020年5月6日 上午11:33:13 - */ -public class OfflineEvent extends ApplicationEvent { - - /** - * - */ - private static final long serialVersionUID = 1L; - - public OfflineEvent(Object source) { - super(source); - } - - private String deviceId; - - private String from; - - public String getDeviceId() { - return deviceId; - } - - public void setDeviceId(String deviceId) { - this.deviceId = deviceId; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java deleted file mode 100644 index 46332566..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/offline/OfflineEventListener.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.event.offline; - -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; -import com.genersoft.iot.vmp.service.IMediaServerService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; - -import java.util.List; - -/** - * @description: 离线事件监听器,监听到离线后,修改设备离在线状态。 设备离线有两个来源: - * 1、设备主动注销,发送注销指令,{@link com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor} - * 2、设备未知原因离线,心跳超时,{@link com.genersoft.iot.vmp.gb28181.event.offline.OfflineEventListener} - * @author: swwheihei - * @date: 2020年5月6日 下午1:51:23 - */ -@Component -public class OfflineEventListener implements ApplicationListener { - - private final static Logger logger = LoggerFactory.getLogger(OfflineEventListener.class); - - @Autowired - private IVideoManagerStorage storager; - - @Autowired - private VideoStreamSessionManager streamSession; - - @Autowired - private RedisUtil redis; - - @Autowired - private UserSetting userSetting; - - @Autowired - private EventPublisher eventPublisher; - - - @Autowired - private IMediaServerService mediaServerService; - - - @Autowired - private ZLMRTPServerFactory zlmrtpServerFactory; - - @Override - public void onApplicationEvent(OfflineEvent event) { - - logger.info("设备离线事件触发,deviceId:" + event.getDeviceId() + ",from:" + event.getFrom()); - - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDeviceId(); - - switch (event.getFrom()) { - // 心跳超时触发的离线事件,说明redis中已删除,无需处理 - case VideoManagerConstants.EVENT_OUTLINE_TIMEOUT: - break; - // 设备主动注销触发的离线事件,需要删除redis中的超时监听 - case VideoManagerConstants.EVENT_OUTLINE_UNREGISTER: - redis.del(key); - break; - default: - boolean exist = redis.hasKey(key); - if (exist) { - redis.del(key); - } - } - - List deviceChannelList = storager.queryOnlineChannelsByDeviceId(event.getDeviceId()); - eventPublisher.catalogEventPublish(null, deviceChannelList, CatalogEvent.OFF); - // 处理离线监听 - storager.outline(event.getDeviceId()); - - // TODO 离线取消订阅 - - // 离线释放所有ssrc - List ssrcTransactions = streamSession.getSsrcTransactionForAll(event.getDeviceId(), null, null, null); - if (ssrcTransactions != null && ssrcTransactions.size() > 0) { - for (SsrcTransaction ssrcTransaction : ssrcTransactions) { - mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); - mediaServerService.closeRTPServer(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); - streamSession.remove(event.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); - } - } - - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java deleted file mode 100644 index 9aa9f8d7..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEvent.java +++ /dev/null @@ -1,51 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.event.online; - -import com.genersoft.iot.vmp.gb28181.bean.Device; -import org.springframework.context.ApplicationEvent; - -/** - * @description: 在线事件类 - * @author: swwheihei - * @date: 2020年5月6日 上午11:32:56 - */ -public class OnlineEvent extends ApplicationEvent { - - /** - * - */ - private static final long serialVersionUID = 1L; - - public OnlineEvent(Object source) { - super(source); - } - - private Device device; - - private String from; - - private int expires; - - public Device getDevice() { - return device; - } - - public void setDevice(Device device) { - this.device = device; - } - - public String getFrom() { - return from; - } - - public void setFrom(String from) { - this.from = from; - } - - public int getExpires() { - return expires; - } - - public void setExpires(int expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java deleted file mode 100644 index f32637e5..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/online/OnlineEventListener.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.event.online; - -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.service.IDeviceService; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; -import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; - -import java.text.SimpleDateFormat; -import java.util.List; - -/** - * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: - * 1、设备主动注销,发送注销指令 - * 2、设备未知原因离线,心跳超时 - * @author: swwheihei - * @date: 2020年5月6日 下午1:51:23 - */ -@Component -public class OnlineEventListener implements ApplicationListener { - - private final static Logger logger = LoggerFactory.getLogger(OnlineEventListener.class); - - @Autowired - private IVideoManagerStorage storager; - - @Autowired - private IDeviceService deviceService; - - @Autowired - private RedisUtil redis; - - @Autowired - private SipConfig sipConfig; - - @Autowired - private UserSetting userSetting; - - @Autowired - private EventPublisher eventPublisher; - - @Autowired - private SIPCommander cmder; - - - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - @Override - public void onApplicationEvent(OnlineEvent event) { - - logger.info("设备上线事件触发,deviceId:" + event.getDevice().getDeviceId() + ",from:" + event.getFrom()); - Device device = event.getDevice(); - if (device == null) { - return; - } - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + event.getDevice().getDeviceId(); - Device deviceInStore = storager.queryVideoDevice(device.getDeviceId()); - device.setOnline(1); - switch (event.getFrom()) { - // 注册时触发的在线事件,先在redis中增加超时超时监听 - case VideoManagerConstants.EVENT_ONLINE_REGISTER: - // 超时时间 - redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut()); - device.setRegisterTime(format.format(System.currentTimeMillis())); - if (deviceInStore == null) { //第一次上线 - logger.info("[{}] 首次注册,查询设备信息以及通道信息", device.getDeviceId()); - cmder.deviceInfoQuery(device); - deviceService.sync(device); - } - break; - // 设备主动发送心跳触发的在线事件 - case VideoManagerConstants.EVENT_ONLINE_KEEPLIVE: - boolean exist = redis.hasKey(key); - // 先判断是否还存在,当设备先心跳超时后又发送心跳时,redis没有监听,需要增加 - if (!exist) { - redis.set(key, event.getDevice().getDeviceId(), sipConfig.getKeepaliveTimeOut()); - } else { - redis.expire(key, sipConfig.getKeepaliveTimeOut()); - } - device.setKeepaliveTime(format.format(System.currentTimeMillis())); - break; - // 设备主动发送消息触发的在线事件 - case VideoManagerConstants.EVENT_ONLINE_MESSAGE: - - break; - } - // 处理上线监听 - storager.updateDevice(device); - // 上线添加订阅 - if (device.getSubscribeCycleForCatalog() > 0) { - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅 - deviceService.addCatalogSubscribe(device); - } - if (device.getSubscribeCycleForMobilePosition() > 0) { - deviceService.addMobilePositionSubscribe(device); - } - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipDeviceRunner.java similarity index 54% rename from src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java rename to src/main/java/com/genersoft/iot/vmp/gb28181/task/SipDeviceRunner.java index 4a897968..91d8c3da 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/runner/SipDeviceRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipDeviceRunner.java @@ -1,4 +1,4 @@ -package com.genersoft.iot.vmp.conf.runner; +package com.genersoft.iot.vmp.gb28181.task; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -10,11 +10,13 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import java.util.ArrayList; import java.util.List; /** * 系统启动时控制设备 + * @author lin */ @Component @Order(value=4) @@ -34,26 +36,16 @@ public class SipDeviceRunner implements CommandLineRunner { @Override public void run(String... args) throws Exception { - // 读取redis没有心跳信息的则设置为离线,等收到下次心跳设置为在线 - // 设置所有设备离线 - storager.outlineForAll(); - List onlineForAll = redisCatchStorage.getOnlineForAll(); - for (String deviceId : onlineForAll) { - storager.online(deviceId); - Device device = redisCatchStorage.getDevice(deviceId); - if (device != null ) { - if (device.getSubscribeCycleForCatalog() > 0) { - // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅 - deviceService.addCatalogSubscribe(device); - } - if (device.getSubscribeCycleForMobilePosition() > 0) { - deviceService.addMobilePositionSubscribe(device); - } + List deviceList = deviceService.getAllOnlineDevice(); + + for (Device device : deviceList) { + if (deviceService.expire(device)){ + deviceService.offline(device.getDeviceId()); + }else { + deviceService.online(device); } } // 重置cseq计数 redisCatchStorage.resetAllCSEQ(); - - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java index a9c9089c..a06a73d0 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java @@ -1,7 +1,10 @@ package com.genersoft.iot.vmp.gb28181.transmit; +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.RegisterRequestProcessor; +import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd.KeepaliveNotifyMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.response.ISIPResponseProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.timeout.ITimeoutProcessor; import org.slf4j.Logger; @@ -11,10 +14,13 @@ import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import javax.sip.*; -import javax.sip.header.CSeqHeader; -import javax.sip.header.CallIdHeader; +import javax.sip.address.SipURI; +import javax.sip.address.URI; +import javax.sip.header.*; +import javax.sip.message.Request; import javax.sip.message.Response; import java.util.Map; +import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; /** @@ -34,10 +40,11 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { @Autowired private SipSubscribe sipSubscribe; + @Autowired + private EventPublisher eventPublisher; + + -// @Autowired -// @Qualifier(value = "taskExecutor") -// private ThreadPoolTaskExecutor poolTaskExecutor; /** * 添加 request订阅 @@ -141,9 +148,32 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { */ @Override public void processTimeout(TimeoutEvent timeoutEvent) { - if(timeoutProcessor != null) { - timeoutProcessor.process(timeoutEvent); + logger.info("[消息发送超时]"); + ClientTransaction clientTransaction = timeoutEvent.getClientTransaction(); + eventPublisher.requestTimeOut(timeoutEvent); + if (clientTransaction != null) { + Request request = clientTransaction.getRequest(); + if (request != null) { + CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); + if (callIdHeader != null) { + SipSubscribe.Event subscribe = sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()); + SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(timeoutEvent); + subscribe.response(eventResult); + sipSubscribe.removeErrorSubscribe(callIdHeader.getCallId()); + } + } } + +// Timeout timeout = timeoutEvent.getTimeout(); +// ServerTransaction serverTransaction = timeoutEvent.getServerTransaction(); +// if (serverTransaction != null) { +// Request request = serverTransaction.getRequest(); +// URI requestURI = request.getRequestURI(); +// Header header = request.getHeader(FromHeader.NAME); +// } +// if(timeoutProcessor != null) { +// timeoutProcessor.process(timeoutEvent); +// } } @Override 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 index ea8f2025..567bcac7 100644 --- 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 @@ -10,7 +10,7 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; @@ -27,7 +27,6 @@ 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.boot.SpringBootVersion; import org.springframework.context.annotation.DependsOn; import org.springframework.stereotype.Component; import org.springframework.util.StringUtils; 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 index 2aafd98d..a4fd5079 100644 --- 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 @@ -4,7 +4,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.service.IMediaServerService; 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 index bb46a71c..1ba1b3e7 100644 --- 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 @@ -23,6 +23,7 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.SSRCInfo; 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.utils.SerializeUtils; import gov.nist.javax.sdp.TimeDescriptionImpl; import gov.nist.javax.sdp.fields.TimeField; @@ -39,7 +40,6 @@ import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import javax.sip.message.Response; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Date; import java.util.Vector; @@ -335,9 +335,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements sendRtpItem.setStreamId(ssrcInfo.getStream()); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, format.format(start), - format.format(end), null, result -> { + playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.format.format(start), + DateUtil.format.format(end), null, result -> { if (result.getCode() != 0){ logger.warn("录像回放失败"); if (result.getEvent() != null) { 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 index 98cb3aa9..e923a54a 100644 --- 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 @@ -252,14 +252,12 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); - Element rootElement = getRootElement(evt); Device device = redisCatchStorage.getDevice(deviceId); - if (device == null) { + if (device == null || device.getOnline() == 0) { + logger.warn("[收到 目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" )); return; } - if (device != null ) { - rootElement = getRootElement(evt, device.getCharset()); - } + Element rootElement = getRootElement(evt, device.getCharset()); Element deviceListElement = rootElement.element("DeviceList"); if (deviceListElement == null) { return; @@ -279,39 +277,46 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements channel.setDeviceId(device.getDeviceId()); logger.info("[收到 目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); switch (eventElement.getText().toUpperCase()) { - case CatalogEvent.ON: // 上线 + case CatalogEvent.ON: + // 上线 logger.info("收到来自设备【{}】的通道【{}】上线通知", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOnline(deviceId, channel.getChannelId()); // 回复200 OK responseAck(evt, Response.OK); break; - case CatalogEvent.OFF : // 离线 + case CatalogEvent.OFF : + // 离线 logger.info("收到来自设备【{}】的通道【{}】离线通知", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOffline(deviceId, channel.getChannelId()); // 回复200 OK responseAck(evt, Response.OK); break; - case CatalogEvent.VLOST: // 视频丢失 + case CatalogEvent.VLOST: + // 视频丢失 logger.info("收到来自设备【{}】的通道【{}】视频丢失通知", device.getDeviceId(), channel.getChannelId()); storager.deviceChannelOffline(deviceId, channel.getChannelId()); // 回复200 OK responseAck(evt, Response.OK); break; - case CatalogEvent.DEFECT: // 故障 + case CatalogEvent.DEFECT: + // 故障 // 回复200 OK responseAck(evt, Response.OK); break; - case CatalogEvent.ADD: // 增加 + case CatalogEvent.ADD: + // 增加 logger.info("收到来自设备【{}】的增加通道【{}】通知", device.getDeviceId(), channel.getChannelId()); storager.updateChannel(deviceId, channel); responseAck(evt, Response.OK); break; - case CatalogEvent.DEL: // 删除 + case CatalogEvent.DEL: + // 删除 logger.info("收到来自设备【{}】的删除通道【{}】通知", device.getDeviceId(), channel.getChannelId()); storager.delChannel(deviceId, channel.getChannelId()); responseAck(evt, Response.OK); break; - case CatalogEvent.UPDATE: // 更新 + case CatalogEvent.UPDATE: + // 更新 logger.info("收到来自设备【{}】的更新通道【{}】通知", device.getDeviceId(), channel.getChannelId()); storager.updateChannel(deviceId, channel); responseAck(evt, Response.OK); @@ -324,10 +329,6 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements eventPublisher.catalogEventPublish(null, channel, eventElement.getText().toUpperCase()); } - - if (!redisCatchStorage.deviceIsOnline(deviceId)) { - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); - } } } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { e.printStackTrace(); 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 index ce5ca439..4f5f96a7 100644 --- 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 @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; 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.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import gov.nist.javax.sip.RequestEventExt; @@ -60,6 +61,9 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @Autowired private SIPProcessorObserver sipProcessorObserver; + @Autowired + private IDeviceService deviceService; + @Override public void afterPropertiesSet() throws Exception { // 添加消息处理的订阅 @@ -82,7 +86,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen Response response = null; boolean passwordCorrect = false; // 注册标志 0:未携带授权头或者密码错误 1:注册成功 2:注销成功 - int registerFlag = 0; + boolean registerFlag = false; FromHeader fromHeader = (FromHeader) request.getHeader(FromHeader.NAME); AddressImpl address = (AddressImpl) fromHeader.getAddress(); SipUri uri = (SipUri) address.getURI(); @@ -111,12 +115,8 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen return; } - Device deviceInRedis = redisCatchStorage.getDevice(deviceId); - Device device = storager.queryVideoDevice(deviceId); - if (deviceInRedis != null && device == null) { - // redis 存在脏数据 - redisCatchStorage.clearCatchByDeviceId(deviceId); - } + Device device = deviceService.queryDevice(deviceId); + // 携带授权头并且密码正确 response = getMessageFactory().createResponse(Response.OK, request); // 添加date头 @@ -154,20 +154,17 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen device.setStreamMode("UDP"); device.setCharset("GB2312"); device.setDeviceId(deviceId); - device.setFirsRegister(true); - } else { - device.setFirsRegister(device.getOnline() == 0); } device.setIp(received); device.setPort(rPort); device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); if (expiresHeader.getExpires() == 0) { // 注销成功 - registerFlag = 2; + registerFlag = false; } else { // 注册成功 device.setExpires(expiresHeader.getExpires()); - registerFlag = 1; + registerFlag = true; // 判断TCP还是UDP ViaHeader reqViaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME); String transport = reqViaHeader.getTransport(); @@ -177,12 +174,12 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen sendResponse(evt, response); // 注册成功 // 保存到redis - if (registerFlag == 1) { + if (registerFlag) { logger.info("[{}] 注册成功! deviceId:" + deviceId, requestAddress); - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_REGISTER, expiresHeader.getExpires()); - } else if (registerFlag == 2) { + deviceService.online(device); + } else { logger.info("[{}] 注销成功! deviceId:" + deviceId, requestAddress); - publisher.outlineEventPublish(deviceId, VideoManagerConstants.EVENT_OUTLINE_UNREGISTER); + deviceService.offline(deviceId); } } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { e.printStackTrace(); 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 index 08a77518..56a4c49b 100644 --- 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 @@ -1,14 +1,15 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; -import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; +import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; import org.dom4j.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -23,24 +24,20 @@ import javax.sip.SipException; import javax.sip.header.ViaHeader; import javax.sip.message.Response; import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; @Component public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { private Logger logger = LoggerFactory.getLogger(KeepaliveNotifyMessageHandler.class); - private final String cmdType = "Keepalive"; + private final static String cmdType = "Keepalive"; @Autowired private NotifyMessageHandler notifyMessageHandler; @Autowired - private EventPublisher publisher; - - @Autowired - private IVideoManagerStorage videoManagerStorager; - - @Autowired - private IRedisCatchStorage redisCatchStorage; + private IDeviceService deviceService; @Override public void afterPropertiesSet() throws Exception { @@ -49,29 +46,35 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @Override public void handForDevice(RequestEvent evt, Device device, Element element) { - // 检查设备是否存在并在线, 不在线则设置为在线 + if (device == null) { + // 未注册的设备不做处理 + return; + } try { - if (device != null ) { + if (device.getOnline() == 1) { // 回复200 OK responseAck(evt, Response.OK); - // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 - // 获取到通信地址等信息 - ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); - String received = viaHeader.getReceived(); - int rPort = viaHeader.getRPort(); - // 解析本地地址替代 - if (StringUtils.isEmpty(received) || rPort == -1) { - received = viaHeader.getHost(); - rPort = viaHeader.getPort(); - } - if (device.getPort() != rPort) { - device.setPort(rPort); - device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); - videoManagerStorager.updateDevice(device); - redisCatchStorage.updateDevice(device); - } - if (!redisCatchStorage.deviceIsOnline(device.getDeviceId())) { - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_KEEPLIVE); + }else { + // 对于已经离线的设备判断他的注册是否已经过期 + if (!deviceService.expire(device)){ + device.setKeepaliveTime(DateUtil.getNow()); + // 判断RPort是否改变,改变则说明路由nat信息变化,修改设备信息 + // 获取到通信地址等信息 + ViaHeader viaHeader = (ViaHeader) evt.getRequest().getHeader(ViaHeader.NAME); + String received = viaHeader.getReceived(); + int rPort = viaHeader.getRPort(); + // 解析本地地址替代 + if (StringUtils.isEmpty(received) || rPort == -1) { + received = viaHeader.getHost(); + rPort = viaHeader.getPort(); + } + if (device.getPort() != rPort) { + device.setPort(rPort); + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); + } + deviceService.online(device); + // 回复200 OK + responseAck(evt, Response.OK); } } } catch (SipException e) { 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 index efd6ffdf..4b6c9026 100644 --- 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 @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.query.QueryMessageHandler; -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; import org.dom4j.Element; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/CatalogResponseMessageHandler.java index 56b42caf..891b21da 100644 --- 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 @@ -28,7 +28,6 @@ import javax.sip.RequestEvent; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -39,8 +38,6 @@ public class CatalogResponseMessageHandler extends SIPRequestProcessorParent imp private Logger logger = LoggerFactory.getLogger(CatalogResponseMessageHandler.class); private final String cmdType = "Catalog"; - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @Autowired private ResponseMessageHandler responseMessageHandler; 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 index 276be490..639d4d91 100644 --- 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 @@ -29,6 +29,9 @@ import java.text.ParseException; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; +/** + * @author lin + */ @Component public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -61,6 +64,11 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @Override public void handForDevice(RequestEvent evt, Device device, Element rootElement) { logger.debug("接收到DeviceInfo应答消息"); + // 检查设备是否存在, 不存在则不回复 + if (device == null || device.getOnline() == 0) { + logger.warn("[接收到DeviceInfo应答消息,但是设备已经离线]:" + (device != null ? device.getDeviceId():"" )); + return; + } try { rootElement = getRootElement(evt, device.getCharset()); Element deviceIdElement = rootElement.element("DeviceID"); @@ -82,9 +90,6 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent deferredResultHolder.invokeAllResult(msg); // 回复200 OK responseAck(evt, Response.OK); - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); - } } catch (DocumentException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { 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 index 4e2f7f74..1fed401a 100644 --- 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 @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import org.dom4j.Element; import org.slf4j.Logger; @@ -24,6 +25,7 @@ import javax.sip.RequestEvent; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; +import java.util.Objects; @Component public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -34,12 +36,11 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen @Autowired private ResponseMessageHandler responseMessageHandler; - @Autowired private DeferredResultHolder deferredResultHolder; @Autowired - private EventPublisher publisher; + private IDeviceService deviceService; @Autowired private IRedisCatchStorage redisCatchStorage; @@ -53,6 +54,9 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen public void handForDevice(RequestEvent evt, Device device, Element element) { logger.info("接收到DeviceStatus应答消息"); // 检查设备是否存在, 不存在则不回复 + if (device == null) { + return; + } // 回复200 OK try { responseAck(evt, Response.OK); @@ -64,20 +68,23 @@ public class DeviceStatusResponseMessageHandler extends SIPRequestProcessorParen e.printStackTrace(); } Element deviceIdElement = element.element("DeviceID"); + Element onlineElement = element.element("Online"); String channelId = deviceIdElement.getText(); JSONObject json = new JSONObject(); XmlUtil.node2Json(element, json); if (logger.isDebugEnabled()) { logger.debug(json.toJSONString()); } + String text = onlineElement.getText(); + if (Objects.equals(text.trim().toUpperCase(), "ONLINE")) { + deviceService.online(device); + }else { + deviceService.offline(device.getDeviceId()); + } RequestMessage msg = new RequestMessage(); msg.setKey(DeferredResultHolder.CALLBACK_CMD_DEVICESTATUS + device.getDeviceId() + channelId); msg.setData(json); deferredResultHolder.invokeAllResult(msg); - - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { - publisher.onlineEventPublish(device, VideoManagerConstants.EVENT_ONLINE_MESSAGE); - } } @Override 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 index 1c9ec21b..36626004 100644 --- 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 @@ -20,7 +20,6 @@ import javax.sip.RequestEvent; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -33,8 +32,6 @@ public class PresetQueryResponseMessageHandler extends SIPRequestProcessorParent private Logger logger = LoggerFactory.getLogger(PresetQueryResponseMessageHandler.class); private final String cmdType = "PresetQuery"; - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @Autowired private ResponseMessageHandler responseMessageHandler; 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 index 45b7e56b..2de8ef16 100644 --- 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 @@ -11,7 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import org.dom4j.DocumentException; import org.dom4j.Element; 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 index 12829e90..02612093 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -55,9 +55,6 @@ public class ZLMRunner implements CommandLineRunner { @Autowired private DynamicTask dynamicTask; - @Qualifier("taskExecutor") - @Autowired - private ThreadPoolTaskExecutor taskExecutor; @Override public void run(String... strings) throws Exception { @@ -105,9 +102,7 @@ public class ZLMRunner implements CommandLineRunner { startGetMedia = new HashMap<>(); } startGetMedia.put(mediaServerItem.getId(), true); - taskExecutor.execute(()->{ - connectZlmServer(mediaServerItem); - }); + connectZlmServer(mediaServerItem); } String taskKey = "zlm-connect-timeout"; dynamicTask.startDelay(taskKey, ()->{ @@ -119,21 +114,37 @@ public class ZLMRunner implements CommandLineRunner { startGetMedia = null; } // TODO 清理数据库中与redis不匹配的zlm - }, 6 * 1000 ); + }, 60 * 1000 ); } @Async public void connectZlmServer(MediaServerItem mediaServerItem){ - ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem, 1); - if (zlmServerConfig != null) { - zlmServerConfig.setIp(mediaServerItem.getIp()); - zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); + String connectZlmServerTaskKey = "connect-zlm-" + mediaServerItem.getId(); + ZLMServerConfig zlmServerConfigFirst = getMediaServerConfig(mediaServerItem); + if (zlmServerConfigFirst != null) { + zlmServerConfigFirst.setIp(mediaServerItem.getIp()); + zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort()); startGetMedia.remove(mediaServerItem.getId()); - mediaServerService.zlmServerOnline(zlmServerConfig); + mediaServerService.zlmServerOnline(zlmServerConfigFirst); + }else { + logger.info("[ {} ]-[ {}:{} ]主动连接失败, 清理相关资源, 开始尝试重试连接", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + publisher.zlmOfflineEventPublish(mediaServerItem.getId()); } + + dynamicTask.startCron(connectZlmServerTaskKey, ()->{ + ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem); + if (zlmServerConfig != null) { + dynamicTask.stop(connectZlmServerTaskKey); + zlmServerConfig.setIp(mediaServerItem.getIp()); + zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); + startGetMedia.remove(mediaServerItem.getId()); + mediaServerService.zlmServerOnline(zlmServerConfig); + } + }, 2000); } - public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem, int index) { + public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) { if (startGetMedia == null) { return null;} if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) { return null; @@ -149,53 +160,10 @@ public class ZLMRunner implements CommandLineRunner { zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); } } else { - logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index); - if (index == 1 && !StringUtils.isEmpty(mediaServerItem.getId())) { - logger.info("[ {} ]-[ {}:{} ]第{}次主动连接失败, 开始清理相关资源", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index); - publisher.zlmOfflineEventPublish(mediaServerItem.getId()); - } - try { - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - zlmServerConfig = getMediaServerConfig(mediaServerItem, index += 1); + logger.error("[ {} ]-[ {}:{} ]主动连接失败, 2s后重试", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } return zlmServerConfig; } - - /** - * zlm 连接成功或者zlm重启后 - */ -// private void zLmRunning(ZLMServerConfig zlmServerConfig){ -// logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm接入成功..."); -// // 关闭循环获取zlm配置 -// startGetMedia = false; -// MediaServerItem mediaServerItem = new MediaServerItem(zlmServerConfig, sipIp); -// storager.updateMediaServer(mediaServerItem); -// -// if (mediaServerItem.isAutoConfig()) setZLMConfig(mediaServerItem); -// zlmServerManger.updateServerCatchFromHook(zlmServerConfig); -// -// // 清空所有session -//// zlmMediaListManager.clearAllSessions(); -// -// // 更新流列表 -// zlmMediaListManager.updateMediaList(mediaServerItem); -// // 恢复流代理, 只查找这个这个流媒体 -// List streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer( -// mediaServerItem.getId(), true); -// for (StreamProxyItem streamProxyDto : streamProxyListForEnable) { -// logger.info("恢复流代理," + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); -// JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto); -// if (jsonObject == null) { -// // 设置为未启用 -// logger.info("恢复流代理失败,请检查流地址后重新启用" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); -// streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream()); -// } -// } -// } } 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 index ca6fdfe4..b193add9 100644 --- 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 @@ -7,12 +7,10 @@ import com.genersoft.iot.vmp.service.IStreamPushService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationListener; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; -import java.text.SimpleDateFormat; /** * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: @@ -38,13 +36,11 @@ public class ZLMStatusEventListener { @Autowired private IPlayService playService; - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @Async @EventListener public void onApplicationEvent(ZLMOnlineEvent event) { - logger.info("ZLM上线事件触发,ID:" + event.getMediaServerId()); + logger.info("【ZLM上线】ID:" + event.getMediaServerId()); streamPushService.zlmServerOnline(event.getMediaServerId()); streamProxyService.zlmServerOnline(event.getMediaServerId()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java index 5621d2aa..a7c52ba7 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java @@ -3,56 +3,105 @@ package com.genersoft.iot.vmp.service; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; +import java.util.List; + /** * 设备相关业务处理 + * @author lin */ public interface IDeviceService { + /** + * 设备上线 + * @param device 设备信息 + */ + void online(Device device); + + /** + * 设备下线 + * @param deviceId 设备编号 + */ + void offline(String deviceId); + /** * 添加目录订阅 * @param device 设备信息 - * @return + * @return 布尔 */ boolean addCatalogSubscribe(Device device); /** * 移除目录订阅 * @param device 设备信息 - * @return + * @return 布尔 */ boolean removeCatalogSubscribe(Device device); /** * 添加移动位置订阅 * @param device 设备信息 - * @return + * @return 布尔 */ boolean addMobilePositionSubscribe(Device device); /** * 移除移动位置订阅 * @param device 设备信息 - * @return + * @return 布尔 */ boolean removeMobilePositionSubscribe(Device device); /** * 移除移动位置订阅 * @param deviceId 设备ID - * @return + * @return 同步状态 */ SyncStatus getChannelSyncStatus(String deviceId); /** * 查看是否仍在同步 * @param deviceId 设备ID - * @return + * @return 布尔 */ Boolean isSyncRunning(String deviceId); /** * 通道同步 - * @param device + * @param device 设备信息 */ void sync(Device device); + + /** + * 查询设备信息 + * @param deviceId 设备编号 + * @return 设备信息 + */ + Device queryDevice(String deviceId); + + /** + * 获取所有在线设备 + * @return 设备列表 + */ + List getAllOnlineDevice(); + + /** + * 判断是否注册已经失效 + * @param device 设备信息 + * @return 布尔 + */ + boolean expire(Device device); + + /** + * 检查设备状态 + * @param device 设备信息 + */ + void checkDeviceStatus(Device device); + + /** + * 根据IP和端口获取设备信息 + * @param host IP + * @param port 端口 + * @return 设备信息 + */ + Device getDeviceByHostAndPort(String host, int port); } 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 index 39a59f80..ce211c3b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -2,13 +2,19 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.dao.DeviceMapper; +import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,6 +23,11 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import javax.sip.DialogState; +import javax.sip.TimeoutEvent; +import java.text.ParseException; +import java.util.Calendar; +import java.util.Date; +import java.util.List; /** * 设备业务(目录订阅) @@ -26,6 +37,8 @@ public class DeviceServiceImpl implements IDeviceService { private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); + private final String registerExpireTaskKeyPrefix = "device-register-expire-"; + @Autowired private DynamicTask dynamicTask; @@ -38,6 +51,84 @@ public class DeviceServiceImpl implements IDeviceService { @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private DeviceMapper deviceMapper; + + @Autowired + private ISIPCommander commander; + + @Autowired + private VideoStreamSessionManager streamSession; + + @Autowired + private IMediaServerService mediaServerService; + + @Override + public void online(Device device) { + logger.info("[设备上线],deviceId:" + device.getDeviceId()); + Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId()); + Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); + + String now = DateUtil.getNow(); + if (deviceInRedis != null && deviceInDb == null) { + // redis 存在脏数据 + redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); + device.setCreateTime(now); + } + device.setOnline(1); + device.setRegisterTime(now); + + // 第一次上线 + if (device.getCreateTime() == null) { + logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); + commander.deviceInfoQuery(device); + sync(device); + deviceMapper.add(device); + }else { + deviceMapper.update(device); + } + redisCatchStorage.updateDevice(device); + // 上线添加订阅 + if (device.getSubscribeCycleForCatalog() > 0) { + // 查询在线设备那些开启了订阅,为设备开启定时的目录订阅 + addCatalogSubscribe(device); + } + if (device.getSubscribeCycleForMobilePosition() > 0) { + addMobilePositionSubscribe(device); + } + // 刷新过期任务 + String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); + dynamicTask.stop(registerExpireTaskKey); + dynamicTask.startDelay(registerExpireTaskKey, ()->{ + offline(device.getDeviceId()); + }, device.getExpires() * 1000); + } + + @Override + public void offline(String deviceId) { + Device device = deviceMapper.getDeviceByDeviceId(deviceId); + if (device == null) { + return; + } + String registerExpireTaskKey = registerExpireTaskKeyPrefix + deviceId; + dynamicTask.stop(registerExpireTaskKey); + device.setOnline(0); + redisCatchStorage.updateDevice(device); + deviceMapper.update(device); + // 离线释放所有ssrc + List ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null); + if (ssrcTransactions != null && ssrcTransactions.size() > 0) { + for (SsrcTransaction ssrcTransaction : ssrcTransactions) { + mediaServerService.releaseSsrc(ssrcTransaction.getMediaServerId(), ssrcTransaction.getSsrc()); + mediaServerService.closeRTPServer(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); + streamSession.remove(deviceId, ssrcTransaction.getChannelId(), ssrcTransaction.getStream()); + } + } + // 移除订阅 + removeCatalogSubscribe(device); + removeMobilePositionSubscribe(device); + } + @Override public boolean addCatalogSubscribe(Device device) { if (device == null || device.getSubscribeCycleForCatalog() < 0) { @@ -49,7 +140,7 @@ public class DeviceServiceImpl implements IDeviceService { // 提前开始刷新订阅 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForCatalog(),30); // 设置最小值为30 - dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, subscribeCycleForCatalog -1); + dynamicTask.startCron(device.getDeviceId() + "catalog", catalogSubscribeTask, (subscribeCycleForCatalog -1) * 1000); return true; } @@ -74,7 +165,7 @@ public class DeviceServiceImpl implements IDeviceService { // 设置最小值为30 int subscribeCycleForCatalog = Math.max(device.getSubscribeCycleForMobilePosition(),30); // 提前开始刷新订阅 - dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, subscribeCycleForCatalog -1 ); + dynamicTask.startCron(device.getDeviceId() + "mobile_position" , mobilePositionSubscribeTask, (subscribeCycleForCatalog -1 ) * 1000); return true; } @@ -111,4 +202,44 @@ public class DeviceServiceImpl implements IDeviceService { catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(), errorMsg); }); } + + @Override + public Device queryDevice(String deviceId) { + return deviceMapper.getDeviceByDeviceId(deviceId); + } + + @Override + public List getAllOnlineDevice() { + return deviceMapper.getOnlineDevices(); + } + + @Override + public boolean expire(Device device) { + Date registerTimeDate; + try { + registerTimeDate = DateUtil.format.parse(device.getRegisterTime()); + } catch (ParseException e) { + logger.error("设备时间格式化失败:{}->{} ", device.getDeviceId(), device.getRegisterTime() ); + return false; + } + int expires = device.getExpires(); + Calendar calendarForExpire = Calendar.getInstance(); + calendarForExpire.setTime(registerTimeDate); + calendarForExpire.set(Calendar.SECOND, calendarForExpire.get(Calendar.SECOND) + expires); + return calendarForExpire.before(DateUtil.getNow()); + } + + @Override + public void checkDeviceStatus(Device device) { + if (device == null || device.getOnline() == 0) { + return; + } + sipCommander.deviceStatusQuery(device, null); + + } + + @Override + public Device getDeviceByHostAndPort(String host, int port) { + return deviceMapper.getDeviceByHostAndPort(host, port); + } } 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 index e311890c..a690c1bd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -18,6 +18,7 @@ import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.redis.JedisUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; @@ -89,8 +90,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @Autowired JedisUtil jedisUtil; - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - /** * 初始化 */ @@ -231,7 +230,7 @@ public class MediaServerServiceImpl implements IMediaServerService { result.sort((serverItem1, serverItem2)->{ int sortResult = 0; try { - sortResult = format.parse(serverItem1.getCreateTime()).compareTo(format.parse(serverItem2.getCreateTime())); + sortResult = DateUtil.format.parse(serverItem1.getCreateTime()).compareTo(DateUtil.format.parse(serverItem2.getCreateTime())); } catch (ParseException e) { e.printStackTrace(); } @@ -291,8 +290,8 @@ public class MediaServerServiceImpl implements IMediaServerService { @Override public WVPResult add(MediaServerItem mediaServerItem) { WVPResult result = new WVPResult<>(); - mediaServerItem.setCreateTime(this.format.format(System.currentTimeMillis())); - mediaServerItem.setUpdateTime(this.format.format(System.currentTimeMillis())); + mediaServerItem.setCreateTime(DateUtil.getNow()); + mediaServerItem.setUpdateTime(DateUtil.getNow()); mediaServerItem.setHookAliveInterval(120); JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); if (responseJSON != null) { 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 index f2b6c282..4372f8eb 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -13,7 +13,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; -import com.genersoft.iot.vmp.gb28181.utils.DateUtil; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java index 2bff8643..ef5932d4 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java @@ -4,20 +4,15 @@ import com.alibaba.fastjson.JSON; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.redis.connection.Message; import org.springframework.data.redis.connection.MessageListener; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; -import java.text.SimpleDateFormat; @Component public class RedisAlarmMsgListener implements MessageListener { @@ -33,8 +28,6 @@ public class RedisAlarmMsgListener implements MessageListener { @Autowired private IVideoManagerStorage storage; - private final SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - @Override public void onMessage(Message message, byte[] bytes) { logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); @@ -52,7 +45,7 @@ public class RedisAlarmMsgListener implements MessageListener { deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); deviceAlarm.setAlarmPriority("1"); - deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis())); + deviceAlarm.setAlarmTime(DateUtil.getNow()); deviceAlarm.setAlarmType("1"); deviceAlarm.setLongitude(0); deviceAlarm.setLatitude(0); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 67697c8d..4a3aa78b 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -111,23 +111,6 @@ public interface IRedisCatchStorage { */ void clearCatchByDeviceId(String deviceId); - /** - * 获取mediaServer节点 - * @param mediaServerId - * @return - */ -// MediaServerItem getMediaInfo(String mediaServerId); - - /** - * 设置所有设备离线 - */ - void outlineForAll(); - - /** - * 获取所有在线的 - */ - List getOnlineForAll(); - /** * 在redis添加wvp的信息 */ diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java index 97cf2ccf..37d951e2 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java @@ -99,4 +99,9 @@ public interface DeviceMapper { @Update("UPDATE device SET online=0") int outlineForAll(); + + @Select("SELECT * FROM device WHERE online = 1") + List getOnlineDevices(); + @Select("SELECT * FROM device WHERE ip = #{host} AND port=${port}") + Device getDeviceByHostAndPort(String host, int port); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index ae7647f8..39daeda9 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -14,13 +14,13 @@ import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.text.SimpleDateFormat; import java.util.*; @SuppressWarnings("rawtypes") @@ -38,8 +38,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Autowired private UserSetting userSetting; - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @Override public Long getCSEQ(String method) { String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId() + "_" + method; @@ -469,26 +467,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { } } - @Override - public void outlineForAll() { - List onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + "*" ); - for (int i = 0; i < onlineDevices.size(); i++) { - String key = (String) onlineDevices.get(i); - redis.del(key); - } - } - - @Override - public List getOnlineForAll() { - List result = new ArrayList<>(); - List onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + "*" ); - for (int i = 0; i < onlineDevices.size(); i++) { - String key = (String) onlineDevices.get(i); - result.add((String) redis.get(key)); - } - return result; - } - @Override public void updateWVPInfo(JSONObject jsonObject, int time) { String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); @@ -638,7 +616,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { public void addCpuInfo(double cpuInfo) { String key = VideoManagerConstants.SYSTEM_INFO_CPU_PREFIX + userSetting.getServerId(); SystemInfoDto systemInfoDto = new SystemInfoDto<>(); - systemInfoDto.setTime(format.format(System.currentTimeMillis())); + systemInfoDto.setTime(DateUtil.getNow()); systemInfoDto.setData(cpuInfo); redis.lSet(key, systemInfoDto); // 每秒一个,最多只存30个 @@ -653,7 +631,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { public void addMemInfo(double memInfo) { String key = VideoManagerConstants.SYSTEM_INFO_MEM_PREFIX + userSetting.getServerId(); SystemInfoDto systemInfoDto = new SystemInfoDto<>(); - systemInfoDto.setTime(format.format(System.currentTimeMillis())); + systemInfoDto.setTime(DateUtil.getNow()); systemInfoDto.setData(memInfo); redis.lSet(key, systemInfoDto); // 每秒一个,最多只存30个 @@ -668,7 +646,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { public void addNetInfo(Map networkInterfaces) { String key = VideoManagerConstants.SYSTEM_INFO_NET_PREFIX + userSetting.getServerId(); SystemInfoDto> systemInfoDto = new SystemInfoDto<>(); - systemInfoDto.setTime(format.format(System.currentTimeMillis())); + systemInfoDto.setTime(DateUtil.getNow()); systemInfoDto.setData(networkInterfaces); redis.lSet(key, systemInfoDto); // 每秒一个,最多只存30个 @@ -702,7 +680,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @Override public boolean deviceIsOnline(String deviceId) { - String key = VideoManagerConstants.KEEPLIVEKEY_PREFIX + userSetting.getServerId() + "_" + deviceId; - return redis.hasKey(key); + return getDevice(deviceId).getOnline() == 1; } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index 2dc88f8d..b72671a7 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -13,6 +13,7 @@ import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.dao.*; import com.genersoft.iot.vmp.storager.dao.dto.ChannelSourceInfo; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; @@ -26,7 +27,6 @@ import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; -import java.text.SimpleDateFormat; import java.util.*; /** @@ -91,9 +91,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { @Autowired private ParentPlatformMapper parentPlatformMapper; - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - - /** * 根据设备ID判断设备是否存在 * @@ -127,7 +124,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { */ @Override public synchronized boolean updateDevice(Device device) { - String now = this.format.format(System.currentTimeMillis()); + String now = DateUtil.getNow(); device.setUpdateTime(now); Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); device.setCharset(device.getCharset().toUpperCase()); @@ -140,8 +137,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { return deviceMapper.update(device) > 0; } - - } @Override @@ -152,7 +147,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { if (streamInfo != null) { channel.setStreamId(streamInfo.getStream()); } - String now = this.format.format(System.currentTimeMillis()); + String now = DateUtil.getNow(); channel.setUpdateTime(now); DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); if (deviceChannel == null) { @@ -178,7 +173,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { if (streamInfo != null) { channel.setStreamId(streamInfo.getStream()); } - String now = this.format.format(System.currentTimeMillis()); + String now = DateUtil.getNow(); channel.setUpdateTime(now); channel.setCreateTime(now); addChannels.add(channel); @@ -193,7 +188,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { if (streamInfo != null) { channel.setStreamId(streamInfo.getStream()); } - String now = this.format.format(System.currentTimeMillis()); + String now = DateUtil.getNow(); channel.setUpdateTime(now); if (channelsInStore.get(channel.getChannelId()) != null) { updateChannels.add(channel); @@ -732,7 +727,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { boolean result = false; streamProxyItem.setStreamType("proxy"); streamProxyItem.setStatus(true); - String now = this.format.format(System.currentTimeMillis()); + String now = DateUtil.getNow(); streamProxyItem.setCreateTime(now); streamProxyItem.setCreateStamp(System.currentTimeMillis()); try { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java similarity index 52% rename from src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java rename to src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java index 604c0835..1be0f407 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/DateUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java @@ -1,57 +1,57 @@ -package com.genersoft.iot.vmp.gb28181.utils; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; - -/** - * @description:时间工具类,主要处理ISO 8601格式转换 - * @author: swwheihei - * @date: 2020年5月8日 下午3:24:42 - */ -public class DateUtil { - - //private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX"; - private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss"; - private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; - - public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { - - SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()); - SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()); - try { - return newsdf.format(oldsdf.parse(formatTime)); - } catch (ParseException e) { - e.printStackTrace(); - } - return ""; - } - - public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { - - SimpleDateFormat oldsdf = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()); - SimpleDateFormat newsdf = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()); - try { - return newsdf.format(oldsdf.parse(formatTime)); - } catch (ParseException e) { - e.printStackTrace(); - } - return ""; - } - - public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) { - SimpleDateFormat format=new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss); - //设置要读取的时间字符串格式 - Date date; - try { - date = format.parse(formatTime); - Long timestamp=date.getTime()/1000; - //转换为Date类 - return timestamp; - } catch (ParseException e) { - e.printStackTrace(); - } - return 0; - } -} +package com.genersoft.iot.vmp.utils; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +/** + * 全局时间工具类 + * @author swwheihei + */ +public class DateUtil { + + private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss"; + private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; + + public static final SimpleDateFormat formatISO8601 = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()); + public static final SimpleDateFormat format = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()); + + public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { + + try { + return formatISO8601.format(format.parse(formatTime)); + } catch (ParseException e) { + e.printStackTrace(); + } + return ""; + } + + public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { + + try { + return format.format(formatISO8601.parse(formatTime)); + } catch (ParseException e) { + e.printStackTrace(); + } + return ""; + } + + public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) { + //设置要读取的时间字符串格式 + Date date; + try { + date = format.parse(formatTime); + Long timestamp=date.getTime()/1000; + //转换为Date类 + return timestamp; + } catch (ParseException e) { + e.printStackTrace(); + } + return 0; + } + + public static String getNow() { + return format.format(System.currentTimeMillis()); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java index addc431e..56864dbc 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/alarm/AlarmController.java @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.service.IDeviceAlarmService; import com.genersoft.iot.vmp.service.IGbStreamService; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; @@ -23,9 +24,7 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.text.ParseException; -import java.text.SimpleDateFormat; import java.util.Arrays; -import java.util.Date; import java.util.List; @Api(tags = "报警信息管理") @@ -46,9 +45,6 @@ public class AlarmController { @Autowired private IVideoManagerStorage storage; - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - private SimpleDateFormat formatForGB = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - /** * 分页查询报警 * @@ -104,10 +100,10 @@ public class AlarmController { try { if (startTime != null) { - format.parse(startTime); + DateUtil.format.parse(startTime); } if (endTime != null) { - format.parse(endTime); + DateUtil.format.parse(endTime); } } catch (ParseException e) { return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); @@ -150,7 +146,7 @@ public class AlarmController { } try { if (time != null) { - format.parse(time); + DateUtil.format.parse(time); } } catch (ParseException e) { return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); @@ -193,7 +189,7 @@ public class AlarmController { deviceAlarm.setAlarmDescription("test"); deviceAlarm.setAlarmMethod("1"); deviceAlarm.setAlarmPriority("1"); - deviceAlarm.setAlarmTime(formatForGB.format(System.currentTimeMillis())); + deviceAlarm.setAlarmTime(DateUtil.formatISO8601.format(System.currentTimeMillis())); deviceAlarm.setAlarmType("1"); deviceAlarm.setLongitude(115.33333); deviceAlarm.setLatitude(39.33333); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java index 44b16883..65f5f7c7 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/log/LogController.java @@ -3,6 +3,7 @@ package com.genersoft.iot.vmp.vmanager.log; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.service.ILogService; import com.genersoft.iot.vmp.storager.dao.dto.LogDto; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; import io.swagger.annotations.Api; @@ -18,7 +19,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import java.text.ParseException; -import java.text.SimpleDateFormat; @Api(tags = "日志管理") @CrossOrigin @@ -34,8 +34,6 @@ public class LogController { @Autowired private UserSetting userSetting; - private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - /** * 分页查询日志 * @@ -80,10 +78,10 @@ public class LogController { try { if (startTime != null) { - format.parse(startTime); + DateUtil.format.parse(startTime); } if (endTime != null) { - format.parse(endTime); + DateUtil.format.parse(endTime); } } catch (ParseException e) { return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java index 6a75e1dd..887eb46a 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/user/RoleController.java @@ -2,9 +2,8 @@ package com.genersoft.iot.vmp.vmanager.user; import com.genersoft.iot.vmp.conf.security.SecurityUtils; import com.genersoft.iot.vmp.service.IRoleService; -import com.genersoft.iot.vmp.service.IUserService; import com.genersoft.iot.vmp.storager.dao.dto.Role; -import com.genersoft.iot.vmp.storager.dao.dto.User; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -13,12 +12,8 @@ import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.util.DigestUtils; -import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; -import java.text.SimpleDateFormat; import java.util.List; @Api(tags = "角色管理") @@ -30,8 +25,6 @@ public class RoleController { @Autowired private IRoleService roleService; - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @ApiOperation("添加角色") @ApiImplicitParams({ @ApiImplicitParam(name = "name", required = true, value = "角色名", dataTypeClass = String.class), @@ -53,8 +46,8 @@ public class RoleController { Role role = new Role(); role.setName(name); role.setAuthority(authority); - role.setCreateTime(format.format(System.currentTimeMillis())); - role.setUpdateTime(format.format(System.currentTimeMillis())); + role.setCreateTime(DateUtil.getNow()); + role.setUpdateTime(DateUtil.getNow()); int addResult = roleService.add(role); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java index 17fe2fb6..152122d2 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/user/UserController.java @@ -6,6 +6,7 @@ import com.genersoft.iot.vmp.service.IRoleService; import com.genersoft.iot.vmp.service.IUserService; import com.genersoft.iot.vmp.storager.dao.dto.Role; import com.genersoft.iot.vmp.storager.dao.dto.User; +import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; @@ -20,7 +21,6 @@ import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import javax.security.sasl.AuthenticationException; -import java.text.SimpleDateFormat; import java.util.List; @Api(tags = "用户管理") @@ -38,8 +38,6 @@ public class UserController { @Autowired private IRoleService roleService; - private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @ApiOperation("登录") @ApiImplicitParams({ @ApiImplicitParam(name = "username", required = true, value = "用户名", dataTypeClass = String.class), @@ -135,8 +133,8 @@ public class UserController { return new ResponseEntity<>(result, HttpStatus.OK); } user.setRole(role); - user.setCreateTime(format.format(System.currentTimeMillis())); - user.setUpdateTime(format.format(System.currentTimeMillis())); + user.setCreateTime(DateUtil.getNow()); + user.setUpdateTime(DateUtil.getNow()); int addResult = userService.addUser(user); result.setCode(addResult > 0 ? 0 : -1); diff --git a/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java b/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java index 23b9f6b2..6d6ff37f 100644 --- a/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java +++ b/src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java @@ -2,12 +2,12 @@ package com.genersoft.iot.vmp.service.impl; import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.service.IDeviceAlarmService; +import com.genersoft.iot.vmp.utils.DateUtil; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; -import java.text.SimpleDateFormat; import java.util.Date; @@ -18,8 +18,6 @@ class DeviceAlarmServiceImplTest { @Resource private IDeviceAlarmService deviceAlarmService; - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); - @org.junit.jupiter.api.Test void getAllAlarm() { // deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111",null,null,null, null, null); @@ -67,7 +65,7 @@ class DeviceAlarmServiceImplTest { */ deviceAlarm.setAlarmMethod((int)(Math.random()*7 + 1) + ""); Date date = randomDate("2021-01-01 00:00:00", "2021-06-01 00:00:00"); - deviceAlarm.setAlarmTime(format.format(date)); + deviceAlarm.setAlarmTime(DateUtil.format.format(date)); /** * 报警级别, 1为一级警情, 2为二级警情, 3为三级警情, 4为四级 警情- */ @@ -90,8 +88,8 @@ class DeviceAlarmServiceImplTest { private Date randomDate(String beginDate, String endDate) { try { - Date start = format.parse(beginDate);//构造开始日期 - Date end = format.parse(endDate);//构造结束日期 + Date start = DateUtil.format.parse(beginDate);//构造开始日期 + Date end = DateUtil.format.parse(endDate);//构造结束日期 //getTime()表示返回自 1970 年 1 月 1 日 00:00:00 GMT 以来此 Date 对象表示的毫秒数。 if (start.getTime() >= end.getTime()) { return null; diff --git a/src/test/java/com/genersoft/iot/vmp/service/impl/RoleServiceImplTest.java b/src/test/java/com/genersoft/iot/vmp/service/impl/RoleServiceImplTest.java index 13479fe2..02dedcf5 100644 --- a/src/test/java/com/genersoft/iot/vmp/service/impl/RoleServiceImplTest.java +++ b/src/test/java/com/genersoft/iot/vmp/service/impl/RoleServiceImplTest.java @@ -4,12 +4,12 @@ import com.genersoft.iot.vmp.service.IRoleService; import com.genersoft.iot.vmp.service.IUserService; import com.genersoft.iot.vmp.storager.dao.dto.Role; import com.genersoft.iot.vmp.storager.dao.dto.User; +import com.genersoft.iot.vmp.utils.DateUtil; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; -import java.text.SimpleDateFormat; import java.util.List; @@ -20,7 +20,6 @@ class RoleServiceImplTest { @Resource private IRoleService roleService; - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @org.junit.jupiter.api.Test void getAllUser() { List all = roleService.getAll(); @@ -35,8 +34,8 @@ class RoleServiceImplTest { Role role = new Role(); role.setName("test+" + i); role.setAuthority("adadadda"); - role.setCreateTime(format.format(System.currentTimeMillis())); - role.setUpdateTime(format.format(System.currentTimeMillis())); + role.setCreateTime(DateUtil.getNow()); + role.setUpdateTime(DateUtil.getNow()); roleService.add(role); } } diff --git a/src/test/java/com/genersoft/iot/vmp/service/impl/UserServiceImplTest.java b/src/test/java/com/genersoft/iot/vmp/service/impl/UserServiceImplTest.java index 41148706..3f902dc4 100644 --- a/src/test/java/com/genersoft/iot/vmp/service/impl/UserServiceImplTest.java +++ b/src/test/java/com/genersoft/iot/vmp/service/impl/UserServiceImplTest.java @@ -1,17 +1,14 @@ package com.genersoft.iot.vmp.service.impl; -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; -import com.genersoft.iot.vmp.service.IDeviceAlarmService; import com.genersoft.iot.vmp.service.IUserService; import com.genersoft.iot.vmp.storager.dao.dto.Role; import com.genersoft.iot.vmp.storager.dao.dto.User; +import com.genersoft.iot.vmp.utils.DateUtil; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import javax.annotation.Resource; -import java.text.SimpleDateFormat; -import java.util.Date; import java.util.List; @@ -22,7 +19,6 @@ class UserServiceImplTest { @Resource private IUserService userService; - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @org.junit.jupiter.api.Test void getAllUser() { @@ -42,8 +38,8 @@ class UserServiceImplTest { Role role = new Role(); role.setId(1); user.setRole(role); - user.setCreateTime(format.format(System.currentTimeMillis())); - user.setUpdateTime(format.format(System.currentTimeMillis())); + user.setCreateTime(DateUtil.getNow()); + user.setUpdateTime(DateUtil.getNow()); userService.addUser(user); } } @@ -62,7 +58,7 @@ class UserServiceImplTest { Role role = new Role(); role.setId(2); user.setRole(role); - user.setUpdateTime(format.format(System.currentTimeMillis())); + user.setUpdateTime(DateUtil.getNow()); userService.updateUsers(user); } diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 7e0637c4..f7e4e406 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -237,10 +237,10 @@ export default { that.initData(); }, 1000) - } else { - that.$message.error(res.data.msg); } }).catch(function (e) { + that.isLoging = false; + that.$message.error("请求超时"); }); }, queryRecords: function (itemData) { From 715ecb1d64a4d85482dbfdedfc6c11f44a5da282 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 11 May 2022 20:22:15 +0800 Subject: [PATCH 06/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=AE=BE=E5=A4=87?= =?UTF-8?q?=E7=BC=BA=E5=A4=B1=E7=9A=84=E6=95=B0=E6=8D=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/service/impl/DeviceServiceImpl.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) 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 index ce211c3b..6fd171e9 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -73,10 +73,18 @@ public class DeviceServiceImpl implements IDeviceService { if (deviceInRedis != null && deviceInDb == null) { // redis 存在脏数据 redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); + + } + if (device.getCreateTime() == null) { device.setCreateTime(now); } + if (device.getRegisterTime() == null) { + device.setRegisterTime(now); + } + if(device.getUpdateTime() == null) { + device.setUpdateTime(now); + } device.setOnline(1); - device.setRegisterTime(now); // 第一次上线 if (device.getCreateTime() == null) { From 3cd1378d39ed026ed05a1008c3bc92d39162d60b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 12 May 2022 10:24:08 +0800 Subject: [PATCH 07/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=96=B0=E8=AE=BE?= =?UTF-8?q?=E5=A4=87=E6=B3=A8=E5=86=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) 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 index 6fd171e9..b6edf9a9 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -75,9 +75,6 @@ public class DeviceServiceImpl implements IDeviceService { redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); } - if (device.getCreateTime() == null) { - device.setCreateTime(now); - } if (device.getRegisterTime() == null) { device.setRegisterTime(now); } @@ -88,6 +85,7 @@ public class DeviceServiceImpl implements IDeviceService { // 第一次上线 if (device.getCreateTime() == null) { + device.setCreateTime(now); logger.info("[设备上线,首次注册]: {},查询设备信息以及通道信息", device.getDeviceId()); commander.deviceInfoQuery(device); sync(device); From a030d00c8819612de2c280b75abdc90573eb52ce Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 12 May 2022 10:48:50 +0800 Subject: [PATCH 08/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cmd/DeviceInfoResponseMessageHandler.java | 7 ++- .../iot/vmp/service/IDeviceService.java | 6 ++ .../vmp/service/impl/DeviceServiceImpl.java | 58 +++++++++++++++++++ .../vmp/storager/IVideoManagerStorage.java | 16 ----- .../impl/VideoManagerStorageImpl.java | 37 ------------ .../MobilePositionController.java | 2 +- .../vmanager/gb28181/device/DeviceQuery.java | 46 ++------------- 7 files changed, 75 insertions(+), 97 deletions(-) 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 index 639d4d91..eb2c7b8f 100644 --- 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 @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; +import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import org.dom4j.DocumentException; @@ -56,6 +57,9 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent @Autowired private EventPublisher publisher; + @Autowired + private IDeviceService deviceService; + @Override public void afterPropertiesSet() throws Exception { responseMessageHandler.addHandler(cmdType, this); @@ -82,7 +86,8 @@ public class DeviceInfoResponseMessageHandler extends SIPRequestProcessorParent if (StringUtils.isEmpty(device.getStreamMode())) { device.setStreamMode("UDP"); } - storager.updateDevice(device); + deviceService.updateDevice(device); +// storager.updateDevice(device); RequestMessage msg = new RequestMessage(); msg.setKey(key); diff --git a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java index a7c52ba7..72af803d 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IDeviceService.java @@ -104,4 +104,10 @@ public interface IDeviceService { * @return 设备信息 */ Device getDeviceByHostAndPort(String host, int port); + + /** + * 更新设备 + * @param device 设备信息 + */ + void updateDevice(Device device); } 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 index b6edf9a9..2bf1b276 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -21,6 +21,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; +import org.springframework.util.StringUtils; import javax.sip.DialogState; import javax.sip.TimeoutEvent; @@ -248,4 +249,61 @@ public class DeviceServiceImpl implements IDeviceService { public Device getDeviceByHostAndPort(String host, int port) { return deviceMapper.getDeviceByHostAndPort(host, port); } + + @Override + public void updateDevice(Device device) { + + Device deviceInStore = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); + if (deviceInStore == null) { + logger.warn("更新设备时未找到设备信息"); + return; + } + if (!StringUtils.isEmpty(device.getName())) { + deviceInStore.setName(device.getName()); + } + if (!StringUtils.isEmpty(device.getCharset())) { + deviceInStore.setCharset(device.getCharset()); + } + if (!StringUtils.isEmpty(device.getMediaServerId())) { + deviceInStore.setMediaServerId(device.getMediaServerId()); + } + + // 目录订阅相关的信息 + if (device.getSubscribeCycleForCatalog() > 0) { + if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); + // 开启订阅 + addCatalogSubscribe(deviceInStore); + } + }else if (device.getSubscribeCycleForCatalog() == 0) { + if (deviceInStore.getSubscribeCycleForCatalog() != 0) { + deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); + // 取消订阅 + removeCatalogSubscribe(deviceInStore); + } + } + + // 移动位置订阅相关的信息 + if (device.getSubscribeCycleForMobilePosition() > 0) { + if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) { + deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval()); + deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition()); + // 开启订阅 + addMobilePositionSubscribe(deviceInStore); + } + }else if (device.getSubscribeCycleForMobilePosition() == 0) { + if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) { + // 取消订阅 + removeMobilePositionSubscribe(deviceInStore); + } + } + + String now = DateUtil.getNow(); + device.setUpdateTime(now); + device.setCharset(device.getCharset().toUpperCase()); + device.setUpdateTime(DateUtil.getNow()); + if (deviceMapper.update(device) > 0) { + redisCatchStorage.updateDevice(device); + } + } } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java index a29b7ae9..d94669b8 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorage.java @@ -25,22 +25,6 @@ public interface IVideoManagerStorage { * @return true:存在 false:不存在 */ public boolean exists(String deviceId); - - /** - * 视频设备创建 - * - * @param device 设备对象 - * @return true:创建成功 false:创建失败 - */ - public boolean create(Device device); - - /** - * 视频设备更新 - * - * @param device 设备对象 - * @return true:创建成功 false:创建失败 - */ - public boolean updateDevice(Device device); /** * 添加设备通道 diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index b72671a7..eea07e94 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -102,43 +102,6 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { return deviceMapper.getDeviceByDeviceId(deviceId) != null; } - /** - * 视频设备创建 - * - * @param device 设备对象 - * @return true:创建成功 false:创建失败 - */ - @Override - public synchronized boolean create(Device device) { - redisCatchStorage.updateDevice(device); - return deviceMapper.add(device) > 0; - } - - - - /** - * 视频设备更新 - * - * @param device 设备对象 - * @return true:更新成功 false:更新失败 - */ - @Override - public synchronized boolean updateDevice(Device device) { - String now = DateUtil.getNow(); - device.setUpdateTime(now); - Device deviceByDeviceId = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); - device.setCharset(device.getCharset().toUpperCase()); - if (deviceByDeviceId == null) { - device.setCreateTime(now); - redisCatchStorage.updateDevice(device); - return deviceMapper.add(device) > 0; - }else { - redisCatchStorage.updateDevice(device); - - return deviceMapper.update(device) > 0; - } - } - @Override public synchronized void updateChannel(String deviceId, DeviceChannel channel) { String channelId = channel.getChannelId(); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java index 7d11b15c..fa12f5d9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/MobilePosition/MobilePositionController.java @@ -169,7 +169,7 @@ public class MobilePositionController { Device device = storager.queryVideoDevice(deviceId); device.setSubscribeCycleForMobilePosition(Integer.parseInt(expires)); device.setMobilePositionSubmissionInterval(Integer.parseInt(interval)); - storager.updateDevice(device); + deviceService.updateDevice(device); String result = msg; if (deviceService.removeMobilePositionSubscribe(device)) { result += ",成功"; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java index d6e614d9..3e538486 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java @@ -288,7 +288,8 @@ public class DeviceQuery { public ResponseEntity updateTransport(@PathVariable String deviceId, @PathVariable String streamMode){ Device device = storager.queryVideoDevice(deviceId); device.setStreamMode(streamMode); - storager.updateDevice(device); +// storager.updateDevice(device); + deviceService.updateDevice(device); return new ResponseEntity<>(null,HttpStatus.OK); } @@ -305,51 +306,12 @@ public class DeviceQuery { public ResponseEntity> updateDevice(Device device){ if (device != null && device.getDeviceId() != null) { - Device deviceInStore = storager.queryVideoDevice(device.getDeviceId()); - if (!StringUtils.isEmpty(device.getName())) { - deviceInStore.setName(device.getName()); - } - if (!StringUtils.isEmpty(device.getCharset())) { - deviceInStore.setCharset(device.getCharset()); - } - if (!StringUtils.isEmpty(device.getMediaServerId())) { - deviceInStore.setMediaServerId(device.getMediaServerId()); - } - - // 目录订阅相关的信息 - if (device.getSubscribeCycleForCatalog() > 0) { - if (deviceInStore.getSubscribeCycleForCatalog() == 0 || deviceInStore.getSubscribeCycleForCatalog() != device.getSubscribeCycleForCatalog()) { - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); - // 开启订阅 - deviceService.addCatalogSubscribe(deviceInStore); - } - }else if (device.getSubscribeCycleForCatalog() == 0) { - if (deviceInStore.getSubscribeCycleForCatalog() != 0) { - deviceInStore.setSubscribeCycleForCatalog(device.getSubscribeCycleForCatalog()); - // 取消订阅 - deviceService.removeCatalogSubscribe(deviceInStore); - } - } - // 移动位置订阅相关的信息 - if (device.getSubscribeCycleForMobilePosition() > 0) { - if (deviceInStore.getSubscribeCycleForMobilePosition() == 0 || deviceInStore.getSubscribeCycleForMobilePosition() != device.getSubscribeCycleForMobilePosition()) { - deviceInStore.setMobilePositionSubmissionInterval(device.getMobilePositionSubmissionInterval()); - deviceInStore.setSubscribeCycleForMobilePosition(device.getSubscribeCycleForMobilePosition()); - // 开启订阅 - deviceService.addMobilePositionSubscribe(deviceInStore); - } - }else if (device.getSubscribeCycleForMobilePosition() == 0) { - if (deviceInStore.getSubscribeCycleForMobilePosition() != 0) { - // 取消订阅 - deviceService.removeMobilePositionSubscribe(deviceInStore); - } - } // TODO 报警订阅相关的信息 - storager.updateDevice(device); - cmder.deviceInfoQuery(device); + deviceService.updateDevice(device); +// cmder.deviceInfoQuery(device); } WVPResult result = new WVPResult<>(); result.setCode(0); From 0781d9bc2803713d227d8a1965298dde6d96d838 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 12 May 2022 17:48:52 +0800 Subject: [PATCH 09/18] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=BC=BA=E5=A4=B1?= =?UTF-8?q?=E7=9A=84=E8=AE=BE=E5=A4=87=E6=97=B6=E9=97=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../event/request/impl/RegisterRequestProcessor.java | 2 ++ .../message/notify/cmd/KeepaliveNotifyMessageHandler.java | 1 + .../genersoft/iot/vmp/service/impl/DeviceServiceImpl.java | 7 +------ 3 files changed, 4 insertions(+), 6 deletions(-) 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 index 4f5f96a7..594c41a1 100644 --- 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 @@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorP import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.RequestEventExt; import gov.nist.javax.sip.address.AddressImpl; import gov.nist.javax.sip.address.SipUri; @@ -176,6 +177,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 保存到redis if (registerFlag) { logger.info("[{}] 注册成功! deviceId:" + deviceId, requestAddress); + device.setRegisterTime(DateUtil.getNow()); deviceService.online(device); } else { logger.info("[{}] 注销成功! deviceId:" + deviceId, requestAddress); 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 index 56a4c49b..a6280831 100644 --- 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 @@ -72,6 +72,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp device.setPort(rPort); device.setHostAddress(received.concat(":").concat(String.valueOf(rPort))); } + device.setKeepaliveTime(DateUtil.getNow()); deviceService.online(device); // 回复200 OK responseAck(evt, Response.OK); 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 index 2bf1b276..9ac4d316 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -76,12 +76,7 @@ public class DeviceServiceImpl implements IDeviceService { redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); } - if (device.getRegisterTime() == null) { - device.setRegisterTime(now); - } - if(device.getUpdateTime() == null) { - device.setUpdateTime(now); - } + device.setUpdateTime(now); device.setOnline(1); // 第一次上线 From 4199650c20e48cd3cb897a413aec13fa518c81cd Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 12 May 2022 18:15:35 +0800 Subject: [PATCH 10/18] #471 --- .../iot/vmp/storager/dao/DeviceChannelMapper.java | 4 ++++ .../vmp/storager/impl/VideoManagerStorageImpl.java | 13 ++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) 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 index 312d3e03..c3b94f68 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java @@ -257,4 +257,8 @@ public interface DeviceChannelMapper { @Update(value = {"UPDATE device_channel SET latitude=${latitude}, longitude=${longitude} WHERE deviceId=#{deviceId} AND channelId=#{channelId}"}) void updatePotion(String deviceId, String channelId, double longitude, double latitude); + + @Select("SELECT * FROM device_channel WHERE length(trim(streamId)) > 0") + List getAllChannelInPlay(); + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java index eea07e94..1f359114 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java @@ -28,6 +28,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * 视频设备数据存储-jdbc实现 @@ -197,17 +198,27 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { if (deviceChannelList == null) { return false; } + List allChannelInPlay = deviceChannelMapper.getAllChannelInPlay(); + Map allChannelMapInPlay = new ConcurrentHashMap<>(); + if (allChannelInPlay.size() > 0) { + for (DeviceChannel deviceChannel : allChannelInPlay) { + allChannelMapInPlay.put(deviceChannel.getChannelId(), deviceChannel); + } + } TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); // 数据去重 List channels = new ArrayList<>(); StringBuilder stringBuilder = new StringBuilder(); Map subContMap = new HashMap<>(); - if (deviceChannelList != null && deviceChannelList.size() > 1) { + if (deviceChannelList.size() > 1) { // 数据去重 Set gbIdSet = new HashSet<>(); for (DeviceChannel deviceChannel : deviceChannelList) { if (!gbIdSet.contains(deviceChannel.getChannelId())) { gbIdSet.add(deviceChannel.getChannelId()); + if (allChannelMapInPlay.containsKey(deviceChannel.getChannelId())) { + deviceChannel.setStreamId(allChannelMapInPlay.get(deviceChannel.getChannelId()).getStreamId()); + } channels.add(deviceChannel); if (!StringUtils.isEmpty(deviceChannel.getParentId())) { if (subContMap.get(deviceChannel.getParentId()) == null) { From ec749de7c114aa6bc47d9766ff2242d7a4d553f7 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 12 May 2022 18:17:15 +0800 Subject: [PATCH 11/18] #470 --- web_src/src/components/control.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue index a0b2834f..b8b3e344 100644 --- a/web_src/src/components/control.vue +++ b/web_src/src/components/control.vue @@ -576,7 +576,7 @@ export default { let that = this; this.$axios({ method: 'get', - url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session&id=' + id + url: '/zlm/' + that.mediaServerChoose + '/index/api/kick_session?id=' + id }).then(function (res) { that.getAllSession(); that.$message({ From 175720320244a7d576e576b65e1995f53d9f843e Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 15:32:30 +0800 Subject: [PATCH 12/18] =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E6=91=84=E5=83=8F=E5=A4=B4=E5=9B=BD=E6=A0=87=E5=BD=95=E5=83=8F?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E6=92=AD=E6=94=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/gb28181/SipLayer.java | 8 +- .../iot/vmp/gb28181/bean/RecordInfo.java | 14 ++- .../vmp/gb28181/session/RecordDataCatch.java | 94 ++++++++++++++++++ .../callback/CheckForAllRecordsThread.java | 76 -------------- .../transmit/cmd/impl/SIPCommander.java | 37 +++---- .../request/impl/InviteRequestProcessor.java | 4 +- .../impl/RegisterRequestProcessor.java | 12 +-- .../cmd/RecordInfoResponseMessageHandler.java | 99 +++++++++---------- .../iot/vmp/media/zlm/ZLMRunner.java | 2 +- .../zlm/event/ZLMStatusEventListener.java | 5 +- .../iot/vmp/service/IMediaServerService.java | 2 +- .../vmp/service/impl/DeviceServiceImpl.java | 2 +- .../service/impl/MediaServerServiceImpl.java | 18 ++-- .../iot/vmp/service/impl/PlayServiceImpl.java | 8 +- .../com/genersoft/iot/vmp/utils/DateUtil.java | 57 +++++------ .../gb28181/record/GBRecordController.java | 33 ++++++- web_src/src/components/channelList.vue | 2 +- .../src/components/dialog/devicePlayer.vue | 16 ++- 18 files changed, 275 insertions(+), 214 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java 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 2b93d702..a3428b10 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -81,11 +81,11 @@ public class SipLayer{ tcpSipProvider.setDialogErrorsAutomaticallyHandled(); tcpSipProvider.addSipListener(sipProcessorObserver); // tcpSipProvider.setAutomaticDialogSupportEnabled(false); - logger.info("Sip Server TCP 启动成功 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "}"); + logger.info("[Sip Server] TCP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort()); } catch (TransportNotSupportedException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { - logger.error("无法使用 [ {}:{} ]作为SIP[ TCP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" + logger.error("[Sip Server] 无法使用 [ {}:{} ]作为SIP[ TCP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" , sipConfig.getMonitorIp(), sipConfig.getPort()); } catch (TooManyListenersException e) { e.printStackTrace(); @@ -108,14 +108,14 @@ public class SipLayer{ } catch (TransportNotSupportedException e) { e.printStackTrace(); } catch (InvalidArgumentException e) { - logger.error("无法使用 [ {}:{} ]作为SIP[ UDP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" + logger.error("[Sip Server] 无法使用 [ {}:{} ]作为SIP[ UDP ]服务,可排查: 1. sip.monitor-ip 是否为本机网卡IP; 2. sip.port 是否已被占用" , sipConfig.getMonitorIp(), sipConfig.getPort()); } catch (TooManyListenersException e) { e.printStackTrace(); } catch (ObjectInUseException e) { e.printStackTrace(); } - logger.info("Sip Server UDP 启动成功 port [" + sipConfig.getMonitorIp() + ":" + sipConfig.getPort() + "]"); + logger.info("[Sip Server] UDP 启动成功 {}:{}", sipConfig.getMonitorIp(), sipConfig.getPort()); return udpSipProvider; } 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 index 24fc2212..55bf71f2 100644 --- 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,8 +1,6 @@ package com.genersoft.iot.vmp.gb28181.bean; - -//import gov.nist.javax.sip.header.SIPDate; - +import java.util.Date; import java.util.List; /** @@ -21,6 +19,8 @@ public class RecordInfo { private String name; private int sumNum; + + private Date lastTime; private List recordList; @@ -71,4 +71,12 @@ public class RecordInfo { public void setSn(String sn) { this.sn = sn; } + + public Date getLastTime() { + return lastTime; + } + + public void setLastTime(Date lastTime) { + this.lastTime = lastTime; + } } 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 new file mode 100644 index 00000000..0d166c12 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java @@ -0,0 +1,94 @@ +package com.genersoft.iot.vmp.gb28181.session; + +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +/** + * @author lin + */ +@Component +public class RecordDataCatch { + + public static Map data = new ConcurrentHashMap<>(); + + @Autowired + private DeferredResultHolder deferredResultHolder; + + + public int put(String deviceId, String sn, int sumNum, List recordItems) { + String key = deviceId + sn; + RecordInfo recordInfo = data.get(key); + if (recordInfo == null) { + recordInfo = new RecordInfo(); + recordInfo.setDeviceId(deviceId); + recordInfo.setSn(sn.trim()); + recordInfo.setSumNum(sumNum); + recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>())); + recordInfo.setLastTime(new Date(System.currentTimeMillis())); + recordInfo.getRecordList().addAll(recordItems); + data.put(key, recordInfo); + }else { + // 同一个设备的通道同步请求只考虑一个,其他的直接忽略 + if (!Objects.equals(sn.trim(), recordInfo.getSn())) { + return 0; + } + recordInfo.getRecordList().addAll(recordItems); + recordInfo.setLastTime(new Date(System.currentTimeMillis())); + } + return recordInfo.getRecordList().size(); + } + + @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 + private void timerTask(){ + Set keys = data.keySet(); + Calendar calendarBefore5S = Calendar.getInstance(); + calendarBefore5S.setTime(new Date()); + calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5); + + for (String key : keys) { + RecordInfo recordInfo = data.get(key); + // 超过五秒收不到消息任务超时, 只更新这一部分数据 + if ( recordInfo.getLastTime().before(calendarBefore5S.getTime())) { + // 处理录像数据, 返回给前端 + String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn(); + + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(0); + wvpResult.setMsg("success"); + // 对数据进行排序 + Collections.sort(recordInfo.getRecordList()); + wvpResult.setData(recordInfo); + + RequestMessage msg = new RequestMessage(); + msg.setKey(msgKey); + msg.setData(wvpResult); + deferredResultHolder.invokeAllResult(msg); + data.remove(key); + } + } + } + + public boolean isComplete(String deviceId, String sn) { + RecordInfo recordInfo = data.get(deviceId + sn); + return recordInfo != null && recordInfo.getRecordList().size() == recordInfo.getSumNum(); + } + + public RecordInfo getRecordInfo(String deviceId, String sn) { + return data.get(deviceId + sn); + } + + public void remove(String deviceId, String sn) { + data.remove(deviceId + sn); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java deleted file mode 100644 index 8a2e9009..00000000 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.genersoft.iot.vmp.gb28181.transmit.callback; - -import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; -import com.genersoft.iot.vmp.gb28181.bean.RecordItem; -import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.RecordInfoResponseMessageHandler; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; -import org.slf4j.Logger; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.TimeUnit; - -@SuppressWarnings("unchecked") -public class CheckForAllRecordsThread extends Thread { - - private String key; - - private RecordInfo recordInfo; - - private RedisUtil redis; - - private Logger logger; - - private DeferredResultHolder deferredResultHolder; - - public CheckForAllRecordsThread(String key, RecordInfo recordInfo) { - this.key = key; - this.recordInfo = recordInfo; - } - - @Override - public void run() { - - String cacheKey = this.key; - - for (long stop = System.nanoTime() + TimeUnit.SECONDS.toNanos(10); stop > System.nanoTime();) { - List cacheKeys = redis.scan(cacheKey + "_*"); - List totalRecordList = new ArrayList(); - for (int i = 0; i < cacheKeys.size(); i++) { - totalRecordList.addAll((List) redis.get(cacheKeys.get(i).toString())); - } - if (totalRecordList.size() < this.recordInfo.getSumNum()) { - logger.info("已获取" + totalRecordList.size() + "项录像数据,共" + this.recordInfo.getSumNum() + "项"); - } else { - logger.info("录像数据已全部获取,共 {} 项", this.recordInfo.getSumNum()); - this.recordInfo.setRecordList(totalRecordList); - for (int i = 0; i < cacheKeys.size(); i++) { - redis.del(cacheKeys.get(i).toString()); - } - break; - } - } - // 自然顺序排序, 元素进行升序排列 - this.recordInfo.getRecordList().sort(Comparator.naturalOrder()); - RequestMessage msg = new RequestMessage(); - msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn()); - msg.setData(recordInfo); - deferredResultHolder.invokeAllResult(msg); - logger.info("处理完成,返回结果"); - RecordInfoResponseMessageHandler.threadNameList.remove(cacheKey); - } - - public void setRedis(RedisUtil redis) { - this.redis = redis; - } - - public void setDeferredResultHolder(DeferredResultHolder deferredResultHolder) { - this.deferredResultHolder = deferredResultHolder; - } - - public void setLogger(Logger logger) { - this.logger = logger; - } - -} 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 index 567bcac7..8a6e9314 100644 --- 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 @@ -370,7 +370,7 @@ public class SIPCommander implements ISIPCommander { // StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); - content.append("o="+ sipConfig.getId()+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); + content.append("o="+ channelId+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); content.append("s=Play\r\n"); content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); content.append("t=0 0\r\n"); @@ -389,8 +389,7 @@ public class SIPCommander implements ISIPCommander { content.append("a=rtpmap:126 H264/90000\r\n"); content.append("a=rtpmap:125 H264S/90000\r\n"); content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); - content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); - content.append("a=fmtp:99 profile-level-id=3\r\n"); + content.append("a=rtpmap:99 H265/90000\r\n"); content.append("a=rtpmap:98 H264/90000\r\n"); content.append("a=rtpmap:97 MPEG4/90000\r\n"); if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 @@ -402,16 +401,17 @@ public class SIPCommander implements ISIPCommander { } }else { if("TCP-PASSIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if ("TCP-ACTIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if("UDP".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n"); } content.append("a=recvonly\r\n"); content.append("a=rtpmap:96 PS/90000\r\n"); content.append("a=rtpmap:98 H264/90000\r\n"); content.append("a=rtpmap:97 MPEG4/90000\r\n"); + content.append("a=rtpmap:99 H265/90000\r\n"); if ("TCP-PASSIVE".equals(streamMode)) { // tcp被动模式 content.append("a=setup:passive\r\n"); content.append("a=connection:new\r\n"); @@ -467,7 +467,7 @@ public class SIPCommander implements ISIPCommander { StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); - content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); content.append("s=Playback\r\n"); content.append("u="+channelId+":0\r\n"); content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); @@ -490,8 +490,7 @@ public class SIPCommander implements ISIPCommander { content.append("a=rtpmap:126 H264/90000\r\n"); content.append("a=rtpmap:125 H264S/90000\r\n"); content.append("a=fmtp:125 profile-level-id=42e01e\r\n"); - content.append("a=rtpmap:99 MP4V-ES/90000\r\n"); - content.append("a=fmtp:99 profile-level-id=3\r\n"); + content.append("a=rtpmap:99 H265/90000\r\n"); content.append("a=rtpmap:98 H264/90000\r\n"); content.append("a=rtpmap:97 MPEG4/90000\r\n"); if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 @@ -503,16 +502,17 @@ public class SIPCommander implements ISIPCommander { } }else { if("TCP-PASSIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if ("TCP-ACTIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if("UDP".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n"); } content.append("a=recvonly\r\n"); content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("a=rtpmap:98 H264/90000\r\n"); content.append("a=rtpmap:97 MPEG4/90000\r\n"); + content.append("a=rtpmap:98 H264/90000\r\n"); + content.append("a=rtpmap:99 H265/90000\r\n"); if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 content.append("a=setup:passive\r\n"); content.append("a=connection:new\r\n"); @@ -577,7 +577,7 @@ public class SIPCommander implements ISIPCommander { StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); - content.append("o="+sipConfig.getId()+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); + content.append("o="+channelId+" 0 0 IN IP4 " + mediaServerItem.getSdpIp() + "\r\n"); content.append("s=Download\r\n"); content.append("u="+channelId+":0\r\n"); content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); @@ -613,16 +613,17 @@ public class SIPCommander implements ISIPCommander { } }else { if("TCP-PASSIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if ("TCP-ACTIVE".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" TCP/RTP/AVP 96 97 98 99\r\n"); }else if("UDP".equals(streamMode)) { - content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 98 97\r\n"); + content.append("m=video "+ ssrcInfo.getPort() +" RTP/AVP 96 97 98 99\r\n"); } content.append("a=recvonly\r\n"); content.append("a=rtpmap:96 PS/90000\r\n"); - content.append("a=rtpmap:98 H264/90000\r\n"); content.append("a=rtpmap:97 MPEG4/90000\r\n"); + content.append("a=rtpmap:98 H264/90000\r\n"); + content.append("a=rtpmap:99 H265/90000\r\n"); if("TCP-PASSIVE".equals(streamMode)){ // tcp被动模式 content.append("a=setup:passive\r\n"); content.append("a=connection:new\r\n"); 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 index 1ba1b3e7..7c63279d 100644 --- 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 @@ -331,7 +331,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements sendRtpItem.setApp("rtp"); if ("Playback".equals(sessionName)) { sendRtpItem.setPlayType(InviteStreamType.PLAYBACK); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, true, true); sendRtpItem.setStreamId(ssrcInfo.getStream()); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); @@ -372,7 +372,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements if (mediaServerItem.isRtpEnable()) { streamId = String.format("%s_%s", device.getDeviceId(), channelId); } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, true, false); sendRtpItem.setStreamId(ssrcInfo.getStream()); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); 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 index 594c41a1..1c054401 100644 --- 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 @@ -81,7 +81,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen try { RequestEventExt evtExt = (RequestEventExt) evt; String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort(); - logger.info("[{}] 收到注册请求,开始处理", requestAddress); + logger.info("[注册请求] 开始处理: {}", requestAddress); Request request = evt.getRequest(); ExpiresHeader expiresHeader = (ExpiresHeader) request.getHeader(Expires.NAME); Response response = null; @@ -95,7 +95,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen AuthorizationHeader authHead = (AuthorizationHeader) request.getHeader(AuthorizationHeader.NAME); if (authHead == null) { - logger.info("[{}] 未携带授权头 回复401", requestAddress); + logger.info("[注册请求] 未携带授权头 回复401: {}", requestAddress); response = getMessageFactory().createResponse(Response.UNAUTHORIZED, request); new DigestServerAuthenticationHelper().generateChallenge(getHeaderFactory(), response, sipConfig.getDomain()); sendResponse(evt, response); @@ -111,7 +111,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 注册失败 response = getMessageFactory().createResponse(Response.FORBIDDEN, request); response.setReasonPhrase("wrong password"); - logger.info("[{}] 密码/SIP服务器ID错误, 回复403", requestAddress); + logger.info("[注册请求] 密码/SIP服务器ID错误, 回复403: {}", requestAddress); sendResponse(evt, response); return; } @@ -176,11 +176,11 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen // 注册成功 // 保存到redis if (registerFlag) { - logger.info("[{}] 注册成功! deviceId:" + deviceId, requestAddress); + logger.info("[注册成功] deviceId: {}->{}", deviceId, requestAddress); device.setRegisterTime(DateUtil.getNow()); deviceService.online(device); } else { - logger.info("[{}] 注销成功! deviceId:" + deviceId, requestAddress); + logger.info("[注销成功] deviceId: {}->{}" ,deviceId, requestAddress); deviceService.offline(deviceId); } } catch (SipException | InvalidArgumentException | NoSuchAlgorithmException | ParseException e) { @@ -192,7 +192,7 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen private void sendResponse(RequestEvent evt, Response response) throws InvalidArgumentException, SipException { ServerTransaction serverTransaction = getServerTransaction(evt); if (serverTransaction == null) { - logger.warn("回复失败:{}", response); + logger.warn("[回复失败]:{}", response); return; } serverTransaction.sendResponse(response); 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 index 2de8ef16..4509e424 100644 --- 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 @@ -5,14 +5,14 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.RecordInfo; import com.genersoft.iot.vmp.gb28181.bean.RecordItem; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.transmit.callback.CheckForAllRecordsThread; +import com.genersoft.iot.vmp.gb28181.session.RecordDataCatch; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.ResponseMessageHandler; import com.genersoft.iot.vmp.utils.DateUtil; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import org.dom4j.DocumentException; import org.dom4j.Element; import org.slf4j.Logger; @@ -20,19 +20,20 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; import javax.sip.SipException; import javax.sip.message.Response; import java.text.ParseException; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.UUID; +import java.util.*; import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; +/** + * @author lin + */ @Component public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { @@ -45,11 +46,13 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent private ResponseMessageHandler responseMessageHandler; @Autowired - private RedisUtil redis; + private RecordDataCatch recordDataCatch; @Autowired private DeferredResultHolder deferredResultHolder; + + @Autowired private EventPublisher eventPublisher; @@ -66,32 +69,22 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent responseAck(evt, Response.OK); rootElement = getRootElement(evt, device.getCharset()); - String uuid = UUID.randomUUID().toString().replace("-", ""); - RecordInfo recordInfo = new RecordInfo(); String sn = getText(rootElement, "SN"); - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn; - recordInfo.setDeviceId(device.getDeviceId()); - recordInfo.setSn(sn); - recordInfo.setName(getText(rootElement, "Name")); - if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") { - recordInfo.setSumNum(0); - } else { - recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum"))); + + String sumNumStr = getText(rootElement, "SumNum"); + int sumNum = 0; + if (!StringUtils.isEmpty(sumNumStr)) { + sumNum = Integer.parseInt(sumNumStr); } Element recordListElement = rootElement.element("RecordList"); - if (recordListElement == null || recordInfo.getSumNum() == 0) { + if (recordListElement == null || sumNum == 0) { logger.info("无录像数据"); - eventPublisher.recordEndEventPush(recordInfo); - RequestMessage msg = new RequestMessage(); - msg.setKey(key); - msg.setData(recordInfo); - deferredResultHolder.invokeAllResult(msg); + recordDataCatch.put(device.getDeviceId(), sn, sumNum, new ArrayList<>()); + releaseRequest(device.getDeviceId(), sn); } else { Iterator recordListIterator = recordListElement.elementIterator(); - List recordList = new ArrayList(); if (recordListIterator != null) { - RecordItem record = new RecordItem(); - logger.info("处理录像列表数据..."); + List recordList = new ArrayList<>(); // 遍历DeviceList while (recordListIterator.hasNext()) { Element itemRecord = recordListIterator.next(); @@ -100,43 +93,31 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent logger.info("记录为空,下一个..."); continue; } - record = new RecordItem(); + RecordItem record = new RecordItem(); record.setDeviceId(getText(itemRecord, "DeviceID")); record.setName(getText(itemRecord, "Name")); record.setFilePath(getText(itemRecord, "FilePath")); record.setFileSize(getText(itemRecord, "FileSize")); record.setAddress(getText(itemRecord, "Address")); - record.setStartTime( - DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "StartTime"))); - record.setEndTime( - DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(getText(itemRecord, "EndTime"))); + + String startTimeStr = getText(itemRecord, "StartTime"); + record.setStartTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(startTimeStr)); + + String endTimeStr = getText(itemRecord, "EndTime"); + record.setEndTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(endTimeStr)); + record.setSecrecy(itemRecord.element("Secrecy") == null ? 0 : Integer.parseInt(getText(itemRecord, "Secrecy"))); record.setType(getText(itemRecord, "Type")); record.setRecorderId(getText(itemRecord, "RecorderID")); recordList.add(record); } - recordInfo.setRecordList(recordList); + int count = recordDataCatch.put(device.getDeviceId(), sn, sumNum, recordList); + logger.info("[国标录像], {}->{}: {}/{}", device.getDeviceId(), sn, count, sumNum); } - eventPublisher.recordEndEventPush(recordInfo); - // 改用单独线程统计已获取录像文件数量,避免多包并行分别统计不完整的问题 - String cacheKey = CACHE_RECORDINFO_KEY + device.getDeviceId() + sn; - redis.set(cacheKey + "_" + uuid, recordList, 90); - if (!threadNameList.contains(cacheKey)) { - threadNameList.add(cacheKey); - CheckForAllRecordsThread chk = new CheckForAllRecordsThread(cacheKey, recordInfo); - chk.setName(cacheKey); - chk.setDeferredResultHolder(deferredResultHolder); - chk.setRedis(redis); - chk.setLogger(logger); - chk.start(); - if (logger.isDebugEnabled()) { - logger.debug("Start Thread " + cacheKey + "."); - } - } else { - if (logger.isDebugEnabled()) { - logger.debug("Thread " + cacheKey + " already started."); - } + + if (recordDataCatch.isComplete(device.getDeviceId(), sn)){ + releaseRequest(device.getDeviceId(), sn); } } } catch (SipException e) { @@ -154,4 +135,20 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent public void handForPlatform(RequestEvent evt, ParentPlatform parentPlatform, Element element) { } + + public void releaseRequest(String deviceId, String sn){ + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(0); + wvpResult.setMsg("success"); + // 对数据进行排序 + Collections.sort(recordDataCatch.getRecordInfo(deviceId, sn).getRecordList()); + wvpResult.setData(recordDataCatch.getRecordInfo(deviceId, sn)); + + RequestMessage msg = new RequestMessage(); + msg.setKey(key); + msg.setData(wvpResult); + deferredResultHolder.invokeAllResult(msg); + recordDataCatch.remove(deviceId, sn); + } } 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 index 02612093..138af7ae 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -89,7 +89,7 @@ public class ZLMRunner implements CommandLineRunner { }); // 获取zlm信息 - logger.info("[zlm接入]等待默认zlm中..."); + logger.info("[zlm] 等待默认zlm中..."); // 获取所有的zlm, 并开启主动连接 List all = mediaServerService.getAllFromDatabase(); 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 index b193add9..f4a9febb 100644 --- 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 @@ -39,8 +39,7 @@ public class ZLMStatusEventListener { @Async @EventListener public void onApplicationEvent(ZLMOnlineEvent event) { - - logger.info("【ZLM上线】ID:" + event.getMediaServerId()); + logger.info("[ZLM] 上线 ID:" + event.getMediaServerId()); streamPushService.zlmServerOnline(event.getMediaServerId()); streamProxyService.zlmServerOnline(event.getMediaServerId()); @@ -50,7 +49,7 @@ public class ZLMStatusEventListener { @EventListener public void onApplicationEvent(ZLMOfflineEvent event) { - logger.info("ZLM离线事件触发,ID:" + event.getMediaServerId()); + logger.info("[ZLM] 离线,ID:" + event.getMediaServerId()); // 处理ZLM离线 mediaServerService.zlmServerOffline(event.getMediaServerId()); streamProxyService.zlmServerOffline(event.getMediaServerId()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java index 4614ee7d..e216c654 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -44,7 +44,7 @@ public interface IMediaServerService { void updateVmServer(List mediaServerItemList); - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck); + SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback); SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback); 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 index 9ac4d316..5cfa8525 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -66,7 +66,7 @@ public class DeviceServiceImpl implements IDeviceService { @Override public void online(Device device) { - logger.info("[设备上线],deviceId:" + device.getDeviceId()); + logger.info("[设备上线] deviceId:{}->{}:{}", device.getDeviceId(), device.getIp(), device.getPort()); Device deviceInRedis = redisCatchStorage.getDevice(device.getDeviceId()); Device deviceInDb = deviceMapper.getDeviceByDeviceId(device.getDeviceId()); 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 index a690c1bd..5468faef 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -95,7 +95,7 @@ public class MediaServerServiceImpl implements IMediaServerService { */ @Override public void updateVmServer(List mediaServerItemList) { - logger.info("[缓存初始化] Media Server "); + logger.info("[zlm] 缓存初始化 "); for (MediaServerItem mediaServerItem : mediaServerItemList) { if (StringUtils.isEmpty(mediaServerItem.getId())) { continue; @@ -116,8 +116,8 @@ public class MediaServerServiceImpl implements IMediaServerService { } @Override - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck) { - return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,false); + public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean ssrcCheck, boolean isPlayback) { + return openRTPServer(mediaServerItem, streamId, null, ssrcCheck,isPlayback); } @Override @@ -352,7 +352,7 @@ public class MediaServerServiceImpl implements IMediaServerService { */ @Override public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { - logger.info("[ ZLM:{} ]-[ {}:{} ]正在连接", + logger.info("[ZLM] 正在连接 : {} -> {}:{}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); @@ -405,7 +405,7 @@ public class MediaServerServiceImpl implements IMediaServerService { setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); } publisher.zlmOnlineEventPublish(serverItem.getId()); - logger.info("[ ZLM:{} ]-[ {}:{} ]连接成功", + logger.info("[ZLM] 连接成功 {} - {}:{} ", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); } @@ -483,7 +483,7 @@ public class MediaServerServiceImpl implements IMediaServerService { */ @Override public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { - logger.info("[ ZLM:{} ]-[ {}:{} ]正在设置zlm", + logger.info("[ZLM] 正在设置 :{} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); String protocol = sslEnabled ? "https" : "http"; String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); @@ -527,17 +527,17 @@ public class MediaServerServiceImpl implements IMediaServerService { if (responseJSON != null && responseJSON.getInteger("code") == 0) { if (restart) { - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功, 开始重启以保证配置生效", + logger.info("[ZLM] 设置成功,开始重启以保证配置生效 {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); zlmresTfulUtils.restartServer(mediaServerItem); }else { - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm成功", + logger.info("[ZLM] 设置成功 {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } }else { - logger.info("[ ZLM:{} ]-[ {}:{} ]设置zlm失败", + logger.info("[ZLM] 设置zlm失败 {} -> {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); } 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 index 4372f8eb..eb3831a9 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -193,7 +193,7 @@ public class PlayServiceImpl implements IPlayService { if (mediaServerItem.isRtpEnable()) { streamId = String.format("%s_%s", device.getDeviceId(), channelId); } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ if (hookEvent != null) { hookEvent.response(mediaServerItem, response); @@ -237,7 +237,7 @@ public class PlayServiceImpl implements IPlayService { streamId = String.format("%s_%s", device.getDeviceId(), channelId); } if (ssrcInfo == null) { - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck()); + ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); } // 超时处理 @@ -360,7 +360,7 @@ public class PlayServiceImpl implements IPlayService { return null; } MediaServerItem newMediaServerItem = getNewMediaServerItem(device); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true, true); return playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); } @@ -447,7 +447,7 @@ public class PlayServiceImpl implements IPlayService { return null; } MediaServerItem newMediaServerItem = getNewMediaServerItem(device); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true, true); return download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed,infoCallBack, hookCallBack); } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java index 1be0f407..15313cdc 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java @@ -1,8 +1,15 @@ package com.genersoft.iot.vmp.utils; -import java.text.ParseException; + import java.text.SimpleDateFormat; -import java.util.Date; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAccessor; + import java.util.Locale; /** @@ -12,46 +19,40 @@ import java.util.Locale; public class DateUtil { private static final String yyyy_MM_dd_T_HH_mm_ss_SSSXXX = "yyyy-MM-dd'T'HH:mm:ss"; - private static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; + public static final String yyyy_MM_dd_HH_mm_ss = "yyyy-MM-dd HH:mm:ss"; public static final SimpleDateFormat formatISO8601 = new SimpleDateFormat(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()); public static final SimpleDateFormat format = new SimpleDateFormat(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()); - public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { + public static final DateTimeFormatter formatterISO8601 = DateTimeFormatter.ofPattern(yyyy_MM_dd_T_HH_mm_ss_SSSXXX, Locale.getDefault()).withZone(ZoneId.systemDefault()); + public static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern(yyyy_MM_dd_HH_mm_ss, Locale.getDefault()).withZone(ZoneId.systemDefault()); - try { - return formatISO8601.format(format.parse(formatTime)); - } catch (ParseException e) { - e.printStackTrace(); - } - return ""; + public static String yyyy_MM_dd_HH_mm_ssToISO8601(String formatTime) { + return formatterISO8601.format(formatter.parse(formatTime)); } public static String ISO8601Toyyyy_MM_dd_HH_mm_ss(String formatTime) { + return formatter.format(formatterISO8601.parse(formatTime)); - try { - return format.format(formatISO8601.parse(formatTime)); - } catch (ParseException e) { - e.printStackTrace(); - } - return ""; } public static long yyyy_MM_dd_HH_mm_ssToTimestamp(String formatTime) { - //设置要读取的时间字符串格式 - Date date; - try { - date = format.parse(formatTime); - Long timestamp=date.getTime()/1000; - //转换为Date类 - return timestamp; - } catch (ParseException e) { - e.printStackTrace(); - } - return 0; + TemporalAccessor temporalAccessor = formatter.parse(formatTime); + Instant instant = Instant.from(temporalAccessor); + return instant.getEpochSecond(); } public static String getNow() { - return format.format(System.currentTimeMillis()); + LocalDateTime nowDateTime = LocalDateTime.now(); + return formatter.format(nowDateTime); + } + + public static boolean verification(String timeStr, DateTimeFormatter dateTimeFormatter) { + try { + LocalDate.parse(timeStr, dateTimeFormatter); + return true; + }catch (DateTimeParseException exception) { + return false; + } } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java index 6fdadf26..8cb923a7 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java @@ -5,6 +5,8 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; +import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -27,6 +29,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import java.time.LocalDate; import java.util.UUID; @Api(tags = "国标录像") @@ -60,15 +63,32 @@ public class GBRecordController { @ApiImplicitParam(name = "endTime", value = "结束时间", dataTypeClass = String.class), }) @GetMapping("/query/{deviceId}/{channelId}") - public DeferredResult> recordinfo(@PathVariable String deviceId,@PathVariable String channelId, String startTime, String endTime){ + public DeferredResult>> recordinfo(@PathVariable String deviceId, @PathVariable String channelId, String startTime, String endTime){ if (logger.isDebugEnabled()) { logger.debug(String.format("录像信息查询 API调用,deviceId:%s ,startTime:%s, endTime:%s",deviceId, startTime, endTime)); } + DeferredResult>> result = new DeferredResult<>(); + if (!DateUtil.verification(startTime, DateUtil.formatter)){ + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("startTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss); + + ResponseEntity> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK); + result.setResult(resultResponseEntity); + return result; + } + if (!DateUtil.verification(endTime, DateUtil.formatter)){ + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("endTime error, format is " + DateUtil.yyyy_MM_dd_HH_mm_ss); + ResponseEntity> resultResponseEntity = new ResponseEntity<>(wvpResult, HttpStatus.OK); + result.setResult(resultResponseEntity); + return result; + } Device device = storager.queryVideoDevice(deviceId); // 指定超时时间 1分钟30秒 - DeferredResult> result = new DeferredResult<>(90*1000L); String uuid = UUID.randomUUID().toString(); int sn = (int)((Math.random()*9+1)*100000); String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn; @@ -76,7 +96,10 @@ public class GBRecordController { msg.setId(uuid); msg.setKey(key); cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, null, null, null, (eventResult -> { - msg.setData("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg ); + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg); + msg.setData(wvpResult); resultHolder.invokeResult(msg); })); @@ -84,6 +107,10 @@ public class GBRecordController { resultHolder.put(key, uuid, result); result.onTimeout(()->{ msg.setData("timeout"); + WVPResult wvpResult = new WVPResult<>(); + wvpResult.setCode(-1); + wvpResult.setMsg("timeout"); + msg.setData(wvpResult); resultHolder.invokeResult(msg); }); return result; diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index f7e4e406..9c7ab8ef 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -244,7 +244,7 @@ export default { }); }, queryRecords: function (itemData) { - var format = moment().format("YYYY-M-D"); + var format = moment().format("yyyy-MM-DD"); let deviceId = this.deviceId; let channelId = itemData.channelId; this.$refs.devicePlayer.openDialog("record", deviceId, channelId, {date: format}) diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index f0b45125..135bd85b 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -453,9 +453,19 @@ export default { method: 'get', url: '/api/gb_record/query/' + this.deviceId + '/' + this.channelId + '?startTime=' + startTime + '&endTime=' + endTime }).then(function (res) { - // 处理时间信息 - that.videoHistory.searchHistoryResult = res.data.recordList; - that.recordsLoading = false; + console.log(res) + if(res.data.code === 0) { + // 处理时间信息 + that.videoHistory.searchHistoryResult = res.data.data.recordList; + that.recordsLoading = false; + }else { + this.$message({ + showClose: true, + message: res.data.msg, + type: "error", + }); + } + }).catch(function (e) { console.log(e.message); // that.videoHistory.searchHistoryResult = falsificationData.recordData; From 4d3f0a8d790afea1a3f577ac07cfea258457ebc2 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 15:41:50 +0800 Subject: [PATCH 13/18] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E5=9B=BD=E6=A0=87=E5=BD=95=E5=83=8F=E6=92=AD=E6=94=BE=E7=9A=84?= =?UTF-8?q?=E6=8E=A7=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java | 2 +- web_src/src/components/dialog/devicePlayer.vue | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java index 15313cdc..9d37dcd3 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/DateUtil.java @@ -14,7 +14,7 @@ import java.util.Locale; /** * 全局时间工具类 - * @author swwheihei + * @author lin */ public class DateUtil { diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 135bd85b..921e4136 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -681,7 +681,11 @@ export default { this.$axios({ method: 'get', url: `/api/playback/seek/${this.streamId }/` + Math.floor(this.seekTime * val / 100000) - }).then(function (res) {}); + }).then( (res)=> { + setTimeout(()=>{ + this.$refs.videoPlayer.play(this.videoUrl) + }, 600) + }); } } From d571e440400067d7a935b1ba5cf6efce027c5d98 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 15:45:02 +0800 Subject: [PATCH 14/18] =?UTF-8?q?=E5=8E=BB=E9=99=A4=E8=BF=87=E6=97=B6?= =?UTF-8?q?=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 1 - pom.xml | 7 ------- src/main/resources/all-application.yml | 2 +- src/main/resources/application-dev.yml | 1 - src/main/resources/application-docker.yml | 2 +- 5 files changed, 2 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index f9ef44a5..7ba443fe 100644 --- a/README.md +++ b/README.md @@ -106,7 +106,6 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git - [X] 添加RTMP视频 - [X] 云端录像(需要部署单独服务配合使用) - [X] 多流媒体节点,自动选择负载最低的节点使用。 -- [X] 支持使用mysql作为数据库,默认sqlite3,开箱即用。 - [X] WEB端支持播放H264与H265,音频支持G.711A/G.711U/AAC,覆盖国标常用编码格式。 [//]: # (# docker快速体验) diff --git a/pom.xml b/pom.xml index eade1f08..1546e39c 100644 --- a/pom.xml +++ b/pom.xml @@ -101,13 +101,6 @@ 8.0.22 - - - org.xerial - sqlite-jdbc - 3.32.3.2 - - com.github.pagehelper diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 3f148d6f..1233a890 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -28,7 +28,7 @@ spring: poolMaxIdle: 500 # [可选] 最大的等待时间(秒) poolMaxWait: 5 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + # [必选] jdbc数据库配置 datasource: type: com.alibaba.druid.pool.DruidDataSource driver-class-name: com.mysql.cj.jdbc.Driver diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index b1950c5d..35314314 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -16,7 +16,6 @@ spring: password: face2020 # [可选] 超时时间 timeout: 10000 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 # mysql数据源 datasource: type: com.alibaba.druid.pool.DruidDataSource diff --git a/src/main/resources/application-docker.yml b/src/main/resources/application-docker.yml index 6487f9a9..1653a586 100644 --- a/src/main/resources/application-docker.yml +++ b/src/main/resources/application-docker.yml @@ -16,7 +16,7 @@ spring: password: ${REDIS_PWD:root} # [可选] 超时时间 timeout: 10000 - # [可选] jdbc数据库配置, 项目使用sqlite作为数据库,一般不需要配置 + # [必选] jdbc数据库配置 datasource: # 使用mysql 打开23-28行注释, 删除29-36行 name: wvp From 98e6cf5bae84ec7860c3da3a6e3228353ae9b385 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 21:05:33 +0800 Subject: [PATCH 15/18] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=B7=E5=BA=B7?= =?UTF-8?q?=E5=BD=95=E5=83=8F=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/bean/SubscribeHolder.java | 1 - .../session/VideoStreamSessionManager.java | 4 ++-- .../gb28181/transmit/cmd/impl/SIPCommander.java | 16 +++++++++++++--- .../cmd/MediaStatusNotifyMessageHandler.java | 5 ++--- web_src/src/components/dialog/recordDownload.vue | 1 + 5 files changed, 18 insertions(+), 9 deletions(-) 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 index 2736be2d..f191c005 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SubscribeHolder.java @@ -66,7 +66,6 @@ public class SubscribeHolder { dynamicTask.stop(taskOverdueKey); // 添加任务处理订阅过期 dynamicTask.startDelay(taskOverdueKey, () -> { - System.out.println("订阅过期"); removeMobilePositionSubscribe(subscribeInfo.getId()); }, subscribeInfo.getExpires() * 1000); 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 index 8d72a282..85bc39dc 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java @@ -76,8 +76,8 @@ public class VideoStreamSessionManager { } - public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){ - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream); + public ClientTransaction getTransaction(String deviceId, String channelId, String stream, String callId){ + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, stream); if (ssrcTransaction == null) { return null; } 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 index 8a6e9314..3bab0ebd 100644 --- 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 @@ -652,6 +652,14 @@ public class SIPCommander implements ISIPCommander { (MediaServerItem mediaServerItemInUse, JSONObject json)->{ hookEvent.call(new InviteStreamInfo(mediaServerItem, json, callIdHeader.getCallId(), "rtp", ssrcInfo.getStream())); subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); + subscribeKey.put("regist", false); + subscribeKey.put("schema", "rtmp"); + // 添加流注销的订阅,注销了后向设备发送bye + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{ + logger.info("[录像]下载结束, 发送BYE"); + streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId()); + }); }); Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); @@ -684,10 +692,10 @@ public class SIPCommander implements ISIPCommander { @Override public void streamByeCmd(String deviceId, String channelId, String stream, String callId, SipSubscribe.Event okEvent) { try { - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, null, stream); - ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream); + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callId, stream); + ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId, stream, callId); - if (transaction == null) { + if (transaction == null ) { logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult<>(); if (okEvent != null) { @@ -1664,6 +1672,7 @@ public class SIPCommander implements ISIPCommander { sipSubscribe.addErrorSubscribe(callIdHeader.getCallId(), (eventResult -> { errorEvent.response(eventResult); sipSubscribe.removeErrorSubscribe(eventResult.callId); + sipSubscribe.removeOkSubscribe(eventResult.callId); })); } // 添加订阅 @@ -1671,6 +1680,7 @@ public class SIPCommander implements ISIPCommander { sipSubscribe.addOkSubscribe(callIdHeader.getCallId(), eventResult ->{ okEvent.response(eventResult); sipSubscribe.removeOkSubscribe(eventResult.callId); + sipSubscribe.removeErrorSubscribe(eventResult.callId); }); } 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 index e36a705a..4cf97685 100644 --- 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 @@ -60,10 +60,9 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); String NotifyType =getText(rootElement, "NotifyType"); if (NotifyType.equals("121")){ - logger.info("媒体播放完毕,通知关流"); + logger.info("[录像流]推送完毕,收到关流通知"); String channelId =getText(rootElement, "DeviceID"); -// redisCatchStorage.stopPlayback(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); -// redisCatchStorage.stopDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); + // 查询是设备 StreamInfo streamInfo = redisCatchStorage.queryDownload(device.getDeviceId(), channelId, null, callIdHeader.getCallId()); // 设置进度100% streamInfo.setProgress(1); diff --git a/web_src/src/components/dialog/recordDownload.vue b/web_src/src/components/dialog/recordDownload.vue index 6b7ca1f6..c50e4ce1 100644 --- a/web_src/src/components/dialog/recordDownload.vue +++ b/web_src/src/components/dialog/recordDownload.vue @@ -172,6 +172,7 @@ export default { isEnd: true, } }).then((res) => { + console.log(res) if (res.data.code == 0) { this.percentage = parseFloat(res.data.data.percentage)*100 if (res.data.data[0].percentage === '1') { From 95642d0bb83759603a837ac9935db63439719898 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 21:10:02 +0800 Subject: [PATCH 16/18] =?UTF-8?q?=E4=BC=98=E5=8C=96=E5=BD=95=E5=83=8F?= =?UTF-8?q?=E7=BB=93=E6=9D=9F=E5=8F=91=E9=80=81BYE=E5=88=A4=E6=96=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) 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 index 3bab0ebd..f2e524e4 100644 --- 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 @@ -657,8 +657,11 @@ public class SIPCommander implements ISIPCommander { // 添加流注销的订阅,注销了后向设备发送bye subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, (MediaServerItem mediaServerItemForEnd, JSONObject jsonForEnd)->{ - logger.info("[录像]下载结束, 发送BYE"); - streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId()); + ClientTransaction transaction = streamSession.getTransaction(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId()); + if (transaction != null) { + logger.info("[录像]下载结束, 发送BYE"); + streamByeCmd(device.getDeviceId(), channelId, ssrcInfo.getStream(), callIdHeader.getCallId()); + } }); }); From 9a80e10f6ead2382503a4059f4472471bfd45b8b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 13 May 2022 22:15:31 +0800 Subject: [PATCH 17/18] =?UTF-8?q?=E4=BD=BF=E7=94=A8=20java.time.Instant?= =?UTF-8?q?=E4=BB=A3=E6=9B=BF=20java.util.Date?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../genersoft/iot/vmp/conf/DynamicTask.java | 19 +++++++----- .../DigestServerAuthenticationHelper.java | 10 ++----- .../iot/vmp/gb28181/bean/CatalogData.java | 8 ++--- .../iot/vmp/gb28181/bean/RecordInfo.java | 8 ++--- .../iot/vmp/gb28181/bean/RecordItem.java | 25 ++++++++-------- .../iot/vmp/gb28181/event/SipSubscribe.java | 28 +++++++++--------- .../vmp/gb28181/session/CatalogDataCatch.java | 27 +++++++---------- .../vmp/gb28181/session/RecordDataCatch.java | 17 +++++------ .../request/impl/InviteRequestProcessor.java | 14 ++++----- .../cmd/KeepaliveNotifyMessageHandler.java | 2 -- .../vmp/service/impl/DeviceServiceImpl.java | 29 ++++--------------- 11 files changed, 78 insertions(+), 109 deletions(-) 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 2812f92c..3b021de4 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/DynamicTask.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.conf; import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; -import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -9,25 +8,27 @@ import org.springframework.context.annotation.Bean; import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; import org.springframework.stereotype.Component; -import java.util.Date; +import java.time.Instant; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; /** * 动态定时任务 + * @author lin */ @Component public class DynamicTask { - private Logger logger = LoggerFactory.getLogger(DynamicTask.class); + private final Logger logger = LoggerFactory.getLogger(DynamicTask.class); @Autowired private ThreadPoolTaskScheduler threadPoolTaskScheduler; - private Map> futureMap = new ConcurrentHashMap<>(); - private Map runnableMap = new ConcurrentHashMap<>(); + private final Map> futureMap = new ConcurrentHashMap<>(); + private final Map runnableMap = new ConcurrentHashMap<>(); @Bean public ThreadPoolTaskScheduler threadPoolTaskScheduler() { @@ -47,7 +48,7 @@ public class DynamicTask { * @return */ public void startCron(String key, Runnable task, int cycleForCatalog) { - ScheduledFuture future = futureMap.get(key); + ScheduledFuture future = futureMap.get(key); if (future != null) { if (future.isCancelled()) { logger.debug("任务【{}】已存在但是关闭状态!!!", key); @@ -76,7 +77,9 @@ public class DynamicTask { */ public void startDelay(String key, Runnable task, int delay) { stop(key); - Date starTime = new Date(System.currentTimeMillis() + delay); + + // 获取执行的时刻 + Instant startInstant = Instant.now().plusMillis(TimeUnit.MILLISECONDS.toMillis(delay)); ScheduledFuture future = futureMap.get(key); if (future != null) { @@ -88,7 +91,7 @@ public class DynamicTask { } } // scheduleWithFixedDelay 必须等待上一个任务结束才开始计时period, cycleForCatalog表示执行的间隔 - future = threadPoolTaskScheduler.schedule(task, starTime); + future = threadPoolTaskScheduler.schedule(task, startInstant); if (future != null){ futureMap.put(key, future); runnableMap.put(key, task); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java index f6284f5a..a0e16bff 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/auth/DigestServerAuthenticationHelper.java @@ -27,8 +27,7 @@ package com.genersoft.iot.vmp.gb28181.auth; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; -import java.text.DecimalFormat; -import java.util.Date; +import java.time.Instant; import java.util.Random; import javax.sip.address.URI; @@ -90,17 +89,12 @@ public class DigestServerAuthenticationHelper { * @return a generated nonce. */ private String generateNonce() { - // Get the time of day and run MD5 over it. - Date date = new Date(); - long time = date.getTime(); + long time = Instant.now().toEpochMilli(); Random rand = new Random(); long pad = rand.nextLong(); - // String nonceString = (new Long(time)).toString() - // + (new Long(pad)).toString(); String nonceString = Long.valueOf(time).toString() + Long.valueOf(pad).toString(); byte mdbytes[] = messageDigest.digest(nonceString.getBytes()); - // Convert the mdbytes array into a hex string. return toHexString(mdbytes); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java index 338f8ad5..8a96d356 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/CatalogData.java @@ -1,13 +1,13 @@ package com.genersoft.iot.vmp.gb28181.bean; -import java.util.Date; +import java.time.Instant; import java.util.List; public class CatalogData { private int sn; // 命令序列号 private int total; private List channelList; - private Date lastTime; + private Instant lastTime; private Device device; private String errorMsg; @@ -41,11 +41,11 @@ public class CatalogData { this.channelList = channelList; } - public Date getLastTime() { + public Instant getLastTime() { return lastTime; } - public void setLastTime(Date lastTime) { + public void setLastTime(Instant lastTime) { this.lastTime = lastTime; } 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 index 55bf71f2..2121db7a 100644 --- 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,6 +1,6 @@ package com.genersoft.iot.vmp.gb28181.bean; -import java.util.Date; +import java.time.Instant; import java.util.List; /** @@ -20,7 +20,7 @@ public class RecordInfo { private int sumNum; - private Date lastTime; + private Instant lastTime; private List recordList; @@ -72,11 +72,11 @@ public class RecordInfo { this.sn = sn; } - public Date getLastTime() { + public Instant getLastTime() { return lastTime; } - public void setLastTime(Date lastTime) { + public void setLastTime(Instant lastTime) { this.lastTime = lastTime; } } 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 index 3349cdc5..a47147a1 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordItem.java @@ -5,7 +5,8 @@ import com.genersoft.iot.vmp.utils.DateUtil; import org.jetbrains.annotations.NotNull; import java.text.ParseException; -import java.util.Date; +import java.time.Instant; +import java.time.temporal.TemporalAccessor; /** * @description:设备录像bean @@ -116,17 +117,17 @@ public class RecordItem implements Comparable{ @Override public int compareTo(@NotNull RecordItem recordItem) { - try { - Date startTime_now = DateUtil.format.parse(startTime); - Date startTime_param = DateUtil.format.parse(recordItem.getStartTime()); - if (startTime_param.compareTo(startTime_now) > 0) { - return -1; - }else { - return 1; - } - } catch (ParseException e) { - e.printStackTrace(); + 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; } - return 0; + } } 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 index bc775e46..3d817c34 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java @@ -9,11 +9,14 @@ import org.springframework.stereotype.Component; import javax.sip.*; import javax.sip.header.CallIdHeader; import javax.sip.message.Response; -import java.util.Calendar; -import java.util.Date; +import java.time.Instant; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; +/** + * @author lin + */ @Component public class SipSubscribe { @@ -23,28 +26,25 @@ public class SipSubscribe { private Map okSubscribes = new ConcurrentHashMap<>(); - private Map okTimeSubscribes = new ConcurrentHashMap<>(); - private Map errorTimeSubscribes = new ConcurrentHashMap<>(); + private Map okTimeSubscribes = new ConcurrentHashMap<>(); + private Map errorTimeSubscribes = new ConcurrentHashMap<>(); // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 -// @Scheduled(fixedRate= 100 * 60 * 60 ) + // @Scheduled(fixedRate= 100 * 60 * 60 ) @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次 public void execute(){ logger.info("[定时任务] 清理过期的SIP订阅信息"); - Calendar calendar = Calendar.getInstance(); - calendar.setTime(new Date()); - calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5); + + Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); for (String key : okTimeSubscribes.keySet()) { - if (okTimeSubscribes.get(key).before(calendar.getTime())){ -// logger.info("[定时任务] 清理过期的订阅信息: {}", key); + if (okTimeSubscribes.get(key).isBefore(instant)){ okSubscribes.remove(key); okTimeSubscribes.remove(key); } } for (String key : errorTimeSubscribes.keySet()) { - if (errorTimeSubscribes.get(key).before(calendar.getTime())){ -// logger.info("[定时任务] 清理过期的订阅信息: {}", key); + if (errorTimeSubscribes.get(key).isBefore(instant)){ errorSubscribes.remove(key); errorTimeSubscribes.remove(key); } @@ -117,12 +117,12 @@ public class SipSubscribe { public void addErrorSubscribe(String key, SipSubscribe.Event event) { errorSubscribes.put(key, event); - errorTimeSubscribes.put(key, new Date()); + errorTimeSubscribes.put(key, Instant.now()); } public void addOkSubscribe(String key, SipSubscribe.Event event) { okSubscribes.put(key, event); - okTimeSubscribes.put(key, new Date()); + okTimeSubscribes.put(key, Instant.now()); } public SipSubscribe.Event getErrorSubscribe(String key) { 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 index 75b9f59a..7ed3c116 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/CatalogDataCatch.java @@ -4,25 +4,21 @@ import com.genersoft.iot.vmp.gb28181.bean.CatalogData; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; -import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; +import java.time.Instant; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; @Component public class CatalogDataCatch { public static Map data = new ConcurrentHashMap<>(); - @Autowired - private DeferredResultHolder deferredResultHolder; - @Autowired private IVideoManagerStorage storager; @@ -34,7 +30,7 @@ public class CatalogDataCatch { catalogData.setDevice(device); catalogData.setSn(sn); catalogData.setStatus(CatalogData.CatalogDataStatus.ready); - catalogData.setLastTime(new Date(System.currentTimeMillis())); + catalogData.setLastTime(Instant.now()); data.put(device.getDeviceId(), catalogData); } } @@ -48,7 +44,7 @@ public class CatalogDataCatch { catalogData.setDevice(device); catalogData.setChannelList(Collections.synchronizedList(new ArrayList<>())); catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); - catalogData.setLastTime(new Date(System.currentTimeMillis())); + catalogData.setLastTime(Instant.now()); data.put(deviceId, catalogData); }else { // 同一个设备的通道同步请求只考虑一个,其他的直接忽略 @@ -59,7 +55,7 @@ public class CatalogDataCatch { catalogData.setDevice(device); catalogData.setStatus(CatalogData.CatalogDataStatus.runIng); catalogData.getChannelList().addAll(deviceChannelList); - catalogData.setLastTime(new Date(System.currentTimeMillis())); + catalogData.setLastTime(Instant.now()); } } @@ -102,16 +98,13 @@ public class CatalogDataCatch { @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 private void timerTask(){ Set keys = data.keySet(); - Calendar calendarBefore5S = Calendar.getInstance(); - calendarBefore5S.setTime(new Date()); - calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5); - Calendar calendarBefore30S = Calendar.getInstance(); - calendarBefore30S.setTime(new Date()); - calendarBefore30S.set(Calendar.SECOND, calendarBefore30S.get(Calendar.SECOND) - 30); + Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5)); + Instant instantBefore30S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(30)); + for (String deviceId : keys) { CatalogData catalogData = data.get(deviceId); - if ( catalogData.getLastTime().before(calendarBefore5S.getTime())) { // 超过五秒收不到消息任务超时, 只更新这一部分数据 + if ( catalogData.getLastTime().isBefore(instantBefore5S)) { // 超过五秒收不到消息任务超时, 只更新这一部分数据 if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.runIng)) { storager.resetChannels(catalogData.getDevice().getDeviceId(), catalogData.getChannelList()); if (catalogData.getTotal() != catalogData.getChannelList().size()) { @@ -124,7 +117,7 @@ public class CatalogDataCatch { } catalogData.setStatus(CatalogData.CatalogDataStatus.end); } - if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().before(calendarBefore30S.getTime())) { // 超过三十秒,如果标记为end则删除 + if (catalogData.getStatus().equals(CatalogData.CatalogDataStatus.end) && catalogData.getLastTime().isBefore(instantBefore30S)) { // 超过三十秒,如果标记为end则删除 data.remove(deviceId); } } 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 index 0d166c12..dd5b8dfe 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/RecordDataCatch.java @@ -3,16 +3,15 @@ package com.genersoft.iot.vmp.gb28181.session; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; -import java.text.SimpleDateFormat; +import java.time.Instant; import java.util.*; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; /** * @author lin @@ -35,7 +34,7 @@ public class RecordDataCatch { recordInfo.setSn(sn.trim()); recordInfo.setSumNum(sumNum); recordInfo.setRecordList(Collections.synchronizedList(new ArrayList<>())); - recordInfo.setLastTime(new Date(System.currentTimeMillis())); + recordInfo.setLastTime(Instant.now()); recordInfo.getRecordList().addAll(recordItems); data.put(key, recordInfo); }else { @@ -44,7 +43,7 @@ public class RecordDataCatch { return 0; } recordInfo.getRecordList().addAll(recordItems); - recordInfo.setLastTime(new Date(System.currentTimeMillis())); + recordInfo.setLastTime(Instant.now()); } return recordInfo.getRecordList().size(); } @@ -52,14 +51,12 @@ public class RecordDataCatch { @Scheduled(fixedRate = 5 * 1000) //每5秒执行一次, 发现数据5秒未更新则移除数据并认为数据接收超时 private void timerTask(){ Set keys = data.keySet(); - Calendar calendarBefore5S = Calendar.getInstance(); - calendarBefore5S.setTime(new Date()); - calendarBefore5S.set(Calendar.SECOND, calendarBefore5S.get(Calendar.SECOND) - 5); - + // 获取五秒前的时刻 + Instant instantBefore5S = Instant.now().minusMillis(TimeUnit.SECONDS.toMillis(5)); for (String key : keys) { RecordInfo recordInfo = data.get(key); // 超过五秒收不到消息任务超时, 只更新这一部分数据 - if ( recordInfo.getLastTime().before(calendarBefore5S.getTime())) { + if ( recordInfo.getLastTime().isBefore(instantBefore5S)) { // 处理录像数据, 返回给前端 String msgKey = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn(); 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 index 7c63279d..2723da47 100644 --- 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 @@ -40,7 +40,7 @@ import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import javax.sip.message.Response; import java.text.ParseException; -import java.util.Date; +import java.time.Instant; import java.util.Vector; /** @@ -180,16 +180,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements Long startTime = null; Long stopTime = null; - Date start = null; - Date end = null; + Instant start = null; + Instant end = null; if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) { TimeDescriptionImpl timeDescription = (TimeDescriptionImpl)(sdp.getTimeDescriptions(false).get(0)); TimeField startTimeFiled = (TimeField)timeDescription.getTime(); startTime = startTimeFiled.getStartTime(); stopTime = startTimeFiled.getStopTime(); - start = new Date(startTime*1000); - end = new Date(stopTime*1000); + start = Instant.ofEpochMilli(startTime*1000); + end = Instant.ofEpochMilli(stopTime*1000); } // 获取支持的格式 Vector mediaDescriptions = sdp.getMediaDescriptions(true); @@ -335,8 +335,8 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements sendRtpItem.setStreamId(ssrcInfo.getStream()); // 写入redis, 超时时回复 redisCatchStorage.updateSendRTPSever(sendRtpItem); - playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.format.format(start), - DateUtil.format.format(end), null, result -> { + playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), + DateUtil.formatter.format(end), null, result -> { if (result.getCode() != 0){ logger.warn("录像回放失败"); if (result.getEvent() != null) { 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 index a6280831..d5d4c1d0 100644 --- 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 @@ -24,8 +24,6 @@ import javax.sip.SipException; import javax.sip.header.ViaHeader; import javax.sip.message.Response; import java.text.ParseException; -import java.util.Calendar; -import java.util.Date; @Component public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent implements InitializingBean, IMessageHandler { 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 index 5cfa8525..0144e83b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -11,24 +11,18 @@ import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; import com.genersoft.iot.vmp.gb28181.bean.SyncStatus; import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; import com.genersoft.iot.vmp.utils.DateUtil; 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.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; -import javax.sip.DialogState; -import javax.sip.TimeoutEvent; -import java.text.ParseException; -import java.util.Calendar; -import java.util.Date; +import java.time.Instant; import java.util.List; +import java.util.concurrent.TimeUnit; /** * 设备业务(目录订阅) @@ -101,9 +95,7 @@ public class DeviceServiceImpl implements IDeviceService { // 刷新过期任务 String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); dynamicTask.stop(registerExpireTaskKey); - dynamicTask.startDelay(registerExpireTaskKey, ()->{ - offline(device.getDeviceId()); - }, device.getExpires() * 1000); + dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); } @Override @@ -217,18 +209,9 @@ public class DeviceServiceImpl implements IDeviceService { @Override public boolean expire(Device device) { - Date registerTimeDate; - try { - registerTimeDate = DateUtil.format.parse(device.getRegisterTime()); - } catch (ParseException e) { - logger.error("设备时间格式化失败:{}->{} ", device.getDeviceId(), device.getRegisterTime() ); - return false; - } - int expires = device.getExpires(); - Calendar calendarForExpire = Calendar.getInstance(); - calendarForExpire.setTime(registerTimeDate); - calendarForExpire.set(Calendar.SECOND, calendarForExpire.get(Calendar.SECOND) + expires); - return calendarForExpire.before(DateUtil.getNow()); + Instant registerTimeDate = Instant.from(DateUtil.formatter.parse(device.getRegisterTime())); + Instant expireInstant = registerTimeDate.plusMillis(TimeUnit.SECONDS.toMillis(device.getExpires())); + return expireInstant.isBefore(Instant.now()); } @Override From bfb3b4ea13dcfd360c313375d03658dfc82e19ef Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 16 May 2022 17:49:44 +0800 Subject: [PATCH 18/18] =?UTF-8?q?=E6=92=AD=E6=94=BE=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=89=80=E6=9C=89=E6=B5=81=E5=9C=B0=E5=9D=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web_src/src/components/channelList.vue | 2 + .../src/components/dialog/devicePlayer.vue | 122 ++++++++++++++++-- 2 files changed, 114 insertions(+), 10 deletions(-) diff --git a/web_src/src/components/channelList.vue b/web_src/src/components/channelList.vue index 9c7ab8ef..21223ce1 100644 --- a/web_src/src/components/channelList.vue +++ b/web_src/src/components/channelList.vue @@ -237,6 +237,8 @@ export default { that.initData(); }, 1000) + }else{ + that.$message.error(res.data.msg); } }).catch(function (e) { that.isLoging = false; diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index 921e4136..43a929c5 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -33,10 +33,100 @@
资源地址: - + + + + 更多地址 + + + + FLV: + {{ streamInfo.flv }} + + + FLV(https): + {{ streamInfo.https_flv }} + + + FLV(ws): + {{ streamInfo.ws_flv }} + + + FLV(wss): + {{ streamInfo.wss_flv }} + + + FMP4: + {{ streamInfo.fmp4 }} + + + FMP4(https): + {{ streamInfo.https_fmp4 }} + + + FMP4(ws): + {{ streamInfo.ws_fmp4 }} + + + FMP4(wss): + {{ streamInfo.wss_fmp4 }} + + + HLS: + {{ streamInfo.hls }} + + + HLS(https): + {{ streamInfo.https_hls }} + + + HLS(ws): + {{ streamInfo.ws_hls }} + + + HLS(wss): + {{ streamInfo.wss_hls }} + + + TS: + {{ streamInfo.ts }} + + + TS(https): + {{ streamInfo.https_ts }} + + + TS(ws): + {{ streamInfo.ws_ts }} + + + TS(wss): + {{ streamInfo.wss_ts }} + + + RTC: + {{ streamInfo.rtc }} + + + RTMP: + {{ streamInfo.rtmp }} + + + RTMPS: + {{ streamInfo.rtmps }} + + + RTSP: + {{ streamInfo.rtsp }} + + + RTSPS: + {{ streamInfo.rtsps }} + + + +
@@ -117,27 +207,27 @@
- 预置位编号 + 预置位编号 设置 调用 删除 - 巡航速度 + 巡航速度 设置 - 停留时间 + 停留时间 设置 - 巡航组编号 + 巡航组编号 添加点 删除点 删除组 巡航 - 扫描速度 + 扫描速度 设置 - 扫描组编号 + 扫描组编号 左边界 右边界 @@ -174,6 +264,7 @@
+ @@ -244,6 +335,7 @@ export default { seekTime: 0, recordStartTime: 0, showTimeText: "00:00:00", + streamInfo: null, }; }, methods: { @@ -306,6 +398,7 @@ export default { console.log(val) }, play: function (streamInfo, hasAudio) { + this.streamInfo = streamInfo; this.hasAudio = hasAudio; this.isLoging = false; // this.videoUrl = streamInfo.rtc; @@ -646,6 +739,14 @@ export default { console.log(resultArray) return resultArray; }, + copyUrl: function (dropdownItem){ + console.log(dropdownItem) + this.$copyText(dropdownItem).then((e)=> { + this.$message.success("成功拷贝到粘贴板"); + }, (e)=> { + + }) + }, gbPlay(){ console.log('前端控制:播放'); this.$axios({ @@ -686,7 +787,8 @@ export default { this.$refs.videoPlayer.play(this.videoUrl) }, 600) }); - } + }, + } };