Commit a9f21c6b771c6e54f4a9e19195ad493f7d7e705c

Authored by 李 俊亮
Committed by xp.Huang
1 parent 71c6d651

fix:云台控制传参参数错误

@@ -12,6 +12,7 @@ import org.apache.curator.shaded.com.google.common.util.concurrent.Futures; @@ -12,6 +12,7 @@ import org.apache.curator.shaded.com.google.common.util.concurrent.Futures;
12 import org.apache.curator.shaded.com.google.common.util.concurrent.ListenableFuture; 12 import org.apache.curator.shaded.com.google.common.util.concurrent.ListenableFuture;
13 import org.checkerframework.checker.nullness.qual.Nullable; 13 import org.checkerframework.checker.nullness.qual.Nullable;
14 import org.jetbrains.annotations.NotNull; 14 import org.jetbrains.annotations.NotNull;
  15 +import org.springframework.security.access.prepost.PreAuthorize;
15 import org.springframework.web.bind.annotation.*; 16 import org.springframework.web.bind.annotation.*;
16 import org.springframework.web.context.request.async.DeferredResult; 17 import org.springframework.web.context.request.async.DeferredResult;
17 import org.thingsboard.server.common.data.StringUtils; 18 import org.thingsboard.server.common.data.StringUtils;
@@ -38,34 +39,67 @@ public class TkVideoControlController extends BaseController { @@ -38,34 +39,67 @@ public class TkVideoControlController extends BaseController {
38 39
39 @GetMapping("/start/{deviceId}/{channelId}") 40 @GetMapping("/start/{deviceId}/{channelId}")
40 @ApiOperation(value = "视频点播/预览") 41 @ApiOperation(value = "视频点播/预览")
  42 + @PreAuthorize(
  43 + "@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:play'})")
41 public DeferredResult<ResponseResult<StreamContentDTO>> startPlay( 44 public DeferredResult<ResponseResult<StreamContentDTO>> startPlay(
42 - @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId)  
43 - throws ThingsboardException { 45 + @PathVariable("deviceId") String tbDeviceId, @PathVariable("channelId") String channelId)
  46 + throws ThingsboardException {
44 if (StringUtils.isEmpty(tbDeviceId) || StringUtils.isEmpty(channelId)) { 47 if (StringUtils.isEmpty(tbDeviceId) || StringUtils.isEmpty(channelId)) {
45 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 48 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
46 } 49 }
47 DeferredResult<ResponseResult<StreamContentDTO>> response = new DeferredResult<>(); 50 DeferredResult<ResponseResult<StreamContentDTO>> response = new DeferredResult<>();
48 ListenableFuture<StreamContentDTO> future = 51 ListenableFuture<StreamContentDTO> future =
49 - tkVideoControlService.startPlay(getCurrentUser(),tbDeviceId, channelId, getCurrentUser().getCurrentTenantId()); 52 + tkVideoControlService.startPlay(getCurrentUser(),tbDeviceId, channelId);
  53 + Futures.addCallback(
  54 + future,
  55 + new FutureCallback<>() {
  56 + @Override
  57 + public void onSuccess(@Nullable StreamContentDTO streamContentDTO) {
  58 + response.setResult(ResponseResult.success(streamContentDTO));
  59 + }
  60 +
  61 + @Override
  62 + public void onFailure(@NotNull Throwable throwable) {
  63 + response.setResult(ResponseResult.failed(throwable.getMessage()));
  64 + }
  65 + },
  66 + MoreExecutors.directExecutor());
  67 + return response;
  68 + }
  69 + @GetMapping("/sync/{deviceId}")
  70 + @ApiOperation(value = "摄像头通道同步")
  71 + @PreAuthorize(
  72 + "@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:channel'})")
  73 + public DeferredResult<ResponseResult<String>> freshChannel(
  74 + @PathVariable("deviceId") String tbDeviceId)
  75 + throws ThingsboardException {
  76 + if (StringUtils.isEmpty(tbDeviceId) ) {
  77 + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  78 + }
  79 + DeferredResult<ResponseResult<String>> response = new DeferredResult<>();
  80 + ListenableFuture<String> future =
  81 + tkVideoControlService.freshChannel(getCurrentUser(),tbDeviceId);
50 Futures.addCallback( 82 Futures.addCallback(
51 - future,  
52 - new FutureCallback<>() {  
53 - @Override  
54 - public void onSuccess(@Nullable StreamContentDTO streamContentDTO) {  
55 - response.setResult(ResponseResult.success(streamContentDTO));  
56 - } 83 + future,
  84 + new FutureCallback<>() {
  85 + @Override
  86 + public void onSuccess(@Nullable String result) {
  87 + response.setResult(ResponseResult.success(result));
  88 + }
57 89
58 - @Override  
59 - public void onFailure(@NotNull Throwable throwable) {  
60 - response.setResult(ResponseResult.failed(null));  
61 - }  
62 - },  
63 - MoreExecutors.directExecutor()); 90 + @Override
  91 + public void onFailure(@NotNull Throwable throwable) {
  92 + response.setResult(ResponseResult.failed(throwable.getMessage()));
  93 + }
  94 + },
  95 + MoreExecutors.directExecutor());
64 return response; 96 return response;
65 } 97 }
66 98
67 @ApiOperation(value = "停止点播") 99 @ApiOperation(value = "停止点播")
68 @GetMapping("/stop/{deviceId}/{channelId}") 100 @GetMapping("/stop/{deviceId}/{channelId}")
  101 + @PreAuthorize(
  102 + "@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:stop'})")
69 public ResponseResult playStop( 103 public ResponseResult playStop(
70 @ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String tbDeviceId, 104 @ApiParam(value = "设备ID", required = true) @PathVariable("deviceId") String tbDeviceId,
71 @ApiParam(value = "通道ID", required = true) @PathVariable("channelId") String channelId) 105 @ApiParam(value = "通道ID", required = true) @PathVariable("channelId") String channelId)
@@ -89,6 +123,8 @@ public class TkVideoControlController extends BaseController { @@ -89,6 +123,8 @@ public class TkVideoControlController extends BaseController {
89 @Parameter(name = "verticalSpeed", description = "垂直速度", required = true) 123 @Parameter(name = "verticalSpeed", description = "垂直速度", required = true)
90 @Parameter(name = "zoomSpeed", description = "缩放速度", required = true) 124 @Parameter(name = "zoomSpeed", description = "缩放速度", required = true)
91 @GetMapping("/control/{tbDeviceId}/{channelId}") 125 @GetMapping("/control/{tbDeviceId}/{channelId}")
  126 + @PreAuthorize(
  127 + "@check.checkPermissions({'SYS_ADMIN','PLATFORM_ADMIN','TENANT_ADMIN','CUSTOMER_USER'},{'api:yt:video:control:control'})")
92 public void ptzControl( 128 public void ptzControl(
93 @PathVariable String tbDeviceId, 129 @PathVariable String tbDeviceId,
94 @PathVariable String channelId, 130 @PathVariable String channelId,
@@ -17,11 +17,18 @@ public interface TkVideoControlService { @@ -17,11 +17,18 @@ public interface TkVideoControlService {
17 * 17 *
18 * @param deviceId 设备ID 18 * @param deviceId 设备ID
19 * @param channelId 通道ID 19 * @param channelId 通道ID
20 - * @param tenantId 租户ID  
21 * @return 视频流播放地址内容 20 * @return 视频流播放地址内容
22 */ 21 */
23 ListenableFuture<StreamContentDTO> startPlay( 22 ListenableFuture<StreamContentDTO> startPlay(
24 - SecurityUser currentUser, String deviceId, String channelId, String tenantId); 23 + SecurityUser currentUser, String deviceId, String channelId);
  24 +
  25 + /**
  26 + * 摄像头通道同步
  27 + *
  28 + * @param deviceId 设备ID
  29 + * @return 视频流播放地址内容
  30 + */
  31 + ListenableFuture<String> freshChannel(SecurityUser currentUser, String deviceId);
25 32
26 /** 33 /**
27 * 当点播时的推送处理程序 34 * 当点播时的推送处理程序
@@ -41,20 +48,30 @@ public interface TkVideoControlService { @@ -41,20 +48,30 @@ public interface TkVideoControlService {
41 * @param channelId 通道ID 48 * @param channelId 通道ID
42 * @return 暂停播放结果 true成功 false失败 49 * @return 暂停播放结果 true成功 false失败
43 */ 50 */
44 - boolean stopPlay(SecurityUser currentUser, String tbDeviceId, String channelId) throws ThingsboardException; 51 + boolean stopPlay(SecurityUser currentUser, String tbDeviceId, String channelId)
  52 + throws ThingsboardException;
45 53
46 /** 54 /**
47 * 摄像头控制 55 * 摄像头控制
  56 + *
48 * @param currentUser 登录用户 57 * @param currentUser 登录用户
49 * @param tbDeviceId 设备ID 58 * @param tbDeviceId 设备ID
50 * @param channelId 设备通道 59 * @param channelId 设备通道
51 - * @param command 控制指令 60 + * @param command 控制指令
52 * @param horizonSpeed 水平速度 61 * @param horizonSpeed 水平速度
53 * @param verticalSpeed 垂直速度 62 * @param verticalSpeed 垂直速度
54 * @param zoomSpeed 缩放速度 63 * @param zoomSpeed 缩放速度
55 * @return 64 * @return
56 */ 65 */
57 - boolean control(SecurityUser currentUser, String tbDeviceId, String channelId, PTZCommandEnum command, int horizonSpeed, int verticalSpeed, int zoomSpeed) throws ThingsboardException; 66 + boolean control(
  67 + SecurityUser currentUser,
  68 + String tbDeviceId,
  69 + String channelId,
  70 + PTZCommandEnum command,
  71 + int horizonSpeed,
  72 + int verticalSpeed,
  73 + int zoomSpeed)
  74 + throws ThingsboardException;
58 75
59 StreamInfoDTO play( 76 StreamInfoDTO play(
60 SecurityUser currentUser, 77 SecurityUser currentUser,
@@ -63,11 +80,14 @@ public interface TkVideoControlService { @@ -63,11 +80,14 @@ public interface TkVideoControlService {
63 SsrcInfoDTO ssrcInfo, 80 SsrcInfoDTO ssrcInfo,
64 SipDeviceDTO device, 81 SipDeviceDTO device,
65 String channelId); 82 String channelId);
  83 +
66 public void byeCmdInSsrcTransaction( 84 public void byeCmdInSsrcTransaction(
67 - String tenantId,  
68 - boolean oneWay,  
69 - String tbDeviceId,  
70 - String cameraCode,String channelId,String streamId,  
71 - Consumer<FromDeviceRpcResponse> responseConsumer)  
72 - throws ThingsboardException; 85 + String tenantId,
  86 + boolean oneWay,
  87 + String tbDeviceId,
  88 + String cameraCode,
  89 + String channelId,
  90 + String streamId,
  91 + Consumer<FromDeviceRpcResponse> responseConsumer)
  92 + throws ThingsboardException;
73 } 93 }
@@ -31,9 +31,7 @@ import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage; @@ -31,9 +31,7 @@ import org.thingsboard.server.common.data.yunteng.core.message.ErrorMessage;
31 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO; 31 import org.thingsboard.server.common.data.yunteng.dto.DeviceDTO;
32 import org.thingsboard.server.common.data.yunteng.dto.sip.*; 32 import org.thingsboard.server.common.data.yunteng.dto.sip.*;
33 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.HookSubscribeForStreamChange; 33 import org.thingsboard.server.common.data.yunteng.dto.sip.hook.param.HookSubscribeForStreamChange;
34 -import org.thingsboard.server.common.data.yunteng.enums.PTZCommandEnum;  
35 -import org.thingsboard.server.common.data.yunteng.enums.SessionTypeEnum;  
36 -import org.thingsboard.server.common.data.yunteng.enums.VideoMethodEnum; 34 +import org.thingsboard.server.common.data.yunteng.enums.*;
37 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil; 35 import org.thingsboard.server.common.data.yunteng.utils.JacksonUtil;
38 import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils; 36 import org.thingsboard.server.common.data.yunteng.utils.ZLMediaKitRestFulUtils;
39 import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse; 37 import org.thingsboard.server.common.msg.rpc.FromDeviceRpcResponse;
@@ -63,7 +61,8 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -63,7 +61,8 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
63 61
64 @Override 62 @Override
65 public ListenableFuture<StreamContentDTO> startPlay( 63 public ListenableFuture<StreamContentDTO> startPlay(
66 - SecurityUser currentUser, String deviceId, String channelId, String tenantId) { 64 + SecurityUser currentUser, String deviceId, String channelId) {
  65 + String tenantId = currentUser.getCurrentTenantId();
67 // 判断设备、通道是否存在 66 // 判断设备、通道是否存在
68 DeviceDTO deviceDTO = tkDeviceService.checkDeviceByTenantIdAndId(tenantId, deviceId, true); 67 DeviceDTO deviceDTO = tkDeviceService.checkDeviceByTenantIdAndId(tenantId, deviceId, true);
69 SipDeviceDTO sipDeviceDTO = 68 SipDeviceDTO sipDeviceDTO =
@@ -74,7 +73,9 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -74,7 +73,9 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
74 if (null == sipDeviceDTO) { 73 if (null == sipDeviceDTO) {
75 throw new TkDataValidationException(ErrorMessage.FOUND_VIDEO_DEVICE_FAILED.getMessage()); 74 throw new TkDataValidationException(ErrorMessage.FOUND_VIDEO_DEVICE_FAILED.getMessage());
76 } 75 }
77 - VideoChanelDTO videoChanelDTO = tkVideoChannelService.findVideoChannelById(sipDeviceDTO.getCameraCode(), channelId, tenantId); 76 + VideoChanelDTO videoChanelDTO =
  77 + tkVideoChannelService.findVideoChannelById(
  78 + sipDeviceDTO.getCameraCode(), channelId, tenantId);
78 if (null == videoChanelDTO) { 79 if (null == videoChanelDTO) {
79 throw new TkDataValidationException(ErrorMessage.VIDEO_CHANNEL_NOT_FOUND.getMessage()); 80 throw new TkDataValidationException(ErrorMessage.VIDEO_CHANNEL_NOT_FOUND.getMessage());
80 } 81 }
@@ -114,6 +115,69 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -114,6 +115,69 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
114 } 115 }
115 116
116 @Override 117 @Override
  118 + public ListenableFuture<String> freshChannel(SecurityUser currentUser, String deviceId) {
  119 + String tenantId = currentUser.getCurrentTenantId();
  120 + // 判断设备、通道是否存在
  121 + Optional<DeviceDTO> device = Optional.ofNullable(tkDeviceService.checkDeviceByTenantIdAndId(tenantId, deviceId, true));
  122 + if(device.isEmpty()){
  123 + return Futures.immediateFuture(ErrorMessage.DEVICE_NOT_EXTIED.getMessage());
  124 + }
  125 + DeviceDTO deviceDTO = device.get();
  126 + if (!deviceDTO.getDeviceState().equals(DeviceState.ONLINE)) {
  127 + return Futures.immediateFuture(ErrorMessage.DEVICE_NOT_ONLINE.getMessage());
  128 + }
  129 + SipDeviceDTO sipDeviceDTO =
  130 + JacksonUtil.convertValue(
  131 + deviceDTO.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP),
  132 + SipDeviceDTO.class);
  133 + // 获取设备的附加信息
  134 + if (null == sipDeviceDTO) {
  135 + throw new TkDataValidationException(ErrorMessage.FOUND_VIDEO_DEVICE_FAILED.getMessage());
  136 + }
  137 + CountDownLatch timeoutLatch = new CountDownLatch(1);
  138 + AtomicReference<String> result = new AtomicReference<>();
  139 + // 进行命令发送
  140 +
  141 +
  142 + ObjectNode paramJson = JacksonUtil.newObjectNode();
  143 + paramJson.put(FastIotConstants.ZLMediaBody.MSG_TYPE, VideoXmlEnum.Query.name());
  144 + int sn = (int) ((Math.random() * 9 + 1) * 100000);
  145 + paramJson.put(FastIotConstants.ZLMediaBody.MSG_CONTEXT, sn);
  146 +
  147 + try {
  148 + cameraCommonCmd(
  149 + currentUser.getCurrentTenantId(),
  150 + paramJson,
  151 + sipDeviceDTO.getCameraCode(),
  152 + VideoMethodEnum.MESSAGE,
  153 + false,
  154 + deviceId,
  155 + fromDeviceRpcResponse -> {
  156 + log.warn(
  157 + "【流媒体SIP】收到【视频点播】结果=异常【{}】+数据【{}】",
  158 + fromDeviceRpcResponse.getError(),
  159 + fromDeviceRpcResponse.getResponse());
  160 + fromDeviceRpcResponse
  161 + .getResponse()
  162 + .ifPresent(
  163 + jsonStr -> {
  164 + JsonNode responseJson = JacksonUtil.toJsonNode(jsonStr);
  165 + if (fromDeviceRpcResponse.getError().isEmpty()) {
  166 + result.set(jsonStr);
  167 + } else {
  168 + result.set(fromDeviceRpcResponse.getError().get().name());
  169 + }
  170 + });
  171 + timeoutLatch.countDown();
  172 + });
  173 + } catch (ThingsboardException e) {
  174 + Futures.immediateFailedFuture(e);
  175 + }
  176 + return Futures.immediateFuture(result.get());
  177 +
  178 + }
  179 +
  180 + @Override
117 public StreamInfoDTO onPublishHandlerForPlay( 181 public StreamInfoDTO onPublishHandlerForPlay(
118 MediaServerDTO mediaServerItem, JsonNode response, String deviceCode, String channelId) { 182 MediaServerDTO mediaServerItem, JsonNode response, String deviceCode, String channelId) {
119 StreamInfoDTO streamInfo = onPublishHandler(mediaServerItem, response, deviceCode, channelId); 183 StreamInfoDTO streamInfo = onPublishHandler(mediaServerItem, response, deviceCode, channelId);
@@ -130,37 +194,41 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -130,37 +194,41 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
130 } 194 }
131 195
132 @Override 196 @Override
133 - public boolean stopPlay(SecurityUser currentUser, String tbDeviceId, String channelId) throws ThingsboardException {  
134 - String tenantId = currentUser.getCurrentTenantId();  
135 - DeviceDTO deviceDTO = tkDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId);  
136 - if (null == deviceDTO  
137 - || !deviceDTO.getDeviceInfo().has(FastIotConstants.DeviceAdditional.SIP)) {  
138 - throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());  
139 - }  
140 - String cameraCode =  
141 - deviceDTO  
142 - .getDeviceInfo()  
143 - .get(FastIotConstants.DeviceAdditional.SIP)  
144 - .get(FastIotConstants.ZLMediaBody.CAMERA_CODE)  
145 - .asText();  
146 -  
147 - Optional<StreamInfoDTO> streamInfoDTO =  
148 - tkCacheStorageService.queryPlayStreamByChannel(cameraCode, channelId);  
149 - if (streamInfoDTO.isEmpty()) {  
150 - throw new TkDataValidationException(  
151 - ErrorMessage.STREAM_INFO_NOT_FOUND_FOR_PLAY.getMessage());  
152 - }  
153 - byeCmdInSsrcTransaction(  
154 - currentUser.getCurrentTenantId(),  
155 - false,  
156 - tbDeviceId,  
157 - cameraCode,channelId,streamInfoDTO.get().getStream(),  
158 - fromDeviceRpcResponse->{  
159 -  
160 - }); 197 + public boolean stopPlay(SecurityUser currentUser, String tbDeviceId, String channelId)
  198 + throws ThingsboardException {
  199 + String tenantId = currentUser.getCurrentTenantId();
  200 + DeviceDTO deviceDTO = tkDeviceService.findDeviceInfoByTbDeviceId(tenantId, tbDeviceId);
  201 + if (null == deviceDTO
  202 + || !deviceDTO.getDeviceInfo().has(FastIotConstants.DeviceAdditional.SIP)) {
  203 + throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
  204 + }
  205 + String cameraCode =
  206 + deviceDTO
  207 + .getDeviceInfo()
  208 + .get(FastIotConstants.DeviceAdditional.SIP)
  209 + .get(FastIotConstants.ZLMediaBody.CAMERA_CODE)
  210 + .asText();
  211 +
  212 + Optional<StreamInfoDTO> streamInfoDTO =
  213 + tkCacheStorageService.queryPlayStreamByChannel(cameraCode, channelId);
  214 + if (streamInfoDTO.isEmpty()) {
  215 + throw new TkDataValidationException(ErrorMessage.STREAM_INFO_NOT_FOUND_FOR_PLAY.getMessage());
  216 + }
  217 + byeCmdInSsrcTransaction(
  218 + currentUser.getCurrentTenantId(),
  219 + false,
  220 + tbDeviceId,
  221 + cameraCode,
  222 + channelId,
  223 + streamInfoDTO.get().getStream(),
  224 + fromDeviceRpcResponse -> {});
161 225
162 - tkCacheStorageService.deleteCacheStreamInfoByStopPlay(streamInfoDTO.get()); //redisCatchStorage.stopPlay(streamInfo);  
163 - return tkVideoChannelService.updateVideoChannelStreamId(null, cameraCode, channelId);//storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 226 + tkCacheStorageService.deleteCacheStreamInfoByStopPlay(
  227 + streamInfoDTO.get()); // redisCatchStorage.stopPlay(streamInfo);
  228 + return tkVideoChannelService.updateVideoChannelStreamId(
  229 + null,
  230 + cameraCode,
  231 + channelId); // storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
164 } 232 }
165 233
166 @Override 234 @Override
@@ -214,7 +282,8 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -214,7 +282,8 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
214 mediaServerDTO.getMediaServerId(), ssrcInfoDTO.getSsrc()); 282 mediaServerDTO.getMediaServerId(), ssrcInfoDTO.getSsrc());
215 videoStreamSessionManager.remove( 283 videoStreamSessionManager.remove(
216 sipDeviceDTO.getCameraCode(), channelId, ssrcInfoDTO.getStream()); 284 sipDeviceDTO.getCameraCode(), channelId, ssrcInfoDTO.getStream());
217 - throw new TkDataValidationException(ErrorMessage.GET_PLAY_PORT_FAILED.getMessage()); 285 + throw new TkDataValidationException(
  286 + String.format(ErrorMessage.GET_PLAY_PORT_FAILED.getMessage(), mediaServerDTO.getIp()));
218 } 287 }
219 // 进行命令发送 288 // 进行命令发送
220 AtomicReference<StreamInfoDTO> result = new AtomicReference<>(); 289 AtomicReference<StreamInfoDTO> result = new AtomicReference<>();
@@ -263,9 +332,12 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -263,9 +332,12 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
263 sipDeviceDTO.getCameraCode(), 332 sipDeviceDTO.getCameraCode(),
264 VideoMethodEnum.INVITE, 333 VideoMethodEnum.INVITE,
265 false, 334 false,
266 - tbDeviceId, 335 + tbDeviceId,
267 fromDeviceRpcResponse -> { 336 fromDeviceRpcResponse -> {
268 - log.warn("【流媒体SIP】收到【视频点播】结果=异常【{}】+数据【{}】",fromDeviceRpcResponse.getError(), fromDeviceRpcResponse.getResponse()); 337 + log.warn(
  338 + "【流媒体SIP】收到【视频点播】结果=异常【{}】+数据【{}】",
  339 + fromDeviceRpcResponse.getError(),
  340 + fromDeviceRpcResponse.getResponse());
269 fromDeviceRpcResponse 341 fromDeviceRpcResponse
270 .getResponse() 342 .getResponse()
271 .ifPresent( 343 .ifPresent(
@@ -298,7 +370,7 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -298,7 +370,7 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
298 } catch (Exception e) { 370 } catch (Exception e) {
299 zlMediaKitTaskUtils.stop(timeOutTaskKey); 371 zlMediaKitTaskUtils.stop(timeOutTaskKey);
300 tkMediaServerNodeService.closeRTPServer( 372 tkMediaServerNodeService.closeRTPServer(
301 - Optional.ofNullable(mediaServerDTO), ssrcInfoDTO.getStream()); 373 + Optional.of(mediaServerDTO), ssrcInfoDTO.getStream());
302 // 释放ssrc 374 // 释放ssrc
303 tkMediaServerNodeService.releaseSsrc(mediaServerDTO.getId(), ssrcInfoDTO.getSsrc()); 375 tkMediaServerNodeService.releaseSsrc(mediaServerDTO.getId(), ssrcInfoDTO.getSsrc());
304 376
@@ -466,8 +538,15 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -466,8 +538,15 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
466 boolean persisted = false; 538 boolean persisted = false;
467 ToDeviceRpcRequest rpcRequest = 539 ToDeviceRpcRequest rpcRequest =
468 new ToDeviceRpcRequest( 540 new ToDeviceRpcRequest(
469 - rpcRequestUUID, new TenantId(UUID.fromString(tenantId)),  
470 - new DeviceId(UUID.fromString(deviceId)), oneWay, expTime, body, persisted, null, null); 541 + rpcRequestUUID,
  542 + new TenantId(UUID.fromString(tenantId)),
  543 + new DeviceId(UUID.fromString(deviceId)),
  544 + oneWay,
  545 + expTime,
  546 + body,
  547 + persisted,
  548 + null,
  549 + null);
471 deviceRpcService.processRestApiRpcRequest(rpcRequest, responseConsumer, null); 550 deviceRpcService.processRestApiRpcRequest(rpcRequest, responseConsumer, null);
472 } catch (IllegalArgumentException ioe) { 551 } catch (IllegalArgumentException ioe) {
473 throw new ThingsboardException( 552 throw new ThingsboardException(
@@ -485,69 +564,90 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -485,69 +564,90 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
485 */ 564 */
486 @Override 565 @Override
487 public void byeCmdInSsrcTransaction( 566 public void byeCmdInSsrcTransaction(
488 - String tenantId,  
489 - boolean oneWay,  
490 - String tbDeviceId,  
491 - String cameraCode,String channelId,String streamId,  
492 - Consumer<FromDeviceRpcResponse> responseConsumer)  
493 - throws ThingsboardException {  
494 - Optional<SsrcTransactionDTO> transactionDTO = videoStreamSessionManager.getSsrcTransaction(cameraCode,channelId,streamId); 567 + String tenantId,
  568 + boolean oneWay,
  569 + String tbDeviceId,
  570 + String cameraCode,
  571 + String channelId,
  572 + String streamId,
  573 + Consumer<FromDeviceRpcResponse> responseConsumer)
  574 + throws ThingsboardException {
  575 + Optional<SsrcTransactionDTO> transactionDTO =
  576 + videoStreamSessionManager.getSsrcTransaction(cameraCode, channelId, streamId);
495 if (transactionDTO.isEmpty()) { 577 if (transactionDTO.isEmpty()) {
496 - throw new TkDataValidationException(  
497 - ErrorMessage.STREAM_INFO_NOT_FOUND_FOR_PLAY.getMessage()); 578 + throw new TkDataValidationException(ErrorMessage.STREAM_INFO_NOT_FOUND_FOR_PLAY.getMessage());
498 } 579 }
499 SsrcTransactionDTO ssrc = transactionDTO.get(); 580 SsrcTransactionDTO ssrc = transactionDTO.get();
500 cameraByeCmd( 581 cameraByeCmd(
501 - tenantId,ssrc.getSipTransactionInfo(),oneWay,true,tbDeviceId,  
502 - cameraCode,channelId,streamId,ssrc.getSsrc(),ssrc.getMediaServerId(),  
503 - responseConsumer); 582 + tenantId,
  583 + ssrc.getSipTransactionInfo(),
  584 + oneWay,
  585 + true,
  586 + tbDeviceId,
  587 + cameraCode,
  588 + channelId,
  589 + streamId,
  590 + ssrc.getSsrc(),
  591 + ssrc.getMediaServerId(),
  592 + responseConsumer);
504 } 593 }
505 594
506 public void byeCmdInSendRtp( 595 public void byeCmdInSendRtp(
507 - SecurityUser currentUser,  
508 - boolean oneWay,  
509 - String tbDeviceId,  
510 - String cameraCode,String channelId,String streamId,  
511 - Consumer<FromDeviceRpcResponse> responseConsumer)  
512 - throws ThingsboardException {  
513 -  
514 -// SendRtpItemDTO sendRtpItem =null;  
515 -// SipMessageHeaderDTO sipTransactionInfo =  
516 -// SipMessageHeaderDTO.builder()  
517 -// .toTag(sendRtpItem.getToTag())  
518 -// .fromTag(sendRtpItem.getFromTag())  
519 -// .callId(sendRtpItem.getCallId())  
520 -// .build();  
521 -// MediaServerDTO mediaServer = tkMediaServerService.getMediaServerByMediaServerId(sendRtpItem.getMediaServerId());  
522 -// cameraByeCmd(  
523 -// currentUser,ssrc.getSipTransactionInfo(),oneWay,mediaServer != null,tbDeviceId,  
524 -// cameraCode,sendRtpItem.getChannelId(),streamId,ssrc.getSsrc(),ssrc.getMediaServerId(),  
525 -// responseConsumer);  
526 - } 596 + SecurityUser currentUser,
  597 + boolean oneWay,
  598 + String tbDeviceId,
  599 + String cameraCode,
  600 + String channelId,
  601 + String streamId,
  602 + Consumer<FromDeviceRpcResponse> responseConsumer)
  603 + throws ThingsboardException {
527 604
  605 + // SendRtpItemDTO sendRtpItem =null;
  606 + // SipMessageHeaderDTO sipTransactionInfo =
  607 + // SipMessageHeaderDTO.builder()
  608 + // .toTag(sendRtpItem.getToTag())
  609 + // .fromTag(sendRtpItem.getFromTag())
  610 + // .callId(sendRtpItem.getCallId())
  611 + // .build();
  612 + // MediaServerDTO mediaServer =
  613 + // tkMediaServerService.getMediaServerByMediaServerId(sendRtpItem.getMediaServerId());
  614 + // cameraByeCmd(
  615 + // currentUser,ssrc.getSipTransactionInfo(),oneWay,mediaServer != null,tbDeviceId,
  616 + //
  617 + // cameraCode,sendRtpItem.getChannelId(),streamId,ssrc.getSsrc(),ssrc.getMediaServerId(),
  618 + // responseConsumer);
  619 + }
528 620
529 public void cameraByeCmd( 621 public void cameraByeCmd(
530 - String currentUser,SipMessageHeaderDTO messageHeaderDTO,  
531 - boolean oneWay,boolean mediaOnline,  
532 - String tbDeviceId,  
533 - String cameraCode,String channelId,String streamId,String ssrc,String mediaServerId,  
534 - Consumer<FromDeviceRpcResponse> responseConsumer) throws ThingsboardException {  
535 - if(mediaOnline){  
536 - tkMediaServerNodeService.releaseSsrc(mediaServerId,ssrc);  
537 - tkMediaServerNodeService.closeRTPServer(mediaServerId,streamId); 622 + String currentUser,
  623 + SipMessageHeaderDTO messageHeaderDTO,
  624 + boolean oneWay,
  625 + boolean mediaOnline,
  626 + String tbDeviceId,
  627 + String cameraCode,
  628 + String channelId,
  629 + String streamId,
  630 + String ssrc,
  631 + String mediaServerId,
  632 + Consumer<FromDeviceRpcResponse> responseConsumer)
  633 + throws ThingsboardException {
  634 + if (mediaOnline) {
  635 + tkMediaServerNodeService.releaseSsrc(mediaServerId, ssrc);
  636 + tkMediaServerNodeService.closeRTPServer(mediaServerId, streamId);
538 } 637 }
539 - videoStreamSessionManager.remove(cameraCode,channelId,streamId); 638 + videoStreamSessionManager.remove(cameraCode, channelId, streamId);
540 ObjectNode paramJson = JacksonUtil.newObjectNode(); 639 ObjectNode paramJson = JacksonUtil.newObjectNode();
541 paramJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId); 640 paramJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId);
542 - paramJson.set(FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(messageHeaderDTO)); 641 + paramJson.set(
  642 + FastIotConstants.ZLMediaBody.MSG_HEADER, JacksonUtil.valueToTree(messageHeaderDTO));
543 cameraCommonCmd( 643 cameraCommonCmd(
544 - currentUser,  
545 - paramJson,  
546 - cameraCode,  
547 - VideoMethodEnum.BYE,  
548 - oneWay,  
549 - tbDeviceId,  
550 - responseConsumer); 644 + currentUser,
  645 + paramJson,
  646 + cameraCode,
  647 + VideoMethodEnum.BYE,
  648 + oneWay,
  649 + tbDeviceId,
  650 + responseConsumer);
551 } 651 }
552 652
553 /** 653 /**
@@ -687,11 +787,11 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -687,11 +787,11 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
687 byeCmdInSsrcTransaction( 787 byeCmdInSsrcTransaction(
688 currentUser.getCurrentTenantId(), 788 currentUser.getCurrentTenantId(),
689 false, 789 false,
690 - tbDeviceId,  
691 - cameraCode,channelId,streamId,  
692 - fromDeviceRpcResponse->{  
693 -  
694 - }); 790 + tbDeviceId,
  791 + cameraCode,
  792 + channelId,
  793 + streamId,
  794 + fromDeviceRpcResponse -> {});
695 } catch (Exception e) { 795 } catch (Exception e) {
696 log.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); 796 log.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
697 } 797 }
@@ -707,21 +807,31 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -707,21 +807,31 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
707 } 807 }
708 808
709 @Override 809 @Override
710 - public boolean control(SecurityUser currentUser, String tbDeviceId, String channelId, PTZCommandEnum command, int horizonSpeed, int verticalSpeed, int zoomSpeed) throws ThingsboardException { 810 + public boolean control(
  811 + SecurityUser currentUser,
  812 + String tbDeviceId,
  813 + String channelId,
  814 + PTZCommandEnum command,
  815 + int horizonSpeed,
  816 + int verticalSpeed,
  817 + int zoomSpeed)
  818 + throws ThingsboardException {
711 819
712 if (PTZCommandEnum.STOP.equals(command)) { 820 if (PTZCommandEnum.STOP.equals(command)) {
713 horizonSpeed = 0; 821 horizonSpeed = 0;
714 verticalSpeed = 0; 822 verticalSpeed = 0;
715 zoomSpeed = 0; 823 zoomSpeed = 0;
716 } 824 }
717 - DeviceDTO deviceDTO = tkDeviceService.checkDeviceByTenantIdAndId(currentUser.getCurrentTenantId(), tbDeviceId, true); 825 + DeviceDTO deviceDTO =
  826 + tkDeviceService.checkDeviceByTenantIdAndId(
  827 + currentUser.getCurrentTenantId(), tbDeviceId, true);
718 if (null == deviceDTO) { 828 if (null == deviceDTO) {
719 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 829 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
720 } 830 }
721 SipDeviceDTO sipDeviceDTO = 831 SipDeviceDTO sipDeviceDTO =
722 - JacksonUtil.convertValue(  
723 - deviceDTO.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP),  
724 - SipDeviceDTO.class); 832 + JacksonUtil.convertValue(
  833 + deviceDTO.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP),
  834 + SipDeviceDTO.class);
725 if (null == sipDeviceDTO) { 835 if (null == sipDeviceDTO) {
726 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage()); 836 throw new TkDataValidationException(ErrorMessage.INVALID_PARAMETER.getMessage());
727 } 837 }
@@ -732,17 +842,17 @@ public class TkVideoControlServiceImpl implements TkVideoControlService { @@ -732,17 +842,17 @@ public class TkVideoControlServiceImpl implements TkVideoControlService {
732 ptzCmdDTO.setZoomSpeed(zoomSpeed); 842 ptzCmdDTO.setZoomSpeed(zoomSpeed);
733 ObjectNode requestJson = JacksonUtil.newObjectNode(); 843 ObjectNode requestJson = JacksonUtil.newObjectNode();
734 requestJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId); 844 requestJson.put(FastIotConstants.ZLMediaBody.CHANNEL_ID, channelId);
735 - requestJson.set(FastIotConstants.ZLMediaBody.CONTROL_CONTEXT, JacksonUtil.valueToTree(ptzCmdDTO)); 845 + requestJson.put(FastIotConstants.ZLMediaBody.MSG_TYPE, VideoXmlEnum.Control.name());
  846 + requestJson.set(
  847 + FastIotConstants.ZLMediaBody.MSG_CONTEXT, JacksonUtil.valueToTree(ptzCmdDTO));
736 cameraCommonCmd( 848 cameraCommonCmd(
737 - currentUser.getCurrentTenantId(),  
738 - requestJson,  
739 - sipDeviceDTO.getCameraCode(),  
740 - VideoMethodEnum.MESSAGE,  
741 - false,  
742 - tbDeviceId,  
743 - fromDeviceRpcResponse->{  
744 -  
745 - }); 849 + currentUser.getCurrentTenantId(),
  850 + requestJson,
  851 + sipDeviceDTO.getCameraCode(),
  852 + VideoMethodEnum.MESSAGE,
  853 + false,
  854 + tbDeviceId,
  855 + fromDeviceRpcResponse -> {});
746 return false; 856 return false;
747 } 857 }
748 } 858 }
@@ -1203,10 +1203,10 @@ file: @@ -1203,10 +1203,10 @@ file:
1203 type: ${FILE_STORAGE_TYPE:minio} #minio, or other to be implemented 1203 type: ${FILE_STORAGE_TYPE:minio} #minio, or other to be implemented
1204 randomFileName: ${FILE_STORAGE_FILENAME:true} #是否重命名文件名字,防止冲突 1204 randomFileName: ${FILE_STORAGE_FILENAME:true} #是否重命名文件名字,防止冲突
1205 minio: 1205 minio:
1206 - minioUrl: ${MINIO_URL:https://demo.thingskit.com:9000} #minio储存地址  
1207 - minioName: ${MINIO_NAME:thingskit} #minio账户  
1208 - minioPass: ${MINIO_PWD:Dzr227+bjsz} #minio访问密码  
1209 - bucketName: yunteng-test #minio储存桶名称 1206 + minioUrl: ${MINIO_URL:http://127.0.0.1:9000} #minio储存地址
  1207 + minioName: ${MINIO_NAME:xxxxxx} #minio账户
  1208 + minioPass: ${MINIO_PWD:xxxxx} #minio访问密码
  1209 + bucketName: ${MINIO_BUCKET_NAME:yunteng-test} #minio储存桶名称
1210 randomFileName: ${file.storage.randomFileName} 1210 randomFileName: ${file.storage.randomFileName}
1211 account: 1211 account:
1212 info: 1212 info:
@@ -1246,13 +1246,13 @@ sip: @@ -1246,13 +1246,13 @@ sip:
1246 password: ${GBT28181_SIP_PASSWORD:61332286} 1246 password: ${GBT28181_SIP_PASSWORD:61332286}
1247 #zlm 默认服务器配置 1247 #zlm 默认服务器配置
1248 media: 1248 media:
1249 - id: ${GBT28181_MEDIA_GENERAL_ID:f6GfbO0BGEaROKLP} 1249 + id: ${GBT28181_MEDIA_GENERAL_ID:D2okJWKKaQ5bX7Va}
1250 # [必须修改] zlm服务器的内网IP 1250 # [必须修改] zlm服务器的内网IP
1251 - ip: ${GBT28181_MEDIA_IP:192.168.1.16} 1251 + ip: ${GBT28181_MEDIA_IP:192.168.1.20}
1252 # [必须修改] zlm服务器的http.port 1252 # [必须修改] zlm服务器的http.port
1253 http-port: ${GBT28181_MEDIA_HTTP_PORT:28080} 1253 http-port: ${GBT28181_MEDIA_HTTP_PORT:28080}
1254 # [可选] zlm服务器的hook.admin_params=secret 1254 # [可选] zlm服务器的hook.admin_params=secret
1255 - secret: ${GBT28181_MEDIA_API_SECRET:5PnbPDCcxQGeK15OowHPPdSgort2Cx9Y} 1255 + secret: ${GBT28181_MEDIA_API_SECRET:QhrTN7k6HcDnt0YyeolwHwiVYDgIHPMZ}
1256 # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试 1256 # 启用多端口模式, 多端口模式使用端口区分每路流,兼容性更好。 单端口使用流的ssrc区分, 点播超时建议使用多端口测试
1257 rtp: 1257 rtp:
1258 # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输 1258 # [可选] 是否启用多端口模式, 开启后会在portRange范围内选择端口用于媒体流传输
@@ -184,8 +184,8 @@ public interface FastIotConstants { @@ -184,8 +184,8 @@ public interface FastIotConstants {
184 /** 请求响应事件:表单内容 */ 184 /** 请求响应事件:表单内容 */
185 String MSG_CONTEXT = "msgContext"; 185 String MSG_CONTEXT = "msgContext";
186 186
187 - /** 设备控制内容 */  
188 - String CONTROL_CONTEXT = "ptzContext"; 187 + /** 消息类型,例如:查询、控制等 */
  188 + String MSG_TYPE = "xmlRoot";
189 189
190 /** 订阅处理结果 */ 190 /** 订阅处理结果 */
191 String SESSION_TYPE = "sessionType"; 191 String SESSION_TYPE = "sessionType";
@@ -206,6 +206,7 @@ public interface FastIotConstants { @@ -206,6 +206,7 @@ public interface FastIotConstants {
206 String UDP = "UDP"; 206 String UDP = "UDP";
207 } 207 }
208 208
  209 +
209 interface TBCacheConfig { 210 interface TBCacheConfig {
210 String TB_CACHE_CONFIG_KEY = "TB_CONNECT_CACHE"; 211 String TB_CACHE_CONFIG_KEY = "TB_CONNECT_CACHE";
211 String EXISTING_TENANT = "EXISTING_TENANT"; 212 String EXISTING_TENANT = "EXISTING_TENANT";
@@ -123,16 +123,18 @@ public enum ErrorMessage { @@ -123,16 +123,18 @@ public enum ErrorMessage {
123 SSRC_INFO_NOT_FOUND(400098,"缓存事务信息未找到,设备【%s】 通道【%s】"), 123 SSRC_INFO_NOT_FOUND(400098,"缓存事务信息未找到,设备【%s】 通道【%s】"),
124 VIDEO_CHANNEL_NOT_FOUND(400099,"视频通道不存在"), 124 VIDEO_CHANNEL_NOT_FOUND(400099,"视频通道不存在"),
125 ONLINE_MEDIA_SERVER_NOT_FOUND(400100,"没有可用的流媒体节点"), 125 ONLINE_MEDIA_SERVER_NOT_FOUND(400100,"没有可用的流媒体节点"),
126 - FOUND_VIDEO_DEVICE_FAILED(400101,"获取视频设备信息失败"), 126 + FOUND_VIDEO_DEVICE_FAILED(400101,"视频设备SIP信息丢失"),
127 NOT_FOUND_MEDIA_SERVER_FOR_PLAY(400102,"未找到可用于播放的流媒体"), 127 NOT_FOUND_MEDIA_SERVER_FOR_PLAY(400102,"未找到可用于播放的流媒体"),
128 RECEIVE_STREAM_FAILED(400103,"开启收流失败"), 128 RECEIVE_STREAM_FAILED(400103,"开启收流失败"),
129 - GET_PLAY_PORT_FAILED(400104,"获取点播端口异常"), 129 + GET_PLAY_PORT_FAILED(400104,"从流媒体【{}】获取点播端口异常"),
130 STREAM_INFO_NOT_FOUND_FOR_PLAY(400105,"点播信息未找到"), 130 STREAM_INFO_NOT_FOUND_FOR_PLAY(400105,"点播信息未找到"),
131 SIP_COMMAND_SEND_FAILED(400106,"sip命令下发失败"), 131 SIP_COMMAND_SEND_FAILED(400106,"sip命令下发失败"),
132 NOT_BELONG_CURRENT_CUSTOMER(400107,"该数据不属于当前客户"), 132 NOT_BELONG_CURRENT_CUSTOMER(400107,"该数据不属于当前客户"),
133 IMPORT_ERROR(400108,"请使用模板excel重新导入"), 133 IMPORT_ERROR(400108,"请使用模板excel重新导入"),
134 INTRANET_ERROR(400109,"内网ip+端口不能重复,请重新输入"), 134 INTRANET_ERROR(400109,"内网ip+端口不能重复,请重新输入"),
135 OUTER_NET_ERROR(400110,"外网ip+端口不能重复,请重新输入"), 135 OUTER_NET_ERROR(400110,"外网ip+端口不能重复,请重新输入"),
  136 +
  137 + DEVICE_NOT_ONLINE(400111,"设备不在线,无法执行相关操作!"),
136 HAVE_NO_PERMISSION(500002,"没有修改权限"), 138 HAVE_NO_PERMISSION(500002,"没有修改权限"),
137 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置"); 139 NOT_ALLOED_ISOLATED_IN_MONOLITH(500003,"【monolith】模式下,不能选择【isolated】类型的租户配置");
138 140
@@ -515,6 +515,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -515,6 +515,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
515 switch (VideoCmdEnum.valueOf(cmd)) { 515 switch (VideoCmdEnum.valueOf(cmd)) {
516 case DeviceInfo: 516 case DeviceInfo:
517 SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement); 517 SipDeviceDTO cameraInfoDTO = TKXmlUtil.cameraInfoBuilder(rootElement);
  518 + cameraInfoDTO.setHostAddress(request.getViaHost() + ":" + request.getViaPort());
518 byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO); 519 byte[] cameraMsgBytes = encodingService.encode(cameraInfoDTO);
519 msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes)); 520 msgBuilder.setContext(ByteString.copyFrom(cameraMsgBytes));
520 break; 521 break;
@@ -680,21 +681,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -680,21 +681,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
680 .build(); 681 .build();
681 commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader); 682 commanderService.queryDeviceInfo(deviceSessionCtx, deviceInfoHeader);
682 int sn = (int) ((Math.random() * 9 + 1) * 100000); 683 int sn = (int) ((Math.random() * 9 + 1) * 100000);
683 - // catalogResponseMessageHandler.setChannelSyncReady(device, sn);  
684 - SipMessageHeaderDTO catalogHeader =  
685 - SipMessageHeaderDTO.builder()  
686 - .viaTag(TKSipUtils.getNewViaTag())  
687 - .fromTag(TKSipUtils.getNewFromTag())  
688 - .build();  
689 - commanderService.queryCatalog(  
690 - deviceSessionCtx,  
691 - catalogHeader,  
692 - sn,  
693 - ev -> {  
694 - String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg);  
695 - // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(),  
696 - // errorMsg);  
697 - }); 684 + rpcCameraChannel(deviceSessionCtx,sn);
698 } catch (InvalidArgumentException | SipException | ParseException e) { 685 } catch (InvalidArgumentException | SipException | ParseException e) {
699 throw new RuntimeException(e); 686 throw new RuntimeException(e);
700 } 687 }
@@ -733,6 +720,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -733,6 +720,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
733 720
734 721
735 722
  723 +
736 /** 724 /**
737 * 向超时订阅发送消息 725 * 向超时订阅发送消息
738 * 726 *
@@ -859,14 +847,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -859,14 +847,7 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
859 }); 847 });
860 break; 848 break;
861 case MESSAGE: 849 case MESSAGE:
862 - SipMessageHeaderDTO controlHeaderDTO =  
863 - SipMessageHeaderDTO.builder()  
864 - .viaTag(TKSipUtils.getNewViaTag())  
865 - .fromTag(TKSipUtils.getNewViaTag())  
866 - .toTag(null)  
867 - .build();  
868 - PTZCmdDTO ptzCmdDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.CONTROL_CONTEXT),PTZCmdDTO.class);  
869 - commanderService.controlPtzCmd(channelId,devSession,controlHeaderDTO,ptzCmdDTO); 850 + toDeviceRpcMessage(devSession,channelId,rpcBody);
870 break; 851 break;
871 } 852 }
872 } catch (InvalidArgumentException | SipException | ParseException e) { 853 } catch (InvalidArgumentException | SipException | ParseException e) {
@@ -875,6 +856,47 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent @@ -875,6 +856,47 @@ public class SIPProcessorObserver extends SIPRequestProcessorParent
875 } 856 }
876 } 857 }
877 858
  859 + private void toDeviceRpcMessage(GbtDeviceSessionCtx devSession,String channelId,JsonNode rpcBody) throws InvalidArgumentException, ParseException, SipException {
  860 + SipMessageHeaderDTO controlHeaderDTO =
  861 + SipMessageHeaderDTO.builder()
  862 + .viaTag(TKSipUtils.getNewViaTag())
  863 + .fromTag(TKSipUtils.getNewViaTag())
  864 + .toTag(null)
  865 + .build();
  866 + String msgType = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_TYPE).asText();
  867 + switch (VideoXmlEnum.valueOf(msgType)){
  868 + case Control:
  869 + PTZCmdDTO ptzCmdDTO = JacksonUtil.convertValue(rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT),PTZCmdDTO.class);
  870 + commanderService.controlPtzCmd(channelId,devSession,controlHeaderDTO,ptzCmdDTO);
  871 + break;
  872 + case Query:
  873 + int sn = rpcBody.get(FastIotConstants.ZLMediaBody.MSG_CONTEXT).intValue();
  874 + rpcCameraChannel(devSession,sn);
  875 + }
  876 + }
  877 +
  878 + /**
  879 + * 查询设备通道信息
  880 + * @throws InvalidArgumentException
  881 + * @throws SipException
  882 + * @throws ParseException
  883 + */
  884 + private void rpcCameraChannel(GbtDeviceSessionCtx deviceSessionCtx,int sn) throws InvalidArgumentException, SipException, ParseException {
  885 + SipMessageHeaderDTO catalogHeader =
  886 + SipMessageHeaderDTO.builder()
  887 + .viaTag(TKSipUtils.getNewViaTag())
  888 + .fromTag(TKSipUtils.getNewFromTag())
  889 + .build();
  890 + commanderService.queryCatalog(
  891 + deviceSessionCtx,
  892 + catalogHeader,
  893 + sn,
  894 + ev -> {
  895 + String errorMsg = String.format("同步通道失败,错误码: %s, %s", ev.statusCode, ev.msg);
  896 + // catalogResponseMessageHandler.setChannelSyncEnd(device.getDeviceId(),
  897 + // errorMsg);
  898 + });
  899 + }
878 private String rpcParamVal(JsonNode rpcBody, String key) { 900 private String rpcParamVal(JsonNode rpcBody, String key) {
879 if (rpcBody.has(key)) { 901 if (rpcBody.has(key)) {
880 return rpcBody.get(key).asText(); 902 return rpcBody.get(key).asText();
@@ -180,6 +180,7 @@ public class TKXmlUtil { @@ -180,6 +180,7 @@ public class TKXmlUtil {
180 cameraInfo.setModel(getText(root, "Model")); 180 cameraInfo.setModel(getText(root, "Model"));
181 cameraInfo.setFirmware(getText(root, "Firmware")); 181 cameraInfo.setFirmware(getText(root, "Firmware"));
182 cameraInfo.setStreamMode("UDP"); 182 cameraInfo.setStreamMode("UDP");
  183 + cameraInfo.setTransport("UDP");
183 return cameraInfo; 184 return cameraInfo;
184 } 185 }
185 186
@@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.yunteng.dto.*; @@ -30,6 +30,7 @@ import org.thingsboard.server.common.data.yunteng.dto.*;
30 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO; 30 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertConfigDTO;
31 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertDevicesDTO; 31 import org.thingsboard.server.common.data.yunteng.dto.convert.ConvertDevicesDTO;
32 import org.thingsboard.server.common.data.yunteng.dto.convert.DatasourceContentDTO; 32 import org.thingsboard.server.common.data.yunteng.dto.convert.DatasourceContentDTO;
  33 +import org.thingsboard.server.common.data.yunteng.dto.sip.SipDeviceDTO;
33 import org.thingsboard.server.common.data.yunteng.enums.*; 34 import org.thingsboard.server.common.data.yunteng.enums.*;
34 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData; 35 import org.thingsboard.server.common.data.yunteng.utils.tools.TkPageData;
35 import org.thingsboard.server.dao.device.DeviceProfileDao; 36 import org.thingsboard.server.dao.device.DeviceProfileDao;
@@ -78,10 +79,16 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev @@ -78,10 +79,16 @@ public class TkDeviceServiceImpl extends AbstractBaseService<DeviceMapper, TkDev
78 validateUpdate(deviceDTO); 79 validateUpdate(deviceDTO);
79 TkDeviceEntity entity = baseMapper.selectOne(new LambdaQueryWrapper<TkDeviceEntity>().eq(TkDeviceEntity::getTenantId, 80 TkDeviceEntity entity = baseMapper.selectOne(new LambdaQueryWrapper<TkDeviceEntity>().eq(TkDeviceEntity::getTenantId,
80 deviceDTO.getTenantId()).eq(TkDeviceEntity::getId,deviceDTO.getId())); 81 deviceDTO.getTenantId()).eq(TkDeviceEntity::getId,deviceDTO.getId()));
81 - if(null != entity && !entity.getProfileId().equals(deviceDTO.getProfileId())){  
82 - //更改了产品,需将原产品的缓存置为无效  
83 - cacheUtils.invalidate(cacheName,deviceDTO.getTenantId()+","+entity.getProfileId());  
84 - } 82 + Optional.ofNullable(entity).ifPresent(db->{
  83 + if(!entity.getProfileId().equals(deviceDTO.getProfileId())){
  84 + //更改了产品,需将原产品的缓存置为无效
  85 + cacheUtils.invalidate(cacheName,deviceDTO.getTenantId()+","+entity.getProfileId());
  86 + }
  87 + Optional.ofNullable(db.getDeviceInfo().get(FastIotConstants.DeviceAdditional.SIP)).ifPresent(sip ->{
  88 + ObjectNode additional = (ObjectNode) deviceDTO.getDeviceInfo();
  89 + additional.set(FastIotConstants.DeviceAdditional.SIP,sip);
  90 + });
  91 + });
85 TkDeviceEntity device = new TkDeviceEntity(); 92 TkDeviceEntity device = new TkDeviceEntity();
86 deviceDTO.copyToEntity( 93 deviceDTO.copyToEntity(
87 device, 94 device,