优化notify性能,增加notify超出处理能力时直接回复错误码,不做处理。
| | |
| | | |
| | | private List<String> allowedOrigins = new ArrayList<>(); |
| | | |
| | | private int maxNotifyCountQueue = 10000; |
| | | |
| | | public Boolean getSavePositionHistory() { |
| | | return savePositionHistory; |
| | | } |
| | |
| | | public void setRecordPath(String recordPath) { |
| | | this.recordPath = recordPath; |
| | | } |
| | | |
| | | public int getMaxNotifyCountQueue() { |
| | | return maxNotifyCountQueue; |
| | | } |
| | | |
| | | public void setMaxNotifyCountQueue(int maxNotifyCountQueue) { |
| | | this.maxNotifyCountQueue = maxNotifyCountQueue; |
| | | } |
| | | } |
New file |
| | |
| | | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| | | |
| | | import com.genersoft.iot.vmp.conf.DynamicTask; |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| | | import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; |
| | | import com.genersoft.iot.vmp.gb28181.event.EventPublisher; |
| | | import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| | | import com.genersoft.iot.vmp.gb28181.utils.SipUtils; |
| | | import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; |
| | | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import org.dom4j.DocumentException; |
| | | import org.dom4j.Element; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Component; |
| | | |
| | | import javax.sip.RequestEvent; |
| | | import javax.sip.header.FromHeader; |
| | | import java.util.*; |
| | | import java.util.concurrent.ConcurrentHashMap; |
| | | import java.util.concurrent.CopyOnWriteArrayList; |
| | | |
| | | /** |
| | | * SIP命令类型: NOTIFY请求中的目录请求处理 |
| | | */ |
| | | @Component |
| | | public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent { |
| | | |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(NotifyRequestForCatalogProcessor.class); |
| | | |
| | | private final List<DeviceChannel> updateChannelOnlineList = new CopyOnWriteArrayList<>(); |
| | | private final List<DeviceChannel> updateChannelOfflineList = new CopyOnWriteArrayList<>(); |
| | | private final Map<String, DeviceChannel> updateChannelMap = new ConcurrentHashMap<>(); |
| | | |
| | | private final Map<String, DeviceChannel> addChannelMap = new ConcurrentHashMap<>(); |
| | | private final List<DeviceChannel> deleteChannelList = new CopyOnWriteArrayList<>(); |
| | | |
| | | |
| | | @Autowired |
| | | private UserSetting userSetting; |
| | | |
| | | @Autowired |
| | | private EventPublisher eventPublisher; |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | @Autowired |
| | | private IDeviceChannelService deviceChannelService; |
| | | |
| | | @Autowired |
| | | private DynamicTask dynamicTask; |
| | | |
| | | private final static String talkKey = "notify-request-for-catalog-task"; |
| | | |
| | | public void process(RequestEvent evt) { |
| | | try { |
| | | long start = System.currentTimeMillis(); |
| | | FromHeader fromHeader = (FromHeader) evt.getRequest().getHeader(FromHeader.NAME); |
| | | String deviceId = SipUtils.getUserIdFromFromHeader(fromHeader); |
| | | |
| | | Device device = redisCatchStorage.getDevice(deviceId); |
| | | if (device == null || device.getOnline() == 0) { |
| | | logger.warn("[收到目录订阅]:{}, 但是设备已经离线", (device != null ? device.getDeviceId():"" )); |
| | | return; |
| | | } |
| | | Element rootElement = getRootElement(evt, device.getCharset()); |
| | | if (rootElement == null) { |
| | | logger.warn("[ 收到目录订阅 ] content cannot be null, {}", evt.getRequest()); |
| | | return; |
| | | } |
| | | Element deviceListElement = rootElement.element("DeviceList"); |
| | | if (deviceListElement == null) { |
| | | return; |
| | | } |
| | | Iterator<Element> deviceListIterator = deviceListElement.elementIterator(); |
| | | if (deviceListIterator != null) { |
| | | |
| | | // 遍历DeviceList |
| | | while (deviceListIterator.hasNext()) { |
| | | Element itemDevice = deviceListIterator.next(); |
| | | Element channelDeviceElement = itemDevice.element("DeviceID"); |
| | | if (channelDeviceElement == null) { |
| | | continue; |
| | | } |
| | | Element eventElement = itemDevice.element("Event"); |
| | | String event; |
| | | if (eventElement == null) { |
| | | logger.warn("[收到目录订阅]:{}, 但是Event为空, 设为默认值 ADD", (device != null ? device.getDeviceId():"" )); |
| | | event = CatalogEvent.ADD; |
| | | }else { |
| | | event = eventElement.getText().toUpperCase(); |
| | | } |
| | | DeviceChannel channel = XmlUtil.channelContentHander(itemDevice, device, event); |
| | | |
| | | channel.setDeviceId(device.getDeviceId()); |
| | | logger.info("[收到目录订阅]:{}/{}", device.getDeviceId(), channel.getChannelId()); |
| | | switch (event) { |
| | | case CatalogEvent.ON: |
| | | // 上线 |
| | | logger.info("[收到通道上线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | updateChannelOnlineList.add(channel); |
| | | if (updateChannelOnlineList.size() > 300) { |
| | | executeSaveForOnline(); |
| | | } |
| | | break; |
| | | case CatalogEvent.OFF : |
| | | // 离线 |
| | | logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | if (userSetting.getRefuseChannelStatusChannelFormNotify()) { |
| | | updateChannelOfflineList.add(channel); |
| | | if (updateChannelOfflineList.size() > 300) { |
| | | executeSaveForOffline(); |
| | | } |
| | | }else { |
| | | logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | } |
| | | break; |
| | | case CatalogEvent.VLOST: |
| | | // 视频丢失 |
| | | logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | if (userSetting.getRefuseChannelStatusChannelFormNotify()) { |
| | | updateChannelOfflineList.add(channel); |
| | | if (updateChannelOfflineList.size() > 300) { |
| | | executeSaveForOffline(); |
| | | } |
| | | }else { |
| | | logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | } |
| | | break; |
| | | case CatalogEvent.DEFECT: |
| | | // 故障 |
| | | logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | if (userSetting.getRefuseChannelStatusChannelFormNotify()) { |
| | | updateChannelOfflineList.add(channel); |
| | | if (updateChannelOfflineList.size() > 300) { |
| | | executeSaveForOffline(); |
| | | } |
| | | }else { |
| | | logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | } |
| | | break; |
| | | case CatalogEvent.ADD: |
| | | // 增加 |
| | | logger.info("[收到增加通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | // 判断此通道是否存在 |
| | | DeviceChannel deviceChannel = deviceChannelService.getOne(deviceId, channel.getChannelId()); |
| | | if (deviceChannel != null) { |
| | | channel.setId(deviceChannel.getId()); |
| | | updateChannelMap.put(channel.getChannelId(), channel); |
| | | if (updateChannelMap.keySet().size() > 300) { |
| | | executeSaveForUpdate(); |
| | | } |
| | | }else { |
| | | addChannelMap.put(channel.getChannelId(), channel); |
| | | if (addChannelMap.keySet().size() > 300) { |
| | | executeSaveForAdd(); |
| | | } |
| | | } |
| | | |
| | | break; |
| | | case CatalogEvent.DEL: |
| | | // 删除 |
| | | logger.info("[收到删除通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | deleteChannelList.add(channel); |
| | | if (deleteChannelList.size() > 300) { |
| | | executeSaveForDelete(); |
| | | } |
| | | break; |
| | | case CatalogEvent.UPDATE: |
| | | // 更新 |
| | | logger.info("[收到更新通道通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId()); |
| | | // 判断此通道是否存在 |
| | | DeviceChannel deviceChannelForUpdate = deviceChannelService.getOne(deviceId, channel.getChannelId()); |
| | | if (deviceChannelForUpdate != null) { |
| | | channel.setId(deviceChannelForUpdate.getId()); |
| | | updateChannelMap.put(channel.getChannelId(), channel); |
| | | if (updateChannelMap.keySet().size() > 300) { |
| | | executeSaveForUpdate(); |
| | | } |
| | | }else { |
| | | addChannelMap.put(channel.getChannelId(), channel); |
| | | if (addChannelMap.keySet().size() > 300) { |
| | | executeSaveForAdd(); |
| | | } |
| | | } |
| | | break; |
| | | default: |
| | | logger.warn("[ NotifyCatalog ] event not found : {}", event ); |
| | | |
| | | } |
| | | // 转发变化信息 |
| | | eventPublisher.catalogEventPublish(null, channel, event); |
| | | |
| | | if (updateChannelMap.keySet().size() > 0 |
| | | || addChannelMap.keySet().size() > 0 |
| | | || updateChannelOnlineList.size() > 0 |
| | | || updateChannelOfflineList.size() > 0 |
| | | || deleteChannelList.size() > 0) { |
| | | |
| | | if (!dynamicTask.contains(talkKey)) { |
| | | dynamicTask.startDelay(talkKey, this::executeSave, 1000); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | } catch (DocumentException e) { |
| | | logger.error("未处理的异常 ", e); |
| | | } |
| | | } |
| | | |
| | | private void executeSave(){ |
| | | System.out.println("定时存储数据"); |
| | | executeSaveForUpdate(); |
| | | executeSaveForDelete(); |
| | | executeSaveForOnline(); |
| | | executeSaveForOffline(); |
| | | dynamicTask.stop(talkKey); |
| | | } |
| | | |
| | | private void executeSaveForUpdate(){ |
| | | if (updateChannelMap.values().size() > 0) { |
| | | ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(updateChannelMap.values()); |
| | | updateChannelMap.clear(); |
| | | deviceChannelService.batchUpdateChannel(deviceChannels); |
| | | } |
| | | |
| | | } |
| | | |
| | | private void executeSaveForAdd(){ |
| | | if (addChannelMap.values().size() > 0) { |
| | | ArrayList<DeviceChannel> deviceChannels = new ArrayList<>(addChannelMap.values()); |
| | | addChannelMap.clear(); |
| | | deviceChannelService.batchAddChannel(deviceChannels); |
| | | } |
| | | } |
| | | |
| | | private void executeSaveForDelete(){ |
| | | if (deleteChannelList.size() > 0) { |
| | | deviceChannelService.deleteChannels(deleteChannelList); |
| | | deleteChannelList.clear(); |
| | | } |
| | | } |
| | | |
| | | private void executeSaveForOnline(){ |
| | | if (updateChannelOnlineList.size() > 0) { |
| | | deviceChannelService.channelsOnline(updateChannelOnlineList); |
| | | updateChannelOnlineList.clear(); |
| | | } |
| | | } |
| | | |
| | | private void executeSaveForOffline(){ |
| | | if (updateChannelOfflineList.size() > 0) { |
| | | deviceChannelService.channelsOffline(updateChannelOfflineList); |
| | | updateChannelOfflineList.clear(); |
| | | } |
| | | } |
| | | |
| | | } |
| | |
| | | @Autowired |
| | | private IDeviceChannelService deviceChannelService; |
| | | |
| | | @Autowired |
| | | private NotifyRequestForCatalogProcessor notifyRequestForCatalogProcessor; |
| | | |
| | | private ConcurrentLinkedQueue<HandlerCatchData> taskQueue = new ConcurrentLinkedQueue<>(); |
| | | |
| | | @Qualifier("taskExecutor") |
| | | @Autowired |
| | | private ThreadPoolTaskExecutor taskExecutor; |
| | | |
| | | private int maxQueueCount = 30000; |
| | | |
| | | @Override |
| | | public void afterPropertiesSet() throws Exception { |
| | |
| | | @Override |
| | | public void process(RequestEvent evt) { |
| | | try { |
| | | responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); |
| | | |
| | | if (taskQueue.size() >= userSetting.getMaxNotifyCountQueue()) { |
| | | responseAck((SIPRequest) evt.getRequest(), Response.BUSY_HERE, null, null); |
| | | logger.error("[notify] 待处理消息队列已满 {},返回486 BUSY_HERE,消息不做处理", userSetting.getMaxNotifyCountQueue()); |
| | | return; |
| | | }else { |
| | | responseAck((SIPRequest) evt.getRequest(), Response.OK, null, null); |
| | | } |
| | | |
| | | }catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("未处理的异常 ", e); |
| | | } |
| | |
| | | while (!taskQueue.isEmpty()) { |
| | | try { |
| | | HandlerCatchData take = taskQueue.poll(); |
| | | if (take == null) { |
| | | continue; |
| | | } |
| | | Element rootElement = getRootElement(take.getEvt()); |
| | | if (rootElement == null) { |
| | | logger.error("处理NOTIFY消息时未获取到消息体,{}", take.getEvt().getRequest()); |
| | |
| | | |
| | | if (CmdType.CATALOG.equals(cmd)) { |
| | | logger.info("接收到Catalog通知"); |
| | | processNotifyCatalogList(take.getEvt()); |
| | | // processNotifyCatalogList(take.getEvt()); |
| | | notifyRequestForCatalogProcessor.process(take.getEvt()); |
| | | } else if (CmdType.ALARM.equals(cmd)) { |
| | | logger.info("接收到Alarm通知"); |
| | | processNotifyAlarm(take.getEvt()); |
| | |
| | | |
| | | /** |
| | | * 处理MobilePosition移动位置Notify |
| | | * |
| | | * |
| | | * @param evt |
| | | */ |
| | | private void processNotifyMobilePosition(RequestEvent evt) { |
| | |
| | | |
| | | /*** |
| | | * 处理alarm设备报警Notify |
| | | * |
| | | * |
| | | * @param evt |
| | | */ |
| | | private void processNotifyAlarm(RequestEvent evt) { |
| | |
| | | |
| | | /*** |
| | | * 处理catalog设备目录列表Notify |
| | | * |
| | | * |
| | | * @param evt |
| | | */ |
| | | private void processNotifyCatalogList(RequestEvent evt) { |
| | |
| | | * 查询通道所属的设备 |
| | | */ |
| | | List<Device> getDeviceByChannelId(String channelId); |
| | | |
| | | /** |
| | | * 批量删除通道 |
| | | * @param deleteChannelList 待删除的通道列表 |
| | | */ |
| | | int deleteChannels(List<DeviceChannel> deleteChannelList); |
| | | |
| | | /** |
| | | * 批量上线 |
| | | */ |
| | | int channelsOnline(List<DeviceChannel> channels); |
| | | |
| | | /** |
| | | * 批量下线 |
| | | */ |
| | | int channelsOffline(List<DeviceChannel> channels); |
| | | |
| | | /** |
| | | * 获取一个通道 |
| | | */ |
| | | DeviceChannel getOne(String deviceId, String channelId); |
| | | |
| | | /** |
| | | * 直接批量更新通道 |
| | | */ |
| | | void batchUpdateChannel(List<DeviceChannel> channels); |
| | | |
| | | /** |
| | | * 直接批量添加 |
| | | */ |
| | | void batchAddChannel(List<DeviceChannel> deviceChannels); |
| | | } |
| | |
| | | |
| | | @Override |
| | | public List<Device> getDeviceByChannelId(String channelId) { |
| | | |
| | | return channelMapper.getDeviceByChannelId(channelId); |
| | | } |
| | | |
| | | @Override |
| | | public int deleteChannels(List<DeviceChannel> deleteChannelList) { |
| | | return channelMapper.batchDel(deleteChannelList); |
| | | } |
| | | |
| | | @Override |
| | | public int channelsOnline(List<DeviceChannel> channels) { |
| | | return channelMapper.batchOnline(channels); |
| | | } |
| | | |
| | | @Override |
| | | public int channelsOffline(List<DeviceChannel> channels) { |
| | | return channelMapper.batchOffline(channels); |
| | | } |
| | | |
| | | @Override |
| | | public DeviceChannel getOne(String deviceId, String channelId){ |
| | | return channelMapper.queryChannel(deviceId, channelId); |
| | | } |
| | | |
| | | @Override |
| | | public void batchUpdateChannel(List<DeviceChannel> channels) { |
| | | channelMapper.batchUpdate(channels); |
| | | for (DeviceChannel channel : channels) { |
| | | if (channel.getParentId() != null) { |
| | | channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void batchAddChannel(List<DeviceChannel> channels) { |
| | | channelMapper.batchAdd(channels); |
| | | for (DeviceChannel channel : channels) { |
| | | if (channel.getParentId() != null) { |
| | | channelMapper.updateChannelSubCount(channel.getDeviceId(), channel.getParentId()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | |
| | | public List<Device> getAll() { |
| | | return deviceMapper.getAll(); |
| | | } |
| | | |
| | | |
| | | } |
| | |
| | | @Update(value = {"UPDATE device_channel SET status=0 WHERE deviceId=#{deviceId}"}) |
| | | void offlineByDeviceId(String deviceId); |
| | | |
| | | // @Insert("<script> " + |
| | | // "insert into device_channel " + |
| | | // "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + |
| | | // " address, parental, parentId, safetyWay, registerWay, certNum, certifiable, errCode, secrecy, " + |
| | | // " ipAddress, port, password, PTZType, status, streamId, longitude, latitude, longitudeGcj02, latitudeGcj02, " + |
| | | // " longitudeWgs84, latitudeWgs84, hasAudio, createTime, updateTime, businessGroupId, gpsTime) " + |
| | | // "values " + |
| | | // "<foreach collection='addChannels' index='index' item='item' separator=','> " + |
| | | // "(#{item.channelId}, #{item.deviceId}, #{item.name}, #{item.manufacture}, #{item.model}, " + |
| | | // "#{item.owner}, #{item.civilCode}, #{item.block},#{item.subCount}," + |
| | | // "#{item.address}, #{item.parental}, #{item.parentId}, #{item.safetyWay}, #{item.registerWay}, " + |
| | | // "#{item.certNum}, #{item.certifiable}, #{item.errCode}, #{item.secrecy}, " + |
| | | // "#{item.ipAddress}, #{item.port}, #{item.password}, #{item.PTZType}, #{item.status}, " + |
| | | // "#{item.streamId}, #{item.longitude}, #{item.latitude},#{item.longitudeGcj02}, " + |
| | | // "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + |
| | | // "#{item.businessGroupId}, #{item.gpsTime}) " + |
| | | // "</foreach> " + |
| | | // "ON DUPLICATE KEY UPDATE " + |
| | | // "updateTime=VALUES(updateTime), " + |
| | | // "name=VALUES(name), " + |
| | | // "manufacture=VALUES(manufacture), " + |
| | | // "model=VALUES(model), " + |
| | | // "owner=VALUES(owner), " + |
| | | // "civilCode=VALUES(civilCode), " + |
| | | // "block=VALUES(block), " + |
| | | // "subCount=VALUES(subCount), " + |
| | | // "address=VALUES(address), " + |
| | | // "parental=VALUES(parental), " + |
| | | // "parentId=VALUES(parentId), " + |
| | | // "safetyWay=VALUES(safetyWay), " + |
| | | // "registerWay=VALUES(registerWay), " + |
| | | // "certNum=VALUES(certNum), " + |
| | | // "certifiable=VALUES(certifiable), " + |
| | | // "errCode=VALUES(errCode), " + |
| | | // "secrecy=VALUES(secrecy), " + |
| | | // "ipAddress=VALUES(ipAddress), " + |
| | | // "port=VALUES(port), " + |
| | | // "password=VALUES(password), " + |
| | | // "PTZType=VALUES(PTZType), " + |
| | | // "status=VALUES(status), " + |
| | | // "streamId=VALUES(streamId), " + |
| | | // "longitude=VALUES(longitude), " + |
| | | // "latitude=VALUES(latitude), " + |
| | | // "longitudeGcj02=VALUES(longitudeGcj02), " + |
| | | // "latitudeGcj02=VALUES(latitudeGcj02), " + |
| | | // "longitudeWgs84=VALUES(longitudeWgs84), " + |
| | | // "latitudeWgs84=VALUES(latitudeWgs84), " + |
| | | // "hasAudio=VALUES(hasAudio), " + |
| | | // "businessGroupId=VALUES(businessGroupId), " + |
| | | // "gpsTime=VALUES(gpsTime)" + |
| | | // "</script>") |
| | | // int batchAdd(List<DeviceChannel> addChannels); |
| | | |
| | | |
| | | @Insert("<script> " + |
| | | "insert into device_channel " + |
| | | "(channelId, deviceId, name, manufacture, model, owner, civilCode, block, subCount, " + |
| | |
| | | "#{item.latitudeGcj02},#{item.longitudeWgs84}, #{item.latitudeWgs84}, #{item.hasAudio}, now(), now(), " + |
| | | "#{item.businessGroupId}, #{item.gpsTime}) " + |
| | | "</foreach> " + |
| | | "ON DUPLICATE KEY UPDATE " + |
| | | "updateTime=VALUES(updateTime), " + |
| | | "name=VALUES(name), " + |
| | | "manufacture=VALUES(manufacture), " + |
| | | "model=VALUES(model), " + |
| | | "owner=VALUES(owner), " + |
| | | "civilCode=VALUES(civilCode), " + |
| | | "block=VALUES(block), " + |
| | | "subCount=VALUES(subCount), " + |
| | | "address=VALUES(address), " + |
| | | "parental=VALUES(parental), " + |
| | | "parentId=VALUES(parentId), " + |
| | | "safetyWay=VALUES(safetyWay), " + |
| | | "registerWay=VALUES(registerWay), " + |
| | | "certNum=VALUES(certNum), " + |
| | | "certifiable=VALUES(certifiable), " + |
| | | "errCode=VALUES(errCode), " + |
| | | "secrecy=VALUES(secrecy), " + |
| | | "ipAddress=VALUES(ipAddress), " + |
| | | "port=VALUES(port), " + |
| | | "password=VALUES(password), " + |
| | | "PTZType=VALUES(PTZType), " + |
| | | "status=VALUES(status), " + |
| | | "streamId=VALUES(streamId), " + |
| | | "longitude=VALUES(longitude), " + |
| | | "latitude=VALUES(latitude), " + |
| | | "longitudeGcj02=VALUES(longitudeGcj02), " + |
| | | "latitudeGcj02=VALUES(latitudeGcj02), " + |
| | | "longitudeWgs84=VALUES(longitudeWgs84), " + |
| | | "latitudeWgs84=VALUES(latitudeWgs84), " + |
| | | "hasAudio=VALUES(hasAudio), " + |
| | | "businessGroupId=VALUES(businessGroupId), " + |
| | | "gpsTime=VALUES(gpsTime)" + |
| | | "</script>") |
| | | int batchAdd(List<DeviceChannel> addChannels); |
| | | |
| | |
| | | "<if test='item.owner != null'>, owner=#{item.owner}</if>" + |
| | | "<if test='item.civilCode != null'>, civilCode=#{item.civilCode}</if>" + |
| | | "<if test='item.block != null'>, block=#{item.block}</if>" + |
| | | "<if test='item.subCount != null'>, block=#{item.subCount}</if>" + |
| | | "<if test='item.subCount != null'>, subCount=#{item.subCount}</if>" + |
| | | "<if test='item.address != null'>, address=#{item.address}</if>" + |
| | | "<if test='item.parental != null'>, parental=#{item.parental}</if>" + |
| | | "<if test='item.parentId != null'>, parentId=#{item.parentId}</if>" + |
| | |
| | | "<if test='item.latitudeWgs84 != null'>, latitudeWgs84=#{item.latitudeWgs84}</if>" + |
| | | "<if test='item.businessGroupId != null'>, businessGroupId=#{item.businessGroupId}</if>" + |
| | | "<if test='item.gpsTime != null'>, gpsTime=#{item.gpsTime}</if>" + |
| | | "WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}"+ |
| | | "<if test='item.id > 0'>WHERE id=#{item.id}</if>" + |
| | | "<if test='item.id == 0'>WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}</if>" + |
| | | "</foreach>" + |
| | | "</script>"}) |
| | | int batchUpdate(List<DeviceChannel> updateChannels); |
| | |
| | | |
| | | @Select("select de.* from device de left join device_channel dc on de.deviceId = dc.deviceId where dc.channelId=#{channelId}") |
| | | List<Device> getDeviceByChannelId(String channelId); |
| | | |
| | | |
| | | @Delete({"<script>" + |
| | | "<foreach collection='deleteChannelList' item='item' separator=';'>" + |
| | | "DELETE FROM device_channel WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + |
| | | "</foreach>" + |
| | | "</script>"}) |
| | | int batchDel(List<DeviceChannel> deleteChannelList); |
| | | |
| | | @Update({"<script>" + |
| | | "<foreach collection='channels' item='item' separator=';'>" + |
| | | "UPDATE device_channel SET status=1 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + |
| | | "</foreach>" + |
| | | "</script>"}) |
| | | int batchOnline(List<DeviceChannel> channels); |
| | | |
| | | @Update({"<script>" + |
| | | "<foreach collection='channels' item='item' separator=';'>" + |
| | | "UPDATE device_channel SET status=0 WHERE deviceId=#{item.deviceId} AND channelId=#{item.channelId}" + |
| | | "</foreach>" + |
| | | "</script>"}) |
| | | int batchOffline(List<DeviceChannel> channels); |
| | | } |
| | |
| | | send-to-platforms-when-id-lost: true |
| | | # 保持通道状态,不接受notify通道状态变化, 兼容海康平台发送错误消息 |
| | | refuse-channel-status-channel-form-notify: false |
| | | # 设置notify缓存队列最大长度,超过此长度的数据将返回486 BUSY_HERE,消息丢弃, 默认10000 |
| | | max-notify-count-queue: 10000 |
| | | # 跨域配置,配置你访问前端页面的地址即可, 可以配置多个 |
| | | allowed-origins: |
| | | - http://localhost:8008 |