Commit a9f21c6b771c6e54f4a9e19195ad493f7d7e705c
Committed by
xp.Huang
1 parent
71c6d651
fix:云台控制传参参数错误
Showing
9 changed files
with
373 additions
and
174 deletions
@@ -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, |