| | |
| | | package com.genersoft.iot.vmp.service.impl; |
| | | |
| | | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| | | import com.genersoft.iot.vmp.conf.DynamicTask; |
| | | import com.genersoft.iot.vmp.conf.UserSetting; |
| | | import com.genersoft.iot.vmp.gb28181.bean.*; |
| | | import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; |
| | | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| | | import com.genersoft.iot.vmp.gb28181.task.ISubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; |
| | | import com.genersoft.iot.vmp.gb28181.utils.Coordtransform; |
| | | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| | | import com.genersoft.iot.vmp.service.IDeviceService; |
| | | import com.genersoft.iot.vmp.gb28181.task.impl.CatalogSubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.task.impl.MobilePositionSubscribeTask; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| | | import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; |
| | | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| | | import com.genersoft.iot.vmp.service.IDeviceChannelService; |
| | | import com.genersoft.iot.vmp.service.IDeviceService; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| | | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| | | import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; |
| | | import com.genersoft.iot.vmp.storager.dao.DeviceMapper; |
| | | import com.genersoft.iot.vmp.storager.dao.PlatformChannelMapper; |
| | |
| | | import org.slf4j.LoggerFactory; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.jdbc.datasource.DataSourceTransactionManager; |
| | | import org.springframework.jdbc.support.incrementer.AbstractIdentityColumnMaxValueIncrementer; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.TransactionDefinition; |
| | | import org.springframework.transaction.TransactionStatus; |
| | | import org.springframework.util.ObjectUtils; |
| | | import org.springframework.util.StringUtils; |
| | | |
| | | import javax.sip.InvalidArgumentException; |
| | | import javax.sip.SipException; |
| | | import java.text.ParseException; |
| | | import java.time.Instant; |
| | | import java.util.ArrayList; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | |
| | | public class DeviceServiceImpl implements IDeviceService { |
| | | |
| | | private final static Logger logger = LoggerFactory.getLogger(DeviceServiceImpl.class); |
| | | |
| | | private final String registerExpireTaskKeyPrefix = "device-register-expire-"; |
| | | |
| | | @Autowired |
| | | private DynamicTask dynamicTask; |
| | |
| | | TransactionDefinition transactionDefinition; |
| | | |
| | | @Autowired |
| | | private IVideoManagerStorage storage; |
| | | private UserSetting userSetting; |
| | | |
| | | @Autowired |
| | | private ISIPCommander commander; |
| | |
| | | |
| | | @Autowired |
| | | private IMediaServerService mediaServerService; |
| | | |
| | | @Autowired |
| | | private AudioBroadcastManager audioBroadcastManager; |
| | | |
| | | @Autowired |
| | | private ZLMRESTfulUtils zlmresTfulUtils; |
| | | |
| | | @Override |
| | | public void online(Device device) { |
| | |
| | | redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); |
| | | } |
| | | device.setUpdateTime(now); |
| | | |
| | | if (device.getKeepaliveIntervalTime() == 0) { |
| | | // 默认心跳间隔60 |
| | | device.setKeepaliveIntervalTime(60); |
| | | } |
| | | // 第一次上线 或则设备之前是离线状态--进行通道同步和设备信息查询 |
| | | if (device.getCreateTime() == null) { |
| | | device.setOnline(1); |
| | |
| | | } |
| | | sync(device); |
| | | }else { |
| | | |
| | | if(device.getOnline() == 0){ |
| | | device.setOnline(1); |
| | | device.setCreateTime(now); |
| | | logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); |
| | | deviceMapper.update(device); |
| | | redisCatchStorage.updateDevice(device); |
| | | try { |
| | | commander.deviceInfoQuery(device); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); |
| | | if (userSetting.getSyncChannelOnDeviceOnline()) { |
| | | logger.info("[设备上线,离线状态下重新注册]: {},查询设备信息以及通道信息", device.getDeviceId()); |
| | | try { |
| | | commander.deviceInfoQuery(device); |
| | | } catch (InvalidArgumentException | SipException | ParseException e) { |
| | | logger.error("[命令发送失败] 查询设备信息: {}", e.getMessage()); |
| | | } |
| | | sync(device); |
| | | // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台 |
| | | } |
| | | sync(device); |
| | | // TODO 如果设备下的通道级联到了其他平台,那么需要发送事件或者notify给上级平台 |
| | | }else { |
| | | if (deviceChannelMapper.queryAllChannels(device.getDeviceId()).size() == 0) { |
| | | logger.info("[设备上线]: {},通道数为0,查询通道信息", device.getDeviceId()); |
| | |
| | | addMobilePositionSubscribe(device); |
| | | } |
| | | // 刷新过期任务 |
| | | String registerExpireTaskKey = registerExpireTaskKeyPrefix + device.getDeviceId(); |
| | | dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getExpires() * 1000); |
| | | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + device.getDeviceId(); |
| | | // 如果第一次注册那么必须在60 * 3时间内收到一个心跳,否则设备离线 |
| | | dynamicTask.startDelay(registerExpireTaskKey, ()-> offline(device.getDeviceId()), device.getKeepaliveIntervalTime() * 1000 * 3); |
| | | } |
| | | |
| | | @Override |
| | | public void offline(String deviceId) { |
| | | logger.info("[设备离线], device:{}", deviceId); |
| | | logger.error("[设备离线], device:{}", deviceId); |
| | | Device device = deviceMapper.getDeviceByDeviceId(deviceId); |
| | | if (device == null) { |
| | | return; |
| | | } |
| | | String registerExpireTaskKey = registerExpireTaskKeyPrefix + deviceId; |
| | | String registerExpireTaskKey = VideoManagerConstants.REGISTER_EXPIRE_TASK_KEY_PREFIX + deviceId; |
| | | dynamicTask.stop(registerExpireTaskKey); |
| | | device.setOnline(0); |
| | | redisCatchStorage.updateDevice(device); |
| | | deviceMapper.update(device); |
| | | //进行通道离线 |
| | | deviceChannelMapper.offlineByDeviceId(deviceId); |
| | | // deviceChannelMapper.offlineByDeviceId(deviceId); |
| | | // 离线释放所有ssrc |
| | | List<SsrcTransaction> ssrcTransactions = streamSession.getSsrcTransactionForAll(deviceId, null, null, null); |
| | | if (ssrcTransactions != null && ssrcTransactions.size() > 0) { |
| | |
| | | // 移除订阅 |
| | | removeCatalogSubscribe(device); |
| | | removeMobilePositionSubscribe(device); |
| | | List<AudioBroadcastCatch> audioBroadcastCatches = audioBroadcastManager.get(deviceId); |
| | | if (audioBroadcastCatches.size() > 0) { |
| | | for (AudioBroadcastCatch audioBroadcastCatch : audioBroadcastCatches) { |
| | | |
| | | SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); |
| | | if (sendRtpItem != null) { |
| | | redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null); |
| | | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| | | Map<String, Object> param = new HashMap<>(); |
| | | param.put("vhost", "__defaultVhost__"); |
| | | param.put("app", sendRtpItem.getApp()); |
| | | param.put("stream", sendRtpItem.getStream()); |
| | | zlmresTfulUtils.stopSendRtp(mediaInfo, param); |
| | | } |
| | | |
| | | audioBroadcastManager.del(deviceId, audioBroadcastCatch.getChannelId()); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | |
| | | device.setUpdateTime(DateUtil.getNow()); |
| | | if (deviceMapper.update(device) > 0) { |
| | | redisCatchStorage.updateDevice(device); |
| | | |
| | | } |
| | | } |
| | | |
| | |
| | | if (parentId.length() < 14 ) { |
| | | return null; |
| | | } |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null); |
| | | List<BaseTree<DeviceChannel>> trees = transportChannelsToTree(deviceChannels, parentId); |
| | | return trees; |
| | | } |
| | |
| | | if (parentId.length() < 14 ) { |
| | | return null; |
| | | } |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null); |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, parentId, null, null, null,null); |
| | | return deviceChannels; |
| | | } |
| | | |
| | |
| | | } |
| | | }else { |
| | | if (haveChannel) { |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null); |
| | | List<DeviceChannel> deviceChannels = deviceChannelMapper.queryChannels(deviceId, null, null, null, null,null); |
| | | if (deviceChannels != null && deviceChannels.size() > 0) { |
| | | result.addAll(deviceChannels); |
| | | } |
| | |
| | | if (!ObjectUtils.isEmpty(device.getMediaServerId())) { |
| | | deviceInStore.setMediaServerId(device.getMediaServerId()); |
| | | } |
| | | deviceInStore.setSdpIp(device.getSdpIp()); |
| | | deviceInStore.setCharset(device.getCharset()); |
| | | deviceInStore.setTreeType(device.getTreeType()); |
| | | |
| | | // 目录订阅相关的信息 |
| | | if (device.getSubscribeCycleForCatalog() > 0) { |
| | |
| | | if (!deviceInStore.getGeoCoordSys().equals(device.getGeoCoordSys())) { |
| | | updateDeviceChannelGeoCoordSys(device); |
| | | } |
| | | // 更新redis |
| | | redisCatchStorage.updateDevice(device); |
| | | deviceMapper.updateCustom(device); |
| | | } |
| | | |
| | |
| | | public ResourceBaceInfo getOverview() { |
| | | return deviceMapper.getOverview(); |
| | | } |
| | | |
| | | @Override |
| | | public List<Device> getAll() { |
| | | return deviceMapper.getAll(); |
| | | } |
| | | } |