Commit db2ccfedfa17eb3cb5ca73ac3b6bc4b5a05d4148
1 parent
cf1696e0
优化notify性能,增加notify超出处理能力时直接回复错误码,不做处理。
Showing
9 changed files
with
451 additions
and
40 deletions
doc/_content/ability/_media/img_16.png
src/main/java/com/genersoft/iot/vmp/conf/UserSetting.java
| ... | ... | @@ -62,6 +62,8 @@ public class UserSetting { |
| 62 | 62 | |
| 63 | 63 | private List<String> allowedOrigins = new ArrayList<>(); |
| 64 | 64 | |
| 65 | + private int maxNotifyCountQueue = 10000; | |
| 66 | + | |
| 65 | 67 | public Boolean getSavePositionHistory() { |
| 66 | 68 | return savePositionHistory; |
| 67 | 69 | } |
| ... | ... | @@ -257,4 +259,12 @@ public class UserSetting { |
| 257 | 259 | public void setRecordPath(String recordPath) { |
| 258 | 260 | this.recordPath = recordPath; |
| 259 | 261 | } |
| 262 | + | |
| 263 | + public int getMaxNotifyCountQueue() { | |
| 264 | + return maxNotifyCountQueue; | |
| 265 | + } | |
| 266 | + | |
| 267 | + public void setMaxNotifyCountQueue(int maxNotifyCountQueue) { | |
| 268 | + this.maxNotifyCountQueue = maxNotifyCountQueue; | |
| 269 | + } | |
| 260 | 270 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.DynamicTask; | |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.bean.Device; | |
| 6 | +import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; | |
| 7 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 8 | +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; | |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | |
| 10 | +import com.genersoft.iot.vmp.gb28181.utils.SipUtils; | |
| 11 | +import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; | |
| 12 | +import com.genersoft.iot.vmp.service.IDeviceChannelService; | |
| 13 | +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | |
| 14 | +import org.dom4j.DocumentException; | |
| 15 | +import org.dom4j.Element; | |
| 16 | +import org.slf4j.Logger; | |
| 17 | +import org.slf4j.LoggerFactory; | |
| 18 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 19 | +import org.springframework.stereotype.Component; | |
| 20 | + | |
| 21 | +import javax.sip.RequestEvent; | |
| 22 | +import javax.sip.header.FromHeader; | |
| 23 | +import java.util.*; | |
| 24 | +import java.util.concurrent.ConcurrentHashMap; | |
| 25 | +import java.util.concurrent.CopyOnWriteArrayList; | |
| 26 | + | |
| 27 | +/** | |
| 28 | + * SIP命令类型: NOTIFY请求中的目录请求处理 | |
| 29 | + */ | |
| 30 | +@Component | |
| 31 | +public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent { | |
| 32 | + | |
| 33 | + | |
| 34 | + private final static Logger logger = LoggerFactory.getLogger(NotifyRequestForCatalogProcessor.class); | |
| 35 | + | |
| 36 | + private final List<DeviceChannel> updateChannelOnlineList = new CopyOnWriteArrayList<>(); | |
| 37 | + private final List<DeviceChannel> updateChannelOfflineList = new CopyOnWriteArrayList<>(); | |
| 38 | + private final Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>(); | |
| 39 | + | |
| 40 | + private final Map<String, DeviceChannel> addChannelMap = new ConcurrentHashMap<>(); | |
| 41 | + private final List<DeviceChannel> deleteChannelList = new CopyOnWriteArrayList<>(); | |
| 42 | + | |
| 43 | + | |
| 44 | + @Autowired | |
| 45 | + private UserSetting userSetting; | |
| 46 | + | |
| 47 | + @Autowired | |
| 48 | + private EventPublisher eventPublisher; | |
| 49 | + | |
| 50 | + @Autowired | |
| 51 | + private IRedisCatchStorage redisCatchStorage; | |
| 52 | + | |
| 53 | + @Autowired | |
| 54 | + private IDeviceChannelService deviceChannelService; | |
| 55 | + | |
| 56 | + @Autowired | |
| 57 | + private DynamicTask dynamicTask; | |
| 58 | + | |
| 59 | + private final static String talkKey = "notify-request-for-catalog-task"; | |
| 60 | + | |
| 61 | + public void process(RequestEvent evt) { | |
| 62 | + try { | |
| 63 | + long start = System.currentTimeMillis(); | |
| 64 | + FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); | |
| 65 | + String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); | |
| 66 | + | |
| 67 | + Device device = redisCatchStorage.getDevice(deviceId); | |
| 68 | + if (device == null || device.getOnline() == 0) { | |
| 69 | + logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" )); | |
| 70 | + return; | |
| 71 | + } | |
| 72 | + Element rootElement = getRootElement(evt, device.getCharset()); | |
| 73 | + if (rootElement == null) { | |
| 74 | + logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest()); | |
| 75 | + return; | |
| 76 | + } | |
| 77 | + Element deviceListElement = rootElement.element("DeviceList"); | |
| 78 | + if (deviceListElement == null) { | |
| 79 | + return; | |
| 80 | + } | |
| 81 | + Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); | |
| 82 | + if (deviceListIterator != null) { | |
| 83 | + | |
| 84 | + // 遍历DeviceList | |
| 85 | + while (deviceListIterator.hasNext()) { | |
| 86 | + Element itemDevice = deviceListIterator.next(); | |
| 87 | + Element channelDeviceElement = itemDevice.element("DeviceID"); | |
| 88 | + if (channelDeviceElement == null) { | |
| 89 | + continue; | |
| 90 | + } | |
| 91 | + Element eventElement = itemDevice.element("Event"); | |
| 92 | + String event; | |
| 93 | + if (eventElement == null) { | |
| 94 | + logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" )); | |
| 95 | + event = CatalogEvent.ADD; | |
| 96 | + }else { | |
| 97 | + event = eventElement.getText().toUpperCase(); | |
| 98 | + } | |
| 99 | + DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event); | |
| 100 | + | |
| 101 | + channel.setDeviceId(device.getDeviceId()); | |
| 102 | + logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); | |
| 103 | + switch (event) { | |
| 104 | + case CatalogEvent.ON: | |
| 105 | + // 上线 | |
| 106 | + logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 107 | + updateChannelOnlineList.add(channel); | |
| 108 | + if (updateChannelOnlineList.size() > 300) { | |
| 109 | + executeSaveForOnline(); | |
| 110 | + } | |
| 111 | + break; | |
| 112 | + case CatalogEvent.OFF : | |
| 113 | + // 离线 | |
| 114 | + logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 115 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | |
| 116 | + updateChannelOfflineList.add(channel); | |
| 117 | + if (updateChannelOfflineList.size() > 300) { | |
| 118 | + executeSaveForOffline(); | |
| 119 | + } | |
| 120 | + }else { | |
| 121 | + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 122 | + } | |
| 123 | + break; | |
| 124 | + case CatalogEvent.VLOST: | |
| 125 | + // 视频丢失 | |
| 126 | + logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 127 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | |
| 128 | + updateChannelOfflineList.add(channel); | |
| 129 | + if (updateChannelOfflineList.size() > 300) { | |
| 130 | + executeSaveForOffline(); | |
| 131 | + } | |
| 132 | + }else { | |
| 133 | + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 134 | + } | |
| 135 | + break; | |
| 136 | + case CatalogEvent.DEFECT: | |
| 137 | + // 故障 | |
| 138 | + logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 139 | + if (userSetting.getRefuseChannelStatusChannelFormNotify()) { | |
| 140 | + updateChannelOfflineList.add(channel); | |
| 141 | + if (updateChannelOfflineList.size() > 300) { | |
| 142 | + executeSaveForOffline(); | |
| 143 | + } | |
| 144 | + }else { | |
| 145 | + logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 146 | + } | |
| 147 | + break; | |
| 148 | + case CatalogEvent.ADD: | |
| 149 | + // 增加 | |
| 150 | + logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 151 | + // 判断此通道是否存在 | |
| 152 | + DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId()); | |
| 153 | + if (deviceChannel != null) { | |
| 154 | + channel.setId(deviceChannel.getId()); | |
| 155 | + updateChannelMap.put(channel.getChannelId(), channel); | |
| 156 | + if (updateChannelMap.keySet().size() > 300) { | |
| 157 | + executeSaveForUpdate(); | |
| 158 | + } | |
| 159 | + }else { | |
| 160 | + addChannelMap.put(channel.getChannelId(), channel); | |
| 161 | + if (addChannelMap.keySet().size() > 300) { | |
| 162 | + executeSaveForAdd(); | |
| 163 | + } | |
| 164 | + } | |
| 165 | + | |
| 166 | + break; | |
| 167 | + case CatalogEvent.DEL: | |
| 168 | + // 删除 | |
| 169 | + logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 170 | + deleteChannelList.add(channel); | |
| 171 | + if (deleteChannelList.size() > 300) { | |
| 172 | + executeSaveForDelete(); | |
| 173 | + } | |
| 174 | + break; | |
| 175 | + case CatalogEvent.UPDATE: | |
| 176 | + // 更新 | |
| 177 | + logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); | |
| 178 | + // 判断此通道是否存在 | |
| 179 | + DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId()); | |
| 180 | + if (deviceChannelForUpdate != null) { | |
| 181 | + channel.setId(deviceChannelForUpdate.getId()); | |
| 182 | + updateChannelMap.put(channel.getChannelId(), channel); | |
| 183 | + if (updateChannelMap.keySet().size() > 300) { | |
| 184 | + executeSaveForUpdate(); | |
| 185 | + } | |
| 186 | + }else { | |
| 187 | + addChannelMap.put(channel.getChannelId(), channel); | |
| 188 | + if (addChannelMap.keySet().size() > 300) { | |
| 189 | + executeSaveForAdd(); | |
| 190 | + } | |
| 191 | + } | |
| 192 | + break; | |
| 193 | + default: | |
| 194 | + logger.warn("[ NotifyCatalog ] event not found : {}", event ); | |
| 195 | + | |
| 196 | + } | |
| 197 | + // 转发变化信息 | |
| 198 | + eventPublisher.catalogEventPublish(null, channel, event); | |
| 199 | + | |
| 200 | + if (updateChannelMap.keySet().size() > 0 | |
| 201 | + || addChannelMap.keySet().size() > 0 | |
| 202 | + || updateChannelOnlineList.size() > 0 | |
| 203 | + || updateChannelOfflineList.size() > 0 | |
| 204 | + || deleteChannelList.size() > 0) { | |
| 205 | + | |
| 206 | + if (!dynamicTask.contains(talkKey)) { | |
| 207 | + dynamicTask.startDelay(talkKey, this::executeSave, 1000); | |
| 208 | + } | |
| 209 | + } | |
| 210 | + } | |
| 211 | + } | |
| 212 | + } catch (DocumentException e) { | |
| 213 | + logger.error("未处理的异常 ", e); | |
| 214 | + } | |
| 215 | + } | |
| 216 | + | |
| 217 | + private void executeSave(){ | |
| 218 | + System.out.println("定时存储数据"); | |
| 219 | + executeSaveForUpdate(); | |
| 220 | + executeSaveForDelete(); | |
| 221 | + executeSaveForOnline(); | |
| 222 | + executeSaveForOffline(); | |
| 223 | + dynamicTask.stop(talkKey); | |
| 224 | + } | |
| 225 | + | |
| 226 | + private void executeSaveForUpdate(){ | |
| 227 | + if (updateChannelMap.values().size() > 0) { | |
| 228 | + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values()); | |
| 229 | + updateChannelMap.clear(); | |
| 230 | + deviceChannelService.batchUpdateChannel(deviceChannels); | |
| 231 | + } | |
| 232 | + | |
| 233 | + } | |
| 234 | + | |
| 235 | + private void executeSaveForAdd(){ | |
| 236 | + if (addChannelMap.values().size() > 0) { | |
| 237 | + ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values()); | |
| 238 | + addChannelMap.clear(); | |
| 239 | + deviceChannelService.batchAddChannel(deviceChannels); | |
| 240 | + } | |
| 241 | + } | |
| 242 | + | |
| 243 | + private void executeSaveForDelete(){ | |
| 244 | + if (deleteChannelList.size() > 0) { | |
| 245 | + deviceChannelService.deleteChannels(deleteChannelList); | |
| 246 | + deleteChannelList.clear(); | |
| 247 | + } | |
| 248 | + } | |
| 249 | + | |
| 250 | + private void executeSaveForOnline(){ | |
| 251 | + if (updateChannelOnlineList.size() > 0) { | |
| 252 | + deviceChannelService.channelsOnline(updateChannelOnlineList); | |
| 253 | + updateChannelOnlineList.clear(); | |
| 254 | + } | |
| 255 | + } | |
| 256 | + | |
| 257 | + private void executeSaveForOffline(){ | |
| 258 | + if (updateChannelOfflineList.size() > 0) { | |
| 259 | + deviceChannelService.channelsOffline(updateChannelOfflineList); | |
| 260 | + updateChannelOfflineList.clear(); | |
| 261 | + } | |
| 262 | + } | |
| 263 | + | |
| 264 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestProcessor.java
| ... | ... | @@ -76,12 +76,17 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 76 | 76 | @Autowired |
| 77 | 77 | private IDeviceChannelService deviceChannelService; |
| 78 | 78 | |
| 79 | + @Autowired | |
| 80 | + private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor; | |
| 81 | + | |
| 79 | 82 | private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); |
| 80 | 83 | |
| 81 | 84 | @Qualifier("taskExecutor") |
| 82 | 85 | @Autowired |
| 83 | 86 | private ThreadPoolTaskExecutor taskExecutor; |
| 84 | 87 | |
| 88 | + private int maxQueueCount = 30000; | |
| 89 | + | |
| 85 | 90 | @Override |
| 86 | 91 | public void afterPropertiesSet() throws Exception { |
| 87 | 92 | // 添加消息处理的订阅 |
| ... | ... | @@ -91,7 +96,15 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 91 | 96 | @Override |
| 92 | 97 | public void process(RequestEvent evt) { |
| 93 | 98 | try { |
| 94 | - responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); | |
| 99 | + | |
| 100 | + if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { | |
| 101 | + responseAck((SIPRequest) evt.getRequest(), Response.BUSY_HERE, null, null); | |
| 102 | + logger.error("[notify] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); | |
| 103 | + return; | |
| 104 | + }else { | |
| 105 | + responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); | |
| 106 | + } | |
| 107 | + | |
| 95 | 108 | }catch (SipException | InvalidArgumentException | ParseException e) { |
| 96 | 109 | logger.error("未处理的异常 ", e); |
| 97 | 110 | } |
| ... | ... | @@ -103,6 +116,9 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 103 | 116 | while (!taskQueue.isEmpty()) { |
| 104 | 117 | try { |
| 105 | 118 | HandlerCatchData take = taskQueue.poll(); |
| 119 | + if (take == null) { | |
| 120 | + continue; | |
| 121 | + } | |
| 106 | 122 | Element rootElement = getRootElement(take.getEvt()); |
| 107 | 123 | if (rootElement == null) { |
| 108 | 124 | logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest()); |
| ... | ... | @@ -112,7 +128,8 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 112 | 128 | |
| 113 | 129 | if (CmdType.CATALOG.equals(cmd)) { |
| 114 | 130 | logger.info("接收到Catalog通知"); |
| 115 | - processNotifyCatalogList(take.getEvt()); | |
| 131 | +// processNotifyCatalogList(take.getEvt()); | |
| 132 | + notifyRequestForCatalogProcessor.process(take.getEvt()); | |
| 116 | 133 | } else if (CmdType.ALARM.equals(cmd)) { |
| 117 | 134 | logger.info("接收到Alarm通知"); |
| 118 | 135 | processNotifyAlarm(take.getEvt()); |
| ... | ... | @@ -132,7 +149,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 132 | 149 | |
| 133 | 150 | /** |
| 134 | 151 | * 处理MobilePosition移动位置Notify |
| 135 | - * | |
| 152 | + * | |
| 136 | 153 | * @param evt |
| 137 | 154 | */ |
| 138 | 155 | private void processNotifyMobilePosition(RequestEvent evt) { |
| ... | ... | @@ -236,7 +253,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 236 | 253 | |
| 237 | 254 | /*** |
| 238 | 255 | * 处理alarm设备报警Notify |
| 239 | - * | |
| 256 | + * | |
| 240 | 257 | * @param evt |
| 241 | 258 | */ |
| 242 | 259 | private void processNotifyAlarm(RequestEvent evt) { |
| ... | ... | @@ -346,7 +363,7 @@ public class NotifyRequestProcessor extends SIPRequestProcessorParent implements |
| 346 | 363 | |
| 347 | 364 | /*** |
| 348 | 365 | * 处理catalog设备目录列表Notify |
| 349 | - * | |
| 366 | + * | |
| 350 | 367 | * @param evt |
| 351 | 368 | */ |
| 352 | 369 | private void processNotifyCatalogList(RequestEvent evt) { | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IDeviceChannelService.java
| ... | ... | @@ -56,4 +56,35 @@ public interface IDeviceChannelService { |
| 56 | 56 | * 查询通道所属的设备 |
| 57 | 57 | */ |
| 58 | 58 | List<Device> getDeviceByChannelId(String channelId); |
| 59 | + | |
| 60 | + /** | |
| 61 | + * 批量删除通道 | |
| 62 | + * @param deleteChannelList 待删除的通道列表 | |
| 63 | + */ | |
| 64 | + int deleteChannels(List<DeviceChannel> deleteChannelList); | |
| 65 | + | |
| 66 | + /** | |
| 67 | + * 批量上线 | |
| 68 | + */ | |
| 69 | + int channelsOnline(List<DeviceChannel> channels); | |
| 70 | + | |
| 71 | + /** | |
| 72 | + * 批量下线 | |
| 73 | + */ | |
| 74 | + int channelsOffline(List<DeviceChannel> channels); | |
| 75 | + | |
| 76 | + /** | |
| 77 | + * 获取一个通道 | |
| 78 | + */ | |
| 79 | + DeviceChannel getOne(String deviceId, String channelId); | |
| 80 | + | |
| 81 | + /** | |
| 82 | + * 直接批量更新通道 | |
| 83 | + */ | |
| 84 | + void batchUpdateChannel(List<DeviceChannel> channels); | |
| 85 | + | |
| 86 | + /** | |
| 87 | + * 直接批量添加 | |
| 88 | + */ | |
| 89 | + void batchAddChannel(List<DeviceChannel> deviceChannels); | |
| 59 | 90 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceChannelServiceImpl.java
| ... | ... | @@ -209,6 +209,47 @@ public class DeviceChannelServiceImpl implements IDeviceChannelService { |
| 209 | 209 | |
| 210 | 210 | @Override |
| 211 | 211 | public List<Device> getDeviceByChannelId(String channelId) { |
| 212 | + | |
| 212 | 213 | return channelMapper.getDeviceByChannelId(channelId); |
| 213 | 214 | } |
| 215 | + | |
| 216 | + @Override | |
| 217 | + public int deleteChannels(List<DeviceChannel> deleteChannelList) { | |
| 218 | + return channelMapper.batchDel(deleteChannelList); | |
| 219 | + } | |
| 220 | + | |
| 221 | + @Override | |
| 222 | + public int channelsOnline(List<DeviceChannel> channels) { | |
| 223 | + return channelMapper.batchOnline(channels); | |
| 224 | + } | |
| 225 | + | |
| 226 | + @Override | |
| 227 | + public int channelsOffline(List<DeviceChannel> channels) { | |
| 228 | + return channelMapper.batchOffline(channels); | |
| 229 | + } | |
| 230 | + | |
| 231 | + @Override | |
| 232 | + public DeviceChannel getOne(String deviceId, String channelId){ | |
| 233 | + return channelMapper.queryChannel(deviceId, channelId); | |
| 234 | + } | |
| 235 | + | |
| 236 | + @Override | |
| 237 | + public void batchUpdateChannel(List<DeviceChannel> channels) { | |
| 238 | + channelMapper.batchUpdate(channels); | |
| 239 | + for (DeviceChannel channel : channels) { | |
| 240 | + if (channel.getParentId() != null) { | |
| 241 | + channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); | |
| 242 | + } | |
| 243 | + } | |
| 244 | + } | |
| 245 | + | |
| 246 | + @Override | |
| 247 | + public void batchAddChannel(List<DeviceChannel> channels) { | |
| 248 | + channelMapper.batchAdd(channels); | |
| 249 | + for (DeviceChannel channel : channels) { | |
| 250 | + if (channel.getParentId() != null) { | |
| 251 | + channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); | |
| 252 | + } | |
| 253 | + } | |
| 254 | + } | |
| 214 | 255 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceChannelMapper.java
| ... | ... | @@ -197,6 +197,60 @@ public interface DeviceChannelMapper { |
| 197 | 197 | @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"}) |
| 198 | 198 | void offlineByDeviceId(String deviceId); |
| 199 | 199 | |
| 200 | +// @Insert("<script> " + | |
| 201 | +// "insert into device_channel " + | |
| 202 | +// "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + | |
| 203 | +// " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + | |
| 204 | +// " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + | |
| 205 | +// " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + | |
| 206 | +// "values " + | |
| 207 | +// "<foreach collection='addChannels' index='index' item='item' separator=','> " + | |
| 208 | +// "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + | |
| 209 | +// "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + | |
| 210 | +// "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + | |
| 211 | +// "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + | |
| 212 | +// "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + | |
| 213 | +// "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + | |
| 214 | +// "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + | |
| 215 | +// "#{item.businessGroupId}, #{item.gpsTime}) " + | |
| 216 | +// "</foreach> " + | |
| 217 | +// "ON DUPLICATE KEY UPDATE " + | |
| 218 | +// "updateTime=VALUES(updateTime), " + | |
| 219 | +// "name=VALUES(name), " + | |
| 220 | +// "manufacture=VALUES(manufacture), " + | |
| 221 | +// "model=VALUES(model), " + | |
| 222 | +// "owner=VALUES(owner), " + | |
| 223 | +// "civilCode=VALUES(civilCode), " + | |
| 224 | +// "block=VALUES(block), " + | |
| 225 | +// "subCount=VALUES(subCount), " + | |
| 226 | +// "address=VALUES(address), " + | |
| 227 | +// "parental=VALUES(parental), " + | |
| 228 | +// "parentId=VALUES(parentId), " + | |
| 229 | +// "safetyWay=VALUES(safetyWay), " + | |
| 230 | +// "registerWay=VALUES(registerWay), " + | |
| 231 | +// "certNum=VALUES(certNum), " + | |
| 232 | +// "certifiable=VALUES(certifiable), " + | |
| 233 | +// "errCode=VALUES(errCode), " + | |
| 234 | +// "secrecy=VALUES(secrecy), " + | |
| 235 | +// "ipAddress=VALUES(ipAddress), " + | |
| 236 | +// "port=VALUES(port), " + | |
| 237 | +// "password=VALUES(password), " + | |
| 238 | +// "PTZType=VALUES(PTZType), " + | |
| 239 | +// "status=VALUES(status), " + | |
| 240 | +// "streamId=VALUES(streamId), " + | |
| 241 | +// "longitude=VALUES(longitude), " + | |
| 242 | +// "latitude=VALUES(latitude), " + | |
| 243 | +// "longitudeGcj02=VALUES(longitudeGcj02), " + | |
| 244 | +// "latitudeGcj02=VALUES(latitudeGcj02), " + | |
| 245 | +// "longitudeWgs84=VALUES(longitudeWgs84), " + | |
| 246 | +// "latitudeWgs84=VALUES(latitudeWgs84), " + | |
| 247 | +// "hasAudio=VALUES(hasAudio), " + | |
| 248 | +// "businessGroupId=VALUES(businessGroupId), " + | |
| 249 | +// "gpsTime=VALUES(gpsTime)" + | |
| 250 | +// "</script>") | |
| 251 | +// int batchAdd(List<DeviceChannel> addChannels); | |
| 252 | + | |
| 253 | + | |
| 200 | 254 | @Insert("<script> " + |
| 201 | 255 | "insert into device_channel " + |
| 202 | 256 | "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + |
| ... | ... | @@ -214,39 +268,6 @@ public interface DeviceChannelMapper { |
| 214 | 268 | "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + |
| 215 | 269 | "#{item.businessGroupId}, #{item.gpsTime}) " + |
| 216 | 270 | "</foreach> " + |
| 217 | - "ON DUPLICATE KEY UPDATE " + | |
| 218 | - "updateTime=VALUES(updateTime), " + | |
| 219 | - "name=VALUES(name), " + | |
| 220 | - "manufacture=VALUES(manufacture), " + | |
| 221 | - "model=VALUES(model), " + | |
| 222 | - "owner=VALUES(owner), " + | |
| 223 | - "civilCode=VALUES(civilCode), " + | |
| 224 | - "block=VALUES(block), " + | |
| 225 | - "subCount=VALUES(subCount), " + | |
| 226 | - "address=VALUES(address), " + | |
| 227 | - "parental=VALUES(parental), " + | |
| 228 | - "parentId=VALUES(parentId), " + | |
| 229 | - "safetyWay=VALUES(safetyWay), " + | |
| 230 | - "registerWay=VALUES(registerWay), " + | |
| 231 | - "certNum=VALUES(certNum), " + | |
| 232 | - "certifiable=VALUES(certifiable), " + | |
| 233 | - "errCode=VALUES(errCode), " + | |
| 234 | - "secrecy=VALUES(secrecy), " + | |
| 235 | - "ipAddress=VALUES(ipAddress), " + | |
| 236 | - "port=VALUES(port), " + | |
| 237 | - "password=VALUES(password), " + | |
| 238 | - "PTZType=VALUES(PTZType), " + | |
| 239 | - "status=VALUES(status), " + | |
| 240 | - "streamId=VALUES(streamId), " + | |
| 241 | - "longitude=VALUES(longitude), " + | |
| 242 | - "latitude=VALUES(latitude), " + | |
| 243 | - "longitudeGcj02=VALUES(longitudeGcj02), " + | |
| 244 | - "latitudeGcj02=VALUES(latitudeGcj02), " + | |
| 245 | - "longitudeWgs84=VALUES(longitudeWgs84), " + | |
| 246 | - "latitudeWgs84=VALUES(latitudeWgs84), " + | |
| 247 | - "hasAudio=VALUES(hasAudio), " + | |
| 248 | - "businessGroupId=VALUES(businessGroupId), " + | |
| 249 | - "gpsTime=VALUES(gpsTime)" + | |
| 250 | 271 | "</script>") |
| 251 | 272 | int batchAdd(List<DeviceChannel> addChannels); |
| 252 | 273 | |
| ... | ... | @@ -264,7 +285,7 @@ public interface DeviceChannelMapper { |
| 264 | 285 | "<if test='item.owner != null'>, owner=#{item.owner}</if>" + |
| 265 | 286 | "<if test='item.civilCode != null'>, civilCode=#{item.civilCode}</if>" + |
| 266 | 287 | "<if test='item.block != null'>, block=#{item.block}</if>" + |
| 267 | - "<if test='item.subCount != null'>, block=#{item.subCount}</if>" + | |
| 288 | + "<if test='item.subCount != null'>, subCount=#{item.subCount}</if>" + | |
| 268 | 289 | "<if test='item.address != null'>, address=#{item.address}</if>" + |
| 269 | 290 | "<if test='item.parental != null'>, parental=#{item.parental}</if>" + |
| 270 | 291 | "<if test='item.parentId != null'>, parentId=#{item.parentId}</if>" + |
| ... | ... | @@ -289,7 +310,8 @@ public interface DeviceChannelMapper { |
| 289 | 310 | "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=#{item.latitudeWgs84}</if>" + |
| 290 | 311 | "<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" + |
| 291 | 312 | "<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" + |
| 292 | - "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+ | |
| 313 | + "<if test='item.id > 0'>WHERE id=#{item.id}</if>" + | |
| 314 | + "<if test='item.id == 0'>WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}</if>" + | |
| 293 | 315 | "</foreach>" + |
| 294 | 316 | "</script>"}) |
| 295 | 317 | int batchUpdate(List<DeviceChannel> updateChannels); |
| ... | ... | @@ -403,4 +425,26 @@ public interface DeviceChannelMapper { |
| 403 | 425 | |
| 404 | 426 | @Select("select de.* from device de left join device_channel dc on de.deviceId = dc.deviceId where dc.channelId=#{channelId}") |
| 405 | 427 | List<Device> getDeviceByChannelId(String channelId); |
| 428 | + | |
| 429 | + | |
| 430 | + @Delete({"<script>" + | |
| 431 | + "<foreach collection='deleteChannelList' item='item' separator=';'>" + | |
| 432 | + "DELETE FROM device_channel WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | |
| 433 | + "</foreach>" + | |
| 434 | + "</script>"}) | |
| 435 | + int batchDel(List<DeviceChannel> deleteChannelList); | |
| 436 | + | |
| 437 | + @Update({"<script>" + | |
| 438 | + "<foreach collection='channels' item='item' separator=';'>" + | |
| 439 | + "UPDATE device_channel SET status=1 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | |
| 440 | + "</foreach>" + | |
| 441 | + "</script>"}) | |
| 442 | + int batchOnline(List<DeviceChannel> channels); | |
| 443 | + | |
| 444 | + @Update({"<script>" + | |
| 445 | + "<foreach collection='channels' item='item' separator=';'>" + | |
| 446 | + "UPDATE device_channel SET status=0 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + | |
| 447 | + "</foreach>" + | |
| 448 | + "</script>"}) | |
| 449 | + int batchOffline(List<DeviceChannel> channels); | |
| 406 | 450 | } | ... | ... |
src/main/resources/all-application.yml
| ... | ... | @@ -178,6 +178,8 @@ user-settings: |
| 178 | 178 | send-to-platforms-when-id-lost: true |
| 179 | 179 | # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息 |
| 180 | 180 | refuse-channel-status-channel-form-notify: false |
| 181 | + # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000 | |
| 182 | + max-notify-count-queue: 10000 | |
| 181 | 183 | # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个 |
| 182 | 184 | allowed-origins: |
| 183 | 185 | - http://localhost:8008 | ... | ... |