Commit fbdd35b906e81fa90a0b46e79b965cd401d32d8e

Authored by xp.Huang
2 parents 59d0a199 45e152b4

Merge branch 'master_dev_gbt_0319' into 'master_dev'

fix: 视频点播问题修复

See merge request yunteng/thingskit!371
  1 +--修改流媒体表名称--
  2 +alter table tk_media_server rename to tk_video_zlmediakit;
  3 +--先删除status字段再加新类型--
  4 +alter table tk_video_zlmediakit drop status;
  5 +alter table tk_video_zlmediakit add status BOOLEAN;
  6 +COMMENT ON COLUMN "public"."tk_video_zlmediakit"."status" IS '流媒体服务状态:false离线 true在线';
@@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.page.PageLink; @@ -42,6 +42,7 @@ import org.thingsboard.server.common.data.page.PageLink;
42 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 42 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
43 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; 43 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;
44 import org.thingsboard.server.common.data.yunteng.dto.TkDeviceStateLogDTO; 44 import org.thingsboard.server.common.data.yunteng.dto.TkDeviceStateLogDTO;
  45 +import org.thingsboard.server.common.data.yunteng.enums.StatusEnum;
45 import org.thingsboard.server.common.msg.TbMsg; 46 import org.thingsboard.server.common.msg.TbMsg;
46 import org.thingsboard.server.common.msg.TbMsgDataType; 47 import org.thingsboard.server.common.msg.TbMsgDataType;
47 import org.thingsboard.server.common.msg.TbMsgMetaData; 48 import org.thingsboard.server.common.msg.TbMsgMetaData;
@@ -54,6 +55,7 @@ import org.thingsboard.server.dao.tenant.TenantService; @@ -54,6 +55,7 @@ import org.thingsboard.server.dao.tenant.TenantService;
54 import org.thingsboard.server.dao.timeseries.TimeseriesService; 55 import org.thingsboard.server.dao.timeseries.TimeseriesService;
55 import org.thingsboard.server.dao.yunteng.service.TkDeviceService; 56 import org.thingsboard.server.dao.yunteng.service.TkDeviceService;
56 import org.thingsboard.server.dao.yunteng.service.TkDeviceStateLogService; 57 import org.thingsboard.server.dao.yunteng.service.TkDeviceStateLogService;
  58 +import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService;
57 import org.thingsboard.server.gen.transport.TransportProtos; 59 import org.thingsboard.server.gen.transport.TransportProtos;
58 import org.thingsboard.server.queue.discovery.PartitionService; 60 import org.thingsboard.server.queue.discovery.PartitionService;
59 import org.thingsboard.server.service.partition.AbstractPartitionBasedService; 61 import org.thingsboard.server.service.partition.AbstractPartitionBasedService;
@@ -94,6 +96,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev @@ -94,6 +96,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev
94 private final TbClusterService clusterService; 96 private final TbClusterService clusterService;
95 private final PartitionService partitionService; 97 private final PartitionService partitionService;
96 private final TkDeviceService tkDeviceService; 98 private final TkDeviceService tkDeviceService;
  99 + private final TkVideoChannelService channelService;
97 private final TkDeviceStateLogService tkDeviceStateLogService; 100 private final TkDeviceStateLogService tkDeviceStateLogService;
98 101
99 private TelemetrySubscriptionService tsSubService; 102 private TelemetrySubscriptionService tsSubService;
@@ -121,7 +124,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev @@ -121,7 +124,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev
121 public DefaultDeviceStateService(TenantService tenantService, DeviceService deviceService, 124 public DefaultDeviceStateService(TenantService tenantService, DeviceService deviceService,
122 AttributesService attributesService, TimeseriesService tsService, 125 AttributesService attributesService, TimeseriesService tsService,
123 TbClusterService clusterService, PartitionService partitionService, 126 TbClusterService clusterService, PartitionService partitionService,
124 - TkDeviceService tkDeviceService,TkDeviceStateLogService tkDeviceStateLogService) { 127 + TkDeviceService tkDeviceService, TkVideoChannelService channelService, TkDeviceStateLogService tkDeviceStateLogService) {
125 this.tenantService = tenantService; 128 this.tenantService = tenantService;
126 this.deviceService = deviceService; 129 this.deviceService = deviceService;
127 this.attributesService = attributesService; 130 this.attributesService = attributesService;
@@ -129,6 +132,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev @@ -129,6 +132,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev
129 this.clusterService = clusterService; 132 this.clusterService = clusterService;
130 this.partitionService = partitionService; 133 this.partitionService = partitionService;
131 this.tkDeviceService = tkDeviceService; 134 this.tkDeviceService = tkDeviceService;
  135 + this.channelService = channelService;
132 this.tkDeviceStateLogService = tkDeviceStateLogService; 136 this.tkDeviceStateLogService = tkDeviceStateLogService;
133 } 137 }
134 138
@@ -420,6 +424,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev @@ -420,6 +424,7 @@ public class DefaultDeviceStateService extends AbstractPartitionBasedService<Dev
420 save(deviceId, INACTIVITY_ALARM_TIME, ts); 424 save(deviceId, INACTIVITY_ALARM_TIME, ts);
421 pushRuleEngineMessage(stateData, INACTIVITY_EVENT); 425 pushRuleEngineMessage(stateData, INACTIVITY_EVENT);
422 //thingskit update tkDevice state 426 //thingskit update tkDevice state
  427 + channelService.updateVideoChannelState(deviceId.getId().toString(), StatusEnum.OFFLINE);
