Commit 5e73874880cdfd5b6b99147a0cdd8a6eabcfbf16
1 parent
710600db
添加队列处理redis消息和sip消息,支持使用推流状态作为通道在线状态
Showing
19 changed files
with
645 additions
and
436 deletions
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| ... | ... | @@ -31,6 +31,8 @@ public class UserSetting { |
| 31 | 31 | |
| 32 | 32 | private Boolean logInDatebase = Boolean.TRUE; |
| 33 | 33 | |
| 34 | + private Boolean usePushingAsStatus = Boolean.TRUE; | |
| 35 | + | |
| 34 | 36 | private String serverId = "000000"; |
| 35 | 37 | |
| 36 | 38 | private String thirdPartyGBIdReg = "[\\s\\S]*"; |
| ... | ... | @@ -136,4 +138,12 @@ public class UserSetting { |
| 136 | 138 | public void setPlatformPlayTimeout(int platformPlayTimeout) { |
| 137 | 139 | this.platformPlayTimeout = platformPlayTimeout; |
| 138 | 140 | } |
| 141 | + | |
| 142 | + public Boolean isUsePushingAsStatus() { | |
| 143 | + return usePushingAsStatus; | |
| 144 | + } | |
| 145 | + | |
| 146 | + public void setUsePushingAsStatus(Boolean usePushingAsStatus) { | |
| 147 | + this.usePushingAsStatus = usePushingAsStatus; | |
| 148 | + } | |
| 139 | 149 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisConfig.java
| ... | ... | @@ -3,7 +3,7 @@ package com.genersoft.iot.vmp.conf.redis; |
| 3 | 3 | |
| 4 | 4 | import com.alibaba.fastjson.parser.ParserConfig; |
| 5 | 5 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 6 | -import com.genersoft.iot.vmp.service.impl.*; | |
| 6 | +import com.genersoft.iot.vmp.service.redisMsg.*; | |
| 7 | 7 | import org.springframework.beans.factory.annotation.Autowired; |
| 8 | 8 | import org.springframework.cache.annotation.CachingConfigurerSupport; |
| 9 | 9 | import org.springframework.context.annotation.Bean; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SipMsgInfo.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.bean; | |
| 2 | + | |
| 3 | +import org.dom4j.Element; | |
| 4 | + | |
| 5 | +import javax.sip.RequestEvent; | |
| 6 | + | |
| 7 | +public class SipMsgInfo { | |
| 8 | + private RequestEvent evt; | |
| 9 | + private Device device; | |
| 10 | + private ParentPlatform platform; | |
| 11 | + private Element rootElement; | |
| 12 | + | |
| 13 | + public SipMsgInfo(RequestEvent evt, Device device, Element rootElement) { | |
| 14 | + this.evt = evt; | |
| 15 | + this.device = device; | |
| 16 | + this.rootElement = rootElement; | |
| 17 | + } | |
| 18 | + | |
| 19 | + public SipMsgInfo(RequestEvent evt, ParentPlatform platform, Element rootElement) { | |
| 20 | + this.evt = evt; | |
| 21 | + this.platform = platform; | |
| 22 | + this.rootElement = rootElement; | |
| 23 | + } | |
| 24 | + | |
| 25 | + public RequestEvent getEvt() { | |
| 26 | + return evt; | |
| 27 | + } | |
| 28 | + | |
| 29 | + public void setEvt(RequestEvent evt) { | |
| 30 | + this.evt = evt; | |
| 31 | + } | |
| 32 | + | |
| 33 | + public Device getDevice() { | |
| 34 | + return device; | |
| 35 | + } | |
| 36 | + | |
| 37 | + public void setDevice(Device device) { | |
| 38 | + this.device = device; | |
| 39 | + } | |
| 40 | + | |
| 41 | + public ParentPlatform getPlatform() { | |
| 42 | + return platform; | |
| 43 | + } | |
| 44 | + | |
| 45 | + public void setPlatform(ParentPlatform platform) { | |
| 46 | + this.platform = platform; | |
| 47 | + } | |
| 48 | + | |
| 49 | + public Element getRootElement() { | |
| 50 | + return rootElement; | |
| 51 | + } | |
| 52 | + | |
| 53 | + public void setRootElement(Element rootElement) { | |
| 54 | + this.rootElement = rootElement; | |
| 55 | + } | |
| 56 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| ... | ... | @@ -14,18 +14,15 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 14 | 14 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 15 | 15 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 16 | 16 | import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; |
| 17 | -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener; | |
| 17 | +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | |
| 18 | 18 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 19 | 19 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 20 | -import com.genersoft.iot.vmp.utils.SerializeUtils; | |
| 21 | 20 | import org.slf4j.Logger; |
| 22 | 21 | import org.slf4j.LoggerFactory; |
| 23 | 22 | import org.springframework.beans.factory.InitializingBean; |
| 24 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 25 | 24 | import org.springframework.stereotype.Component; |
| 26 | 25 | |
| 27 | -import javax.sip.Dialog; | |
| 28 | -import javax.sip.DialogState; | |
| 29 | 26 | import javax.sip.RequestEvent; |
| 30 | 27 | import javax.sip.address.SipURI; |
| 31 | 28 | import javax.sip.header.CallIdHeader; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| ... | ... | @@ -22,8 +22,8 @@ import com.genersoft.iot.vmp.service.IStreamProxyService; |
| 22 | 22 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| 23 | 23 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 24 | 24 | import com.genersoft.iot.vmp.service.bean.SSRCInfo; |
| 25 | -import com.genersoft.iot.vmp.service.impl.RedisGbPlayMsgListener; | |
| 26 | -import com.genersoft.iot.vmp.service.impl.RedisPushStreamResponseListener; | |
| 25 | +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | |
| 26 | +import com.genersoft.iot.vmp.service.redisMsg.RedisPushStreamResponseListener; | |
| 27 | 27 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 28 | 28 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 29 | 29 | import com.genersoft.iot.vmp.utils.DateUtil; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/AlarmNotifyMessageHandler.java
| ... | ... | @@ -21,6 +21,8 @@ import org.slf4j.Logger; |
| 21 | 21 | import org.slf4j.LoggerFactory; |
| 22 | 22 | import org.springframework.beans.factory.InitializingBean; |
| 23 | 23 | import org.springframework.beans.factory.annotation.Autowired; |
| 24 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 25 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 24 | 26 | import org.springframework.stereotype.Component; |
| 25 | 27 | import org.springframework.util.ObjectUtils; |
| 26 | 28 | import org.springframework.util.StringUtils; |
| ... | ... | @@ -31,6 +33,7 @@ import javax.sip.SipException; |
| 31 | 33 | import javax.sip.message.Response; |
| 32 | 34 | |
| 33 | 35 | import java.text.ParseException; |
| 36 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 34 | 37 | |
| 35 | 38 | import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.*; |
| 36 | 39 | |
| ... | ... | @@ -67,6 +70,15 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme |
| 67 | 70 | @Autowired |
| 68 | 71 | private IDeviceChannelService deviceChannelService; |
| 69 | 72 | |
| 73 | + private boolean taskQueueHandlerRun = false; | |
| 74 | + | |
| 75 | + private final ConcurrentLinkedQueue<SipMsgInfo> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 76 | + | |
| 77 | + @Qualifier("taskExecutor") | |
| 78 | + @Autowired | |
| 79 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 80 | + | |
| 81 | + | |
| 70 | 82 | @Override |
| 71 | 83 | public void afterPropertiesSet() throws Exception { |
| 72 | 84 | notifyMessageHandler.addHandler(cmdType, this); |
| ... | ... | @@ -75,114 +87,127 @@ public class AlarmNotifyMessageHandler extends SIPRequestProcessorParent impleme |
| 75 | 87 | @Override |
| 76 | 88 | public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
| 77 | 89 | logger.info("[收到报警通知]设备:{}", device.getDeviceId()); |
| 78 | - // 回复200 OK | |
| 79 | - try { | |
| 80 | - responseAck(getServerTransaction(evt), Response.OK); | |
| 81 | - } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 82 | - logger.error("[收到报警通知], 回复200OK失败", e); | |
| 83 | - } | |
| 84 | - | |
| 85 | - Element deviceIdElement = rootElement.element("DeviceID"); | |
| 86 | - String channelId = deviceIdElement.getText().toString(); | |
| 87 | 90 | |
| 88 | - DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 89 | - deviceAlarm.setCreateTime(DateUtil.getNow()); | |
| 90 | - deviceAlarm.setDeviceId(device.getDeviceId()); | |
| 91 | - deviceAlarm.setChannelId(channelId); | |
| 92 | - deviceAlarm.setAlarmPriority(getText(rootElement, "AlarmPriority")); | |
| 93 | - deviceAlarm.setAlarmMethod(getText(rootElement, "AlarmMethod")); | |
| 94 | - String alarmTime = XmlUtil.getText(rootElement, "AlarmTime"); | |
| 95 | - if (alarmTime == null) { | |
| 96 | - return; | |
| 97 | - } | |
| 98 | - deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); | |
| 99 | - String alarmDescription = getText(rootElement, "AlarmDescription"); | |
| 100 | - if (alarmDescription == null) { | |
| 101 | - deviceAlarm.setAlarmDescription(""); | |
| 102 | - } else { | |
| 103 | - deviceAlarm.setAlarmDescription(alarmDescription); | |
| 104 | - } | |
| 105 | - String longitude = getText(rootElement, "Longitude"); | |
| 106 | - if (longitude != null && NumericUtil.isDouble(longitude)) { | |
| 107 | - deviceAlarm.setLongitude(Double.parseDouble(longitude)); | |
| 108 | - } else { | |
| 109 | - deviceAlarm.setLongitude(0.00); | |
| 110 | - } | |
| 111 | - String latitude = getText(rootElement, "Latitude"); | |
| 112 | - if (latitude != null && NumericUtil.isDouble(latitude)) { | |
| 113 | - deviceAlarm.setLatitude(Double.parseDouble(latitude)); | |
| 114 | - } else { | |
| 115 | - deviceAlarm.setLatitude(0.00); | |
| 116 | - } | |
| 117 | - | |
| 118 | - if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) { | |
| 119 | - if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) { | |
| 120 | - MobilePosition mobilePosition = new MobilePosition(); | |
| 121 | - mobilePosition.setCreateTime(DateUtil.getNow()); | |
| 122 | - mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); | |
| 123 | - mobilePosition.setTime(deviceAlarm.getAlarmTime()); | |
| 124 | - mobilePosition.setLongitude(deviceAlarm.getLongitude()); | |
| 125 | - mobilePosition.setLatitude(deviceAlarm.getLatitude()); | |
| 126 | - mobilePosition.setReportSource("GPS Alarm"); | |
| 127 | - | |
| 128 | - // 更新device channel 的经纬度 | |
| 129 | - DeviceChannel deviceChannel = new DeviceChannel(); | |
| 130 | - deviceChannel.setDeviceId(device.getDeviceId()); | |
| 131 | - deviceChannel.setChannelId(channelId); | |
| 132 | - deviceChannel.setLongitude(mobilePosition.getLongitude()); | |
| 133 | - deviceChannel.setLatitude(mobilePosition.getLatitude()); | |
| 134 | - deviceChannel.setGpsTime(mobilePosition.getTime()); | |
| 135 | - | |
| 136 | - deviceChannel = deviceChannelService.updateGps(deviceChannel, device); | |
| 137 | - | |
| 138 | - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); | |
| 139 | - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); | |
| 140 | - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); | |
| 141 | - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); | |
| 142 | - | |
| 143 | - if (userSetting.getSavePositionHistory()) { | |
| 144 | - storager.insertMobilePosition(mobilePosition); | |
| 91 | + taskQueue.offer(new SipMsgInfo(evt, device, rootElement)); | |
| 92 | + if (!taskQueueHandlerRun) { | |
| 93 | + taskQueueHandlerRun = true; | |
| 94 | + taskExecutor.execute(() -> { | |
| 95 | + while (!taskQueue.isEmpty()) { | |
| 96 | + SipMsgInfo sipMsgInfo = taskQueue.poll(); | |
| 97 | + // 回复200 OK | |
| 98 | + try { | |
| 99 | + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK); | |
| 100 | + } catch (SipException | InvalidArgumentException | ParseException e) { | |
| 101 | + logger.error("[收到报警通知], 回复200OK失败", e); | |
| 102 | + } | |
| 103 | + | |
| 104 | + Element deviceIdElement = sipMsgInfo.getRootElement().element("DeviceID"); | |
| 105 | + String channelId = deviceIdElement.getText().toString(); | |
| 106 | + | |
| 107 | + DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 108 | + deviceAlarm.setCreateTime(DateUtil.getNow()); | |
| 109 | + deviceAlarm.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); | |
| 110 | + deviceAlarm.setChannelId(channelId); | |
| 111 | + deviceAlarm.setAlarmPriority(getText(sipMsgInfo.getRootElement(), "AlarmPriority")); | |
| 112 | + deviceAlarm.setAlarmMethod(getText(sipMsgInfo.getRootElement(), "AlarmMethod")); | |
| 113 | + String alarmTime = XmlUtil.getText(sipMsgInfo.getRootElement(), "AlarmTime"); | |
| 114 | + if (alarmTime == null) { | |
| 115 | + return; | |
| 116 | + } | |
| 117 | + deviceAlarm.setAlarmTime(DateUtil.ISO8601Toyyyy_MM_dd_HH_mm_ss(alarmTime)); | |
| 118 | + String alarmDescription = getText(sipMsgInfo.getRootElement(), "AlarmDescription"); | |
| 119 | + if (alarmDescription == null) { | |
| 120 | + deviceAlarm.setAlarmDescription(""); | |
| 121 | + } else { | |
| 122 | + deviceAlarm.setAlarmDescription(alarmDescription); | |
| 123 | + } | |
| 124 | + String longitude = getText(sipMsgInfo.getRootElement(), "Longitude"); | |
| 125 | + if (longitude != null && NumericUtil.isDouble(longitude)) { | |
| 126 | + deviceAlarm.setLongitude(Double.parseDouble(longitude)); | |
| 127 | + } else { | |
| 128 | + deviceAlarm.setLongitude(0.00); | |
| 129 | + } | |
| 130 | + String latitude = getText(sipMsgInfo.getRootElement(), "Latitude"); | |
| 131 | + if (latitude != null && NumericUtil.isDouble(latitude)) { | |
| 132 | + deviceAlarm.setLatitude(Double.parseDouble(latitude)); | |
| 133 | + } else { | |
| 134 | + deviceAlarm.setLatitude(0.00); | |
| 135 | + } | |
| 136 | + | |
| 137 | + if (!ObjectUtils.isEmpty(deviceAlarm.getAlarmMethod())) { | |
| 138 | + if ( deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.GPS.getVal() + "")) { | |
| 139 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 140 | + mobilePosition.setCreateTime(DateUtil.getNow()); | |
| 141 | + mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); | |
| 142 | + mobilePosition.setTime(deviceAlarm.getAlarmTime()); | |
| 143 | + mobilePosition.setLongitude(deviceAlarm.getLongitude()); | |
| 144 | + mobilePosition.setLatitude(deviceAlarm.getLatitude()); | |
| 145 | + mobilePosition.setReportSource("GPS Alarm"); | |
| 146 | + | |
| 147 | + // 更新device channel 的经纬度 | |
| 148 | + DeviceChannel deviceChannel = new DeviceChannel(); | |
| 149 | + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); | |
| 150 | + deviceChannel.setChannelId(channelId); | |
| 151 | + deviceChannel.setLongitude(mobilePosition.getLongitude()); | |
| 152 | + deviceChannel.setLatitude(mobilePosition.getLatitude()); | |
| 153 | + deviceChannel.setGpsTime(mobilePosition.getTime()); | |
| 154 | + | |
| 155 | + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice()); | |
| 156 | + | |
| 157 | + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); | |
| 158 | + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); | |
| 159 | + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); | |
| 160 | + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); | |
| 161 | + | |
| 162 | + if (userSetting.getSavePositionHistory()) { | |
| 163 | + storager.insertMobilePosition(mobilePosition); | |
| 164 | + } | |
| 165 | + storager.updateChannelPosition(deviceChannel); | |
| 166 | + | |
| 167 | + // 发送redis消息。 通知位置信息的变化 | |
| 168 | + JSONObject jsonObject = new JSONObject(); | |
| 169 | + jsonObject.put("time", mobilePosition.getTime()); | |
| 170 | + jsonObject.put("serial", deviceChannel.getDeviceId()); | |
| 171 | + jsonObject.put("code", deviceChannel.getChannelId()); | |
| 172 | + jsonObject.put("longitude", mobilePosition.getLongitude()); | |
| 173 | + jsonObject.put("latitude", mobilePosition.getLatitude()); | |
| 174 | + jsonObject.put("altitude", mobilePosition.getAltitude()); | |
| 175 | + jsonObject.put("direction", mobilePosition.getDirection()); | |
| 176 | + jsonObject.put("speed", mobilePosition.getSpeed()); | |
| 177 | + redisCatchStorage.sendMobilePositionMsg(jsonObject); | |
| 178 | + } | |
| 179 | + } | |
| 180 | + if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) { | |
| 181 | + if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) { | |
| 182 | + deviceAlarm.setAlarmType(getText(sipMsgInfo.getRootElement().element("Info"), "AlarmType")); | |
| 183 | + } | |
| 184 | + } | |
| 185 | + | |
| 186 | + if ("7".equals(deviceAlarm.getAlarmMethod()) ) { | |
| 187 | + // 发送给平台的报警信息。 发送redis通知 | |
| 188 | + AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); | |
| 189 | + alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | |
| 190 | + alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); | |
| 191 | + alarmChannelMessage.setGbId(channelId); | |
| 192 | + redisCatchStorage.sendAlarmMsg(alarmChannelMessage); | |
| 193 | + return; | |
| 194 | + } | |
| 195 | + | |
| 196 | + logger.debug("存储报警信息、报警分类"); | |
| 197 | + // 存储报警信息、报警分类 | |
| 198 | + if (sipConfig.isAlarm()) { | |
| 199 | + deviceAlarmService.add(deviceAlarm); | |
| 200 | + } | |
| 201 | + logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); | |
| 202 | + if (redisCatchStorage.deviceIsOnline(sipMsgInfo.getDevice().getDeviceId())) { | |
| 203 | + publisher.deviceAlarmEventPublish(deviceAlarm); | |
| 204 | + } | |
| 145 | 205 | } |
| 146 | - storager.updateChannelPosition(deviceChannel); | |
| 147 | - | |
| 148 | - // 发送redis消息。 通知位置信息的变化 | |
| 149 | - JSONObject jsonObject = new JSONObject(); | |
| 150 | - jsonObject.put("time", mobilePosition.getTime()); | |
| 151 | - jsonObject.put("serial", deviceChannel.getDeviceId()); | |
| 152 | - jsonObject.put("code", deviceChannel.getChannelId()); | |
| 153 | - jsonObject.put("longitude", mobilePosition.getLongitude()); | |
| 154 | - jsonObject.put("latitude", mobilePosition.getLatitude()); | |
| 155 | - jsonObject.put("altitude", mobilePosition.getAltitude()); | |
| 156 | - jsonObject.put("direction", mobilePosition.getDirection()); | |
| 157 | - jsonObject.put("speed", mobilePosition.getSpeed()); | |
| 158 | - redisCatchStorage.sendMobilePositionMsg(jsonObject); | |
| 159 | - } | |
| 160 | - } | |
| 161 | - if (!ObjectUtils.isEmpty(deviceAlarm.getDeviceId())) { | |
| 162 | - if (deviceAlarm.getAlarmMethod().contains(DeviceAlarmMethod.Video.getVal() + "")) { | |
| 163 | - deviceAlarm.setAlarmType(getText(rootElement.element("Info"), "AlarmType")); | |
| 164 | - } | |
| 206 | + taskQueueHandlerRun = false; | |
| 207 | + }); | |
| 165 | 208 | } |
| 166 | 209 | |
| 167 | - if ("7".equals(deviceAlarm.getAlarmMethod()) ) { | |
| 168 | - // 发送给平台的报警信息。 发送redis通知 | |
| 169 | - AlarmChannelMessage alarmChannelMessage = new AlarmChannelMessage(); | |
| 170 | - alarmChannelMessage.setAlarmSn(Integer.parseInt(deviceAlarm.getAlarmMethod())); | |
| 171 | - alarmChannelMessage.setAlarmDescription(deviceAlarm.getAlarmDescription()); | |
| 172 | - alarmChannelMessage.setGbId(channelId); | |
| 173 | - redisCatchStorage.sendAlarmMsg(alarmChannelMessage); | |
| 174 | - return; | |
| 175 | - } | |
| 176 | 210 | |
| 177 | - logger.debug("存储报警信息、报警分类"); | |
| 178 | - // 存储报警信息、报警分类 | |
| 179 | - if (sipConfig.isAlarm()) { | |
| 180 | - deviceAlarmService.add(deviceAlarm); | |
| 181 | - } | |
| 182 | - logger.info("[收到报警通知]内容:{}", JSONObject.toJSON(deviceAlarm)); | |
| 183 | - if (redisCatchStorage.deviceIsOnline(device.getDeviceId())) { | |
| 184 | - publisher.deviceAlarmEventPublish(deviceAlarm); | |
| 185 | - } | |
| 186 | 211 | } |
| 187 | 212 | |
| 188 | 213 | @Override | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MobilePositionNotifyMessageHandler.java
| ... | ... | @@ -17,6 +17,8 @@ import org.slf4j.Logger; |
| 17 | 17 | import org.slf4j.LoggerFactory; |
| 18 | 18 | import org.springframework.beans.factory.InitializingBean; |
| 19 | 19 | import org.springframework.beans.factory.annotation.Autowired; |
| 20 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 21 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 20 | 22 | import org.springframework.stereotype.Component; |
| 21 | 23 | import org.springframework.util.ObjectUtils; |
| 22 | 24 | import org.springframework.util.StringUtils; |
| ... | ... | @@ -26,6 +28,7 @@ import javax.sip.RequestEvent; |
| 26 | 28 | import javax.sip.SipException; |
| 27 | 29 | import javax.sip.message.Response; |
| 28 | 30 | import java.text.ParseException; |
| 31 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 29 | 32 | |
| 30 | 33 | import static com.genersoft.iot.vmp.gb28181.utils.XmlUtil.getText; |
| 31 | 34 | |
| ... | ... | @@ -53,6 +56,14 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen |
| 53 | 56 | @Autowired |
| 54 | 57 | private IDeviceChannelService deviceChannelService; |
| 55 | 58 | |
| 59 | + private boolean taskQueueHandlerRun = false; | |
| 60 | + | |
| 61 | + private final ConcurrentLinkedQueue<SipMsgInfo> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 62 | + | |
| 63 | + @Qualifier("taskExecutor") | |
| 64 | + @Autowired | |
| 65 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 66 | + | |
| 56 | 67 | @Override |
| 57 | 68 | public void afterPropertiesSet() throws Exception { |
| 58 | 69 | notifyMessageHandler.addHandler(cmdType, this); |
| ... | ... | @@ -61,78 +72,91 @@ public class MobilePositionNotifyMessageHandler extends SIPRequestProcessorParen |
| 61 | 72 | @Override |
| 62 | 73 | public void handForDevice(RequestEvent evt, Device device, Element rootElement) { |
| 63 | 74 | |
| 64 | - try { | |
| 65 | - rootElement = getRootElement(evt, device.getCharset()); | |
| 66 | - if (rootElement == null) { | |
| 67 | - logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", evt.getRequest()); | |
| 68 | - responseAck(getServerTransaction(evt), Response.BAD_REQUEST); | |
| 69 | - return; | |
| 70 | - } | |
| 71 | - MobilePosition mobilePosition = new MobilePosition(); | |
| 72 | - mobilePosition.setCreateTime(DateUtil.getNow()); | |
| 73 | - if (!ObjectUtils.isEmpty(device.getName())) { | |
| 74 | - mobilePosition.setDeviceName(device.getName()); | |
| 75 | - } | |
| 76 | - mobilePosition.setDeviceId(device.getDeviceId()); | |
| 77 | - mobilePosition.setChannelId(getText(rootElement, "DeviceID")); | |
| 78 | - mobilePosition.setTime(getText(rootElement, "Time")); | |
| 79 | - mobilePosition.setLongitude(Double.parseDouble(getText(rootElement, "Longitude"))); | |
| 80 | - mobilePosition.setLatitude(Double.parseDouble(getText(rootElement, "Latitude"))); | |
| 81 | - if (NumericUtil.isDouble(getText(rootElement, "Speed"))) { | |
| 82 | - mobilePosition.setSpeed(Double.parseDouble(getText(rootElement, "Speed"))); | |
| 83 | - } else { | |
| 84 | - mobilePosition.setSpeed(0.0); | |
| 85 | - } | |
| 86 | - if (NumericUtil.isDouble(getText(rootElement, "Direction"))) { | |
| 87 | - mobilePosition.setDirection(Double.parseDouble(getText(rootElement, "Direction"))); | |
| 88 | - } else { | |
| 89 | - mobilePosition.setDirection(0.0); | |
| 90 | - } | |
| 91 | - if (NumericUtil.isDouble(getText(rootElement, "Altitude"))) { | |
| 92 | - mobilePosition.setAltitude(Double.parseDouble(getText(rootElement, "Altitude"))); | |
| 93 | - } else { | |
| 94 | - mobilePosition.setAltitude(0.0); | |
| 95 | - } | |
| 96 | - mobilePosition.setReportSource("Mobile Position"); | |
| 97 | - | |
| 98 | - | |
| 99 | - // 更新device channel 的经纬度 | |
| 100 | - DeviceChannel deviceChannel = new DeviceChannel(); | |
| 101 | - deviceChannel.setDeviceId(device.getDeviceId()); | |
| 102 | - deviceChannel.setChannelId(mobilePosition.getChannelId()); | |
| 103 | - deviceChannel.setLongitude(mobilePosition.getLongitude()); | |
| 104 | - deviceChannel.setLatitude(mobilePosition.getLatitude()); | |
| 105 | - deviceChannel.setGpsTime(mobilePosition.getTime()); | |
| 106 | - | |
| 107 | - deviceChannel = deviceChannelService.updateGps(deviceChannel, device); | |
| 108 | - | |
| 109 | - mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); | |
| 110 | - mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); | |
| 111 | - mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); | |
| 112 | - mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); | |
| 113 | - | |
| 114 | - if (userSetting.getSavePositionHistory()) { | |
| 115 | - storager.insertMobilePosition(mobilePosition); | |
| 116 | - } | |
| 117 | - storager.updateChannelPosition(deviceChannel); | |
| 118 | - //回复 200 OK | |
| 119 | - responseAck(getServerTransaction(evt), Response.OK); | |
| 120 | - | |
| 121 | - // 发送redis消息。 通知位置信息的变化 | |
| 122 | - JSONObject jsonObject = new JSONObject(); | |
| 123 | - jsonObject.put("time", mobilePosition.getTime()); | |
| 124 | - jsonObject.put("serial", deviceChannel.getDeviceId()); | |
| 125 | - jsonObject.put("code", deviceChannel.getChannelId()); | |
| 126 | - jsonObject.put("longitude", mobilePosition.getLongitude()); | |
| 127 | - jsonObject.put("latitude", mobilePosition.getLatitude()); | |
| 128 | - jsonObject.put("altitude", mobilePosition.getAltitude()); | |
| 129 | - jsonObject.put("direction", mobilePosition.getDirection()); | |
| 130 | - jsonObject.put("speed", mobilePosition.getSpeed()); | |
| 131 | - redisCatchStorage.sendMobilePositionMsg(jsonObject); | |
| 132 | - | |
| 133 | - } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 134 | - e.printStackTrace(); | |
| 75 | + taskQueue.offer(new SipMsgInfo(evt, device, rootElement)); | |
| 76 | + if (!taskQueueHandlerRun) { | |
| 77 | + taskQueueHandlerRun = true; | |
| 78 | + taskExecutor.execute(() -> { | |
| 79 | + while (!taskQueue.isEmpty()) { | |
| 80 | + SipMsgInfo sipMsgInfo = taskQueue.poll(); | |
| 81 | + try { | |
| 82 | + Element rootElementAfterCharset = getRootElement(sipMsgInfo.getEvt(), sipMsgInfo.getDevice().getCharset()); | |
| 83 | + if (rootElementAfterCharset == null) { | |
| 84 | + logger.warn("[ 移动设备位置数据通知 ] content cannot be null, {}", sipMsgInfo.getEvt().getRequest()); | |
| 85 | + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.BAD_REQUEST); | |
| 86 | + return; | |
| 87 | + } | |
| 88 | + MobilePosition mobilePosition = new MobilePosition(); | |
| 89 | + mobilePosition.setCreateTime(DateUtil.getNow()); | |
| 90 | + if (!ObjectUtils.isEmpty(sipMsgInfo.getDevice().getName())) { | |
| 91 | + mobilePosition.setDeviceName(sipMsgInfo.getDevice().getName()); | |
| 92 | + } | |
| 93 | + mobilePosition.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); | |
| 94 | + mobilePosition.setChannelId(getText(rootElementAfterCharset, "DeviceID")); | |
| 95 | + mobilePosition.setTime(getText(rootElementAfterCharset, "Time")); | |
| 96 | + mobilePosition.setLongitude(Double.parseDouble(getText(rootElementAfterCharset, "Longitude"))); | |
| 97 | + mobilePosition.setLatitude(Double.parseDouble(getText(rootElementAfterCharset, "Latitude"))); | |
| 98 | + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Speed"))) { | |
| 99 | + mobilePosition.setSpeed(Double.parseDouble(getText(rootElementAfterCharset, "Speed"))); | |
| 100 | + } else { | |
| 101 | + mobilePosition.setSpeed(0.0); | |
| 102 | + } | |
| 103 | + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Direction"))) { | |
| 104 | + mobilePosition.setDirection(Double.parseDouble(getText(rootElementAfterCharset, "Direction"))); | |
| 105 | + } else { | |
| 106 | + mobilePosition.setDirection(0.0); | |
| 107 | + } | |
| 108 | + if (NumericUtil.isDouble(getText(rootElementAfterCharset, "Altitude"))) { | |
| 109 | + mobilePosition.setAltitude(Double.parseDouble(getText(rootElementAfterCharset, "Altitude"))); | |
| 110 | + } else { | |
| 111 | + mobilePosition.setAltitude(0.0); | |
| 112 | + } | |
| 113 | + mobilePosition.setReportSource("Mobile Position"); | |
| 114 | + | |
| 115 | + | |
| 116 | + // 更新device channel 的经纬度 | |
| 117 | + DeviceChannel deviceChannel = new DeviceChannel(); | |
| 118 | + deviceChannel.setDeviceId(sipMsgInfo.getDevice().getDeviceId()); | |
| 119 | + deviceChannel.setChannelId(mobilePosition.getChannelId()); | |
| 120 | + deviceChannel.setLongitude(mobilePosition.getLongitude()); | |
| 121 | + deviceChannel.setLatitude(mobilePosition.getLatitude()); | |
| 122 | + deviceChannel.setGpsTime(mobilePosition.getTime()); | |
| 123 | + | |
| 124 | + deviceChannel = deviceChannelService.updateGps(deviceChannel, sipMsgInfo.getDevice()); | |
| 125 | + | |
| 126 | + mobilePosition.setLongitudeWgs84(deviceChannel.getLongitudeWgs84()); | |
| 127 | + mobilePosition.setLatitudeWgs84(deviceChannel.getLatitudeWgs84()); | |
| 128 | + mobilePosition.setLongitudeGcj02(deviceChannel.getLongitudeGcj02()); | |
| 129 | + mobilePosition.setLatitudeGcj02(deviceChannel.getLatitudeGcj02()); | |
| 130 | + | |
| 131 | + if (userSetting.getSavePositionHistory()) { | |
| 132 | + storager.insertMobilePosition(mobilePosition); | |
| 133 | + } | |
| 134 | + storager.updateChannelPosition(deviceChannel); | |
| 135 | + //回复 200 OK | |
| 136 | + responseAck(getServerTransaction(sipMsgInfo.getEvt()), Response.OK); | |
| 137 | + | |
| 138 | + // 发送redis消息。 通知位置信息的变化 | |
| 139 | + JSONObject jsonObject = new JSONObject(); | |
| 140 | + jsonObject.put("time", mobilePosition.getTime()); | |
| 141 | + jsonObject.put("serial", deviceChannel.getDeviceId()); | |
| 142 | + jsonObject.put("code", deviceChannel.getChannelId()); | |
| 143 | + jsonObject.put("longitude", mobilePosition.getLongitude()); | |
| 144 | + jsonObject.put("latitude", mobilePosition.getLatitude()); | |
| 145 | + jsonObject.put("altitude", mobilePosition.getAltitude()); | |
| 146 | + jsonObject.put("direction", mobilePosition.getDirection()); | |
| 147 | + jsonObject.put("speed", mobilePosition.getSpeed()); | |
| 148 | + redisCatchStorage.sendMobilePositionMsg(jsonObject); | |
| 149 | + | |
| 150 | + } catch (DocumentException | SipException | InvalidArgumentException | ParseException e) { | |
| 151 | + e.printStackTrace(); | |
| 152 | + } | |
| 153 | + | |
| 154 | + } | |
| 155 | + taskQueueHandlerRun = false; | |
| 156 | + }); | |
| 135 | 157 | } |
| 158 | + | |
| 159 | + | |
| 136 | 160 | } |
| 137 | 161 | |
| 138 | 162 | @Override | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java
| 1 | 1 | package com.genersoft.iot.vmp.service.impl; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 4 | 5 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 5 | 6 | import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; |
| 6 | 7 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| ... | ... | @@ -59,6 +60,9 @@ public class PlatformServiceImpl implements IPlatformService { |
| 59 | 60 | @Autowired |
| 60 | 61 | private GbStreamMapper gbStreamMapper; |
| 61 | 62 | |
| 63 | + @Autowired | |
| 64 | + private UserSetting userSetting; | |
| 65 | + | |
| 62 | 66 | |
| 63 | 67 | |
| 64 | 68 | @Override |
| ... | ... | @@ -241,7 +245,7 @@ public class PlatformServiceImpl implements IPlatformService { |
| 241 | 245 | if (subscribe != null) { |
| 242 | 246 | |
| 243 | 247 | // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 |
| 244 | - List<DeviceChannel> gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId()); | |
| 248 | + List<DeviceChannel> gbStreams = gbStreamMapper.queryGbStreamListInPlatform(platform.getServerGBId(), userSetting.isUsePushingAsStatus()); | |
| 245 | 249 | if (gbStreams.size() == 0) { |
| 246 | 250 | return; |
| 247 | 251 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| ... | ... | @@ -131,23 +131,6 @@ public class PlayServiceImpl implements IPlayService { |
| 131 | 131 | StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); |
| 132 | 132 | playResult.setDevice(device); |
| 133 | 133 | |
| 134 | - result.onCompletion(()->{ | |
| 135 | - // 点播结束时调用截图接口 | |
| 136 | - taskExecutor.execute(()->{ | |
| 137 | - // TODO 应该在上流时调用更好,结束也可能是错误结束 | |
| 138 | - String path = "snap"; | |
| 139 | - String fileName = deviceId + "_" + channelId + ".jpg"; | |
| 140 | - WVPResult wvpResult = (WVPResult)result.getResult(); | |
| 141 | - if (Objects.requireNonNull(wvpResult).getCode() == 0) { | |
| 142 | - StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); | |
| 143 | - MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); | |
| 144 | - String streamUrl = streamInfoForSuccess.getFmp4(); | |
| 145 | - // 请求截图 | |
| 146 | - logger.info("[请求截图]: " + fileName); | |
| 147 | - zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); | |
| 148 | - } | |
| 149 | - }); | |
| 150 | - }); | |
| 151 | 134 | if (streamInfo != null) { |
| 152 | 135 | String streamId = streamInfo.getStream(); |
| 153 | 136 | if (streamId == null) { |
| ... | ... | @@ -209,6 +192,21 @@ public class PlayServiceImpl implements IPlayService { |
| 209 | 192 | SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, device.isSsrcCheck(), false); |
| 210 | 193 | logger.info(JSONObject.toJSONString(ssrcInfo)); |
| 211 | 194 | play(mediaServerItem, ssrcInfo, device, channelId, (mediaServerItemInUse, response)->{ |
| 195 | + // 点播结束时调用截图接口 | |
| 196 | + taskExecutor.execute(()->{ | |
| 197 | + // TODO 应该在上流时调用更好,结束也可能是错误结束 | |
| 198 | + String path = "snap"; | |
| 199 | + String fileName = deviceId + "_" + channelId + ".jpg"; | |
| 200 | + WVPResult wvpResult = (WVPResult)result.getResult(); | |
| 201 | + if (Objects.requireNonNull(wvpResult).getCode() == 0) { | |
| 202 | + StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); | |
| 203 | + MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); | |
| 204 | + String streamUrl = streamInfoForSuccess.getFmp4(); | |
| 205 | + // 请求截图 | |
| 206 | + logger.info("[请求截图]: " + fileName); | |
| 207 | + zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); | |
| 208 | + } | |
| 209 | + }); | |
| 212 | 210 | if (hookEvent != null) { |
| 213 | 211 | hookEvent.response(mediaServerItem, response); |
| 214 | 212 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisAlarmMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisAlarmMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; |
| 7 | -import com.genersoft.iot.vmp.service.IPlatformChannelService; | |
| 8 | -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 9 | 7 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 10 | 8 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 11 | 9 | import org.slf4j.Logger; |
| 12 | 10 | import org.slf4j.LoggerFactory; |
| 13 | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| 12 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 14 | 13 | import org.springframework.data.redis.connection.Message; |
| 15 | 14 | import org.springframework.data.redis.connection.MessageListener; |
| 15 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 16 | 16 | import org.springframework.stereotype.Component; |
| 17 | 17 | import org.springframework.util.ObjectUtils; |
| 18 | 18 | |
| 19 | 19 | import java.util.List; |
| 20 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 20 | 21 | |
| 21 | 22 | |
| 22 | 23 | @Component |
| ... | ... | @@ -33,45 +34,67 @@ public class RedisAlarmMsgListener implements MessageListener { |
| 33 | 34 | @Autowired |
| 34 | 35 | private IVideoManagerStorage storage; |
| 35 | 36 | |
| 37 | + private boolean taskQueueHandlerRun = false; | |
| 38 | + | |
| 39 | + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 40 | + | |
| 41 | + @Qualifier("taskExecutor") | |
| 42 | + @Autowired | |
| 43 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 44 | + | |
| 36 | 45 | @Override |
| 37 | 46 | public void onMessage(Message message, byte[] bytes) { |
| 38 | 47 | logger.info("收到来自REDIS的ALARM通知: {}", new String(message.getBody())); |
| 39 | - AlarmChannelMessage alarmChannelMessage = JSON.parseObject(message.getBody(), AlarmChannelMessage.class); | |
| 40 | - if (alarmChannelMessage == null) { | |
| 41 | - logger.warn("[REDIS的ALARM通知]消息解析失败"); | |
| 42 | - return; | |
| 43 | - } | |
| 44 | - String gbId = alarmChannelMessage.getGbId(); | |
| 45 | - | |
| 46 | - DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 47 | - deviceAlarm.setCreateTime(DateUtil.getNow()); | |
| 48 | - deviceAlarm.setChannelId(gbId); | |
| 49 | - deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); | |
| 50 | - deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); | |
| 51 | - deviceAlarm.setAlarmPriority("1"); | |
| 52 | - deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); | |
| 53 | - deviceAlarm.setAlarmType("1"); | |
| 54 | - deviceAlarm.setLongitude(0); | |
| 55 | - deviceAlarm.setLatitude(0); | |
| 56 | - | |
| 57 | - if (ObjectUtils.isEmpty(gbId)) { | |
| 58 | - // 发送给所有的上级 | |
| 59 | - List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); | |
| 60 | - if (parentPlatforms.size() > 0) { | |
| 61 | - for (ParentPlatform parentPlatform : parentPlatforms) { | |
| 62 | - commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); | |
| 48 | + | |
| 49 | + taskQueue.offer(message); | |
| 50 | + if (!taskQueueHandlerRun) { | |
| 51 | + taskQueueHandlerRun = true; | |
| 52 | + taskExecutor.execute(() -> { | |
| 53 | + while (!taskQueue.isEmpty()) { | |
| 54 | + Message msg = taskQueue.poll(); | |
| 55 | + | |
| 56 | + AlarmChannelMessage alarmChannelMessage = JSON.parseObject(msg.getBody(), AlarmChannelMessage.class); | |
| 57 | + if (alarmChannelMessage == null) { | |
| 58 | + logger.warn("[REDIS的ALARM通知]消息解析失败"); | |
| 59 | + return; | |
| 60 | + } | |
| 61 | + String gbId = alarmChannelMessage.getGbId(); | |
| 62 | + | |
| 63 | + DeviceAlarm deviceAlarm = new DeviceAlarm(); | |
| 64 | + deviceAlarm.setCreateTime(DateUtil.getNow()); | |
| 65 | + deviceAlarm.setChannelId(gbId); | |
| 66 | + deviceAlarm.setAlarmDescription(alarmChannelMessage.getAlarmDescription()); | |
| 67 | + deviceAlarm.setAlarmMethod("" + alarmChannelMessage.getAlarmSn()); | |
| 68 | + deviceAlarm.setAlarmPriority("1"); | |
| 69 | + deviceAlarm.setAlarmTime(DateUtil.getNowForISO8601()); | |
| 70 | + deviceAlarm.setAlarmType("1"); | |
| 71 | + deviceAlarm.setLongitude(0); | |
| 72 | + deviceAlarm.setLatitude(0); | |
| 73 | + | |
| 74 | + if (ObjectUtils.isEmpty(gbId)) { | |
| 75 | + // 发送给所有的上级 | |
| 76 | + List<ParentPlatform> parentPlatforms = storage.queryEnableParentPlatformList(true); | |
| 77 | + if (parentPlatforms.size() > 0) { | |
| 78 | + for (ParentPlatform parentPlatform : parentPlatforms) { | |
| 79 | + commanderForPlatform.sendAlarmMessage(parentPlatform, deviceAlarm); | |
| 80 | + } | |
| 81 | + } | |
| 82 | + }else { | |
| 83 | + Device device = storage.queryVideoDevice(gbId); | |
| 84 | + ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); | |
| 85 | + if (device != null && platform == null) { | |
| 86 | + commander.sendAlarmMessage(device, deviceAlarm); | |
| 87 | + }else if (device == null && platform != null){ | |
| 88 | + commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); | |
| 89 | + }else { | |
| 90 | + logger.warn("无法确定" + gbId + "是平台还是设备"); | |
| 91 | + } | |
| 92 | + } | |
| 63 | 93 | } |
| 64 | - } | |
| 65 | - }else { | |
| 66 | - Device device = storage.queryVideoDevice(gbId); | |
| 67 | - ParentPlatform platform = storage.queryParentPlatByServerGBId(gbId); | |
| 68 | - if (device != null && platform == null) { | |
| 69 | - commander.sendAlarmMessage(device, deviceAlarm); | |
| 70 | - }else if (device == null && platform != null){ | |
| 71 | - commanderForPlatform.sendAlarmMessage(platform, deviceAlarm); | |
| 72 | - }else { | |
| 73 | - logger.warn("无法确定" + gbId + "是平台还是设备"); | |
| 74 | - } | |
| 94 | + taskQueueHandlerRun = false; | |
| 95 | + }); | |
| 75 | 96 | } |
| 97 | + | |
| 98 | + | |
| 76 | 99 | } |
| 77 | 100 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGbPlayMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONObject; |
| ... | ... | @@ -19,8 +19,10 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult; |
| 19 | 19 | import org.slf4j.Logger; |
| 20 | 20 | import org.slf4j.LoggerFactory; |
| 21 | 21 | import org.springframework.beans.factory.annotation.Autowired; |
| 22 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 22 | 23 | import org.springframework.data.redis.connection.Message; |
| 23 | 24 | import org.springframework.data.redis.connection.MessageListener; |
| 25 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 24 | 26 | import org.springframework.stereotype.Component; |
| 25 | 27 | |
| 26 | 28 | import java.text.ParseException; |
| ... | ... | @@ -28,6 +30,7 @@ import java.util.HashMap; |
| 28 | 30 | import java.util.Map; |
| 29 | 31 | import java.util.UUID; |
| 30 | 32 | import java.util.concurrent.ConcurrentHashMap; |
| 33 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 31 | 34 | |
| 32 | 35 | |
| 33 | 36 | /** |
| ... | ... | @@ -85,6 +88,14 @@ public class RedisGbPlayMsgListener implements MessageListener { |
| 85 | 88 | @Autowired |
| 86 | 89 | private ZlmHttpHookSubscribe subscribe; |
| 87 | 90 | |
| 91 | + private boolean taskQueueHandlerRun = false; | |
| 92 | + | |
| 93 | + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 94 | + | |
| 95 | + @Qualifier("taskExecutor") | |
| 96 | + @Autowired | |
| 97 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 98 | + | |
| 88 | 99 | |
| 89 | 100 | public interface PlayMsgCallback{ |
| 90 | 101 | void handler(ResponseSendItemMsg responseSendItemMsg) throws ParseException; |
| ... | ... | @@ -100,94 +111,107 @@ public class RedisGbPlayMsgListener implements MessageListener { |
| 100 | 111 | |
| 101 | 112 | @Override |
| 102 | 113 | public void onMessage(Message message, byte[] bytes) { |
| 103 | - JSONObject msgJSON = JSON.parseObject(message.getBody(), JSONObject.class); | |
| 104 | - WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); | |
| 105 | - if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { | |
| 106 | - return; | |
| 107 | - } | |
| 108 | - if (WvpRedisMsg.isRequest(wvpRedisMsg)) { | |
| 109 | - logger.info("[收到REDIS通知] 请求: {}", new String(message.getBody())); | |
| 110 | - | |
| 111 | - switch (wvpRedisMsg.getCmd()){ | |
| 112 | - case WvpRedisMsgCmd.GET_SEND_ITEM: | |
| 113 | - RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class); | |
| 114 | - requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); | |
| 115 | - break; | |
| 116 | - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: | |
| 117 | - RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);; | |
| 118 | - requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); | |
| 119 | - break; | |
| 120 | - default: | |
| 121 | - break; | |
| 122 | - } | |
| 123 | 114 | |
| 124 | - }else { | |
| 125 | - logger.info("[收到REDIS通知] 回复: {}", new String(message.getBody())); | |
| 126 | - switch (wvpRedisMsg.getCmd()){ | |
| 127 | - case WvpRedisMsgCmd.GET_SEND_ITEM: | |
| 128 | - | |
| 129 | - WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); | |
| 130 | - | |
| 131 | - String key = wvpRedisMsg.getSerial(); | |
| 132 | - switch (content.getCode()) { | |
| 133 | - case 0: | |
| 134 | - ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); | |
| 135 | - PlayMsgCallback playMsgCallback = callbacks.get(key); | |
| 136 | - if (playMsgCallback != null) { | |
| 137 | - callbacksForError.remove(key); | |
| 138 | - try { | |
| 139 | - playMsgCallback.handler(responseSendItemMsg); | |
| 140 | - } catch (ParseException e) { | |
| 141 | - throw new RuntimeException(e); | |
| 142 | - } | |
| 143 | - } | |
| 144 | - break; | |
| 145 | - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: | |
| 146 | - case ERROR_CODE_OFFLINE: | |
| 147 | - case ERROR_CODE_TIMEOUT: | |
| 148 | - PlayMsgErrorCallback errorCallback = callbacksForError.get(key); | |
| 149 | - if (errorCallback != null) { | |
| 150 | - callbacks.remove(key); | |
| 151 | - errorCallback.handler(content); | |
| 152 | - } | |
| 153 | - break; | |
| 154 | - default: | |
| 155 | - break; | |
| 115 | + taskQueue.offer(message); | |
| 116 | + if (!taskQueueHandlerRun) { | |
| 117 | + taskQueueHandlerRun = true; | |
| 118 | + taskExecutor.execute(() -> { | |
| 119 | + while (!taskQueue.isEmpty()) { | |
| 120 | + Message msg = taskQueue.poll(); | |
| 121 | + JSONObject msgJSON = JSON.parseObject(msg.getBody(), JSONObject.class); | |
| 122 | + WvpRedisMsg wvpRedisMsg = JSON.toJavaObject(msgJSON, WvpRedisMsg.class); | |
| 123 | + if (!userSetting.getServerId().equals(wvpRedisMsg.getToId())) { | |
| 124 | + return; | |
| 156 | 125 | } |
| 157 | - break; | |
| 158 | - case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: | |
| 159 | - WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); | |
| 160 | - String serial = wvpRedisMsg.getSerial(); | |
| 161 | - switch (wvpResult.getCode()) { | |
| 162 | - case 0: | |
| 163 | - JSONObject jsonObject = (JSONObject)wvpResult.getData(); | |
| 164 | - PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial); | |
| 165 | - if (playMsgCallback != null) { | |
| 166 | - callbacksForError.remove(serial); | |
| 167 | - playMsgCallback.handler(jsonObject); | |
| 168 | - } | |
| 169 | - break; | |
| 170 | - case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: | |
| 171 | - case ERROR_CODE_OFFLINE: | |
| 172 | - case ERROR_CODE_TIMEOUT: | |
| 173 | - PlayMsgErrorCallback errorCallback = callbacksForError.get(serial); | |
| 174 | - if (errorCallback != null) { | |
| 175 | - callbacks.remove(serial); | |
| 176 | - errorCallback.handler(wvpResult); | |
| 177 | - } | |
| 178 | - break; | |
| 179 | - default: | |
| 180 | - break; | |
| 126 | + if (WvpRedisMsg.isRequest(wvpRedisMsg)) { | |
| 127 | + logger.info("[收到REDIS通知] 请求: {}", new String(msg.getBody())); | |
| 128 | + | |
| 129 | + switch (wvpRedisMsg.getCmd()){ | |
| 130 | + case WvpRedisMsgCmd.GET_SEND_ITEM: | |
| 131 | + RequestSendItemMsg content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestSendItemMsg.class); | |
| 132 | + requestSendItemMsgHand(content, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); | |
| 133 | + break; | |
| 134 | + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: | |
| 135 | + RequestPushStreamMsg param = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), RequestPushStreamMsg.class);; | |
| 136 | + requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); | |
| 137 | + break; | |
| 138 | + default: | |
| 139 | + break; | |
| 140 | + } | |
| 141 | + | |
| 142 | + }else { | |
| 143 | + logger.info("[收到REDIS通知] 回复: {}", new String(msg.getBody())); | |
| 144 | + switch (wvpRedisMsg.getCmd()){ | |
| 145 | + case WvpRedisMsgCmd.GET_SEND_ITEM: | |
| 146 | + | |
| 147 | + WVPResult content = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); | |
| 148 | + | |
| 149 | + String key = wvpRedisMsg.getSerial(); | |
| 150 | + switch (content.getCode()) { | |
| 151 | + case 0: | |
| 152 | + ResponseSendItemMsg responseSendItemMsg =JSON.toJavaObject((JSONObject)content.getData(), ResponseSendItemMsg.class); | |
| 153 | + PlayMsgCallback playMsgCallback = callbacks.get(key); | |
| 154 | + if (playMsgCallback != null) { | |
| 155 | + callbacksForError.remove(key); | |
| 156 | + try { | |
| 157 | + playMsgCallback.handler(responseSendItemMsg); | |
| 158 | + } catch (ParseException e) { | |
| 159 | + throw new RuntimeException(e); | |
| 160 | + } | |
| 161 | + } | |
| 162 | + break; | |
| 163 | + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: | |
| 164 | + case ERROR_CODE_OFFLINE: | |
| 165 | + case ERROR_CODE_TIMEOUT: | |
| 166 | + PlayMsgErrorCallback errorCallback = callbacksForError.get(key); | |
| 167 | + if (errorCallback != null) { | |
| 168 | + callbacks.remove(key); | |
| 169 | + errorCallback.handler(content); | |
| 170 | + } | |
| 171 | + break; | |
| 172 | + default: | |
| 173 | + break; | |
| 174 | + } | |
| 175 | + break; | |
| 176 | + case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: | |
| 177 | + WVPResult wvpResult = JSON.toJavaObject((JSONObject)wvpRedisMsg.getContent(), WVPResult.class); | |
| 178 | + String serial = wvpRedisMsg.getSerial(); | |
| 179 | + switch (wvpResult.getCode()) { | |
| 180 | + case 0: | |
| 181 | + JSONObject jsonObject = (JSONObject)wvpResult.getData(); | |
| 182 | + PlayMsgCallbackForStartSendRtpStream playMsgCallback = callbacksForStartSendRtpStream.get(serial); | |
| 183 | + if (playMsgCallback != null) { | |
| 184 | + callbacksForError.remove(serial); | |
| 185 | + playMsgCallback.handler(jsonObject); | |
| 186 | + } | |
| 187 | + break; | |
| 188 | + case ERROR_CODE_MEDIA_SERVER_NOT_FOUND: | |
| 189 | + case ERROR_CODE_OFFLINE: | |
| 190 | + case ERROR_CODE_TIMEOUT: | |
| 191 | + PlayMsgErrorCallback errorCallback = callbacksForError.get(serial); | |
| 192 | + if (errorCallback != null) { | |
| 193 | + callbacks.remove(serial); | |
| 194 | + errorCallback.handler(wvpResult); | |
| 195 | + } | |
| 196 | + break; | |
| 197 | + default: | |
| 198 | + break; | |
| 199 | + } | |
| 200 | + break; | |
| 201 | + default: | |
| 202 | + break; | |
| 203 | + } | |
| 181 | 204 | } |
| 182 | - break; | |
| 183 | - default: | |
| 184 | - break; | |
| 185 | - } | |
| 205 | + } | |
| 206 | + taskQueueHandlerRun = false; | |
| 207 | + }); | |
| 186 | 208 | } |
| 187 | 209 | |
| 188 | 210 | |
| 189 | 211 | |
| 190 | 212 | |
| 213 | + | |
| 214 | + | |
| 191 | 215 | } |
| 192 | 216 | |
| 193 | 217 | /** | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisGpsMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGpsMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | -import com.genersoft.iot.vmp.gb28181.bean.HandlerCatchData; | |
| 5 | 4 | import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; |
| 6 | 5 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 7 | 6 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamResponseListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamResponseListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | -import com.alibaba.fastjson.JSONObject; | |
| 5 | -import com.genersoft.iot.vmp.media.zlm.dto.ChannelOnlineEvent; | |
| 6 | -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | |
| 7 | -import com.genersoft.iot.vmp.service.IGbStreamService; | |
| 8 | -import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 9 | -import com.genersoft.iot.vmp.service.IStreamPushService; | |
| 4 | +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | |
| 10 | 5 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; |
| 11 | -import com.genersoft.iot.vmp.utils.DateUtil; | |
| 12 | 6 | import org.slf4j.Logger; |
| 13 | 7 | import org.slf4j.LoggerFactory; |
| 8 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 9 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 14 | 10 | import org.springframework.data.redis.connection.Message; |
| 15 | 11 | import org.springframework.data.redis.connection.MessageListener; |
| 12 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 16 | 13 | import org.springframework.stereotype.Component; |
| 17 | 14 | import org.springframework.util.ObjectUtils; |
| 18 | 15 | |
| 19 | -import javax.annotation.Resource; | |
| 20 | -import java.util.ArrayList; | |
| 21 | -import java.util.List; | |
| 22 | 16 | import java.util.Map; |
| 23 | 17 | import java.util.concurrent.ConcurrentHashMap; |
| 18 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 24 | 19 | |
| 25 | 20 | /** |
| 26 | 21 | * 接收redis返回的推流结果 |
| ... | ... | @@ -31,6 +26,15 @@ public class RedisPushStreamResponseListener implements MessageListener { |
| 31 | 26 | |
| 32 | 27 | private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamResponseListener.class); |
| 33 | 28 | |
| 29 | + private boolean taskQueueHandlerRun = false; | |
| 30 | + | |
| 31 | + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 32 | + | |
| 33 | + @Qualifier("taskExecutor") | |
| 34 | + @Autowired | |
| 35 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 36 | + | |
| 37 | + | |
| 34 | 38 | private Map<String, PushStreamResponseEvent> responseEvents = new ConcurrentHashMap<>(); |
| 35 | 39 | |
| 36 | 40 | public interface PushStreamResponseEvent{ |
| ... | ... | @@ -39,16 +43,25 @@ public class RedisPushStreamResponseListener implements MessageListener { |
| 39 | 43 | |
| 40 | 44 | @Override |
| 41 | 45 | public void onMessage(Message message, byte[] bytes) { |
| 42 | - // | |
| 43 | 46 | logger.warn("[REDIS消息-请求推流结果]: {}", new String(message.getBody())); |
| 44 | - MessageForPushChannelResponse response = JSON.parseObject(new String(message.getBody()), MessageForPushChannelResponse.class); | |
| 45 | - if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ | |
| 46 | - logger.info("[REDIS消息-请求推流结果]:参数不全"); | |
| 47 | - return; | |
| 48 | - } | |
| 49 | - // 查看正在等待的invite消息 | |
| 50 | - if (responseEvents.get(response.getApp() + response.getStream()) != null) { | |
| 51 | - responseEvents.get(response.getApp() + response.getStream()).run(response); | |
| 47 | + taskQueue.offer(message); | |
| 48 | + if (!taskQueueHandlerRun) { | |
| 49 | + taskQueueHandlerRun = true; | |
| 50 | + taskExecutor.execute(() -> { | |
| 51 | + while (!taskQueue.isEmpty()) { | |
| 52 | + Message msg = taskQueue.poll(); | |
| 53 | + MessageForPushChannelResponse response = JSON.parseObject(new String(msg.getBody()), MessageForPushChannelResponse.class); | |
| 54 | + if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ | |
| 55 | + logger.info("[REDIS消息-请求推流结果]:参数不全"); | |
| 56 | + return; | |
| 57 | + } | |
| 58 | + // 查看正在等待的invite消息 | |
| 59 | + if (responseEvents.get(response.getApp() + response.getStream()) != null) { | |
| 60 | + responseEvents.get(response.getApp() + response.getStream()).run(response); | |
| 61 | + } | |
| 62 | + } | |
| 63 | + taskQueueHandlerRun = false; | |
| 64 | + }); | |
| 52 | 65 | } |
| 53 | 66 | } |
| 54 | 67 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusListMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONObject; |
| ... | ... | @@ -6,15 +6,20 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 6 | 6 | import com.genersoft.iot.vmp.service.IGbStreamService; |
| 7 | 7 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 8 | 8 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| 9 | +import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | |
| 9 | 10 | import com.genersoft.iot.vmp.utils.DateUtil; |
| 10 | 11 | import org.slf4j.Logger; |
| 11 | 12 | import org.slf4j.LoggerFactory; |
| 13 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 14 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 12 | 15 | import org.springframework.data.redis.connection.Message; |
| 13 | 16 | import org.springframework.data.redis.connection.MessageListener; |
| 17 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 14 | 18 | import org.springframework.stereotype.Component; |
| 15 | 19 | |
| 16 | 20 | import javax.annotation.Resource; |
| 17 | 21 | import java.util.*; |
| 22 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 18 | 23 | |
| 19 | 24 | /** |
| 20 | 25 | * @Auther: JiangFeng |
| ... | ... | @@ -33,49 +38,66 @@ public class RedisPushStreamStatusListMsgListener implements MessageListener { |
| 33 | 38 | @Resource |
| 34 | 39 | private IGbStreamService gbStreamService; |
| 35 | 40 | |
| 41 | + private boolean taskQueueHandlerRun = false; | |
| 42 | + | |
| 43 | + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 44 | + | |
| 45 | + @Qualifier("taskExecutor") | |
| 46 | + @Autowired | |
| 47 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 48 | + | |
| 36 | 49 | @Override |
| 37 | 50 | public void onMessage(Message message, byte[] bytes) { |
| 38 | - // | |
| 39 | - logger.warn("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody())); | |
| 40 | - List<StreamPushItem> streamPushItems = JSON.parseArray(new String(message.getBody()), StreamPushItem.class); | |
| 41 | - //查询全部的app+stream 用于判断是添加还是修改 | |
| 42 | - List<String> allAppAndStream = streamPushService.getAllAppAndStream(); | |
| 51 | + logger.info("[REDIS消息-推流设备列表更新]: {}", new String(message.getBody())); | |
| 43 | 52 | |
| 44 | - /** | |
| 45 | - * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 | |
| 46 | - */ | |
| 47 | - List<StreamPushItem> streamPushItemForSave = new ArrayList<>(); | |
| 48 | - List<StreamPushItem> streamPushItemForUpdate = new ArrayList<>(); | |
| 49 | - for (StreamPushItem streamPushItem : streamPushItems) { | |
| 50 | - String app = streamPushItem.getApp(); | |
| 51 | - String stream = streamPushItem.getStream(); | |
| 52 | - boolean contains = allAppAndStream.contains(app + stream); | |
| 53 | - //不存在就添加 | |
| 54 | - if (!contains) { | |
| 55 | - streamPushItem.setStreamType("push"); | |
| 56 | - streamPushItem.setCreateTime(DateUtil.getNow()); | |
| 57 | - streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); | |
| 58 | - streamPushItem.setOriginType(2); | |
| 59 | - streamPushItem.setOriginTypeStr("rtsp_push"); | |
| 60 | - streamPushItem.setTotalReaderCount("0"); | |
| 61 | - streamPushItemForSave.add(streamPushItem); | |
| 62 | - } else { | |
| 63 | - //存在就只修改 name和gbId | |
| 64 | - streamPushItemForUpdate.add(streamPushItem); | |
| 65 | - } | |
| 66 | - } | |
| 67 | - if (streamPushItemForSave.size() > 0) { | |
| 53 | + taskQueue.offer(message); | |
| 54 | + if (!taskQueueHandlerRun) { | |
| 55 | + taskQueueHandlerRun = true; | |
| 56 | + taskExecutor.execute(() -> { | |
| 57 | + while (!taskQueue.isEmpty()) { | |
| 58 | + Message msg = taskQueue.poll(); | |
| 59 | + List<StreamPushItem> streamPushItems = JSON.parseArray(new String(msg.getBody()), StreamPushItem.class); | |
| 60 | + //查询全部的app+stream 用于判断是添加还是修改 | |
| 61 | + List<String> allAppAndStream = streamPushService.getAllAppAndStream(); | |
| 68 | 62 | |
| 69 | - logger.info("添加{}条",streamPushItemForSave.size()); | |
| 70 | - logger.info(JSONObject.toJSONString(streamPushItemForSave)); | |
| 71 | - streamPushService.batchAdd(streamPushItemForSave); | |
| 63 | + /** | |
| 64 | + * 用于存储更具APP+Stream过滤后的数据,可以直接存入stream_push表与gb_stream表 | |
| 65 | + */ | |
| 66 | + List<StreamPushItem> streamPushItemForSave = new ArrayList<>(); | |
| 67 | + List<StreamPushItem> streamPushItemForUpdate = new ArrayList<>(); | |
| 68 | + for (StreamPushItem streamPushItem : streamPushItems) { | |
| 69 | + String app = streamPushItem.getApp(); | |
| 70 | + String stream = streamPushItem.getStream(); | |
| 71 | + boolean contains = allAppAndStream.contains(app + stream); | |
| 72 | + //不存在就添加 | |
| 73 | + if (!contains) { | |
| 74 | + streamPushItem.setStreamType("push"); | |
| 75 | + streamPushItem.setCreateTime(DateUtil.getNow()); | |
| 76 | + streamPushItem.setMediaServerId(mediaServerService.getDefaultMediaServer().getId()); | |
| 77 | + streamPushItem.setOriginType(2); | |
| 78 | + streamPushItem.setOriginTypeStr("rtsp_push"); | |
| 79 | + streamPushItem.setTotalReaderCount("0"); | |
| 80 | + streamPushItemForSave.add(streamPushItem); | |
| 81 | + } else { | |
| 82 | + //存在就只修改 name和gbId | |
| 83 | + streamPushItemForUpdate.add(streamPushItem); | |
| 84 | + } | |
| 85 | + } | |
| 86 | + if (streamPushItemForSave.size() > 0) { | |
| 72 | 87 | |
| 73 | - } | |
| 74 | - if(streamPushItemForUpdate.size()>0){ | |
| 75 | - logger.info("修改{}条",streamPushItemForUpdate.size()); | |
| 76 | - logger.info(JSONObject.toJSONString(streamPushItemForUpdate)); | |
| 77 | - gbStreamService.updateGbIdOrName(streamPushItemForUpdate); | |
| 78 | - } | |
| 88 | + logger.info("添加{}条",streamPushItemForSave.size()); | |
| 89 | + logger.info(JSONObject.toJSONString(streamPushItemForSave)); | |
| 90 | + streamPushService.batchAdd(streamPushItemForSave); | |
| 79 | 91 | |
| 92 | + } | |
| 93 | + if(streamPushItemForUpdate.size()>0){ | |
| 94 | + logger.info("修改{}条",streamPushItemForUpdate.size()); | |
| 95 | + logger.info(JSONObject.toJSONString(streamPushItemForUpdate)); | |
| 96 | + gbStreamService.updateGbIdOrName(streamPushItemForUpdate); | |
| 97 | + } | |
| 98 | + } | |
| 99 | + taskQueueHandlerRun = false; | |
| 100 | + }); | |
| 101 | + } | |
| 80 | 102 | } |
| 81 | 103 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisPushStreamStatusMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | -import com.alibaba.fastjson.JSONObject; | |
| 5 | 4 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 6 | 5 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 7 | -import com.genersoft.iot.vmp.conf.UserSetting; | |
| 8 | -import com.genersoft.iot.vmp.gb28181.bean.GbStream; | |
| 9 | -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 10 | -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | |
| 11 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 12 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 13 | -import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; | |
| 14 | -import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; | |
| 15 | -import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; | |
| 16 | 6 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| 17 | -import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; | |
| 18 | 7 | import com.genersoft.iot.vmp.service.bean.PushStreamStatusChangeFromRedisDto; |
| 19 | -import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis; | |
| 20 | 8 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 21 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 22 | 9 | import org.slf4j.Logger; |
| 23 | 10 | import org.slf4j.LoggerFactory; |
| 24 | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| ... | ... | @@ -30,8 +17,6 @@ import org.springframework.data.redis.connection.MessageListener; |
| 30 | 17 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| 31 | 18 | import org.springframework.stereotype.Component; |
| 32 | 19 | |
| 33 | -import java.util.ArrayList; | |
| 34 | -import java.util.List; | |
| 35 | 20 | import java.util.concurrent.ConcurrentLinkedQueue; |
| 36 | 21 | |
| 37 | 22 | |
| ... | ... | @@ -65,7 +50,6 @@ public class RedisPushStreamStatusMsgListener implements MessageListener, Applic |
| 65 | 50 | |
| 66 | 51 | @Override |
| 67 | 52 | public void onMessage(Message message, byte[] bytes) { |
| 68 | - // TODO 增加队列 | |
| 69 | 53 | logger.warn("[REDIS消息-推流设备状态变化]: {}", new String(message.getBody())); |
| 70 | 54 | taskQueue.offer(message); |
| 71 | 55 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/RedisStreamMsgListener.java renamed to src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisStreamMsgListener.java
| 1 | -package com.genersoft.iot.vmp.service.impl; | |
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | |
| 2 | 2 | |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONObject; |
| 5 | 5 | import com.genersoft.iot.vmp.conf.UserSetting; |
| 6 | 6 | |
| 7 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | |
| 8 | -import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; | |
| 9 | 7 | import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; |
| 10 | 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| 11 | -import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | |
| 12 | 9 | import org.slf4j.Logger; |
| 13 | 10 | import org.slf4j.LoggerFactory; |
| 14 | 11 | import org.springframework.beans.factory.annotation.Autowired; |
| 12 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 15 | 13 | import org.springframework.data.redis.connection.Message; |
| 16 | 14 | import org.springframework.data.redis.connection.MessageListener; |
| 15 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | |
| 17 | 16 | import org.springframework.stereotype.Component; |
| 18 | 17 | |
| 18 | +import java.util.concurrent.ConcurrentLinkedQueue; | |
| 19 | + | |
| 19 | 20 | |
| 20 | 21 | /** |
| 21 | 22 | * 接收其他wvp发送流变化通知 |
| ... | ... | @@ -32,41 +33,59 @@ public class RedisStreamMsgListener implements MessageListener { |
| 32 | 33 | @Autowired |
| 33 | 34 | private ZLMMediaListManager zlmMediaListManager; |
| 34 | 35 | |
| 36 | + private boolean taskQueueHandlerRun = false; | |
| 37 | + | |
| 38 | + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | |
| 39 | + | |
| 40 | + @Qualifier("taskExecutor") | |
| 41 | + @Autowired | |
| 42 | + private ThreadPoolTaskExecutor taskExecutor; | |
| 43 | + | |
| 35 | 44 | @Override |
| 36 | 45 | public void onMessage(Message message, byte[] bytes) { |
| 37 | 46 | |
| 38 | - JSONObject steamMsgJson = JSON.parseObject(message.getBody(), JSONObject.class); | |
| 39 | - if (steamMsgJson == null) { | |
| 40 | - logger.warn("[收到redis 流变化]消息解析失败"); | |
| 41 | - return; | |
| 42 | - } | |
| 43 | - String serverId = steamMsgJson.getString("serverId"); | |
| 47 | + taskQueue.offer(message); | |
| 48 | + if (!taskQueueHandlerRun) { | |
| 49 | + taskQueueHandlerRun = true; | |
| 50 | + taskExecutor.execute(() -> { | |
| 51 | + while (!taskQueue.isEmpty()) { | |
| 52 | + Message msg = taskQueue.poll(); | |
| 53 | + JSONObject steamMsgJson = JSON.parseObject(msg.getBody(), JSONObject.class); | |
| 54 | + if (steamMsgJson == null) { | |
| 55 | + logger.warn("[收到redis 流变化]消息解析失败"); | |
| 56 | + return; | |
| 57 | + } | |
| 58 | + String serverId = steamMsgJson.getString("serverId"); | |
| 44 | 59 | |
| 45 | - if (userSetting.getServerId().equals(serverId)) { | |
| 46 | - // 自己发送的消息忽略即可 | |
| 47 | - return; | |
| 48 | - } | |
| 49 | - logger.info("[收到redis 流变化]: {}", new String(message.getBody())); | |
| 50 | - String app = steamMsgJson.getString("app"); | |
| 51 | - String stream = steamMsgJson.getString("stream"); | |
| 52 | - boolean register = steamMsgJson.getBoolean("register"); | |
| 53 | - String mediaServerId = steamMsgJson.getString("mediaServerId"); | |
| 54 | - MediaItem mediaItem = new MediaItem(); | |
| 55 | - mediaItem.setSeverId(serverId); | |
| 56 | - mediaItem.setApp(app); | |
| 57 | - mediaItem.setStream(stream); | |
| 58 | - mediaItem.setRegist(register); | |
| 59 | - mediaItem.setMediaServerId(mediaServerId); | |
| 60 | - mediaItem.setCreateStamp(System.currentTimeMillis()/1000); | |
| 61 | - mediaItem.setAliveSecond(0L); | |
| 62 | - mediaItem.setTotalReaderCount("0"); | |
| 63 | - mediaItem.setOriginType(0); | |
| 64 | - mediaItem.setOriginTypeStr("0"); | |
| 65 | - mediaItem.setOriginTypeStr("unknown"); | |
| 66 | - if (register) { | |
| 67 | - zlmMediaListManager.addPush(mediaItem); | |
| 68 | - }else { | |
| 69 | - zlmMediaListManager.removeMedia(app, stream); | |
| 60 | + if (userSetting.getServerId().equals(serverId)) { | |
| 61 | + // 自己发送的消息忽略即可 | |
| 62 | + return; | |
| 63 | + } | |
| 64 | + logger.info("[收到redis 流变化]: {}", new String(message.getBody())); | |
| 65 | + String app = steamMsgJson.getString("app"); | |
| 66 | + String stream = steamMsgJson.getString("stream"); | |
| 67 | + boolean register = steamMsgJson.getBoolean("register"); | |
| 68 | + String mediaServerId = steamMsgJson.getString("mediaServerId"); | |
| 69 | + MediaItem mediaItem = new MediaItem(); | |
| 70 | + mediaItem.setSeverId(serverId); | |
| 71 | + mediaItem.setApp(app); | |
| 72 | + mediaItem.setStream(stream); | |
| 73 | + mediaItem.setRegist(register); | |
| 74 | + mediaItem.setMediaServerId(mediaServerId); | |
| 75 | + mediaItem.setCreateStamp(System.currentTimeMillis()/1000); | |
| 76 | + mediaItem.setAliveSecond(0L); | |
| 77 | + mediaItem.setTotalReaderCount("0"); | |
| 78 | + mediaItem.setOriginType(0); | |
| 79 | + mediaItem.setOriginTypeStr("0"); | |
| 80 | + mediaItem.setOriginTypeStr("unknown"); | |
| 81 | + if (register) { | |
| 82 | + zlmMediaListManager.addPush(mediaItem); | |
| 83 | + }else { | |
| 84 | + zlmMediaListManager.removeMedia(app, stream); | |
| 85 | + } | |
| 86 | + } | |
| 87 | + taskQueueHandlerRun = false; | |
| 88 | + }); | |
| 70 | 89 | } |
| 71 | 90 | } |
| 72 | 91 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
| ... | ... | @@ -75,18 +75,23 @@ public interface GbStreamMapper { |
| 75 | 75 | "WHERE gs.gbId = '${gbId}' AND pgs.platformId = '${platformId}'") |
| 76 | 76 | GbStream queryStreamInPlatform(String platformId, String gbId); |
| 77 | 77 | |
| 78 | - @Select("select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," + | |
| 78 | + @Select("<script> "+ | |
| 79 | + "select gt.gbId as channelId, gt.name, 'wvp-pro' as manufacture, st.status, gt.longitude, gt.latitude, pc.id as parentId," + | |
| 79 | 80 | " '1' as registerWay, pc.civilCode, 'live' as model, 'wvp-pro' as owner, '0' as parental,'0' as secrecy" + |
| 80 | 81 | " from gb_stream gt " + |
| 81 | 82 | " left join (" + |
| 82 | - " select sp.status, sp.app, sp.stream from stream_push sp" + | |
| 83 | + " select " + | |
| 84 | + " <if test='usPushingAsStatus != true'> sp.status as status, </if>" + | |
| 85 | + " <if test='usPushingAsStatus == true'> sp.pushIng as status, </if>" + | |
| 86 | + "sp.app, sp.stream from stream_push sp" + | |
| 83 | 87 | " union all" + |
| 84 | 88 | " select spxy.status, spxy.app, spxy.stream from stream_proxy spxy" + |
| 85 | 89 | " ) st on st.app = gt.app and st.stream = gt.stream" + |
| 86 | 90 | " left join platform_gb_stream pgs on gt.gbStreamId = pgs.gbStreamId" + |
| 87 | 91 | " left join platform_catalog pc on pgs.catalogId = pc.id and pgs.platformId = pc.platformId" + |
| 88 | - " where pgs.platformId=#{platformId}") | |
| 89 | - List<DeviceChannel> queryGbStreamListInPlatform(String platformId); | |
| 92 | + " where pgs.platformId=#{platformId}" + | |
| 93 | + "</script>") | |
| 94 | + List<DeviceChannel> queryGbStreamListInPlatform(String platformId, boolean usPushingAsStatus); | |
| 90 | 95 | |
| 91 | 96 | |
| 92 | 97 | @Select("SELECT gs.* FROM gb_stream gs LEFT JOIN platform_gb_stream pgs " + | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStorageImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.storager.impl; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | 4 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 5 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 5 | 6 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 6 | 7 | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| 7 | 8 | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; |
| ... | ... | @@ -84,6 +85,9 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { |
| 84 | 85 | private GbStreamMapper gbStreamMapper; |
| 85 | 86 | |
| 86 | 87 | @Autowired |
| 88 | + private UserSetting userSetting; | |
| 89 | + | |
| 90 | + @Autowired | |
| 87 | 91 | private PlatformCatalogMapper catalogMapper; |
| 88 | 92 | |
| 89 | 93 | @Autowired |
| ... | ... | @@ -614,7 +618,7 @@ public class VideoManagerStorageImpl implements IVideoManagerStorage { |
| 614 | 618 | */ |
| 615 | 619 | @Override |
| 616 | 620 | public List<DeviceChannel> queryGbStreamListInPlatform(String platformId) { |
| 617 | - return gbStreamMapper.queryGbStreamListInPlatform(platformId); | |
| 621 | + return gbStreamMapper.queryGbStreamListInPlatform(platformId, userSetting.isUsePushingAsStatus()); | |
| 618 | 622 | } |
| 619 | 623 | |
| 620 | 624 | /** | ... | ... |