423 if(stateData.getState().getLastActivityTime()>0){ 428 if(stateData.getState().getLastActivityTime()>0){
424 String tenantId = stateData.getTenantId().getId().toString(); 429 String tenantId = stateData.getTenantId().getId().toString();
425 String tbDeviceId = deviceId.getId().toString(); 430 String tbDeviceId = deviceId.getId().toString();
@@ -24,10 +24,8 @@ import com.google.common.util.concurrent.Futures; @@ -24,10 +24,8 @@ import com.google.common.util.concurrent.Futures;
24 import com.google.common.util.concurrent.ListenableFuture; 24 import com.google.common.util.concurrent.ListenableFuture;
25 import com.google.common.util.concurrent.MoreExecutors; 25 import com.google.common.util.concurrent.MoreExecutors;
26 import com.google.protobuf.ByteString; 26 import com.google.protobuf.ByteString;
27 -import java.util.List;  
28 -import java.util.Optional;  
29 -import java.util.Set;  
30 -import java.util.UUID; 27 +
  28 +import java.util.*;
31 import java.util.concurrent.ConcurrentHashMap; 29 import java.util.concurrent.ConcurrentHashMap;
32 import java.util.concurrent.ConcurrentMap; 30 import java.util.concurrent.ConcurrentMap;
33 import java.util.concurrent.locks.Lock; 31 import java.util.concurrent.locks.Lock;
@@ -886,10 +884,18 @@ public class DefaultTransportApiService implements TransportApiService { @@ -886,10 +884,18 @@ public class DefaultTransportApiService implements TransportApiService {
886 dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray()); 884 dataDecodingEncodingService.decode(requestMsg.getContext().toByteArray());
887 allChannel.ifPresent( 885 allChannel.ifPresent(
888 d -> { 886 d -> {
889 - channelService.clearDeviceChannel(d.get(0).getCameraCode()); 887 + String cameraCode = d.get(0).getCameraCode();
  888 + Map<String, String> playingChannels = channelService.findPlayingChannel(cameraCode);
  889 + channelService.clearDeviceChannel(cameraCode);
890 List<TkVideoChannelEntity> chanel = 890 List<TkVideoChannelEntity> chanel =
891 d.stream() 891 d.stream()
892 - .map(item -> item.getEntity(TkVideoChannelEntity.class)) 892 + .map(item -> {
  893 + String channelId = item.getChannelId();
  894 + if(playingChannels.containsKey(channelId)){
  895 + item.setStreamId(playingChannels.get(channelId));
  896 + }
  897 + return item.getEntity(TkVideoChannelEntity.class);
  898 + })
893 .collect(Collectors.toList()); 899 .collect(Collectors.toList());
894 channelService.insertBatch(chanel, chanel.size()); 900 channelService.insertBatch(chanel, chanel.size());
895 }); 901 });
@@ -82,7 +82,7 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -82,7 +82,7 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
82 // 找到可以使用的流媒体 82 // 找到可以使用的流媒体
83 MediaServerDTO mediaServer = 83 MediaServerDTO mediaServer =
84 tkMediaServerService.getMediaServerForPlay(tenantId, sipDeviceDTO.getMediaServerId()); 84 tkMediaServerService.getMediaServerForPlay(tenantId, sipDeviceDTO.getMediaServerId());
85 - if (null == mediaServer) { 85 + if (null == mediaServer || !mediaServer.isStatus()) {
86 throw new TkDataValidationException( 86 throw new TkDataValidationException(
87 ErrorMessage.NOT_FOUND_MEDIA_SERVER_FOR_PLAY.getMessage()); 87 ErrorMessage.NOT_FOUND_MEDIA_SERVER_FOR_PLAY.getMessage());
88 } 88 }
@@ -28,6 +28,7 @@ import org.thingsboard.server.dao.tenant.TenantService; @@ -28,6 +28,7 @@ import org.thingsboard.server.dao.tenant.TenantService;
28 import org.thingsboard.server.dao.timeseries.TimeseriesService; 28 import org.thingsboard.server.dao.timeseries.TimeseriesService;
29 import org.thingsboard.server.dao.yunteng.service.TkDeviceService; 29 import org.thingsboard.server.dao.yunteng.service.TkDeviceService;
30 import org.thingsboard.server.dao.yunteng.service.TkDeviceStateLogService; 30 import org.thingsboard.server.dao.yunteng.service.TkDeviceStateLogService;
  31 +import org.thingsboard.server.dao.yunteng.service.media.TkVideoChannelService;
31 import org.thingsboard.server.queue.discovery.PartitionService; 32 import org.thingsboard.server.queue.discovery.PartitionService;
32 import org.thingsboard.server.cluster.TbClusterService; 33 import org.thingsboard.server.cluster.TbClusterService;
33 34
@@ -59,14 +60,15 @@ public class DefaultDeviceStateServiceTest { @@ -59,14 +60,15 @@ public class DefaultDeviceStateServiceTest {
59 TkDeviceService tkDeviceService; 60 TkDeviceService tkDeviceService;
60 @Mock 61 @Mock
61 TkDeviceStateLogService tkDeviceStateLogService; 62 TkDeviceStateLogService tkDeviceStateLogService;
62 - 63 + @Mock
  64 + TkVideoChannelService channelService;
63 DeviceId deviceId = DeviceId.fromString("00797a3b-7aeb-4b5b-b57a-c2a810d0f112"); 65 DeviceId deviceId = DeviceId.fromString("00797a3b-7aeb-4b5b-b57a-c2a810d0f112");
64 66
65 DefaultDeviceStateService service; 67 DefaultDeviceStateService service;
66 68
67 @Before 69 @Before
68 public void setUp() { 70 public void setUp() {
69 - service = spy(new DefaultDeviceStateService(tenantService, deviceService, attributesService, tsService, clusterService, partitionService,tkDeviceService,tkDeviceStateLogService)); 71 + service = spy(new DefaultDeviceStateService(tenantService, deviceService, attributesService, tsService, clusterService, partitionService,tkDeviceService, channelService, tkDeviceStateLogService));
70 } 72 }
71 73
72 @Test 74 @Test
@@ -86,4 +88,4 @@ public class DefaultDeviceStateServiceTest { @@ -86,4 +88,4 @@ public class DefaultDeviceStateServiceTest {
86 Mockito.verify(service, times(1)).fetchDeviceStateData(deviceId); 88 Mockito.verify(service, times(1)).fetchDeviceStateData(deviceId);
87 } 89 }
88 90
89 -}  
  91 +}
@@ -138,7 +138,7 @@ public final class ModelConstants { @@ -138,7 +138,7 @@ public final class ModelConstants {
138 public static final String TK_DEVICE_ACCESS_INFORMATION = "tk_device_access_information"; 138 public static final String TK_DEVICE_ACCESS_INFORMATION = "tk_device_access_information";
139 139
140 /** ZLMediaKit 流媒体表 */ 140 /** ZLMediaKit 流媒体表 */
141 - public static final String TK_MEDIA_SERVER_NAME = "tk_media_server"; 141 + public static final String TK_MEDIA_SERVER_NAME = "tk_video_zlmediakit";
142 142
143 /** 视频通道表 */ 143 /** 视频通道表 */
144 public static final String TK_VIDEO_CHANNEL_NAME = "tk_video_channel"; 144 public static final String TK_VIDEO_CHANNEL_NAME = "tk_video_channel";
@@ -136,6 +136,7 @@ public enum ErrorMessage { @@ -136,6 +136,7 @@ public enum ErrorMessage {
136 136
137 DEVICE_NOT_ONLINE(400111,"设备不在线,无法执行相关操作!"), 137 DEVICE_NOT_ONLINE(400111,"设备不在线,无法执行相关操作!"),
138 GBT_VIDEO_REPETITION(400112,"该设备通道号视频已存在!"), 138 GBT_VIDEO_REPETITION(400112,"该设备通道号视频已存在!"),
  139 + SSRC_NO_ENABLED(400113,"未获取到可用的SSRC资源"),
139 HAVE_NO_PERMISSION(500002,"没有修改权限"), 140 HAVE_NO_PERMISSION(500002,"没有修改权限"),
140 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置"); 141 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置");
141 142
@@ -23,7 +23,7 @@ public class TkMediaServerEntity extends TenantBaseEntity { @@ -23,7 +23,7 @@ public class TkMediaServerEntity extends TenantBaseEntity {
23 private Integer rtspSslPort; 23 private Integer rtspSslPort;
24 private String secret; 24 private String secret;
25 private boolean rtpEnable; 25 private boolean rtpEnable;
26 - private Integer status; 26 + private boolean status;
27 private String rtpPortRange; 27 private String rtpPortRange;
28 private String sendRtpPortRange; 28 private String sendRtpPortRange;
29 private int recordAssistPort; 29 private int recordAssistPort;
@@ -8,6 +8,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting; @@ -8,6 +8,7 @@ import org.thingsboard.server.common.data.yunteng.config.media.UserSetting;
8 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants; 8 import org.thingsboard.server.common.data.yunteng.constant.FastIotConstants;
9 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils; 9 import org.thingsboard.server.common.data.yunteng.core.cache.CacheUtils;
10 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException; 10 import org.thingsboard.server.common.data.yunteng.core.exception.TkDataValidationException;
  11 +import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
11 12
12 /** ssrc使用 */ 13 /** ssrc使用 */
13 @Component 14 @Component
@@ -88,7 +89,7 @@ public class SSRCFactory { @@ -88,7 +89,7 @@ public class SSRCFactory {
88 String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId; 89 String redisKey = SSRC_INFO_KEY + userSetting.getServerId() + "_" + mediaServerId;
89 Optional<Set<String>> all = cacheUtils.get(cacheName, redisKey); 90 Optional<Set<String>> all = cacheUtils.get(cacheName, redisKey);
90 if (all.isEmpty()) { 91 if (all.isEmpty()) {
91 - throw new TkDataValidationException("ssrc已经用完"); 92 + throw new TkDataValidationException(ErrorMessage.SSRC_NO_ENABLED.getMessage());
92 } else { 93 } else {
93 // 在集合中移除并返回第一个成员。 94 // 在集合中移除并返回第一个成员。
94 Set<String> list = all.get(); 95 Set<String> list = all.get();
@@ -3,9 +3,12 @@ package org.thingsboard.server.dao.yunteng.impl.media; @@ -3,9 +3,12 @@ package org.thingsboard.server.dao.yunteng.impl.media;
3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; 3 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
4 import com.baomidou.mybatisplus.core.metadata.IPage; 4 import com.baomidou.mybatisplus.core.metadata.IPage;
5 import java.time.LocalDateTime; 5 import java.time.LocalDateTime;
  6 +import java.util.HashMap;
6 import java.util.List; 7 import java.util.List;
7 import java.util.Map; 8 import java.util.Map;
8 import java.util.Optional; 9 import java.util.Optional;
  10 +import java.util.stream.Collectors;
  11 +
9 import lombok.RequiredArgsConstructor; 12 import lombok.RequiredArgsConstructor;
10 import org.springframework.stereotype.Service; 13 import org.springframework.stereotype.Service;
11 import org.springframework.transaction.annotation.Transactional; 14 import org.springframework.transaction.annotation.Transactional;
@@ -74,6 +77,23 @@ public class TkVideoChannelServiceImpl @@ -74,6 +77,23 @@ public class TkVideoChannelServiceImpl
74 } 77 }
75 78
76 @Override 79 @Override
  80 + public Map<String, String> findPlayingChannel(String cameraCode) {
  81 + List<TkVideoChannelEntity> channelList =
  82 + baseMapper.selectList(
  83 + new LambdaQueryWrapper<TkVideoChannelEntity>()
  84 + .isNotNull(TkVideoChannelEntity::getStreamId)
  85 + .eq(TkVideoChannelEntity::getCameraCode, cameraCode));
  86 + Map<String, String> result = new HashMap<>();
  87 + if(channelList == null){
  88 + return result;
  89 + }
  90 + channelList.forEach(item ->{
  91 + result.put(item.getChannelId(),item.getStreamId());
  92 + });
  93 + return result;
  94 + }
  95 +
  96 + @Override
77 public VideoChanelDTO updateChannelInfo(VideoChanelDTO videoChanelDTO) { 97 public VideoChanelDTO updateChannelInfo(VideoChanelDTO videoChanelDTO) {
78 if (StringUtils.isEmpty(videoChanelDTO.getId())) { 98 if (StringUtils.isEmpty(videoChanelDTO.getId())) {
79 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 99 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
@@ -103,6 +123,14 @@ public class TkVideoChannelServiceImpl @@ -103,6 +123,14 @@ public class TkVideoChannelServiceImpl
103 .orElse(false); 123 .orElse(false);
104 } 124 }
105 125
  126 + @Override
  127 + public void updateVideoChannelState(String tbDeviceId, StatusEnum online) {
  128 + TkVideoChannelEntity entity = new TkVideoChannelEntity();
  129 + entity.setStatus(online);
  130 + entity.setStreamId(null);
  131 + baseMapper.update(entity,new LambdaQueryWrapper<TkVideoChannelEntity>()
  132 + .eq(TkVideoChannelEntity::getDeviceId, tbDeviceId));
  133 + }
106 134
107 @Override 135 @Override
108 public List<VideoChanelDTO> getListByDeviceId(String deviceId,String tenantId) { 136 public List<VideoChanelDTO> getListByDeviceId(String deviceId,String tenantId) {
@@ -3,6 +3,7 @@ package org.thingsboard.server.dao.yunteng.service.media; @@ -3,6 +3,7 @@ package org.thingsboard.server.dao.yunteng.service.media;
3 import java.util.List; 3 import java.util.List;
4 import java.util.Map; 4 import java.util.Map;
5 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO; 5 import org.thingsboard.server.common.data.yunteng.dto.sip.VideoChanelDTO;
  6 +import org.thingsboard.server.common.data.yunteng.enums.StatusEnum;
6 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 7 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
7 import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity; 8 import org.thingsboard.server.dao.yunteng.entities.TkVideoChannelEntity;
8 import org.thingsboard.server.dao.yunteng.service.BaseService; 9 import org.thingsboard.server.dao.yunteng.service.BaseService;
@@ -27,7 +28,12 @@ public interface TkVideoChannelService extends BaseService<TkVideoChannelEntity> @@ -27,7 +28,12 @@ public interface TkVideoChannelService extends BaseService<TkVideoChannelEntity>
27 * @param cameraCode 28 * @param cameraCode
28 * @return 29 * @return
29 */ 30 */
30 - int clearDeviceChannel(String cameraCode); 31 + int clearDeviceChannel(String cameraCode); /**
  32 + * 查询点播中的摄像头通道
  33 + * @param cameraCode
  34 + * @return
  35 + */
  36 + Map<String,String> findPlayingChannel(String cameraCode);
31 37
32 /** 38 /**
33 * 更新视频通道信息。 39 * 更新视频通道信息。
@@ -46,7 +52,14 @@ public interface TkVideoChannelService extends BaseService<TkVideoChannelEntity> @@ -46,7 +52,14 @@ public interface TkVideoChannelService extends BaseService<TkVideoChannelEntity>
46 * @return true 更新成功 false更新失败 52 * @return true 更新成功 false更新失败
47 */ 53 */
48 boolean updateVideoChannelStreamId( 54 boolean updateVideoChannelStreamId(
49 - String streamId, String deviceCode, String channelId); 55 + String streamId, String deviceCode, String channelId);
  56 + /**
  57 + * 更新视频通道状态
  58 + *
  59 + * @param tbDeviceId 设备ID
  60 + * @return true 更新成功 false更新失败
  61 + */
  62 + void updateVideoChannelState(String tbDeviceId, StatusEnum online);
50 63
51 /** 64 /**
52 * 根据设备id获取通道号集合 65 * 根据设备id获取通道号集合